@pikacss/core 0.0.51 → 0.0.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- //#region src/internal/generated-shorthand-map.ts
1
+ //#region src/generated/property-effects.ts
2
2
  const PROPERTY_EFFECTS = {
3
3
  "accent-color": ["accent-color"],
4
4
  "align-content": ["align-content"],
@@ -17,8 +17,11 @@ const PROPERTY_EFFECTS = {
17
17
  "animation-iteration-count",
18
18
  "animation-name",
19
19
  "animation-play-state",
20
+ "animation-range-end",
21
+ "animation-range-start",
20
22
  "animation-timeline",
21
- "animation-timing-function"
23
+ "animation-timing-function",
24
+ "animation-trigger"
22
25
  ],
23
26
  "animation-composition": ["animation-composition"],
24
27
  "animation-delay": ["animation-delay"],
@@ -29,6 +32,7 @@ const PROPERTY_EFFECTS = {
29
32
  "animation-name": ["animation-name"],
30
33
  "animation-play-state": ["animation-play-state"],
31
34
  "animation-range": ["animation-range-end", "animation-range-start"],
35
+ "animation-range-center": ["animation-range-center"],
32
36
  "animation-range-end": ["animation-range-end"],
33
37
  "animation-range-start": ["animation-range-start"],
34
38
  "animation-timeline": ["animation-timeline"],
@@ -40,6 +44,7 @@ const PROPERTY_EFFECTS = {
40
44
  "backface-visibility": ["backface-visibility"],
41
45
  "background": [
42
46
  "background-attachment",
47
+ "background-blend-mode",
43
48
  "background-clip",
44
49
  "background-color",
45
50
  "background-image",
@@ -56,18 +61,44 @@ const PROPERTY_EFFECTS = {
56
61
  "background-image": ["background-image"],
57
62
  "background-origin": ["background-origin"],
58
63
  "background-position": ["background-position-x", "background-position-y"],
64
+ "background-position-block": ["background-position-block"],
65
+ "background-position-inline": ["background-position-inline"],
59
66
  "background-position-x": ["background-position-x"],
60
67
  "background-position-y": ["background-position-y"],
61
68
  "background-repeat": ["background-repeat"],
69
+ "background-repeat-block": ["background-repeat-block"],
70
+ "background-repeat-inline": ["background-repeat-inline"],
71
+ "background-repeat-x": ["background-repeat-x"],
72
+ "background-repeat-y": ["background-repeat-y"],
62
73
  "background-size": ["background-size"],
74
+ "background-tbd": ["background-tbd"],
63
75
  "baseline-shift": ["baseline-shift"],
64
76
  "baseline-source": ["baseline-source"],
77
+ "block-ellipsis": ["block-ellipsis"],
65
78
  "block-size": ["block-size"],
79
+ "block-step": [
80
+ "block-step-align",
81
+ "block-step-insert",
82
+ "block-step-round",
83
+ "block-step-size"
84
+ ],
85
+ "block-step-align": ["block-step-align"],
86
+ "block-step-insert": ["block-step-insert"],
87
+ "block-step-round": ["block-step-round"],
88
+ "block-step-size": ["block-step-size"],
89
+ "bookmark-label": ["bookmark-label"],
90
+ "bookmark-level": ["bookmark-level"],
91
+ "bookmark-state": ["bookmark-state"],
66
92
  "border": [
67
93
  "border-bottom-color",
68
94
  "border-left-color",
69
95
  "border-right-color",
70
96
  "border-top-color",
97
+ "border-image-outset",
98
+ "border-image-repeat",
99
+ "border-image-slice",
100
+ "border-image-source",
101
+ "border-image-width",
71
102
  "border-bottom-style",
72
103
  "border-left-style",
73
104
  "border-right-style",
@@ -79,19 +110,22 @@ const PROPERTY_EFFECTS = {
79
110
  ],
80
111
  "border-block": [
81
112
  "border-block-end-color",
82
- "border-block-start-color",
83
113
  "border-block-end-style",
84
- "border-block-start-style",
85
114
  "border-block-end-width",
115
+ "border-block-start-color",
116
+ "border-block-start-style",
86
117
  "border-block-start-width"
87
118
  ],
119
+ "border-block-clip": ["border-block-end-clip", "border-block-start-clip"],
88
120
  "border-block-color": ["border-block-end-color", "border-block-start-color"],
89
121
  "border-block-end": [
90
122
  "border-block-end-color",
91
123
  "border-block-end-style",
92
124
  "border-block-end-width"
93
125
  ],
126
+ "border-block-end-clip": ["border-block-end-clip"],
94
127
  "border-block-end-color": ["border-block-end-color"],
128
+ "border-block-end-radius": ["border-end-end-radius", "border-end-start-radius"],
95
129
  "border-block-end-style": ["border-block-end-style"],
96
130
  "border-block-end-width": ["border-block-end-width"],
97
131
  "border-block-start": [
@@ -99,7 +133,9 @@ const PROPERTY_EFFECTS = {
99
133
  "border-block-start-style",
100
134
  "border-block-start-width"
101
135
  ],
136
+ "border-block-start-clip": ["border-block-start-clip"],
102
137
  "border-block-start-color": ["border-block-start-color"],
138
+ "border-block-start-radius": ["border-start-end-radius", "border-start-start-radius"],
103
139
  "border-block-start-style": ["border-block-start-style"],
104
140
  "border-block-start-width": ["border-block-start-width"],
105
141
  "border-block-style": ["border-block-end-style", "border-block-start-style"],
@@ -109,11 +145,20 @@ const PROPERTY_EFFECTS = {
109
145
  "border-bottom-style",
110
146
  "border-bottom-width"
111
147
  ],
148
+ "border-bottom-clip": ["border-bottom-clip"],
112
149
  "border-bottom-color": ["border-bottom-color"],
113
150
  "border-bottom-left-radius": ["border-bottom-left-radius"],
151
+ "border-bottom-radius": ["border-bottom-left-radius", "border-bottom-right-radius"],
114
152
  "border-bottom-right-radius": ["border-bottom-right-radius"],
115
153
  "border-bottom-style": ["border-bottom-style"],
116
154
  "border-bottom-width": ["border-bottom-width"],
155
+ "border-boundary": ["border-boundary"],
156
+ "border-clip": [
157
+ "border-bottom-clip",
158
+ "border-left-clip",
159
+ "border-right-clip",
160
+ "border-top-clip"
161
+ ],
117
162
  "border-collapse": ["border-collapse"],
118
163
  "border-color": [
119
164
  "border-bottom-color",
@@ -137,19 +182,22 @@ const PROPERTY_EFFECTS = {
137
182
  "border-image-width": ["border-image-width"],
138
183
  "border-inline": [
139
184
  "border-inline-end-color",
140
- "border-inline-start-color",
141
185
  "border-inline-end-style",
142
- "border-inline-start-style",
143
186
  "border-inline-end-width",
187
+ "border-inline-start-color",
188
+ "border-inline-start-style",
144
189
  "border-inline-start-width"
145
190
  ],
191
+ "border-inline-clip": ["border-inline-end-clip", "border-inline-start-clip"],
146
192
  "border-inline-color": ["border-inline-end-color", "border-inline-start-color"],
147
193
  "border-inline-end": [
148
194
  "border-inline-end-color",
149
195
  "border-inline-end-style",
150
196
  "border-inline-end-width"
151
197
  ],
198
+ "border-inline-end-clip": ["border-inline-end-clip"],
152
199
  "border-inline-end-color": ["border-inline-end-color"],
200
+ "border-inline-end-radius": ["border-end-end-radius", "border-start-end-radius"],
153
201
  "border-inline-end-style": ["border-inline-end-style"],
154
202
  "border-inline-end-width": ["border-inline-end-width"],
155
203
  "border-inline-start": [
@@ -157,7 +205,9 @@ const PROPERTY_EFFECTS = {
157
205
  "border-inline-start-style",
158
206
  "border-inline-start-width"
159
207
  ],
208
+ "border-inline-start-clip": ["border-inline-start-clip"],
160
209
  "border-inline-start-color": ["border-inline-start-color"],
210
+ "border-inline-start-radius": ["border-end-start-radius", "border-start-start-radius"],
161
211
  "border-inline-start-style": ["border-inline-start-style"],
162
212
  "border-inline-start-width": ["border-inline-start-width"],
163
213
  "border-inline-style": ["border-inline-end-style", "border-inline-start-style"],
@@ -167,9 +217,12 @@ const PROPERTY_EFFECTS = {
167
217
  "border-left-style",
168
218
  "border-left-width"
169
219
  ],
220
+ "border-left-clip": ["border-left-clip"],
170
221
  "border-left-color": ["border-left-color"],
222
+ "border-left-radius": ["border-bottom-left-radius", "border-top-left-radius"],
171
223
  "border-left-style": ["border-left-style"],
172
224
  "border-left-width": ["border-left-width"],
225
+ "border-limit": ["border-limit"],
173
226
  "border-radius": [
174
227
  "border-bottom-left-radius",
175
228
  "border-bottom-right-radius",
@@ -181,9 +234,12 @@ const PROPERTY_EFFECTS = {
181
234
  "border-right-style",
182
235
  "border-right-width"
183
236
  ],
237
+ "border-right-clip": ["border-right-clip"],
184
238
  "border-right-color": ["border-right-color"],
239
+ "border-right-radius": ["border-bottom-right-radius", "border-top-right-radius"],
185
240
  "border-right-style": ["border-right-style"],
186
241
  "border-right-width": ["border-right-width"],
242
+ "border-shape": ["border-shape"],
187
243
  "border-spacing": ["border-spacing"],
188
244
  "border-start-end-radius": ["border-start-end-radius"],
189
245
  "border-start-start-radius": ["border-start-start-radius"],
@@ -198,8 +254,10 @@ const PROPERTY_EFFECTS = {
198
254
  "border-top-style",
199
255
  "border-top-width"
200
256
  ],
257
+ "border-top-clip": ["border-top-clip"],
201
258
  "border-top-color": ["border-top-color"],
202
259
  "border-top-left-radius": ["border-top-left-radius"],
260
+ "border-top-radius": ["border-top-left-radius", "border-top-right-radius"],
203
261
  "border-top-right-radius": ["border-top-right-radius"],
204
262
  "border-top-style": ["border-top-style"],
205
263
  "border-top-width": ["border-top-width"],
@@ -219,8 +277,20 @@ const PROPERTY_EFFECTS = {
219
277
  "box-ordinal-group": ["box-ordinal-group"],
220
278
  "box-orient": ["box-orient"],
221
279
  "box-pack": ["box-pack"],
222
- "box-shadow": ["box-shadow"],
280
+ "box-shadow": [
281
+ "box-shadow-blur",
282
+ "box-shadow-color",
283
+ "box-shadow-offset",
284
+ "box-shadow-position",
285
+ "box-shadow-spread"
286
+ ],
287
+ "box-shadow-blur": ["box-shadow-blur"],
288
+ "box-shadow-color": ["box-shadow-color"],
289
+ "box-shadow-offset": ["box-shadow-offset"],
290
+ "box-shadow-position": ["box-shadow-position"],
291
+ "box-shadow-spread": ["box-shadow-spread"],
223
292
  "box-sizing": ["box-sizing"],
293
+ "box-snap": ["box-snap"],
224
294
  "break-after": ["break-after"],
225
295
  "break-before": ["break-before"],
226
296
  "break-inside": ["break-inside"],
@@ -238,7 +308,10 @@ const PROPERTY_EFFECTS = {
238
308
  "clip-path": ["clip-path"],
239
309
  "clip-rule": ["clip-rule"],
240
310
  "color": ["color"],
311
+ "color-adjust": ["print-color-adjust"],
312
+ "color-interpolation": ["color-interpolation"],
241
313
  "color-interpolation-filters": ["color-interpolation-filters"],
314
+ "color-rendering": ["color-rendering"],
242
315
  "color-scheme": ["color-scheme"],
243
316
  "column-count": ["column-count"],
244
317
  "column-fill": ["column-fill"],
@@ -249,8 +322,24 @@ const PROPERTY_EFFECTS = {
249
322
  "column-rule-style",
250
323
  "column-rule-width"
251
324
  ],
325
+ "column-rule-break": ["column-rule-break"],
252
326
  "column-rule-color": ["column-rule-color"],
327
+ "column-rule-inset": [
328
+ "column-rule-inset-cap-end",
329
+ "column-rule-inset-cap-start",
330
+ "column-rule-inset-junction-end",
331
+ "column-rule-inset-junction-start"
332
+ ],
333
+ "column-rule-inset-cap": ["column-rule-inset-cap-end", "column-rule-inset-cap-start"],
334
+ "column-rule-inset-cap-end": ["column-rule-inset-cap-end"],
335
+ "column-rule-inset-cap-start": ["column-rule-inset-cap-start"],
336
+ "column-rule-inset-end": ["column-rule-inset-cap-end", "column-rule-inset-junction-end"],
337
+ "column-rule-inset-junction": ["column-rule-inset-junction-end", "column-rule-inset-junction-start"],
338
+ "column-rule-inset-junction-end": ["column-rule-inset-junction-end"],
339
+ "column-rule-inset-junction-start": ["column-rule-inset-junction-start"],
340
+ "column-rule-inset-start": ["column-rule-inset-cap-start", "column-rule-inset-junction-start"],
253
341
  "column-rule-style": ["column-rule-style"],
342
+ "column-rule-visibility-items": ["column-rule-visibility-items"],
254
343
  "column-rule-width": ["column-rule-width"],
255
344
  "column-span": ["column-span"],
256
345
  "column-width": ["column-width"],
@@ -271,16 +360,74 @@ const PROPERTY_EFFECTS = {
271
360
  "container-type": ["container-type"],
272
361
  "content": ["content"],
273
362
  "content-visibility": ["content-visibility"],
363
+ "continue": ["continue"],
364
+ "copy-into": ["copy-into"],
365
+ "corner": [
366
+ "border-bottom-left-radius",
367
+ "border-bottom-right-radius",
368
+ "border-top-left-radius",
369
+ "border-top-right-radius",
370
+ "corner-bottom-left-shape",
371
+ "corner-bottom-right-shape",
372
+ "corner-top-left-shape",
373
+ "corner-top-right-shape"
374
+ ],
375
+ "corner-block-end": [
376
+ "border-end-end-radius",
377
+ "border-end-start-radius",
378
+ "corner-end-end-shape",
379
+ "corner-end-start-shape"
380
+ ],
274
381
  "corner-block-end-shape": ["corner-end-end-shape", "corner-end-start-shape"],
382
+ "corner-block-start": [
383
+ "border-start-end-radius",
384
+ "border-start-start-radius",
385
+ "corner-start-end-shape",
386
+ "corner-start-start-shape"
387
+ ],
275
388
  "corner-block-start-shape": ["corner-start-end-shape", "corner-start-start-shape"],
389
+ "corner-bottom": [
390
+ "border-bottom-left-radius",
391
+ "border-bottom-right-radius",
392
+ "corner-bottom-left-shape",
393
+ "corner-bottom-right-shape"
394
+ ],
395
+ "corner-bottom-left": ["border-bottom-left-radius", "corner-bottom-left-shape"],
276
396
  "corner-bottom-left-shape": ["corner-bottom-left-shape"],
397
+ "corner-bottom-right": ["border-bottom-right-radius", "corner-bottom-right-shape"],
277
398
  "corner-bottom-right-shape": ["corner-bottom-right-shape"],
278
399
  "corner-bottom-shape": ["corner-bottom-left-shape", "corner-bottom-right-shape"],
400
+ "corner-end-end": ["border-end-end-radius", "corner-end-end-shape"],
279
401
  "corner-end-end-shape": ["corner-end-end-shape"],
402
+ "corner-end-start": ["border-end-start-radius", "corner-end-start-shape"],
280
403
  "corner-end-start-shape": ["corner-end-start-shape"],
404
+ "corner-inline-end": [
405
+ "border-end-end-radius",
406
+ "border-start-end-radius",
407
+ "corner-end-end-shape",
408
+ "corner-start-end-shape"
409
+ ],
281
410
  "corner-inline-end-shape": ["corner-end-end-shape", "corner-start-end-shape"],
282
- "corner-inline-start-shape": ["corner-start-end-shape", "corner-start-start-shape"],
411
+ "corner-inline-start": [
412
+ "border-end-start-radius",
413
+ "border-start-start-radius",
414
+ "corner-end-start-shape",
415
+ "corner-start-start-shape"
416
+ ],
417
+ "corner-inline-start-shape": ["corner-end-start-shape", "corner-start-start-shape"],
418
+ "corner-left": [
419
+ "border-bottom-left-radius",
420
+ "border-top-left-radius",
421
+ "corner-bottom-left-shape",
422
+ "corner-top-left-shape"
423
+ ],
283
424
  "corner-left-shape": ["corner-bottom-left-shape", "corner-top-left-shape"],
425
+ "corner-right": [
426
+ "border-bottom-right-radius",
427
+ "border-top-right-radius",
428
+ "corner-bottom-right-shape",
429
+ "corner-top-right-shape"
430
+ ],
284
431
  "corner-right-shape": ["corner-bottom-right-shape", "corner-top-right-shape"],
285
432
  "corner-shape": [
286
433
  "corner-bottom-left-shape",
@@ -288,14 +435,27 @@ const PROPERTY_EFFECTS = {
288
435
  "corner-top-left-shape",
289
436
  "corner-top-right-shape"
290
437
  ],
438
+ "corner-start-end": ["border-start-end-radius", "corner-start-end-shape"],
291
439
  "corner-start-end-shape": ["corner-start-end-shape"],
440
+ "corner-start-start": ["border-start-start-radius", "corner-start-start-shape"],
292
441
  "corner-start-start-shape": ["corner-start-start-shape"],
442
+ "corner-top": [
443
+ "border-top-left-radius",
444
+ "border-top-right-radius",
445
+ "corner-top-left-shape",
446
+ "corner-top-right-shape"
447
+ ],
448
+ "corner-top-left": ["border-top-left-radius", "corner-top-left-shape"],
293
449
  "corner-top-left-shape": ["corner-top-left-shape"],
450
+ "corner-top-right": ["border-top-right-radius", "corner-top-right-shape"],
294
451
  "corner-top-right-shape": ["corner-top-right-shape"],
295
452
  "corner-top-shape": ["corner-top-left-shape", "corner-top-right-shape"],
296
453
  "counter-increment": ["counter-increment"],
297
454
  "counter-reset": ["counter-reset"],
298
455
  "counter-set": ["counter-set"],
456
+ "cue": ["cue-after", "cue-before"],
457
+ "cue-after": ["cue-after"],
458
+ "cue-before": ["cue-before"],
299
459
  "cursor": ["cursor"],
300
460
  "cx": ["cx"],
301
461
  "cy": ["cy"],
@@ -305,10 +465,20 @@ const PROPERTY_EFFECTS = {
305
465
  "dominant-baseline": ["dominant-baseline"],
306
466
  "dynamic-range-limit": ["dynamic-range-limit"],
307
467
  "empty-cells": ["empty-cells"],
468
+ "event-trigger": ["event-trigger"],
469
+ "event-trigger-name": ["event-trigger-name"],
470
+ "event-trigger-source": ["event-trigger-source"],
308
471
  "field-sizing": ["field-sizing"],
309
472
  "fill": ["fill"],
473
+ "fill-break": ["fill-break"],
474
+ "fill-color": ["fill-color"],
475
+ "fill-image": ["fill-image"],
310
476
  "fill-opacity": ["fill-opacity"],
477
+ "fill-origin": ["fill-origin"],
478
+ "fill-position": ["fill-position"],
479
+ "fill-repeat": ["fill-repeat"],
311
480
  "fill-rule": ["fill-rule"],
481
+ "fill-size": ["fill-size"],
312
482
  "filter": ["filter"],
313
483
  "flex": [
314
484
  "flex-basis",
@@ -319,14 +489,26 @@ const PROPERTY_EFFECTS = {
319
489
  "flex-direction": ["flex-direction"],
320
490
  "flex-flow": ["flex-direction", "flex-wrap"],
321
491
  "flex-grow": ["flex-grow"],
492
+ "flex-line-count": ["flex-line-count"],
322
493
  "flex-shrink": ["flex-shrink"],
323
494
  "flex-wrap": ["flex-wrap"],
324
495
  "float": ["float"],
496
+ "float-defer": ["float-defer"],
497
+ "float-offset": ["float-offset"],
498
+ "float-reference": ["float-reference"],
325
499
  "flood-color": ["flood-color"],
326
500
  "flood-opacity": ["flood-opacity"],
501
+ "flow-from": ["flow-from"],
502
+ "flow-into": ["flow-into"],
503
+ "flow-tolerance": ["flow-tolerance"],
327
504
  "font": [
328
505
  "font-family",
506
+ "font-feature-settings",
507
+ "font-kerning",
508
+ "font-language-override",
509
+ "font-optical-sizing",
329
510
  "font-size",
511
+ "font-size-adjust",
330
512
  "font-stretch",
331
513
  "font-style",
332
514
  "font-variant-alternates",
@@ -336,6 +518,7 @@ const PROPERTY_EFFECTS = {
336
518
  "font-variant-ligatures",
337
519
  "font-variant-numeric",
338
520
  "font-variant-position",
521
+ "font-variation-settings",
339
522
  "font-weight",
340
523
  "line-height"
341
524
  ],
@@ -379,19 +562,19 @@ const PROPERTY_EFFECTS = {
379
562
  "font-variation-settings": ["font-variation-settings"],
380
563
  "font-weight": ["font-weight"],
381
564
  "font-width": ["font-width"],
565
+ "footnote-display": ["footnote-display"],
566
+ "footnote-policy": ["footnote-policy"],
382
567
  "forced-color-adjust": ["forced-color-adjust"],
568
+ "frame-sizing": ["frame-sizing"],
383
569
  "gap": ["column-gap", "row-gap"],
570
+ "glyph-orientation-vertical": ["glyph-orientation-vertical"],
384
571
  "grid": [
385
- "column-gap",
386
572
  "grid-auto-columns",
387
573
  "grid-auto-flow",
388
574
  "grid-auto-rows",
389
- "grid-column-gap",
390
- "grid-row-gap",
391
575
  "grid-template-areas",
392
576
  "grid-template-columns",
393
- "grid-template-rows",
394
- "row-gap"
577
+ "grid-template-rows"
395
578
  ],
396
579
  "grid-area": [
397
580
  "grid-column-end",
@@ -406,7 +589,7 @@ const PROPERTY_EFFECTS = {
406
589
  "grid-column-end": ["grid-column-end"],
407
590
  "grid-column-gap": ["grid-column-gap"],
408
591
  "grid-column-start": ["grid-column-start"],
409
- "grid-gap": ["grid-column-gap", "grid-row-gap"],
592
+ "grid-gap": ["column-gap", "row-gap"],
410
593
  "grid-row": ["grid-row-end", "grid-row-start"],
411
594
  "grid-row-end": ["grid-row-end"],
412
595
  "grid-row-gap": ["grid-row-gap"],
@@ -423,14 +606,21 @@ const PROPERTY_EFFECTS = {
423
606
  "height": ["height"],
424
607
  "hyphenate-character": ["hyphenate-character"],
425
608
  "hyphenate-limit-chars": ["hyphenate-limit-chars"],
609
+ "hyphenate-limit-last": ["hyphenate-limit-last"],
610
+ "hyphenate-limit-lines": ["hyphenate-limit-lines"],
611
+ "hyphenate-limit-zone": ["hyphenate-limit-zone"],
426
612
  "hyphens": ["hyphens"],
613
+ "image-animation": ["image-animation"],
427
614
  "image-orientation": ["image-orientation"],
428
615
  "image-rendering": ["image-rendering"],
429
616
  "image-resolution": ["image-resolution"],
430
617
  "ime-mode": ["ime-mode"],
431
618
  "initial-letter": ["initial-letter"],
432
619
  "initial-letter-align": ["initial-letter-align"],
620
+ "initial-letter-wrap": ["initial-letter-wrap"],
433
621
  "inline-size": ["inline-size"],
622
+ "inline-sizing": ["inline-sizing"],
623
+ "input-security": ["input-security"],
434
624
  "inset": [
435
625
  "bottom",
436
626
  "left",
@@ -457,9 +647,18 @@ const PROPERTY_EFFECTS = {
457
647
  "letter-spacing": ["letter-spacing"],
458
648
  "lighting-color": ["lighting-color"],
459
649
  "line-break": ["line-break"],
460
- "line-clamp": ["line-clamp"],
650
+ "line-clamp": [
651
+ "block-ellipsis",
652
+ "continue",
653
+ "max-lines"
654
+ ],
655
+ "line-fit-edge": ["line-fit-edge"],
656
+ "line-grid": ["line-grid"],
461
657
  "line-height": ["line-height"],
462
658
  "line-height-step": ["line-height-step"],
659
+ "line-padding": ["line-padding"],
660
+ "line-snap": ["line-snap"],
661
+ "link-parameters": ["link-parameters"],
463
662
  "list-style": [
464
663
  "list-style-image",
465
664
  "list-style-position",
@@ -478,6 +677,7 @@ const PROPERTY_EFFECTS = {
478
677
  "margin-block-end": ["margin-block-end"],
479
678
  "margin-block-start": ["margin-block-start"],
480
679
  "margin-bottom": ["margin-bottom"],
680
+ "margin-break": ["margin-break"],
481
681
  "margin-inline": ["margin-inline-end", "margin-inline-start"],
482
682
  "margin-inline-end": ["margin-inline-end"],
483
683
  "margin-inline-start": ["margin-inline-start"],
@@ -492,8 +692,15 @@ const PROPERTY_EFFECTS = {
492
692
  ],
493
693
  "marker-end": ["marker-end"],
494
694
  "marker-mid": ["marker-mid"],
695
+ "marker-side": ["marker-side"],
495
696
  "marker-start": ["marker-start"],
496
697
  "mask": [
698
+ "mask-border-mode",
699
+ "mask-border-outset",
700
+ "mask-border-repeat",
701
+ "mask-border-slice",
702
+ "mask-border-source",
703
+ "mask-border-width",
497
704
  "mask-clip",
498
705
  "mask-composite",
499
706
  "mask-image",
@@ -538,8 +745,13 @@ const PROPERTY_EFFECTS = {
538
745
  "min-block-size": ["min-block-size"],
539
746
  "min-height": ["min-height"],
540
747
  "min-inline-size": ["min-inline-size"],
748
+ "min-intrinsic-sizing": ["min-intrinsic-sizing"],
541
749
  "min-width": ["min-width"],
542
750
  "mix-blend-mode": ["mix-blend-mode"],
751
+ "nav-down": ["nav-down"],
752
+ "nav-left": ["nav-left"],
753
+ "nav-right": ["nav-right"],
754
+ "nav-up": ["nav-up"],
543
755
  "object-fit": ["object-fit"],
544
756
  "object-position": ["object-position"],
545
757
  "object-view-box": ["object-view-box"],
@@ -571,7 +783,22 @@ const PROPERTY_EFFECTS = {
571
783
  "overflow-anchor": ["overflow-anchor"],
572
784
  "overflow-block": ["overflow-block"],
573
785
  "overflow-clip-box": ["overflow-clip-box"],
574
- "overflow-clip-margin": ["overflow-clip-margin"],
786
+ "overflow-clip-margin": [
787
+ "overflow-clip-margin-bottom",
788
+ "overflow-clip-margin-left",
789
+ "overflow-clip-margin-right",
790
+ "overflow-clip-margin-top"
791
+ ],
792
+ "overflow-clip-margin-block": ["overflow-clip-margin-block-end", "overflow-clip-margin-block-start"],
793
+ "overflow-clip-margin-block-end": ["overflow-clip-margin-block-end"],
794
+ "overflow-clip-margin-block-start": ["overflow-clip-margin-block-start"],
795
+ "overflow-clip-margin-bottom": ["overflow-clip-margin-bottom"],
796
+ "overflow-clip-margin-inline": ["overflow-clip-margin-inline-end", "overflow-clip-margin-inline-start"],
797
+ "overflow-clip-margin-inline-end": ["overflow-clip-margin-inline-end"],
798
+ "overflow-clip-margin-inline-start": ["overflow-clip-margin-inline-start"],
799
+ "overflow-clip-margin-left": ["overflow-clip-margin-left"],
800
+ "overflow-clip-margin-right": ["overflow-clip-margin-right"],
801
+ "overflow-clip-margin-top": ["overflow-clip-margin-top"],
575
802
  "overflow-inline": ["overflow-inline"],
576
803
  "overflow-wrap": ["overflow-wrap"],
577
804
  "overflow-x": ["overflow-x"],
@@ -603,12 +830,19 @@ const PROPERTY_EFFECTS = {
603
830
  "page-break-before": ["page-break-before"],
604
831
  "page-break-inside": ["page-break-inside"],
605
832
  "paint-order": ["paint-order"],
833
+ "path-length": ["path-length"],
834
+ "pause": ["pause-after", "pause-before"],
835
+ "pause-after": ["pause-after"],
836
+ "pause-before": ["pause-before"],
606
837
  "perspective": ["perspective"],
607
838
  "perspective-origin": ["perspective-origin"],
608
839
  "place-content": ["align-content", "justify-content"],
609
840
  "place-items": ["align-items", "justify-items"],
610
841
  "place-self": ["align-self", "justify-self"],
611
842
  "pointer-events": ["pointer-events"],
843
+ "pointer-timeline": ["pointer-timeline-axis", "pointer-timeline-name"],
844
+ "pointer-timeline-axis": ["pointer-timeline-axis"],
845
+ "pointer-timeline-name": ["pointer-timeline-name"],
612
846
  "position": ["position"],
613
847
  "position-anchor": ["position-anchor"],
614
848
  "position-area": ["position-area"],
@@ -621,14 +855,80 @@ const PROPERTY_EFFECTS = {
621
855
  "r": ["r"],
622
856
  "reading-flow": ["reading-flow"],
623
857
  "reading-order": ["reading-order"],
858
+ "region-fragment": ["region-fragment"],
624
859
  "resize": ["resize"],
860
+ "rest": ["rest-after", "rest-before"],
861
+ "rest-after": ["rest-after"],
862
+ "rest-before": ["rest-before"],
625
863
  "right": ["right"],
626
864
  "rotate": ["rotate"],
627
865
  "row-gap": ["row-gap"],
866
+ "row-rule": [
867
+ "row-rule-color",
868
+ "row-rule-style",
869
+ "row-rule-width"
870
+ ],
871
+ "row-rule-break": ["row-rule-break"],
872
+ "row-rule-color": ["row-rule-color"],
873
+ "row-rule-inset": [
874
+ "row-rule-inset-cap-end",
875
+ "row-rule-inset-cap-start",
876
+ "row-rule-inset-junction-end",
877
+ "row-rule-inset-junction-start"
878
+ ],
879
+ "row-rule-inset-cap": ["row-rule-inset-cap-end", "row-rule-inset-cap-start"],
880
+ "row-rule-inset-cap-end": ["row-rule-inset-cap-end"],
881
+ "row-rule-inset-cap-start": ["row-rule-inset-cap-start"],
882
+ "row-rule-inset-end": ["row-rule-inset-cap-end", "row-rule-inset-junction-end"],
883
+ "row-rule-inset-junction": ["row-rule-inset-junction-end", "row-rule-inset-junction-start"],
884
+ "row-rule-inset-junction-end": ["row-rule-inset-junction-end"],
885
+ "row-rule-inset-junction-start": ["row-rule-inset-junction-start"],
886
+ "row-rule-inset-start": ["row-rule-inset-cap-start", "row-rule-inset-junction-start"],
887
+ "row-rule-style": ["row-rule-style"],
888
+ "row-rule-visibility-items": ["row-rule-visibility-items"],
889
+ "row-rule-width": ["row-rule-width"],
628
890
  "ruby-align": ["ruby-align"],
629
891
  "ruby-merge": ["ruby-merge"],
630
892
  "ruby-overhang": ["ruby-overhang"],
631
893
  "ruby-position": ["ruby-position"],
894
+ "rule": [
895
+ "column-rule-color",
896
+ "column-rule-style",
897
+ "column-rule-width",
898
+ "row-rule-color",
899
+ "row-rule-style",
900
+ "row-rule-width"
901
+ ],
902
+ "rule-break": ["column-rule-break", "row-rule-break"],
903
+ "rule-color": ["column-rule-color", "row-rule-color"],
904
+ "rule-inset": [
905
+ "column-rule-inset-cap-end",
906
+ "column-rule-inset-cap-start",
907
+ "column-rule-inset-junction-end",
908
+ "column-rule-inset-junction-start",
909
+ "row-rule-inset-cap-end",
910
+ "row-rule-inset-cap-start",
911
+ "row-rule-inset-junction-end",
912
+ "row-rule-inset-junction-start"
913
+ ],
914
+ "rule-inset-cap": ["column-rule-inset-cap-end", "column-rule-inset-cap-start"],
915
+ "rule-inset-end": [
916
+ "column-rule-inset-cap-end",
917
+ "column-rule-inset-junction-end",
918
+ "row-rule-inset-cap-end",
919
+ "row-rule-inset-junction-end"
920
+ ],
921
+ "rule-inset-junction": ["column-rule-inset-junction-end", "column-rule-inset-junction-start"],
922
+ "rule-inset-start": [
923
+ "column-rule-inset-cap-start",
924
+ "column-rule-inset-junction-start",
925
+ "row-rule-inset-cap-start",
926
+ "row-rule-inset-junction-start"
927
+ ],
928
+ "rule-overlap": ["rule-overlap"],
929
+ "rule-style": ["column-rule-style", "row-rule-style"],
930
+ "rule-visibility-items": ["column-rule-visibility-items"],
931
+ "rule-width": ["column-rule-width", "row-rule-width"],
632
932
  "rx": ["rx"],
633
933
  "ry": ["ry"],
634
934
  "scale": ["scale"],
@@ -684,12 +984,20 @@ const PROPERTY_EFFECTS = {
684
984
  "scrollbar-gutter": ["scrollbar-gutter"],
685
985
  "scrollbar-width": ["scrollbar-width"],
686
986
  "shape-image-threshold": ["shape-image-threshold"],
987
+ "shape-inside": ["shape-inside"],
687
988
  "shape-margin": ["shape-margin"],
688
989
  "shape-outside": ["shape-outside"],
990
+ "shape-padding": ["shape-padding"],
689
991
  "shape-rendering": ["shape-rendering"],
992
+ "slider-orientation": ["slider-orientation"],
993
+ "spatial-navigation-action": ["spatial-navigation-action"],
994
+ "spatial-navigation-contain": ["spatial-navigation-contain"],
995
+ "spatial-navigation-function": ["spatial-navigation-function"],
996
+ "speak": ["speak"],
690
997
  "speak-as": ["speak-as"],
691
998
  "stop-color": ["stop-color"],
692
999
  "stop-opacity": ["stop-opacity"],
1000
+ "string-set": ["string-set"],
693
1001
  "stroke": [
694
1002
  "stroke-dasharray",
695
1003
  "stroke-dashoffset",
@@ -699,17 +1007,30 @@ const PROPERTY_EFFECTS = {
699
1007
  "stroke-opacity",
700
1008
  "stroke-width"
701
1009
  ],
1010
+ "stroke-align": ["stroke-align"],
1011
+ "stroke-alignment": ["stroke-alignment"],
1012
+ "stroke-break": ["stroke-break"],
702
1013
  "stroke-color": ["stroke-color"],
1014
+ "stroke-dash-corner": ["stroke-dash-corner"],
1015
+ "stroke-dash-justify": ["stroke-dash-justify"],
1016
+ "stroke-dashadjust": ["stroke-dashadjust"],
703
1017
  "stroke-dasharray": ["stroke-dasharray"],
1018
+ "stroke-dashcorner": ["stroke-dashcorner"],
704
1019
  "stroke-dashoffset": ["stroke-dashoffset"],
1020
+ "stroke-image": ["stroke-image"],
705
1021
  "stroke-linecap": ["stroke-linecap"],
706
1022
  "stroke-linejoin": ["stroke-linejoin"],
707
1023
  "stroke-miterlimit": ["stroke-miterlimit"],
708
1024
  "stroke-opacity": ["stroke-opacity"],
1025
+ "stroke-origin": ["stroke-origin"],
1026
+ "stroke-position": ["stroke-position"],
1027
+ "stroke-repeat": ["stroke-repeat"],
1028
+ "stroke-size": ["stroke-size"],
709
1029
  "stroke-width": ["stroke-width"],
710
1030
  "tab-size": ["tab-size"],
711
1031
  "table-layout": ["table-layout"],
712
- "text-align": ["text-align"],
1032
+ "text-align": ["text-align-all", "text-align-last"],
1033
+ "text-align-all": ["text-align-all"],
713
1034
  "text-align-last": ["text-align-last"],
714
1035
  "text-anchor": ["text-anchor"],
715
1036
  "text-autospace": ["text-autospace"],
@@ -726,14 +1047,25 @@ const PROPERTY_EFFECTS = {
726
1047
  "text-decoration-color": ["text-decoration-color"],
727
1048
  "text-decoration-inset": ["text-decoration-inset"],
728
1049
  "text-decoration-line": ["text-decoration-line"],
729
- "text-decoration-skip": ["text-decoration-skip"],
1050
+ "text-decoration-skip": [
1051
+ "text-decoration-skip-box",
1052
+ "text-decoration-skip-ink",
1053
+ "text-decoration-skip-self",
1054
+ "text-decoration-skip-spaces"
1055
+ ],
1056
+ "text-decoration-skip-box": ["text-decoration-skip-box"],
730
1057
  "text-decoration-skip-ink": ["text-decoration-skip-ink"],
1058
+ "text-decoration-skip-self": ["text-decoration-skip-self"],
1059
+ "text-decoration-skip-spaces": ["text-decoration-skip-spaces"],
731
1060
  "text-decoration-style": ["text-decoration-style"],
732
1061
  "text-decoration-thickness": ["text-decoration-thickness"],
733
1062
  "text-emphasis": ["text-emphasis-color", "text-emphasis-style"],
734
1063
  "text-emphasis-color": ["text-emphasis-color"],
735
1064
  "text-emphasis-position": ["text-emphasis-position"],
1065
+ "text-emphasis-skip": ["text-emphasis-skip"],
736
1066
  "text-emphasis-style": ["text-emphasis-style"],
1067
+ "text-fit": ["text-fit"],
1068
+ "text-group-align": ["text-group-align"],
737
1069
  "text-indent": ["text-indent"],
738
1070
  "text-justify": ["text-justify"],
739
1071
  "text-orientation": ["text-orientation"],
@@ -741,6 +1073,7 @@ const PROPERTY_EFFECTS = {
741
1073
  "text-rendering": ["text-rendering"],
742
1074
  "text-shadow": ["text-shadow"],
743
1075
  "text-size-adjust": ["text-size-adjust"],
1076
+ "text-spacing": ["text-autospace", "text-spacing-trim"],
744
1077
  "text-spacing-trim": ["text-spacing-trim"],
745
1078
  "text-transform": ["text-transform"],
746
1079
  "text-underline-offset": ["text-underline-offset"],
@@ -750,20 +1083,20 @@ const PROPERTY_EFFECTS = {
750
1083
  "text-wrap-style": ["text-wrap-style"],
751
1084
  "timeline-scope": ["timeline-scope"],
752
1085
  "timeline-trigger": [
753
- "timeline-trigger-exit-range-end",
754
- "timeline-trigger-exit-range-start",
1086
+ "timeline-trigger-activation-range-end",
1087
+ "timeline-trigger-activation-range-start",
1088
+ "timeline-trigger-active-range-end",
1089
+ "timeline-trigger-active-range-start",
755
1090
  "timeline-trigger-name",
756
- "timeline-trigger-range-end",
757
- "timeline-trigger-range-start",
758
1091
  "timeline-trigger-source"
759
1092
  ],
760
- "timeline-trigger-exit-range": ["timeline-trigger-exit-range-end", "timeline-trigger-exit-range-start"],
761
- "timeline-trigger-exit-range-end": ["timeline-trigger-exit-range-end"],
762
- "timeline-trigger-exit-range-start": ["timeline-trigger-exit-range-start"],
1093
+ "timeline-trigger-activation-range": ["timeline-trigger-activation-range-end", "timeline-trigger-activation-range-start"],
1094
+ "timeline-trigger-activation-range-end": ["timeline-trigger-activation-range-end"],
1095
+ "timeline-trigger-activation-range-start": ["timeline-trigger-activation-range-start"],
1096
+ "timeline-trigger-active-range": ["timeline-trigger-active-range-end", "timeline-trigger-active-range-start"],
1097
+ "timeline-trigger-active-range-end": ["timeline-trigger-active-range-end"],
1098
+ "timeline-trigger-active-range-start": ["timeline-trigger-active-range-start"],
763
1099
  "timeline-trigger-name": ["timeline-trigger-name"],
764
- "timeline-trigger-range": ["timeline-trigger-range-end", "timeline-trigger-range-start"],
765
- "timeline-trigger-range-end": ["timeline-trigger-range-end"],
766
- "timeline-trigger-range-start": ["timeline-trigger-range-start"],
767
1100
  "timeline-trigger-source": ["timeline-trigger-source"],
768
1101
  "top": ["top"],
769
1102
  "touch-action": ["touch-action"],
@@ -788,22 +1121,44 @@ const PROPERTY_EFFECTS = {
788
1121
  "unicode-bidi": ["unicode-bidi"],
789
1122
  "user-select": ["user-select"],
790
1123
  "vector-effect": ["vector-effect"],
791
- "vertical-align": ["vertical-align"],
1124
+ "vertical-align": [
1125
+ "alignment-baseline",
1126
+ "baseline-shift",
1127
+ "baseline-source"
1128
+ ],
792
1129
  "view-timeline": ["view-timeline-axis", "view-timeline-name"],
793
1130
  "view-timeline-axis": ["view-timeline-axis"],
794
1131
  "view-timeline-inset": ["view-timeline-inset"],
795
1132
  "view-timeline-name": ["view-timeline-name"],
796
1133
  "view-transition-class": ["view-transition-class"],
1134
+ "view-transition-group": ["view-transition-group"],
797
1135
  "view-transition-name": ["view-transition-name"],
1136
+ "view-transition-scope": ["view-transition-scope"],
798
1137
  "visibility": ["visibility"],
1138
+ "voice-balance": ["voice-balance"],
1139
+ "voice-duration": ["voice-duration"],
1140
+ "voice-family": ["voice-family"],
1141
+ "voice-pitch": ["voice-pitch"],
1142
+ "voice-range": ["voice-range"],
1143
+ "voice-rate": ["voice-rate"],
1144
+ "voice-stress": ["voice-stress"],
1145
+ "voice-volume": ["voice-volume"],
799
1146
  "white-space": ["text-wrap-mode", "white-space-collapse"],
800
1147
  "white-space-collapse": ["white-space-collapse"],
1148
+ "white-space-trim": ["white-space-trim"],
801
1149
  "widows": ["widows"],
802
1150
  "width": ["width"],
803
1151
  "will-change": ["will-change"],
1152
+ "window-drag": ["window-drag"],
804
1153
  "word-break": ["word-break"],
1154
+ "word-space-transform": ["word-space-transform"],
805
1155
  "word-spacing": ["word-spacing"],
806
1156
  "word-wrap": ["word-wrap"],
1157
+ "wrap-after": ["wrap-after"],
1158
+ "wrap-before": ["wrap-before"],
1159
+ "wrap-flow": ["wrap-flow"],
1160
+ "wrap-inside": ["wrap-inside"],
1161
+ "wrap-through": ["wrap-through"],
807
1162
  "writing-mode": ["writing-mode"],
808
1163
  "x": ["x"],
809
1164
  "y": ["y"],
@@ -811,7 +1166,7 @@ const PROPERTY_EFFECTS = {
811
1166
  "zoom": ["zoom"]
812
1167
  };
813
1168
  //#endregion
814
- //#region src/internal/property-effects.ts
1169
+ //#region src/property-effects.ts
815
1170
  const UNIVERSAL_EFFECT = "*";
816
1171
  const propertyEffectsLookup = PROPERTY_EFFECTS;
817
1172
  function isCustomProperty(property) {
@@ -869,7 +1224,7 @@ function hasPropertyEffectOverlap(left, right) {
869
1224
  return leftEffects.some((effect) => rightEffectSet.has(effect));
870
1225
  }
871
1226
  //#endregion
872
- //#region src/internal/utils.ts
1227
+ //#region src/utils.ts
873
1228
  /**
874
1229
  * Creates a scoped logger with configurable log-level functions and a toggleable debug mode.
875
1230
  *
@@ -948,13 +1303,13 @@ const numOfChars = chars.length;
948
1303
  * @param num - The non-negative integer to encode.
949
1304
  * @returns A short alphabetic string unique to the given integer.
950
1305
  *
951
- * @remarks Used to generate compact, human-readable atomic style class IDs. The encoding is deterministic: the same number always produces the same string.
1306
+ * @remarks Used to generate compact, human-readable atomic style class IDs. The encoding is deterministic (the same number always produces the same string) and least-significant-digit first: `52` maps to `'aa'`, `53` to `'ba'`, and so on.
952
1307
  *
953
1308
  * @example
954
1309
  * ```ts
955
1310
  * numberToChars(0) // 'a'
956
1311
  * numberToChars(51) // 'Z'
957
- * numberToChars(52) // 'ba'
1312
+ * numberToChars(52) // 'aa'
958
1313
  * ```
959
1314
  */
960
1315
  function numberToChars(num) {
@@ -1025,27 +1380,111 @@ function isNotString(value) {
1025
1380
  return typeof value !== "string";
1026
1381
  }
1027
1382
  /**
1028
- * Tests whether a value conforms to the `InternalPropertyValue` shape: a string, a `[value, fallback[]]` tuple, or nullish.
1383
+ * Type-narrowing guard that returns `true` when the value is a plain object record (non-null, non-array object).
1384
+ * @internal
1385
+ *
1386
+ * @param value - The value to test.
1387
+ * @returns `true` if the value is an object that is neither `null` nor an array, narrowing the type to `Record<string, unknown>`.
1388
+ *
1389
+ * @remarks Used to distinguish nested definition objects (variables, design tokens) from scalar values and arrays while walking configuration trees.
1390
+ *
1391
+ * @example
1392
+ * ```ts
1393
+ * isPlainObjectRecord({ a: 1 }) // true
1394
+ * isPlainObjectRecord([1, 2]) // false
1395
+ * isPlainObjectRecord(null) // false
1396
+ * ```
1397
+ */
1398
+ function isPlainObjectRecord(value) {
1399
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1400
+ }
1401
+ const REGEXP_SPECIAL_CHARS_RE = /[.*+?^${}()|[\]\\/-]/g;
1402
+ /**
1403
+ * Escapes regular expression special characters in a string so it can be embedded in a `RegExp` source as a literal match.
1404
+ * @internal
1405
+ *
1406
+ * @param value - The literal text to escape.
1407
+ * @returns The input with every regex special character prefixed by a backslash.
1408
+ *
1409
+ * @remarks Runtime substitute for `RegExp.escape()` (available in Node.js >= 24 but not yet typed by TypeScript 5.9). Escapes all regex syntax characters plus `/` and `-`; the extra escapes are identity escapes in non-`u`-flag patterns, so the result is safe to embed in the non-unicode-mode regexes built by the engine and integrations.
1410
+ *
1411
+ * @example
1412
+ * ```ts
1413
+ * escapeRegExp('i-icon?') // 'i\\-icon\\?'
1414
+ * new RegExp(`^${escapeRegExp('a.b')}$`).test('a.b') // true
1415
+ * ```
1416
+ */
1417
+ function escapeRegExp(value) {
1418
+ return value.replace(REGEXP_SPECIAL_CHARS_RE, "\\$&");
1419
+ }
1420
+ function isPropertyValueScalar(v) {
1421
+ return typeof v === "string" || typeof v === "number";
1422
+ }
1423
+ /**
1424
+ * Tests whether a value conforms to the `InternalPropertyValue` shape: a string, a number, a `[value, fallback[]]` tuple, or nullish.
1029
1425
  * @internal
1030
1426
  *
1031
1427
  * @param v - The value to inspect.
1032
1428
  * @returns `true` if the value is a valid property value.
1033
1429
  *
1034
- * @remarks During extraction, the engine uses this guard to distinguish CSS property values from nested selector objects or style item arrays.
1430
+ * @remarks During extraction, the engine uses this guard to distinguish CSS property values from nested selector objects or style item arrays. Numbers are accepted because the csstype-based input types allow numeric values such as `0`; they are converted to strings during value normalization.
1035
1431
  *
1036
1432
  * @example
1037
1433
  * ```ts
1038
1434
  * isPropertyValue('red') // true
1435
+ * isPropertyValue(0) // true
1039
1436
  * isPropertyValue(['red', ['blue']]) // true
1437
+ * isPropertyValue(['auto', [0]]) // true
1040
1438
  * isPropertyValue(null) // true
1041
1439
  * isPropertyValue({ color: 'red' }) // false
1042
1440
  * ```
1043
1441
  */
1044
1442
  function isPropertyValue(v) {
1045
- if (Array.isArray(v)) return v.length === 2 && typeof v[0] === "string" && Array.isArray(v[1]) && v[1].every((i) => typeof i === "string");
1443
+ if (Array.isArray(v)) return v.length === 2 && isPropertyValueScalar(v[0]) && Array.isArray(v[1]) && v[1].every(isPropertyValueScalar);
1046
1444
  if (v == null) return true;
1047
- if (typeof v === "string") return true;
1048
- return false;
1445
+ return isPropertyValueScalar(v);
1446
+ }
1447
+ /**
1448
+ * Applies a transform to the parts of a string outside quoted segments,
1449
+ * leaving single- and double-quoted content (e.g. attribute values) untouched.
1450
+ * @internal
1451
+ *
1452
+ * @param str - The string to scan.
1453
+ * @param transform - Transform applied to each unquoted segment.
1454
+ * @returns The reassembled string with transformed unquoted segments and untouched quoted segments.
1455
+ *
1456
+ * @remarks A backslash-escaped character is treated as a literal both inside and outside quoted segments, so a CSS-escaped quote in an identifier (e.g. `.it\'s`) never starts quoted-segment scanning.
1457
+ *
1458
+ * @example
1459
+ * ```ts
1460
+ * transformOutsideQuotes('[data-x="%"] %', s => s.replace(/%/g, 'pk-a'))
1461
+ * // '[data-x="%"] pk-a'
1462
+ * ```
1463
+ */
1464
+ function transformOutsideQuotes(str, transform) {
1465
+ let result = "";
1466
+ let segmentStart = 0;
1467
+ for (let i = 0; i < str.length; i++) {
1468
+ const ch = str[i];
1469
+ if (ch === "\\") {
1470
+ i++;
1471
+ continue;
1472
+ }
1473
+ if (ch === "\"" || ch === "'") {
1474
+ result += transform(str.slice(segmentStart, i));
1475
+ let j = i + 1;
1476
+ while (j < str.length && str[j] !== ch) {
1477
+ if (str[j] === "\\") j++;
1478
+ j++;
1479
+ }
1480
+ const end = Math.min(j, str.length - 1);
1481
+ result += str.slice(i, end + 1);
1482
+ i = end;
1483
+ segmentStart = i + 1;
1484
+ }
1485
+ }
1486
+ result += transform(str.slice(segmentStart));
1487
+ return result;
1049
1488
  }
1050
1489
  /**
1051
1490
  * Serializes a value to a JSON string for use as a deterministic cache key.
@@ -1117,23 +1556,25 @@ function appendAutocompleteEntries(set, values) {
1117
1556
  * @param entries - A record mapping keys to single or arrayed string values, or `undefined` to skip.
1118
1557
  * @returns `true` if at least one entry was added or extended; `false` if the input was nullish or empty.
1119
1558
  *
1120
- * @remarks Existing map entries are extended (not replaced) with the new values, maintaining all previously registered suggestions for a given key. This accumulative behavior allows multiple plugins to contribute value suggestions for the same property.
1559
+ * @remarks Existing map entries are extended (not replaced) with the new values, maintaining all previously registered suggestions for a given key. This accumulative behavior allows multiple plugins to contribute value suggestions for the same property. Values already present for a key are skipped, and the function returns `false` when nothing new was added.
1121
1560
  *
1122
1561
  * @example
1123
1562
  * ```ts
1124
1563
  * const map = new Map<string, string[]>()
1125
1564
  * appendAutocompleteRecordEntries(map, { color: ['red', 'blue'] }) // true
1126
1565
  * appendAutocompleteRecordEntries(map, { color: 'green' }) // true (now ['red','blue','green'])
1566
+ * appendAutocompleteRecordEntries(map, { color: 'green' }) // false (no change)
1127
1567
  * ```
1128
1568
  */
1129
1569
  function appendAutocompleteRecordEntries(map, entries) {
1130
1570
  if (entries == null) return false;
1131
1571
  let changed = false;
1132
1572
  for (const [key, value] of Object.entries(entries)) {
1133
- const nextValues = [value].flat();
1134
- if (nextValues.length === 0) continue;
1135
- const current = map.get(key) || [];
1136
- map.set(key, [...current, ...nextValues]);
1573
+ const current = map.get(key);
1574
+ const existing = new Set(current);
1575
+ const added = [value].flat().filter((v) => !existing.has(v));
1576
+ if (added.length === 0) continue;
1577
+ map.set(key, [...current ?? [], ...added]);
1137
1578
  changed = true;
1138
1579
  }
1139
1580
  return changed;
@@ -1199,19 +1640,27 @@ function renderCSSStyleBlocks(blocks, isFormatted, depth = 0) {
1199
1640
  const propertySpace = isFormatted ? " " : "";
1200
1641
  const lineEnd = isFormatted ? "\n" : "";
1201
1642
  const lines = [];
1202
- blocks.forEach(({ properties, children }, selector) => {
1203
- if (properties.length === 0 && (children == null || children.size === 0)) return;
1643
+ blocks.forEach((blockBody, selector) => {
1644
+ if (hasRenderableBlockContent(blockBody) === false) return;
1645
+ const { properties, children } = blockBody;
1646
+ const childrenCss = children != null && children.size > 0 ? renderCSSStyleBlocks(children, isFormatted, depth + 1) : "";
1204
1647
  lines.push(...[
1205
1648
  `${blockIndent}${selector}${selectorEnd}{`,
1206
1649
  ...properties.map(({ property, value }) => `${blockBodyIndent}${property}:${propertySpace}${value};`),
1207
- ...children != null && children.size > 0 ? [renderCSSStyleBlocks(children, isFormatted, depth + 1)] : [],
1650
+ ...childrenCss !== "" ? [childrenCss] : [],
1208
1651
  `${blockIndent}}`
1209
1652
  ]);
1210
1653
  });
1211
1654
  return lines.join(lineEnd);
1212
1655
  }
1656
+ function hasRenderableBlockContent(blockBody) {
1657
+ if (blockBody.properties.length > 0) return true;
1658
+ if (blockBody.children == null) return false;
1659
+ for (const child of blockBody.children.values()) if (hasRenderableBlockContent(child)) return true;
1660
+ return false;
1661
+ }
1213
1662
  //#endregion
1214
- //#region src/internal/atomic-style.ts
1663
+ //#region src/atomic-style.ts
1215
1664
  /**
1216
1665
  * Creates a fresh, empty `EngineStore` with all maps initialized.
1217
1666
  * @internal
@@ -1423,7 +1872,7 @@ function getOrderSensitiveDependencyKeys(scoped, property) {
1423
1872
  return dependencyKeys;
1424
1873
  }
1425
1874
  //#endregion
1426
- //#region src/internal/constants.ts
1875
+ //#region src/constants.ts
1427
1876
  /**
1428
1877
  * CSS `@layer` at-rule prefix used when constructing layer-scoped selectors
1429
1878
  * in generated stylesheet output.
@@ -1435,11 +1884,50 @@ const LAYER_SELECTOR_PREFIX = "@layer ";
1435
1884
  * Global regex matching all occurrences of {@link ATOMIC_STYLE_ID_PLACEHOLDER}
1436
1885
  * for batch replacement in selector templates.
1437
1886
  *
1887
+ * A `%` directly preceded by a digit is treated as a literal percentage
1888
+ * (e.g. `@supports (width: 50%)`), not a placeholder.
1889
+ *
1890
+ * @internal
1891
+ */
1892
+ const ATOMIC_STYLE_ID_PLACEHOLDER_RE_GLOBAL = /(?<!\d)%/g;
1893
+ /**
1894
+ * Tests whether a selector string contains the atomic style ID placeholder.
1895
+ *
1896
+ * Uses the same digit-protection rule as {@link ATOMIC_STYLE_ID_PLACEHOLDER_RE_GLOBAL}:
1897
+ * `%` preceded by a digit is a literal percentage, not a placeholder.
1898
+ * A `%` inside single- or double-quoted content (e.g. an attribute value)
1899
+ * is never treated as a placeholder.
1900
+ *
1901
+ * @internal
1902
+ */
1903
+ function hasAtomicStyleIdPlaceholder(selector) {
1904
+ if (!selector.includes("\"") && !selector.includes("'")) {
1905
+ ATOMIC_STYLE_ID_PLACEHOLDER_RE_GLOBAL.lastIndex = 0;
1906
+ return ATOMIC_STYLE_ID_PLACEHOLDER_RE_GLOBAL.test(selector);
1907
+ }
1908
+ let found = false;
1909
+ transformOutsideQuotes(selector, (segment) => {
1910
+ if (found === false) {
1911
+ ATOMIC_STYLE_ID_PLACEHOLDER_RE_GLOBAL.lastIndex = 0;
1912
+ found = ATOMIC_STYLE_ID_PLACEHOLDER_RE_GLOBAL.test(segment);
1913
+ }
1914
+ return segment;
1915
+ });
1916
+ return found;
1917
+ }
1918
+ /**
1919
+ * Replaces every atomic style ID placeholder in a selector string with the given atomic style ID.
1920
+ *
1921
+ * Applies the same rules as {@link hasAtomicStyleIdPlaceholder}: a `%` directly
1922
+ * preceded by a digit is a literal percentage, and quoted content is never rewritten.
1923
+ *
1438
1924
  * @internal
1439
1925
  */
1440
- const ATOMIC_STYLE_ID_PLACEHOLDER_RE_GLOBAL = /%/g;
1926
+ function replaceAtomicStyleIdPlaceholder(selector, atomicStyleId) {
1927
+ return transformOutsideQuotes(selector, (segment) => segment.replace(ATOMIC_STYLE_ID_PLACEHOLDER_RE_GLOBAL, () => atomicStyleId));
1928
+ }
1441
1929
  //#endregion
1442
- //#region src/internal/extractor.ts
1930
+ //#region src/extractor.ts
1443
1931
  function replaceBySplitAndJoin(str, split, mapFn, join) {
1444
1932
  let splitted = str.split(split);
1445
1933
  if (mapFn != null) splitted = splitted.map(mapFn);
@@ -1458,7 +1946,7 @@ const ATTRIBUTE_SUFFIX_MATCH_RE_GLOBAL = /\$=/g;
1458
1946
  * @param options.defaultSelector - The selector template that replaces `$` placeholders.
1459
1947
  * @returns An array of normalized selector strings with all placeholders resolved.
1460
1948
  *
1461
- * @remarks The `$` character in a selector is replaced with the engine's `defaultSelector`. The `%` character is the atomic style ID placeholder, preserved for later substitution. Attribute suffix matches (`$=`) are protected from the `$` replacement.
1949
+ * @remarks The `$` character in a selector is replaced with the engine's `defaultSelector`. The `%` character is the atomic style ID placeholder, preserved for later substitution. Attribute suffix matches (`$=`) are protected from the `$` replacement. Content inside single or double quotes is never rewritten, and a `%` directly preceded by a digit (e.g. `@supports (width: 50%)`) is treated as a literal percentage.
1462
1950
  *
1463
1951
  * @example
1464
1952
  * ```ts
@@ -1467,7 +1955,7 @@ const ATTRIBUTE_SUFFIX_MATCH_RE_GLOBAL = /\$=/g;
1467
1955
  * ```
1468
1956
  */
1469
1957
  function normalizeSelectors({ selectors, defaultSelector }) {
1470
- return selectors.map((s) => replaceBySplitAndJoin(s.replace(RE_SPLIT, ","), ATOMIC_STYLE_ID_PLACEHOLDER_RE_GLOBAL, (a) => replaceBySplitAndJoin(a, ATTRIBUTE_SUFFIX_MATCH_RE_GLOBAL, (b) => replaceBySplitAndJoin(b, DEFAULT_SELECTOR_PLACEHOLDER_RE_GLOBAL, null, defaultSelector), ATTRIBUTE_SUFFIX_MATCH), "%"));
1958
+ return selectors.map((s) => transformOutsideQuotes(s, (segment) => replaceBySplitAndJoin(segment.replace(RE_SPLIT, ","), ATOMIC_STYLE_ID_PLACEHOLDER_RE_GLOBAL, (a) => replaceBySplitAndJoin(a, ATTRIBUTE_SUFFIX_MATCH_RE_GLOBAL, (b) => replaceBySplitAndJoin(b, DEFAULT_SELECTOR_PLACEHOLDER_RE_GLOBAL, null, defaultSelector), ATTRIBUTE_SUFFIX_MATCH), "%")));
1471
1959
  }
1472
1960
  /**
1473
1961
  * Normalizes a raw `InternalPropertyValue` into the extraction output format: an array of trimmed, deduplicated CSS value strings with fallbacks ordered before the primary value, or `null`/`undefined` to signal removal.
@@ -1476,11 +1964,12 @@ function normalizeSelectors({ selectors, defaultSelector }) {
1476
1964
  * @param value - The raw property value to normalize.
1477
1965
  * @returns An array of CSS value strings (fallbacks first, primary last), or `null`/`undefined` for removal.
1478
1966
  *
1479
- * @remarks For tuple values `[primary, fallbacks]`, duplicates among fallbacks are removed and the primary value is appended last so CSS cascade uses it as the effective value while older browsers fall back to earlier entries.
1967
+ * @remarks For tuple values `[primary, fallbacks]`, duplicates among fallbacks are removed and the primary value is appended last so CSS cascade uses it as the effective value while older browsers fall back to earlier entries. Numeric values (e.g. `0`) are converted to strings.
1480
1968
  *
1481
1969
  * @example
1482
1970
  * ```ts
1483
1971
  * normalizeValue('red') // ['red']
1972
+ * normalizeValue(0) // ['0']
1484
1973
  * normalizeValue(['red', ['blue']]) // ['blue', 'red']
1485
1974
  * normalizeValue(null) // null
1486
1975
  * ```
@@ -1489,11 +1978,11 @@ function normalizeValue(value) {
1489
1978
  if (value == null) return value;
1490
1979
  if (Array.isArray(value)) {
1491
1980
  const [primary, fallbacks] = value;
1492
- const p = primary.trim();
1981
+ const p = String(primary).trim();
1493
1982
  const seen = new Set([p]);
1494
1983
  const result = [];
1495
1984
  for (const v of fallbacks) {
1496
- const s = v.trim();
1985
+ const s = String(v).trim();
1497
1986
  if (!seen.has(s)) {
1498
1987
  seen.add(s);
1499
1988
  result.push(s);
@@ -1502,7 +1991,7 @@ function normalizeValue(value) {
1502
1991
  result.push(p);
1503
1992
  return result;
1504
1993
  }
1505
- return [value.trim()];
1994
+ return [String(value).trim()];
1506
1995
  }
1507
1996
  /**
1508
1997
  * Recursively walks a style definition tree, extracting each CSS property-value pair into a flat list of `ExtractedStyleContent` entries with their full selector chain.
@@ -1532,18 +2021,24 @@ function normalizeValue(value) {
1532
2021
  * ```
1533
2022
  */
1534
2023
  async function extract({ styleDefinition, levels = [], result = [], defaultSelector, transformSelectors, transformStyleItems, transformStyleDefinitions }) {
1535
- for (const definition of await transformStyleDefinitions([styleDefinition])) for (const [k, v] of Object.entries(definition)) if (isPropertyValue(v)) {
1536
- const selector = normalizeSelectors({
1537
- selectors: await transformSelectors(levels),
1538
- defaultSelector
1539
- });
1540
- if (selector.length === 0 || selector.every((s) => s.includes("%") === false)) selector.push(defaultSelector);
1541
- result.push({
1542
- selector,
1543
- property: toKebab(k),
1544
- value: normalizeValue(v)
1545
- });
1546
- } else if (Array.isArray(v)) for (const styleItem of await transformStyleItems(v)) {
2024
+ let scopeSelector;
2025
+ const resolveScopeSelector = async () => {
2026
+ if (scopeSelector == null) {
2027
+ const selector = normalizeSelectors({
2028
+ selectors: await transformSelectors(levels),
2029
+ defaultSelector
2030
+ });
2031
+ if (selector.length === 0 || selector.every((s) => hasAtomicStyleIdPlaceholder(s) === false)) selector.push(defaultSelector);
2032
+ scopeSelector = selector;
2033
+ }
2034
+ return scopeSelector;
2035
+ };
2036
+ for (const definition of await transformStyleDefinitions([styleDefinition])) for (const [k, v] of Object.entries(definition)) if (isPropertyValue(v)) result.push({
2037
+ selector: await resolveScopeSelector(),
2038
+ property: toKebab(k),
2039
+ value: normalizeValue(v)
2040
+ });
2041
+ else if (Array.isArray(v)) for (const styleItem of await transformStyleItems(v)) {
1547
2042
  if (typeof styleItem === "string") continue;
1548
2043
  await extract({
1549
2044
  styleDefinition: styleItem,
@@ -1596,7 +2091,7 @@ function createExtractFn(options) {
1596
2091
  });
1597
2092
  }
1598
2093
  //#endregion
1599
- //#region src/internal/plugin.ts
2094
+ //#region src/plugin.ts
1600
2095
  function getPluginHook(plugin, hook) {
1601
2096
  const hookFn = plugin[hook];
1602
2097
  return typeof hookFn === "function" ? hookFn : null;
@@ -1747,7 +2242,7 @@ function resolvePlugins(plugins) {
1747
2242
  * ```ts
1748
2243
  * export default defineEnginePlugin({
1749
2244
  * name: 'my-plugin',
1750
- * configureRawConfig: (config) => ({ ...config, important: true }),
2245
+ * configureRawConfig: (config) => ({ ...config, important: { default: true } }),
1751
2246
  * })
1752
2247
  * ```
1753
2248
  */
@@ -1756,9 +2251,11 @@ function defineEnginePlugin(plugin) {
1756
2251
  }
1757
2252
  /* c8 ignore end */
1758
2253
  //#endregion
1759
- //#region src/internal/plugins/important.ts
2254
+ //#region src/plugins/important.ts
2255
+ const TRAILING_IMPORTANT_RE = /!\s*important\s*$/i;
1760
2256
  function appendImportant(v) {
1761
- return v.endsWith("!important") ? v : `${v} !important`;
2257
+ const value = String(v);
2258
+ return TRAILING_IMPORTANT_RE.test(value) ? value : `${value} !important`;
1762
2259
  }
1763
2260
  function modifyPropertyValue(value) {
1764
2261
  if (value == null) return null;
@@ -1770,7 +2267,7 @@ function modifyPropertyValue(value) {
1770
2267
  *
1771
2268
  * @returns An `EnginePlugin` that intercepts `transformStyleDefinitions` to conditionally append `!important` to every property value.
1772
2269
  *
1773
- * @remarks When `EngineConfig.important.default` is `true`, all property values receive `!important` unless the style definition explicitly sets `__important: false`. Individual style definitions can also opt-in with `__important: true` regardless of the default.
2270
+ * @remarks When `EngineConfig.important.default` is `true`, all property values receive `!important` unless the style definition explicitly sets `__important: false`. Individual style definitions can also opt-in with `__important: true` regardless of the default. An explicit `__important` flag is propagated into nested selector blocks (which may override it with their own explicit flag). The `__shortcut` reference is never modified.
1774
2271
  *
1775
2272
  * @example
1776
2273
  * ```ts
@@ -1779,6 +2276,16 @@ function modifyPropertyValue(value) {
1779
2276
  */
1780
2277
  function important() {
1781
2278
  let defaultValue;
2279
+ function propagateExplicitFlag(v, flag) {
2280
+ if (Array.isArray(v)) return v.map((item) => typeof item === "object" && item !== null && !Array.isArray(item) ? {
2281
+ __important: flag,
2282
+ ...item
2283
+ } : item);
2284
+ return {
2285
+ __important: flag,
2286
+ ...v
2287
+ };
2288
+ }
1782
2289
  return defineEnginePlugin({
1783
2290
  name: "core:important",
1784
2291
  rawConfigConfigured(config) {
@@ -1793,17 +2300,20 @@ function important() {
1793
2300
  transformStyleDefinitions(styleDefinitions) {
1794
2301
  return styleDefinitions.map((styleDefinition) => {
1795
2302
  const { __important, ...rest } = styleDefinition;
1796
- if ((__important ?? defaultValue) === false) return rest;
2303
+ const explicit = __important;
2304
+ const important = explicit ?? defaultValue;
2305
+ if (important === false && explicit == null) return rest;
1797
2306
  return Object.fromEntries(Object.entries(rest).map(([k, v]) => {
1798
- if (isPropertyValue(v)) return [k, modifyPropertyValue(v)];
1799
- return [k, v];
2307
+ if (k === "__shortcut") return [k, v];
2308
+ if (isPropertyValue(v)) return [k, important ? modifyPropertyValue(v) : v];
2309
+ return [k, explicit == null ? v : propagateExplicitFlag(v, explicit)];
1800
2310
  }));
1801
2311
  });
1802
2312
  }
1803
2313
  });
1804
2314
  }
1805
2315
  //#endregion
1806
- //#region src/internal/plugins/keyframes.ts
2316
+ //#region src/plugins/keyframes.ts
1807
2317
  /**
1808
2318
  * Built-in engine plugin that provides CSS `@keyframes` registration, autocomplete integration, and smart pruning.
1809
2319
  *
@@ -1823,7 +2333,7 @@ function keyframes() {
1823
2333
  name: "core:keyframes",
1824
2334
  rawConfigConfigured(config) {
1825
2335
  resolveKeyframesConfig = createResolveConfigFn({ pruneUnused: config.keyframes?.pruneUnused });
1826
- configList = config.keyframes?.keyframes ?? [];
2336
+ configList = config.keyframes?.definitions ?? [];
1827
2337
  },
1828
2338
  configureEngine(engine) {
1829
2339
  engine.keyframes = {
@@ -1842,11 +2352,12 @@ function keyframes() {
1842
2352
  }
1843
2353
  };
1844
2354
  engine.keyframes.add(...configList);
1845
- engine.addPreflight((engine) => {
2355
+ engine.addPreflight((engine, _isFormatted, ctx) => {
1846
2356
  const maybeUsedName = /* @__PURE__ */ new Set();
1847
- engine.store.atomicStyles.forEach(({ content: { property, value } }) => {
2357
+ engine.store.atomicStyles.forEach(({ content: { property, value } }, id) => {
2358
+ if (ctx?.usedAtomicStyleIds != null && ctx.usedAtomicStyleIds.has(id) === false) return;
1848
2359
  if (property === "animation-name") {
1849
- value.forEach((name) => maybeUsedName.add(name));
2360
+ value.forEach((name) => addToSet(maybeUsedName, ...name.split(",").map((v) => v.trim())));
1850
2361
  return;
1851
2362
  }
1852
2363
  if (property === "animation") value.forEach((value) => {
@@ -1858,7 +2369,7 @@ function keyframes() {
1858
2369
  const maybeUsedKeyframes = Array.from(engine.keyframes.store.values()).filter(({ name, frames, pruneUnused }) => (pruneUnused === false || maybeUsedName.has(name)) && frames != null);
1859
2370
  const preflightDefinition = {};
1860
2371
  maybeUsedKeyframes.forEach(({ name, frames }) => {
1861
- preflightDefinition[`@keyframes ${name}`] = Object.fromEntries(Object.entries(frames).map(([frame, properties]) => [frame, properties]));
2372
+ preflightDefinition[`@keyframes ${name}`] = frames;
1862
2373
  });
1863
2374
  return preflightDefinition;
1864
2375
  });
@@ -1892,7 +2403,7 @@ function createResolveConfigFn({ pruneUnused: defaultPruneUnused = true } = {})
1892
2403
  };
1893
2404
  }
1894
2405
  //#endregion
1895
- //#region src/internal/resolver.ts
2406
+ //#region src/resolver.ts
1896
2407
  function stripGlobalFlag(re) {
1897
2408
  if (!re.global) return re;
1898
2409
  return new RegExp(re.source, re.flags.replace("g", ""));
@@ -1915,6 +2426,10 @@ function stripGlobalFlag(re) {
1915
2426
  var AbstractResolver = class {
1916
2427
  /** Cache of previously resolved input-string → result pairs. */
1917
2428
  _resolvedResultsMap = /* @__PURE__ */ new Map();
2429
+ /** Negative cache of input strings that matched no rule at all. Retryable-unresolved dynamic results (a matched dynamic rule whose value fn returned nullish) are never stored here. */
2430
+ _unmatchedStrings = /* @__PURE__ */ new Set();
2431
+ /** Index of static rules keyed by their exact match string (first registered rule wins on string collisions), giving O(1) static lookups. */
2432
+ _staticRulesByString = /* @__PURE__ */ new Map();
1918
2433
  /** Registry of static rules keyed by their unique key. */
1919
2434
  staticRulesMap = /* @__PURE__ */ new Map();
1920
2435
  /** Registry of dynamic rules keyed by their unique key. */
@@ -1933,7 +2448,7 @@ var AbstractResolver = class {
1933
2448
  * @param rule - The static rule to register.
1934
2449
  * @returns `this` for chaining.
1935
2450
  *
1936
- * @remarks Overwrites any existing static rule with the same key.
2451
+ * @remarks Overwrites any existing static rule with the same key. The entire resolution cache is cleared because cached results (including recursively expanded ones) may depend on the previous rule.
1937
2452
  *
1938
2453
  * @example
1939
2454
  * ```ts
@@ -1942,7 +2457,14 @@ var AbstractResolver = class {
1942
2457
  */
1943
2458
  addStaticRule(rule) {
1944
2459
  log.debug(`Adding static rule: ${rule.key}`);
2460
+ const previous = this.staticRulesMap.get(rule.key);
1945
2461
  this.staticRulesMap.set(rule.key, rule);
2462
+ if (previous != null) {
2463
+ if (previous.string !== rule.string) this._reindexStaticRuleString(previous.string);
2464
+ this._reindexStaticRuleString(rule.string);
2465
+ } else if (this._staticRulesByString.has(rule.string) === false) this._staticRulesByString.set(rule.string, rule);
2466
+ this._resolvedResultsMap.clear();
2467
+ this._unmatchedStrings.clear();
1946
2468
  return this;
1947
2469
  }
1948
2470
  /**
@@ -1951,7 +2473,7 @@ var AbstractResolver = class {
1951
2473
  * @param key - The key of the static rule to remove.
1952
2474
  * @returns `this` for chaining.
1953
2475
  *
1954
- * @remarks Logs a warning if the key does not exist. Also evicts the cached result for the rule's input string.
2476
+ * @remarks Logs a warning if the key does not exist. The entire resolution cache is cleared because cached results (including recursively expanded ones) may depend on the removed rule.
1955
2477
  *
1956
2478
  * @example
1957
2479
  * ```ts
@@ -1966,16 +2488,32 @@ var AbstractResolver = class {
1966
2488
  }
1967
2489
  log.debug(`Removing static rule: ${key}`);
1968
2490
  this.staticRulesMap.delete(key);
1969
- this._resolvedResultsMap.delete(rule.string);
2491
+ if (this._staticRulesByString.get(rule.string) === rule) this._reindexStaticRuleString(rule.string);
2492
+ this._resolvedResultsMap.clear();
2493
+ this._unmatchedStrings.clear();
1970
2494
  return this;
1971
2495
  }
1972
2496
  /**
2497
+ * Recomputes the string-index entry for a given match string after a rule mutation.
2498
+ *
2499
+ * @param string - The match string whose index entry should be recomputed.
2500
+ *
2501
+ * @remarks Scans `staticRulesMap` in insertion order so the first registered rule matching the string wins, mirroring the pre-index linear-scan behavior. Removes the entry when no rule matches the string anymore.
2502
+ */
2503
+ _reindexStaticRuleString(string) {
2504
+ for (const rule of this.staticRulesMap.values()) if (rule.string === string) {
2505
+ this._staticRulesByString.set(string, rule);
2506
+ return;
2507
+ }
2508
+ this._staticRulesByString.delete(string);
2509
+ }
2510
+ /**
1973
2511
  * Registers a dynamic rule in the resolver.
1974
2512
  *
1975
2513
  * @param rule - The dynamic rule to register.
1976
2514
  * @returns `this` for chaining.
1977
2515
  *
1978
- * @remarks Overwrites any existing dynamic rule with the same key.
2516
+ * @remarks Overwrites any existing dynamic rule with the same key. The entire resolution cache is cleared because cached results (including recursively expanded ones) may depend on the previous rule.
1979
2517
  *
1980
2518
  * @example
1981
2519
  * ```ts
@@ -1985,6 +2523,8 @@ var AbstractResolver = class {
1985
2523
  addDynamicRule(rule) {
1986
2524
  log.debug(`Adding dynamic rule: ${rule.key}`);
1987
2525
  this.dynamicRulesMap.set(rule.key, rule);
2526
+ this._resolvedResultsMap.clear();
2527
+ this._unmatchedStrings.clear();
1988
2528
  return this;
1989
2529
  }
1990
2530
  /**
@@ -1993,7 +2533,7 @@ var AbstractResolver = class {
1993
2533
  * @param key - The key of the dynamic rule to remove.
1994
2534
  * @returns `this` for chaining.
1995
2535
  *
1996
- * @remarks Iterates through all cached results and deletes any whose input string matches the removed rule's pattern. Logs a warning if the key does not exist.
2536
+ * @remarks Logs a warning if the key does not exist. The entire resolution cache is cleared because cached results (including recursively expanded ones) may depend on the removed rule.
1997
2537
  *
1998
2538
  * @example
1999
2539
  * ```ts
@@ -2001,19 +2541,14 @@ var AbstractResolver = class {
2001
2541
  * ```
2002
2542
  */
2003
2543
  removeDynamicRule(key) {
2004
- const rule = this.dynamicRulesMap.get(key);
2005
- if (rule == null) {
2544
+ if (this.dynamicRulesMap.get(key) == null) {
2006
2545
  log.warn(`Dynamic rule not found for removal: ${key}`);
2007
2546
  return this;
2008
2547
  }
2009
2548
  log.debug(`Removing dynamic rule: ${key}`);
2010
- const matchedResolvedStringList = Array.from(this._resolvedResultsMap.keys()).filter((string) => {
2011
- rule.stringPattern.lastIndex = 0;
2012
- return rule.stringPattern.test(string);
2013
- });
2014
2549
  this.dynamicRulesMap.delete(key);
2015
- matchedResolvedStringList.forEach((string) => this._resolvedResultsMap.delete(string));
2016
- log.debug(` - Cleared ${matchedResolvedStringList.length} cached results`);
2550
+ this._resolvedResultsMap.clear();
2551
+ this._unmatchedStrings.clear();
2017
2552
  return this;
2018
2553
  }
2019
2554
  /**
@@ -2022,7 +2557,7 @@ var AbstractResolver = class {
2022
2557
  * @param string - The input string to resolve.
2023
2558
  * @returns The resolved result wrapper, or `null`/`undefined` if no rule matches.
2024
2559
  *
2025
- * @remarks Results are cached for subsequent calls. Invokes `onResolved` after a successful match. Dynamic rule matching is async because `createResolved` may return a `Promise`.
2560
+ * @remarks Results are cached for subsequent calls. Invokes `onResolved` after a successful match. Dynamic rule matching is async because `createResolved` may return a `Promise`. When a dynamic rule's `createResolved` returns `undefined`/`null`, the input is treated as unresolved and no cache entry is stored, so a later resolve call re-invokes the rule.
2026
2561
  *
2027
2562
  * @example
2028
2563
  * ```ts
@@ -2035,7 +2570,11 @@ var AbstractResolver = class {
2035
2570
  log.debug(`Resolved from cache: ${string}`);
2036
2571
  return existedResult;
2037
2572
  }
2038
- const staticRule = Array.from(this.staticRulesMap.values()).find((rule) => rule.string === string);
2573
+ if (this._unmatchedStrings.has(string)) {
2574
+ log.debug(`Resolution failed (cached): ${string}`);
2575
+ return;
2576
+ }
2577
+ const staticRule = this._staticRulesByString.get(string);
2039
2578
  if (staticRule != null) {
2040
2579
  log.debug(`Resolved by static rule: ${staticRule.key}`);
2041
2580
  const resolvedResult = { value: staticRule.resolved };
@@ -2054,13 +2593,19 @@ var AbstractResolver = class {
2054
2593
  }
2055
2594
  }
2056
2595
  if (dynamicRule != null && matched != null) {
2596
+ const value = await dynamicRule.createResolved(matched);
2597
+ if (value == null) {
2598
+ log.debug(`Dynamic rule "${dynamicRule.key}" returned no value for "${string}", treating as unresolved (not cached)`);
2599
+ return;
2600
+ }
2057
2601
  log.debug(`Resolved by dynamic rule: ${dynamicRule.key}`);
2058
- const resolvedResult = { value: await dynamicRule.createResolved(matched) };
2602
+ const resolvedResult = { value };
2059
2603
  this._resolvedResultsMap.set(string, resolvedResult);
2060
2604
  this.onResolved(string, "dynamic", resolvedResult);
2061
2605
  return resolvedResult;
2062
2606
  }
2063
2607
  log.debug(`Resolution failed for: ${string}`);
2608
+ this._unmatchedStrings.add(string);
2064
2609
  }
2065
2610
  /**
2066
2611
  * Updates or creates the cached resolved result for a given input string.
@@ -2072,10 +2617,11 @@ var AbstractResolver = class {
2072
2617
  *
2073
2618
  * @example
2074
2619
  * ```ts
2075
- * resolver._setResolvedResult('hover', ['&:hover'])
2620
+ * resolver._setResolvedResult('hover', ['$:hover'])
2076
2621
  * ```
2077
2622
  */
2078
2623
  _setResolvedResult(string, resolved) {
2624
+ this._unmatchedStrings.delete(string);
2079
2625
  const resolvedResult = this._resolvedResultsMap.get(string);
2080
2626
  if (resolvedResult) {
2081
2627
  resolvedResult.value = resolved;
@@ -2096,7 +2642,7 @@ var AbstractResolver = class {
2096
2642
  * ```ts
2097
2643
  * class SelectorResolver extends RecursiveResolver<string> { }
2098
2644
  * const result = await resolver.resolve('hover-focus')
2099
- * // ['&:hover', '&:focus'] after recursive expansion
2645
+ * // ['$:hover', '$:focus'] after recursive expansion
2100
2646
  * ```
2101
2647
  */
2102
2648
  var RecursiveResolver = class extends AbstractResolver {
@@ -2132,6 +2678,13 @@ var RecursiveResolver = class extends AbstractResolver {
2132
2678
  return result;
2133
2679
  }
2134
2680
  };
2681
+ function createDynamicResolvedFactory(fn) {
2682
+ return async (match) => {
2683
+ const value = await fn(match);
2684
+ if (value == null) return value;
2685
+ return [value].flat(1);
2686
+ };
2687
+ }
2135
2688
  /**
2136
2689
  * Normalizes a user-supplied rule shorthand into a `ResolvedRuleConfig`, a plain redirect string, or `undefined`.
2137
2690
  * @internal
@@ -2146,64 +2699,47 @@ var RecursiveResolver = class extends AbstractResolver {
2146
2699
  * - **Tuple**: `[string, T | T[]]` for static rules, `[RegExp, fn, autocomplete?]` for dynamic rules.
2147
2700
  * - **Object**: `{ [keyName]: string | RegExp, value: T | fn, autocomplete?: string[] }`.
2148
2701
  *
2702
+ * A dynamic rule's value function may return `undefined`/`null` to signal a retryable-unresolved result: the resolver treats the input as unresolved and stores no cache entry, so the rule is re-invoked on a later resolve call.
2703
+ *
2149
2704
  * @example
2150
2705
  * ```ts
2151
- * resolveRuleConfig(['hover', '&:hover'], 'selector')
2706
+ * resolveRuleConfig(['hover', '$:hover'], 'selector')
2152
2707
  * // { type: 'static', rule: { key: 'hover', ... }, autocomplete: ['hover'] }
2153
2708
  * ```
2154
2709
  */
2155
2710
  function resolveRuleConfig(config, keyName) {
2156
2711
  if (typeof config === "string") return config;
2157
- if (Array.isArray(config)) {
2158
- if (typeof config[0] === "string" && typeof config[1] !== "function") return {
2159
- type: "static",
2160
- rule: {
2161
- key: config[0],
2162
- string: config[0],
2163
- resolved: [config[1]].flat(1)
2164
- },
2165
- autocomplete: [config[0]]
2166
- };
2167
- if (config[0] instanceof RegExp && typeof config[1] === "function") {
2168
- const fn = config[1];
2169
- return {
2170
- type: "dynamic",
2171
- rule: {
2172
- key: config[0].source,
2173
- stringPattern: stripGlobalFlag(config[0]),
2174
- createResolved: async (match) => [await fn(match)].flat(1)
2175
- },
2176
- autocomplete: config[2] != null ? [config[2]].flat(1) : []
2177
- };
2178
- }
2179
- return;
2180
- }
2181
2712
  if (typeof config !== "object" || config === null) return;
2182
- const configKey = config[keyName];
2183
- if (typeof configKey === "string" && typeof config.value !== "function") return {
2713
+ const { key, value, autocomplete } = Array.isArray(config) ? {
2714
+ key: config[0],
2715
+ value: config[1],
2716
+ autocomplete: config[2]
2717
+ } : {
2718
+ key: config[keyName],
2719
+ value: config.value,
2720
+ autocomplete: config.autocomplete
2721
+ };
2722
+ if (typeof key === "string" && typeof value !== "function") return {
2184
2723
  type: "static",
2185
2724
  rule: {
2186
- key: configKey,
2187
- string: configKey,
2188
- resolved: [config.value].flat(1)
2725
+ key,
2726
+ string: key,
2727
+ resolved: [value].flat(1)
2189
2728
  },
2190
- autocomplete: [configKey]
2729
+ autocomplete: [key]
2730
+ };
2731
+ if (key instanceof RegExp && typeof value === "function") return {
2732
+ type: "dynamic",
2733
+ rule: {
2734
+ key: key.source,
2735
+ stringPattern: stripGlobalFlag(key),
2736
+ createResolved: createDynamicResolvedFactory(value)
2737
+ },
2738
+ autocomplete: autocomplete != null ? [autocomplete].flat(1) : []
2191
2739
  };
2192
- if (configKey instanceof RegExp && typeof config.value === "function") {
2193
- const fn = config.value;
2194
- return {
2195
- type: "dynamic",
2196
- rule: {
2197
- key: configKey.source,
2198
- stringPattern: stripGlobalFlag(configKey),
2199
- createResolved: async (match) => [await fn(match)].flat(1)
2200
- },
2201
- autocomplete: "autocomplete" in config && config.autocomplete != null ? [config.autocomplete].flat(1) : []
2202
- };
2203
- }
2204
2740
  }
2205
2741
  //#endregion
2206
- //#region src/internal/plugins/selectors.ts
2742
+ //#region src/plugins/selectors.ts
2207
2743
  /**
2208
2744
  * Built-in engine plugin that provides the selector resolution system.
2209
2745
  *
@@ -2222,7 +2758,7 @@ function selectors() {
2222
2758
  return defineEnginePlugin({
2223
2759
  name: "core:selectors",
2224
2760
  rawConfigConfigured(config) {
2225
- configList = config.selectors?.selectors ?? [];
2761
+ configList = config.selectors?.definitions ?? [];
2226
2762
  },
2227
2763
  configureEngine(_engine) {
2228
2764
  engine = _engine;
@@ -2236,11 +2772,8 @@ function selectors() {
2236
2772
  engine.appendAutocomplete({ selectors: resolved });
2237
2773
  return;
2238
2774
  }
2239
- const addRule = {
2240
- static: () => engine.selectors.resolver.addStaticRule(resolved.rule),
2241
- dynamic: () => engine.selectors.resolver.addDynamicRule(resolved.rule)
2242
- }[resolved.type];
2243
- addRule?.();
2775
+ if (resolved.type === "static") engine.selectors.resolver.addStaticRule(resolved.rule);
2776
+ else engine.selectors.resolver.addDynamicRule(resolved.rule);
2244
2777
  engine.appendAutocomplete({ selectors: resolved.autocomplete });
2245
2778
  });
2246
2779
  }
@@ -2268,14 +2801,14 @@ var SelectorResolver = class extends RecursiveResolver {};
2268
2801
  *
2269
2802
  * @example
2270
2803
  * ```ts
2271
- * const resolved = resolveSelectorConfig(['hover', '&:hover'])
2804
+ * const resolved = resolveSelectorConfig(['hover', '$:hover'])
2272
2805
  * ```
2273
2806
  */
2274
2807
  function resolveSelectorConfig(config) {
2275
2808
  return resolveRuleConfig(config, "selector");
2276
2809
  }
2277
2810
  //#endregion
2278
- //#region src/internal/plugins/shortcuts.ts
2811
+ //#region src/plugins/shortcuts.ts
2279
2812
  /**
2280
2813
  * Built-in engine plugin that provides the shortcut resolution system.
2281
2814
  *
@@ -2294,7 +2827,7 @@ function shortcuts() {
2294
2827
  return defineEnginePlugin({
2295
2828
  name: "core:shortcuts",
2296
2829
  rawConfigConfigured(config) {
2297
- configList = config.shortcuts?.shortcuts ?? [];
2830
+ configList = config.shortcuts?.definitions ?? [];
2298
2831
  },
2299
2832
  configureEngine(_engine) {
2300
2833
  engine = _engine;
@@ -2308,11 +2841,8 @@ function shortcuts() {
2308
2841
  engine.appendAutocomplete({ shortcuts: resolved });
2309
2842
  return;
2310
2843
  }
2311
- const addRule = {
2312
- static: () => engine.shortcuts.resolver.addStaticRule(resolved.rule),
2313
- dynamic: () => engine.shortcuts.resolver.addDynamicRule(resolved.rule)
2314
- }[resolved.type];
2315
- addRule?.();
2844
+ if (resolved.type === "static") engine.shortcuts.resolver.addStaticRule(resolved.rule);
2845
+ else engine.shortcuts.resolver.addDynamicRule(resolved.rule);
2316
2846
  engine.appendAutocomplete({ shortcuts: resolved.autocomplete });
2317
2847
  });
2318
2848
  }
@@ -2342,10 +2872,14 @@ function shortcuts() {
2342
2872
  const result = [];
2343
2873
  for (const styleDefinition of styleDefinitions) if ("__shortcut" in styleDefinition) {
2344
2874
  const { __shortcut, ...rest } = styleDefinition;
2875
+ const explicitImportant = rest.__important ?? null;
2345
2876
  const applied = [];
2346
2877
  for (const shortcut of __shortcut == null ? [] : [__shortcut].flat(1)) {
2347
2878
  const resolved = (await engine.shortcuts.resolver.resolve(shortcut)).filter(isNotString);
2348
- applied.push(...resolved);
2879
+ applied.push(...explicitImportant == null ? resolved : resolved.map((definition) => ({
2880
+ __important: explicitImportant,
2881
+ ...definition
2882
+ })));
2349
2883
  }
2350
2884
  result.push(...applied, rest);
2351
2885
  } else result.push(styleDefinition);
@@ -2358,94 +2892,7 @@ function resolveShortcutConfig(config) {
2358
2892
  return resolveRuleConfig(config, "shortcut");
2359
2893
  }
2360
2894
  //#endregion
2361
- //#region src/internal/generated-property-semantics.ts
2362
- const VARIABLE_SEMANTIC_FAMILY_PROPERTIES = {
2363
- "angle": [],
2364
- "color": [
2365
- "accent-color",
2366
- "background-color",
2367
- "border-block-color",
2368
- "border-block-end-color",
2369
- "border-block-start-color",
2370
- "border-bottom-color",
2371
- "border-inline-color",
2372
- "border-inline-end-color",
2373
- "border-inline-start-color",
2374
- "border-left-color",
2375
- "border-right-color",
2376
- "border-top-color",
2377
- "caret-color",
2378
- "color",
2379
- "column-rule-color",
2380
- "flood-color",
2381
- "lighting-color",
2382
- "outline-color",
2383
- "stop-color",
2384
- "stroke-color",
2385
- "text-decoration-color",
2386
- "text-emphasis-color"
2387
- ],
2388
- "easing": ["animation-timing-function", "transition-timing-function"],
2389
- "font-family": ["font-family"],
2390
- "image": [],
2391
- "length": [
2392
- "block-size",
2393
- "border-bottom-width",
2394
- "border-left-width",
2395
- "border-right-width",
2396
- "border-spacing",
2397
- "border-top-width",
2398
- "bottom",
2399
- "font-size",
2400
- "height",
2401
- "inline-size",
2402
- "inset-block-end",
2403
- "inset-block-start",
2404
- "inset-inline-end",
2405
- "inset-inline-start",
2406
- "left",
2407
- "letter-spacing",
2408
- "max-height",
2409
- "max-width",
2410
- "min-height",
2411
- "min-width",
2412
- "outline-offset",
2413
- "right",
2414
- "top",
2415
- "width"
2416
- ],
2417
- "number": [
2418
- "fill-opacity",
2419
- "flex-grow",
2420
- "flex-shrink",
2421
- "flood-opacity",
2422
- "opacity",
2423
- "order",
2424
- "orphans",
2425
- "stop-opacity",
2426
- "stroke-opacity",
2427
- "widows"
2428
- ],
2429
- "percentage": [],
2430
- "position": [],
2431
- "time": [
2432
- "animation-delay",
2433
- "animation-duration",
2434
- "transition-delay",
2435
- "transition-duration"
2436
- ],
2437
- "url": []
2438
- };
2439
- //#endregion
2440
- //#region src/internal/plugins/variables.ts
2441
- const VARIABLE_SEMANTIC_TYPE_PROPERTIES = {
2442
- "color": VARIABLE_SEMANTIC_FAMILY_PROPERTIES.color,
2443
- "length": VARIABLE_SEMANTIC_FAMILY_PROPERTIES.length,
2444
- "time": VARIABLE_SEMANTIC_FAMILY_PROPERTIES.time,
2445
- "number": VARIABLE_SEMANTIC_FAMILY_PROPERTIES.number,
2446
- "easing": VARIABLE_SEMANTIC_FAMILY_PROPERTIES.easing,
2447
- "font-family": VARIABLE_SEMANTIC_FAMILY_PROPERTIES["font-family"]
2448
- };
2895
+ //#region src/plugins/variables.ts
2449
2896
  /**
2450
2897
  * Built-in engine plugin that provides CSS custom properties (variables) with smart pruning and autocomplete integration.
2451
2898
  *
@@ -2492,18 +2939,22 @@ function variables() {
2492
2939
  rawVariables.forEach((variables) => engine.variables.add(variables));
2493
2940
  engine.addPreflight({
2494
2941
  id: "core:variables",
2495
- preflight: async (engine) => {
2942
+ preflight: async (engine, isFormatted, ctx) => {
2496
2943
  const used = /* @__PURE__ */ new Set();
2497
- engine.store.atomicStyles.forEach(({ content: { value } }) => {
2944
+ engine.store.atomicStyles.forEach(({ content: { value } }, id) => {
2945
+ if (ctx?.usedAtomicStyleIds != null && ctx.usedAtomicStyleIds.has(id) === false) return;
2498
2946
  value.flatMap(extractUsedVarNames).forEach((name) => used.add(normalizeVariableName(name)));
2499
2947
  });
2500
2948
  const otherPreflights = engine.config.preflights.filter((p) => p.id !== "core:variables");
2501
- (await Promise.all(otherPreflights.map(({ fn }) => Promise.resolve().then(() => fn(engine, false)).catch(() => null)))).forEach((result) => {
2949
+ (await Promise.all(otherPreflights.map(({ fn }) => engine.invokePreflight(fn, isFormatted, ctx).catch(() => null)))).forEach((result) => {
2502
2950
  if (result == null) return;
2503
2951
  extractUsedVarNamesFromPreflightResult(result).forEach((name) => used.add(name));
2504
2952
  });
2505
- const varMap = /* @__PURE__ */ new Map();
2506
- for (const [name, list] of engine.variables.store.entries()) varMap.set(name, list);
2953
+ const varMap = engine.variables.store;
2954
+ for (const [name, entries] of varMap.entries()) {
2955
+ if (used.has(name)) continue;
2956
+ if (safeSet.has(name) || entries.some((entry) => entry.pruneUnused === false)) used.add(name);
2957
+ }
2507
2958
  const queue = Array.from(used);
2508
2959
  while (queue.length > 0) {
2509
2960
  const name = queue.pop();
@@ -2537,19 +2988,9 @@ function variables() {
2537
2988
  function normalizeVariablesConfig(config) {
2538
2989
  if (config == null) return [];
2539
2990
  const merged = {};
2540
- mergeVariablesBucket(merged, config.colors, "color");
2541
- mergeVariablesBucket(merged, config.lengths, "length");
2542
- mergeVariablesBucket(merged, config.times, "time");
2543
- mergeVariablesBucket(merged, config.numbers, "number");
2544
- mergeVariablesBucket(merged, config.easings, "easing");
2545
- mergeVariablesBucket(merged, config.fontFamilies, "font-family");
2546
- mergeVariablesBucket(merged, config.others);
2991
+ if (config.definitions != null) [config.definitions].flat().forEach((definition) => mergeVariablesDefinition(merged, definition));
2547
2992
  return Object.keys(merged).length > 0 ? [merged] : [];
2548
2993
  }
2549
- function mergeVariablesBucket(target, definitions, semanticType) {
2550
- if (definitions == null) return;
2551
- [definitions].flat().forEach((definition) => mergeVariablesDefinition(target, applyBucketSemanticType(definition, semanticType)));
2552
- }
2553
2994
  function mergeVariablesDefinition(target, source) {
2554
2995
  for (const [key, value] of Object.entries(source)) {
2555
2996
  if (!key.startsWith("--") && isPlainObjectRecord(value) && isPlainObjectRecord(target[key])) {
@@ -2560,53 +3001,16 @@ function mergeVariablesDefinition(target, source) {
2560
3001
  }
2561
3002
  return target;
2562
3003
  }
2563
- function applyBucketSemanticType(definition, semanticType) {
2564
- const result = {};
2565
- for (const [key, value] of Object.entries(definition)) {
2566
- if (key.startsWith("--")) {
2567
- if (semanticType == null) {
2568
- result[key] = value;
2569
- continue;
2570
- }
2571
- if (isPlainObjectRecord(value)) {
2572
- const variableValue = value;
2573
- result[key] = {
2574
- ...variableValue,
2575
- semanticType: mergeSemanticTypes(semanticType, variableValue.semanticType)
2576
- };
2577
- continue;
2578
- }
2579
- result[key] = {
2580
- value,
2581
- semanticType
2582
- };
2583
- continue;
2584
- }
2585
- result[key] = isPlainObjectRecord(value) ? applyBucketSemanticType(value, semanticType) : value;
2586
- }
2587
- return result;
2588
- }
2589
- function mergeSemanticTypes(semanticType, existingSemanticType) {
2590
- const merged = Array.from(new Set([semanticType, ...existingSemanticType == null ? [] : [existingSemanticType].flat()]));
2591
- return merged.length === 1 ? merged[0] : merged;
2592
- }
2593
- function isPlainObjectRecord(value) {
2594
- return typeof value === "object" && value !== null && !Array.isArray(value);
2595
- }
2596
3004
  function createResolveVariablesFn({ pruneUnused: defaultPruneUnused = true } = {}) {
2597
3005
  function _resolveVariables(variables, levels, result) {
2598
3006
  for (const [key, value] of Object.entries(variables)) if (key.startsWith("--")) {
2599
- const { value: varValue, semanticType, autocomplete = {}, pruneUnused = defaultPruneUnused } = isPlainObjectRecord(value) ? value : { value };
3007
+ const { value: varValue, autocomplete = {}, pruneUnused = defaultPruneUnused } = isPlainObjectRecord(value) ? value : { value };
2600
3008
  result.push({
2601
3009
  name: key,
2602
3010
  value: varValue,
2603
3011
  selector: levels.length > 0 ? levels : [":root"],
2604
3012
  autocomplete: {
2605
- asValueOf: resolveAutocompleteValueTargets({
2606
- name: key,
2607
- asValueOf: autocomplete.asValueOf,
2608
- semanticType
2609
- }),
3013
+ asValueOf: resolveAutocompleteValueTargets({ asValueOf: autocomplete.asValueOf }),
2610
3014
  asProperty: autocomplete.asProperty ?? true
2611
3015
  },
2612
3016
  pruneUnused
@@ -2624,27 +3028,18 @@ function createResolveVariablesFn({ pruneUnused: defaultPruneUnused = true } = {
2624
3028
  return _resolveVariables(variables, [], []);
2625
3029
  };
2626
3030
  }
2627
- function resolveAutocompleteValueTargets({ name, asValueOf, semanticType }) {
3031
+ function resolveAutocompleteValueTargets({ asValueOf }) {
2628
3032
  const explicitTargets = asValueOf == null ? [] : [asValueOf].flat().map((value) => String(value));
2629
- const semanticTypes = semanticType == null ? [] : [semanticType].flat().map((value) => String(value));
2630
3033
  if (explicitTargets.includes("-")) return [];
2631
3034
  const targets = /* @__PURE__ */ new Set();
2632
- if (asValueOf == null && semanticTypes.length === 0) targets.add("*");
3035
+ if (asValueOf == null) targets.add("*");
2633
3036
  explicitTargets.forEach((target) => {
2634
3037
  targets.add(target);
2635
3038
  });
2636
- semanticTypes.forEach((family) => {
2637
- const properties = VARIABLE_SEMANTIC_TYPE_PROPERTIES[family];
2638
- if (properties != null) {
2639
- properties.forEach((property) => targets.add(property));
2640
- return;
2641
- }
2642
- log.warn(`Unknown semanticType "${family}" for variable "${name}". Skipping semantic autocomplete expansion.`);
2643
- });
2644
3039
  if (targets.has("*")) return ["*"];
2645
3040
  return [...targets];
2646
3041
  }
2647
- const VAR_NAME_RE = /var\((--[\w-]+)/g;
3042
+ const VAR_NAME_RE = /var\(\s*(--[\w-]+)/g;
2648
3043
  /**
2649
3044
  * Extracts all CSS variable names referenced via `var(--*)` calls in a string.
2650
3045
  *
@@ -2708,7 +3103,7 @@ function extractUsedVarNamesFromPreflightResult(result) {
2708
3103
  return names;
2709
3104
  }
2710
3105
  //#endregion
2711
- //#region src/internal/engine.ts
3106
+ //#region src/engine.ts
2712
3107
  /**
2713
3108
  * Default CSS layer name for preflight styles.
2714
3109
  * @internal
@@ -2764,11 +3159,11 @@ const DEFAULT_LAYERS = {
2764
3159
  async function createEngine(config = {}) {
2765
3160
  log.debug("Creating engine with config:", config);
2766
3161
  const corePlugins = [
2767
- important(),
2768
3162
  variables(),
2769
3163
  keyframes(),
2770
3164
  selectors(),
2771
- shortcuts()
3165
+ shortcuts(),
3166
+ important()
2772
3167
  ];
2773
3168
  log.debug("Core plugins loaded:", corePlugins.length);
2774
3169
  const plugins = resolvePlugins([...corePlugins, ...config.plugins || []]);
@@ -2814,6 +3209,12 @@ var Engine = class {
2814
3209
  /** The engine's runtime store holding registered atomic styles and their ID mappings. */
2815
3210
  store = createEngineStore();
2816
3211
  /**
3212
+ * Absolute paths of external files this engine's config depends on (e.g. token files loaded by plugins).
3213
+ *
3214
+ * @remarks Plugins register paths via `addConfigDependency` during `configureEngine`. Integration layers (e.g. the unplugin) watch these files and re-create the engine when they change.
3215
+ */
3216
+ configDependencies = /* @__PURE__ */ new Set();
3217
+ /**
2817
3218
  * Creates an engine instance from a resolved configuration.
2818
3219
  *
2819
3220
  * @param config - The fully resolved engine configuration.
@@ -2835,6 +3236,45 @@ var Engine = class {
2835
3236
  });
2836
3237
  }
2837
3238
  /**
3239
+ * Invokes a preflight function, memoizing the result in the given render-pass context.
3240
+ *
3241
+ * @param fn - The preflight function to invoke.
3242
+ * @param isFormatted - Whether the preflight should produce formatted output.
3243
+ * @param ctx - The render-pass context created by `renderPreflights`. When provided, each function executes at most once per pass and the context is forwarded to the preflight function.
3244
+ * @returns A promise of the preflight result.
3245
+ *
3246
+ * @remarks Within one render pass each function executes at most once; concurrent callers (e.g. the variables pruning preflight scanning other preflights for `var()` usage) share the same promise. The memoization is scoped to `ctx`, so overlapping `renderPreflights` calls never interfere with each other. Without a context the function is invoked directly without caching — this is a deliberate change from the previous instance-scoped memoization, which could not tell overlapping passes apart. A preflight that inspects other preflights must therefore forward the `ctx` it receives (its third argument); calling with only `(fn, isFormatted)` from inside a pass runs `fn` again instead of reusing the pass result.
3247
+ *
3248
+ * @example
3249
+ * ```ts
3250
+ * const result = await engine.invokePreflight(preflight.fn, false, ctx)
3251
+ * ```
3252
+ */
3253
+ invokePreflight(fn, isFormatted, ctx) {
3254
+ if (ctx == null) return Promise.resolve().then(() => fn(this, isFormatted));
3255
+ let invocation = ctx.invocations.get(fn);
3256
+ if (invocation == null) {
3257
+ invocation = Promise.resolve().then(() => fn(this, isFormatted, ctx));
3258
+ ctx.invocations.set(fn, invocation);
3259
+ }
3260
+ return invocation;
3261
+ }
3262
+ /**
3263
+ * Registers an external file path as a config dependency of this engine.
3264
+ *
3265
+ * @param path - The file path (ideally absolute) the current config was derived from.
3266
+ *
3267
+ * @remarks Call from a plugin (typically in `configureEngine`) after loading data from disk. Integration layers watch registered paths and rebuild the engine when any of them changes.
3268
+ *
3269
+ * @example
3270
+ * ```ts
3271
+ * engine.addConfigDependency('/project/design.md')
3272
+ * ```
3273
+ */
3274
+ addConfigDependency(path) {
3275
+ this.configDependencies.add(path);
3276
+ }
3277
+ /**
2838
3278
  * Fires the `preflightUpdated` hook to notify plugins that preflight content has changed.
2839
3279
  *
2840
3280
  *
@@ -2932,7 +3372,7 @@ var Engine = class {
2932
3372
  * Processes style items through the plugin pipeline and registers the resulting atomic styles in the store.
2933
3373
  *
2934
3374
  * @param itemList - Style items to process: string references (shortcuts) and/or style definition objects.
2935
- * @returns An array of atomic style IDs (and unresolved string references) in insertion order.
3375
+ * @returns An array containing any unresolved string references first, followed by atomic style IDs in resolution order.
2936
3376
  *
2937
3377
  * @remarks Runs `transformStyleItems` and `extractStyleDefinition` hooks, resolves each extracted content into an atomic style, deduplicates by base key, and fires `atomicStyleAdded` for new entries.
2938
3378
  *
@@ -2971,20 +3411,27 @@ var Engine = class {
2971
3411
  * Renders all registered preflight definitions into a CSS string.
2972
3412
  *
2973
3413
  * @param isFormatted - Whether to produce human-readable CSS with newlines and indentation.
3414
+ * @param options - Optional render-pass options.
3415
+ * @param options.usedAtomicStyleIds - Atomic style IDs considered "in use" for this pass. When provided, pruning preflights (variables, keyframes) only consider these atomic styles instead of the whole append-only store; when omitted, all stored atomic styles are considered.
2974
3416
  * @returns The rendered preflight CSS, including `@import` statements, optional `@layer` wrappers, and all preflight content.
2975
3417
  *
2976
- * @remarks Evaluates each preflight function, groups output by layer, wraps unlayered preflights in the default preflights layer (when present), and respects configured layer ordering.
3418
+ * @remarks Evaluates each preflight function, groups output by layer, wraps unlayered preflights in the default preflights layer (when present), and respects configured layer ordering. Each call creates its own `PreflightContext`, so within one pass each preflight function executes exactly once even when passes overlap.
2977
3419
  *
2978
3420
  * @example
2979
3421
  * ```ts
2980
3422
  * const css = await engine.renderPreflights(true)
3423
+ * const scoped = await engine.renderPreflights(true, { usedAtomicStyleIds: ['pk-a'] })
2981
3424
  * ```
2982
3425
  */
2983
- async renderPreflights(isFormatted) {
3426
+ async renderPreflights(isFormatted, options = {}) {
2984
3427
  log.debug("Rendering preflights...");
2985
3428
  const lineEnd = isFormatted ? "\n" : "";
3429
+ const ctx = {
3430
+ invocations: /* @__PURE__ */ new Map(),
3431
+ usedAtomicStyleIds: options.usedAtomicStyleIds == null ? void 0 : new Set(options.usedAtomicStyleIds)
3432
+ };
2986
3433
  const rendered = (await Promise.all(this.config.preflights.map(async ({ layer, fn }) => {
2987
- const result = await fn(this, isFormatted);
3434
+ const result = await this.invokePreflight(fn, isFormatted, ctx);
2988
3435
  return {
2989
3436
  layer,
2990
3437
  css: (typeof result === "string" ? result : await renderPreflightDefinition({
@@ -3181,15 +3628,10 @@ function groupAtomicStylesByLayer({ styles, layerOrder, defaultUtilitiesLayer })
3181
3628
  layerGroups
3182
3629
  };
3183
3630
  }
3184
- function isWithLayer(p) {
3185
- if (typeof p !== "object" || p === null) return false;
3186
- const record = p;
3187
- return typeof record.layer === "string" && record.preflight !== void 0;
3188
- }
3189
- function isWithId(p) {
3631
+ function hasPreflightWrapper(p, key) {
3190
3632
  if (typeof p !== "object" || p === null) return false;
3191
3633
  const record = p;
3192
- return typeof record.id === "string" && record.preflight !== void 0;
3634
+ return typeof record[key] === "string" && record.preflight !== void 0;
3193
3635
  }
3194
3636
  /**
3195
3637
  * Normalizes a `Preflight` input into a `ResolvedPreflight` by extracting optional `layer` and `id` wrappers.
@@ -3208,11 +3650,11 @@ function isWithId(p) {
3208
3650
  function resolvePreflight(preflight) {
3209
3651
  let layer;
3210
3652
  let id;
3211
- if (isWithLayer(preflight)) {
3653
+ if (hasPreflightWrapper(preflight, "layer")) {
3212
3654
  layer = preflight.layer;
3213
3655
  preflight = preflight.preflight;
3214
3656
  }
3215
- if (isWithId(preflight)) {
3657
+ if (hasPreflightWrapper(preflight, "id")) {
3216
3658
  id = preflight.id;
3217
3659
  preflight = preflight.preflight;
3218
3660
  }
@@ -3330,9 +3772,9 @@ function renderAtomicStylesCss({ atomicStyles, isPreview, isFormatted }) {
3330
3772
  const blocks = /* @__PURE__ */ new Map();
3331
3773
  atomicStyles.forEach(({ id, content: { selector: rawSelector, property, value } }) => {
3332
3774
  const { selector } = splitLayerSelector(rawSelector);
3333
- if (selector.some((s) => s.includes("%")) === false || value == null) return;
3775
+ if (selector.some((s) => hasAtomicStyleIdPlaceholder(s)) === false || value == null) return;
3334
3776
  const renderObject = {
3335
- selector: isPreview ? selector : selector.map((s) => s.replace(ATOMIC_STYLE_ID_PLACEHOLDER_RE_GLOBAL, id)),
3777
+ selector: isPreview ? selector : selector.map((s) => replaceAtomicStyleIdPlaceholder(s, id)),
3336
3778
  properties: value.map((v) => ({
3337
3779
  property,
3338
3780
  value: v
@@ -3505,108 +3947,6 @@ async function renderPreflightDefinition(payload) {
3505
3947
  function defineEngineConfig(config) {
3506
3948
  return config;
3507
3949
  }
3508
- /**
3509
- * Identity helper that returns the style definition as-is, providing TypeScript type inference and autocompletion.
3510
- *
3511
- * @typeParam T - The exact literal type of the style definition.
3512
- * @param styleDefinition - A style definition object.
3513
- * @returns The same style definition, unchanged.
3514
- *
3515
- * @remarks A compile-time-only helper with no runtime effect. Useful for extracting a reusable style definition with full type safety.
3516
- *
3517
- * @example
3518
- * ```ts
3519
- * const card = defineStyleDefinition({ padding: '1rem', borderRadius: '0.5rem' })
3520
- * ```
3521
- */
3522
- function defineStyleDefinition(styleDefinition) {
3523
- return styleDefinition;
3524
- }
3525
- /**
3526
- * Identity helper that returns the preflight as-is, providing TypeScript type inference and autocompletion.
3527
- *
3528
- * @typeParam T - The exact literal type of the preflight.
3529
- * @param preflight - A preflight definition: a function, a static string/object, or a wrapper with `layer`/`id` metadata.
3530
- * @returns The same preflight, unchanged.
3531
- *
3532
- * @remarks A compile-time-only helper with no runtime effect. Useful for defining reusable preflight values with type safety.
3533
- *
3534
- * @example
3535
- * ```ts
3536
- * const reset = definePreflight('*, *::before { box-sizing: border-box; }')
3537
- * ```
3538
- */
3539
- function definePreflight(preflight) {
3540
- return preflight;
3541
- }
3542
- /**
3543
- * Identity helper that returns the keyframes definition as-is, providing TypeScript type inference and autocompletion.
3544
- *
3545
- * @typeParam T - The exact literal type of the keyframes configuration.
3546
- * @param keyframes - A keyframes definition: a name string, a tuple, or an object form.
3547
- * @returns The same keyframes definition, unchanged.
3548
- *
3549
- * @remarks A compile-time-only helper with no runtime effect.
3550
- *
3551
- * @example
3552
- * ```ts
3553
- * const spin = defineKeyframes(['spin', { from: { transform: 'rotate(0deg)' }, to: { transform: 'rotate(360deg)' } }])
3554
- * ```
3555
- */
3556
- function defineKeyframes(keyframes) {
3557
- return keyframes;
3558
- }
3559
- /**
3560
- * Identity helper that returns the selector definition as-is, providing TypeScript type inference and autocompletion.
3561
- *
3562
- * @typeParam T - The exact literal type of the selector configuration.
3563
- * @param selector - A selector definition: a string redirect, tuple, or object form.
3564
- * @returns The same selector definition, unchanged.
3565
- *
3566
- * @remarks A compile-time-only helper with no runtime effect.
3567
- *
3568
- * @example
3569
- * ```ts
3570
- * const hover = defineSelector(['hover', '&:hover'])
3571
- * ```
3572
- */
3573
- function defineSelector(selector) {
3574
- return selector;
3575
- }
3576
- /**
3577
- * Identity helper that returns the shortcut definition as-is, providing TypeScript type inference and autocompletion.
3578
- *
3579
- * @typeParam T - The exact literal type of the shortcut configuration.
3580
- * @param shortcut - A shortcut definition: a string redirect, tuple, or object form.
3581
- * @returns The same shortcut definition, unchanged.
3582
- *
3583
- * @remarks A compile-time-only helper with no runtime effect.
3584
- *
3585
- * @example
3586
- * ```ts
3587
- * const btn = defineShortcut(['btn', { padding: '0.5rem 1rem', borderRadius: '0.25rem' }])
3588
- * ```
3589
- */
3590
- function defineShortcut(shortcut) {
3591
- return shortcut;
3592
- }
3593
- /**
3594
- * Identity helper that returns the variables definition as-is, providing TypeScript type inference and autocompletion.
3595
- *
3596
- * @typeParam T - The exact literal type of the variables definition.
3597
- * @param variables - A nested record of CSS custom property definitions.
3598
- * @returns The same variables definition, unchanged.
3599
- *
3600
- * @remarks A compile-time-only helper with no runtime effect.
3601
- *
3602
- * @example
3603
- * ```ts
3604
- * const vars = defineVariables({ '--color-primary': '#3b82f6', '.dark': { '--color-primary': '#60a5fa' } })
3605
- * ```
3606
- */
3607
- function defineVariables(variables) {
3608
- return variables;
3609
- }
3610
3950
  /* c8 ignore end */
3611
3951
  //#endregion
3612
- export { appendAutocomplete, createEngine, createLogger, defineEngineConfig, defineEnginePlugin, defineKeyframes, definePreflight, defineSelector, defineShortcut, defineStyleDefinition, defineVariables, log, renderCSSStyleBlocks, sortLayerNames };
3952
+ export { appendAutocomplete, createEngine, createLogger, defineEngineConfig, defineEnginePlugin, escapeRegExp, isPlainObjectRecord, log, renderCSSStyleBlocks, sortLayerNames };