qualia-framework-v2 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CLAUDE.md CHANGED
@@ -51,9 +51,10 @@ No accumulated garbage. No context rot.
51
51
  ## Quality Gates (always active)
52
52
  - **Frontend guard:** Read .planning/DESIGN.md before any frontend changes
53
53
  - **Deploy guard:** tsc + lint + build + tests must pass before deploy
54
- - **Branch guard:** Employees cannot push to main
55
- - **Env guard:** Never edit .env files
56
- - **Intent verification:** Confirm before modifying 3+ files
54
+ - **Branch guard:** Employees cannot push to main (OWNER can)
55
+ - **Env guard:** Employees cannot edit .env files (OWNER can — add keys, configure secrets directly)
56
+ - **Sudo guard:** Employees cannot run sudo (OWNER can)
57
+ - **Intent verification:** Confirm before modifying 3+ files (OWNER: just do it)
57
58
 
58
59
  ## Tracking
59
60
  `.planning/tracking.json` is updated on every push. The ERP reads it via git.
package/agents/builder.md CHANGED
@@ -83,10 +83,28 @@ Rule of thumb: If you can explain the change in one sentence in a commit message
83
83
  - Always check auth server-side
84
84
  - Enable RLS on every table
85
85
  - Validate input with Zod at system boundaries
86
- 5. **Frontend standards:**
87
- - Distinctive fonts (not Inter/Arial)
88
- - Cohesive color palette with sharp accents
89
- - CSS transitions, subtle animations
90
- - Full-width layouts, no hardcoded max-width
86
+ 5. **Frontend standards (mandatory for any .tsx/.jsx/.css file):**
87
+ - Before writing any frontend code: read `.planning/DESIGN.md` if it exists — it's the design source of truth
88
+ - If no DESIGN.md, apply rules from `rules/frontend.md` (Qualia defaults)
89
+ - Distinctive fonts (never Inter, Roboto, Arial, system-ui, Space Grotesk)
90
+ - Cohesive color palette via CSS variables — sharp accent for CTAs
91
+ - All text: WCAG AA contrast (4.5:1 normal, 3:1 large text)
92
+ - Full-width fluid layouts — no hardcoded max-width caps
93
+ - Every interactive element needs ALL states: hover, focus (visible ring), active, disabled, loading, error, empty
94
+ - Semantic HTML (`nav`, `main`, `section`, `article`) — not div soup
95
+ - Keyboard accessible: Tab, Enter, Escape, Arrow keys work
96
+ - Touch targets: 44px minimum
97
+ - Form inputs: visible labels (not placeholder-only), error messages with `aria-describedby`
98
+ - Motion: 150–200ms hover, 250ms expand, stagger children on load, respect `prefers-reduced-motion`
99
+ - Mobile-first responsive: stack on mobile, expand on desktop, fluid typography
100
+ - Skip link on every page, heading hierarchy (one h1, sequential order)
101
+ - No emoji as icons — use SVGs
102
+ - `cursor: pointer` on all clickable elements
91
103
  6. **No empty catch blocks.** At minimum, log the error.
92
104
  7. **No dangerouslySetInnerHTML.** No eval().
105
+ 8. **React/Next.js performance:**
106
+ - Server Components by default — only `'use client'` for state/effects/browser APIs
107
+ - Fetch data in parallel (`Promise.all`), not sequential waterfalls
108
+ - Import specific functions, not entire libraries — avoid barrel file re-exports
109
+ - Use `next/image` with explicit width/height
110
+ - Use `next/dynamic` for heavy below-fold components
package/agents/planner.md CHANGED
@@ -85,6 +85,20 @@ If a task involves a library or API you're unsure about, use WebFetch to check t
85
85
 
86
86
  **Self-check:** Before returning the plan, verify every task has specific file paths, concrete actions, and testable done-when criteria. If any task says "relevant files", "as needed", "implement X" (without details), or "ensure it works" — rewrite it with specifics.
87
87
 
88
+ ## Design-Aware Planning
89
+
90
+ When a phase involves frontend work (pages, components, layouts, UI):
91
+
92
+ 1. **Check for `.planning/DESIGN.md`** — if it exists, reference it in task Context fields: `@.planning/DESIGN.md`
93
+ 2. **If no DESIGN.md and this is Phase 1** — add a Task 1 (Wave 1) to create it:
94
+ - Generate `.planning/DESIGN.md` from the design direction in PROJECT.md
95
+ - Use the template at `templates/DESIGN.md` — fill in: palette, typography (distinctive fonts), spacing, motion approach, component patterns
96
+ - Done when: DESIGN.md exists with concrete CSS variable values (not placeholders)
97
+ 3. **Include design criteria in "Done when"** for frontend tasks:
98
+ - Not just "page renders" but "page renders with design system typography, proper color palette, all interactive states (hover/focus/loading/error/empty), semantic HTML, keyboard accessible"
99
+ - Include responsive: "works on 375px mobile and 1440px desktop"
100
+ 4. **Reference `@.planning/DESIGN.md`** in the Context field of every frontend task so builders read it before coding
101
+
88
102
  ## Rules
89
103
 
90
104
  1. **Plans complete within ~50% context.** More plans with smaller scope = consistent quality. 2-3 tasks per plan is ideal.
@@ -148,6 +148,68 @@ Phase verdict:
148
148
 
149
149
  Never round up. A PARTIAL is not a PASS. The goal of verification is to catch the work that LOOKS done but ISN'T.
150
150
 
151
+ ## Design Verification (for phases with frontend work)
152
+
153
+ If the phase involved UI/frontend tasks, add a **Design Quality** section to the report:
154
+
155
+ ### Check 1: Design System Compliance
156
+ ```bash
157
+ # Generic fonts (should NOT appear)
158
+ grep -rn "font-family.*Inter\|font-family.*Roboto\|font-family.*Arial\|fontFamily.*Inter\|fontFamily.*Roboto" --include="*.tsx" --include="*.jsx" --include="*.css" app/ components/ src/ 2>/dev/null
159
+ grep -rn "font-sans\|font-inter" --include="*.tsx" --include="*.jsx" app/ components/ src/ 2>/dev/null
160
+
161
+ # Hardcoded max-width containers (should NOT appear)
162
+ grep -rn "max-w-\[1200\|max-w-\[1280\|max-width.*1200\|max-width.*1280\|max-w-7xl" --include="*.tsx" --include="*.jsx" --include="*.css" app/ components/ src/ 2>/dev/null
163
+
164
+ # Hardcoded colors instead of CSS variables (check density)
165
+ grep -rn "color:.*#\|background:.*#\|bg-\[#" --include="*.tsx" --include="*.jsx" app/ components/ src/ 2>/dev/null | wc -l
166
+ ```
167
+
168
+ ### Check 2: Accessibility Basics
169
+ ```bash
170
+ # Images without alt text
171
+ grep -rn "<img" --include="*.tsx" --include="*.jsx" app/ components/ src/ 2>/dev/null | grep -v "alt="
172
+
173
+ # Inputs without labels
174
+ grep -rn "<input\|<textarea\|<select" --include="*.tsx" --include="*.jsx" app/ components/ src/ 2>/dev/null | grep -v "aria-label\|aria-labelledby\|id=" | head -10
175
+
176
+ # outline:none without replacement focus style
177
+ grep -rn "outline.*none\|outline-none" --include="*.tsx" --include="*.jsx" --include="*.css" app/ components/ src/ 2>/dev/null | grep -v "focus-visible\|focus:\|focus-within"
178
+
179
+ # Missing lang attribute
180
+ grep -rn "<html" --include="*.tsx" --include="*.jsx" app/ 2>/dev/null | grep -v "lang="
181
+
182
+ # Heading hierarchy — check for h1 count
183
+ grep -rn "<h1\|<H1" --include="*.tsx" --include="*.jsx" app/ 2>/dev/null | wc -l
184
+ ```
185
+
186
+ ### Check 3: Interactive States
187
+ ```bash
188
+ # Buttons/links without hover/focus styles — spot check
189
+ grep -rn "<button\|<Button\|<a " --include="*.tsx" --include="*.jsx" app/ components/ src/ 2>/dev/null | head -5
190
+ # Verify these have hover/focus transitions in their styling
191
+
192
+ # Loading states — check for skeleton/spinner usage in pages with data fetching
193
+ grep -rn "fetch\|useQuery\|useSWR\|getServerSide\|async.*Component" --include="*.tsx" app/ 2>/dev/null | head -5
194
+ grep -rn "loading\|skeleton\|spinner\|Spinner\|Loading" --include="*.tsx" app/ components/ 2>/dev/null | wc -l
195
+
196
+ # Empty states — check lists/tables have empty handling
197
+ grep -rn "\.length.*===.*0\|\.length.*>.*0\|isEmpty\|no.*results\|no.*data" --include="*.tsx" app/ components/ 2>/dev/null | wc -l
198
+ ```
199
+
200
+ ### Check 4: Responsive
201
+ ```bash
202
+ # Check for responsive utilities or media queries
203
+ grep -rn "sm:\|md:\|lg:\|xl:\|@media" --include="*.tsx" --include="*.jsx" --include="*.css" app/ components/ src/ 2>/dev/null | wc -l
204
+ # If 0 responsive declarations across multiple components → FAIL
205
+ ```
206
+
207
+ ### Scoring Design
208
+ - 0 generic fonts + 0 hardcoded max-widths + colors via variables = **PASS**
209
+ - Accessibility basics all present = **PASS**
210
+ - States and responsive present = **PASS**
211
+ - Any category failing = add to **Gaps** list with specific file:line
212
+
151
213
  ## Rules
152
214
 
153
215
  1. **Never trust summaries.** Always grep the code yourself.
@@ -156,3 +218,4 @@ Never round up. A PARTIAL is not a PASS. The goal of verification is to catch th
156
218
  4. **Stubs are failures.** `// TODO: implement` means the task wasn't done.
157
219
  5. **Empty catch blocks are failures.** They hide real errors.
158
220
  6. **Run tsc.** If TypeScript doesn't compile, nothing works.
221
+ 7. **Design debt is a gap.** Generic fonts, missing states, inaccessible components, and hardcoded layouts are failures — not "nice to haves."
package/bin/install.js CHANGED
@@ -253,6 +253,16 @@ async function main() {
253
253
  };
254
254
  fs.writeFileSync(configFile, JSON.stringify(config, null, 2) + "\n");
255
255
 
256
+ // ─── ERP API key (for report uploads) ──────────────────
257
+ log(`${WHITE}ERP integration${RESET}`);
258
+ const erpKeyFile = path.join(CLAUDE_DIR, ".erp-api-key");
259
+ if (!fs.existsSync(erpKeyFile)) {
260
+ fs.writeFileSync(erpKeyFile, "qualia-claude-2026", { mode: 0o600 });
261
+ ok(".erp-api-key (created)");
262
+ } else {
263
+ ok(".erp-api-key (exists)");
264
+ }
265
+
256
266
  // ─── Configure settings.json ───────────────────────────
257
267
  console.log("");
258
268
  log(`${WHITE}Configuring settings.json...${RESET}`);
@@ -322,6 +332,11 @@ async function main() {
322
332
  {
323
333
  matcher: "Bash",
324
334
  hooks: [
335
+ {
336
+ type: "command",
337
+ command: `${hd}/auto-update.sh`,
338
+ timeout: 5,
339
+ },
325
340
  {
326
341
  type: "command",
327
342
  if: "Bash(git push*)",
@@ -414,7 +429,7 @@ async function main() {
414
429
 
415
430
  fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
416
431
 
417
- ok("Hooks: branch-guard, pre-push, env-block, migration-guard, deploy-gate, pre-compact");
432
+ ok("Hooks: auto-update, branch-guard, pre-push, env-block, migration-guard, deploy-gate, pre-compact");
418
433
  ok("Status line + spinner configured");
419
434
  ok("Environment variables + permissions");
420
435
 
@@ -425,11 +440,11 @@ async function main() {
425
440
  console.log(` ${WHITE}${member.name}${RESET} ${DIM}(${member.role})${RESET}`);
426
441
  console.log(` Skills: ${WHITE}${skills.length}${RESET}`);
427
442
  console.log(` Agents: ${WHITE}3${RESET} ${DIM}(planner, builder, verifier)${RESET}`);
428
- console.log(` Hooks: ${WHITE}6${RESET} ${DIM}(branch-guard, pre-push, env-block, migration-guard, deploy-gate, pre-compact)${RESET}`);
429
- console.log(` Rules: ${WHITE}3${RESET} ${DIM}(security, frontend, deployment)${RESET}`);
443
+ console.log(` Hooks: ${WHITE}7${RESET} ${DIM}(auto-update, branch-guard, pre-push, env-block, migration-guard, deploy-gate, pre-compact)${RESET}`);
444
+ console.log(` Rules: ${WHITE}${fs.readdirSync(rulesDir).length}${RESET} ${DIM}(security, frontend, design-reference, deployment)${RESET}`);
430
445
  console.log(` Scripts: ${WHITE}1${RESET} ${DIM}(state.js — state machine)${RESET}`);
431
446
  console.log(` Knowledge: ${WHITE}3${RESET} ${DIM}(patterns, fixes, client prefs)${RESET}`);
432
- console.log(` Templates: ${WHITE}4${RESET}`);
447
+ console.log(` Templates: ${WHITE}${fs.readdirSync(tmplDir).length}${RESET}`);
433
448
  console.log(` Status line: ${GREEN}✓${RESET}`);
434
449
  console.log(` CLAUDE.md: ${GREEN}✓${RESET} ${DIM}(${member.role})${RESET}`);
435
450
 
@@ -0,0 +1,56 @@
1
+ #!/bin/bash
2
+ # Qualia auto-update — checks once per day, updates silently in background
3
+ # Runs as PreToolUse hook. Cached so it's a no-op most of the time.
4
+
5
+ CLAUDE_DIR="$HOME/.claude"
6
+ CACHE_FILE="$CLAUDE_DIR/.qualia-last-update-check"
7
+ CONFIG_FILE="$CLAUDE_DIR/.qualia-config.json"
8
+ LOCK_FILE="$CLAUDE_DIR/.qualia-updating"
9
+ MAX_AGE=86400 # 24 hours in seconds
10
+
11
+ # Exit fast if recently checked (most common path — single stat call)
12
+ if [ -f "$CACHE_FILE" ]; then
13
+ LAST_CHECK=$(cat "$CACHE_FILE" 2>/dev/null || echo 0)
14
+ NOW=$(date +%s)
15
+ AGE=$((NOW - LAST_CHECK))
16
+ if [ "$AGE" -lt "$MAX_AGE" ]; then
17
+ exit 0
18
+ fi
19
+ fi
20
+
21
+ # Exit if already updating
22
+ [ -f "$LOCK_FILE" ] && exit 0
23
+
24
+ # Update cache timestamp immediately (prevents concurrent checks)
25
+ date +%s > "$CACHE_FILE"
26
+
27
+ # Run the actual check + update in background so we don't block the user
28
+ (
29
+ trap 'rm -f "$LOCK_FILE"' EXIT
30
+ touch "$LOCK_FILE"
31
+
32
+ # Get installed version
33
+ INSTALLED=$(node -e "try{console.log(JSON.parse(require('fs').readFileSync('$CONFIG_FILE','utf8')).version)}catch{console.log('0.0.0')}" 2>/dev/null)
34
+ [ -z "$INSTALLED" ] && INSTALLED="0.0.0"
35
+
36
+ # Get latest from npm (5s timeout)
37
+ LATEST=$(npm view qualia-framework-v2 version 2>/dev/null)
38
+ [ -z "$LATEST" ] && exit 0
39
+
40
+ # Compare versions
41
+ NEEDS_UPDATE=$(node -e "
42
+ const a='$LATEST'.split('.').map(Number), b='$INSTALLED'.split('.').map(Number);
43
+ for(let i=0;i<3;i++){if(a[i]>b[i]){console.log('yes');process.exit()}if(a[i]<b[i]){process.exit()}}
44
+ " 2>/dev/null)
45
+
46
+ if [ "$NEEDS_UPDATE" = "yes" ]; then
47
+ # Get saved install code
48
+ CODE=$(node -e "try{console.log(JSON.parse(require('fs').readFileSync('$CONFIG_FILE','utf8')).code)}catch{}" 2>/dev/null)
49
+ [ -z "$CODE" ] && exit 0
50
+
51
+ # Run silent update
52
+ npx qualia-framework-v2@latest install <<< "$CODE" > /dev/null 2>&1
53
+ fi
54
+ ) &
55
+
56
+ exit 0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qualia-framework-v2",
3
- "version": "2.4.0",
3
+ "version": "2.5.0",
4
4
  "description": "Claude Code workflow framework by Qualia Solutions. Plan, build, verify, ship.",
5
5
  "bin": {
6
6
  "qualia-framework-v2": "./bin/cli.js"
@@ -0,0 +1,179 @@
1
+ ---
2
+ globs: ["*.tsx", "*.jsx", "*.css", "*.scss"]
3
+ ---
4
+
5
+ # Design Reference — Deep Specs
6
+
7
+ Detailed values for motion, accessibility, and responsive design. Loaded alongside `frontend.md` for frontend work.
8
+
9
+ ## Motion Specification
10
+
11
+ ### Duration Table
12
+
13
+ | Action | Duration | Easing | Example |
14
+ |--------|----------|--------|---------|
15
+ | Micro-feedback | 100ms | ease-out | Button press, checkbox toggle |
16
+ | Hover/focus | 150ms | ease-out | Color change, underline appear |
17
+ | Small reveal | 200ms | ease-out | Tooltip show, dropdown open |
18
+ | Expand/collapse | 250ms | ease-in-out | Accordion, panel slide |
19
+ | Page element enter | 300ms | cubic-bezier(0, 0, 0.2, 1) | Card fade-in, section reveal |
20
+ | Page transition | 400ms | cubic-bezier(0.4, 0, 0.2, 1) | Route change, modal open |
21
+ | Complex orchestration | 500–800ms | staggered | Page load sequence |
22
+
23
+ ### Easing Curves (CSS)
24
+
25
+ ```css
26
+ --ease-standard: cubic-bezier(0.4, 0, 0.2, 1); /* General movement */
27
+ --ease-decelerate: cubic-bezier(0, 0, 0.2, 1); /* Enter screen */
28
+ --ease-accelerate: cubic-bezier(0.4, 0, 1, 1); /* Exit screen */
29
+ --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1); /* Playful bounce */
30
+ --ease-smooth: cubic-bezier(0.25, 0.1, 0.25, 1); /* Subtle shift */
31
+ ```
32
+
33
+ ### Stagger Pattern
34
+
35
+ ```css
36
+ /* Stagger children on page load */
37
+ @keyframes fadeUp {
38
+ from { opacity: 0; transform: translateY(12px); }
39
+ to { opacity: 1; transform: translateY(0); }
40
+ }
41
+
42
+ .stagger > * {
43
+ animation: fadeUp 300ms var(--ease-decelerate) both;
44
+ }
45
+ .stagger > *:nth-child(1) { animation-delay: 0ms; }
46
+ .stagger > *:nth-child(2) { animation-delay: 60ms; }
47
+ .stagger > *:nth-child(3) { animation-delay: 120ms; }
48
+ .stagger > *:nth-child(4) { animation-delay: 180ms; }
49
+ .stagger > *:nth-child(5) { animation-delay: 240ms; }
50
+ ```
51
+
52
+ ### Reduced Motion
53
+
54
+ ```css
55
+ @media (prefers-reduced-motion: reduce) {
56
+ *, *::before, *::after {
57
+ animation-duration: 0.01ms !important;
58
+ animation-iteration-count: 1 !important;
59
+ transition-duration: 0.01ms !important;
60
+ scroll-behavior: auto !important;
61
+ }
62
+ }
63
+ ```
64
+
65
+ ## WCAG AA Checklist
66
+
67
+ ### Perceivable
68
+ - [ ] All images have descriptive alt text (decorative: `alt=""` + `aria-hidden="true"`)
69
+ - [ ] Color contrast: 4.5:1 normal text, 3:1 large text (18px+ bold / 24px+)
70
+ - [ ] Color contrast: 3:1 for UI components and graphical objects
71
+ - [ ] Information not conveyed by color alone — icons, text, patterns as supplements
72
+ - [ ] Video/audio: captions or transcripts where applicable
73
+ - [ ] Text resizable to 200% without loss of content
74
+ - [ ] Content reflows at 320px viewport width (no horizontal scroll)
75
+
76
+ ### Operable
77
+ - [ ] All functionality available via keyboard (Tab, Enter, Space, Escape, Arrows)
78
+ - [ ] No keyboard traps (except intentional focus traps in modals)
79
+ - [ ] Visible focus indicator: 2px+ ring, contrasting color, no `outline: none` without replacement
80
+ - [ ] Skip navigation link as first focusable element
81
+ - [ ] Touch targets: 44x44px minimum (48x48px recommended)
82
+ - [ ] No content that flashes more than 3 times per second
83
+ - [ ] Page titles are descriptive and unique
84
+
85
+ ### Understandable
86
+ - [ ] Form inputs have visible labels (not placeholder-only)
87
+ - [ ] Error messages identify the field and describe the error
88
+ - [ ] Error suggestions explain how to fix the problem
89
+ - [ ] Required fields marked with `aria-required="true"` and visual indicator
90
+ - [ ] Language set: `<html lang="en">`
91
+ - [ ] Consistent navigation across pages
92
+ - [ ] No unexpected context changes on input
93
+
94
+ ### Robust
95
+ - [ ] Valid HTML (no duplicate IDs, proper nesting)
96
+ - [ ] ARIA used correctly: `role`, `aria-label`, `aria-describedby`, `aria-expanded`, `aria-hidden`
97
+ - [ ] Dynamic content: `aria-live="polite"` for updates, `aria-live="assertive"` for errors
98
+ - [ ] Custom components have proper roles and keyboard interaction patterns
99
+
100
+ ## Responsive Breakpoints
101
+
102
+ ### Strategy: Mobile-First with Fluid Scaling
103
+
104
+ ```css
105
+ /* Base: mobile (320px–639px) */
106
+ /* sm: 640px+ — large phone / small tablet */
107
+ /* md: 768px+ — tablet */
108
+ /* lg: 1024px+ — laptop */
109
+ /* xl: 1280px+ — desktop */
110
+ /* 2xl: 1536px+ — large desktop */
111
+ ```
112
+
113
+ ### Common Patterns
114
+
115
+ | Pattern | Mobile | Tablet | Desktop |
116
+ |---------|--------|--------|---------|
117
+ | Navigation | Hamburger + drawer | Hamburger or condensed | Full horizontal |
118
+ | Grid | 1 column | 2 columns | 3–4 columns |
119
+ | Sidebar | Hidden, overlay | Collapsible | Always visible |
120
+ | Hero | Stacked, full-width | Stacked, padded | Side-by-side |
121
+ | Table | Card view or scroll | Scroll with sticky col | Full table |
122
+ | Modal | Full screen | Centered, 80% width | Centered, max-width |
123
+ | Form | Single column | Single column | Two column for long forms |
124
+
125
+ ### Fluid Typography
126
+
127
+ ```css
128
+ /* Body */
129
+ font-size: clamp(1rem, 0.5rem + 1.5vw, 1.125rem);
130
+
131
+ /* H1 */
132
+ font-size: clamp(2rem, 1rem + 3vw, 3.75rem);
133
+
134
+ /* H2 */
135
+ font-size: clamp(1.5rem, 0.75rem + 2.25vw, 2.5rem);
136
+
137
+ /* H3 */
138
+ font-size: clamp(1.25rem, 0.75rem + 1.5vw, 1.875rem);
139
+ ```
140
+
141
+ ### Fluid Spacing
142
+
143
+ ```css
144
+ /* Section padding */
145
+ padding-inline: clamp(1rem, 5vw, 4rem);
146
+ padding-block: clamp(2rem, 8vw, 6rem);
147
+
148
+ /* Component gap */
149
+ gap: clamp(1rem, 3vw, 2rem);
150
+ ```
151
+
152
+ ## React/Next.js Performance (Critical)
153
+
154
+ ### Priority 1: Eliminate Waterfalls
155
+ - Fetch data in parallel (`Promise.all`), not sequentially
156
+ - Use Suspense boundaries to stream content progressively
157
+ - Prefetch data on hover/focus for anticipated navigation
158
+ - Colocate data fetching with the component that needs it
159
+
160
+ ### Priority 2: Bundle Size
161
+ - Import specific functions, not entire libraries (`import { format } from 'date-fns'`)
162
+ - Avoid barrel files (index.ts re-exports) — import directly from source
163
+ - Use `next/dynamic` for heavy components not needed on initial load
164
+ - Lazy-load below-fold content and non-critical features
165
+
166
+ ### Priority 3: Rendering
167
+ - Server Components by default — only add `'use client'` when needed (state, effects, browser APIs)
168
+ - Avoid unnecessary `useEffect` — derive values during render when possible
169
+ - Use CSS `content-visibility: auto` for long scrollable lists
170
+ - Images: `next/image` with proper `width`/`height` to prevent layout shift
171
+
172
+ ## Compound Component Patterns
173
+
174
+ When building reusable components:
175
+ - **No boolean prop proliferation** (`isCompact`, `showHeader`, `isRounded`) — use composition instead
176
+ - Compound components: `<Select>`, `<Select.Trigger>`, `<Select.Content>` with shared context
177
+ - Explicit variants: `<Alert.Destructive>` instead of `<Alert isDestructive>`
178
+ - Children over render props: `children` for composition, not `renderHeader`/`renderFooter`
179
+ - React 19: use `use()` instead of `useContext()`, skip `forwardRef` (ref is a regular prop)
package/rules/frontend.md CHANGED
@@ -2,31 +2,124 @@
2
2
  globs: ["*.tsx", "*.jsx", "*.css", "*.scss", "tailwind.config.*"]
3
3
  ---
4
4
 
5
- # Frontend Aesthetics
5
+ # Frontend Design Standards
6
6
 
7
- - Distinctive fonts (not Inter/Arial)
8
- - Cohesive color palette with sharp accents
9
- - CSS transitions, staggered animations
10
- - Layered backgrounds, subtle gradients
11
- - Avoid: card grids, generic heroes, blue-purple gradients
12
- - Full-width layouts — no hardcoded 1200px/1280px caps. Use fluid widths that fill the viewport with sensible padding.
7
+ These are Qualia brand standards — mandatory for every frontend component. Not suggestions.
13
8
 
14
- Note: Qualia agents MUST follow these rules when building any frontend component. These are Fawzi's brand standards, not suggestions.
9
+ ## Typography
10
+
11
+ **Never use:** Inter, Roboto, Arial, Helvetica, system-ui, Space Grotesk (overused by AI).
12
+
13
+ - Pair a distinctive display font with a refined body font
14
+ - Type scale: 12 / 14 / 16 / 18 / 20 / 24 / 30 / 36 / 48 / 60 / 72
15
+ - Body: 16px min, line-height 1.5–1.7
16
+ - Headings: line-height 1.1–1.3, letter-spacing -0.02em for large sizes
17
+ - Weight hierarchy: Regular (400) body, Medium (500) labels, Semibold (600) headings, Bold (700) display
18
+ - Prose max-width: 65ch. Everything else: fluid full-width
19
+
20
+ ## Color
21
+
22
+ - Commit to a cohesive palette — define in CSS variables
23
+ - One dominant brand color with sharp accent for CTAs
24
+ - Never: blue-purple gradients, rainbow palettes, gray-on-gray
25
+ - Dark mode: not just inverted — rethink surfaces, reduce contrast slightly
26
+ - Semantic colors: success (green), warning (amber), error (red), info (blue) — always with non-color indicator too
27
+ - All text must meet **WCAG AA** contrast: 4.5:1 normal text, 3:1 large text (18px+ bold or 24px+)
28
+
29
+ ## Layout
30
+
31
+ - Full-width layouts — no hardcoded `max-width: 1200px` or `1280px` caps
32
+ - Fluid padding: `clamp(1rem, 5vw, 4rem)` for horizontal, generous vertical
33
+ - 8px spacing grid: 4 / 8 / 12 / 16 / 24 / 32 / 48 / 64 / 96
34
+ - Tight spacing within groups, generous between sections
35
+ - Asymmetry > symmetry. Overlap, diagonal flow, grid-breaking elements when appropriate
36
+ - No card grids — use varied layouts with visual hierarchy
37
+ - No generic hero sections — make them distinctive and purposeful
38
+
39
+ ## Motion & Animation
40
+
41
+ - Hover/focus transitions: 150–200ms ease-out
42
+ - Expand/collapse: 200–300ms ease-in-out
43
+ - Page transitions: 300–500ms ease-out
44
+ - Staggered entrance animations: 50–80ms delay between items
45
+ - **Always** respect `prefers-reduced-motion: reduce` — disable non-essential animation
46
+ - Easing: `cubic-bezier(0.4, 0, 0.2, 1)` (standard), `cubic-bezier(0, 0, 0.2, 1)` (decelerate), `cubic-bezier(0.4, 0, 1, 1)` (accelerate)
47
+ - One well-orchestrated page load > scattered micro-interactions
48
+ - CSS-only for HTML projects, Motion library (`motion/react`) for React
49
+
50
+ ## States (Every Interactive Element)
51
+
52
+ - **Loading:** Skeleton or spinner on async operations — never a blank void
53
+ - **Empty:** Helpful message + action when lists/data are empty — never "No results"
54
+ - **Error:** User-friendly message + recovery action — never raw error text
55
+ - **Hover:** Visual feedback within 100ms
56
+ - **Focus:** Visible focus ring (2px+ offset, high contrast) — never `outline: none` without replacement
57
+ - **Active/Pressed:** Scale down slightly or color shift
58
+ - **Disabled:** Reduced opacity (0.5) + `cursor: not-allowed` + `aria-disabled`
59
+
60
+ ## Accessibility (WCAG AA Minimum)
61
+
62
+ - Semantic HTML: `<nav>`, `<main>`, `<article>`, `<section>`, `<aside>`, `<header>`, `<footer>` — not divs for everything
63
+ - Heading hierarchy: One `<h1>` per page, sequential order (no skipping h2→h4)
64
+ - All images: descriptive `alt` text (or `alt=""` + `aria-hidden` if decorative)
65
+ - All form inputs: visible `<label>` linked via `htmlFor` — not placeholder-only
66
+ - All interactive elements: keyboard accessible (Tab, Enter, Escape, Arrow keys)
67
+ - Touch targets: 44x44px minimum
68
+ - ARIA: use native HTML elements first. Only add ARIA when HTML semantics aren't enough
69
+ - Never rely solely on color to convey information — add icons, text, or patterns
70
+ - Skip link: `<a href="#main" class="sr-only focus:not-sr-only">` on every page
71
+ - Live regions: `aria-live="polite"` for dynamic content updates (toasts, form validation)
72
+
73
+ ## Responsive Design
74
+
75
+ - Mobile-first: base styles for mobile, `@media (min-width)` for larger screens
76
+ - Breakpoints: `sm: 640px`, `md: 768px`, `lg: 1024px`, `xl: 1280px`, `2xl: 1536px`
77
+ - Fluid typography: `clamp(1rem, 0.5rem + 1.5vw, 1.25rem)` for body, scale up for headings
78
+ - Stack on mobile, expand on desktop — never force horizontal scroll
79
+ - Test: 320px (small phone), 375px (iPhone), 768px (tablet), 1024px (laptop), 1440px (desktop)
80
+ - Images: `max-width: 100%`, `height: auto`, use `srcset` for responsive images
81
+ - Navigation: hamburger menu on mobile, expanded on desktop
82
+
83
+ ## Component Quality
84
+
85
+ - `cursor: pointer` on ALL clickable elements
86
+ - Smooth transitions (150–300ms) on all state changes
87
+ - No emoji as icons — use SVGs or icon libraries
88
+ - Buttons: clear visual hierarchy (primary, secondary, ghost, destructive)
89
+ - Inputs: visible borders, focus rings, error states with `aria-describedby`
90
+ - Links: distinguishable from text (underline or color + another indicator)
91
+ - Modals: trap focus, close on Escape, `aria-modal="true"`, restore focus on close
92
+ - Toast/notifications: `aria-live`, auto-dismiss with adequate time (5s+), dismissible
93
+
94
+ ## Anti-Patterns (Kill on Sight)
95
+
96
+ - Card grids where every card looks identical → varied layouts
97
+ - Generic hero with stock photo → distinctive, purposeful hero
98
+ - Blue-purple gradients → brand colors
99
+ - Static pages with no motion → purposeful animation
100
+ - Fixed widths → fluid responsive
101
+ - Gray text on white (#999 on #fff fails WCAG) → proper contrast
102
+ - Placeholder text shipped to production → real content or proper empty states
103
+ - `outline: none` without focus replacement → visible focus indicators
104
+ - `div` soup → semantic HTML
105
+ - Hardcoded colors scattered in JSX → CSS variables or Tailwind config
106
+
107
+ ## Design System Integration
108
+
109
+ If `.planning/DESIGN.md` exists in the project, it takes precedence over these defaults.
110
+ Read it before any frontend work. It contains project-specific: palette, typography, spacing, component patterns.
15
111
 
16
112
  ## Impeccable Design Skills (global)
17
- Use these `/commands` for design refinement on any frontend work:
18
- - `/polish` — Final detail pass before shipping (spacing, alignment, consistency)
19
- - `/bolder` — Amplify safe/boring designs to be more striking
113
+ - `/polish` Final detail pass before shipping
114
+ - `/bolder` — Amplify safe/boring designs
20
115
  - `/design-quieter` — Tone down overly aggressive designs
21
- - `/animate` — Add purposeful micro-interactions and motion
116
+ - `/animate` — Add purposeful micro-interactions
22
117
  - `/colorize` — Inject strategic color into monochrome UIs
23
118
  - `/clarify` — Fix unclear UX copy, labels, error messages
24
- - `/critique` — Design director-level review (run before shipping)
119
+ - `/critique` — Design director-level review
25
120
  - `/distill` — Strip unnecessary complexity
26
121
  - `/delight` — Add memorable touches and personality
27
122
  - `/harden` — Edge cases, overflow, i18n robustness
28
- - `/onboard` — First-time user experience flows
29
- - `/normalize` — Align with project design system
30
123
  - `/responsive` — Cross-device responsive adaptation
31
124
 
32
125
  ### Recommended workflow
@@ -223,6 +223,44 @@ Create Supabase project (via MCP or manual).
223
223
  **`.planning/PROJECT.md`** — use template, fill from answers:
224
224
  - Client, description, requirements (from features), out of scope, stack, design direction, decisions
225
225
 
226
+ ### Step 8a. Create Design System
227
+
228
+ Generate **`.planning/DESIGN.md`** using `templates/DESIGN.md` as the template.
229
+
230
+ Fill in based on the design direction chosen in Step 3:
231
+
232
+ **Dark & Bold:**
233
+ - Palette: dark backgrounds (#0a0a0a, #141414), vibrant accent (teal #00d4aa, amber #f59e0b, etc.)
234
+ - Typography: bold display font + clean body font (e.g., "Plus Jakarta Sans" + "DM Sans")
235
+ - Effects: glass morphism, noise textures, glow effects
236
+ - Motion: expressive — staggered fades, parallax hints
237
+
238
+ **Clean & Minimal:**
239
+ - Palette: light backgrounds (#fafafa, #ffffff), single muted accent
240
+ - Typography: refined serif or geometric sans (e.g., "Outfit" + "Source Serif 4")
241
+ - Effects: subtle shadows, thin borders
242
+ - Motion: minimal — fades only, no stagger
243
+
244
+ **Colorful & Playful:**
245
+ - Palette: vibrant multi-color, warm backgrounds
246
+ - Typography: rounded friendly fonts (e.g., "Nunito" + "Quicksand")
247
+ - Effects: gradients, rounded shapes, illustrations
248
+ - Motion: expressive — bouncy spring easing, scale on hover
249
+
250
+ **Corporate / Professional:**
251
+ - Palette: navy/charcoal base, conservative accent (blue, green)
252
+ - Typography: trustworthy geometric (e.g., "Manrope" + "IBM Plex Sans")
253
+ - Effects: clean borders, subtle shadows, structured grids
254
+ - Motion: subtle — smooth fades, no bounce
255
+
256
+ **Always include in DESIGN.md:**
257
+ - Concrete CSS variable values (not placeholders)
258
+ - Google Fonts import URL
259
+ - Spacing scale (8px grid)
260
+ - Component patterns (buttons, inputs, cards)
261
+ - Responsive approach
262
+ - Anti-patterns to avoid
263
+
226
264
  ### Step 8b. Initialize State
227
265
 
228
266
  ```bash
@@ -14,39 +14,125 @@ Run after all feature phases are verified. Makes it look production-ready.
14
14
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
15
15
  ```
16
16
 
17
- ### 1. Critique
18
- Review the entire UI. Check:
19
- - Visual hierarchy and information architecture
20
- - Color consistency, contrast, readability
21
- - Spacing and alignment
22
- - Component consistency across pages
23
-
24
- ### 2. Polish
25
- Fix what critique found:
26
- - Alignment and spacing issues
27
- - Font consistency
28
- - Color palette adherence (Qualia teal brand)
29
- - Transition and hover state consistency
17
+ ### 0. Load Design Context
18
+
19
+ ```bash
20
+ cat .planning/DESIGN.md 2>/dev/null || echo "NO_DESIGN"
21
+ ```
22
+
23
+ If DESIGN.md exists → use it as the standard. If not → use Qualia defaults from `rules/frontend.md`.
24
+
25
+ Read EVERY frontend file before modifying. No blind edits.
26
+
27
+ ### 1. Critique (Structured Audit)
28
+
29
+ Review the entire UI against this checklist. Check each item, note violations with file:line.
30
+
31
+ **Typography:**
32
+ - [ ] No generic fonts (Inter, Roboto, Arial, system-ui, Space Grotesk)
33
+ - [ ] Proper type scale with clear hierarchy (display → heading → body → caption)
34
+ - [ ] Body text: 16px+, line-height 1.5–1.7
35
+ - [ ] Headings: tighter line-height (1.1–1.3), negative letter-spacing for large sizes
36
+ - [ ] Prose max-width: 65ch
37
+ - [ ] Font weights used for hierarchy (Regular, Medium, Semibold, Bold)
38
+
39
+ **Color & Contrast:**
40
+ - [ ] Cohesive palette via CSS variables (not scattered hex values)
41
+ - [ ] All text passes WCAG AA contrast (4.5:1 normal, 3:1 large)
42
+ - [ ] CTA buttons use accent color — stand out from the page
43
+ - [ ] No blue-purple gradients, no rainbow palettes
44
+ - [ ] Dark mode: rethought surfaces (not just inverted)
45
+ - [ ] Semantic colors used consistently (success=green, error=red, warning=amber)
46
+
47
+ **Layout & Spacing:**
48
+ - [ ] Full-width fluid layouts — no hardcoded max-width caps
49
+ - [ ] 8px spacing grid followed consistently
50
+ - [ ] Tight spacing within groups, generous between sections
51
+ - [ ] Fluid padding: `clamp(1rem, 5vw, 4rem)` horizontal
52
+ - [ ] No identical card grids — varied visual hierarchy
53
+ - [ ] No generic heroes — purposeful, distinctive
54
+
55
+ **Interactive States:**
56
+ - [ ] Every button/link: hover (color shift, 150ms), focus (visible ring), active (press feedback), disabled
57
+ - [ ] Loading: skeleton or spinner on all async operations
58
+ - [ ] Empty: helpful message + action on empty lists/data
59
+ - [ ] Error: user-friendly message + recovery action on failed fetches
60
+ - [ ] Form validation: inline errors with `aria-describedby`
61
+
62
+ **Motion:**
63
+ - [ ] Hover/focus: 150–200ms transitions
64
+ - [ ] Page load: staggered entrance animations (50–80ms delay)
65
+ - [ ] Expand/collapse: 250ms ease-in-out
66
+ - [ ] `prefers-reduced-motion` respected (no animation for users who opt out)
67
+ - [ ] No jank: transforms and opacity only for animated properties
68
+
69
+ **Accessibility:**
70
+ - [ ] Semantic HTML: `nav`, `main`, `section`, `article`, `header`, `footer`
71
+ - [ ] One `h1` per page, sequential heading hierarchy
72
+ - [ ] All images: descriptive `alt` (or `alt=""` + `aria-hidden` if decorative)
73
+ - [ ] All form inputs: visible `<label>` with `htmlFor` — not placeholder-only
74
+ - [ ] All interactive elements: keyboard accessible (Tab/Enter/Escape)
75
+ - [ ] Touch targets: 44px minimum
76
+ - [ ] Skip link: `<a href="#main">` as first focusable element
77
+ - [ ] No `outline: none` without focus replacement
78
+ - [ ] `<html lang="en">` set
79
+ - [ ] Color not sole information carrier — icons/text as supplements
80
+
81
+ **Responsive:**
82
+ - [ ] Mobile-first approach (base styles for mobile, min-width breakpoints for larger)
83
+ - [ ] No horizontal scroll at 320px
84
+ - [ ] Navigation: hamburger on mobile, expanded on desktop
85
+ - [ ] Touch targets adequate on mobile (44px min)
86
+ - [ ] Fluid typography with `clamp()`
87
+ - [ ] Images: `max-width: 100%`, responsive srcset where needed
88
+ - [ ] Tables: card view or horizontal scroll on mobile
89
+
90
+ **Performance:**
91
+ - [ ] Server Components by default — `'use client'` only when needed
92
+ - [ ] Images via `next/image` with width/height
93
+ - [ ] No barrel file imports — direct imports from source
94
+ - [ ] Heavy components lazy-loaded with `next/dynamic`
95
+ - [ ] Data fetched in parallel, not sequentially
96
+
97
+ ### 2. Fix Everything
98
+
99
+ Work through violations from the critique. Fix each category:
100
+
101
+ 1. Typography first (sets the visual foundation)
102
+ 2. Color & contrast (palette coherence)
103
+ 3. Layout & spacing (structural fixes)
104
+ 4. Interactive states (loading, empty, error, hover, focus)
105
+ 5. Motion (transitions, entrance animations, reduced-motion)
106
+ 6. Accessibility (semantic HTML, ARIA, keyboard, labels)
107
+ 7. Responsive (mobile breakpoints, fluid sizing)
108
+ 8. Performance (quick wins — image optimization, dynamic imports)
30
109
 
31
110
  ### 3. Harden
32
- Edge cases and robustness:
33
- - Empty states (no data, loading, error)
34
- - Text overflow, long content
35
- - Mobile responsive (check all breakpoints)
36
- - Error messages (user-friendly, not technical)
37
111
 
38
- ### 4. Qualia Frontend Rules
39
- - Distinctive fonts (not Inter/Arial)
40
- - Cohesive color palette with sharp accents
41
- - CSS transitions, staggered animations
42
- - Full-width layouts, no hardcoded max-width caps
43
- - No card grids, no generic heroes, no blue-purple gradients
112
+ After polish, stress-test edge cases:
113
+ - Long text content (overflow, truncation, word-break)
114
+ - Extremely long usernames or email addresses
115
+ - Empty data everywhere simultaneously
116
+ - Error state on every fetch simultaneously
117
+ - 320px viewport width
118
+ - Keyboard-only navigation through entire flow
119
+ - Screen reader landmarks check (semantic HTML)
120
+ - Right-to-left text (if i18n is planned)
121
+ - Slow network (loading states visible, no flash of empty content)
44
122
 
45
- ### 5. Commit & Update
123
+ ### 4. Verify
124
+
125
+ ```bash
126
+ npx tsc --noEmit 2>&1 | head -20
127
+ ```
128
+
129
+ Fix any TypeScript errors before committing.
130
+
131
+ ### 5. Commit & Transition
46
132
 
47
133
  ```bash
48
134
  git add {changed files}
49
- git commit -m "polish: design and UX pass"
135
+ git commit -m "polish: design and UX pass — typography, accessibility, responsive, states"
50
136
  ```
51
137
 
52
138
  ```bash
@@ -54,6 +140,22 @@ node ~/.claude/bin/state.js transition --to polished
54
140
  ```
55
141
  Do NOT manually edit STATE.md or tracking.json — state.js handles both.
56
142
 
143
+ ### 6. Report
144
+
57
145
  ```
146
+ ◆ QUALIA ► POLISHED
147
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
148
+ Files modified: {N}
149
+
150
+ Typography ✓ {brief}
151
+ Color ✓ {brief}
152
+ Layout ✓ {brief}
153
+ States ✓ {brief}
154
+ Motion ✓ {brief}
155
+ Accessibility ✓ {brief}
156
+ Responsive ✓ {brief}
157
+ Performance ✓ {brief}
158
+ Hardening ✓ {brief}
159
+
58
160
  → Run: /qualia-ship
59
161
  ```
@@ -5,7 +5,7 @@ description: "Generate session report and commit to repo. Mandatory before clock
5
5
 
6
6
  # /qualia-report — Session Report
7
7
 
8
- Generate a concise report of what was done. Committed to git for the ERP to read.
8
+ Generate a concise report of what was done. Committed to git and uploaded to the ERP for clock-out.
9
9
 
10
10
  ## Process
11
11
 
@@ -69,7 +69,28 @@ git commit -m "report: session {YYYY-MM-DD}"
69
69
  git push
70
70
  ```
71
71
 
72
- ### 5. Update State
72
+ ### 5. Upload to ERP
73
+
74
+ **This step is MANDATORY** — the clock-out modal requires the report to be uploaded.
75
+
76
+ ```bash
77
+ ERP_URL="https://portal.qualiasolutions.net"
78
+ API_KEY=$(cat ~/.claude/.erp-api-key 2>/dev/null)
79
+ REPORT_FILE=".planning/reports/report-{date}.md"
80
+ EMAIL=$(git config user.email)
81
+ PROJECT=$(basename $(pwd))
82
+
83
+ curl -s -X POST "$ERP_URL/api/claude/report-upload" \
84
+ -H "X-API-Key: $API_KEY" \
85
+ -F "file=@$REPORT_FILE" \
86
+ -F "employee_email=$EMAIL" \
87
+ -F "project_name=$PROJECT"
88
+ ```
89
+
90
+ If the upload succeeds, print: "Report uploaded to ERP. You can now clock out."
91
+ If it fails (no API key, network error), print the error and tell the employee to ask Fawzi.
92
+
93
+ ### 6. Update State
73
94
 
74
95
  ```bash
75
96
  node ~/.claude/bin/state.js transition --to activity --notes "Session report generated"
@@ -0,0 +1,137 @@
1
+ # Design System — {Project Name}
2
+
3
+ > Generated during project setup. This is the source of truth for all frontend work.
4
+ > Builder agents read this before writing any component. Update it as design evolves.
5
+
6
+ ## Brand
7
+
8
+ - **Tone:** {dark-bold | clean-minimal | colorful-playful | corporate-professional}
9
+ - **Personality:** {1-2 sentences describing the feel — e.g., "Confident and technical, like a Bloomberg terminal meets a luxury brand"}
10
+ - **Industry:** {e.g., fintech, healthcare, SaaS, e-commerce}
11
+
12
+ ## Color System
13
+
14
+ ```css
15
+ :root {
16
+ /* Primary — brand identity */
17
+ --color-primary: {value};
18
+ --color-primary-hover: {value};
19
+ --color-primary-subtle: {value}; /* backgrounds, badges */
20
+
21
+ /* Accent — CTAs, highlights */
22
+ --color-accent: {value};
23
+ --color-accent-hover: {value};
24
+
25
+ /* Neutral — text, borders, backgrounds */
26
+ --color-bg: {value};
27
+ --color-bg-subtle: {value}; /* cards, raised surfaces */
28
+ --color-bg-muted: {value}; /* disabled, secondary surfaces */
29
+ --color-text: {value};
30
+ --color-text-muted: {value}; /* secondary text */
31
+ --color-text-subtle: {value}; /* placeholders, hints */
32
+ --color-border: {value};
33
+ --color-border-subtle: {value};
34
+
35
+ /* Semantic */
36
+ --color-success: {value};
37
+ --color-warning: {value};
38
+ --color-error: {value};
39
+ --color-info: {value};
40
+ }
41
+
42
+ /* Dark mode overrides */
43
+ [data-theme="dark"] {
44
+ --color-bg: {value};
45
+ --color-bg-subtle: {value};
46
+ --color-text: {value};
47
+ /* ... override all tokens ... */
48
+ }
49
+ ```
50
+
51
+ ## Typography
52
+
53
+ ```css
54
+ :root {
55
+ /* Font families */
56
+ --font-display: '{Display Font}', {fallback}; /* Hero text, page titles */
57
+ --font-heading: '{Heading Font}', {fallback}; /* Section headings */
58
+ --font-body: '{Body Font}', {fallback}; /* Paragraphs, UI text */
59
+ --font-mono: '{Mono Font}', monospace; /* Code, data */
60
+
61
+ /* Scale */
62
+ --text-xs: clamp(0.75rem, 0.7rem + 0.25vw, 0.8rem);
63
+ --text-sm: clamp(0.875rem, 0.8rem + 0.4vw, 0.9rem);
64
+ --text-base: clamp(1rem, 0.5rem + 1.5vw, 1.125rem);
65
+ --text-lg: clamp(1.125rem, 0.75rem + 1.2vw, 1.25rem);
66
+ --text-xl: clamp(1.25rem, 0.75rem + 1.5vw, 1.5rem);
67
+ --text-2xl: clamp(1.5rem, 0.75rem + 2.25vw, 2rem);
68
+ --text-3xl: clamp(1.875rem, 1rem + 2.5vw, 2.5rem);
69
+ --text-4xl: clamp(2.25rem, 1rem + 3vw, 3rem);
70
+ --text-5xl: clamp(3rem, 1rem + 4vw, 4rem);
71
+ }
72
+ ```
73
+
74
+ **Google Fonts import:** `{URL}`
75
+
76
+ ## Spacing Scale
77
+
78
+ Based on 8px grid: `4 / 8 / 12 / 16 / 24 / 32 / 48 / 64 / 96 / 128`
79
+
80
+ - **Within components:** 8–16px
81
+ - **Between related elements:** 16–24px
82
+ - **Between sections:** 48–96px
83
+ - **Page padding:** `clamp(1rem, 5vw, 4rem)` horizontal
84
+
85
+ ## Motion
86
+
87
+ - **Approach:** {minimal | subtle | expressive}
88
+ - **Page load:** staggered fade-up, 60ms delay between elements
89
+ - **Hover/focus:** 150ms ease-out
90
+ - **Expand/collapse:** 250ms ease-in-out
91
+ - **Page transitions:** 400ms ease-out
92
+ - **Reduced motion:** all non-essential animations disabled
93
+
94
+ ## Component Patterns
95
+
96
+ ### Buttons
97
+ - **Primary:** solid {accent} background, white text, rounded-{radius}
98
+ - **Secondary:** bordered, transparent background
99
+ - **Ghost:** text-only, hover background
100
+ - **Destructive:** red variant for dangerous actions
101
+ - **Sizes:** sm (32px), md (40px), lg (48px)
102
+
103
+ ### Inputs
104
+ - Border: 1px solid var(--color-border)
105
+ - Focus: 2px ring var(--color-primary)
106
+ - Error: red border + error text below with `aria-describedby`
107
+ - Height: 40px (md), 48px (lg)
108
+
109
+ ### Cards/Surfaces
110
+ - Background: var(--color-bg-subtle)
111
+ - Border: 1px solid var(--color-border-subtle) or shadow
112
+ - Border-radius: {value}
113
+ - No identical card grids — vary layout and emphasis
114
+
115
+ ## Responsive Approach
116
+
117
+ - **Strategy:** mobile-first
118
+ - **Primary breakpoints:** 768px (tablet), 1024px (desktop)
119
+ - **Navigation:** hamburger on mobile, expanded on desktop
120
+ - **Layout:** single column mobile → multi-column desktop
121
+ - **Touch targets:** 44px minimum on mobile
122
+
123
+ ## Visual Effects
124
+
125
+ - {e.g., "Noise texture overlay at 3% opacity on hero sections"}
126
+ - {e.g., "Glass-morphism on floating elements: backdrop-blur-xl bg-white/80"}
127
+ - {e.g., "Gradient mesh on hero: radial-gradient from primary to transparent"}
128
+ - {e.g., "Decorative geometric shapes as background accents"}
129
+
130
+ ## Anti-Patterns (Don't Do This)
131
+
132
+ - No Inter, Roboto, Arial, system-ui fonts
133
+ - No blue-purple gradients
134
+ - No identical card grids
135
+ - No generic stock-photo heroes
136
+ - No hardcoded max-width containers (use fluid layouts)
137
+ - No gray-on-gray low-contrast text