fractalstyler2 0.1.0 → 0.3.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 (58) hide show
  1. package/README.md +60 -58
  2. package/dist/cli.js +47 -9
  3. package/dist/index.d.ts +32 -1
  4. package/dist/index.js +73 -4
  5. package/dist/mcp/export.d.ts +13 -0
  6. package/dist/mcp/export.js +76 -0
  7. package/dist/mcp/schemas/compile_fractals.json +20 -0
  8. package/dist/mcp/schemas/css_to_fractals.json +16 -0
  9. package/dist/mcp/schemas/generate_component.json +45 -0
  10. package/dist/mcp/schemas/get_design_tokens.json +23 -0
  11. package/dist/mcp/schemas/instructions.md +18 -0
  12. package/dist/mcp/schemas/list_fractals.json +20 -0
  13. package/dist/mcp/schemas/snap_to_tokens.json +25 -0
  14. package/dist/mcp/schemas/validate_recipe.json +16 -0
  15. package/dist/mcp/server.js +28 -12
  16. package/dist/styles/_00_tokens.sass +177 -0
  17. package/{templates/_config.sass → dist/styles/_01_config.sass} +11 -5
  18. package/dist/styles/_02_fonts.sass +13 -0
  19. package/dist/styles/_03_responsive.sass +31 -0
  20. package/dist/styles/{_atoms.sass → _04_atoms.sass} +4 -4
  21. package/{templates/_molecules.sass → dist/styles/_05_molecules.sass} +16 -12
  22. package/dist/styles/_06_recipes.sass +189 -0
  23. package/dist/styles/{_base.sass → _07_base.sass} +3 -2
  24. package/dist/styles/_08_blocks.sass +433 -0
  25. package/dist/styles/{_utilities.sass → _09_utilities.sass} +96 -16
  26. package/dist/styles/_10_layouts.sass +373 -0
  27. package/dist/styles/_11_own.sass +21 -0
  28. package/dist/styles/_fractals.sass +7 -6
  29. package/dist/styles/index.sass +14 -16
  30. package/mcp.json +11 -0
  31. package/package.json +6 -3
  32. package/plugin.json +22 -0
  33. package/skills/fractal-styler/SKILL.md +83 -0
  34. package/skills/fractal-styler/references/fractals.md +28 -0
  35. package/skills/fractal-styler/references/tokens.md +36 -0
  36. package/skills/style-migration/SKILL.md +45 -0
  37. package/templates/_00_tokens.sass +177 -0
  38. package/{dist/styles/_config.sass → templates/_01_config.sass} +11 -5
  39. package/templates/_02_fonts.sass +13 -0
  40. package/templates/_03_responsive.sass +31 -0
  41. package/templates/{_atoms.sass → _04_atoms.sass} +4 -4
  42. package/{dist/styles/_molecules.sass → templates/_05_molecules.sass} +16 -12
  43. package/templates/_06_recipes.sass +189 -0
  44. package/templates/{_base.sass → _07_base.sass} +3 -2
  45. package/templates/_08_blocks.sass +433 -0
  46. package/templates/{_utilities.sass → _09_utilities.sass} +96 -16
  47. package/templates/_10_layouts.sass +373 -0
  48. package/templates/_11_own.sass +21 -0
  49. package/templates/_fractals.sass +7 -6
  50. package/templates/index.sass +14 -16
  51. package/dist/styles/_blocks.sass +0 -88
  52. package/dist/styles/_layouts.sass +0 -108
  53. package/dist/styles/_responsive.sass +0 -43
  54. package/dist/styles/_tokens.sass +0 -127
  55. package/templates/_blocks.sass +0 -88
  56. package/templates/_layouts.sass +0 -108
  57. package/templates/_responsive.sass +0 -43
  58. package/templates/_tokens.sass +0 -127
@@ -0,0 +1,189 @@
1
+ // =============================================================================
2
+ // 06_RECIPES — macro mixins. Compositions of molecules and atoms.
3
+ // -----------------------------------------------------------------------------
4
+ // Recipes are mixins, NOT locked CSS classes. They take arguments and allow
5
+ // custom components to compose standard patterns with flexible parameters.
6
+ // =============================================================================
7
+
8
+ @use '01_config' as *
9
+ @use '04_atoms' as *
10
+ @use '05_molecules' as *
11
+
12
+ // Universal interactive control primitive (Button, Select trigger, Accordion header)
13
+ =control($size: md, $radius: 4)
14
+ +row(null, center)
15
+ +gap(2xs)
16
+ +radius($radius)
17
+ +border(all, var(--border))
18
+ +bg(surface)
19
+ +ink(primary)
20
+ +weight(500)
21
+ user-select: none
22
+ cursor: pointer
23
+ text-decoration: none
24
+ transition: background 120ms ease, border-color 120ms ease, transform 80ms ease
25
+
26
+ @if $size == sm
27
+ height: var(--control-h-sm, 26px)
28
+ +px(2xs)
29
+ +type(xs)
30
+ @else if $size == lg
31
+ height: var(--control-h-lg, 38px)
32
+ +px(s)
33
+ +type(md)
34
+ @else
35
+ height: var(--control-h-md, 32px)
36
+ +px(xs)
37
+ +type(sm)
38
+
39
+ &:hover
40
+ +bg(raised)
41
+ border-color: var(--border-subtle)
42
+
43
+ &:active
44
+ transform: scale(0.985)
45
+
46
+ &:focus-visible
47
+ +ring
48
+
49
+ &:disabled, &[aria-disabled='true']
50
+ opacity: 0.5
51
+ cursor: not-allowed
52
+ pointer-events: none
53
+
54
+ // Select input recipe (with embedded SVG chevron and optical line-height)
55
+ =select($size: md, $radius: 4)
56
+ +control($size, $radius)
57
+ appearance: none
58
+ -webkit-appearance: none
59
+ padding-right: 28px
60
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%237F91AA' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E")
61
+ background-repeat: no-repeat
62
+ background-position: right 8px center
63
+ line-height: 1.2
64
+ cursor: pointer
65
+ width: 100%
66
+
67
+ // Partition divider recipe with guaranteed breathing room
68
+ =partition($side: top, $pad: s)
69
+ @if $side == top
70
+ margin-top: auto
71
+ padding-top: space($pad)
72
+ border-top: 1px solid var(--border)
73
+ @else if $side == bottom
74
+ margin-bottom: space($pad)
75
+ padding-bottom: space($pad)
76
+ border-bottom: 1px solid var(--border)
77
+
78
+ // Pure CSS collapsible transition (0fr -> 1fr grid transition)
79
+ =collapsible
80
+ display: grid
81
+ grid-template-rows: 0fr
82
+ transition: grid-template-rows 140ms cubic-bezier(0.16, 1, 0.3, 1)
83
+
84
+ &[data-open='true'], &[aria-expanded='true']
85
+ grid-template-rows: 1fr
86
+
87
+ > .collapsible-inner
88
+ overflow: hidden
89
+ min-height: 0
90
+
91
+ // Marquee animation recipe
92
+ =marquee($speed: 30s, $gap: 1rem)
93
+ overflow: hidden
94
+ display: flex
95
+ user-select: none
96
+ gap: $gap
97
+ position: relative
98
+
99
+ &[data-fade='true']
100
+ mask-image: linear-gradient(to right, transparent 0%, black 10%, black 90%, transparent 100%)
101
+
102
+ > [data-slot='marquee-track']
103
+ display: flex
104
+ flex-shrink: 0
105
+ justify-content: space-around
106
+ gap: $gap
107
+ min-width: 100%
108
+ animation: marquee-scroll $speed linear infinite
109
+
110
+ &[data-pause='true']:hover > [data-slot='marquee-track']
111
+ animation-play-state: paused
112
+
113
+ // Card recipe — surface material + top-anchored vertical stack
114
+ =card($bg: surface, $pad: null, $radius: 6, $elevation: none)
115
+ +surface($bg, $pad, $radius, $elevation)
116
+ +box(stretch, start)
117
+ +gap(s)
118
+ height: 100%
119
+ text-align: left
120
+
121
+ // Button recipe
122
+ =button($size: md, $radius: 4)
123
+ +control($size, $radius)
124
+ justify-content: center
125
+
126
+ // Badge recipe — compact pill chip with subtle border
127
+ =badge
128
+ +row(center, center)
129
+ display: inline-flex
130
+ +gap(3xs)
131
+ +px(2xs)
132
+ +type(xs)
133
+ +weight(500)
134
+ +radius(3)
135
+ +bg(raised)
136
+ +ink(secondary)
137
+ +border(all, var(--border))
138
+ padding-block: 2px
139
+
140
+ // Input recipe — text entry field
141
+ =input
142
+ display: block
143
+ +w(100%)
144
+ +px(xs)
145
+ +type(sm)
146
+ +leading(1.5)
147
+ +border(all, var(--border))
148
+ +radius(4)
149
+ +bg(input)
150
+ +ink(primary)
151
+ height: var(--control-h-md, 32px)
152
+ transition: border-color 120ms ease, box-shadow 120ms ease
153
+ &:focus-visible, &:focus
154
+ outline: none
155
+ border-color: var(--theme-color)
156
+ box-shadow: 0 0 0 2px var(--ring)
157
+
158
+ // Keycap recipe
159
+ =kbd
160
+ display: inline-block
161
+ +px(3xs)
162
+ +type(xs)
163
+ +leading(1)
164
+ +radius(3)
165
+ +bg(raised)
166
+ border: 1px solid var(--border)
167
+ font-family: var(--font-mono)
168
+ padding-block: 2px
169
+
170
+ // Overlay & Dialog surfaces
171
+ =dialog-surface
172
+ +bg(dialog)
173
+ +border(all, var(--border))
174
+ +radius(6)
175
+ +shadow(lg)
176
+ max-width: min(92vw, 540px)
177
+ width: 100%
178
+
179
+ =popover-surface
180
+ +bg(popover)
181
+ +border(all, var(--border))
182
+ +radius(6)
183
+ +shadow(md)
184
+
185
+ // Divider recipe
186
+ =divider
187
+ border: none
188
+ +border(top)
189
+ margin-block: space(s)
@@ -1,5 +1,5 @@
1
1
  // =============================================================================
2
- // BASE — a minimal, opinionated reset so the tokens actually reach the page.
2
+ // 07_BASE — a minimal, opinionated reset so the tokens actually reach the page.
3
3
  // Kept tiny: box model, sane media defaults, and wiring body to the palette.
4
4
  // =============================================================================
5
5
 
@@ -8,6 +8,7 @@
8
8
 
9
9
  html
10
10
  -webkit-text-size-adjust: 100%
11
+ font-family: var(--font-sans)
11
12
 
12
13
  body
13
14
  margin: 0
@@ -32,7 +33,7 @@ body
32
33
 
33
34
  :where(a)
34
35
  color: inherit
35
- text-decoration-color: var(--border-strong)
36
+ text-decoration-color: var(--border-subtle)
36
37
 
37
38
  :where(button, input, select, textarea)
38
39
  font: inherit
@@ -0,0 +1,433 @@
1
+ // =============================================================================
2
+ // 08_BLOCKS — baseline semantic classes composed from fractal recipes.
3
+ // -----------------------------------------------------------------------------
4
+ // Blocks provide convenient markup classes without locking down arbitrary
5
+ // paddings or scale tokens. State is expressed via data-*/aria-* attributes.
6
+ // =============================================================================
7
+
8
+ @use 'fractals' as *
9
+
10
+ .surface
11
+ +surface(surface, null, 6)
12
+ +box(stretch, start)
13
+ &[data-role='raised']
14
+ +bg(raised)
15
+ &[data-role='bg']
16
+ +bg(bg)
17
+ &[data-role='panel']
18
+ +bg(panel)
19
+ &[data-role='popover']
20
+ +bg(popover)
21
+ &[data-role='dialog']
22
+ +bg(dialog)
23
+
24
+ .card
25
+ +card($pad: null, $radius: 6)
26
+ &[data-elevated]
27
+ +shadow(md)
28
+ > :is(footer, .card-footer, .meta-bottom)
29
+ margin-top: auto
30
+ padding-top: var(--space-xs)
31
+ border-top: 1px solid var(--border)
32
+
33
+ .panel
34
+ +surface(panel, null, 4)
35
+
36
+ .popover
37
+ +surface(popover, null, 6, md)
38
+
39
+ .dialog
40
+ +surface(dialog, null, 6, lg)
41
+
42
+ .terminal
43
+ +surface(terminal, null, 4)
44
+ font-family: var(--font-mono)
45
+ color: var(--text-inverse)
46
+
47
+ .canvas
48
+ +bg(canvas)
49
+
50
+ .badge
51
+ +badge
52
+ &[data-status='released']
53
+ color: var(--theme-color)
54
+ background: rgba(16, 185, 129, 0.1)
55
+ border-color: rgba(16, 185, 129, 0.25)
56
+ &[data-status='wip']
57
+ color: #d97706
58
+ background: rgba(245, 158, 11, 0.1)
59
+ border-color: rgba(245, 158, 11, 0.25)
60
+ &[data-status='archived']
61
+ +ink(muted)
62
+ &[data-status='planned']
63
+ color: #6366f1
64
+ background: rgba(99, 102, 241, 0.1)
65
+ border-color: rgba(99, 102, 241, 0.25)
66
+
67
+ .avatar
68
+ +center
69
+ +square(var(--avatar-size, 40px))
70
+ +radius(full)
71
+ +bg(raised)
72
+ +ink(secondary)
73
+ +border(all, var(--border))
74
+ overflow: hidden
75
+
76
+ .input
77
+ +input
78
+
79
+ .select
80
+ +select(md)
81
+ &.sm
82
+ +select(sm)
83
+ &.lg
84
+ +select(lg)
85
+
86
+ .divider
87
+ +divider
88
+
89
+ .kbd
90
+ +kbd
91
+
92
+ .button
93
+ +button(md, 4)
94
+ background: var(--bg-surface)
95
+ &.sm
96
+ +control(sm, 4)
97
+ justify-content: center
98
+ &.lg
99
+ +control(lg, 4)
100
+ justify-content: center
101
+ &.primary
102
+ background: var(--theme-color)
103
+ color: var(--text-inverse)
104
+ border-color: var(--theme-color)
105
+ &:hover
106
+ background: var(--theme-color-alt)
107
+ border-color: var(--theme-color-alt)
108
+ &.ghost
109
+ background: transparent
110
+ +ink(secondary)
111
+ border-color: var(--border)
112
+ &:hover
113
+ +bg(raised)
114
+ +ink(primary)
115
+ border-color: var(--border-subtle)
116
+ &[data-active]
117
+ +bg(bg)
118
+ +ink(primary)
119
+ border-color: var(--border-subtle)
120
+ +shadow(sm)
121
+
122
+ button.is-icon, a.is-icon
123
+ +row(center, center)
124
+ background: none
125
+ border: none
126
+ padding: 0
127
+ +ink(secondary)
128
+ cursor: pointer
129
+ text-decoration: none
130
+ transition: color 120ms ease
131
+ &:hover
132
+ +ink(primary)
133
+ svg
134
+ height: 16px
135
+ width: 16px
136
+
137
+ // --- Accordion ---------------------------------------------------------------
138
+ .accordion
139
+ +box
140
+ +border(all, var(--border))
141
+ +radius(6)
142
+ +bg(surface)
143
+ overflow: hidden
144
+
145
+ .accordion-item
146
+ +border(bottom, var(--border))
147
+ &:last-child
148
+ border-bottom: none
149
+
150
+ .accordion-trigger
151
+ +row(between, center)
152
+ width: 100%
153
+ padding: var(--space-xs) var(--space-s)
154
+ +bg(surface)
155
+ +ink(primary)
156
+ +type(sm)
157
+ +weight(500)
158
+ border: none
159
+ cursor: pointer
160
+ user-select: none
161
+ text-align: left
162
+ transition: background 120ms ease
163
+ &:hover
164
+ +bg(raised)
165
+ .accordion-icon
166
+ transition: transform 140ms ease
167
+ +ink(muted)
168
+
169
+ .accordion-item[data-open='true']
170
+ .accordion-trigger .accordion-icon
171
+ transform: rotate(180deg)
172
+ +ink(primary)
173
+
174
+ .accordion-content
175
+ +collapsible
176
+ .accordion-body
177
+ padding: 0 var(--space-s) var(--space-s) var(--space-s)
178
+ +type(sm)
179
+ +ink(secondary)
180
+ line-height: 1.6
181
+
182
+ // --- Dialog Modal ------------------------------------------------------------
183
+ dialog.dialog-modal
184
+ position: fixed
185
+ inset: 0
186
+ margin: auto
187
+ border: none
188
+ background: transparent
189
+ padding: 0
190
+ max-width: min(92vw, 520px)
191
+ width: 100%
192
+ z-index: var(--z-modal, 200)
193
+
194
+ &::backdrop
195
+ background: rgba(0, 0, 0, 0.55)
196
+ backdrop-filter: blur(4px)
197
+ -webkit-backdrop-filter: blur(4px)
198
+
199
+ > .dialog-card
200
+ +dialog-surface
201
+ +box
202
+ +gap(m)
203
+ +pad(m)
204
+
205
+ // --- Drawer ------------------------------------------------------------------
206
+ .drawer
207
+ position: fixed
208
+ top: 0
209
+ bottom: 0
210
+ z-index: var(--z-modal, 200)
211
+ width: min(85vw, 360px)
212
+ +bg(surface)
213
+ +border(all, var(--border))
214
+ +shadow(lg)
215
+ transition: transform 200ms ease-out
216
+ &.right
217
+ right: 0
218
+ transform: translateX(105%)
219
+ +border(left, var(--border))
220
+ &.left
221
+ left: 0
222
+ transform: translateX(-105%)
223
+ +border(right, var(--border))
224
+ &[data-open='true']
225
+ transform: translateX(0)
226
+
227
+ // --- Tabs --------------------------------------------------------------------
228
+ .tab-list
229
+ +row(null, center)
230
+ +gap(3xs)
231
+ +pad(3xs)
232
+ +radius(4)
233
+ +bg(raised)
234
+ width: fit-content
235
+ max-width: 100%
236
+
237
+ .tab-trigger
238
+ +row(center, center)
239
+ +px(xs)
240
+ +type(xs)
241
+ +weight(500)
242
+ +radius(3)
243
+ height: var(--control-h-sm, 26px)
244
+ border: none
245
+ background: transparent
246
+ +ink(secondary)
247
+ cursor: pointer
248
+ user-select: none
249
+ white-space: nowrap
250
+ transition: all 120ms ease
251
+ &:hover
252
+ +ink(primary)
253
+ &[data-active='true'], &[aria-selected='true']
254
+ +bg(surface)
255
+ +ink(primary)
256
+ +border(all, var(--border))
257
+ +shadow(sm)
258
+
259
+ // --- Switch ------------------------------------------------------------------
260
+ .switch-track
261
+ position: relative
262
+ display: inline-flex
263
+ align-items: center
264
+ flex-shrink: 0
265
+ width: 36px
266
+ height: 20px
267
+ +radius(full)
268
+ +bg(raised)
269
+ +border(all, var(--border))
270
+ cursor: pointer
271
+ user-select: none
272
+ padding: 2px
273
+ transition: background 140ms ease, border-color 140ms ease
274
+
275
+ &[data-checked='true']
276
+ background: var(--theme-color)
277
+ border-color: var(--theme-color)
278
+
279
+ .switch-thumb
280
+ display: block
281
+ width: 14px
282
+ height: 14px
283
+ +radius(full)
284
+ background: var(--text-primary)
285
+ transition: transform 140ms cubic-bezier(0.34, 1.56, 0.64, 1), background 140ms ease
286
+ will-change: transform
287
+
288
+ .switch-track[data-checked='true'] .switch-thumb
289
+ transform: translateX(16px)
290
+ background: var(--text-inverse)
291
+
292
+ // --- Field -------------------------------------------------------------------
293
+ .field
294
+ +box
295
+ +gap(3xs)
296
+ width: 100%
297
+
298
+ .field-label
299
+ +type(xs)
300
+ +weight(600)
301
+ text-transform: uppercase
302
+ letter-spacing: 0.05em
303
+ +ink(secondary)
304
+
305
+ .field-error
306
+ +type(xs)
307
+ color: #dc2626
308
+ margin-top: 2px
309
+
310
+ // --- Marquee -----------------------------------------------------------------
311
+ .marquee, [data-slot="marquee"]
312
+ overflow: hidden
313
+ display: flex
314
+ user-select: none
315
+ gap: var(--marquee-gap, 1rem)
316
+ position: relative
317
+ width: 100%
318
+
319
+ &[data-fade="true"]
320
+ mask-image: linear-gradient(to right, transparent 0%, black 10%, black 90%, transparent 100%)
321
+
322
+ [data-slot="marquee-track"]
323
+ display: flex
324
+ flex-shrink: 0
325
+ justify-content: space-around
326
+ gap: var(--marquee-gap, 1rem)
327
+ min-width: 100%
328
+ animation: marquee-scroll var(--marquee-speed, 30s) linear infinite
329
+
330
+ &[data-pause="true"]:hover [data-slot="marquee-track"]
331
+ animation-play-state: paused
332
+
333
+ &[data-vertical="true"]
334
+ flex-direction: column
335
+ height: 300px
336
+ &[data-fade="true"]
337
+ mask-image: linear-gradient(to bottom, transparent 0%, black 10%, black 90%, transparent 100%)
338
+ [data-slot="marquee-track"]
339
+ flex-direction: column
340
+ min-height: 100%
341
+ animation-name: marquee-scroll-vertical
342
+
343
+ @keyframes marquee-scroll
344
+ from
345
+ transform: translateX(0)
346
+ to
347
+ transform: translateX(calc(-100% - var(--marquee-gap, 1rem)))
348
+
349
+ @keyframes marquee-scroll-vertical
350
+ from
351
+ transform: translateY(0)
352
+ to
353
+ transform: translateY(calc(-100% - var(--marquee-gap, 1rem)))
354
+
355
+ // --- Animated Badge ----------------------------------------------------------
356
+ [data-slot="badge"]
357
+ position: relative
358
+ display: inline-flex
359
+ align-items: center
360
+ overflow: hidden
361
+ border: 1px solid var(--border)
362
+ border-radius: var(--radius-full)
363
+ font-weight: 500
364
+ white-space: nowrap
365
+ color: var(--text-secondary)
366
+ background: var(--bg-surface)
367
+
368
+ &[data-size="sm"]
369
+ height: 1.5rem
370
+ gap: var(--space-3xs)
371
+ padding: 0 var(--space-2xs)
372
+ font-size: var(--text-xs)
373
+ &[data-size="md"]
374
+ height: 1.75rem
375
+ gap: var(--space-2xs)
376
+ padding: 0 var(--space-xs)
377
+ font-size: var(--text-xs)
378
+
379
+ &[data-status="info"], &[data-status="loading"]
380
+ border-color: var(--theme-color)
381
+ color: var(--theme-color)
382
+ background: var(--bg-raised)
383
+ &[data-status="success"]
384
+ border-color: #10b981
385
+ color: #10b981
386
+ &[data-status="warning"]
387
+ border-color: #f59e0b
388
+ color: #f59e0b
389
+ &[data-status="danger"]
390
+ border-color: #ef4444
391
+ color: #ef4444
392
+
393
+ [data-slot="badge-icon"], [data-slot="badge-label"]
394
+ position: relative
395
+ z-index: 1
396
+ display: inline-flex
397
+ animation: badge-roll 0.42s cubic-bezier(0.16, 1, 0.3, 1)
398
+
399
+ [data-slot="badge-icon"]
400
+ align-items: center
401
+ justify-content: center
402
+
403
+ [data-status="loading"] [data-slot="badge-icon"]
404
+ animation: badge-spin 1s linear infinite
405
+
406
+ [data-slot="badge-pulse"]
407
+ position: absolute
408
+ inset: 0
409
+ border-radius: inherit
410
+ background: currentColor
411
+ animation: badge-pulse 1.6s ease-in-out infinite
412
+
413
+ @keyframes badge-roll
414
+ from
415
+ transform: translateY(80%)
416
+ opacity: 0
417
+ filter: blur(4px)
418
+
419
+ @keyframes badge-spin
420
+ to
421
+ transform: rotate(360deg)
422
+
423
+ @keyframes badge-pulse
424
+ 0%, 100%
425
+ opacity: 0.08
426
+ transform: scale(0.94)
427
+ 50%
428
+ opacity: 0.18
429
+ transform: scale(1.08)
430
+
431
+ @media (prefers-reduced-motion: reduce)
432
+ [data-slot="badge-icon"], [data-slot="badge-label"], [data-slot="badge-pulse"], [data-slot="marquee-track"]
433
+ animation: none !important