baldart 5.1.0 → 5.2.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/README.md +3 -3
  3. package/VERSION +1 -1
  4. package/framework/.claude/agents/CHANGELOG.md +45 -0
  5. package/framework/.claude/agents/REGISTRY.md +2 -2
  6. package/framework/.claude/agents/coder.md +3 -3
  7. package/framework/.claude/agents/remotion-animator-orchestrator.md +4 -3
  8. package/framework/.claude/agents/ui-expert.md +4 -10
  9. package/framework/.claude/agents/ui-quality-critic.md +27 -11
  10. package/framework/.claude/skills/design-system-init/CHANGELOG.md +5 -0
  11. package/framework/.claude/skills/design-system-init/SKILL.md +2 -2
  12. package/framework/.claude/skills/e2e-review/CHANGELOG.md +5 -0
  13. package/framework/.claude/skills/e2e-review/SKILL.md +2 -2
  14. package/framework/.claude/skills/frontend-design/CHANGELOG.md +20 -0
  15. package/framework/.claude/skills/frontend-design/SKILL.md +39 -216
  16. package/framework/.claude/skills/gamification-design/CHANGELOG.md +5 -0
  17. package/framework/.claude/skills/gamification-design/SKILL.md +2 -2
  18. package/framework/.claude/skills/ui-design/CHANGELOG.md +60 -1
  19. package/framework/.claude/skills/ui-design/SKILL.md +127 -75
  20. package/framework/.claude/skills/ui-design/references/anti-slop.md +106 -0
  21. package/framework/.claude/skills/ui-design/references/craft-standards.md +259 -0
  22. package/framework/.claude/skills/ui-design/references/design-brief.md +92 -0
  23. package/framework/.claude/skills/ui-design/references/design-directions.md +188 -0
  24. package/framework/.claude/skills/ui-design/references/evaluation.md +125 -165
  25. package/framework/.claude/skills/ui-design/references/generation.md +125 -92
  26. package/framework/.claude/skills/ui-design/references/inventory.md +9 -2
  27. package/framework/.claude/skills/ui-design/scripts/craft-check.mjs +248 -0
  28. package/framework/agents/component-manifest-schema.md +1 -1
  29. package/framework/agents/design-system-protocol.md +6 -6
  30. package/framework/agents/index.md +1 -0
  31. package/framework/agents/skills-mapping.md +25 -23
  32. package/framework/docs/PROJECT-CONFIGURATION.md +5 -5
  33. package/package.json +1 -1
  34. package/src/commands/configure.js +1 -1
  35. package/src/utils/__tests__/classify-divergence.test.js +42 -0
  36. package/src/utils/git.js +45 -9
@@ -0,0 +1,259 @@
1
+ # Craft Standards — always-on rules for every generated surface
2
+
3
+ These are the non-negotiable craft rules the generator applies while producing
4
+ mockups (Step C) and the evaluator verifies (Step D). They are **binding on
5
+ every option**, in every direction, in both registers — aesthetic direction
6
+ changes *what* you design, never *how well*.
7
+
8
+ > **Numeric SSOT rule.** Type-scale ratios, contrast targets (WCAG + APCA),
9
+ > spacing scales, and density tiers live in
10
+ > [`framework/agents/design-system-protocol.md`](../../../../agents/design-system-protocol.md)
11
+ > § "Reference Tables" — cite those values verbatim, never restate from memory.
12
+ > This file adds the craft rules *not* covered there.
13
+ >
14
+ > Distilled in part from [impeccable](https://github.com/pbakaus/impeccable)
15
+ > (Apache-2.0, © Paul Bakaus),
16
+ > [taste-skill](https://github.com/Leonxlnx/taste-skill) (MIT, © Leonxlnx) and
17
+ > [open-design](https://github.com/nexu-io/open-design) (Apache-2.0, nexu-io).
18
+ >
19
+ > **Precedence.** The project's own contract wins on conflict: design-system
20
+ > tokens (`tokens-reference.md`) > `${paths.ui_guidelines}` + the skill overlay
21
+ > > these craft standards. Craft rules cover everything the project does not
22
+ > explicitly override.
23
+
24
+ ## Typography
25
+
26
+ - **One scale.** Pick ONE ratio from the protocol § Type scale and derive every
27
+ size from it — 6–9 deliberate steps max. Extra hierarchy comes from weight,
28
+ color, and spacing, not new sizes.
29
+ - **Line length**: body text 65–75ch (`max-w-[65ch]` or equivalent). Apply
30
+ `text-wrap: balance` on h1–h3, `text-wrap: pretty` on prose.
31
+ - **Display ceiling**: hero/display headings cap at `clamp()` max ≤ 6rem
32
+ (~96px). Above that the page is shouting, not designing. Keep any `clamp()`
33
+ bounded: max ≤ ~2.5× min.
34
+ - **Headline discipline**: H1 max 2 lines at desktop. A 4-line hero headline is
35
+ a font-size error, never a copy-length error — plan scale and copy together.
36
+ - **Tracking — the single most-skipped rule in AI-generated design.** Body
37
+ (14–18px) `0` · small text (11–13px) `+0.01–0.02em` · UI labels `+0.02em` ·
38
+ **ALL-CAPS `+0.06–0.1em` (required — the 0.06em floor is the empirical
39
+ typographic lower bound)** · headings 32px+ `−0.01–0.02em` · display 48px+
40
+ `−0.02–0.03em`, never below `−0.04em`. ALL-CAPS without positive tracking
41
+ looks cramped; display without negative tracking looks loose — the two most
42
+ reliable slop tells. ALL-CAPS body text is banned; never `text-align:
43
+ justify`.
44
+ - **Three-weight system**: Read (400/450) · Emphasize (510/550) · Announce
45
+ (590/600). Weight 700+ is rarely needed — reach for size/color/space first.
46
+ - **Pairing**: pair on a contrast axis (serif + sans, geometric + humanist,
47
+ display + mono) or use one family in multiple weights. Never pair fonts that
48
+ are similar-but-not-identical.
49
+ - **Emphasis**: italic or bold of the SAME family. Never inject a serif word
50
+ into a sans headline for "flair" — mixed-family emphasis reads amateur.
51
+ - **Italic descender clearance**: italic display words containing `y g j p q`
52
+ need `leading-[1.1]` minimum plus bottom padding — `leading-none` clips them.
53
+ - **Light-on-dark compensation**: on dark surfaces bump line-height by
54
+ 0.05–0.1, add 0.01–0.02em letter-spacing, and optionally drop body weight one
55
+ notch (400 → 350). Light text visually thickens.
56
+
57
+ ## Color
58
+
59
+ - **Contrast is zero-tolerance.** Every text/background pair meets the
60
+ protocol § Color contrast targets (body ≥ 4.5:1, large ≥ 3:1, UI ≥ 3:1 —
61
+ APCA as secondary gate). Placeholder text counts as content. Every `bg-*`
62
+ utility has an explicit paired `text-*`. Light-gray-for-elegance is the
63
+ single biggest reason AI designs read as hard to use.
64
+ - **Gray-on-color is banned.** Gray text over a colored background looks
65
+ washed out — use a darker shade of the background's own hue, or a
66
+ transparency of the text color.
67
+ - **Color proportions**: neutrals carry 70–90% of pixels · ONE accent at
68
+ 5–10% · semantic colors 0–5% · pure-effect color < 1%. Never invent a second
69
+ accent. **Ration the accent to ≤ 2 visible uses per screen** (typical pair:
70
+ one chip/eyebrow + the primary CTA — links, hover states and focus rings
71
+ count). A fuller commitment is a deliberate direction choice (see
72
+ `design-brief.md` § Color commitment), never a drift. Once chosen, the
73
+ accent is consistent page-wide — a warm-grey page does not sprout a blue CTA
74
+ in section 7.
75
+ - **Tinted neutrals.** Pure gray is dead: tint neutrals 0.005–0.015 chroma
76
+ toward the brand hue (OKLCH). Prefer OKLCH for any new palette work.
77
+ - **Dark surfaces**: never pure `#000000` / `#ffffff` — off-black and
78
+ off-white keep depth. Dark mode is not inversion: build a 3-step surface
79
+ scale (≈15% / 20% / 25% lightness) and let depth come from surface
80
+ lightness, not shadow.
81
+ - **Alpha is a design smell.** Heavy use of transparency usually means an
82
+ incomplete palette — name the actual surface colors.
83
+
84
+ ## Spacing, layout & hierarchy
85
+
86
+ - **One spacing scale** from the protocol § Spacing scale (base-4 preferred
87
+ for product UI). Arbitrary off-scale values (`p-[13px]`) are token
88
+ violations.
89
+ - **Rhythm**: 8–12px between tight siblings, 48–96px between sections.
90
+ Consistent gaps between similar elements — monotonous identical spacing
91
+ everywhere is its own tell.
92
+ - **Hierarchy math**: a strong size jump is ≥ 3:1; below 2:1 the hierarchy is
93
+ weak. The best hierarchy combines 2–3 dimensions at once (size + weight +
94
+ color/space), never size alone.
95
+ - **Layout mechanics**: Flexbox for 1D, Grid for 2D. Breakpoint-free grids via
96
+ `repeat(auto-fit, minmax(280px, 1fr))` where content allows. Semantic
97
+ z-index scale (dropdown → sticky → modal-backdrop → modal → toast →
98
+ tooltip), never `z-[999]`.
99
+ - **Cards are the lazy answer.** Use a card only when a bounded, repeatable
100
+ unit is truly the best affordance. Nested cards are always wrong.
101
+ - **Layout-family diversity**: a section layout family appears max twice per
102
+ page and never 3× consecutively (image+text zigzag caps at 2 in a row). A
103
+ landing page with 8 sections needs ≥ 4 distinct layout families.
104
+ - **Bento cell count = content count.** A grid with an empty filler tile was
105
+ planned wrong — reshape the grid instead of pasting a blank cell. Give 2–3
106
+ cells real visual variation (image / gradient / pattern), not uniform
107
+ white-on-white.
108
+ - **Viewport discipline**: `min-h-[100dvh]` never `h-screen` (iOS Safari).
109
+ Text never overflows or clips — the viewport is part of the design.
110
+ Dropdowns inside `overflow: hidden` containers get clipped: use
111
+ `<dialog>`, the popover API, `position: fixed`, or a portal.
112
+ - **Touch targets**: honor the protocol § Density tiers (touch-primary ⇒
113
+ Comfortable tier, 44px). When a control must render smaller, expand the hit
114
+ area with a pseudo-element.
115
+
116
+ ## States — the 8-state taxonomy
117
+
118
+ Every interactive component ships **default · hover · focus · active ·
119
+ disabled · loading · error** — plus the surface-level **empty** state. Never
120
+ design only the happy path:
121
+
122
+ - Loading = skeletons that mirror real layout dimensions exactly (a
123
+ wrong-height skeleton *causes* layout shift), not spinners. Thresholds:
124
+ 0–300ms no indicator at all · past ~15s show a "taking longer than
125
+ expected" fallback.
126
+ - Empty states teach the interface (what goes here + the CTA that fills it).
127
+ - Error states answer three questions: what happened · why (if knowable) ·
128
+ what the user can do — localized (`identity.language`), with the user's
129
+ input preserved. Never a bare "Invalid input".
130
+ - Focus is visible and styled (≥ 3:1 contrast on the indicator), not the
131
+ browser default leaking through a restyled component.
132
+ - Edge state: extreme volume, 200-char titles, RTL, partial network — a
133
+ populated-only mockup hides the layout's real failure modes.
134
+
135
+ ## Cognitive load (Laws of UX, operational numbers)
136
+
137
+ - **Proximity**: variable vertical rhythm — 8–12px within a group, 32–48px
138
+ between groups. Uniform spacing reads as nothing being grouped.
139
+ - **Hick's Law**: cap any single decision screen at 3–5 visible primary
140
+ options.
141
+ - **Choice overload**: pricing 3–4 tiers with exactly one marked recommended ·
142
+ product grids 6–9 hero cards above the fold · settings ≤ 5 named groups ·
143
+ nav ≤ 5 top-level items.
144
+ - **Tesler's Law**: complexity is conserved — the design decision is *where*
145
+ it lives (defaults, progressive disclosure), not whether to eliminate it.
146
+ - Working memory holds ~4 chunks: never ask the user to carry more across a
147
+ flow.
148
+
149
+ ## Motion
150
+
151
+ - **The 100/300/500 rule**: 100–150ms instant feedback (hover, press) ·
152
+ 200–300ms state changes · 300–500ms layout moves · 500–800ms entrances
153
+ (brand surfaces only). Exits run ~75% of the paired entrance. Below ~80ms
154
+ motion isn't perceived — don't spend it. Mobile runs 20–30% shorter than
155
+ desktop.
156
+ - **Curve vs spring**: a curve for opacity/color, a spring for
157
+ position/scale/rotation. Animate only when the user moves through space,
158
+ time, or state (navigation, container expansion, progress, gesture
159
+ follow-through) — never to teach, decorate, or signal "premium".
160
+ - **Easing**: ease-out with exponential curves (quart/quint/expo family). No
161
+ bounce, no elastic, no `linear`/`ease-in-out` defaults — pick a deliberate
162
+ cubic-bezier.
163
+ - **Motion must be motivated.** Valid reasons: hierarchy, storytelling,
164
+ feedback, state transition. "It looked cool" is not one — if you cannot
165
+ state the reason in one sentence, drop the animation.
166
+ - **The uniform reflex is the tell, not motion itself.** One identical
167
+ entrance applied to every section reads as AI grammar; but shipping a page
168
+ with zero motion to avoid it is also wrong. One well-orchestrated entrance
169
+ with staggered reveals beats scattered micro-interactions.
170
+ - **Reveal animations enhance already-visible content.** Never gate content
171
+ visibility on a class-triggered transition: transitions pause in hidden tabs
172
+ and headless renderers, and the section ships blank.
173
+ - **Register budgets**: product surfaces 150–250ms, no orchestrated page-load
174
+ sequences; brand surfaces may spend one entrance sequence. Marquee ≤ 1 per
175
+ page.
176
+ - **Mechanics**: animate `transform`/`opacity` only. Never
177
+ `window.addEventListener("scroll")` and never continuous input values
178
+ (mouse, scroll progress) in framework state — use the animation library's
179
+ motion values. `prefers-reduced-motion` support is not optional.
180
+
181
+ ## Forms (always-on, every project)
182
+
183
+ - `<label>` associated via `htmlFor`/`id` (never wrap-only).
184
+ - `autocomplete=` on every personal-data field (`email | tel | given-name |
185
+ family-name | street-address | postal-code | cc-number | one-time-code` …).
186
+ - Validate **on blur**, re-validate on submit — never on every keystroke.
187
+ - Errors actionable ("Email manca @ — esempio: nome@dominio.it"), with
188
+ `aria-invalid` + `aria-describedby`; `role="alert"` only when the error
189
+ appears dynamically.
190
+ - `inputMode=` when it differs from `type` (SMS codes: `type="text"
191
+ inputMode="numeric"`).
192
+ - Paste handling normalizes whitespace/format BEFORE validating.
193
+ - Submit disabled only **after** a failed attempt, never pre-emptively.
194
+
195
+ ## Performance Gates (Core Web Vitals 2026) — canonical home
196
+
197
+ Production-grade frontend ships within CWV budgets by design, not after
198
+ Lighthouse complains. (This section moved here from the retired
199
+ `frontend-design` generator — this is now the canonical reference, cited by
200
+ `ui-expert`.)
201
+
202
+ | Metric | Good | Poor | What it measures |
203
+ |---|---|---|---|
204
+ | **LCP** | ≤ 2.5s | > 4.0s | Largest Contentful Paint — usually hero image or H1 |
205
+ | **INP** | ≤ 200ms | > 500ms | Interaction to Next Paint |
206
+ | **CLS** | ≤ 0.1 | > 0.25 | Cumulative Layout Shift |
207
+ | TTFB | ≤ 0.8s | > 1.8s | Subset of LCP (~40% of budget) |
208
+ | FCP | ≤ 1.8s | > 3.0s | Diagnostic only |
209
+
210
+ **LCP image — the only correct pattern:**
211
+
212
+ ```html
213
+ <!-- in <head> — preload + fetchpriority for the hero -->
214
+ <link rel="preload" as="image"
215
+ href="/hero.avif"
216
+ imagesrcset="/hero-800.avif 800w, /hero-1600.avif 1600w"
217
+ imagesizes="100vw"
218
+ fetchpriority="high">
219
+
220
+ <!-- in body — picture with AVIF/WebP/fallback + explicit dimensions -->
221
+ <picture>
222
+ <source srcset="/hero.avif" type="image/avif">
223
+ <source srcset="/hero.webp" type="image/webp">
224
+ <img src="/hero.jpg" alt="..."
225
+ fetchpriority="high"
226
+ width="1600" height="900">
227
+ </picture>
228
+ ```
229
+
230
+ **Never** `loading="lazy"` on the LCP image; **never** client-render it
231
+ post-hydration.
232
+
233
+ **INP**: break tasks > 50ms with `await scheduler.yield()` (fallback
234
+ `setTimeout 0`) · debounce input handlers to one frame when they trigger
235
+ expensive recomputes · move CPU-bound work to Web Workers · no `setInterval`
236
+ polling (use stale-while-revalidate).
237
+
238
+ **CLS — zero unexpected shift**: every `<img>`/`<iframe>`/`<video>` declares
239
+ `width`+`height` or `aspect-ratio` · web fonts use `font-display: optional` OR
240
+ `size-adjust` + metric overrides · skeletons mirror real dimensions · inserted
241
+ UI (banners, notices) reserves space upfront via `min-height`.
242
+
243
+ ## Modern CSS (2025–2026)
244
+
245
+ Default to platform features instead of JS shims:
246
+
247
+ - **Container queries** (`@container` + `container-type: inline-size`) for any
248
+ component living in variable-width contexts; viewport `@media` only for
249
+ app-shell layout.
250
+ - **`:has()`** to collapse state that exists only for styling — visual
251
+ reactions to DOM state, never business logic.
252
+ - **View Transitions API** for SPA navigation and shared-element morphs (full
253
+ pattern: `motion-design` skill references).
254
+ - **Subgrid** for cross-row content alignment inside cards.
255
+ - **Logical properties** (`margin-inline-start`, `padding-block`) whenever RTL
256
+ or vertical writing modes are conceivable — free i18n.
257
+ - **`color-mix()`** to derive hover/focus/disabled from semantic tokens
258
+ (`color-mix(in oklch, var(--color-action-primary) 90%, black)`).
259
+ - **`@scope`** to scope styles to a subtree without specificity wars.
@@ -0,0 +1,92 @@
1
+ # Design Brief — Step C.0: Design Read & Direction Lock
2
+
3
+ Most AI-generated UIs fail not because of bad code, but because of skipped
4
+ thinking. This step converts the inputs (discovery answers, user brief,
5
+ context screenshots, `identity.*`) into a locked design intent BEFORE any
6
+ HTML is generated. It costs one short block of reasoning and prevents the
7
+ dominant failure mode: generating three layouts of the same unexamined
8
+ default.
9
+
10
+ > Distilled from [impeccable](https://github.com/pbakaus/impeccable)
11
+ > (Apache-2.0, © Paul Bakaus) and
12
+ > [taste-skill](https://github.com/Leonxlnx/taste-skill) (MIT, © Leonxlnx).
13
+
14
+ ## 1. Classify the register
15
+
16
+ | Register | Definition | Consequences |
17
+ |---|---|---|
18
+ | **Brand** | Design IS the product's voice: landing, marketing, hero surfaces, campaign pages | Bolder type ratio (protocol § Type scale, ≥ 1.25) · one orchestrated entrance allowed · color commitment may exceed Restrained · restraint without intent reads as mediocre — go big or go home |
19
+ | **Product** | Design SERVES the task: app screens, dashboards, forms, settings | Fixed rem scale, ratio 1.125–1.2 · Restrained color (accent = actions/selection/state only, never decoration) · motion 150–250ms, no page-load sequences · **the slop test flips: the bar is *earned familiarity*, not distinctiveness** — the tool should disappear into the task; strangeness without purpose is the failure mode |
20
+
21
+ Mixed features (a landing + an app screen) classify per-screen.
22
+
23
+ ## 2. Determine the regime
24
+
25
+ | Regime | When | What varies across the 3 options |
26
+ |---|---|---|
27
+ | **In-context** | `features.has_design_system: true`, OR the feature lands inside an existing app shell (context screenshots exist) | Layout, hierarchy, information architecture, interaction pattern, density — the project's visual language (tokens, type, palette) is FIXED. Context fidelity is king |
28
+ | **Exploration** | Greenfield surface, new product, standalone page with no binding language | Aesthetic direction — each option takes a DIFFERENT named direction from `design-directions.md`, each with its own typography/palette/composition |
29
+
30
+ Never explore aesthetics on an in-context run: proposing a new visual
31
+ language for one screen of an existing product is drift, not creativity.
32
+
33
+ ## 3. Set the three dials
34
+
35
+ `DESIGN_VARIANCE` (how far from convention) · `MOTION_INTENSITY` ·
36
+ `VISUAL_DENSITY` — each 1–10. Canonical names; never invent aliases.
37
+
38
+ | Signal | VARIANCE | MOTION | DENSITY |
39
+ |---|---|---|---|
40
+ | Brand register, launch/campaign | 7–9 | 6–8 | 3–4 |
41
+ | Brand register, trust-first / public-sector / regulated | 3–4 | 2–3 | 4–5 |
42
+ | Product register (default) | 3–5 | 2–4 | 5–7 |
43
+ | Product register, data-heavy power tool | 2–4 | 1–3 | 7–9 |
44
+ | Explicit "make it bold/memorable" from the user | +2 | +1 | — |
45
+
46
+ Quiet constraints override every dial: accessibility-first briefs, kids
47
+ audiences, public sector → drop VARIANCE and MOTION to the low band and say
48
+ so in the Design Read. Dials gate downstream rules ("motion claimed, motion
49
+ shown": if MOTION > 4 the page must actually move — otherwise lower the dial
50
+ and ship clean static).
51
+
52
+ ## 4. Emit the Design Read (mandatory, one line + assignments)
53
+
54
+ Before generating, output — to the user in interactive mode, to the state
55
+ file always:
56
+
57
+ ```
58
+ Design Read: <page kind> for <audience>, <register> register, <regime>
59
+ regime, dials V<x>/M<y>/D<z>, leaning <design system | direction family>.
60
+ Options: A = <direction/layout hypothesis> · B = … · C = …
61
+ Color commitment: <Restrained | Committed | Full | Drenched> (reference: <named real-world anchor>)
62
+ Dark/light: <choice> — <the one-sentence physical scene that forces it>
63
+ Anti-references: <what this must NOT look like — e.g. "not SaaS-cream, not dark-glow">
64
+ ```
65
+
66
+ Rules:
67
+
68
+ - **Ambiguity → exactly ONE question.** If the read is genuinely ambiguous
69
+ ("Linear-clean or Awwwards-experimental?"), ask one crisp question with the
70
+ two poles — never a battery of questions, and never guess silently.
71
+ Assert-then-confirm beats menu-with-escape: "This reads as Restrained
72
+ product UI — confirm?" When invoked from `/prd`, the discovery answers
73
+ usually make the read unambiguous: do NOT re-ask what discovery already
74
+ answered. (Decision-gate mechanics per runtime:
75
+ `framework/agents/runtime-portability-protocol.md`.)
76
+ - **Run the two-altitude slop test** on your own read (`anti-slop.md`): if
77
+ the direction you "naturally" landed on is the first- or second-order
78
+ reflex for this category, reject it and pick deliberately.
79
+ - **Rotation check**: read the state file / previous designs in
80
+ `${paths.prd_dir}` for the last exploration run's direction and display
81
+ font — do not repeat them (`design-directions.md` § Rotation rule).
82
+ - **Anti-references are part of the brief.** Ask for them in discovery if
83
+ absent; they are the cheapest signal the user can give.
84
+
85
+ ## 5. What C.0 hands to generation (C.1)
86
+
87
+ - The Design Read block (above), persisted in the state file under
88
+ `## UI Design` → `design_read`.
89
+ - Per-option: direction name (exploration) or layout/IA hypothesis
90
+ (in-context), color commitment, register, dials.
91
+ - The reflex-reject outcomes: which defaults were considered and refused
92
+ (one line — this keeps the generator honest and the evaluator informed).
@@ -0,0 +1,188 @@
1
+ # Design Directions — the aesthetic vocabulary for exploration
2
+
3
+ The curated menu of named aesthetic directions, font pools, and palette
4
+ strategies used at **Step C.0 (Direction Lock)** when the run is in
5
+ **exploration regime** (no binding design system / new surface — see
6
+ `design-brief.md` § Regime). In **in-context regime** this file is consulted
7
+ only for craft vocabulary — the project's own visual language always wins.
8
+
9
+ > Distilled from [taste-skill](https://github.com/Leonxlnx/taste-skill) (MIT,
10
+ > © Leonxlnx), [impeccable](https://github.com/pbakaus/impeccable)
11
+ > (Apache-2.0, © Paul Bakaus) and
12
+ > [open-design](https://github.com/nexu-io/open-design) (Apache-2.0, nexu-io).
13
+
14
+ ## How to use this menu
15
+
16
+ 1. Classify register + read the brief (`design-brief.md`), THEN pick.
17
+ 2. In exploration regime, each of the 3 options takes a **different**
18
+ direction from this menu (or a deliberate hybrid, named in the rationale).
19
+ 3. **One system per project**: if the brief reads as a real design system
20
+ (Material, Fluent, Carbon, Polaris, Primer, GOV.UK/USWDS, Radix, shadcn),
21
+ honor that language — never recreate its CSS from imagination and never mix
22
+ two systems.
23
+ 4. **Rotation rule**: never reuse the same direction or the same display font
24
+ family across consecutive exploration runs in the same project — check the
25
+ state file for the previous run's direction.
26
+ 5. **Identity preservation wins**: reflex-reject lists below apply to
27
+ *greenfield defaults*, never to an existing brand's established choices.
28
+
29
+ ## The direction menu
30
+
31
+ Each direction: when it fits · typography · palette · composition · motion ·
32
+ what kills it.
33
+
34
+ ### 1. Editorial Luxury
35
+ Warm paper canvas (`#FDFBF7` family — a *deliberate* opt-in, see the beige
36
+ ban below), muted sage/espresso accents, one refined display serif from the
37
+ rotation pool + humanist sans body, generous whitespace, film-grain noise at
38
+ `opacity-[0.03]`. Fits: premium consumer, craft brands, magazines. Motion:
39
+ slow reveals (400–500ms), no bounce. Killed by: brass/clay/oxblood accents
40
+ (the banned battery), Fraunces/Instrument Serif, more than one decoration
41
+ layer.
42
+
43
+ ### 2. Ethereal Glass (OLED)
44
+ Near-black canvas (`#050505`), radial gradient mesh far behind content,
45
+ vantablack cards with `backdrop-blur-2xl` and `white/10` hairlines,
46
+ white-on-black type. Fits: dev-tools, AI products *when deliberately chosen*,
47
+ premium hardware. Motion: slow parallax, glow-on-hover. Killed by: purple/blue
48
+ "trust" gradients, colored box-shadow glows, gradient text.
49
+
50
+ ### 3. Soft Structuralism
51
+ Silver-grey/white surfaces, bold grotesk display, diffused ambient shadows,
52
+ concentric radii ("double-bezel": outer shell `ring-1 ring-black/5 p-1.5
53
+ rounded-[2rem]`, inner core `rounded-[calc(2rem-0.375rem)]`). Fits: modern
54
+ SaaS brand surfaces that must feel engineered. Motion: custom cubic-bezier
55
+ (`cubic-bezier(0.32, 0.72, 0, 1)`), never linear/ease-in-out. Killed by:
56
+ default shadows, mixed radius systems.
57
+
58
+ ### 4. Warm Minimal (Notion/Linear editorial)
59
+ Warm monochrome: canvas `#FFFFFF`/`#F7F6F3`, borders `#EAEAEA`, ink
60
+ `#111111`, secondary `#787774`; spot pastels only as paired text/bg chips
61
+ (Pale Red `#FDEBEC`/`#9F2F2D`, Pale Blue `#E1F3FE`/`#1F6C9F`, Pale Green
62
+ `#EDF3EC`/`#346538`, Pale Yellow `#FBF3DB`/`#956400`); black CTA, radius
63
+ 4–6px, no shadow. Fits: product register, docs, tools. Motion: 150–200ms
64
+ state changes only. Killed by: decorative color, hero theatrics.
65
+
66
+ ### 5. Swiss Industrial Print
67
+ Paper `#F4F4F0`/`#EAE8E3`, ink `#050505`, ONE accent (Aviation Red
68
+ `#E61919`), macro-type `clamp(4rem, 10vw, 15rem)` uppercase with tight
69
+ leading (0.85–0.95), mono micro-labels (+0.05–0.1em tracking), radius 0
70
+ absolute, mathematical hairlines (`display: grid; gap: 1px` with contrasting
71
+ backgrounds). Fits: portfolios, manifestos, industrial/logistics brands.
72
+ Killed by: rounded corners, soft shadows, second accent.
73
+
74
+ ### 6. Tactical Telemetry (CRT)
75
+ Dark `#0A0A0A`/`#121212`, phosphor text `#EAEAEA`, same single red, Terminal
76
+ Green `#4AF626` reserved for exactly ONE element, mono type, ASCII framing
77
+ (`[ SYSTEMS ]`), scanline via `repeating-linear-gradient`. Fits: dev/infra
78
+ products, dashboards with attitude. Mutually exclusive with #5 — pick one.
79
+ Killed by: glassmorphism, gradients, more than one green element.
80
+
81
+ ### 7. Terminal-Native Product
82
+ Dense data UI on dark 3-step surface scale (≈15/20/25% lightness), tabular
83
+ numerals, base-4 spacing, Compact density tier, restrained accent for state
84
+ only. Fits: consoles, analytics, power-user tools (product register). Motion:
85
+ 120–200ms, zero entrances. Killed by: marketing theatrics, spacious hero
86
+ sections.
87
+
88
+ ### 8. Cold Luxury
89
+ Silver-grey + chrome + smoke; thin display type with wide optical margins,
90
+ monochrome photography, hairline dividers. Fits: fashion, architecture,
91
+ high-end services. Killed by: warm beige drift, script fonts.
92
+
93
+ ### 9. Earthy Rotation (Forest / Black & Tan / Terracotta + Slate / Olive + Brick + Paper / Cobalt + Cream)
94
+ The rotation pool for premium-consumer briefs that must NOT collapse into
95
+ beige+brass: deep green + bone + amber; or black + tan; or terracotta +
96
+ slate; or olive + brick + paper; or cobalt + cream. Pick ONE family, carry it
97
+ with conviction (Committed strategy, below). Killed by: mixing two families,
98
+ gray-on-color text.
99
+
100
+ ### 10. Drenched Brand
101
+ The surface IS the color: one saturated brand color carries 60%+ of pixels
102
+ ("Klim orange" energy), type in near-black or paper-white, zero secondary
103
+ accent. Fits: bold brand surfaces, campaign pages, portfolios. Requires real
104
+ contrast discipline (APCA check on every pair). Killed by: timidity — a
105
+ drenched page with gray hedging reads broken.
106
+
107
+ ### 11. Kinetic Type / Display-Led
108
+ Golden-ratio scale (protocol § Type scale), type AS the imagery, macro
109
+ headlines, scroll-driven reveals (one orchestrated sequence). Fits: launches,
110
+ events, editorial features (brand register, MOTION dial ≥ 7). Killed by:
111
+ competing imagery, more than 2 type families.
112
+
113
+ ### 12. Playful Toy
114
+ Saturated pops on light canvas, chunky rounded geometry (one radius system:
115
+ all-soft 12–16px), springy micro-interactions (spring for position/scale),
116
+ illustrated spot assets. Fits: consumer onboarding, education, kids (with
117
+ a11y quiet-constraint override). Killed by: pastel wash without contrast,
118
+ bounce easing everywhere.
119
+
120
+ ## Color commitment axis (choose per option, name it in the rationale)
121
+
122
+ - **Restrained** — tinted neutrals + one accent ≤ 10% of pixels (product
123
+ register default).
124
+ - **Committed** — one saturated color carries 30–60% of the surface.
125
+ - **Full palette** — 3–4 named color roles, each with a job.
126
+ - **Drenched** — the surface is the color (direction #10).
127
+
128
+ Name a real-world reference before picking ("Stripe purple-on-white
129
+ restraint", "Klim #ff4500 drench") — **unnamed ambition becomes beige**.
130
+
131
+ ## Dark vs light — the scene sentence
132
+
133
+ Dark vs light is never a default. Before choosing, write one sentence of
134
+ physical scene: *who* uses this, *where*, under *what ambient light*, in
135
+ *what mood*. If the sentence doesn't force the answer, it is not concrete
136
+ enough yet — sharpen it, then decide.
137
+
138
+ ## Reflex-reject lists (greenfield defaults only)
139
+
140
+ ### The LILA rule (color)
141
+ The "AI purple / blue glow" aesthetic is refused as a default: no
142
+ violet-indigo gradients, no cyan-on-dark glow, none of the default-Tailwind
143
+ indigo accents (`anti-slop.md` § Absolute bans). Use neutral bases
144
+ (zinc/slate/stone, tinted toward brand hue) with ONE high-contrast accent
145
+ (emerald, electric blue, deep rose, burnt orange). Override: the brand
146
+ genuinely IS purple → embrace it with intent.
147
+
148
+ ### The premium-consumer beige ban (color)
149
+ For premium-consumer briefs (cookware, wellness, artisan, luxury, DTC home),
150
+ the default is warm beige/cream + brass/clay/oxblood + espresso text — banned
151
+ as a default, including the hex families `#f5f1ea #f7f5f1 #fbf8f1 #efeae0
152
+ #ece6db #faf7f1 #e8dfcb` (bg), `#b08947 #b6553a #9a2436 #9c6e2a #bc7c3a
153
+ #7d5621` (accent). Rotate through the Earthy Rotation (#9) or Cold Luxury
154
+ (#8) instead. Warmth is carried by accent + typography + imagery, not by the
155
+ body background. Related: the whole warm-neutral band (OKLCH L 0.84–0.97,
156
+ C < 0.06, hue 40–100) reads as cream/sand/paper regardless of token name —
157
+ token names like `--paper`, `--cream`, `--sand`, `--bone` are tells in
158
+ themselves. Editorial Luxury (#1) may opt into warm paper *deliberately* —
159
+ say so in the rationale and rotate next time.
160
+
161
+ ### Serif discipline (typography)
162
+ Serif is very discouraged as a default. "It feels creative/premium/editorial"
163
+ is NOT a reason — "creative brief = serif" is the single most-tested AI tell.
164
+ **Banned as defaults: Fraunces and Instrument Serif.** If a serif is
165
+ genuinely justified (rare), rotate from: PP Editorial New, GT Sectra, Tiempos
166
+ Headline, Recoleta, Cormorant Garamond, EB Garamond, Canela, Domaine Display,
167
+ Playfair Display (never twice in a row).
168
+
169
+ ### Font reflex-reject (typography)
170
+ Before locking a font, run the 4-step selection: (1) three concrete brand
171
+ words (not "modern/elegant" — "warm, mechanical, opinionated"); (2) list your
172
+ 3 reflex picks and reject them; (3) browse a real catalog thinking of the
173
+ brand as a physical object ("a museum caption", "a 1970s terminal manual");
174
+ (4) if the final pick equals the original reflex, start over. Reflex list to
175
+ reject as defaults: Inter · Roboto · Arial · system-ui (product register may
176
+ override: earned familiarity) · Space Grotesk · Space Mono · IBM Plex family
177
+ · DM Sans/Serif · Outfit · Plus Jakarta Sans · Instrument Sans/Serif ·
178
+ Fraunces · Newsreader · Lora · Crimson · Playfair · Cormorant · Syne.
179
+ Sans pools to rotate: Geist, Satoshi, Cabinet Grotesk, General Sans, Inter
180
+ Tight (as body under a distinctive display). Pairings that work: Geist +
181
+ Geist Mono · Satoshi + JetBrains Mono · Cabinet Grotesk + Inter Tight.
182
+
183
+ ### Aesthetic-lane rejects (composition)
184
+ Saturated whole-lane defaults to refuse at first reflex: the
185
+ **editorial-typographic** lane (italic display serif + small mono labels +
186
+ ruled three-column separators + monochrome restraint) and the
187
+ **SaaS-dark-glow** lane (dark hero, mesh gradient, glass cards). Both may be
188
+ *chosen* — after passing the second-order slop test (`anti-slop.md`).