@astryxdesign/theme-butter 0.0.0-bootstrap.0 → 0.0.15

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.
@@ -0,0 +1,916 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * Butter Theme
5
+ *
6
+ * Warm, golden buttery theme with blue accents.
7
+ * Sarina for display, Outfit for headings and body.
8
+ *
9
+ * Source palette (per design):
10
+ * Accent #225BFF Gray #868B99 Red #FF7553
11
+ * Orange #FFA347 Yellow #fdee8c Green #5DCE5F
12
+ * Cyan #60CFD3 Teal #6CD9A8 Blue #5681FF
13
+ * Purple #B780F6 Pink #F680E8 Error #FF5947
14
+ * Warning #F8C726 Success #91D143
15
+ *
16
+ * All tonal ramps derived in CIELab (matches the algorithm used by
17
+ * ThemePalettePreview so card / badge / banner / strip render the
18
+ * same values). Regen via scripts/butter-palette-gen.mjs if sources
19
+ * change.
20
+ */
21
+
22
+ import {defineTheme, defineSyntaxTheme} from '@astryxdesign/core/theme';
23
+ import {butterIconRegistry} from './icons';
24
+
25
+ /** Butter syntax palette — T25 / T80 of each color's ramp. */
26
+ const butterSyntax = defineSyntaxTheme({
27
+ name: 'xds-butter',
28
+ tokens: {
29
+ keyword: ['#52237b', '#ddb9f6'], // Purple
30
+ string: ['#004800', '#a5d29d'], // Green
31
+ comment: ['#605f52', '#adac9e'],
32
+ number: ['#622e00', '#f2bd81'], // Orange
33
+ function: ['#203a6c', '#bdc5eb'], // Blue
34
+ type: ['#52237b', '#ddb9f6'], // Purple
35
+ variable: ['#605f52', '#adac9e'],
36
+ operator: ['#605f52', '#adac9e'],
37
+ constant: ['#622e00', '#f2bd81'],
38
+ tag: ['#6d211c', '#f4b8ae'], // Red
39
+ attribute: ['#413e00', '#d6c957'], // Yellow
40
+ property: ['#00482d', '#94d3bb'], // Teal
41
+ punctuation: ['#605f52', '#adac9e'],
42
+ background: ['#FDFBE4', '#131107'],
43
+ },
44
+ });
45
+
46
+ export const butterTheme = defineTheme({
47
+ name: 'butter',
48
+
49
+ typography: {
50
+ scale: {base: 14, ratio: 1.25},
51
+ body: {
52
+ family: 'Outfit',
53
+ fallbacks:
54
+ '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
55
+ },
56
+ heading: {
57
+ family: 'Outfit',
58
+ fallbacks:
59
+ '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
60
+ weights: {3: 'bold', 4: 'bold'},
61
+ },
62
+ code: {
63
+ family: 'JetBrains Mono',
64
+ fallbacks: '"SF Mono", Monaco, Consolas, monospace',
65
+ },
66
+ },
67
+
68
+ motion: {fast: 125, medium: 300, slow: 700, ratio: 0.75},
69
+
70
+ syntax: butterSyntax,
71
+
72
+ tokens: {
73
+ // =========================================================================
74
+ // Core semantic — accent is the exact brand #225BFF
75
+ // =========================================================================
76
+ '--color-accent': ['#225BFF', '#FDEE8C'],
77
+ '--color-accent-muted': ['#225BFF33', '#FDEE8C40'],
78
+ '--color-neutral': ['#1d1c110F', '#f3f2e21A'],
79
+ '--color-background-surface': ['#FFFFFF', '#2E2117'],
80
+ '--color-background-body': ['#FDFBE4', '#261A13'],
81
+ '--color-overlay': ['#1d1c1180', '#261A13cc'],
82
+ '--color-overlay-hover': ['#1d1c110D', '#f3f2e20D'],
83
+ '--color-overlay-pressed': ['#1d1c111A', '#f3f2e21A'],
84
+ '--color-background-muted': ['#f3f2e2', '#3A2A1F'],
85
+
86
+ // Text — warm neutral
87
+ '--color-text-primary': ['#1d1c11', '#f3f2e2'],
88
+ '--color-text-secondary': ['#605f52', '#adac9e'],
89
+ '--color-text-disabled': ['#adac9e', '#605f52'],
90
+ '--color-text-accent': ['#225BFF', '#FDEE8C'],
91
+ '--color-on-dark': '#ffffff',
92
+ '--color-on-light': '#1d1c11',
93
+ '--color-on-accent': ['#ffffff', '#1d1c11'],
94
+ // T95 of each ramp for use on the vivid semantic surfaces.
95
+ '--color-on-success': ['#ccff88', '#0b2e00'],
96
+ '--color-on-error': ['#ffe3de', '#600000'],
97
+ '--color-on-warning': ['#ffeec3', '#3b2200'],
98
+
99
+ // Icon
100
+ '--color-icon-accent': ['#225BFF', '#FDEE8C'],
101
+ '--color-icon-primary': ['#1d1c11', '#f3f2e2'],
102
+ '--color-icon-secondary': ['#605f52', '#adac9e'],
103
+ '--color-icon-disabled': ['#adac9e', '#605f52'],
104
+
105
+ // Surface variants
106
+ '--color-background-card': ['#FFFFFF', '#3A2A1F'],
107
+ '--color-background-popover': ['#FFFFFF', '#3A2A1F'],
108
+ '--color-background-inverted': ['#1d1c11', '#FDFBE4'],
109
+
110
+ // Status semantics — T25 light / T80 dark from each status palette.
111
+ '--color-error': ['#771210', '#ffb4a6'],
112
+ '--color-error-muted': ['#77121033', '#ffb4a640'],
113
+ '--color-warning': ['#543700', '#f7be00'],
114
+ '--color-warning-muted': ['#54370033', '#f7be0040'],
115
+ '--color-success': ['#004700', '#99d94b'],
116
+ '--color-success-muted': ['#00470033', '#99d94b40'],
117
+
118
+ // Border — softer taupe card outline (emphasized) in light mode.
119
+ '--color-border': ['#e5e3d4', '#f3f2e21A'],
120
+ '--color-border-emphasized': ['#C7C4B2', '#939184'],
121
+
122
+ // Effects
123
+ '--color-skeleton': ['#e5e3d4', '#49473b'],
124
+ '--color-shadow': ['#1d1c111A', '#0000004D'],
125
+ '--color-tint-hover': ['black', 'white'],
126
+
127
+ // Typography override
128
+ '--text-supporting-size': '12px',
129
+
130
+ // Element sizes — slightly taller defaults so the new input padding
131
+ // (--spacing-2 block) has room to breathe.
132
+ '--size-element-sm': '32px',
133
+ '--size-element-md': '40px',
134
+ '--size-element-lg': '48px',
135
+
136
+ // =========================================================================
137
+ // Categorical — same values in light and dark mode (curated dark mode
138
+ // keeps the same pastel backgrounds + dark text as light mode).
139
+ // =========================================================================
140
+
141
+ // Blue
142
+ '--color-background-blue': ['#dbe1ff', '#dbe1ff'],
143
+ '--color-border-blue': ['#bdc5eb', '#bdc5eb'],
144
+ '--color-icon-blue': ['#203a6c', '#203a6c'],
145
+ '--color-text-blue': ['#203a6c', '#203a6c'],
146
+
147
+ // Cyan
148
+ '--color-background-cyan': ['#a9eff0', '#a9eff0'],
149
+ '--color-border-cyan': ['#8dd2d3', '#8dd2d3'],
150
+ '--color-icon-cyan': ['#004649', '#004649'],
151
+ '--color-text-cyan': ['#004649', '#004649'],
152
+
153
+ // Gray (uses the neutral palette)
154
+ '--color-background-gray': ['#f0edd4', '#f0edd4'],
155
+ '--color-border-gray': ['#d6d3b8', '#d6d3b8'],
156
+ '--color-icon-gray': ['#4a4732', '#4a4732'],
157
+ '--color-text-gray': ['#4a4732', '#4a4732'],
158
+
159
+ // Green
160
+ '--color-background-green': ['#c1efb8', '#c1efb8'],
161
+ '--color-border-green': ['#a5d29d', '#a5d29d'],
162
+ '--color-icon-green': ['#004800', '#004800'],
163
+ '--color-text-green': ['#004800', '#004800'],
164
+
165
+ // Orange
166
+ '--color-background-orange': ['#ffdcb6', '#ffdcb6'],
167
+ '--color-border-orange': ['#f2bd81', '#f2bd81'],
168
+ '--color-icon-orange': ['#622e00', '#622e00'],
169
+ '--color-text-orange': ['#622e00', '#622e00'],
170
+
171
+ // Pink
172
+ '--color-background-pink': ['#ffd5fb', '#ffd5fb'],
173
+ '--color-border-pink': ['#f0b3e8', '#f0b3e8'],
174
+ '--color-icon-pink': ['#6c0a68', '#6c0a68'],
175
+ '--color-text-pink': ['#6c0a68', '#6c0a68'],
176
+
177
+ // Purple
178
+ '--color-background-purple': ['#f2daff', '#f2daff'],
179
+ '--color-border-purple': ['#ddb9f6', '#ddb9f6'],
180
+ '--color-icon-purple': ['#52237b', '#52237b'],
181
+ '--color-text-purple': ['#52237b', '#52237b'],
182
+
183
+ // Red
184
+ '--color-background-red': ['#ffdad3', '#ffdad3'],
185
+ '--color-border-red': ['#f4b8ae', '#f4b8ae'],
186
+ '--color-icon-red': ['#6d211c', '#6d211c'],
187
+ '--color-text-red': ['#6d211c', '#6d211c'],
188
+
189
+ // Teal
190
+ '--color-background-teal': ['#b0f0d7', '#b0f0d7'],
191
+ '--color-border-teal': ['#94d3bb', '#94d3bb'],
192
+ '--color-icon-teal': ['#00482d', '#00482d'],
193
+ '--color-text-teal': ['#00482d', '#00482d'],
194
+
195
+ // Yellow
196
+ '--color-background-yellow': ['#feee7b', '#feee7b'],
197
+ '--color-border-yellow': ['#d6c957', '#d6c957'],
198
+ '--color-icon-yellow': ['#413e00', '#413e00'],
199
+ '--color-text-yellow': ['#413e00', '#413e00'],
200
+
201
+ // =========================================================================
202
+ // Radius
203
+ // --radius-element drives buttons, badges, inputs — 8px per design
204
+ // --radius-container drives cards, banners, popovers — 12px per design
205
+ // =========================================================================
206
+ '--radius-none': '0.125rem',
207
+ '--radius-inner': '0.375rem',
208
+ '--radius-element': '0.5rem', // 8px
209
+ '--radius-container': '0.75rem', // 12px
210
+ '--radius-page': '1.5rem',
211
+ '--radius-full': '9999px',
212
+
213
+ // =========================================================================
214
+ // Shadows — warm neutral tint
215
+ // =========================================================================
216
+ '--shadow-low': '0 2px 4px #1d1c110D, 0 4px 8px #1d1c111A',
217
+ '--shadow-med': '0 2px 4px #1d1c110D, 0 4px 12px #1d1c111A',
218
+ '--shadow-high': '0 4px 6px #1d1c111A, 0 12px 24px #1d1c1126',
219
+ '--shadow-inset-hover': 'inset 0px 0px 0px 2px #79786a30',
220
+ '--shadow-inset-selected': 'inset 0px 0px 0px 2px #79786a50',
221
+ '--shadow-inset-success': 'inset 0px 0px 0px 2px #00470030',
222
+ '--shadow-inset-warning': 'inset 0px 0px 0px 2px #54370030',
223
+ '--shadow-inset-error': 'inset 0px 0px 0px 2px #77121030',
224
+ },
225
+
226
+ components: {
227
+ // TopNav uses Butter's blue accent: the heading and the selected item are
228
+ // the full brand blue; unselected items (default + hover) use a lighter
229
+ // blue. Dark mode keeps the theme's butter-yellow accent.
230
+ 'top-nav-heading': {
231
+ // The heading text is an inner span that reads --color-text-primary, so
232
+ // redirect that token (not just `color`) to the brand blue so the text
233
+ // itself turns blue, not only the container.
234
+ base: {
235
+ color: 'light-dark(#225BFF, #FDEE8C)',
236
+ '--color-text-primary': 'light-dark(#225BFF, #FDEE8C)',
237
+ },
238
+ },
239
+ 'top-nav-item': {
240
+ base: {
241
+ color: 'light-dark(#6E92FF, #FDEE8CCC)',
242
+ },
243
+ // Selected item: full brand blue, no pill background — rely on weight +
244
+ // color for emphasis. Hover/active keep the neutral overlay.
245
+ selected: {
246
+ color: 'light-dark(#225BFF, #FDEE8C)',
247
+ backgroundColor: 'transparent',
248
+ ':hover': {
249
+ backgroundColor: 'var(--color-overlay-hover)',
250
+ },
251
+ ':active': {
252
+ backgroundColor: 'var(--color-overlay-pressed)',
253
+ },
254
+ },
255
+ },
256
+ button: {
257
+ // Radius intentionally not pinned, so buttons keep core's
258
+ // `var(--_button-radius, --radius-element)`: standalone buttons stay 8px,
259
+ // while the chat composer (which sets --_button-radius) rounds them fully.
260
+ base: {
261
+ paddingBlock: 'var(--spacing-3)',
262
+ paddingInline: 'var(--spacing-4)',
263
+ },
264
+ // Secondary: blue outline + label in light, butter yellow in dark.
265
+ 'variant:secondary': {
266
+ backgroundColor: 'transparent',
267
+ borderWidth: '1.5px',
268
+ borderStyle: 'solid',
269
+ borderColor: 'light-dark(#225BFF, #FDEE8C)',
270
+ color: 'light-dark(#225BFF, #FDEE8C)',
271
+ ':hover': {
272
+ backgroundColor: 'light-dark(#225BFF14, #FDEE8C14)',
273
+ },
274
+ },
275
+ // Ghost: same accent color as secondary, no background.
276
+ 'variant:ghost': {
277
+ color: 'light-dark(#225BFF, #FDEE8C)',
278
+ },
279
+ 'variant:destructive': {
280
+ backgroundColor: 'light-dark(#ffdad3, #f4b8ae)',
281
+ color: 'light-dark(#550000, #6d211c)',
282
+ },
283
+ },
284
+
285
+ badge: {
286
+ // Match astryx/daily badge sizing: 30px tall with 12px horizontal pad.
287
+ // Use explicit values because butter inherits the standard spacing
288
+ // scale (where --spacing-3 = 12px), unlike astryx which redefines it.
289
+ base: {
290
+ height: '30px',
291
+ paddingBlock: '0',
292
+ paddingInline: 'var(--spacing-3)',
293
+ },
294
+ // Vivid semantic badges — pinned to the brand colors from the spec.
295
+ // Info uses the Blue palette source (NOT the brand accent #225BFF).
296
+ 'variant:info': {
297
+ backgroundColor: '#4883fd',
298
+ color: '#ffffff',
299
+ },
300
+ 'variant:neutral': {
301
+ backgroundColor: '#ffee7b',
302
+ color: '#225BFF',
303
+ },
304
+ 'variant:success': {
305
+ backgroundColor: '#91D143',
306
+ color: '#1d1c11',
307
+ },
308
+ 'variant:warning': {
309
+ backgroundColor: '#ffc502',
310
+ color: '#1d1c11',
311
+ },
312
+ 'variant:error': {
313
+ backgroundColor: '#fc473b',
314
+ color: '#ffffff',
315
+ },
316
+ },
317
+
318
+ // Banner backgrounds match the semantic badge fills.
319
+ // Banner status colors — override the muted tokens locally so the
320
+ // header (which reads --color-*-muted via StyleX) renders vivid fills
321
+ // matching the badge palette. Scoped to the banner root, doesn't leak.
322
+ banner: {
323
+ 'status:info': {
324
+ '--color-accent-muted': '#4883fd',
325
+ '--color-text-primary': '#ffffff',
326
+ '--color-text-secondary': '#ffffff',
327
+ '--color-accent': '#ffffff',
328
+ },
329
+ 'status:success': {
330
+ '--color-success-muted': '#91D143',
331
+ '--color-text-primary': '#1d1c11',
332
+ '--color-text-secondary': '#1d1c11',
333
+ '--color-success': '#1d1c11',
334
+ },
335
+ 'status:warning': {
336
+ '--color-warning-muted': '#ffc502',
337
+ '--color-text-primary': '#1d1c11',
338
+ '--color-text-secondary': '#1d1c11',
339
+ '--color-warning': '#1d1c11',
340
+ },
341
+ 'status:error': {
342
+ '--color-error-muted': '#fc473b',
343
+ '--color-text-primary': '#ffffff',
344
+ '--color-text-secondary': '#ffffff',
345
+ '--color-error': '#ffffff',
346
+ },
347
+ },
348
+
349
+ card: {
350
+ base: {
351
+ borderRadius: 'var(--radius-container)',
352
+ padding: 'var(--spacing-4)',
353
+ },
354
+ 'variant:info': {
355
+ '--color-text-primary': '#1d1c11',
356
+ '--color-text-secondary': '#605f52',
357
+ },
358
+ 'variant:success': {
359
+ '--color-text-primary': '#1d1c11',
360
+ '--color-text-secondary': '#605f52',
361
+ },
362
+ 'variant:warning': {
363
+ '--color-text-primary': '#1d1c11',
364
+ '--color-text-secondary': '#605f52',
365
+ },
366
+ 'variant:error': {
367
+ '--color-text-primary': '#1d1c11',
368
+ '--color-text-secondary': '#605f52',
369
+ },
370
+ 'variant:blue': {
371
+ '--color-text-primary': '#1d1c11',
372
+ '--color-text-secondary': '#605f52',
373
+ },
374
+ 'variant:cyan': {
375
+ '--color-text-primary': '#1d1c11',
376
+ '--color-text-secondary': '#605f52',
377
+ },
378
+ 'variant:gray': {
379
+ '--color-text-primary': '#1d1c11',
380
+ '--color-text-secondary': '#605f52',
381
+ },
382
+ 'variant:green': {
383
+ '--color-text-primary': '#1d1c11',
384
+ '--color-text-secondary': '#605f52',
385
+ },
386
+ 'variant:orange': {
387
+ '--color-text-primary': '#1d1c11',
388
+ '--color-text-secondary': '#605f52',
389
+ },
390
+ 'variant:pink': {
391
+ '--color-text-primary': '#1d1c11',
392
+ '--color-text-secondary': '#605f52',
393
+ },
394
+ 'variant:purple': {
395
+ '--color-text-primary': '#1d1c11',
396
+ '--color-text-secondary': '#605f52',
397
+ },
398
+ 'variant:red': {
399
+ '--color-text-primary': '#1d1c11',
400
+ '--color-text-secondary': '#605f52',
401
+ },
402
+ 'variant:teal': {
403
+ '--color-text-primary': '#1d1c11',
404
+ '--color-text-secondary': '#605f52',
405
+ },
406
+ 'variant:yellow': {
407
+ '--color-text-primary': '#1d1c11',
408
+ '--color-text-secondary': '#605f52',
409
+ },
410
+ 'variant:muted': {
411
+ '--color-text-primary': '#1d1c11',
412
+ '--color-text-secondary': '#605f52',
413
+ },
414
+ },
415
+
416
+ section: {
417
+ base: {
418
+ padding: 'var(--spacing-4)',
419
+ },
420
+ },
421
+
422
+ // Progress bar — white track in light, warm brown in dark. Vivid
423
+ // semantic fills match the banner colors (Success / Warning / Error).
424
+ 'progressbar-track': {
425
+ base: {
426
+ backgroundColor: 'light-dark(#e5e3d4, #725538)',
427
+ },
428
+ },
429
+ 'progressbar-fill': {
430
+ 'variant:success': {
431
+ backgroundColor: '#91D143',
432
+ },
433
+ 'variant:warning': {
434
+ backgroundColor: '#ffc502',
435
+ },
436
+ 'variant:error': {
437
+ backgroundColor: '#fc473b',
438
+ },
439
+ },
440
+
441
+ // Field status bubble — match the corresponding banner colors so the
442
+ // helper text below an input reads as the same "this is a warning /
443
+ // error / success" surface as the standalone banner.
444
+ 'field-status': {
445
+ 'type:success': {
446
+ backgroundColor: '#91D143',
447
+ color: '#1d1c11',
448
+ },
449
+ 'type:warning': {
450
+ backgroundColor: '#ffc502',
451
+ color: '#1d1c11',
452
+ },
453
+ 'type:error': {
454
+ backgroundColor: '#fc473b',
455
+ color: '#ffffff',
456
+ },
457
+ },
458
+
459
+ // Inputs — softer border than default, more vertical breathing room.
460
+ // Status modifiers also remap the semantic tokens locally so the
461
+ // status icon + border read as the same vivid hue as the banner
462
+ // (icons inherit from --color-{success,warning,error}).
463
+ 'text-input': {
464
+ base: {
465
+ paddingBlock: 'var(--spacing-2)',
466
+ paddingInline: 'var(--spacing-3)',
467
+ borderColor: 'var(--color-border)',
468
+ },
469
+ 'status:success': {'--color-success': '#91D143'},
470
+ 'status:warning': {'--color-warning': '#ffc502'},
471
+ 'status:error': {'--color-error': '#fc473b'},
472
+ },
473
+ textarea: {
474
+ base: {
475
+ paddingBlock: 'var(--spacing-2)',
476
+ paddingInline: 'var(--spacing-3)',
477
+ borderColor: 'var(--color-border)',
478
+ },
479
+ 'status:success': {'--color-success': '#91D143'},
480
+ 'status:warning': {'--color-warning': '#ffc502'},
481
+ 'status:error': {'--color-error': '#fc473b'},
482
+ },
483
+ 'number-input': {
484
+ base: {
485
+ paddingBlock: 'var(--spacing-2)',
486
+ paddingInline: 'var(--spacing-3)',
487
+ borderColor: 'var(--color-border)',
488
+ },
489
+ 'status:success': {'--color-success': '#91D143'},
490
+ 'status:warning': {'--color-warning': '#ffc502'},
491
+ 'status:error': {'--color-error': '#fc473b'},
492
+ },
493
+ 'date-input': {
494
+ base: {
495
+ paddingBlock: 'var(--spacing-2)',
496
+ paddingInline: 'var(--spacing-3)',
497
+ borderColor: 'var(--color-border)',
498
+ },
499
+ 'status:success': {'--color-success': '#91D143'},
500
+ 'status:warning': {'--color-warning': '#ffc502'},
501
+ 'status:error': {'--color-error': '#fc473b'},
502
+ },
503
+ 'time-input': {
504
+ base: {
505
+ paddingBlock: 'var(--spacing-2)',
506
+ paddingInline: 'var(--spacing-3)',
507
+ borderColor: 'var(--color-border)',
508
+ },
509
+ 'status:success': {'--color-success': '#91D143'},
510
+ 'status:warning': {'--color-warning': '#ffc502'},
511
+ 'status:error': {'--color-error': '#fc473b'},
512
+ },
513
+ selector: {
514
+ base: {
515
+ paddingBlock: 'var(--spacing-2)',
516
+ paddingInline: 'var(--spacing-3)',
517
+ borderColor: 'var(--color-border)',
518
+ },
519
+ 'status:success': {'--color-success': '#91D143'},
520
+ 'status:warning': {'--color-warning': '#ffc502'},
521
+ 'status:error': {'--color-error': '#fc473b'},
522
+ },
523
+ 'multi-selector': {
524
+ base: {
525
+ paddingBlock: 'var(--spacing-2)',
526
+ paddingInline: 'var(--spacing-3)',
527
+ borderColor: 'var(--color-border)',
528
+ },
529
+ 'status:success': {'--color-success': '#91D143'},
530
+ 'status:warning': {'--color-warning': '#ffc502'},
531
+ 'status:error': {'--color-error': '#fc473b'},
532
+ },
533
+ typeahead: {
534
+ base: {
535
+ paddingBlock: 'var(--spacing-2)',
536
+ paddingInline: 'var(--spacing-3)',
537
+ borderColor: 'var(--color-border)',
538
+ },
539
+ 'status:success': {'--color-success': '#91D143'},
540
+ 'status:warning': {'--color-warning': '#ffc502'},
541
+ 'status:error': {'--color-error': '#fc473b'},
542
+ },
543
+ tokenizer: {
544
+ base: {
545
+ paddingBlock: 'var(--spacing-2)',
546
+ paddingInline: 'var(--spacing-3)',
547
+ borderColor: 'var(--color-border)',
548
+ },
549
+ 'status:success': {'--color-success': '#91D143'},
550
+ 'status:warning': {'--color-warning': '#ffc502'},
551
+ 'status:error': {'--color-error': '#fc473b'},
552
+ },
553
+
554
+ // Display sizes use Sarina — the signature buttery display
555
+ // cursive, reserved for hero/marketing-scale text only.
556
+ // Headings (h1–h6) and body still use Outfit (configured above
557
+ // under typography.heading / typography.body). Same pattern
558
+ // Gothic uses for its Manufacturing Consent display family.
559
+ text: {
560
+ 'type:display-1': {
561
+ fontFamily: 'Sarina, "Brush Script MT", "Snell Roundhand", cursive',
562
+ },
563
+ 'type:display-2': {
564
+ fontFamily: 'Sarina, "Brush Script MT", "Snell Roundhand", cursive',
565
+ },
566
+ 'type:display-3': {
567
+ fontFamily: 'Sarina, "Brush Script MT", "Snell Roundhand", cursive',
568
+ },
569
+ },
570
+ },
571
+
572
+ icons: butterIconRegistry,
573
+ });
574
+
575
+ /**
576
+ * Raw tonal palettes — generated from design-spec source hexes via the
577
+ * same CIELab algorithm `ThemePalettePreview` uses for the displayed
578
+ * strip, so the rendered ramp and the consumed token values are 1:1.
579
+ *
580
+ * Source colors:
581
+ * accent #225BFF neutral #868B99
582
+ * red #ffc3b8 orange #ffc98d yellow #feee7b
583
+ * green #bdebb4 cyan #abf1f1 teal #aeefd6
584
+ * blue #cdd5fc purple #e6c2ff pink #fec0f5
585
+ * error #fc473b warning #ffc502 success #91D143
586
+ *
587
+ * Categorical sources are the pastel pill hexes from the design spec so
588
+ * each ramp's T85 lands directly on the card / badge background color.
589
+ * Semantic sources are vivid so the ramp anchors near the badge fill.
590
+ *
591
+ * Regenerate with: node packages/themes/butter/scripts/generate-palettes.mjs
592
+ */
593
+ export const butterPalettes = {
594
+ blue: {
595
+ 0: '#000000',
596
+ 5: '#001041',
597
+ 10: '#001b4c',
598
+ 15: '#002558',
599
+ 20: '#062f63',
600
+ 25: '#203a6c',
601
+ 30: '#324575',
602
+ 35: '#41517d',
603
+ 40: '#505d86',
604
+ 45: '#5f698f',
605
+ 50: '#6d7698',
606
+ 55: '#7a82a6',
607
+ 60: '#878fb3',
608
+ 65: '#949cc1',
609
+ 70: '#a2aacf',
610
+ 75: '#afb7dd',
611
+ 80: '#bdc5eb',
612
+ 85: '#cbd3f9',
613
+ 90: '#dbe1ff',
614
+ 95: '#edf0ff',
615
+ 100: '#ffffff',
616
+ },
617
+ cyan: {
618
+ 0: '#000000',
619
+ 5: '#001d1e',
620
+ 10: '#00262a',
621
+ 15: '#003034',
622
+ 20: '#003a3e',
623
+ 25: '#004649',
624
+ 30: '#005255',
625
+ 35: '#005e61',
626
+ 40: '#006a6d',
627
+ 45: '#1f7678',
628
+ 50: '#3c8183',
629
+ 55: '#4a8e90',
630
+ 60: '#579c9d',
631
+ 65: '#65a9aa',
632
+ 70: '#72b7b8',
633
+ 75: '#80c4c5',
634
+ 80: '#8dd2d3',
635
+ 85: '#9be0e1',
636
+ 90: '#a9eff0',
637
+ 95: '#b7fdfe',
638
+ 100: '#ffffff',
639
+ },
640
+ green: {
641
+ 0: '#000000',
642
+ 5: '#001f00',
643
+ 10: '#002800',
644
+ 15: '#003100',
645
+ 20: '#003c00',
646
+ 25: '#004800',
647
+ 30: '#01530d',
648
+ 35: '#1f5f1f',
649
+ 40: '#346a30',
650
+ 45: '#467640',
651
+ 50: '#578151',
652
+ 55: '#648e5d',
653
+ 60: '#709c6a',
654
+ 65: '#7da976',
655
+ 70: '#8ab783',
656
+ 75: '#98c490',
657
+ 80: '#a5d29d',
658
+ 85: '#b3e0ab',
659
+ 90: '#c1efb8',
660
+ 95: '#cffdc6',
661
+ 100: '#ffffff',
662
+ },
663
+ orange: {
664
+ 0: '#000000',
665
+ 5: '#2d0600',
666
+ 10: '#381200',
667
+ 15: '#461b00',
668
+ 20: '#542400',
669
+ 25: '#622e00',
670
+ 30: '#6d3a00',
671
+ 35: '#794700',
672
+ 40: '#845406',
673
+ 45: '#906121',
674
+ 50: '#9b6e36',
675
+ 55: '#a97b42',
676
+ 60: '#b7874e',
677
+ 65: '#c6945b',
678
+ 70: '#d4a267',
679
+ 75: '#e3af74',
680
+ 80: '#f2bd81',
681
+ 85: '#ffcb8e',
682
+ 90: '#ffdcb6',
683
+ 95: '#ffedda',
684
+ 100: '#ffffff',
685
+ },
686
+ pink: {
687
+ 0: '#000000',
688
+ 5: '#3c003d',
689
+ 10: '#490048',
690
+ 15: '#560054',
691
+ 20: '#62005f',
692
+ 25: '#6c0a68',
693
+ 30: '#762371',
694
+ 35: '#80357a',
695
+ 40: '#894583',
696
+ 45: '#93558c',
697
+ 50: '#9c6496',
698
+ 55: '#aa71a3',
699
+ 60: '#b77eb0',
700
+ 65: '#c58bbe',
701
+ 70: '#d398cc',
702
+ 75: '#e2a6da',
703
+ 80: '#f0b3e8',
704
+ 85: '#ffc1f6',
705
+ 90: '#ffd5fb',
706
+ 95: '#ffeafd',
707
+ 100: '#ffffff',
708
+ },
709
+ purple: {
710
+ 0: '#000000',
711
+ 5: '#1e004f',
712
+ 10: '#2b005c',
713
+ 15: '#390268',
714
+ 20: '#461373',
715
+ 25: '#52237b',
716
+ 30: '#5d3283',
717
+ 35: '#69408b',
718
+ 40: '#744e92',
719
+ 45: '#7f5c9a',
720
+ 50: '#8b6aa2',
721
+ 55: '#9877b0',
722
+ 60: '#a584bd',
723
+ 65: '#b391cb',
724
+ 70: '#c19ed9',
725
+ 75: '#cfabe8',
726
+ 80: '#ddb9f6',
727
+ 85: '#eac8ff',
728
+ 90: '#f2daff',
729
+ 95: '#f9ecff',
730
+ 100: '#ffffff',
731
+ },
732
+ red: {
733
+ 0: '#000000',
734
+ 5: '#3e0000',
735
+ 10: '#490000',
736
+ 15: '#550000',
737
+ 20: '#62100f',
738
+ 25: '#6d211c',
739
+ 30: '#773029',
740
+ 35: '#823f36',
741
+ 40: '#8c4d44',
742
+ 45: '#955b52',
743
+ 50: '#9f6961',
744
+ 55: '#ad766d',
745
+ 60: '#bb837a',
746
+ 65: '#c99087',
747
+ 70: '#d79d94',
748
+ 75: '#e6aba1',
749
+ 80: '#f4b8ae',
750
+ 85: '#ffc7bd',
751
+ 90: '#ffdad3',
752
+ 95: '#ffece8',
753
+ 100: '#ffffff',
754
+ },
755
+ teal: {
756
+ 0: '#000000',
757
+ 5: '#001f00',
758
+ 10: '#00280b',
759
+ 15: '#003216',
760
+ 20: '#003d22',
761
+ 25: '#00482d',
762
+ 30: '#005439',
763
+ 35: '#005f45',
764
+ 40: '#136b52',
765
+ 45: '#30775f',
766
+ 50: '#46826d',
767
+ 55: '#528f79',
768
+ 60: '#5f9d86',
769
+ 65: '#6caa93',
770
+ 70: '#7ab8a0',
771
+ 75: '#87c5ae',
772
+ 80: '#94d3bb',
773
+ 85: '#a2e1c9',
774
+ 90: '#b0f0d7',
775
+ 95: '#befee5',
776
+ 100: '#ffffff',
777
+ },
778
+ yellow: {
779
+ 0: '#000000',
780
+ 5: '#1e1200',
781
+ 10: '#271c00',
782
+ 15: '#2e2700',
783
+ 20: '#373200',
784
+ 25: '#413e00',
785
+ 30: '#4c4a00',
786
+ 35: '#575600',
787
+ 40: '#646200',
788
+ 45: '#726e00',
789
+ 50: '#817a00',
790
+ 55: '#8e860e',
791
+ 60: '#9c9320',
792
+ 65: '#aba02f',
793
+ 70: '#b9ae3d',
794
+ 75: '#c7bb4a',
795
+ 80: '#d6c957',
796
+ 85: '#e5d765',
797
+ 90: '#f4e572',
798
+ 95: '#fff294',
799
+ 100: '#ffffff',
800
+ },
801
+ neutral: {
802
+ 0: '#000000',
803
+ 5: '#051124',
804
+ 10: '#101c2f',
805
+ 15: '#1b263a',
806
+ 20: '#273045',
807
+ 25: '#333b4f',
808
+ 30: '#3f4759',
809
+ 35: '#4b5264',
810
+ 40: '#585e6f',
811
+ 45: '#656a79',
812
+ 50: '#727784',
813
+ 55: '#7f8491',
814
+ 60: '#8c909f',
815
+ 65: '#999eac',
816
+ 70: '#a6abba',
817
+ 75: '#b4b9c7',
818
+ 80: '#c1c6d5',
819
+ 85: '#cfd4e3',
820
+ 90: '#dde2f2',
821
+ 95: '#ebf0ff',
822
+ 100: '#ffffff',
823
+ },
824
+ accent: {
825
+ 0: '#000000',
826
+ 5: '#00085e',
827
+ 10: '#00136c',
828
+ 15: '#001c7e',
829
+ 20: '#002592',
830
+ 25: '#002fa7',
831
+ 30: '#0039be',
832
+ 35: '#0043d7',
833
+ 40: '#004df0',
834
+ 45: '#0759ff',
835
+ 50: '#4a67ff',
836
+ 55: '#6875ff',
837
+ 60: '#8083ff',
838
+ 65: '#9492ff',
839
+ 70: '#a6a1ff',
840
+ 75: '#b6b0ff',
841
+ 80: '#c6bfff',
842
+ 85: '#d5cfff',
843
+ 90: '#e3dfff',
844
+ 95: '#f1efff',
845
+ 100: '#ffffff',
846
+ },
847
+ error: {
848
+ 0: '#000000',
849
+ 5: '#470000',
850
+ 10: '#530000',
851
+ 15: '#600000',
852
+ 20: '#6d0000',
853
+ 25: '#771210',
854
+ 30: '#82261e',
855
+ 35: '#8c372c',
856
+ 40: '#96463b',
857
+ 45: '#a0564a',
858
+ 50: '#a96559',
859
+ 55: '#b77265',
860
+ 60: '#c57e72',
861
+ 65: '#d48b7e',
862
+ 70: '#e2998b',
863
+ 75: '#f1a698',
864
+ 80: '#ffb4a6',
865
+ 85: '#ffc7bc',
866
+ 90: '#ffdad2',
867
+ 95: '#ffece8',
868
+ 100: '#ffffff',
869
+ },
870
+ warning: {
871
+ 0: '#000000',
872
+ 5: '#270c00',
873
+ 10: '#301800',
874
+ 15: '#3b2200',
875
+ 20: '#472c00',
876
+ 25: '#543700',
877
+ 30: '#614200',
878
+ 35: '#6f4d00',
879
+ 40: '#7d5800',
880
+ 45: '#8b6400',
881
+ 50: '#9a7000',
882
+ 55: '#a97d00',
883
+ 60: '#b88900',
884
+ 65: '#c89600',
885
+ 70: '#d8a300',
886
+ 75: '#e7b100',
887
+ 80: '#f7be00',
888
+ 85: '#ffcd51',
889
+ 90: '#ffde9c',
890
+ 95: '#ffeed0',
891
+ 100: '#ffffff',
892
+ },
893
+ success: {
894
+ 0: '#000000',
895
+ 5: '#001a00',
896
+ 10: '#092300',
897
+ 15: '#0b2e00',
898
+ 20: '#043b00',
899
+ 25: '#004700',
900
+ 30: '#005400',
901
+ 35: '#036100',
902
+ 40: '#136e00',
903
+ 45: '#277b00',
904
+ 50: '#448700',
905
+ 55: '#529400',
906
+ 60: '#60a105',
907
+ 65: '#6eaf1d',
908
+ 70: '#7cbd2e',
909
+ 75: '#8bcb3c',
910
+ 80: '#99d94b',
911
+ 85: '#a7e758',
912
+ 90: '#b5f566',
913
+ 95: '#ccff88',
914
+ 100: '#ffffff',
915
+ },
916
+ } as const;