@aihu/css-engine 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +11 -11
  2. package/crates/aihu-css-core/src/apply.rs +314 -0
  3. package/crates/aihu-css-core/src/bin/main.rs +8 -7
  4. package/crates/aihu-css-core/src/cache.rs +8 -5
  5. package/crates/aihu-css-core/src/emit.rs +110 -30
  6. package/crates/aihu-css-core/src/lib.rs +10 -2
  7. package/crates/aihu-css-core/src/palette.rs +301 -0
  8. package/crates/aihu-css-core/src/style_parser.rs +587 -0
  9. package/crates/aihu-css-core/src/tokens.rs +625 -29
  10. package/crates/aihu-css-core/src/variants.rs +154 -7
  11. package/crates/aihu-css-core/tests/apply.rs +203 -0
  12. package/crates/aihu-css-core/tests/apply_regression.rs +150 -0
  13. package/crates/aihu-css-core/tests/binary_error.rs +61 -0
  14. package/crates/aihu-css-core/tests/cache.rs +8 -8
  15. package/crates/aihu-css-core/tests/emit.rs +95 -36
  16. package/crates/aihu-css-core/tests/parity.rs +274 -0
  17. package/crates/aihu-css-core/tests/progressive_snapshot.rs +8 -8
  18. package/crates/aihu-css-core/tests/scoped_snapshot.rs +49 -11
  19. package/crates/aihu-css-core/tests/snapshots/apply__apply_inside_nested_rule.snap +11 -0
  20. package/crates/aihu-css-core/tests/snapshots/apply__arbitrary_value_utility_in_apply.snap +8 -0
  21. package/crates/aihu-css-core/tests/snapshots/apply__arbitrary_value_variant_in_apply.snap +10 -0
  22. package/crates/aihu-css-core/tests/snapshots/apply__base_utility_inlines_declarations.snap +9 -0
  23. package/crates/aihu-css-core/tests/snapshots/apply__dark_variant_cascade_in_apply.snap +10 -0
  24. package/crates/aihu-css-core/tests/snapshots/apply__data_attribute_variant.snap +10 -0
  25. package/crates/aihu-css-core/tests/snapshots/apply__multi_token_apply.snap +11 -0
  26. package/crates/aihu-css-core/tests/snapshots/apply__multiple_apply_directives_per_rule.snap +12 -0
  27. package/crates/aihu-css-core/tests/snapshots/apply__responsive_variant_wraps_media.snap +12 -0
  28. package/crates/aihu-css-core/tests/snapshots/apply__single_variant_lifts_to_nested_rule.snap +10 -0
  29. package/crates/aihu-css-core/tests/snapshots/progressive_snapshot__anchor_snapshot.snap +1 -0
  30. package/crates/aihu-css-core/tests/snapshots/progressive_snapshot__popover_snapshot.snap +1 -0
  31. package/crates/aihu-css-core/tests/snapshots/progressive_snapshot__text_balance_snapshot.snap +1 -0
  32. package/crates/aihu-css-core/tests/snapshots/progressive_snapshot__view_transition_snapshot.snap +1 -0
  33. package/crates/aihu-css-core/tests/snapshots/scoped_snapshot__scoped_animate_spin_hoists_keyframes.snap +1 -1
  34. package/crates/aihu-css-core/tests/snapshots/scoped_snapshot__scoped_divide_y_nested_rule.snap +1 -0
  35. package/crates/aihu-css-core/tests/snapshots/scoped_snapshot__scoped_output_for_sfc.snap +1 -0
  36. package/crates/aihu-css-core/tests/snapshots/scoped_snapshot__scoped_space_y_nested_rule.snap +1 -0
  37. package/crates/aihu-css-core/tests/snapshots/scoped_snapshot__scoped_transition_and_transform.snap +1 -1
  38. package/crates/aihu-css-core/tests/snapshots/scoped_snapshot__scoped_with_authored_style_block.snap +6 -2
  39. package/crates/aihu-css-core/tests/snapshots/scoped_snapshot__scoped_with_global_style_block.snap +5 -2
  40. package/crates/aihu-css-core/tests/snapshots/scoped_snapshot__standard_variants.snap +1 -0
  41. package/crates/aihu-css-core/tests/snapshots/scoped_snapshot__theme_default_vs_override.snap +2 -0
  42. package/crates/aihu-css-core/tests/snapshots/scoped_snapshot__wc_native_variants.snap +1 -0
  43. package/crates/aihu-css-core/tests/style_parser.rs +257 -0
  44. package/crates/aihu-css-core/tests/tokens.rs +52 -0
  45. package/dist/index.d.ts +0 -9
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +26 -18
  48. package/dist/index.js.map +1 -1
  49. package/package.json +6 -6
@@ -22,7 +22,7 @@ fn sfc(classes: &str) -> aihu_css_core::SfcAst {
22
22
 
23
23
  #[test]
24
24
  fn view_transition_is_supports_gated_css_only() {
25
- let css = compile_sfc_scoped(&sfc("view-transition:hero"));
25
+ let css = compile_sfc_scoped(&sfc("view-transition:hero")).unwrap();
26
26
  assert!(
27
27
  css.contains("@supports (view-transition-name: none)"),
28
28
  "view-transition gated behind @supports: {css}"
@@ -36,14 +36,14 @@ fn view_transition_is_supports_gated_css_only() {
36
36
 
37
37
  #[test]
38
38
  fn view_transition_snapshot() {
39
- insta::assert_snapshot!(compile_sfc_scoped(&sfc("view-transition:hero")));
39
+ insta::assert_snapshot!(compile_sfc_scoped(&sfc("view-transition:hero")).unwrap());
40
40
  }
41
41
 
42
42
  // ── Task 6: anchor: (@supports gate + JS fallback marker) ────────────────────
43
43
 
44
44
  #[test]
45
45
  fn anchor_is_supports_gated_with_js_marker() {
46
- let css = compile_sfc_scoped(&sfc("anchor:tooltip"));
46
+ let css = compile_sfc_scoped(&sfc("anchor:tooltip")).unwrap();
47
47
  assert!(
48
48
  css.contains("@supports (anchor-name: --a)"),
49
49
  "anchor gated behind @supports (anchor-name): {css}"
@@ -57,14 +57,14 @@ fn anchor_is_supports_gated_with_js_marker() {
57
57
 
58
58
  #[test]
59
59
  fn anchor_snapshot() {
60
- insta::assert_snapshot!(compile_sfc_scoped(&sfc("anchor:tooltip")));
60
+ insta::assert_snapshot!(compile_sfc_scoped(&sfc("anchor:tooltip")).unwrap());
61
61
  }
62
62
 
63
63
  // ── Task 7: popover: (@supports gate + portal JS fallback marker) ────────────
64
64
 
65
65
  #[test]
66
66
  fn popover_is_supports_gated_with_js_marker() {
67
- let css = compile_sfc_scoped(&sfc("popover:menu"));
67
+ let css = compile_sfc_scoped(&sfc("popover:menu")).unwrap();
68
68
  assert!(
69
69
  css.contains("@supports (selector(:popover-open))"),
70
70
  "popover gated behind @supports selector(:popover-open): {css}"
@@ -77,14 +77,14 @@ fn popover_is_supports_gated_with_js_marker() {
77
77
 
78
78
  #[test]
79
79
  fn popover_snapshot() {
80
- insta::assert_snapshot!(compile_sfc_scoped(&sfc("popover:menu")));
80
+ insta::assert_snapshot!(compile_sfc_scoped(&sfc("popover:menu")).unwrap());
81
81
  }
82
82
 
83
83
  // ── Task 8: text-balance: (no gate, no JS) ───────────────────────────────────
84
84
 
85
85
  #[test]
86
86
  fn text_balance_no_gate_no_js() {
87
- let css = compile_sfc_scoped(&sfc("text-balance:"));
87
+ let css = compile_sfc_scoped(&sfc("text-balance:")).unwrap();
88
88
  assert!(css.contains("text-wrap: balance"), "emits text-wrap: balance: {css}");
89
89
  assert!(
90
90
  !css.contains("@supports"),
@@ -98,5 +98,5 @@ fn text_balance_no_gate_no_js() {
98
98
 
99
99
  #[test]
100
100
  fn text_balance_snapshot() {
101
- insta::assert_snapshot!(compile_sfc_scoped(&sfc("text-balance:")));
101
+ insta::assert_snapshot!(compile_sfc_scoped(&sfc("text-balance:")).unwrap());
102
102
  }
@@ -25,7 +25,7 @@ fn flat_output_for_class_list() {
25
25
 
26
26
  #[test]
27
27
  fn scoped_output_for_sfc() {
28
- insta::assert_snapshot!(compile_sfc_scoped(&sfc("bg-primary p-4 rounded-lg")));
28
+ insta::assert_snapshot!(compile_sfc_scoped(&sfc("bg-primary p-4 rounded-lg")).unwrap());
29
29
  }
30
30
 
31
31
  #[test]
@@ -35,7 +35,7 @@ fn scoped_with_authored_style_block() {
35
35
  "meta":{"name":"Card"},
36
36
  "template":[{"kind":"element","tag":"div","attrs":[
37
37
  {"kind":"static","name":"class","value":"p-4 shadow-md"}],"children":[]}]}"#;
38
- insta::assert_snapshot!(compile_sfc_scoped(&ast(json)));
38
+ insta::assert_snapshot!(compile_sfc_scoped(&ast(json)).unwrap());
39
39
  }
40
40
 
41
41
  #[test]
@@ -43,14 +43,14 @@ fn scoped_with_global_style_block() {
43
43
  let json = r#"{"tag":"X","astVersion":1,
44
44
  "style":{"content":"body { margin: 0; }","scope":"global"},
45
45
  "meta":{"name":"X"},"template":null}"#;
46
- insta::assert_snapshot!(compile_sfc_scoped(&ast(json)));
46
+ insta::assert_snapshot!(compile_sfc_scoped(&ast(json)).unwrap());
47
47
  }
48
48
 
49
49
  #[test]
50
50
  fn scoped_space_y_nested_rule() {
51
51
  // Locks in the nested `& > * + *` sibling-margin shape inside component
52
52
  // scope (Round 1: tailwind-support `space-x/y-*` family).
53
- insta::assert_snapshot!(compile_sfc_scoped(&sfc("space-y-4")));
53
+ insta::assert_snapshot!(compile_sfc_scoped(&sfc("space-y-4")).unwrap());
54
54
  }
55
55
 
56
56
  #[test]
@@ -59,7 +59,7 @@ fn scoped_divide_y_nested_rule() {
59
59
  // scope (Round 2: tailwind-support `divide-x/y-*` family). Confirms the
60
60
  // nested rule survives the scoped CSS-nesting emission path, mirroring
61
61
  // `scoped_space_y_nested_rule`.
62
- insta::assert_snapshot!(compile_sfc_scoped(&sfc("divide-y-2")));
62
+ insta::assert_snapshot!(compile_sfc_scoped(&sfc("divide-y-2")).unwrap());
63
63
  }
64
64
 
65
65
  #[test]
@@ -67,7 +67,7 @@ fn scoped_animate_spin_hoists_keyframes() {
67
67
  // Locks the `animate-*` emission shape: the scoped `.animate-spin` rule
68
68
  // followed by a hoisted top-level `@keyframes spin` sibling (Round 2:
69
69
  // tailwind-support `motion` track).
70
- insta::assert_snapshot!(compile_sfc_scoped(&sfc("animate-spin")));
70
+ insta::assert_snapshot!(compile_sfc_scoped(&sfc("animate-spin")).unwrap());
71
71
  }
72
72
 
73
73
  #[test]
@@ -75,32 +75,70 @@ fn scoped_transition_and_transform() {
75
75
  // Locks transition shorthand + a transform utility under component scope.
76
76
  insta::assert_snapshot!(compile_sfc_scoped(&sfc(
77
77
  "transition-transform duration-300 hover:scale-105"
78
- )));
78
+ )).unwrap());
79
79
  }
80
80
 
81
81
  #[test]
82
82
  fn wc_native_variants() {
83
83
  insta::assert_snapshot!(compile_sfc_scoped(&sfc(
84
84
  "host:bg-primary slotted:p-4 slotted-img:rounded-lg part-thumb:bg-accent host-context-dark:bg-surface"
85
- )));
85
+ )).unwrap());
86
86
  }
87
87
 
88
88
  #[test]
89
89
  fn standard_variants() {
90
90
  insta::assert_snapshot!(compile_sfc_scoped(&sfc(
91
91
  "hover:bg-primary focus:text-accent dark:bg-surface md:p-8 [&>div]:text-primary md:hover:bg-primary"
92
- )));
92
+ )).unwrap());
93
+ }
94
+
95
+ #[test]
96
+ fn style_block_does_not_suppress_scanned_utilities() {
97
+ // Regression for #278: an `@style` block must NOT make the utility-class
98
+ // scanner mutually exclusive. Both the scanned template utilities AND the
99
+ // authored `@style` content must land in the same scoped stylesheet.
100
+ //
101
+ // Repro: `<div class="text-3xl gap-4">` + `@style { .__probe__ { ... } }`.
102
+ // Before the fix the sheet contained ONLY `.__probe__`; the utilities
103
+ // vanished. Assert all three rules coexist (concatenated).
104
+ let json = r#"{"tag":"Probe","astVersion":1,
105
+ "style":{"content":".__probe__ { color: rgb(1,2,3); }","scope":"scoped"},
106
+ "meta":{"name":"Probe"},
107
+ "template":[{"kind":"element","tag":"div","attrs":[
108
+ {"kind":"static","name":"class","value":"text-3xl gap-4"}],"children":[]}]}"#;
109
+ // `.unwrap()` added in the PR-1 merge: compile_sfc_scoped now returns Result.
110
+ let css = compile_sfc_scoped(&ast(json)).unwrap();
111
+
112
+ // Scanned template utilities survive.
113
+ assert!(
114
+ css.contains(".text-3xl"),
115
+ "scanned utility .text-3xl missing when @style present:\n{css}"
116
+ );
117
+ assert!(
118
+ css.contains(".gap-4"),
119
+ "scanned utility .gap-4 missing when @style present:\n{css}"
120
+ );
121
+ // Authored @style content survives. (PR-1 merge: authored @style is now
122
+ // re-rendered through the shared @style parser to enable @apply, so it is
123
+ // whitespace-normalized rather than byte-identical — assert the selector
124
+ // and declaration are present, not the exact single-line form. The #278
125
+ // regression intent (scanned utilities AND authored @style coexist) holds.)
126
+ assert!(css.contains(".__probe__"), "authored @style selector missing:\n{css}");
127
+ assert!(
128
+ css.contains("color: rgb(1,2,3)"),
129
+ "authored @style declaration missing:\n{css}"
130
+ );
93
131
  }
94
132
 
95
133
  #[test]
96
134
  fn theme_default_vs_override() {
97
- let default = compile_sfc_scoped(&sfc("bg-primary"));
135
+ let default = compile_sfc_scoped(&sfc("bg-primary")).unwrap();
98
136
  let json = r#"{"tag":"X","astVersion":1,
99
137
  "style":{"content":"@theme { --color-primary: oklch(0.55 0.18 28); }","scope":"scoped"},
100
138
  "meta":{"name":"X"},
101
139
  "template":[{"kind":"element","tag":"div","attrs":[
102
140
  {"kind":"static","name":"class","value":"bg-primary"}],"children":[]}]}"#;
103
- let overridden = compile_sfc_scoped(&ast(json));
141
+ let overridden = compile_sfc_scoped(&ast(json)).unwrap();
104
142
  insta::assert_snapshot!(format!(
105
143
  "--- default ---\n{default}\n--- override ---\n{overridden}"
106
144
  ));
@@ -0,0 +1,11 @@
1
+ ---
2
+ source: packages/css-engine/crates/aihu-css-core/tests/apply.rs
3
+ assertion_line: 91
4
+ expression: css
5
+ ---
6
+ .card {
7
+ display: grid;
8
+ & .title {
9
+ font-weight: 500;
10
+ }
11
+ }
@@ -0,0 +1,8 @@
1
+ ---
2
+ source: packages/css-engine/crates/aihu-css-core/tests/apply.rs
3
+ assertion_line: 103
4
+ expression: css
5
+ ---
6
+ .swatch {
7
+ background-color: #fff;
8
+ }
@@ -0,0 +1,10 @@
1
+ ---
2
+ source: packages/css-engine/crates/aihu-css-core/tests/apply.rs
3
+ assertion_line: 111
4
+ expression: css
5
+ ---
6
+ .swatch {
7
+ &:hover {
8
+ background-color: #fff;
9
+ }
10
+ }
@@ -0,0 +1,9 @@
1
+ ---
2
+ source: packages/css-engine/crates/aihu-css-core/tests/apply.rs
3
+ assertion_line: 39
4
+ expression: css
5
+ ---
6
+ .btn {
7
+ display: inline-flex;
8
+ align-items: center;
9
+ }
@@ -0,0 +1,10 @@
1
+ ---
2
+ source: packages/css-engine/crates/aihu-css-core/tests/apply.rs
3
+ assertion_line: 143
4
+ expression: css
5
+ ---
6
+ .panel {
7
+ :host([data-theme="dark"]) &, :root.dark & {
8
+ background-color: var(--color-surface);
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ ---
2
+ source: packages/css-engine/crates/aihu-css-core/tests/apply.rs
3
+ assertion_line: 131
4
+ expression: css
5
+ ---
6
+ .btn {
7
+ &[data-state="open"] {
8
+ background-color: var(--color-accent);
9
+ }
10
+ }
@@ -0,0 +1,11 @@
1
+ ---
2
+ source: packages/css-engine/crates/aihu-css-core/tests/apply.rs
3
+ assertion_line: 66
4
+ expression: css
5
+ ---
6
+ .btn {
7
+ display: inline-flex;
8
+ align-items: center;
9
+ justify-content: center;
10
+ border-radius: 0.375rem;
11
+ }
@@ -0,0 +1,12 @@
1
+ ---
2
+ source: packages/css-engine/crates/aihu-css-core/tests/apply.rs
3
+ assertion_line: 78
4
+ expression: css
5
+ ---
6
+ .btn {
7
+ display: inline-flex;
8
+ border-radius: 0.375rem;
9
+ &:hover {
10
+ background-color: var(--color-accent);
11
+ }
12
+ }
@@ -0,0 +1,12 @@
1
+ ---
2
+ source: packages/css-engine/crates/aihu-css-core/tests/apply.rs
3
+ assertion_line: 120
4
+ expression: css
5
+ ---
6
+ .grid {
7
+ @media (min-width: 48rem) {
8
+ & {
9
+ display: flex;
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,10 @@
1
+ ---
2
+ source: packages/css-engine/crates/aihu-css-core/tests/apply.rs
3
+ assertion_line: 54
4
+ expression: css
5
+ ---
6
+ .btn {
7
+ &:hover {
8
+ background-color: var(--color-accent);
9
+ }
10
+ }
@@ -20,6 +20,7 @@ expression: "compile_sfc_scoped(&sfc(\"anchor:tooltip\"))"
20
20
  --color-surface: #faf8f4;
21
21
  --color-surface-foreground: #1a1d24;
22
22
  }
23
+ *, ::before, ::after { border-style: solid; border-width: 0; }
23
24
  @supports (anchor-name: --a) {
24
25
  .anchor\:tooltip { anchor-name: --tooltip; position-anchor: --tooltip; }
25
26
  }
@@ -20,6 +20,7 @@ expression: "compile_sfc_scoped(&sfc(\"popover:menu\"))"
20
20
  --color-surface: #faf8f4;
21
21
  --color-surface-foreground: #1a1d24;
22
22
  }
23
+ *, ::before, ::after { border-style: solid; border-width: 0; }
23
24
  @supports (selector(:popover-open)) {
24
25
  .popover\:menu:popover-open { position: fixed; margin: 0; inset: auto; }
25
26
  }
@@ -20,4 +20,5 @@ expression: "compile_sfc_scoped(&sfc(\"text-balance:\"))"
20
20
  --color-surface: #faf8f4;
21
21
  --color-surface-foreground: #1a1d24;
22
22
  }
23
+ *, ::before, ::after { border-style: solid; border-width: 0; }
23
24
  .text-balance { text-wrap: balance; }
@@ -20,6 +20,7 @@ expression: "compile_sfc_scoped(&sfc(\"view-transition:hero\"))"
20
20
  --color-surface: #faf8f4;
21
21
  --color-surface-foreground: #1a1d24;
22
22
  }
23
+ *, ::before, ::after { border-style: solid; border-width: 0; }
23
24
  @supports (view-transition-name: none) {
24
25
  .view-transition\:hero { view-transition-name: hero; }
25
26
  }
@@ -1,6 +1,5 @@
1
1
  ---
2
2
  source: packages/css-engine/crates/aihu-css-core/tests/scoped_snapshot.rs
3
- assertion_line: 61
4
3
  expression: "compile_sfc_scoped(&sfc(\"animate-spin\"))"
5
4
  ---
6
5
  :host {
@@ -21,5 +20,6 @@ expression: "compile_sfc_scoped(&sfc(\"animate-spin\"))"
21
20
  --color-surface: #faf8f4;
22
21
  --color-surface-foreground: #1a1d24;
23
22
  }
23
+ *, ::before, ::after { border-style: solid; border-width: 0; }
24
24
  .animate-spin { animation: spin 1s linear infinite; }
25
25
  @keyframes spin { to { transform: rotate(360deg); } }
@@ -20,4 +20,5 @@ expression: "compile_sfc_scoped(&sfc(\"divide-y-2\"))"
20
20
  --color-surface: #faf8f4;
21
21
  --color-surface-foreground: #1a1d24;
22
22
  }
23
+ *, ::before, ::after { border-style: solid; border-width: 0; }
23
24
  .divide-y-2 { & > * + * { border-block-width: 2px; } }
@@ -20,6 +20,7 @@ expression: "compile_sfc_scoped(&sfc(\"bg-primary p-4 rounded-lg\"))"
20
20
  --color-surface: #faf8f4;
21
21
  --color-surface-foreground: #1a1d24;
22
22
  }
23
+ *, ::before, ::after { border-style: solid; border-width: 0; }
23
24
  .bg-primary { background-color: var(--color-primary); }
24
25
  .p-4 { padding: 1rem; }
25
26
  .rounded-lg { border-radius: 0.5rem; }
@@ -20,4 +20,5 @@ expression: "compile_sfc_scoped(&sfc(\"space-y-4\"))"
20
20
  --color-surface: #faf8f4;
21
21
  --color-surface-foreground: #1a1d24;
22
22
  }
23
+ *, ::before, ::after { border-style: solid; border-width: 0; }
23
24
  .space-y-4 { & > * + * { margin-block-start: 1rem; } }
@@ -1,6 +1,5 @@
1
1
  ---
2
2
  source: packages/css-engine/crates/aihu-css-core/tests/scoped_snapshot.rs
3
- assertion_line: 67
4
3
  expression: "compile_sfc_scoped(&sfc(\"transition-transform duration-300 hover:scale-105\"))"
5
4
  ---
6
5
  :host {
@@ -21,6 +20,7 @@ expression: "compile_sfc_scoped(&sfc(\"transition-transform duration-300 hover:s
21
20
  --color-surface: #faf8f4;
22
21
  --color-surface-foreground: #1a1d24;
23
22
  }
23
+ *, ::before, ::after { border-style: solid; border-width: 0; }
24
24
  .duration-300 { transition-duration: 300ms; }
25
25
  .hover\:scale-105:hover { transform: scale(1.05); }
26
26
  .transition-transform { transition-property: transform; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 150ms; }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  source: packages/css-engine/crates/aihu-css-core/tests/scoped_snapshot.rs
3
- expression: compile_sfc_scoped(&ast(json))
3
+ expression: compile_sfc_scoped(&ast(json)).unwrap()
4
4
  ---
5
5
  :host {
6
6
  --color-accent: #c8543a;
@@ -20,7 +20,11 @@ expression: compile_sfc_scoped(&ast(json))
20
20
  --color-surface: #faf8f4;
21
21
  --color-surface-foreground: #1a1d24;
22
22
  }
23
+ *, ::before, ::after { border-style: solid; border-width: 0; }
23
24
  .p-4 { padding: 1rem; }
24
25
  .shadow-md { box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1); }
25
26
  /* authored @style (scoped) */
26
- .inner { display: grid; gap: 1rem; }
27
+ .inner {
28
+ display: grid;
29
+ gap: 1rem;
30
+ }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  source: packages/css-engine/crates/aihu-css-core/tests/scoped_snapshot.rs
3
- expression: compile_sfc_scoped(&ast(json))
3
+ expression: compile_sfc_scoped(&ast(json)).unwrap()
4
4
  ---
5
5
  :host {
6
6
  --color-accent: #c8543a;
@@ -20,5 +20,8 @@ expression: compile_sfc_scoped(&ast(json))
20
20
  --color-surface: #faf8f4;
21
21
  --color-surface-foreground: #1a1d24;
22
22
  }
23
+ *, ::before, ::after { border-style: solid; border-width: 0; }
23
24
  /* authored @style ($global — unscoped) */
24
- body { margin: 0; }
25
+ body {
26
+ margin: 0;
27
+ }
@@ -20,6 +20,7 @@ expression: "compile_sfc_scoped(&sfc(\"hover:bg-primary focus:text-accent dark:b
20
20
  --color-surface: #faf8f4;
21
21
  --color-surface-foreground: #1a1d24;
22
22
  }
23
+ *, ::before, ::after { border-style: solid; border-width: 0; }
23
24
  .\[&>div\]\:text-primary>div { color: var(--color-primary); }
24
25
  /* dark cascade (Firefox-safe; see decision-firefox-host-context-workaround) */
25
26
  :host([data-theme="dark"]) .dark\:bg-surface, :root.dark .dark\:bg-surface { background-color: var(--color-surface); }
@@ -21,6 +21,7 @@ expression: "format!(\"--- default ---\\n{default}\\n--- override ---\\n{overrid
21
21
  --color-surface: #faf8f4;
22
22
  --color-surface-foreground: #1a1d24;
23
23
  }
24
+ *, ::before, ::after { border-style: solid; border-width: 0; }
24
25
  .bg-primary { background-color: var(--color-primary); }
25
26
 
26
27
  --- override ---
@@ -42,4 +43,5 @@ expression: "format!(\"--- default ---\\n{default}\\n--- override ---\\n{overrid
42
43
  --color-surface: #faf8f4;
43
44
  --color-surface-foreground: #1a1d24;
44
45
  }
46
+ *, ::before, ::after { border-style: solid; border-width: 0; }
45
47
  .bg-primary { background-color: var(--color-primary); }
@@ -20,6 +20,7 @@ expression: "compile_sfc_scoped(&sfc(\"host:bg-primary slotted:p-4 slotted-img:r
20
20
  --color-surface: #faf8f4;
21
21
  --color-surface-foreground: #1a1d24;
22
22
  }
23
+ *, ::before, ::after { border-style: solid; border-width: 0; }
23
24
  /* dark cascade (Firefox-safe; see decision-firefox-host-context-workaround) */
24
25
  :host([data-theme="dark"]) .host-context-dark\:bg-surface, :root.dark .host-context-dark\:bg-surface { background-color: var(--color-surface); }
25
26
  :host(.host\:bg-primary) { background-color: var(--color-primary); }