agemon 0.1.0 → 6.0.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/README.md +732 -28
- package/assets/skills/architecture/agemon-architecture/LICENSE +21 -0
- package/assets/skills/architecture/agemon-architecture/NOTICE.md +9 -0
- package/assets/skills/architecture/agemon-architecture/SKILL.md +275 -0
- package/assets/skills/code-quality/agemon-clean-code/LICENSE +21 -0
- package/assets/skills/code-quality/agemon-clean-code/NOTICE.md +9 -0
- package/assets/skills/code-quality/agemon-clean-code/SKILL.md +78 -0
- package/assets/skills/code-quality/agemon-house-rules/SKILL.md +103 -0
- package/assets/skills/commit/agemon-commit/SKILL.md +87 -0
- package/assets/skills/design/agemon-design/LICENSE +21 -0
- package/assets/skills/design/agemon-design/NOTICE.md +9 -0
- package/assets/skills/design/agemon-design/SKILL.md +391 -0
- package/assets/skills/design/agemon-design/references/accessibility.md +182 -0
- package/assets/skills/design/agemon-design/references/agents.md +63 -0
- package/assets/skills/design/agemon-design/references/ai-chat.md +158 -0
- package/assets/skills/design/agemon-design/references/brief.md +186 -0
- package/assets/skills/design/agemon-design/references/color.md +216 -0
- package/assets/skills/design/agemon-design/references/components.md +91 -0
- package/assets/skills/design/agemon-design/references/copy.md +300 -0
- package/assets/skills/design/agemon-design/references/craft-intent.md +160 -0
- package/assets/skills/design/agemon-design/references/dashboard.md +131 -0
- package/assets/skills/design/agemon-design/references/dataviz.md +197 -0
- package/assets/skills/design/agemon-design/references/finish-bar.md +243 -0
- package/assets/skills/design/agemon-design/references/forms.md +192 -0
- package/assets/skills/design/agemon-design/references/heuristics.md +403 -0
- package/assets/skills/design/agemon-design/references/inspiration.md +287 -0
- package/assets/skills/design/agemon-design/references/layout.md +236 -0
- package/assets/skills/design/agemon-design/references/loops.md +155 -0
- package/assets/skills/design/agemon-design/references/metadata.md +98 -0
- package/assets/skills/design/agemon-design/references/modern-css.md +448 -0
- package/assets/skills/design/agemon-design/references/motion.md +434 -0
- package/assets/skills/design/agemon-design/references/personas.md +206 -0
- package/assets/skills/design/agemon-design/references/principles-catalog.md +299 -0
- package/assets/skills/design/agemon-design/references/recipe-auth.md +88 -0
- package/assets/skills/design/agemon-design/references/recipe-dashboard.md +130 -0
- package/assets/skills/design/agemon-design/references/recipe-landing.md +122 -0
- package/assets/skills/design/agemon-design/references/responsive.md +168 -0
- package/assets/skills/design/agemon-design/references/review.md +340 -0
- package/assets/skills/design/agemon-design/references/sound.md +150 -0
- package/assets/skills/design/agemon-design/references/spec.md +123 -0
- package/assets/skills/design/agemon-design/references/stack.md +522 -0
- package/assets/skills/design/agemon-design/references/state-design.md +188 -0
- package/assets/skills/design/agemon-design/references/themes.md +229 -0
- package/assets/skills/design/agemon-design/references/tokens.md +350 -0
- package/assets/skills/design/agemon-design/references/typography.md +246 -0
- package/assets/skills/design/agemon-design-dashboard/LICENSE +21 -0
- package/assets/skills/design/agemon-design-dashboard/NOTICE.md +9 -0
- package/assets/skills/design/agemon-design-dashboard/SKILL.md +113 -0
- package/assets/skills/design/agemon-design-editorial/LICENSE +21 -0
- package/assets/skills/design/agemon-design-editorial/NOTICE.md +9 -0
- package/assets/skills/design/agemon-design-editorial/SKILL.md +98 -0
- package/assets/skills/design/agemon-design-minimal/LICENSE +21 -0
- package/assets/skills/design/agemon-design-minimal/NOTICE.md +9 -0
- package/assets/skills/design/agemon-design-minimal/SKILL.md +97 -0
- package/assets/skills/geo-seo/geo/LICENSE +21 -0
- package/assets/skills/geo-seo/geo/NOTICE.md +18 -0
- package/assets/skills/geo-seo/geo/SKILL.md +145 -0
- package/assets/skills/geo-seo/geo-audit/LICENSE +21 -0
- package/assets/skills/geo-seo/geo-audit/NOTICE.md +17 -0
- package/assets/skills/geo-seo/geo-audit/SKILL.md +371 -0
- package/assets/skills/geo-seo/geo-audit/references/ai-visibility.md +233 -0
- package/assets/skills/geo-seo/geo-audit/references/content.md +329 -0
- package/assets/skills/geo-seo/geo-audit/references/platform-analysis.md +294 -0
- package/assets/skills/geo-seo/geo-audit/references/schema.md +383 -0
- package/assets/skills/geo-seo/geo-audit/references/technical.md +368 -0
- package/assets/skills/geo-seo/geo-brand-mentions/LICENSE +21 -0
- package/assets/skills/geo-seo/geo-brand-mentions/NOTICE.md +15 -0
- package/assets/skills/geo-seo/geo-brand-mentions/SKILL.md +459 -0
- package/assets/skills/geo-seo/geo-citability/LICENSE +21 -0
- package/assets/skills/geo-seo/geo-citability/NOTICE.md +14 -0
- package/assets/skills/geo-seo/geo-citability/SKILL.md +320 -0
- package/assets/skills/geo-seo/geo-content/LICENSE +21 -0
- package/assets/skills/geo-seo/geo-content/NOTICE.md +14 -0
- package/assets/skills/geo-seo/geo-content/SKILL.md +352 -0
- package/assets/skills/geo-seo/geo-crawlers/LICENSE +21 -0
- package/assets/skills/geo-seo/geo-crawlers/NOTICE.md +15 -0
- package/assets/skills/geo-seo/geo-crawlers/SKILL.md +388 -0
- package/assets/skills/geo-seo/geo-llmstxt/LICENSE +21 -0
- package/assets/skills/geo-seo/geo-llmstxt/NOTICE.md +14 -0
- package/assets/skills/geo-seo/geo-llmstxt/SKILL.md +433 -0
- package/assets/skills/geo-seo/geo-platform-optimizer/LICENSE +21 -0
- package/assets/skills/geo-seo/geo-platform-optimizer/NOTICE.md +14 -0
- package/assets/skills/geo-seo/geo-platform-optimizer/SKILL.md +282 -0
- package/assets/skills/geo-seo/geo-report/LICENSE +21 -0
- package/assets/skills/geo-seo/geo-report/NOTICE.md +14 -0
- package/assets/skills/geo-seo/geo-report/SKILL.md +406 -0
- package/assets/skills/geo-seo/geo-report-pdf/LICENSE +21 -0
- package/assets/skills/geo-seo/geo-report-pdf/NOTICE.md +20 -0
- package/assets/skills/geo-seo/geo-report-pdf/SKILL.md +153 -0
- package/assets/skills/geo-seo/geo-report-pdf/templates/geo-report-template.html +548 -0
- package/assets/skills/geo-seo/geo-schema/LICENSE +21 -0
- package/assets/skills/geo-seo/geo-schema/NOTICE.md +16 -0
- package/assets/skills/geo-seo/geo-schema/SKILL.md +396 -0
- package/assets/skills/geo-seo/geo-technical/LICENSE +21 -0
- package/assets/skills/geo-seo/geo-technical/NOTICE.md +15 -0
- package/assets/skills/geo-seo/geo-technical/SKILL.md +566 -0
- package/assets/skills/performance/agemon-performance/NOTICE.md +1 -0
- package/assets/skills/performance/agemon-performance/SKILL.md +76 -0
- package/assets/skills/security/agemon-security/LICENSE +21 -0
- package/assets/skills/security/agemon-security/NOTICE.md +8 -0
- package/assets/skills/security/agemon-security/SKILL.md +356 -0
- package/assets/skills/self-review/agemon-review-intake/LICENSE +21 -0
- package/assets/skills/self-review/agemon-review-intake/NOTICE.md +9 -0
- package/assets/skills/self-review/agemon-review-intake/SKILL.md +205 -0
- package/assets/skills/self-review/agemon-review-request/LICENSE +21 -0
- package/assets/skills/self-review/agemon-review-request/NOTICE.md +9 -0
- package/assets/skills/self-review/agemon-review-request/SKILL.md +104 -0
- package/assets/skills/self-review/agemon-review-request/code-reviewer.md +188 -0
- package/assets/skills/self-review/agemon-root-cause/LICENSE +21 -0
- package/assets/skills/self-review/agemon-root-cause/NOTICE.md +10 -0
- package/assets/skills/self-review/agemon-root-cause/SKILL.md +283 -0
- package/assets/skills/self-review/agemon-root-cause/condition-based-waiting-example.ts +158 -0
- package/assets/skills/self-review/agemon-root-cause/condition-based-waiting.md +115 -0
- package/assets/skills/self-review/agemon-root-cause/defense-in-depth.md +122 -0
- package/assets/skills/self-review/agemon-root-cause/find-polluter.sh +72 -0
- package/assets/skills/self-review/agemon-root-cause/root-cause-tracing.md +169 -0
- package/assets/skills/self-review/agemon-root-cause/test-academic.md +14 -0
- package/assets/skills/self-review/agemon-root-cause/test-pressure-1.md +58 -0
- package/assets/skills/self-review/agemon-root-cause/test-pressure-2.md +68 -0
- package/assets/skills/self-review/agemon-root-cause/test-pressure-3.md +69 -0
- package/assets/skills/self-review/agemon-verify-before-done/LICENSE +21 -0
- package/assets/skills/self-review/agemon-verify-before-done/NOTICE.md +9 -0
- package/assets/skills/self-review/agemon-verify-before-done/SKILL.md +120 -0
- package/assets/skills/team-lead/agemon-plan-rfc/SKILL.md +317 -0
- package/assets/skills/team-lead/prd-generator/SKILL.md +437 -0
- package/assets/skills/team-lead/skill-headofit-audit/SKILL.md +72 -0
- package/assets/skills/team-lead/skill-incident-rca/SKILL.md +66 -0
- package/assets/skills/team-lead/skill-meeting-lifecycle/SKILL.md +63 -0
- package/assets/skills/team-lead/skill-obsidian-vault-sync/SKILL.md +69 -0
- package/assets/skills/team-lead/skill-prd-decomposer/SKILL.md +71 -0
- package/assets/skills/team-lead/skill-sec-check/SKILL.md +70 -0
- package/assets/skills/team-lead/skill-task-extractor/SKILL.md +79 -0
- package/assets/skills/team-lead/skill-tech-spike/SKILL.md +57 -0
- package/assets/skills/team-lead/skill-techlead-reviewer/SKILL.md +81 -0
- package/assets/tools/code-review-graph-constraints.txt +1418 -0
- package/assets/tools/package-lock.json +111 -0
- package/assets/tools/package.json +6 -0
- package/dist/chunk-5LATHJYU.js +4026 -0
- package/dist/chunk-5LATHJYU.js.map +1 -0
- package/dist/fake-subprocess-2BETWZVZ.js +666 -0
- package/dist/fake-subprocess-2BETWZVZ.js.map +1 -0
- package/dist/index.js +21101 -1956
- package/dist/index.js.map +1 -1
- package/package.json +30 -17
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# State Design — Design the Unhappy Path First
|
|
2
|
+
|
|
3
|
+
Every interactive surface has more states than "it works." The happy path is the easy one. Idle, loading, empty, error, partial, conflict, and offline are where real UX lives — and where AI-generated UIs fall apart.
|
|
4
|
+
|
|
5
|
+
Design every state before writing any JSX. Stub the ones the knob level doesn't require — don't skip them.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## The State Lattice
|
|
10
|
+
|
|
11
|
+
Every component-that-touches-data has this set. For each, design the visual AND the copy before coding.
|
|
12
|
+
|
|
13
|
+
This table is the evaluation source for the `state-coverage` loop preset (see `../SKILL.md` → loops.md).
|
|
14
|
+
|
|
15
|
+
| State | What to design | Common mistake |
|
|
16
|
+
|-------|---------------|----------------|
|
|
17
|
+
| **Idle** | Default resting state. Primary action obvious. | Treating "empty form" as idle — it's actually Empty. |
|
|
18
|
+
| **Loading** | Skeleton matching final layout. Appears after 200ms. | Centered spinner on a blank screen (no layout match, no cue). |
|
|
19
|
+
| **Empty** | Explain why empty + CTA to fix it. | "No data" with no illustration, no explanation, no next step. |
|
|
20
|
+
| **Error** | Specific cause + one-click recovery + support ID. | "Something went wrong" with no detail and no retry. |
|
|
21
|
+
| **Partial** | Some data loaded, some failing. Show what succeeded. | Hide everything because one field failed — user sees blank. |
|
|
22
|
+
| **Success** | Positive feedback, brief, visual + textual. | Toast that vanishes in 1s; user misses it. |
|
|
23
|
+
| **Conflict** | Two actors edited. Show both, let user resolve. | Last write wins silently; prior user's work is gone. |
|
|
24
|
+
| **Offline** | Connection lost. Queue writes. Communicate. | Pretend everything is fine; fail on next sync. |
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Design the Unhappy Path First
|
|
29
|
+
|
|
30
|
+
Designing loading / empty / error states first produces a better happy path. When you start from "the list is empty and we need to onboard the user," the happy-path card has a job it has to fit into, not the other way around. When you start from "this API returns an error," your loading skeleton and retry copy are baked in, not bolted on.
|
|
31
|
+
|
|
32
|
+
Teams that design happy-first ship demos that crumble on real data. Teams that design unhappy-first ship products.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Loading States
|
|
37
|
+
|
|
38
|
+
**Skeleton rules:**
|
|
39
|
+
- Match the final layout — same grid, same rough box sizes. Skeletons that don't match cause cumulative layout shift (CLS) when real content arrives.
|
|
40
|
+
- Show after **200ms**, not immediately. A flash of skeleton for fast responses looks broken.
|
|
41
|
+
- Set an upper bound of **5s**. Past that, escalate to a progress indicator or a timeout message with a retry.
|
|
42
|
+
- Use a subtle pulse or shimmer — not a spinner on top of a skeleton. One signal is enough.
|
|
43
|
+
- Preserve stable layout for known elements (avatar, title) while skeletonizing variable ones (body, list).
|
|
44
|
+
|
|
45
|
+
**Button loading:**
|
|
46
|
+
- Keep the label; don't swap to just a spinner. Users lose context.
|
|
47
|
+
- Disable but don't hide — users click it trying to cancel.
|
|
48
|
+
- Spinner goes *inside* the button, not next to it.
|
|
49
|
+
|
|
50
|
+
**Navigation loading:**
|
|
51
|
+
- Optimistic route change — paint the new layout immediately; stream data into it.
|
|
52
|
+
- A progress bar at the top of the viewport is better than a blank screen.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Empty States
|
|
57
|
+
|
|
58
|
+
Empty states are the most skipped state and the most valuable. A first-time user sees an empty state before any happy path.
|
|
59
|
+
|
|
60
|
+
**Required:**
|
|
61
|
+
- Explain **why** it's empty — "You haven't created any projects yet" beats "No data"
|
|
62
|
+
- Offer **a next action** — a CTA to populate the state. Every empty state is a call to onboard.
|
|
63
|
+
- Visual or illustration — even a subtle icon. Prevents the "this page is broken" read.
|
|
64
|
+
- Secondary info if useful — "Projects help you organize your work. Learn more."
|
|
65
|
+
|
|
66
|
+
**Empty state types:**
|
|
67
|
+
- **First-run empty** (user just signed up) — onboarding. Heavy CTA.
|
|
68
|
+
- **Filtered empty** (user applied filters that match nothing) — "No results — try removing filters" with a clear-filters button.
|
|
69
|
+
- **Cleared empty** (user archived / deleted everything) — celebratory or contextual; may not need a CTA.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Error States
|
|
74
|
+
|
|
75
|
+
Specific beats generic. Actionable beats dead-end. Recoverable beats fatal.
|
|
76
|
+
|
|
77
|
+
**Field-level errors:**
|
|
78
|
+
- Inline, at the field. Not a toast, not a global banner.
|
|
79
|
+
- Describe the problem AND the fix — "Password must include a number" beats "Invalid password."
|
|
80
|
+
- Red is a signal, not the whole message. Pair color with icon and text.
|
|
81
|
+
- `aria-invalid` + `aria-describedby` so screen readers announce.
|
|
82
|
+
|
|
83
|
+
**Form-level errors:**
|
|
84
|
+
- Scroll to the first invalid field, focus it.
|
|
85
|
+
- Summary at the top is fine in addition to inline, not instead of.
|
|
86
|
+
|
|
87
|
+
**Server errors:**
|
|
88
|
+
- Specific cause if you know it ("File too large — max 10MB").
|
|
89
|
+
- Copy-paste support ID — `Error ID: xyz-123` — so the user can send it to support.
|
|
90
|
+
- One-click retry where possible.
|
|
91
|
+
- Never blame the user for network failures.
|
|
92
|
+
|
|
93
|
+
**Network errors:**
|
|
94
|
+
- Distinguish offline from 500 from 403. Different causes, different fixes.
|
|
95
|
+
- Keep the in-flight state — don't throw away the form the user just filled.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Conflict, Partial, and Offline States
|
|
100
|
+
|
|
101
|
+
These are the forgotten states. Designing them separates products from demos.
|
|
102
|
+
|
|
103
|
+
### Conflict
|
|
104
|
+
|
|
105
|
+
Two users edited the same resource at the same time. Someone's about to lose work if you don't handle this.
|
|
106
|
+
|
|
107
|
+
- Detect via version / etag / updated_at.
|
|
108
|
+
- Present both versions. Let the user pick or merge.
|
|
109
|
+
- Never silently overwrite. The "last write wins" pattern looks like a bug to the losing user.
|
|
110
|
+
- For high-frequency collaborative surfaces, consider CRDT or operational transform rather than explicit conflict UI.
|
|
111
|
+
|
|
112
|
+
### Partial
|
|
113
|
+
|
|
114
|
+
Some data loaded, some failed. Common with multi-source dashboards or parallel fetches.
|
|
115
|
+
|
|
116
|
+
- Show what succeeded.
|
|
117
|
+
- Mark what failed with a per-tile error state, not a page-level one.
|
|
118
|
+
- Let the user retry the failing piece without reloading the rest.
|
|
119
|
+
- Example: dashboard with 6 metrics, one metric API is down — render 5 metrics + one inline error tile with retry.
|
|
120
|
+
|
|
121
|
+
### Offline
|
|
122
|
+
|
|
123
|
+
Connection is gone. Anticipate this on mobile, field apps, travel, and flaky wifi.
|
|
124
|
+
|
|
125
|
+
- Detect with `navigator.onLine` + a heartbeat (more reliable).
|
|
126
|
+
- Communicate at the app shell: "You're offline — changes will sync when reconnected."
|
|
127
|
+
- Queue writes locally (IndexedDB, localStorage). Optimistic UI locally.
|
|
128
|
+
- Reconcile on reconnect: apply queued writes, handle conflicts, surface any rejections.
|
|
129
|
+
- Disable actions that *require* connectivity (payments) — explain why.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## State Machine Reference
|
|
134
|
+
|
|
135
|
+
Don't ship a state library for this. But think in state machines. Pseudocode:
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
states:
|
|
139
|
+
idle -> on FETCH -> loading
|
|
140
|
+
loading -> on SUCCESS(data=empty) -> empty
|
|
141
|
+
-> on SUCCESS(data) -> success
|
|
142
|
+
-> on SUCCESS(data=partial) -> partial
|
|
143
|
+
-> on ERROR(network) -> offline
|
|
144
|
+
-> on ERROR(server) -> error
|
|
145
|
+
-> on TIMEOUT -> error
|
|
146
|
+
empty -> on CREATE -> loading
|
|
147
|
+
error -> on RETRY -> loading
|
|
148
|
+
partial -> on RETRY -> loading (retains successful data)
|
|
149
|
+
offline -> on ONLINE -> loading (retries + drains queue)
|
|
150
|
+
success -> on EDIT -> loading (optimistic)
|
|
151
|
+
-> on CONFLICT -> conflict
|
|
152
|
+
conflict -> on RESOLVE -> loading
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
The mental model is the value. Use `useReducer`, XState, Zustand slices, or plain discriminated unions — whatever the project uses. Just don't model states as disconnected booleans (`isLoading && !error && !data`) — that's how impossible states appear.
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Checklist
|
|
160
|
+
|
|
161
|
+
Before any interactive surface ships, every item on this list is designed (not necessarily implemented — design can be "stubbed as an empty component"):
|
|
162
|
+
|
|
163
|
+
- [ ] Idle state has a clear primary action
|
|
164
|
+
- [ ] Loading state matches final layout; appears after 200ms
|
|
165
|
+
- [ ] Empty state has explanation + CTA + visual
|
|
166
|
+
- [ ] Error state is specific, actionable, and recoverable
|
|
167
|
+
- [ ] Partial state handled if data has multiple sources
|
|
168
|
+
- [ ] Success state provides visual feedback (not color-only)
|
|
169
|
+
- [ ] Conflict state exists if the resource is collaborative
|
|
170
|
+
- [ ] Offline state exists if the user-journey is likely on mobile / flaky networks
|
|
171
|
+
|
|
172
|
+
**Knob gating (used by `/ui-craft:unhappy`):**
|
|
173
|
+
|
|
174
|
+
| CRAFT_LEVEL | Required states |
|
|
175
|
+
|-------------|----------------|
|
|
176
|
+
| ≤ 4 | idle, loading, error |
|
|
177
|
+
| 5-7 | idle, loading, empty, error, success |
|
|
178
|
+
| 8+ | all of the above plus partial, conflict, offline |
|
|
179
|
+
|
|
180
|
+
Missing a required state is a finding. Fix before declaring the happy path "done."
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## Cross-Refs
|
|
185
|
+
|
|
186
|
+
- `heuristics.md` — visibility of system status (Nielsen #1) is the principle behind the loading/partial states; use it to argue severity.
|
|
187
|
+
- `forms.md` — validation timing and error-state placement for form surfaces.
|
|
188
|
+
- `recipe-dashboard.md` — states are a build step (step 6), not polish; skeletons mirror final layout geometry.
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# Theme Presets
|
|
2
|
+
|
|
3
|
+
Four named, production-ready token stacks. Each is a complete primitive layer for the 3-layer contract in [tokens.md](tokens.md) — map these into your semantic tokens, don't reference them raw from components. Pick one when the project has no token system; if the project has tokens, those win ([SKILL.md](../SKILL.md) Discovery).
|
|
4
|
+
|
|
5
|
+
These are not "styles to sprinkle". A preset is all-or-nothing: mixing Porcelain's radii with Carbon's shadows produces incoherence that reads as generated.
|
|
6
|
+
|
|
7
|
+
**Contrast rule for all presets:** before shipping, verify text pairs with APCA — Lc ≥ 75 for body text, Lc ≥ 60 for large text (≥24px), Lc ≥ 45 for non-text UI. The pairs below are chosen to clear these; re-verify after any tweak.
|
|
8
|
+
|
|
9
|
+
**Default usage:** light mode unless the user asks for dark. Every preset defines both; both must be intentional ([color.md](color.md) dark-mode rules).
|
|
10
|
+
|
|
11
|
+
**Motion tokens:** each preset's `--motion-*` values intentionally override the canonical scale in [motion.md](motion.md) — pace is part of the aesthetic (Signal is fast, Porcelain unhurried). When a preset is active, its values win; the motion.md scale is the default when building without a preset. All values stay within the ≤400ms ceiling.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Graphite — minimal clean (default)
|
|
16
|
+
|
|
17
|
+
Cool neutrals, one deep accent, hairline borders, tight type. The safe choice for SaaS tools, admin surfaces, and the Command/Overview dashboard compositions. Disappears behind the data — which is the point.
|
|
18
|
+
|
|
19
|
+
```css
|
|
20
|
+
:root {
|
|
21
|
+
/* neutrals — cool, hue 255 */
|
|
22
|
+
--gray-0: oklch(99% 0.002 255); /* page */
|
|
23
|
+
--gray-1: oklch(97% 0.003 255); /* raised surface, sidebar tint */
|
|
24
|
+
--gray-2: oklch(93% 0.004 255); /* hairlines, dividers */
|
|
25
|
+
--gray-3: oklch(86% 0.005 255); /* disabled fills */
|
|
26
|
+
--gray-6: oklch(55% 0.012 255); /* secondary text */
|
|
27
|
+
--gray-7: oklch(42% 0.014 255); /* tertiary headings */
|
|
28
|
+
--gray-9: oklch(18% 0.012 255); /* primary text */
|
|
29
|
+
|
|
30
|
+
/* accent — deep indigo */
|
|
31
|
+
--accent: oklch(46% 0.17 275);
|
|
32
|
+
--accent-hover: oklch(41% 0.17 275);
|
|
33
|
+
--accent-tint: oklch(46% 0.17 275 / 0.08);
|
|
34
|
+
--on-accent: oklch(99% 0.002 255);
|
|
35
|
+
|
|
36
|
+
/* semantic */
|
|
37
|
+
--success: oklch(52% 0.13 155);
|
|
38
|
+
--warning: oklch(62% 0.14 75);
|
|
39
|
+
--danger: oklch(52% 0.18 25);
|
|
40
|
+
|
|
41
|
+
/* type — one grotesque sans for everything */
|
|
42
|
+
--font-body: var(--font-sans); /* Inter-class; system-ui acceptable */
|
|
43
|
+
--text-body: 14px / 1.5;
|
|
44
|
+
--text-display: 28px; /* metrics; 36px for hero */
|
|
45
|
+
--tracking-display: -0.02em;
|
|
46
|
+
|
|
47
|
+
/* shape + depth */
|
|
48
|
+
--radius-input: 0.375rem; --radius-card: 0.625rem; --radius-modal: 0.875rem;
|
|
49
|
+
--shadow-card: 0 0 0 1px oklch(0% 0 0 / 0.04), 0 1px 2px oklch(0% 0 0 / 0.05);
|
|
50
|
+
--shadow-overlay: 0 0 0 1px oklch(0% 0 0 / 0.05), 0 8px 24px oklch(0% 0 0 / 0.12);
|
|
51
|
+
|
|
52
|
+
/* motion */
|
|
53
|
+
--motion-fast: 120ms; --motion-base: 200ms; --motion-slow: 320ms;
|
|
54
|
+
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Dark mapping:** page `oklch(15% 0.012 255)`, raised `oklch(19% 0.012 255)`, hairline `oklch(26% 0.012 255)`, text `oklch(93% 0.004 255)`, accent lifts to `oklch(62% 0.15 275)`, shadows replaced by surface lightness steps.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Porcelain — soft modern
|
|
63
|
+
|
|
64
|
+
Warm neutrals, terracotta accent, generous radius, soft layered shadows. For products that want approachable over technical: consumer SaaS, onboarding-heavy tools, health/finance for humans. Pairs with VISUAL_DENSITY ≤ 5.
|
|
65
|
+
|
|
66
|
+
```css
|
|
67
|
+
:root {
|
|
68
|
+
--gray-0: oklch(98.5% 0.004 80);
|
|
69
|
+
--gray-1: oklch(96.5% 0.006 80);
|
|
70
|
+
--gray-2: oklch(92% 0.008 80);
|
|
71
|
+
--gray-3: oklch(85% 0.009 80);
|
|
72
|
+
--gray-6: oklch(54% 0.015 70);
|
|
73
|
+
--gray-9: oklch(22% 0.015 60);
|
|
74
|
+
|
|
75
|
+
--accent: oklch(60% 0.13 40);
|
|
76
|
+
--accent-hover: oklch(55% 0.13 40);
|
|
77
|
+
--accent-tint: oklch(60% 0.13 40 / 0.09);
|
|
78
|
+
--on-accent: oklch(98.5% 0.004 80);
|
|
79
|
+
|
|
80
|
+
--success: oklch(56% 0.12 150);
|
|
81
|
+
--warning: oklch(66% 0.13 80);
|
|
82
|
+
--danger: oklch(54% 0.17 28);
|
|
83
|
+
|
|
84
|
+
/* type — humanist sans body, optional rounded display */
|
|
85
|
+
--text-body: 15px / 1.55;
|
|
86
|
+
--text-display: 30px;
|
|
87
|
+
--tracking-display: -0.015em;
|
|
88
|
+
|
|
89
|
+
--radius-input: 0.625rem; --radius-card: 0.875rem; --radius-modal: 1.25rem;
|
|
90
|
+
--shadow-card: 0 1px 2px oklch(30% 0.02 60 / 0.06), 0 4px 12px oklch(30% 0.02 60 / 0.06);
|
|
91
|
+
--shadow-overlay: 0 2px 4px oklch(30% 0.02 60 / 0.08), 0 16px 40px oklch(30% 0.02 60 / 0.14);
|
|
92
|
+
|
|
93
|
+
--motion-fast: 140ms; --motion-base: 220ms; --motion-slow: 360ms;
|
|
94
|
+
--ease-out: cubic-bezier(0.22, 1, 0.36, 1);
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Dark mapping:** keep the warm hue — page `oklch(17% 0.012 70)`, raised `oklch(21% 0.012 70)`; accent lifts to `oklch(70% 0.12 45)`. Warm dark is this preset's signature; switching to cool dark breaks it.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Carbon — dark premium
|
|
103
|
+
|
|
104
|
+
Dark-first. Deep cool neutrals, elevation by surface tint (not shadow), one restrained luminous accent. For developer tools, monitoring, pro audio/video — products used for hours in the dark. Light mode exists but dark is primary.
|
|
105
|
+
|
|
106
|
+
```css
|
|
107
|
+
:root { /* dark IS the root */
|
|
108
|
+
--surface-0: oklch(14% 0.012 260); /* page */
|
|
109
|
+
--surface-1: oklch(17.5% 0.012 260); /* card */
|
|
110
|
+
--surface-2: oklch(21% 0.012 260); /* raised: popover, hover */
|
|
111
|
+
--surface-3: oklch(25% 0.012 260); /* highest: modal */
|
|
112
|
+
--line: oklch(28% 0.012 260); /* hairlines */
|
|
113
|
+
--text-1: oklch(93% 0.005 260);
|
|
114
|
+
--text-2: oklch(70% 0.01 260);
|
|
115
|
+
--text-3: oklch(52% 0.012 260);
|
|
116
|
+
|
|
117
|
+
--accent: oklch(78% 0.12 170); /* luminous mint — reads as light, not paint */
|
|
118
|
+
--accent-hover: oklch(84% 0.12 170);
|
|
119
|
+
--accent-tint: oklch(78% 0.12 170 / 0.10);
|
|
120
|
+
--on-accent: oklch(8% 0.008 260); /* near-true black — the 14% surface tone fails Lc 60 here */
|
|
121
|
+
|
|
122
|
+
--success: oklch(74% 0.12 155);
|
|
123
|
+
--warning: oklch(78% 0.13 85);
|
|
124
|
+
--danger: oklch(68% 0.16 25);
|
|
125
|
+
|
|
126
|
+
--text-body: 14px / 1.5;
|
|
127
|
+
--text-display: 28px;
|
|
128
|
+
--tracking-display: -0.02em;
|
|
129
|
+
/* numbers and code in mono; tabular-nums everywhere */
|
|
130
|
+
|
|
131
|
+
--radius-input: 0.375rem; --radius-card: 0.625rem; --radius-modal: 0.875rem;
|
|
132
|
+
/* NO drop shadows — elevation = surface step + 1px line. Glow only on the
|
|
133
|
+
single primary CTA, subtle: 0 0 16px var(--accent-tint) */
|
|
134
|
+
|
|
135
|
+
--motion-fast: 120ms; --motion-base: 180ms; --motion-slow: 300ms;
|
|
136
|
+
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**Light mapping (secondary):** invert the surface ladder onto Graphite's neutrals; accent darkens to `oklch(50% 0.13 170)`. Don't ship light-Carbon as default — if light is the primary need, pick Graphite.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Signal — sharp geometric
|
|
145
|
+
|
|
146
|
+
High-contrast, near-mono neutrals, semantic color doing real work, minimal radius, zero decorative depth. For dense data products — the Analytics composition, trading-adjacent surfaces, ops consoles at VISUAL_DENSITY ≥ 8.
|
|
147
|
+
|
|
148
|
+
```css
|
|
149
|
+
:root {
|
|
150
|
+
--gray-0: oklch(100% 0 0);
|
|
151
|
+
--gray-1: oklch(97% 0 0);
|
|
152
|
+
--gray-2: oklch(91% 0 0);
|
|
153
|
+
--gray-6: oklch(50% 0 0);
|
|
154
|
+
--gray-9: oklch(12% 0 0);
|
|
155
|
+
|
|
156
|
+
--accent: oklch(40% 0.16 264); /* one decisive blue-violet — used ONLY for selection + primary action */
|
|
157
|
+
--accent-hover: oklch(34% 0.16 264);
|
|
158
|
+
--accent-tint: oklch(40% 0.16 264 / 0.08);
|
|
159
|
+
--on-accent: oklch(100% 0 0);
|
|
160
|
+
|
|
161
|
+
/* semantic carries the information load — held to dots, deltas-on-demand, alerts */
|
|
162
|
+
--success: oklch(50% 0.15 150);
|
|
163
|
+
--warning: oklch(60% 0.15 70);
|
|
164
|
+
--danger: oklch(50% 0.20 25);
|
|
165
|
+
|
|
166
|
+
/* type — body sans, ALL numerals mono */
|
|
167
|
+
--text-body: 13px / 1.45;
|
|
168
|
+
--font-data: var(--font-mono);
|
|
169
|
+
--text-display: 26px;
|
|
170
|
+
--tracking-display: -0.01em;
|
|
171
|
+
|
|
172
|
+
--radius-input: 0.125rem; --radius-card: 0.375rem; --radius-modal: 0.625rem;
|
|
173
|
+
--shadow-card: none; /* 1px hairline only */
|
|
174
|
+
--shadow-overlay: 0 0 0 1px oklch(0% 0 0 / 0.08), 0 6px 20px oklch(0% 0 0 / 0.10);
|
|
175
|
+
|
|
176
|
+
--motion-fast: 100ms; --motion-base: 160ms; --motion-slow: 240ms; /* speed IS the aesthetic */
|
|
177
|
+
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Dark mapping:** pure-neutral dark — page `oklch(13% 0 0)`, card `oklch(16.5% 0 0)`, hairline `oklch(25% 0 0)`; accent lifts to `oklch(70% 0.13 264)`; semantic hues lift ~20% lightness. The mono-numeral rule does not relax in dark.
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Choosing
|
|
186
|
+
|
|
187
|
+
| Signal in the brief | Preset |
|
|
188
|
+
|---|---|
|
|
189
|
+
| "clean", "professional", internal tool, no strong brand | **Graphite** |
|
|
190
|
+
| "friendly", "approachable", consumer-facing, onboarding matters | **Porcelain** |
|
|
191
|
+
| "developer tool", "pro", users live in it at night | **Carbon** |
|
|
192
|
+
| "dense", "fast", data is the product, power users | **Signal** |
|
|
193
|
+
|
|
194
|
+
Brand color exists? Replace `--accent` with the brand hue at the preset's lightness/chroma discipline — the preset survives an accent swap; it does not survive a radius or shadow swap.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Accent rotation (no brand yet)
|
|
199
|
+
|
|
200
|
+
When the brief has no brand color, **rotate one accent family per build** so outputs don't all land on indigo. Declare the choice in the Craft Read ([craft-intent.md](craft-intent.md) §6). Swap only `--accent`, `--accent-hover`, `--accent-tint`, and `--on-accent` on the chosen preset — keep neutrals, radii, and shadows intact.
|
|
201
|
+
|
|
202
|
+
| Family | Light `--accent` (OKLCH) | Best on preset | Avoid pairing with |
|
|
203
|
+
|---|---|---|---|
|
|
204
|
+
| **Indigo** | `oklch(46% 0.17 275)` | Graphite, Signal | — (default; rotate away often) |
|
|
205
|
+
| **Teal** | `oklch(48% 0.12 195)` | Graphite, Carbon | Porcelain terracotta clash |
|
|
206
|
+
| **Rose** | `oklch(52% 0.14 15)` | Porcelain, Graphite | Signal high-contrast grids |
|
|
207
|
+
| **Amber** | `oklch(58% 0.14 75)` | Porcelain, Graphite | Carbon mint accent |
|
|
208
|
+
| **Forest** | `oklch(46% 0.11 155)` | Porcelain, Graphite | Signal blue-violet default |
|
|
209
|
+
|
|
210
|
+
**Hover / tint discipline:** `--accent-hover` ≈ 5% darker on the same hue; `--accent-tint` ≈ 8–10% alpha of accent; `--on-accent` must clear APCA Lc ≥ 60 against the filled button.
|
|
211
|
+
|
|
212
|
+
**Dark mode:** lift accent lightness ~15–20% on dark surfaces (see each preset's dark mapping). Re-verify contrast after swap.
|
|
213
|
+
|
|
214
|
+
**Marketing vs product:** landings and portfolios may rotate accent **and** theme preset; dashboards and auth rotate accent only unless the user asks for a full re-skin.
|
|
215
|
+
|
|
216
|
+
## Premium palette families (artisan / luxury / wellness briefs)
|
|
217
|
+
|
|
218
|
+
"Premium" briefs converge on one palette — warm cream background, brass/clay accent, espresso text — until every generated artisan site is interchangeable. Unless the brief names those colors, rotate through distinct families (one per build, never the same family twice in a row):
|
|
219
|
+
|
|
220
|
+
| Family | Recipe | Reads as |
|
|
221
|
+
|---|---|---|
|
|
222
|
+
| **Cold luxury** | silver-grey neutrals + chrome + smoke dark | precision, engineering premium |
|
|
223
|
+
| **Forest** | deep green + bone + amber accent | outdoor heritage, built-to-last |
|
|
224
|
+
| **Black & tan** | true off-black + warm tan, hard contrast, no beige | leather-goods, deliberate |
|
|
225
|
+
| **Cobalt + cream** | one saturated blue against a single neutral | confident, modern craft |
|
|
226
|
+
| **Terracotta + slate** | warm rust against cool grey | earthy without the beige wash |
|
|
227
|
+
| **Mono + pop** | off-white + off-black + one bright accent | gallery, editorial-modern |
|
|
228
|
+
|
|
229
|
+
Warmth can come from typography, imagery, and copy — it doesn't have to live in the background color. Verify AA contrast after picking; dark-mode mapping per the preset rules above.
|