picasso-skill 2.4.0 → 2.6.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.
@@ -1,23 +1,10 @@
1
1
  # Color and Contrast Reference
2
2
 
3
- ## Table of Contents
4
- 1. Color Space and Manipulation
5
- 2. Palette Construction
6
- 3. Tinted Neutrals
7
- 4. Dark Mode
8
- 5. Accessibility
9
- 6. CSS Variables Pattern
10
- 7. Curated Color Palettes
11
- 8. Wide Gamut Colors (P3)
12
- 9. `light-dark()` CSS Function
13
- 10. `color-mix()` for Runtime Blending
14
- 11. Common Mistakes
15
-
16
3
  ---
17
4
 
18
- ## 1. Color Space and Manipulation
5
+ ## 1. Color Space
19
6
 
20
- Use OKLCH for perceptually uniform color. Unlike HSL, OKLCH ensures that colors at the same lightness value actually appear equally bright to the human eye.
7
+ Use OKLCH for perceptually uniform color. Unlike HSL, OKLCH ensures colors at the same lightness value actually appear equally bright.
21
8
 
22
9
  ```css
23
10
  /* OKLCH: lightness (0-1), chroma (0-0.4), hue (0-360) */
@@ -26,7 +13,7 @@ Use OKLCH for perceptually uniform color. Unlike HSL, OKLCH ensures that colors
26
13
  --accent-muted: oklch(0.75 0.08 25); /* same hue, much less chroma */
27
14
  ```
28
15
 
29
- For programmatic palette generation, adjust lightness for tints/shades, chroma for saturation, and hue for variation. OKLCH makes this predictable.
16
+ Adjust lightness for tints/shades, chroma for saturation, hue for variation.
30
17
 
31
18
  ---
32
19
 
@@ -38,35 +25,31 @@ For programmatic palette generation, adjust lightness for tints/shades, chroma f
38
25
  - 10% accent (CTAs, active states, highlights)
39
26
 
40
27
  ### Building a Palette
41
- 1. Start with the accent color (the brand or action color)
42
- 2. Derive a surface color: very low chroma version of the accent hue
28
+ 1. Start with the accent color (brand or action color)
29
+ 2. Derive surface color: very low chroma version of the accent hue
43
30
  3. Build neutral scale: tinted toward the accent hue (never pure gray)
44
- 4. Add a semantic layer: success (green family), warning (amber), error (red), info (blue)
45
- 5. Generate dark mode variants by inverting the lightness scale, not the colors
31
+ 4. Add semantic layer: success (green), warning (amber), error (red), info (blue)
32
+ 5. Generate dark mode by inverting the lightness scale, not the colors
46
33
 
47
34
  ### Token Structure
48
35
  ```css
49
36
  :root {
50
37
  /* Surfaces */
51
- --surface-0: oklch(0.99 0.005 80); /* page background */
52
- --surface-1: oklch(0.97 0.008 80); /* card background */
53
- --surface-2: oklch(0.94 0.01 80); /* elevated/hover surface */
54
- --surface-3: oklch(0.90 0.012 80); /* active/selected surface */
55
-
38
+ --surface-0: oklch(0.99 0.005 80); /* page bg */
39
+ --surface-1: oklch(0.97 0.008 80); /* card bg */
40
+ --surface-2: oklch(0.94 0.01 80); /* elevated/hover */
41
+ --surface-3: oklch(0.90 0.012 80); /* active/selected */
56
42
  /* Text */
57
43
  --text-primary: oklch(0.15 0.02 80);
58
44
  --text-secondary: oklch(0.40 0.02 80);
59
45
  --text-tertiary: oklch(0.55 0.015 80);
60
-
61
46
  /* Accent */
62
47
  --accent: oklch(0.55 0.25 30);
63
48
  --accent-hover: oklch(0.50 0.28 30);
64
49
  --accent-subtle: oklch(0.92 0.04 30);
65
-
66
50
  /* Borders */
67
51
  --border: oklch(0.88 0.01 80);
68
52
  --border-strong: oklch(0.78 0.015 80);
69
-
70
53
  /* Semantic */
71
54
  --success: oklch(0.55 0.18 145);
72
55
  --warning: oklch(0.65 0.18 70);
@@ -78,400 +61,150 @@ For programmatic palette generation, adjust lightness for tints/shades, chroma f
78
61
 
79
62
  ## 3. Tinted Neutrals
80
63
 
81
- Never use pure gray (#808080, rgb(128,128,128), etc.). Always tint neutrals toward the dominant hue of the palette. This creates warmth and cohesion.
64
+ Never use pure gray. Always tint neutrals toward the dominant hue.
82
65
 
83
- **Warm neutrals** (tinted toward amber/brown): suited for editorial, luxury, organic brands
84
- **Cool neutrals** (tinted toward blue/slate): suited for tech, data, professional tools
85
- **Neutral neutrals** (tinted toward the accent hue at very low chroma): the most versatile approach
66
+ - **Warm neutrals** (amber/brown): editorial, luxury, organic brands
67
+ - **Cool neutrals** (blue/slate): tech, data, professional tools
68
+ - **Neutral neutrals** (accent hue, very low chroma): most versatile
86
69
 
87
70
  ```css
88
- /* Instead of #333333 */
89
- --text-primary: oklch(0.25 0.015 260); /* cool-tinted dark */
90
-
91
- /* Instead of #f5f5f5 */
92
- --surface-bg: oklch(0.97 0.005 260); /* cool-tinted light */
71
+ --text-primary: oklch(0.25 0.015 260); /* cool-tinted dark, not #333 */
72
+ --surface-bg: oklch(0.97 0.005 260); /* cool-tinted light, not #f5f5f5 */
93
73
  ```
94
74
 
95
75
  ---
96
76
 
97
77
  ## 4. Dark Mode
98
78
 
99
- Dark mode is not "invert everything." Follow these rules:
79
+ Dark mode is not "invert everything." Rules:
100
80
 
101
- 1. Surface colors get darker but retain their hue tint
102
- 2. Text colors flip but never become pure white (use oklch lightness 0.93-0.97)
103
- 3. Accent colors often need a lightness bump (+0.05 to +0.10) to maintain contrast
104
- 4. Shadows become less visible on dark surfaces; use subtle inner glows or border effects instead
105
- 5. Elevation in dark mode goes lighter (higher surfaces are lighter), opposite of light mode
106
- 6. Images and illustrations may need reduced brightness/contrast (`filter: brightness(0.9)`)
107
-
108
- ```css
109
- [data-theme="dark"] {
110
- --surface-0: oklch(0.13 0.01 260);
111
- --surface-1: oklch(0.17 0.012 260);
112
- --surface-2: oklch(0.21 0.015 260);
113
- --text-primary: oklch(0.93 0.01 260);
114
- --text-secondary: oklch(0.70 0.01 260);
115
- --border: oklch(0.25 0.01 260);
116
- }
117
- ```
81
+ 1. Surface colors get darker but retain hue tint
82
+ 2. Text: never pure white (use oklch lightness 0.93-0.97)
83
+ 3. Accent colors need a lightness bump (+0.05 to +0.10) to maintain contrast
84
+ 4. Replace shadows with subtle inner glows or border effects
85
+ 5. Elevation goes lighter (higher surfaces = lighter), opposite of light mode
86
+ 6. Images may need `filter: brightness(0.9)`
118
87
 
119
88
  ---
120
89
 
121
90
  ## 5. Accessibility
122
91
 
123
92
  ### Contrast Requirements (WCAG 2.2)
124
- - Normal text (<24px or <18.66px bold): 4.5:1 minimum
125
- - Large text (>=24px or >=18.66px bold): 3:1 minimum
126
- - UI components and graphical objects: 3:1 minimum
127
- - Focus indicators: 3:1 against adjacent colors
93
+ - Normal text (<24px or <18.66px bold): **4.5:1** minimum
94
+ - Large text (>=24px or >=18.66px bold): **3:1** minimum
95
+ - UI components and graphical objects: **3:1** minimum
96
+ - Focus indicators: **3:1** against adjacent colors
128
97
 
129
- ### Testing
130
- Use OKLCH lightness difference as a quick heuristic: a difference of 0.40+ between text and background lightness values usually passes AA. For precise checking, use the APCA (Advanced Perceptual Contrast Algorithm) when possible, as it better represents human perception than WCAG 2.x contrast ratios.
98
+ ### Quick Heuristic
99
+ OKLCH lightness difference of 0.40+ between text and background usually passes AA. For precise checking, use APCA when possible.
131
100
 
132
101
  ### Color Blindness
133
- Never use color as the only way to convey information. Pair color with icons, patterns, or text labels. Test palettes with a deuteranopia/protanopia simulator.
102
+ Never use color as the only information channel. Pair with icons, patterns, or text labels. Test with deuteranopia/protanopia simulator.
134
103
 
135
104
  ---
136
105
 
137
106
  ## 6. CSS Variables Pattern
138
107
 
139
- Define all colors as CSS custom properties. Group by function, not by color name.
108
+ Define all colors as CSS custom properties. Group by function, not color name.
140
109
 
141
110
  ```css
142
111
  /* Good: semantic naming */
143
- --color-surface: ...;
144
- --color-text: ...;
145
- --color-accent: ...;
146
- --color-border: ...;
147
-
112
+ --color-surface: ...; --color-text: ...; --color-accent: ...;
148
113
  /* Bad: literal naming */
149
- --blue: ...;
150
- --dark-gray: ...;
151
- --light-blue: ...;
114
+ --blue: ...; --dark-gray: ...; --light-blue: ...;
152
115
  ```
153
116
 
154
- For component-level overrides:
155
- ```css
156
- .card {
157
- --card-bg: var(--surface-1);
158
- --card-border: var(--border);
159
- background: var(--card-bg);
160
- border: 1px solid var(--card-border);
161
- }
162
- .card.highlighted {
163
- --card-bg: var(--accent-subtle);
164
- --card-border: var(--accent);
165
- }
166
- ```
117
+ For component overrides, use local custom properties that reference global tokens.
167
118
 
168
119
  ---
169
120
 
170
121
  ## 7. Curated Color Palettes
171
122
 
172
- Ten tested OKLCH palettes ready to drop into any project. Each includes a complete token set. Copy the one that fits your domain, then adjust chroma and hue to taste.
123
+ Ten tested OKLCH palettes. Each includes surface, text, accent, border, and semantic tokens. Copy the one that fits your domain, adjust chroma and hue to taste.
173
124
 
174
- ### 7.1 Warm Terracotta
175
- **Vibe**: Earthy, grounded, artisanal. Good for lifestyle brands, wellness, real estate, organic products.
176
- ```css
177
- :root {
178
- --surface-0: oklch(0.98 0.008 55);
179
- --surface-1: oklch(0.95 0.012 55);
180
- --text-primary: oklch(0.18 0.025 55);
181
- --text-secondary: oklch(0.42 0.02 55);
182
- --accent: oklch(0.58 0.16 45);
183
- --accent-hover: oklch(0.52 0.18 45);
184
- --accent-subtle: oklch(0.93 0.04 45);
185
- --border: oklch(0.87 0.015 55);
186
- --success: oklch(0.55 0.16 155);
187
- --warning: oklch(0.68 0.16 75);
188
- --error: oklch(0.55 0.20 25);
189
- }
190
- ```
125
+ | # | Name | Vibe | Good For |
126
+ |---|------|------|----------|
127
+ | 1 | Warm Terracotta | Earthy, grounded | Lifestyle, wellness, real estate |
128
+ | 2 | Forest Green | Natural, trustworthy | Fintech, health, environmental |
129
+ | 3 | Amber Gold | Premium, confident | Finance, luxury SaaS, productivity |
130
+ | 4 | Coral Salmon | Warm, energetic | Social apps, creative tools, food |
131
+ | 5 | Deep Teal | Calm, authoritative | Health tech, enterprise, legal |
132
+ | 6 | Slate Blue | Professional, systematic | Project management, B2B SaaS |
133
+ | 7 | Burgundy | Sophisticated, editorial | Wine/food, publishing, fashion |
134
+ | 8 | Sage | Soft, restorative | Wellness, meditation, journaling |
135
+ | 9 | Charcoal + Orange | Bold, industrial | Dev tools, gaming, analytics |
136
+ | 10 | Monochrome B&W | Stark, typographic | Portfolios, photography, editorial |
191
137
 
192
- ### 7.2 Forest Green
193
- **Vibe**: Natural, sustainable, trustworthy. Good for fintech, health, environmental, agriculture.
138
+ ### Example: Warm Terracotta
194
139
  ```css
195
140
  :root {
196
- --surface-0: oklch(0.98 0.006 145);
197
- --surface-1: oklch(0.96 0.01 145);
198
- --text-primary: oklch(0.17 0.03 150);
199
- --text-secondary: oklch(0.40 0.02 150);
200
- --accent: oklch(0.52 0.14 155);
201
- --accent-hover: oklch(0.46 0.16 155);
202
- --accent-subtle: oklch(0.93 0.04 155);
203
- --border: oklch(0.88 0.012 145);
204
- --success: oklch(0.55 0.16 145);
205
- --warning: oklch(0.66 0.16 80);
206
- --error: oklch(0.55 0.20 25);
141
+ --surface-0: oklch(0.98 0.008 55); --surface-1: oklch(0.95 0.012 55);
142
+ --text-primary: oklch(0.18 0.025 55); --text-secondary: oklch(0.42 0.02 55);
143
+ --accent: oklch(0.58 0.16 45); --accent-hover: oklch(0.52 0.18 45);
144
+ --accent-subtle: oklch(0.93 0.04 45); --border: oklch(0.87 0.015 55);
145
+ --success: oklch(0.55 0.16 155); --warning: oklch(0.68 0.16 75); --error: oklch(0.55 0.20 25);
207
146
  }
208
147
  ```
209
148
 
210
- ### 7.3 Amber Gold
211
- **Vibe**: Premium, confident, optimistic. Good for finance, luxury SaaS, productivity tools.
212
- ```css
213
- :root {
214
- --surface-0: oklch(0.99 0.005 85);
215
- --surface-1: oklch(0.96 0.01 85);
216
- --text-primary: oklch(0.16 0.02 85);
217
- --text-secondary: oklch(0.40 0.018 85);
218
- --accent: oklch(0.68 0.18 75);
219
- --accent-hover: oklch(0.62 0.20 75);
220
- --accent-subtle: oklch(0.94 0.04 75);
221
- --border: oklch(0.88 0.012 85);
222
- --success: oklch(0.55 0.16 150);
223
- --warning: oklch(0.68 0.18 75);
224
- --error: oklch(0.55 0.20 28);
225
- }
226
- ```
227
-
228
- ### 7.4 Coral Salmon
229
- **Vibe**: Warm, energetic, approachable. Good for social apps, creative tools, food and hospitality.
230
- ```css
231
- :root {
232
- --surface-0: oklch(0.98 0.006 30);
233
- --surface-1: oklch(0.96 0.01 30);
234
- --text-primary: oklch(0.18 0.02 30);
235
- --text-secondary: oklch(0.42 0.018 30);
236
- --accent: oklch(0.65 0.20 25);
237
- --accent-hover: oklch(0.58 0.22 25);
238
- --accent-subtle: oklch(0.94 0.04 25);
239
- --border: oklch(0.88 0.012 30);
240
- --success: oklch(0.55 0.16 150);
241
- --warning: oklch(0.66 0.16 75);
242
- --error: oklch(0.52 0.22 20);
243
- }
244
- ```
245
-
246
- ### 7.5 Deep Teal
247
- **Vibe**: Calm, medical, authoritative. Good for health tech, enterprise SaaS, data platforms, legal.
248
- ```css
249
- :root {
250
- --surface-0: oklch(0.98 0.005 195);
251
- --surface-1: oklch(0.96 0.008 195);
252
- --text-primary: oklch(0.16 0.025 200);
253
- --text-secondary: oklch(0.40 0.02 200);
254
- --accent: oklch(0.52 0.12 195);
255
- --accent-hover: oklch(0.46 0.14 195);
256
- --accent-subtle: oklch(0.93 0.03 195);
257
- --border: oklch(0.88 0.01 195);
258
- --success: oklch(0.55 0.14 155);
259
- --warning: oklch(0.66 0.16 75);
260
- --error: oklch(0.55 0.20 25);
261
- }
262
- ```
263
-
264
- ### 7.6 Slate Blue
265
- **Vibe**: Professional, systematic, dependable. Good for project management, B2B SaaS, documentation.
266
- ```css
267
- :root {
268
- --surface-0: oklch(0.98 0.005 250);
269
- --surface-1: oklch(0.96 0.008 250);
270
- --text-primary: oklch(0.17 0.02 250);
271
- --text-secondary: oklch(0.42 0.018 250);
272
- --accent: oklch(0.55 0.14 250);
273
- --accent-hover: oklch(0.49 0.16 250);
274
- --accent-subtle: oklch(0.93 0.03 250);
275
- --border: oklch(0.88 0.01 250);
276
- --success: oklch(0.55 0.16 150);
277
- --warning: oklch(0.66 0.16 75);
278
- --error: oklch(0.55 0.20 25);
279
- }
280
- ```
281
-
282
- ### 7.7 Burgundy
283
- **Vibe**: Sophisticated, editorial, rich. Good for wine/food, publishing, luxury, fashion.
284
- ```css
285
- :root {
286
- --surface-0: oklch(0.98 0.006 10);
287
- --surface-1: oklch(0.96 0.01 10);
288
- --text-primary: oklch(0.16 0.025 10);
289
- --text-secondary: oklch(0.40 0.02 10);
290
- --accent: oklch(0.42 0.16 15);
291
- --accent-hover: oklch(0.36 0.18 15);
292
- --accent-subtle: oklch(0.93 0.04 15);
293
- --border: oklch(0.87 0.012 10);
294
- --success: oklch(0.55 0.16 150);
295
- --warning: oklch(0.66 0.16 75);
296
- --error: oklch(0.50 0.20 25);
297
- }
298
- ```
299
-
300
- ### 7.8 Sage
301
- **Vibe**: Soft, organic, restorative. Good for wellness, meditation, journaling, therapy platforms.
302
- ```css
303
- :root {
304
- --surface-0: oklch(0.98 0.006 130);
305
- --surface-1: oklch(0.95 0.012 130);
306
- --text-primary: oklch(0.20 0.02 130);
307
- --text-secondary: oklch(0.42 0.018 130);
308
- --accent: oklch(0.58 0.10 130);
309
- --accent-hover: oklch(0.52 0.12 130);
310
- --accent-subtle: oklch(0.93 0.03 130);
311
- --border: oklch(0.88 0.01 130);
312
- --success: oklch(0.55 0.14 150);
313
- --warning: oklch(0.66 0.15 75);
314
- --error: oklch(0.55 0.18 25);
315
- }
316
- ```
317
-
318
- ### 7.9 Charcoal with Orange Accent
319
- **Vibe**: Bold, industrial, high-contrast. Good for dev tools, gaming, analytics, creative coding.
320
- ```css
321
- :root {
322
- --surface-0: oklch(0.97 0.003 60);
323
- --surface-1: oklch(0.94 0.005 60);
324
- --text-primary: oklch(0.15 0.01 60);
325
- --text-secondary: oklch(0.40 0.01 60);
326
- --accent: oklch(0.65 0.22 55);
327
- --accent-hover: oklch(0.58 0.24 55);
328
- --accent-subtle: oklch(0.94 0.04 55);
329
- --border: oklch(0.86 0.008 60);
330
- --success: oklch(0.55 0.16 150);
331
- --warning: oklch(0.66 0.18 70);
332
- --error: oklch(0.55 0.22 25);
333
- }
334
- ```
335
-
336
- ### 7.10 Monochrome Black and White
337
- **Vibe**: Stark, typographic, gallery-like. Good for portfolios, photography, editorial, minimal SaaS.
338
- ```css
339
- :root {
340
- --surface-0: oklch(0.99 0.000 0);
341
- --surface-1: oklch(0.96 0.000 0);
342
- --text-primary: oklch(0.13 0.000 0);
343
- --text-secondary: oklch(0.45 0.000 0);
344
- --accent: oklch(0.15 0.000 0);
345
- --accent-hover: oklch(0.25 0.000 0);
346
- --accent-subtle: oklch(0.93 0.000 0);
347
- --border: oklch(0.85 0.000 0);
348
- --success: oklch(0.50 0.14 150);
349
- --warning: oklch(0.62 0.14 75);
350
- --error: oklch(0.50 0.18 25);
351
- }
352
- ```
353
-
354
- For the monochrome palette, the accent is near-black. CTAs rely on fill weight (solid black buttons with white text) rather than color. Semantic colors (success, warning, error) break the monochrome intentionally so they remain functional.
149
+ All 10 palettes follow this same token structure. To use a different palette, change the hue and chroma values while keeping the lightness relationships consistent. For monochrome, accent is near-black; CTAs use fill weight (solid black button, white text).
355
150
 
356
151
  ---
357
152
 
358
153
  ## 8. Wide Gamut Colors (P3)
359
154
 
360
- ### What is Display P3?
361
- Display P3 is a color space that covers roughly 25% more visible colors than sRGB. Modern Apple devices, most OLED screens, and recent monitors support it. Colors outside the sRGB gamut appear more vivid without being oversaturated.
362
-
363
- ### CSS Syntax
364
- ```css
365
- /* Display P3 via color() function */
366
- --accent: color(display-p3 0.92 0.34 0.15); /* vivid orange impossible in sRGB */
367
- --success: color(display-p3 0.18 0.75 0.35); /* richer green */
368
- --highlight: color(display-p3 1 0.85 0); /* pure P3 yellow */
369
- ```
370
-
371
- ### Feature Detection
372
- ```css
373
- @media (color-gamut: p3) {
374
- :root {
375
- --accent: color(display-p3 0.92 0.34 0.15);
376
- --success: color(display-p3 0.18 0.75 0.35);
377
- }
378
- }
379
- ```
155
+ Display P3 covers ~25% more visible colors than sRGB. Supported on modern Apple devices and most OLED screens.
380
156
 
381
- ### Progressive Enhancement Pattern
382
- Always define an sRGB fallback first, then override for wide gamut displays. This ensures every screen gets a reasonable color.
157
+ ### Progressive Enhancement
158
+ OKLCH values automatically map to the widest gamut available. Pushing chroma beyond ~0.15-0.20 often enters P3 territory. Override for wide gamut:
383
159
 
384
160
  ```css
385
- :root {
386
- /* sRGB fallback (works everywhere) */
387
- --accent: oklch(0.65 0.22 35);
388
- --success: oklch(0.55 0.18 150);
389
- --highlight: oklch(0.82 0.18 90);
390
- }
391
-
392
161
  @media (color-gamut: p3) {
393
- :root {
394
- /* P3 override (wider gamut screens) */
395
- --accent: oklch(0.65 0.27 35); /* push chroma beyond sRGB limit */
396
- --success: oklch(0.55 0.22 150);
397
- --highlight: oklch(0.82 0.22 90);
398
- }
162
+ :root { --accent: oklch(0.65 0.27 35); /* higher chroma for P3 */ }
399
163
  }
400
164
  ```
401
165
 
402
- Note: OKLCH values automatically map to the widest gamut the browser and display support. Increasing chroma beyond ~0.15-0.20 (depending on hue) often pushes into P3 territory. This makes OKLCH the ideal space for progressive enhancement because you write one value and the browser resolves it to the best available gamut.
403
-
404
166
  ### When to Use P3
405
- - Hero gradients and accent splashes where vibrancy matters
406
- - Success/error states that need to "pop" on capable screens
407
- - Brand colors that were designed in P3 (increasingly common)
408
- - Image overlays and tinted surfaces that blend with wide-gamut photography
167
+ - Hero gradients, accent splashes where vibrancy matters
168
+ - Success/error states that need to pop
169
+ - Brand colors designed in P3
409
170
 
410
171
  ### When NOT to Use P3
411
- - Body text colors (perceptual difference is negligible)
412
- - Border and surface tokens (subtle differences, not worth the complexity)
413
- - Any context where the sRGB version already looks correct
172
+ - Body text, borders, surfaces (negligible perceptual difference)
414
173
 
415
174
  ---
416
175
 
417
176
  ## 9. `light-dark()` CSS Function
418
177
 
419
- The `light-dark()` function returns one of two values depending on the current `color-scheme`. This eliminates the need for duplicate variable declarations in many cases:
178
+ Returns one of two values depending on `color-scheme`. Eliminates duplicate variable declarations for simple color flips.
420
179
 
421
180
  ```css
422
- :root {
423
- color-scheme: light dark;
424
- }
425
-
426
- .surface {
427
- background: light-dark(oklch(0.97 0.005 260), oklch(0.17 0.012 260));
428
- }
429
- .text {
430
- color: light-dark(oklch(0.20 0.015 260), oklch(0.93 0.01 260));
431
- }
432
- .border {
433
- border-color: light-dark(oklch(0.88 0.01 260), oklch(0.25 0.01 260));
434
- }
181
+ :root { color-scheme: light dark; }
182
+ .surface { background: light-dark(oklch(0.97 0.005 260), oklch(0.17 0.012 260)); }
435
183
  ```
436
184
 
437
- Use `light-dark()` for simple color flips (surfaces, text, borders). For complex theme differences (shadow systems, accent adjustments, chroma changes), continue using `[data-theme="dark"]` selectors or CSS custom properties for full control.
438
-
439
- Browser support: baseline since March 2024 (Chrome 123, Firefox 120, Safari 17.5).
185
+ Use for simple flips (surfaces, text, borders). For complex theme differences, use `[data-theme="dark"]` selectors. Baseline since March 2024.
440
186
 
441
187
  ---
442
188
 
443
189
  ## 10. `color-mix()` for Runtime Blending
444
190
 
445
- `color-mix()` blends two colors at runtime without defining intermediate tokens. Useful for hover states, tinted surfaces, and dynamic theming:
191
+ Blend colors at runtime without intermediate tokens. Always use `in oklch` for perceptually uniform results.
446
192
 
447
193
  ```css
448
- /* Hover: darken accent by mixing with black */
449
- .btn:hover {
450
- background: color-mix(in oklch, var(--accent), black 15%);
451
- }
452
-
453
- /* Subtle tint: mix accent into white */
454
- .surface-tinted {
455
- background: color-mix(in oklch, var(--accent), white 92%);
456
- }
457
-
458
- /* Disabled: reduce opacity feel by mixing with the surface */
459
- .btn:disabled {
460
- background: color-mix(in oklch, var(--accent), var(--surface-0) 60%);
461
- }
194
+ .btn:hover { background: color-mix(in oklch, var(--accent), black 15%); }
195
+ .surface-tinted { background: color-mix(in oklch, var(--accent), white 92%); }
196
+ .btn:disabled { background: color-mix(in oklch, var(--accent), var(--surface-0) 60%); }
462
197
  ```
463
198
 
464
- Always specify `in oklch` for perceptually uniform blending. Mixing `in srgb` produces muddier results, especially across hues.
465
-
466
199
  ---
467
200
 
468
201
  ## 11. Common Mistakes
469
202
 
470
- - Using pure black (#000) for text (use tinted near-black instead)
471
- - Using gray text on colored backgrounds (low contrast, hard to read)
472
- - Applying opacity to achieve lighter colors (makes elements look washed out; use chroma reduction instead)
473
- - Using too many accent colors (one primary accent, one secondary maximum)
203
+ - Using pure black (#000) for text (use tinted near-black)
204
+ - Gray text on colored backgrounds (low contrast)
205
+ - Applying opacity for lighter colors (use chroma reduction instead)
206
+ - Too many accent colors (one primary, one secondary max)
474
207
  - Forgetting to test dark mode after building light mode
475
- - Using brand colors at full saturation for large surfaces (they vibrate and cause eye strain; reserve full chroma for small accents)
476
- - Not providing hover/focus states with visible color change
477
- - Using `color-mix(in srgb, ...)` instead of `color-mix(in oklch, ...)` (sRGB blending produces muddier, less predictable results)
208
+ - Full saturation on large surfaces (eye strain; reserve full chroma for small accents)
209
+ - No hover/focus states with visible color change
210
+ - Using `color-mix(in srgb)` instead of `color-mix(in oklch)` (muddier results)