design-protocol 1.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.
Files changed (72) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +225 -0
  3. package/agents/dp-researcher.md +239 -0
  4. package/agents/dp-verifier.md +207 -0
  5. package/bin/install.js +464 -0
  6. package/commands/dp-back.md +221 -0
  7. package/commands/dp-discuss.md +257 -0
  8. package/commands/dp-execute.md +513 -0
  9. package/commands/dp-journey.md +85 -0
  10. package/commands/dp-progress.md +178 -0
  11. package/commands/dp-roadmap.md +83 -0
  12. package/commands/dp-skip.md +186 -0
  13. package/commands/dp-start.md +510 -0
  14. package/commands/dp-storytell.md +94 -0
  15. package/commands/dp-verify.md +207 -0
  16. package/package.json +59 -0
  17. package/skills/dp-color/SKILL.md +214 -0
  18. package/skills/dp-color/export_tokens.py +297 -0
  19. package/skills/dp-color/references/apca-contrast.md +87 -0
  20. package/skills/dp-color/references/hue-emotions.md +109 -0
  21. package/skills/dp-color/references/oklch-gamut.md +79 -0
  22. package/skills/dp-color/references/pitfalls.md +171 -0
  23. package/skills/dp-color/references/scale-patterns.md +206 -0
  24. package/skills/dp-color/references/tool-workflows.md +200 -0
  25. package/skills/dp-discovery/SKILL.md +480 -0
  26. package/skills/dp-eng_review/SKILL.md +471 -0
  27. package/skills/dp-eng_review/references/code-review-checklist.md +385 -0
  28. package/skills/dp-eng_review/references/react-patterns.md +512 -0
  29. package/skills/dp-eng_review/references/shadcn-patterns.md +510 -0
  30. package/skills/dp-eng_review/references/tailwind-conventions.md +351 -0
  31. package/skills/dp-journey/SKILL.md +682 -0
  32. package/skills/dp-journey/references/journey-types.md +97 -0
  33. package/skills/dp-journey/references/map-structures.md +177 -0
  34. package/skills/dp-journey/references/omnichannel-patterns.md +208 -0
  35. package/skills/dp-journey/references/research-methods.md +125 -0
  36. package/skills/dp-prd/SKILL.md +201 -0
  37. package/skills/dp-prd/references/claude-code-spec.md +107 -0
  38. package/skills/dp-prd/references/interview-questions.md +158 -0
  39. package/skills/dp-prd/references/section-templates.md +231 -0
  40. package/skills/dp-research/SKILL.md +540 -0
  41. package/skills/dp-research/references/facilitation-guide.md +291 -0
  42. package/skills/dp-research/references/interview-guide-template.md +190 -0
  43. package/skills/dp-research/references/method-selection.md +195 -0
  44. package/skills/dp-research/references/question-writing.md +244 -0
  45. package/skills/dp-research/references/research-report-template.md +363 -0
  46. package/skills/dp-research/references/synthesis-methods.md +289 -0
  47. package/skills/dp-research/references/usability-test-template.md +260 -0
  48. package/skills/dp-roadmap/SKILL.md +648 -0
  49. package/skills/dp-roadmap/references/prioritization-frameworks.md +312 -0
  50. package/skills/dp-roadmap/references/roadmap-structures.md +179 -0
  51. package/skills/dp-roadmap/references/roadmap-workshops.md +264 -0
  52. package/skills/dp-roadmap/references/theme-development.md +168 -0
  53. package/skills/dp-storytell/SKILL.md +645 -0
  54. package/skills/dp-storytell/references/audience-playbooks.md +260 -0
  55. package/skills/dp-storytell/references/content-type-templates.md +310 -0
  56. package/skills/dp-storytell/references/delivery-tactics.md +228 -0
  57. package/skills/dp-storytell/references/narrative-frameworks.md +259 -0
  58. package/skills/dp-ui/SKILL.md +503 -0
  59. package/skills/dp-ui/references/b2b-enterprise-patterns.md +319 -0
  60. package/skills/dp-ui/references/data-visualization.md +304 -0
  61. package/skills/dp-ui/references/visual-design-principles.md +237 -0
  62. package/skills/dp-ux/SKILL.md +414 -0
  63. package/skills/dp-ux/references/accessibility-checklist.md +128 -0
  64. package/skills/dp-ux/references/product-excellence.md +149 -0
  65. package/skills/dp-ux/references/usability-principles.md +140 -0
  66. package/skills/dp-ux/references/ux-patterns.md +221 -0
  67. package/templates/config.json +55 -0
  68. package/templates/context.md +96 -0
  69. package/templates/project.md +83 -0
  70. package/templates/requirements.md +137 -0
  71. package/templates/roadmap.md +168 -0
  72. package/templates/state.md +107 -0
@@ -0,0 +1,171 @@
1
+ # Common OKLCH Pitfalls
2
+
3
+ Mistakes that even experienced designers make when working with OKLCH. Consult this when
4
+ generating palettes to avoid known traps.
5
+
6
+ ## 1. Chroma Clipping (The Silent Destroyer)
7
+
8
+ **Problem:** You set `oklch(0.65 0.25 185)` — a vibrant teal. But sRGB max chroma at H=185°
9
+ is ~0.13. The browser silently clamps it, shifting both the hue and lightness in
10
+ unpredictable ways. Your carefully tuned color is now something else entirely.
11
+
12
+ **Symptoms:**
13
+ - Color looks different than expected
14
+ - Two "different" OKLCH values render as the same hex
15
+ - Hue appears shifted (common with greens/teals)
16
+ - Lightness appears wrong
17
+
18
+ **Fix:** Always check against the gamut ceiling for the target hue (see `oklch-gamut.md`).
19
+ When in doubt, reduce chroma by 10–15% from what you think the limit is.
20
+
21
+ **CSS mitigation:**
22
+ ```css
23
+ /* Let the browser do smart gamut mapping */
24
+ color: oklch(0.65 0.25 185); /* Browser clamps — unpredictable */
25
+
26
+ /* Better: explicitly target the gamut */
27
+ color: color(display-p3 0.2 0.6 0.55); /* P3-safe equivalent */
28
+ ```
29
+
30
+ ## 2. Gray Hue Shift (The Phantom Color)
31
+
32
+ **Problem:** You create a "neutral gray" with `oklch(0.50 0.003 260)`. At C=0.003, you'd
33
+ expect it to look gray. But because the chroma isn't exactly 0, it carries a visible blue
34
+ tint — especially noticeable on calibrated displays and in large surface areas.
35
+
36
+ **Symptoms:**
37
+ - "Gray" surfaces have a color cast
38
+ - Different "grays" at different hues don't match
39
+ - Neutral UI elements look tinted
40
+
41
+ **Fix:** For true neutrals, use `C = 0` (achromatic). For intentionally tinted neutrals
42
+ (which are great for design systems — see the test artifact's approach), use `C = 0.01–0.02`
43
+ and be deliberate about it. The danger zone is `C = 0.002–0.008` — too much color to be
44
+ gray, too little to read as intentional.
45
+
46
+ **Rule of thumb:**
47
+ - `C = 0` → True gray (no hue influence)
48
+ - `C = 0.01–0.02` → Subtly tinted neutral (deliberate warmth/coolness)
49
+ - `C = 0.003–0.008` → Danger zone (looks like a mistake)
50
+ - `C ≥ 0.03` → Clearly colored
51
+
52
+ ## 3. Lightness ≠ Luminance (The WCAG Trap)
53
+
54
+ **Problem:** You ensure a OKLCH lightness difference of 0.45 between text and background,
55
+ assuming it passes WCAG AA. But WCAG uses relative luminance (derived from linear RGB),
56
+ not perceptual lightness. High-chroma colors can have the same OKLCH L but different
57
+ WCAG luminance values.
58
+
59
+ **Symptoms:**
60
+ - Palette passes your ΔL check but fails a WCAG contrast checker
61
+ - Saturated colors unexpectedly fail contrast
62
+ - Blues appear to pass more easily than yellows at the same ΔL
63
+
64
+ **Fix:** Use OKLCH ΔL as a first approximation (see `apca-contrast.md` for the heuristic),
65
+ but always validate with a proper WCAG calculator for production. The correlation breaks
66
+ down most at high chroma.
67
+
68
+ ## 4. Hue Discontinuity at 360°/0°
69
+
70
+ **Problem:** You're interpolating between H=350° (pink) and H=10° (red). Naively
71
+ interpolating gives you H=180° (teal) instead of H=0° (the short path through red).
72
+
73
+ **Symptoms:**
74
+ - Color transitions pass through unexpected hues
75
+ - Gradient goes "the long way around" the hue wheel
76
+ - Animated color transitions produce rainbow flashes
77
+
78
+ **Fix:** When interpolating hue, always take the shortest path around the wheel:
79
+ ```javascript
80
+ function shortestHuePath(h1, h2, t) {
81
+ let diff = h2 - h1;
82
+ if (diff > 180) diff -= 360;
83
+ if (diff < -180) diff += 360;
84
+ return ((h1 + diff * t) % 360 + 360) % 360;
85
+ }
86
+ ```
87
+
88
+ In CSS, `color-mix(in oklch, ...)` handles this automatically with `shorter hue` (the default).
89
+
90
+ ## 5. Non-Uniform Chroma Across a Ramp
91
+
92
+ **Problem:** You use the same chroma value (say C=0.15) across all lightness steps in a
93
+ ramp. The result: mid-tones look vivid, light tints look washed out, dark shades look
94
+ oversaturated and may clip gamut.
95
+
96
+ **Symptoms:**
97
+ - Light steps (50, 100) look barely tinted
98
+ - Dark steps (800, 900) look muddy or have hue shift
99
+ - The ramp doesn't feel "smooth"
100
+
101
+ **Fix:** Use a bell-curve chroma distribution that peaks at mid-lightness. See
102
+ `scale-patterns.md` for the recommended multiplier curves. This mirrors the natural
103
+ shape of the sRGB gamut envelope.
104
+
105
+ ## 6. Assuming P3 Is Always Better
106
+
107
+ **Problem:** You add P3-enhanced values everywhere, pushing chroma higher for all colors.
108
+ But for blues and magentas, the sRGB and P3 gamuts are very similar. You're adding
109
+ complexity (extra CSS) for negligible visual difference.
110
+
111
+ **Symptoms:**
112
+ - P3 values barely differ from sRGB values for some hues
113
+ - Extra code for no visible benefit
114
+ - Testing burden increases
115
+
116
+ **Fix:** Only include P3 overrides where the gain is meaningful (>15% chroma increase).
117
+ The biggest wins are in greens (H≈145°, +41%), teals (H≈175°, +46%), and cyans (H≈200°, +38%).
118
+ Blues and magentas gain less than 30% — often not worth the complexity.
119
+
120
+ ## 7. Dark Mode by Inversion
121
+
122
+ **Problem:** You create dark mode by simply swapping your 50 with 900, 100 with 800, etc.
123
+ This produces:
124
+ - Text that's too bright (original backgrounds were very light)
125
+ - Surfaces that are too dark (original text was very dark)
126
+ - Chroma that vibrates on dark backgrounds
127
+
128
+ **Symptoms:**
129
+ - Eye strain on dark mode
130
+ - Colors feel "electric" or harsh
131
+ - Contrast ratios are technically fine but readability suffers
132
+
133
+ **Fix:** Don't invert — remap. See the dark mode rules in SKILL.md directive 7. Key moves:
134
+ - Surfaces: L ≈ 0.15–0.20 (not the 0.04 you'd get from inverting step 950)
135
+ - Text: L ≈ 0.85–0.92 (not the 0.96 you'd get from inverting step 50)
136
+ - Chroma: reduce 15–25% across the board
137
+ - Test with real UI components, not just swatch grids
138
+
139
+ ## 8. Over-Rotating Hue Across Steps
140
+
141
+ **Problem:** You add hue rotation to make the ramp feel more natural (warm lights, cool darks).
142
+ But rotating more than ~20° total causes the ramp to lose its identity. A "blue" ramp starts
143
+ looking purple in the darks and green in the lights.
144
+
145
+ **Symptoms:**
146
+ - Dark steps don't feel like they belong to the same color
147
+ - Users describe the color inconsistently ("is this blue or purple?")
148
+ - Adjacent ramps start overlapping in hue
149
+
150
+ **Fix:** Keep total hue rotation under 15–20°. A rotation of 2–3° per step is usually enough
151
+ to create natural shadow depth without losing identity.
152
+
153
+ ## 9. Ignoring Simultaneous Contrast
154
+
155
+ **Problem:** You test your green "success" color on a white background and it looks perfect.
156
+ Then a user places it next to your red "error" color and the green shifts dramatically —
157
+ it looks more yellow.
158
+
159
+ **Symptoms:**
160
+ - Colors look "wrong" in certain UI contexts
161
+ - Side-by-side status colors shift unexpectedly
162
+ - The same color looks different on different pages
163
+
164
+ **Fix:** This is Albers' core lesson. Always test colors in context — next to the other
165
+ colors they'll actually appear beside. Particularly test:
166
+ - Success next to Error (complementary clash)
167
+ - Primary next to Neutral (chroma amplification)
168
+ - Warning next to any high-chroma neighbor
169
+
170
+ When in doubt, increase the spatial separation (more padding, dividers) or reduce chroma
171
+ on one of the neighbors.
@@ -0,0 +1,206 @@
1
+ # Color Scale Patterns Reference
2
+
3
+ ## Standard Scale Steps
4
+
5
+ Design systems typically use named stops from 25 (lightest) to 900 (darkest). The most
6
+ common configurations:
7
+
8
+ ### 13-Step Scale (Comprehensive)
9
+
10
+ `25, 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950, 975`
11
+
12
+ Best for: Large design systems with nuanced surface/state needs.
13
+
14
+ ### 11-Step Scale (Standard)
15
+
16
+ `50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950`
17
+
18
+ Best for: Most production design systems. Matches Tailwind's structure.
19
+
20
+ ### 9-Step Scale (Compact)
21
+
22
+ `100, 200, 300, 400, 500, 600, 700, 800, 900`
23
+
24
+ Best for: Simpler systems, single-brand palettes.
25
+
26
+ ## Lightness Mapping
27
+
28
+ The core of a good ramp is the lightness curve. Here are proven patterns in OKLCH:
29
+
30
+ ### Linear Lightness (Even Steps)
31
+
32
+ ```
33
+ Step → L (OKLCH)
34
+ 25 → 0.97
35
+ 50 → 0.95
36
+ 100 → 0.90
37
+ 200 → 0.82
38
+ 300 → 0.74
39
+ 400 → 0.66
40
+ 500 → 0.58
41
+ 600 → 0.50
42
+ 700 → 0.42
43
+ 800 → 0.34
44
+ 900 → 0.26
45
+ 950 → 0.20
46
+ 975 → 0.15
47
+ ```
48
+
49
+ **Pros:** Truly perceptually uniform in OKLCH. Each step feels equal.
50
+ **Cons:** Mid-range (400–600) can feel compressed visually in UI context.
51
+
52
+ ### Eased Lightness (Tailwind-style)
53
+
54
+ ```
55
+ Step → L (OKLCH)
56
+ 25 → 0.98
57
+ 50 → 0.96
58
+ 100 → 0.93
59
+ 200 → 0.87
60
+ 300 → 0.79
61
+ 400 → 0.70
62
+ 500 → 0.60
63
+ 600 → 0.50
64
+ 700 → 0.40
65
+ 800 → 0.32
66
+ 900 → 0.25
67
+ 950 → 0.18
68
+ 975 → 0.13
69
+ ```
70
+
71
+ **Pros:** More space in the light end (useful for backgrounds/surfaces) and dark end (text).
72
+ **Cons:** Mid-tones are slightly compressed. Matches user expectations from Tailwind.
73
+
74
+ ### Contrast-Anchored (Leonardo-style)
75
+
76
+ Instead of defining lightness directly, anchor certain stops to contrast targets:
77
+
78
+ ```
79
+ Step 50 → WCAG ≥ 1.1:1 against white (barely tinted)
80
+ Step 100 → WCAG ≥ 1.3:1 against white (light surface)
81
+ Step 300 → WCAG ≥ 2:1 against white (decorative)
82
+ Step 500 → WCAG ≥ 4.5:1 against white (AA text on white)
83
+ Step 600 → APCA |Lc| ≥ 60 on white (APCA large text)
84
+ Step 700 → WCAG ≥ 7:1 against white (AAA text on white)
85
+ Step 900 → WCAG ≥ 12:1 against white (high contrast text)
86
+ ```
87
+
88
+ **Pros:** Guarantees accessibility at named stops. Easy to document: "use 500+ on white."
89
+ **Cons:** Lightness spacing is uneven — driven by contrast math, not perception.
90
+
91
+ ## Chroma Curves
92
+
93
+ Chroma should not stay constant across a ramp. Two patterns:
94
+
95
+ ### Bell Curve (Recommended)
96
+
97
+ Chroma peaks at mid-lightness (~500) and tapers at both extremes.
98
+
99
+ ```
100
+ Step → C multiplier (of max hue chroma)
101
+ 25 → 0.15
102
+ 50 → 0.20
103
+ 100 → 0.30
104
+ 200 → 0.50
105
+ 300 → 0.70
106
+ 400 → 0.85
107
+ 500 → 1.00 (peak)
108
+ 600 → 0.90
109
+ 700 → 0.75
110
+ 800 → 0.55
111
+ 900 → 0.35
112
+ 950 → 0.25
113
+ 975 → 0.18
114
+ ```
115
+
116
+ This mirrors the sRGB gamut envelope naturally. See `oklch-gamut.md` for why.
117
+
118
+ ### Front-Loaded (Vibrant Lights)
119
+
120
+ Chroma peaks earlier (~300–400). Creates vivid light tints, muted darks.
121
+
122
+ ```
123
+ Step → C multiplier
124
+ 25 → 0.25
125
+ 50 → 0.40
126
+ 100 → 0.60
127
+ 200 → 0.80
128
+ 300 → 0.95
129
+ 400 → 1.00 (peak)
130
+ 500 → 0.85
131
+ 600 → 0.65
132
+ 700 → 0.50
133
+ 800 → 0.35
134
+ 900 → 0.25
135
+ ```
136
+
137
+ Useful for palettes where light surfaces need to carry brand color strongly.
138
+
139
+ ## Hue Rotation
140
+
141
+ In OKLCH, hue can shift slightly across a ramp to create more natural-feeling scales:
142
+
143
+ - **Warm shift:** Rotate hue +5–15° toward yellow/orange at lighter steps
144
+ - **Cool shift:** Rotate hue -5–10° toward blue at darker steps
145
+ - **Natural shadow:** Dark shades often look more natural slightly cooler (mimics real-world shadow)
146
+
147
+ Example for a blue palette (H = 265):
148
+ ```
149
+ Step 50 → H = 260 (slightly greener / lighter feel)
150
+ Step 500 → H = 265 (anchor)
151
+ Step 900 → H = 272 (slightly violet / deeper)
152
+ ```
153
+
154
+ Keep total rotation under 20° to maintain color identity.
155
+
156
+ ## Multi-Color System Layout
157
+
158
+ For a full design system with 12+ semantic colors:
159
+
160
+ | Color Role | Example Hues (H) | Notes |
161
+ |------------|-------------------|-------|
162
+ | Primary | Brand-dependent | Anchor color |
163
+ | Secondary | Primary ± 30–60° | Analogous harmony |
164
+ | Accent | Primary ± 150–180° | Complementary pop |
165
+ | Success | 145–155 | Green family |
166
+ | Warning | 80–95 | Yellow/amber family |
167
+ | Error/Danger | 25–35 | Red/orange family |
168
+ | Info | 230–260 | Blue family |
169
+ | Neutral | 0 chroma (or C ≤ 0.02) | True gray or tinted neutral |
170
+ | Neutral (tinted) | Primary hue, C = 0.01–0.03 | Warm/cool neutral |
171
+
172
+ Each of these gets the full step ramp (25–900).
173
+
174
+ ## CSS Custom Properties Pattern
175
+
176
+ ```css
177
+ :root {
178
+ /* Primary blue — 11 steps */
179
+ --primary-50: oklch(0.96 0.03 265);
180
+ --primary-100: oklch(0.93 0.05 265);
181
+ --primary-200: oklch(0.87 0.09 264);
182
+ --primary-300: oklch(0.79 0.12 264);
183
+ --primary-400: oklch(0.70 0.15 265);
184
+ --primary-500: oklch(0.60 0.17 265);
185
+ --primary-600: oklch(0.50 0.15 266);
186
+ --primary-700: oklch(0.40 0.13 267);
187
+ --primary-800: oklch(0.32 0.09 268);
188
+ --primary-900: oklch(0.25 0.06 270);
189
+ --primary-950: oklch(0.18 0.04 272);
190
+ }
191
+ ```
192
+
193
+ ## JSON Token Format
194
+
195
+ ```json
196
+ {
197
+ "color": {
198
+ "primary": {
199
+ "50": { "value": "oklch(0.96 0.03 265)", "hex": "#e8eeff" },
200
+ "100": { "value": "oklch(0.93 0.05 265)", "hex": "#d1deff" },
201
+ "500": { "value": "oklch(0.60 0.17 265)", "hex": "#4466dd" },
202
+ "900": { "value": "oklch(0.25 0.06 270)", "hex": "#1a2244" }
203
+ }
204
+ }
205
+ }
206
+ ```
@@ -0,0 +1,200 @@
1
+ # Design Tool Workflows
2
+
3
+ Step-by-step workflows for integrating OKLCH palette work with the four major color
4
+ palette tools. Use this reference when the user mentions any of these tools or asks
5
+ how to validate/export palettes through external tooling.
6
+
7
+ ## Atmos (atmos.style)
8
+
9
+ **What it does:** Generates entire color systems from a few seed colors. Produces
10
+ scales with configurable steps, lightness curves, and chroma behavior. Underrated
11
+ tool — one of the few that thinks in terms of full systems rather than individual colors.
12
+
13
+ ### Workflow: Base Color → Full System
14
+
15
+ 1. **Open Atmos** and start a new palette
16
+ 2. **Add your seed color** as a HEX value (e.g., #1c2739)
17
+ 3. **Configure scale steps:**
18
+ - Set to 11 steps (50–950) or 13 steps (25–975) depending on system needs
19
+ - Atmos uses its own lightness distribution — compare against the eased curve
20
+ in `scale-patterns.md` and adjust if needed
21
+ 4. **Add semantic colors:** Use Atmos's "add color" to create Success, Warning, Error, etc.
22
+ - Tip: Set the hues manually based on your harmony strategy (see SKILL.md directive 8)
23
+ rather than accepting Atmos defaults
24
+ 5. **Review chroma behavior:** Atmos may push chroma higher than sRGB allows for some hues.
25
+ Cross-check against `oklch-gamut.md` chroma ceilings
26
+ 6. **Export:** Atmos exports CSS custom properties and JSON. The format may need light
27
+ transformation to match W3C design token spec — use `scripts/export_tokens.py` for that.
28
+
29
+ ### Strengths
30
+ - Thinks in full systems (multiple color roles at once)
31
+ - Good lightness distribution out of the box
32
+ - Quick iteration on seed colors
33
+
34
+ ### Limitations
35
+ - Doesn't explicitly show OKLCH values (uses its own internal model)
36
+ - No APCA contrast validation built in
37
+ - May produce out-of-gamut values without warning
38
+
39
+ ---
40
+
41
+ ## Huetone (huetone.ardov.me)
42
+
43
+ **What it does:** Purpose-built for OKLCH palette creation. Visualizes the OKLCH color
44
+ space directly, shows gamut boundaries, and validates contrast between steps. The most
45
+ OKLCH-native tool available.
46
+
47
+ ### Workflow: OKLCH Palette Validation
48
+
49
+ 1. **Open Huetone** and create a new palette
50
+ 2. **Set your hue angle** (e.g., H=260 for the navy primary)
51
+ 3. **Define lightness stops:**
52
+ - Enter L values for each step manually to match your target curve
53
+ - Huetone shows a lightness graph — verify it follows the eased pattern
54
+ from `scale-patterns.md`
55
+ 4. **Set chroma per step:**
56
+ - Huetone displays the sRGB gamut boundary as a shaded region
57
+ - If your chroma dot falls outside the shaded area, it's out of gamut
58
+ - Adjust chroma to stay inside the boundary
59
+ 5. **Check contrast pairs:**
60
+ - Huetone shows WCAG contrast ratios between any two steps
61
+ - Verify that step 500+ on white meets your AA/AAA target
62
+ - Verify dark mode pairings (step 100–200 text on step 900 surface)
63
+ 6. **Export:** Huetone exports OKLCH values directly. Copy into your palette JSON
64
+ and run through `scripts/export_tokens.py`
65
+
66
+ ### Strengths
67
+ - Native OKLCH visualization
68
+ - Real-time gamut boundary display
69
+ - Built-in contrast checking between steps
70
+ - Shareable palette URLs
71
+
72
+ ### Limitations
73
+ - One hue at a time (not a full system view)
74
+ - No dark mode preview
75
+ - Limited export formats
76
+ - Manual process for multi-color systems
77
+
78
+ ---
79
+
80
+ ## Leonardo (leonardocolor.io) by Adobe
81
+
82
+ **What it does:** Contrast-ratio-driven palette generation. You define target contrast
83
+ ratios and Leonardo computes the colors that achieve them. The "accessibility-first"
84
+ approach to palette building.
85
+
86
+ ### Workflow: Contrast-Anchored Palette
87
+
88
+ 1. **Open Leonardo** and create a new color scale
89
+ 2. **Set your key color** (the mid-tone anchor — typically your brand color)
90
+ 3. **Define contrast ratios** for each step against your background:
91
+ ```
92
+ Step 50 → 1.1:1 (barely tinted surface)
93
+ Step 100 → 1.3:1 (light surface)
94
+ Step 200 → 1.8:1 (decorative)
95
+ Step 300 → 2.5:1 (large non-text)
96
+ Step 400 → 3.0:1 (AA large text)
97
+ Step 500 → 4.5:1 (AA normal text)
98
+ Step 600 → 5.5:1 (comfortable reading)
99
+ Step 700 → 7.0:1 (AAA normal text)
100
+ Step 800 → 9.0:1 (high contrast)
101
+ Step 900 → 12.0:1 (maximum)
102
+ Step 950 → 15.0:1 (near-black)
103
+ ```
104
+ 4. **Choose the color space:** Select OKLCH (or LCH) as the interpolation space.
105
+ Leonardo supports multiple spaces — always use OKLCH for perceptual uniformity.
106
+ 5. **Adjust the lightness curve:** Leonardo auto-computes L values from contrast ratios.
107
+ The resulting curve will be non-linear (contrast-anchored pattern from `scale-patterns.md`).
108
+ Review whether the steps feel even visually.
109
+ 6. **Generate for multiple backgrounds:**
110
+ - White (#fff) for light mode
111
+ - Your dark surface (e.g., primary-900) for dark mode
112
+ - Leonardo recalculates all colors to hit the same contrast targets on each background
113
+ 7. **Export:** Leonardo exports CSS, JSON, and SVG palettes. The CSS export uses
114
+ the `color()` function — may need conversion to `oklch()` syntax.
115
+
116
+ ### Strengths
117
+ - Accessibility is the foundation, not an afterthought
118
+ - Multi-background support (light + dark mode from the same definition)
119
+ - Generates tokens tied to contrast targets, not arbitrary lightness
120
+ - Adobe-maintained, actively developed
121
+
122
+ ### Limitations
123
+ - Doesn't use OKLCH natively in its UI (uses CAM02/LCH internally)
124
+ - The contrast-driven approach produces uneven perceptual spacing
125
+ - Less intuitive for designers who think in hue/saturation terms
126
+ - Can produce surprising hue shifts at extreme contrast targets
127
+
128
+ ---
129
+
130
+ ## Colorbox (colorbox.io) by Lyft
131
+
132
+ **What it does:** Custom easing curves for palette generation. Lets you define
133
+ bezier curves for lightness, saturation, and hue independently — maximum control
134
+ over the shape of your ramp.
135
+
136
+ ### Workflow: Custom Curve Palette
137
+
138
+ 1. **Open Colorbox** and set the number of steps (11 recommended)
139
+ 2. **Set your anchor color:**
140
+ - Use the color picker or paste your HEX
141
+ - Position it at the step where you want it to anchor (usually 500 or 600)
142
+ 3. **Configure the Lightness curve:**
143
+ - Colorbox provides bezier curve handles
144
+ - For the eased pattern: pull the light end slightly flatter (more space for surfaces)
145
+ and the dark end slightly flatter (more space for text shades)
146
+ - For linear: make the curve as straight as possible
147
+ 4. **Configure the Saturation curve:**
148
+ - Shape this as a bell curve peaking at mid-steps
149
+ - Pull the ends (light and dark) down to reduce chroma at extremes
150
+ - This naturally mirrors the sRGB gamut envelope
151
+ 5. **Configure the Hue curve:**
152
+ - For no rotation: flat line
153
+ - For natural shadow: slight upward curve (rotate toward cooler at dark end)
154
+ - Keep total rotation under 15–20°
155
+ 6. **Preview:** Colorbox renders the full ramp live. Check for:
156
+ - Smooth visual transitions (no sudden jumps)
157
+ - No gamut clipping (compare with `oklch-gamut.md`)
158
+ - The anchor color sitting at the right step
159
+ 7. **Export:** Colorbox exports HEX values. Convert to OKLCH using:
160
+ ```bash
161
+ # If you have the palette in JSON with hex values, the export script can help
162
+ # Or convert manually with a tool like oklch.com
163
+ ```
164
+
165
+ ### Strengths
166
+ - Maximum control over curve shape
167
+ - Visual bezier editor is intuitive for designers
168
+ - Good for understanding how curves affect perception
169
+ - Fast iteration
170
+
171
+ ### Limitations
172
+ - Works in HSL internally (not OKLCH) — perceptual uniformity not guaranteed
173
+ - No contrast validation built in
174
+ - Exports HEX only — requires post-conversion to OKLCH
175
+ - Gamut issues not surfaced (HSL doesn't have gamut boundaries)
176
+
177
+ ---
178
+
179
+ ## Tool Comparison Matrix
180
+
181
+ | Feature | Atmos | Huetone | Leonardo | Colorbox |
182
+ |---------|-------|---------|----------|----------|
183
+ | Native OKLCH | ✗ | ✓ | Partial | ✗ |
184
+ | Full system view | ✓ | ✗ | ✗ | ✗ |
185
+ | Gamut visualization | ✗ | ✓ | ✗ | ✗ |
186
+ | Contrast validation | ✗ | ✓ | ✓ (core) | ✗ |
187
+ | Dark mode support | ✗ | ✗ | ✓ | ✗ |
188
+ | Custom curves | ✗ | ✗ | ✗ | ✓ |
189
+ | Token export | CSS/JSON | Manual | CSS/JSON | HEX only |
190
+ | Best for | System overview | OKLCH precision | A11y-first builds | Curve experimentation |
191
+
192
+ ## Recommended Workflow
193
+
194
+ For production design systems, combine tools:
195
+
196
+ 1. **Start in Colorbox** — experiment with curves to find the right "feel"
197
+ 2. **Validate in Huetone** — check gamut boundaries and inter-step contrast in OKLCH
198
+ 3. **Anchor in Leonardo** — verify contrast targets are met on both light and dark surfaces
199
+ 4. **Review in Atmos** — see the full multi-color system together
200
+ 5. **Export with `scripts/export_tokens.py`** — generate production CSS, JSON, and Figma tokens