css-is-awesome 1.1.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 (198) hide show
  1. package/AGENTS.md +343 -0
  2. package/CHANGELOG.md +1036 -0
  3. package/CLAUDE.md +9 -0
  4. package/CONTRACT.md +580 -0
  5. package/GEMINI.md +9 -0
  6. package/LICENSE +21 -0
  7. package/LICENSE-third-party +88 -0
  8. package/MIGRATION.md +312 -0
  9. package/README.md +380 -0
  10. package/ROADMAP.md +714 -0
  11. package/THEMING.md +290 -0
  12. package/THREE-TIERS.md +158 -0
  13. package/VERSIONING.md +200 -0
  14. package/_index.scss +34 -0
  15. package/api.scss +16 -0
  16. package/bin/README.md +57 -0
  17. package/bin/cia.cjs +114 -0
  18. package/bin/migrate-bootstrap.cjs +427 -0
  19. package/bin/migrate-tailwind.cjs +832 -0
  20. package/css-is-awesome.instructions.md +533 -0
  21. package/dist/css-is-awesome.core.css +598 -0
  22. package/dist/css-is-awesome.core.min.css +1 -0
  23. package/dist/css-is-awesome.css +3733 -0
  24. package/dist/css-is-awesome.min.css +1 -0
  25. package/dist/css-is-awesome.utilities.css +2445 -0
  26. package/dist/css-is-awesome.utilities.min.css +1 -0
  27. package/dist/tokens.css +508 -0
  28. package/dist/tokens.d.ts +266 -0
  29. package/dist/tokens.min.css +1 -0
  30. package/figma-tokens/README.md +57 -0
  31. package/figma-tokens/primitives-brand.scss +121 -0
  32. package/figma-tokens/semantic-dark.scss +61 -0
  33. package/figma-tokens/semantic-light.scss +61 -0
  34. package/figma-tokens/tokens.json +144 -0
  35. package/llm.txt +183 -0
  36. package/mcp/server.cjs +1495 -0
  37. package/package.json +199 -0
  38. package/public/icons/README.md +278 -0
  39. package/public/icons/arrow-right.svg +4 -0
  40. package/public/icons/check.svg +4 -0
  41. package/public/icons/chevron-down.svg +4 -0
  42. package/public/icons/close.svg +4 -0
  43. package/public/icons/core/arrow-down.svg +13 -0
  44. package/public/icons/core/arrow-left.svg +13 -0
  45. package/public/icons/core/arrow-right.svg +13 -0
  46. package/public/icons/core/arrow-up.svg +13 -0
  47. package/public/icons/core/bell.svg +13 -0
  48. package/public/icons/core/calendar.svg +15 -0
  49. package/public/icons/core/check.svg +12 -0
  50. package/public/icons/core/chevron-down.svg +12 -0
  51. package/public/icons/core/chevron-left.svg +12 -0
  52. package/public/icons/core/chevron-right.svg +12 -0
  53. package/public/icons/core/chevron-up.svg +12 -0
  54. package/public/icons/core/clock.svg +13 -0
  55. package/public/icons/core/close.svg +13 -0
  56. package/public/icons/core/copy.svg +13 -0
  57. package/public/icons/core/download.svg +14 -0
  58. package/public/icons/core/edit.svg +13 -0
  59. package/public/icons/core/error.svg +14 -0
  60. package/public/icons/core/external-link.svg +14 -0
  61. package/public/icons/core/eye-off.svg +15 -0
  62. package/public/icons/core/eye.svg +13 -0
  63. package/public/icons/core/filter.svg +12 -0
  64. package/public/icons/core/heart.svg +12 -0
  65. package/public/icons/core/help.svg +14 -0
  66. package/public/icons/core/home.svg +13 -0
  67. package/public/icons/core/info.svg +14 -0
  68. package/public/icons/core/loading.svg +12 -0
  69. package/public/icons/core/lock.svg +13 -0
  70. package/public/icons/core/mail.svg +13 -0
  71. package/public/icons/core/menu.svg +14 -0
  72. package/public/icons/core/message.svg +12 -0
  73. package/public/icons/core/minus.svg +12 -0
  74. package/public/icons/core/more-horizontal.svg +14 -0
  75. package/public/icons/core/pause.svg +13 -0
  76. package/public/icons/core/play.svg +12 -0
  77. package/public/icons/core/plus.svg +13 -0
  78. package/public/icons/core/refresh.svg +15 -0
  79. package/public/icons/core/save.svg +14 -0
  80. package/public/icons/core/search.svg +13 -0
  81. package/public/icons/core/settings.svg +13 -0
  82. package/public/icons/core/share.svg +14 -0
  83. package/public/icons/core/sort.svg +15 -0
  84. package/public/icons/core/star.svg +12 -0
  85. package/public/icons/core/success.svg +13 -0
  86. package/public/icons/core/trash.svg +16 -0
  87. package/public/icons/core/unlock.svg +13 -0
  88. package/public/icons/core/upload.svg +14 -0
  89. package/public/icons/core/user.svg +13 -0
  90. package/public/icons/core/users.svg +15 -0
  91. package/public/icons/core/warning.svg +14 -0
  92. package/public/icons/download.svg +4 -0
  93. package/public/icons/edit.svg +4 -0
  94. package/public/icons/menu.svg +4 -0
  95. package/public/icons/search.svg +4 -0
  96. package/public/theme.css +4179 -0
  97. package/public/themes/README.md +102 -0
  98. package/public/themes/boilerplate/theme.css +154 -0
  99. package/public/themes/boilerplate-dark/theme.css +171 -0
  100. package/public/themes/boilerplate-light/theme.css +171 -0
  101. package/public/themes/cupertino/theme.css +165 -0
  102. package/public/themes/cupertino-dark/theme.css +200 -0
  103. package/public/themes/cupertino-light/theme.css +227 -0
  104. package/public/themes/glass/theme.css +190 -0
  105. package/public/themes/glass-dark/theme.css +201 -0
  106. package/public/themes/glass-light/theme.css +229 -0
  107. package/public/themes/graphite/theme.css +155 -0
  108. package/public/themes/graphite-dark/theme.css +223 -0
  109. package/public/themes/graphite-light/theme.css +191 -0
  110. package/public/themes/press/theme.css +189 -0
  111. package/public/themes/press-dark/theme.css +199 -0
  112. package/public/themes/press-light/theme.css +235 -0
  113. package/public/themes/prism/theme.css +159 -0
  114. package/public/themes/prism-dark/theme.css +185 -0
  115. package/public/themes/prism-light/theme.css +188 -0
  116. package/public/themes/sketchbook/theme.css +152 -0
  117. package/public/themes/sketchbook-dark/theme.css +194 -0
  118. package/public/themes/sketchbook-light/theme.css +188 -0
  119. package/public/themes/terminal/theme.css +159 -0
  120. package/public/themes/terminal-dark/theme.css +229 -0
  121. package/public/themes/terminal-light/theme.css +152 -0
  122. package/scripts/README.md +70 -0
  123. package/scripts/icon-contract.json +67 -0
  124. package/scripts/icon-validator.js +205 -0
  125. package/scripts/prepare-dist.mjs +65 -0
  126. package/scripts/theme-a11y.js +415 -0
  127. package/scripts/theme-contract.json +171 -0
  128. package/scripts/theme-validator.js +674 -0
  129. package/scss/README.md +55 -0
  130. package/scss/_animations-utilities.scss +107 -0
  131. package/scss/_animations.scss +248 -0
  132. package/scss/_app-styles.scss +15 -0
  133. package/scss/_generator.scss +174 -0
  134. package/scss/_icons.scss +475 -0
  135. package/scss/_index.scss +17 -0
  136. package/scss/_layout.scss +597 -0
  137. package/scss/_mixins.scss +1036 -0
  138. package/scss/_system.scss +291 -0
  139. package/scss/_utilities.scss +377 -0
  140. package/scss/api.scss +61 -0
  141. package/scss/components/_accordion.scss +72 -0
  142. package/scss/components/_buttons.scss +171 -0
  143. package/scss/components/_copy-button.scss +69 -0
  144. package/scss/components/_data.scss +190 -0
  145. package/scss/components/_feedback.scss +197 -0
  146. package/scss/components/_forms.scss +272 -0
  147. package/scss/components/_index.scss +17 -0
  148. package/scss/components/_navigation.scss +186 -0
  149. package/scss/components/_overlay.scss +259 -0
  150. package/scss/components/_stepper.scss +159 -0
  151. package/scss/components/_tabs.scss +72 -0
  152. package/scss/core.scss +54 -0
  153. package/scss/examples/_theming.scss +107 -0
  154. package/scss/examples/_usage.scss +317 -0
  155. package/scss/main.scss +64 -0
  156. package/scss/recipes/README.md +110 -0
  157. package/scss/recipes/_bare-tags.scss +232 -0
  158. package/scss/recipes/_recipe-template.md +119 -0
  159. package/scss/recipes/combobox.md +509 -0
  160. package/scss/recipes/dialog.md +265 -0
  161. package/scss/recipes/print-to-pdf.md +263 -0
  162. package/scss/theme/README.md +67 -0
  163. package/scss/theme/_brand.scss +18 -0
  164. package/scss/theme/_colors-dark.scss +68 -0
  165. package/scss/theme/_colors-light.scss +70 -0
  166. package/scss/theme/_components.scss +94 -0
  167. package/scss/theme/_icons.scss +104 -0
  168. package/scss/theme/_index.scss +62 -0
  169. package/scss/theme/_shadows.scss +65 -0
  170. package/scss/theme/_shape.scss +13 -0
  171. package/scss/theme/_typography.scss +9 -0
  172. package/scss/theme/registry.json +447 -0
  173. package/scss/themes/boilerplate-dark.scss +212 -0
  174. package/scss/themes/boilerplate-light.scss +209 -0
  175. package/scss/themes/boilerplate.scss +181 -0
  176. package/scss/themes/cupertino-dark.scss +238 -0
  177. package/scss/themes/cupertino-light.scss +266 -0
  178. package/scss/themes/cupertino.scss +194 -0
  179. package/scss/themes/glass-dark.scss +238 -0
  180. package/scss/themes/glass-light.scss +266 -0
  181. package/scss/themes/glass.scss +220 -0
  182. package/scss/themes/graphite-dark.scss +260 -0
  183. package/scss/themes/graphite-light.scss +228 -0
  184. package/scss/themes/graphite.scss +182 -0
  185. package/scss/themes/press-dark.scss +237 -0
  186. package/scss/themes/press-light.scss +273 -0
  187. package/scss/themes/press.scss +241 -0
  188. package/scss/themes/prism-dark.scss +217 -0
  189. package/scss/themes/prism-light.scss +220 -0
  190. package/scss/themes/prism.scss +190 -0
  191. package/scss/themes/sketchbook-dark.scss +231 -0
  192. package/scss/themes/sketchbook-light.scss +231 -0
  193. package/scss/themes/sketchbook.scss +178 -0
  194. package/scss/themes/terminal-dark.scss +267 -0
  195. package/scss/themes/terminal-light.scss +175 -0
  196. package/scss/themes/terminal.scss +185 -0
  197. package/scss/tokens.scss +23 -0
  198. package/scss/utilities-only.scss +4 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,1036 @@
1
+ # [1.1.0](https://github.com/Jerry2d3d/css-is-awesome/compare/v1.0.0...v1.1.0) (2026-09-01)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **a11y:** copy button used code-surface ink on a page-surface background ([bf84bf4](https://github.com/Jerry2d3d/css-is-awesome/commit/bf84bf4d6c23e3ebafdb5dc98a303d9961d68714))
7
+ * **a11y:** validator ignored unquoted [data-theme]; grade the code palette ([2437f41](https://github.com/Jerry2d3d/css-is-awesome/commit/2437f4182ddccc01b372d9aacd898b6222fcabd3)), closes [#fafafa](https://github.com/Jerry2d3d/css-is-awesome/issues/fafafa) [#0a0a0a](https://github.com/Jerry2d3d/css-is-awesome/issues/0a0a0a)
8
+ * **ci:** snapshot job installed chromium but ran all three engines ([f7b7fc9](https://github.com/Jerry2d3d/css-is-awesome/commit/f7b7fc9e29883863c6a525f44391e6eb4b4b9662))
9
+ * **ci:** snapshot workflow silently discarded the baselines it created ([3358cac](https://github.com/Jerry2d3d/css-is-awesome/commit/3358cacb6fbf88d9dcf0109597bed301efeda483))
10
+ * **compare:** correct every measurable claim on the comparison page ([3d1b602](https://github.com/Jerry2d3d/css-is-awesome/commit/3d1b602ff6074712a2e2d0aea5a1ad27128d2d70))
11
+ * **pkg:** build dist/ on git installs via a prepare hook ([1a0deb1](https://github.com/Jerry2d3d/css-is-awesome/commit/1a0deb19e4fc6de15b7b3530847779920d01d784))
12
+ * **print:** stop the freeze from flattening deliberate opacity and transform ([1af51d2](https://github.com/Jerry2d3d/css-is-awesome/commit/1af51d2e3a08cd61e51ac3b857eeaa261afd044e))
13
+ * root barrel emitted no tokens; retract the false Turbopack claim ([d7f71e3](https://github.com/Jerry2d3d/css-is-awesome/commit/d7f71e366a1ef4b918cfcfd6dafcba8d352afcb5))
14
+ * **sass:** stop using the deprecated if() function; sharpen the AI on-ramp ([61df05a](https://github.com/Jerry2d3d/css-is-awesome/commit/61df05a31228fce169664690c2562d128bf06958))
15
+ * **site:** moat card uses grid; Tailwind sample updated to Headless UI v2 ([cb39e44](https://github.com/Jerry2d3d/css-is-awesome/commit/cb39e44b4eb8d7ab1a86377c1d828b1cde3ed58b))
16
+ * **site:** moat code blocks now fill their card ([8e53d35](https://github.com/Jerry2d3d/css-is-awesome/commit/8e53d355b0f9279125b9dfd6f913851cf2ebcdc3))
17
+ * six upstream bugs from the Boiler audit (BUG-1..7) ([84f4c4f](https://github.com/Jerry2d3d/css-is-awesome/commit/84f4c4fc6f6259bf74541a833fe0ad343821ab12))
18
+ * **themes:** prism was missing from every theme picker ([4ce4f5f](https://github.com/Jerry2d3d/css-is-awesome/commit/4ce4f5f8a696728b513aa1adc148b33c5808e26e))
19
+
20
+
21
+ ### Features
22
+
23
+ * **animate:** accept a raw duration; add letter-spacing() coverage fixture ([25b7cd6](https://github.com/Jerry2d3d/css-is-awesome/commit/25b7cd6cbc09d76b51c9dd0b74077ec1af78c327))
24
+ * **blog:** real posts from real commits, replacing seven dead stubs ([f37c5be](https://github.com/Jerry2d3d/css-is-awesome/commit/f37c5be94cd64f99548a6a119820325d559e6920))
25
+ * **site:** print the story, not the chrome — dogfoods cia's print mixins ([ece519c](https://github.com/Jerry2d3d/css-is-awesome/commit/ece519c43f62230e1b3392538dae5148fc31ddf6))
26
+ * **themes:** themes own the spacing rhythm, not just the palette ([4bc1e24](https://github.com/Jerry2d3d/css-is-awesome/commit/4bc1e24f1b64f33cacd35f3bab12327019634fea))
27
+
28
+ # [1.1.0](https://github.com/Jerry2d3d/css-is-awesome/compare/v1.0.0...v1.1.0) (2026-09-01)
29
+
30
+
31
+ ### Bug Fixes
32
+
33
+ * **a11y:** copy button used code-surface ink on a page-surface background ([bf84bf4](https://github.com/Jerry2d3d/css-is-awesome/commit/bf84bf4d6c23e3ebafdb5dc98a303d9961d68714))
34
+ * **a11y:** validator ignored unquoted [data-theme]; grade the code palette ([2437f41](https://github.com/Jerry2d3d/css-is-awesome/commit/2437f4182ddccc01b372d9aacd898b6222fcabd3)), closes [#fafafa](https://github.com/Jerry2d3d/css-is-awesome/issues/fafafa) [#0a0a0a](https://github.com/Jerry2d3d/css-is-awesome/issues/0a0a0a)
35
+ * **ci:** snapshot job installed chromium but ran all three engines ([f7b7fc9](https://github.com/Jerry2d3d/css-is-awesome/commit/f7b7fc9e29883863c6a525f44391e6eb4b4b9662))
36
+ * **ci:** snapshot workflow silently discarded the baselines it created ([3358cac](https://github.com/Jerry2d3d/css-is-awesome/commit/3358cacb6fbf88d9dcf0109597bed301efeda483))
37
+ * **compare:** correct every measurable claim on the comparison page ([3d1b602](https://github.com/Jerry2d3d/css-is-awesome/commit/3d1b602ff6074712a2e2d0aea5a1ad27128d2d70))
38
+ * **pkg:** build dist/ on git installs via a prepare hook ([1a0deb1](https://github.com/Jerry2d3d/css-is-awesome/commit/1a0deb19e4fc6de15b7b3530847779920d01d784))
39
+ * **print:** stop the freeze from flattening deliberate opacity and transform ([1af51d2](https://github.com/Jerry2d3d/css-is-awesome/commit/1af51d2e3a08cd61e51ac3b857eeaa261afd044e))
40
+ * root barrel emitted no tokens; retract the false Turbopack claim ([d7f71e3](https://github.com/Jerry2d3d/css-is-awesome/commit/d7f71e366a1ef4b918cfcfd6dafcba8d352afcb5))
41
+ * **sass:** stop using the deprecated if() function; sharpen the AI on-ramp ([61df05a](https://github.com/Jerry2d3d/css-is-awesome/commit/61df05a31228fce169664690c2562d128bf06958))
42
+ * **site:** moat card uses grid; Tailwind sample updated to Headless UI v2 ([cb39e44](https://github.com/Jerry2d3d/css-is-awesome/commit/cb39e44b4eb8d7ab1a86377c1d828b1cde3ed58b))
43
+ * **site:** moat code blocks now fill their card ([8e53d35](https://github.com/Jerry2d3d/css-is-awesome/commit/8e53d355b0f9279125b9dfd6f913851cf2ebcdc3))
44
+ * six upstream bugs from the Boiler audit (BUG-1..7) ([84f4c4f](https://github.com/Jerry2d3d/css-is-awesome/commit/84f4c4fc6f6259bf74541a833fe0ad343821ab12))
45
+ * **themes:** prism was missing from every theme picker ([4ce4f5f](https://github.com/Jerry2d3d/css-is-awesome/commit/4ce4f5f8a696728b513aa1adc148b33c5808e26e))
46
+
47
+
48
+ ### Features
49
+
50
+ * **animate:** accept a raw duration; add letter-spacing() coverage fixture ([25b7cd6](https://github.com/Jerry2d3d/css-is-awesome/commit/25b7cd6cbc09d76b51c9dd0b74077ec1af78c327))
51
+ * **blog:** real posts from real commits, replacing seven dead stubs ([f37c5be](https://github.com/Jerry2d3d/css-is-awesome/commit/f37c5be94cd64f99548a6a119820325d559e6920))
52
+ * **site:** print the story, not the chrome — dogfoods cia's print mixins ([ece519c](https://github.com/Jerry2d3d/css-is-awesome/commit/ece519c43f62230e1b3392538dae5148fc31ddf6))
53
+ * **themes:** themes own the spacing rhythm, not just the palette ([4bc1e24](https://github.com/Jerry2d3d/css-is-awesome/commit/4bc1e24f1b64f33cacd35f3bab12327019634fea))
54
+
55
+ # [1.1.0](https://github.com/Jerry2d3d/css-is-awesome/compare/v1.0.0...v1.1.0) (2026-09-01)
56
+
57
+
58
+ ### Bug Fixes
59
+
60
+ * **a11y:** copy button used code-surface ink on a page-surface background ([bf84bf4](https://github.com/Jerry2d3d/css-is-awesome/commit/bf84bf4d6c23e3ebafdb5dc98a303d9961d68714))
61
+ * **a11y:** validator ignored unquoted [data-theme]; grade the code palette ([2437f41](https://github.com/Jerry2d3d/css-is-awesome/commit/2437f4182ddccc01b372d9aacd898b6222fcabd3)), closes [#fafafa](https://github.com/Jerry2d3d/css-is-awesome/issues/fafafa) [#0a0a0a](https://github.com/Jerry2d3d/css-is-awesome/issues/0a0a0a)
62
+ * **ci:** snapshot job installed chromium but ran all three engines ([f7b7fc9](https://github.com/Jerry2d3d/css-is-awesome/commit/f7b7fc9e29883863c6a525f44391e6eb4b4b9662))
63
+ * **ci:** snapshot workflow silently discarded the baselines it created ([3358cac](https://github.com/Jerry2d3d/css-is-awesome/commit/3358cacb6fbf88d9dcf0109597bed301efeda483))
64
+ * **compare:** correct every measurable claim on the comparison page ([3d1b602](https://github.com/Jerry2d3d/css-is-awesome/commit/3d1b602ff6074712a2e2d0aea5a1ad27128d2d70))
65
+ * **pkg:** build dist/ on git installs via a prepare hook ([1a0deb1](https://github.com/Jerry2d3d/css-is-awesome/commit/1a0deb19e4fc6de15b7b3530847779920d01d784))
66
+ * **print:** stop the freeze from flattening deliberate opacity and transform ([1af51d2](https://github.com/Jerry2d3d/css-is-awesome/commit/1af51d2e3a08cd61e51ac3b857eeaa261afd044e))
67
+ * root barrel emitted no tokens; retract the false Turbopack claim ([d7f71e3](https://github.com/Jerry2d3d/css-is-awesome/commit/d7f71e366a1ef4b918cfcfd6dafcba8d352afcb5))
68
+ * **sass:** stop using the deprecated if() function; sharpen the AI on-ramp ([61df05a](https://github.com/Jerry2d3d/css-is-awesome/commit/61df05a31228fce169664690c2562d128bf06958))
69
+ * **site:** moat card uses grid; Tailwind sample updated to Headless UI v2 ([cb39e44](https://github.com/Jerry2d3d/css-is-awesome/commit/cb39e44b4eb8d7ab1a86377c1d828b1cde3ed58b))
70
+ * **site:** moat code blocks now fill their card ([8e53d35](https://github.com/Jerry2d3d/css-is-awesome/commit/8e53d355b0f9279125b9dfd6f913851cf2ebcdc3))
71
+ * six upstream bugs from the Boiler audit (BUG-1..7) ([84f4c4f](https://github.com/Jerry2d3d/css-is-awesome/commit/84f4c4fc6f6259bf74541a833fe0ad343821ab12))
72
+ * **themes:** prism was missing from every theme picker ([4ce4f5f](https://github.com/Jerry2d3d/css-is-awesome/commit/4ce4f5f8a696728b513aa1adc148b33c5808e26e))
73
+
74
+
75
+ ### Features
76
+
77
+ * **animate:** accept a raw duration; add letter-spacing() coverage fixture ([25b7cd6](https://github.com/Jerry2d3d/css-is-awesome/commit/25b7cd6cbc09d76b51c9dd0b74077ec1af78c327))
78
+ * **blog:** real posts from real commits, replacing seven dead stubs ([f37c5be](https://github.com/Jerry2d3d/css-is-awesome/commit/f37c5be94cd64f99548a6a119820325d559e6920))
79
+ * **site:** print the story, not the chrome — dogfoods cia's print mixins ([ece519c](https://github.com/Jerry2d3d/css-is-awesome/commit/ece519c43f62230e1b3392538dae5148fc31ddf6))
80
+ * **themes:** themes own the spacing rhythm, not just the palette ([4bc1e24](https://github.com/Jerry2d3d/css-is-awesome/commit/4bc1e24f1b64f33cacd35f3bab12327019634fea))
81
+
82
+ # [1.1.0](https://github.com/Jerry2d3d/css-is-awesome/compare/v1.0.0...v1.1.0) (2026-08-30)
83
+
84
+
85
+ ### Bug Fixes
86
+
87
+ * **a11y:** copy button used code-surface ink on a page-surface background ([bf84bf4](https://github.com/Jerry2d3d/css-is-awesome/commit/bf84bf4d6c23e3ebafdb5dc98a303d9961d68714))
88
+ * **a11y:** validator ignored unquoted [data-theme]; grade the code palette ([2437f41](https://github.com/Jerry2d3d/css-is-awesome/commit/2437f4182ddccc01b372d9aacd898b6222fcabd3)), closes [#fafafa](https://github.com/Jerry2d3d/css-is-awesome/issues/fafafa) [#0a0a0a](https://github.com/Jerry2d3d/css-is-awesome/issues/0a0a0a)
89
+ * **ci:** snapshot job installed chromium but ran all three engines ([f7b7fc9](https://github.com/Jerry2d3d/css-is-awesome/commit/f7b7fc9e29883863c6a525f44391e6eb4b4b9662))
90
+ * **ci:** snapshot workflow silently discarded the baselines it created ([3358cac](https://github.com/Jerry2d3d/css-is-awesome/commit/3358cacb6fbf88d9dcf0109597bed301efeda483))
91
+ * **compare:** correct every measurable claim on the comparison page ([3d1b602](https://github.com/Jerry2d3d/css-is-awesome/commit/3d1b602ff6074712a2e2d0aea5a1ad27128d2d70))
92
+ * **pkg:** build dist/ on git installs via a prepare hook ([1a0deb1](https://github.com/Jerry2d3d/css-is-awesome/commit/1a0deb19e4fc6de15b7b3530847779920d01d784))
93
+ * **print:** stop the freeze from flattening deliberate opacity and transform ([1af51d2](https://github.com/Jerry2d3d/css-is-awesome/commit/1af51d2e3a08cd61e51ac3b857eeaa261afd044e))
94
+ * root barrel emitted no tokens; retract the false Turbopack claim ([d7f71e3](https://github.com/Jerry2d3d/css-is-awesome/commit/d7f71e366a1ef4b918cfcfd6dafcba8d352afcb5))
95
+ * **sass:** stop using the deprecated if() function; sharpen the AI on-ramp ([61df05a](https://github.com/Jerry2d3d/css-is-awesome/commit/61df05a31228fce169664690c2562d128bf06958))
96
+ * **site:** moat card uses grid; Tailwind sample updated to Headless UI v2 ([cb39e44](https://github.com/Jerry2d3d/css-is-awesome/commit/cb39e44b4eb8d7ab1a86377c1d828b1cde3ed58b))
97
+ * **site:** moat code blocks now fill their card ([8e53d35](https://github.com/Jerry2d3d/css-is-awesome/commit/8e53d355b0f9279125b9dfd6f913851cf2ebcdc3))
98
+ * six upstream bugs from the Boiler audit (BUG-1..7) ([84f4c4f](https://github.com/Jerry2d3d/css-is-awesome/commit/84f4c4fc6f6259bf74541a833fe0ad343821ab12))
99
+ * **themes:** prism was missing from every theme picker ([4ce4f5f](https://github.com/Jerry2d3d/css-is-awesome/commit/4ce4f5f8a696728b513aa1adc148b33c5808e26e))
100
+
101
+
102
+ ### Features
103
+
104
+ * **animate:** accept a raw duration; add letter-spacing() coverage fixture ([25b7cd6](https://github.com/Jerry2d3d/css-is-awesome/commit/25b7cd6cbc09d76b51c9dd0b74077ec1af78c327))
105
+ * **blog:** real posts from real commits, replacing seven dead stubs ([f37c5be](https://github.com/Jerry2d3d/css-is-awesome/commit/f37c5be94cd64f99548a6a119820325d559e6920))
106
+ * **site:** print the story, not the chrome — dogfoods cia's print mixins ([ece519c](https://github.com/Jerry2d3d/css-is-awesome/commit/ece519c43f62230e1b3392538dae5148fc31ddf6))
107
+ * **themes:** themes own the spacing rhythm, not just the palette ([4bc1e24](https://github.com/Jerry2d3d/css-is-awesome/commit/4bc1e24f1b64f33cacd35f3bab12327019634fea))
108
+
109
+ ## [1.1.1](https://github.com/Jerry2d3d/css-is-awesome/compare/v1.1.0...v1.1.1) (2026-08-30)
110
+
111
+
112
+ ### Bug Fixes
113
+
114
+ * **sass:** stop using the deprecated if() function; sharpen the AI on-ramp ([61df05a](https://github.com/Jerry2d3d/css-is-awesome/commit/61df05a31228fce169664690c2562d128bf06958))
115
+
116
+ # [1.1.0](https://github.com/Jerry2d3d/css-is-awesome/compare/v1.0.0...v1.1.0) (2026-08-30)
117
+
118
+
119
+ ### Bug Fixes
120
+
121
+ * **a11y:** copy button used code-surface ink on a page-surface background ([bf84bf4](https://github.com/Jerry2d3d/css-is-awesome/commit/bf84bf4d6c23e3ebafdb5dc98a303d9961d68714))
122
+ * **a11y:** validator ignored unquoted [data-theme]; grade the code palette ([2437f41](https://github.com/Jerry2d3d/css-is-awesome/commit/2437f4182ddccc01b372d9aacd898b6222fcabd3)), closes [#fafafa](https://github.com/Jerry2d3d/css-is-awesome/issues/fafafa) [#0a0a0a](https://github.com/Jerry2d3d/css-is-awesome/issues/0a0a0a)
123
+ * **ci:** snapshot job installed chromium but ran all three engines ([f7b7fc9](https://github.com/Jerry2d3d/css-is-awesome/commit/f7b7fc9e29883863c6a525f44391e6eb4b4b9662))
124
+ * **ci:** snapshot workflow silently discarded the baselines it created ([3358cac](https://github.com/Jerry2d3d/css-is-awesome/commit/3358cacb6fbf88d9dcf0109597bed301efeda483))
125
+ * **compare:** correct every measurable claim on the comparison page ([3d1b602](https://github.com/Jerry2d3d/css-is-awesome/commit/3d1b602ff6074712a2e2d0aea5a1ad27128d2d70))
126
+ * **pkg:** build dist/ on git installs via a prepare hook ([1a0deb1](https://github.com/Jerry2d3d/css-is-awesome/commit/1a0deb19e4fc6de15b7b3530847779920d01d784))
127
+ * **print:** stop the freeze from flattening deliberate opacity and transform ([1af51d2](https://github.com/Jerry2d3d/css-is-awesome/commit/1af51d2e3a08cd61e51ac3b857eeaa261afd044e))
128
+ * root barrel emitted no tokens; retract the false Turbopack claim ([d7f71e3](https://github.com/Jerry2d3d/css-is-awesome/commit/d7f71e366a1ef4b918cfcfd6dafcba8d352afcb5))
129
+ * **site:** moat card uses grid; Tailwind sample updated to Headless UI v2 ([cb39e44](https://github.com/Jerry2d3d/css-is-awesome/commit/cb39e44b4eb8d7ab1a86377c1d828b1cde3ed58b))
130
+ * **site:** moat code blocks now fill their card ([8e53d35](https://github.com/Jerry2d3d/css-is-awesome/commit/8e53d355b0f9279125b9dfd6f913851cf2ebcdc3))
131
+ * six upstream bugs from the Boiler audit (BUG-1..7) ([84f4c4f](https://github.com/Jerry2d3d/css-is-awesome/commit/84f4c4fc6f6259bf74541a833fe0ad343821ab12))
132
+ * **themes:** prism was missing from every theme picker ([4ce4f5f](https://github.com/Jerry2d3d/css-is-awesome/commit/4ce4f5f8a696728b513aa1adc148b33c5808e26e))
133
+
134
+
135
+ ### Features
136
+
137
+ * **animate:** accept a raw duration; add letter-spacing() coverage fixture ([25b7cd6](https://github.com/Jerry2d3d/css-is-awesome/commit/25b7cd6cbc09d76b51c9dd0b74077ec1af78c327))
138
+ * **blog:** real posts from real commits, replacing seven dead stubs ([f37c5be](https://github.com/Jerry2d3d/css-is-awesome/commit/f37c5be94cd64f99548a6a119820325d559e6920))
139
+ * **site:** print the story, not the chrome — dogfoods cia's print mixins ([ece519c](https://github.com/Jerry2d3d/css-is-awesome/commit/ece519c43f62230e1b3392538dae5148fc31ddf6))
140
+ * **themes:** themes own the spacing rhythm, not just the palette ([4bc1e24](https://github.com/Jerry2d3d/css-is-awesome/commit/4bc1e24f1b64f33cacd35f3bab12327019634fea))
141
+
142
+ # Changelog
143
+
144
+ All notable changes to this project will be documented in this file.
145
+
146
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
147
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
148
+
149
+ **See also:** [`VERSIONING.md`](./VERSIONING.md) — version policy, deprecation
150
+ lifecycle, and the Conventional Commits → changelog section mapping that drives
151
+ automated releases.
152
+
153
+ ## [Unreleased]
154
+
155
+ > Ships as **1.1.0** — the first release actually published to npm. `1.0.0` was
156
+ > tagged but never published. The number is computed by `semantic-release` from
157
+ > the Conventional Commit history; nothing here hand-edits `package.json`.
158
+
159
+ ### Fixed
160
+
161
+ - **Both documented SCSS imports failed on a clean install.** `@use 'css-is-awesome'`
162
+ (the README's primary example) and `@use 'css-is-awesome/api'` (the two-import
163
+ model) both errored with *"Can't find stylesheet to import"* for anyone who
164
+ installed the package. Sass does not read `package.json` `"exports"` — it
165
+ resolves a bare specifier against a load path on disk, so `css-is-awesome/api`
166
+ looked for `node_modules/css-is-awesome/api.scss` while the real barrel sits at
167
+ `scss/api.scss`. The `"./api"` exports entry only ever served bundlers that
168
+ honour exports.
169
+
170
+ Fixed by shipping two forwarding shims at the package root: `api.scss`
171
+ (zero-emit) and `_index.scss` (kitchen sink). Only the deep paths
172
+ (`css-is-awesome/scss/api`) worked before, which is why in-repo checks and the
173
+ Boiler showcase both stayed green.
174
+
175
+ ### Added
176
+
177
+ - **`npm run validate-package`** — packs, installs into a temp project, and
178
+ compiles all ten documented `@use` specifiers, asserting the `/api` forms stay
179
+ zero-emit. `validate-api` only ever compiled the barrel from inside this repo
180
+ with `scss/` on the load path, so it could not see the packaging break. Wired
181
+ into CI.
182
+ - **`npm run pack:consumer`** — packs and installs the current build into a local
183
+ consumer project in one step, replacing a three-step manual dance whose middle
184
+ step (hand-editing the versioned tarball filename) failed silently when skipped.
185
+ - CI now also gates `validate-icons` and `validate-api`, which existed but were
186
+ never executed by the workflow.
187
+
188
+ ### Changed — themes own the spacing rhythm (**action required for custom themes**)
189
+
190
+ - **`--space-0` … `--space-9` are now contract-required; the six t-shirt names
191
+ are now optional.** Components call `space(4)`, which reads `var(--space-4)` —
192
+ but a theme could only declare the six t-shirt names, and those were emitted
193
+ as *independent literals* that happened to hold the same values. The token a
194
+ theme set and the token a component read were different variables, so spacing
195
+ was untouchable from a theme. The proof shipped in the box: all 21 themes
196
+ carried byte-identical spacing under a comment reading "Library scales —
197
+ identical". The t-shirt aliases now emit as `var()` **references**
198
+ (`--space-md: var(--space-4)`), so retuning a numbered step moves both.
199
+
200
+ **If you maintain a custom theme, `npm run validate-themes` will now fail it
201
+ until you declare `--space-0` through `--space-9`.** The six t-shirt names
202
+ (`--space-2xs`, `--space-xs`, `--space-sm`, `--space-md`, `--space-lg`,
203
+ `--space-xl`) moved to optional, so keeping or dropping them is your call.
204
+ Contract totals: **123 required + 30 optional → 127 required + 36 optional.**
205
+
206
+ - **Library defaults now emit under `:where(:root)` instead of `:root`.**
207
+ Required by the change above: a dropped-in theme file emits a bare `:root`
208
+ block, which **tied** the library's own `:root` at (0,1,0) — and the
209
+ documented load order is theme first, library second, so the *library* won
210
+ every tie. `:where()` drops the library block to (0,0,0), so a theme's plain
211
+ `:root` always wins. Specificity only *decreases* here, so nothing that used
212
+ to win can start losing. `:where()`, not `@layer` — cia does not use cascade
213
+ layers.
214
+
215
+ - **`theme()` now emits `:root, :root[data-theme="<name>"]`, so a drop-in theme
216
+ file needs no markup change.** Shipped themes disagreed three ways about
217
+ their own selector: 9 emitted `:root[data-theme="x"]`, 7 emitted
218
+ `[data-theme="x"]`, and 5 emitted a bare `:root`. Only that last group worked
219
+ when dropped into a page on its own — the other 16 silently rendered an
220
+ untokenised page unless the consumer *also* set `<html data-theme>` to a value
221
+ matching the file. Both halves now ship, so a single-file drop-in themes the
222
+ page immediately and `data-theme` switching still works. New `$standalone`
223
+ parameter (default `true`) suppresses the bare `:root` half; the multi-theme
224
+ bundle sets it to `false` so 24 blocks don't all claim `:root`.
225
+
226
+ ### Added — theme build + drift gates
227
+
228
+ - **`npm run check:theme-drift`** (`scripts/check-theme-drift.mjs`) — rebuilds
229
+ every theme into a scratch copy and diffs the result against the committed CSS
230
+ declaration by declaration, then restores (the check is read-only).
231
+ `validate-themes` reads the **committed** CSS under `public/`, not the SCSS
232
+ sources, and theme building was in no CI step at all — so a fix could land in
233
+ `scss/themes/*.scss`, never be rebuilt, and CI would happily validate the
234
+ stale artifact and report success. Now wired into CI ahead of
235
+ `validate-themes`.
236
+ - **`scripts/build-theme-bundle.mjs`** — regenerates the whole of
237
+ `public/theme.css` on every build.
238
+ - `build:css:themes` now builds the bundle as well as the per-theme files, and
239
+ is finally part of `build:css:all` (it never was).
240
+ - The a11y audit gained five `--code-*` pairs (`--code-ink`, `--code-muted`,
241
+ `--code-accent`, `--code-blue`, `--code-green`, each against `--code-bg`),
242
+ taking it from **17 to 22 audited pairs per theme**.
243
+
244
+ ### Fixed — a11y validator, theme sources, theme bundle
245
+
246
+ - **The contrast validator silently passed themes it had never read.** Its
247
+ block-matching regex required quotes, so `[data-theme=dark]` — valid CSS —
248
+ matched nothing. The file then fell through to a legacy `:root`-only path in
249
+ which every theme block is invisible, audited `:root` alone, found it fine and
250
+ exited 0, reporting "1 theme block(s)" while passing a theme with near-black
251
+ text on near-black paper. Reproduced both ways: the quoted form failed with 9
252
+ bad pairs, the unquoted form passed. Both now fail. A guard was added on top:
253
+ if a file mentions `data-theme` but no block parses, the validator **refuses to
254
+ grade** rather than fall back and report a meaningless pass.
255
+ - **33 real contrast failures across 9 themes**, worst 3.02:1, surfaced by the
256
+ newly-audited `--code-*` pairs and all fixed by holding hue and saturation and
257
+ moving only lightness. Prism's `--code-muted` needed a structural fix: it was a
258
+ single value sitting against a `light-dark(#fafafa, #0a0a0a)` surface, and no
259
+ single grey clears even 4.5:1 on both (it would need L ≤ 0.174 *and* L ≥ 0.189
260
+ — disjoint). It is now `light-dark()` too.
261
+ - **13 `-light` / `-dark` theme files were hand-authored CSS with no SCSS
262
+ source.** Nothing could rebuild them and they had drifted **31 declarations**
263
+ from their namesakes. They were **ported, not derived** — checked first: 3 were
264
+ exact derivations, 9 were not. `glass-light` carries `blur(30px)` where its
265
+ parent has `blur(20px)`, and a `.70` white glow where the parent has `.16` —
266
+ deliberate tuning that deriving would have silently restyled away. Values were
267
+ copied byte-for-byte; 2,647 declarations across 21 files verified with zero
268
+ value differences.
269
+ - **Three themes existed only inside `public/theme.css`** — `sketchbook-light`
270
+ (the docs site's *default* theme), `boilerplate-light` and `boilerplate-dark`
271
+ were blocks with no SCSS source and no theme directory, invisible to the
272
+ contract gate and unrebuildable. All three were promoted to real sources with
273
+ values copied verbatim (checked first: two are exact derivations,
274
+ `boilerplate-dark` is not — its `--shadow-md/lg/xl` are two-part shadows where
275
+ the parent's dark branch is single-part). **24 themes now ship, all passing the
276
+ contract check and the a11y audit.**
277
+
278
+ ### Removed
279
+
280
+ - **Six dead contract tokens:** `--radius-button`, `--radius-card`,
281
+ `--radius-input`, `--radius-modal`, `--radius-badge`, `--radius-avatar`. They
282
+ were required of every theme and had **zero consumers** anywhere in the
283
+ library. The live knobs are `--btn-radius`, `--card-radius`, `--input-radius`,
284
+ `--modal-radius`, `--badge-radius` and `--tag-radius`, which already cascade
285
+ from the generic `--radius-*` scale; those six are now listed in the contract
286
+ as **optional**, so overriding one is documented rather than folklore.
287
+ - **`scripts/bundle-companion-themes.mjs`** — a one-shot appender that only
288
+ added a theme to `public/theme.css` if its block was *missing*, and never
289
+ updated an existing one, so the bundle silently fell 8 commits behind.
290
+ Replaced by `scripts/build-theme-bundle.mjs`, which regenerates the file.
291
+
292
+ ## [1.0.0] — 2026-08-17 — Mixin-first, stable
293
+
294
+ First 1.0. The API surface (mixins, functions, token contract, theme
295
+ architecture) is now under strict SemVer — breaking changes require a major
296
+ bump. See [`VERSIONING.md`](./VERSIONING.md) for the policy.
297
+
298
+ Nothing in the library changed in this release; 1.0.0 marks the point at which
299
+ the 0.8 mixin-first surface is treated as stable. Everything below shipped
300
+ during the 0.9/1.0 development window.
301
+
302
+ ### Added
303
+
304
+ - **`css-is-awesome/api` — zero-emit authoring barrel for per-component styles.**
305
+ New `scss/api.scss` + package export `"css-is-awesome/api"` forwards the full
306
+ mixin/function/token-map API but emits **zero CSS** until a mixin is actually
307
+ called. This is the correct entry point for a component stylesheet
308
+ (`Card.module.scss`), because it prints no `:root` block and is therefore safe
309
+ under Next.js CSS Modules "pure" mode:
310
+
311
+ ```scss
312
+ @use 'css-is-awesome/api' as cia;
313
+ .card { @include cia.card-base($shadow: 2); background: cia.color(surface-default); }
314
+ ```
315
+
316
+ Tokens + keyframes still live at the app root (emitted once by the CSS bundle
317
+ or a theme stylesheet); components only pull in the mixins. `scss/_index.scss`
318
+ is now the "kitchen-sink" barrel (`api` + the global `.cia-anim-*` utilities)
319
+ and derives its API surface from `api.scss`, so the two can't drift. Guarded by
320
+ `npm run validate-api` (a Sass compile-assertion test).
321
+
322
+ Fixes a latent consume-time bug: `spinner()` and `skeleton()` previously
323
+ defined their `@keyframes` at module top level, which leaked CSS on import and
324
+ would be renamed by CSS Modules (breaking the animation reference). Their
325
+ keyframes now emit via `@at-root` inside the mixin — only when called, and
326
+ co-emitted with the reference so CSS Modules renames both together (matching
327
+ the existing `_overlay.scss` pattern).
328
+
329
+ - **Print / PDF — pure-CSS, zero-JS.** "The page IS the PDF source." Four
330
+ new mixins in `scss/_mixins.scss` (namespaced `cia.` / `m.`): `print`
331
+ (bare `@media print { @content }` wrapper, co-locate inside a selector to
332
+ override on paper), `print-base($freeze-animations, $size, $margin)`
333
+ (root-only page defaults — emits `@page`, freezes animations so nothing
334
+ prints invisible, and emits the print variable control plane),
335
+ `print-hidden` (hide chrome on paper), and `print-only` (show an element
336
+ only on paper, hidden on screen). Three custom properties from
337
+ `print-base`: `--is-print` (`0` on screen, `1` on paper; readable in
338
+ `calc()` / `opacity` / `@container style(--is-print: 1)`), `--print-hide`
339
+ (display for `print-hidden`, default `none`), and `--print-show` (display
340
+ for `print-only`, default `revert`) — override either locally to keep or
341
+ lay out an element with no rule rewrite. New recipe at
342
+ `scss/recipes/print-to-pdf.md` (layout, simple) with framework examples,
343
+ read by humans at `/docs/recipes/print-to-pdf`. No Puppeteer, no server —
344
+ the browser's native Print → Save as PDF is the generator. Pulled forward
345
+ from v1.2 into v1.0.
346
+
347
+ ### Changed
348
+
349
+ - **Docs now teach the two-import model with the `cia.` namespace consistently.**
350
+ AGENTS.md, `llm.txt`, `css-is-awesome.instructions.md`, THREE-TIERS.md,
351
+ MIGRATION.md, the `/docs/install` page, and the MCP server (`assemble_prompt`
352
+ usage blocks + `resolve_size` suggestions) now show component styles importing
353
+ `@use 'css-is-awesome/api' as cia;` (zero-emit) and reference every mixin as
354
+ `cia.*` instead of the inconsistent `m.*`. The root/global bundle
355
+ (`@use 'css-is-awesome'`, optionally `with (...)`) stays the token-emitting
356
+ entry. The MCP theme-name parser now matches any namespace (`m.theme`,
357
+ `cia.theme`, …).
358
+
359
+ ### Fixed
360
+
361
+ - **Docs no longer show imports/mixins that don't compile.** The previously
362
+ documented `@use 'css-is-awesome' as cia;` for component styles resolved to the
363
+ CSS-emitting bundle (no mixin API, and it emitted `:root` — rejected by CSS
364
+ Modules pure mode); it now points at `css-is-awesome/api`. Icon examples used
365
+ `m.svg(...)` (never defined — icons are `cia.icon-svg` via the barrel, or
366
+ `i.svg` via `css-is-awesome/scss/icons`), and the font examples referenced the
367
+ removed `font-load` / `font-load-local` names (now `cia.font-face` /
368
+ `cia.font-face-local`). All doc snippets are verified to compile through `/api`.
369
+
370
+ ## [0.8.2] — 2026-05-21 — Panel R7 bug-fix patch
371
+
372
+ Hotfix responding to the css-scss-master panel audit of v0.8.1. Two real
373
+ build/render bugs caught + four behavior fixes. All compile-verified.
374
+
375
+ ### Fixed
376
+
377
+ - **Bare-tags recipe `<dialog>` block** — `@include m.modal-base` was failing
378
+ with "Undefined mixin" because `_bare-tags.scss` `@use`'s `mixins as m` but
379
+ `modal-base` lives in `_overlay.scss`. Added `@use '../components/overlay' as o;`
380
+ and switched the call to `o.modal-base`. (Same "didn't grep callers" miss as
381
+ Badge in `c06324d` — feedback memory `grep-callers-before-rename-or-move`
382
+ is now in place.)
383
+ - **Stepper composed router selectors** — `[data-status='upcoming'] > &`
384
+ inside `stepper-circle` was compiling to the wrong selector when used via
385
+ `stepper()` (the nested selector resolved with `&` AFTER the parent,
386
+ inverting the intent). Rewritten: status palette now lives at the composer
387
+ level via `> li[data-status='...'] > [data-slot='circle']` selectors.
388
+ Standalone `stepper-circle` retained as the "upcoming default" primitive.
389
+ - **Stepper connector over-painted** — `[data-status='completed'] ~ * > &`
390
+ matched every trailing connector after the first completed step. Switched
391
+ to `+ li` (adjacent sibling only).
392
+ - **`progress-fill-base` transitions `width`** — animated `width` skipped the
393
+ transition when consumer used `inline-size` (RTL-correct logical property).
394
+ Switched to `inline-size`.
395
+ - **`wizard-shell` / `sidebar` / `toolbar` bypassed `m.space()`** — using raw
396
+ `map.get(t.$space, …)` meant runtime `--space-*` overrides had no effect on
397
+ the new mixins. Added `@use './mixins' as m;` to `_layout.scss` and switched
398
+ the new mixins to `m.space()`. Token-theming parity restored.
399
+ - **`_index.scss` barrel now forwards `./animations-utilities`** — survived
400
+ v0.8.1 only because `main.scss` loaded both halves. Bare `@use 'css-is-awesome' as cia`
401
+ now correctly exposes the keyframes + utility classes too.
402
+ - **Dead `$variant` param in `stepper()` removed.**
403
+
404
+ ### Investigated, no change
405
+
406
+ - `if(sass($cond): a; else: b)` syntax in `_layout.scss:46`, `_data.scss:45`,
407
+ `_mixins.scss:630` was flagged as "not valid Dart Sass" by the audit.
408
+ Compile test passes cleanly with no deprecation warning. The form is
409
+ Sass's actively-recommended replacement for the deprecated `if($c, a, b)`
410
+ short form. No change required.
411
+
412
+ ## [0.8.1] — 2026-05-21 — Animations split + 5 new mixins (dogfood patch)
413
+
414
+ Patch release responding to boiler-project-ai dogfood feedback. One real bug
415
+ (animations partial breaking Next.js CSS Modules), five new mixin primitives
416
+ the consumer was hand-rolling.
417
+
418
+ ### BREAKING (small) — `_animations.scss` split + `progress-track`/`progress-fill` rename
419
+
420
+ - **`_animations.scss` split into two files.**
421
+ - `scss/_animations.scss` keeps the mixins (`animate`, `animate-on`,
422
+ `$_anims`/`$_speeds` maps) — safe to `@use` from `.module.scss`
423
+ in Next.js / Vite / Parcel CSS-Modules pipelines.
424
+ - `scss/_animations-utilities.scss` (NEW) holds keyframes, `.cia-anim-*`
425
+ classes, `.cia-hover-*` classes, and the global `*, *::before, *::after`
426
+ reduced-motion safety net. Load ONCE globally.
427
+ - `main.scss` already loads both — full-bundle consumers unaffected.
428
+ - Why: top-level `*, *::before, *::after` in the same file as the mixin
429
+ surface caused `Selector "*, *::before, *::after" is not pure` build
430
+ errors when a `.module.scss` did `@use 'css-is-awesome/scss/animations' as anim`.
431
+ - **`progress-track` / `progress-fill` renamed to `-base` suffix.**
432
+ - `m.progress-track` → `m.progress-track-base`
433
+ - `m.progress-fill` → `m.progress-fill-base`
434
+ - Signals "compose me" intent and unblocks the new `progress()` router name.
435
+ - **`badge-base` / `badge` moved from `_feedback.scss` to `_data.scss`.**
436
+ - Lives next to `card-base` / `table-base` where consumers expect it.
437
+ - Path-specific imports (`@use 'css-is-awesome/scss/components/feedback' as f; f.badge-base;`)
438
+ will break — switch to the cia barrel (`@use 'css-is-awesome' as cia; cia.badge-base;`)
439
+ or import from `data` instead. The cia barrel re-exports all components.
440
+
441
+ ### Added — 5 new mixins (boiler-driven additions)
442
+
443
+ - **`m.wizard-shell($min-height, $gutter, $body-padding, $rail-padding, $max-width, $footer-border)`** — 3-row grid layout with shared horizontal rhythm. Header + scrollable body + footer; all three rows share `padding-inline` so stepper above + controls below align with the body. `<div data-slot="header|body|footer">…</div>` markup.
444
+ - **`m.stepper($orientation, $variant, $size)` + `m.stepper-circle($size, $r)` + `m.stepper-connector($thickness)`** — status-driven progress indicator. `[data-status="upcoming|active|completed|warning|error"]` parent attribute drives the palette. Composable: use just the circle, or the full strip.
445
+ - **`m.progress($height, $r, $bg, $fill)`** — composed router over `progress-track-base` + `progress-fill-base`. Consumer markup: `<div role="progressbar"><span data-slot="fill" style="inline-size: 60%"></span></div>`.
446
+ - **`m.sidebar($side, $side-width, $content-min, $gap)`** — Every-Layout sidebar primitive. Fixed-width nav + flexible content, gracefully stacks when content falls below `$content-min`. `[data-slot="side|content"]` markup.
447
+ - **`m.toolbar($gap, $align)`** — cluster with auto-margin trailing slot. Left group + right group via `[data-slot="trailing"]`.
448
+
449
+ ### Added — Tier 3 bare-tags additions
450
+
451
+ - `:where(dialog)` — wraps `m.modal-base` + `::backdrop` blur for a sensible default `<dialog>` look.
452
+ - `:where(progress)` — themed `<progress>` element using cia tokens.
453
+ - Both still ship at specificity (0,0,0) via the existing `:where()` wrap.
454
+
455
+ ### Locked architectural rule
456
+
457
+ - **No top-level rules in mixin-surface partials.** Any cia partial whose
458
+ public surface is mixins MUST NOT emit CSS rules at file scope. Rule-emitting
459
+ code lives in dedicated `*-utilities.scss` files or entry points. Enforced
460
+ via convention; future CI test planned.
461
+
462
+ ## [0.8.0] — 2026-05-21 — Mixin-first reframe
463
+
464
+ The big one. cia is now **mixin-first** end-to-end: the mixin is the API, the
465
+ class/tag/selector is the consumer's choice. The npm package ships **zero
466
+ JavaScript** by hard rule.
467
+
468
+ ### BREAKING — Mixin renames (no aliases, hard cut)
469
+
470
+ | Old | New | Why |
471
+ |---|---|---|
472
+ | `m.bp` | `m.media` | Matches CSS `@media` |
473
+ | `m.bp-down` | `m.media-down` | Same family |
474
+ | `m.bp-between` | `m.media-between` | Same family |
475
+ | `m.cq` | `m.contain` | Matches `container-type` mental model |
476
+ | `m.cq-down` | `m.contain-down` | Same |
477
+ | `m.cq-between` | `m.contain-between` | Same |
478
+ | `m.color-raw` | `m.color-static` | "static" makes runtime-vs-compile clearer |
479
+ | `m.inset` | `m.pad` | `inset` collides with CSS property |
480
+ | `m.inset-x` | `m.pad-x` | Same family |
481
+ | `m.inset-y` | `m.pad-y` | Same family |
482
+ | `m.squish` | `m.pad-asym` | Cute → ambiguous; `pad-asym` is descriptive |
483
+ | `m.font-load` | `m.font-face` | Matches `@font-face` at-rule emitted |
484
+ | `m.font-load-local` | `m.font-face-local` | Same |
485
+ | Layout `m.container` | `m.wrap` | Resolves collision with the CSS-containment `m.container` |
486
+
487
+ ### BREAKING — Theme system collapsed
488
+
489
+ - 14 hand-authored `public/themes/<name-mode>/theme.css` files → 9 single-file
490
+ themes generated from `scss/themes/<name>.scss` sources via `light-dark()`.
491
+ - New selector: `:root[data-theme="press"]` instead of
492
+ `[data-theme="press-light"]` / `[data-theme="press-dark"]`. **Consumers must
493
+ rename `data-theme` attribute values** — drop the `-light`/`-dark` suffix.
494
+ - Glass uses Pattern C (nested `@media` block for blur/glow that differs per
495
+ mode); all other themes use Pattern B (one block, `light-dark()` per token).
496
+ - Terminal + Terminal-light are two separate themes, not a paired family —
497
+ intentional. Different brand identities.
498
+
499
+ ### BREAKING — Responsive `:` utilities killed
500
+
501
+ - `.cia-sm:flex`, `.cia-md:hidden`, etc. — gone. They were generating ~85
502
+ lines of cartesian-product responsive utility classes that almost nobody
503
+ was opting in to.
504
+ - `main.scss` compiled bundle dropped from 16.6 KB gz → 8.2 KB gz (50%).
505
+ - Consumers needing responsive utilities: opt back in via `@use cia with
506
+ ($responsive-spacing: true)` once the opt-in API ships.
507
+
508
+ ### BREAKING — Utility classes opt-in (Sass path)
509
+
510
+ - Default for Sass-authoring consumers: zero `.cia-*` rules emitted.
511
+ - Opt in via `@use 'css-is-awesome' as cia with ($utilities: true)`.
512
+ - Pre-built `dist/css-is-awesome.utilities.css` still ships every utility for
513
+ CDN drop-in consumers — unchanged. Opt-in governs the Sass compile path only.
514
+
515
+ ### BREAKING — Zero JavaScript in npm package
516
+
517
+ - New hard rule. Audit-able: `find node_modules/css-is-awesome -name "*.mjs"
518
+ -o -name "*.js" -o -name "*.cjs"` returns nothing.
519
+ - The optional `copy-button` JS shim moved to `public/copy-button.mjs`
520
+ (website-only, not in the published `files` manifest).
521
+ - A future `@cia/copy-button` add-on package will be the canonical opt-in path
522
+ for JS-augmented features (v1.x).
523
+
524
+ ### Added — Zero-JS interactive component slate
525
+
526
+ - `cia.accordion` — native `<details name="...">` mutual exclusion
527
+ - `cia.modal` — native `<dialog>` + `::backdrop` + `@starting-style`
528
+ - `cia.tooltip` — native `popover="hint"`
529
+ - `cia.dropdown` — native `[popover]` + auto-dismiss + animation
530
+ - `cia.tabs` — radio + `:has()` + `:nth-of-type()` panel switching
531
+ - `cia.copy-button` + `cia.copy-toast` — styled button (JS handler is a
532
+ documented recipe at `/docs/recipes/copy-button`, NOT shipped)
533
+
534
+ ### Added — Intrinsic layout vocabulary
535
+
536
+ - `m.stack` — vertical rhythm via flex column + gap
537
+ - `m.cluster` — wrapping inline group (pills/tags/buttons)
538
+ - `m.switcher` — auto row↔column based on container width
539
+ - `m.cover` — hero with vertically-centered child
540
+ - `m.frame` — aspect-ratio wrapper for media
541
+
542
+ ### Added — Foundation mixins
543
+
544
+ - `m.theme($name, $scheme)` — wraps a theme's `:root[data-theme=…]` block
545
+ - `m.states($group)` — derives hover/active via `color-mix(in oklch, ..., light-dark(black, white), N%)`
546
+ - `m.theme-properties($tokens)` — emits `@property` registrations for animated theme swaps
547
+ - `m.focus-ring` — centralized; all interactive components route through it
548
+ - `m.sr-only` mixin + opt-in `.cia-sr-only` utility
549
+
550
+ ### Added — Tokens-only micro-bundle
551
+
552
+ - New `scss/tokens.scss` → `dist/tokens.css` (2.3 KB gz). Pure `:root` CSS
553
+ variables, no rules, no resets. The purest mixin-first emit.
554
+ - New `dist/tokens.d.ts` — TypeScript declarations for 123 tokens, IDE
555
+ autocomplete + AI tooling readiness.
556
+
557
+ ### Added — DTCG ingestion
558
+
559
+ - New `scripts/dtcg-to-scss.mjs` — converts DTCG v2025.10 JSON tokens into
560
+ a cia theme SCSS source. Built-in mapping table for color/surface/text/
561
+ action/status/border/type/shape/space paths.
562
+
563
+ ### Added — Docs site refresh
564
+
565
+ - Homepage hero: "Bring your own selectors. We bring the design system." +
566
+ moat comparison section (cia 12 LOC vs Tailwind+HUI 70 LOC accordion).
567
+ - 6 component pages at `/docs/components/{accordion,modal,tooltip,dropdown,tabs,copy-button}`.
568
+ - 3 recipe pages at `/docs/recipes/{anchor-positioning,copy-button,tabs-aria}`.
569
+ - `/docs/themes/pairing` — the `<link media>` two-brand-by-mode recipe.
570
+ - `/compare` refreshed with v0.8 stats + new rows.
571
+ - `/docs/install` mixin-first lead (instead of CDN-first).
572
+ - `/docs/utilities` opt-in callout.
573
+
574
+ ### Fixed — 5-bug cleanup punch list
575
+
576
+ - `scss/_index.scss:12` invalid `@forward 'mixins' as *` syntax (file
577
+ previously failed to compile).
578
+ - `scss/_mixins.scss` `btn-base` calling removed `inline()` mixin → now
579
+ `m.flex($inline: true, $gap: 2)`.
580
+ - 267 lines of dead duplicate mixins removed from `_mixins.scss` (lines 754-1020).
581
+ - Layout `m.container` → `m.wrap` resolves duplicate-mixin collision.
582
+ - `theme/_index.scss` spacing maps now defer to `_system.scss` (single source).
583
+
584
+ ### Locked — Architectural rules (memory)
585
+
586
+ - Mixin-first: cia is the mixin; class/tag is the consumer's choice.
587
+ - No `@layer` — use `:where()` for the Tier 3 bare-tag fix.
588
+ - No JavaScript in the npm package — period.
589
+ - One theme = one file.
590
+ - No Storybook — docs site + `@cia/mcp-server` cover both audiences.
591
+ - No BEM — `__` and `--` modifier patterns forbidden in cia source.
592
+
593
+ ---
594
+
595
+ ## [Unreleased — pre-v0.8]
596
+
597
+ ### Changed — Flex layout API consolidated to `m.flex` (BREAKING)
598
+
599
+ - New `m.flex($direction, $gap, $align, $justify, $wrap, $inline)`
600
+ replaces the six legacy flex helpers. Shorthand value names
601
+ (`start`/`end`/`center`/`between`/`around`/`evenly`) match the
602
+ `cia-*` utility-class vocabulary; full CSS values still pass
603
+ through.
604
+ - **Removed** (no aliases): `m.flex-center`, `m.flex-between`,
605
+ `m.stack`, `m.inline` (from `_mixins.scss`), `m.row`, `m.col`
606
+ (from `_layout.scss`). All internal callsites migrated in this
607
+ pass. Consumers must replace, e.g.:
608
+ ```scss
609
+ @include m.flex-center → @include m.flex($justify: center)
610
+ @include m.flex-between → @include m.flex($justify: between)
611
+ @include m.stack(md) → @include m.flex($direction: column, $gap: md)
612
+ @include m.inline(2) → @include m.flex($gap: 2)
613
+ ```
614
+ - The `cia-flex-center` / `cia-flex-between` utility *classes* in
615
+ `dist/css-is-awesome.utilities.css` are unchanged; only the SCSS
616
+ mixin surface was consolidated.
617
+
618
+ ### Added — Live theme editor (docs site)
619
+
620
+ - New `<ThemeEditorDock>` on `/themes` lets visitors tweak the active
621
+ theme's tokens in-place: category tab strip, paginated sub-pages for
622
+ groups with >4 controls, round color swatches, contrast hints, and a
623
+ lint pass against the 123-token contract. Per-family persistence
624
+ keeps a separate edit set for each theme family.
625
+ - "Download" emits a validator-conformant `theme.css` so an edit can
626
+ drop straight back into `public/themes/<name>/`.
627
+ - **In progress (uncommitted at time of writing):** an "Import" affordance
628
+ that accepts an existing `theme.css` upload and re-hydrates the editor
629
+ with its declared tokens so a partially-edited theme can be picked
630
+ back up later. Will land before the v0.7 tag cuts.
631
+
632
+ ### Changed — npm publish gate (v0.7.0 prep)
633
+
634
+ - `package.json` `files` array now explicitly includes `public/icons` and
635
+ `LICENSE-third-party` so the new Lucide `core` icon pack (49 SVGs) and
636
+ the third-party attribution license ship in the tarball. Verified via
637
+ `npm pack --dry-run` and a real `npm pack` extract: 125 files, 162 kB
638
+ packed / 1.0 MB unpacked, no `dist/components/`, no `src/`, no tests,
639
+ no `.next/` or `out/`. Top-level layout: `dist/`, `scss/`, `public/`,
640
+ `figma-tokens/`, both `LICENSE` files, and the four reference markdown
641
+ docs (`README`, `CHANGELOG`, `AGENTS`, `CLAUDE`, `GEMINI`,
642
+ `css-is-awesome.instructions`).
643
+ - Confirmed `scss/main.scss` no longer `@use`s `_app-styles` (already
644
+ fixed in `d986ea7`). Spot-checked all four `dist/*.css` builds for
645
+ docs-only selectors (`.site-header`, `.docs-*`, `.draft-stamp`,
646
+ `APP STYLES`, `next-`, `launch-gate`) — none present. Build sizes:
647
+ core 18.2 kB / 16.4 kB min, utilities 112.4 kB / 81.9 kB min, full
648
+ 161.5 kB / 115.6 kB min (uncompressed; gzip ≈ 2.4 / 11.5 / 15.2 kB
649
+ per the previously recorded baselines).
650
+ - `_app-styles.scss` itself remains in `scss/` as a project-owned
651
+ template for consuming boilerplates — not imported by any library
652
+ entry, but shipped so a downstream copy-step can pick it up if a
653
+ consumer wants the boilerplate template.
654
+
655
+ ### Added — Docs content refresh + live token visualizers
656
+
657
+ - `/docs` intro now ships a real Quick Start: CDN one-`<link>` snippet, the
658
+ three bundle tiers (`core` 2.4 KB / `utilities` 11.5 KB / `full` 15.2 KB
659
+ gzipped), a side-by-side utility-class vs. SCSS-mixin example, and an
660
+ expanded "What next" with links out to `/docs/tokens`, `/docs/animation`,
661
+ `/themes`, `/docs/authoring/themes`, and `/compare`.
662
+ - `/docs/tokens` swatches now read live values via
663
+ `getComputedStyle(document.documentElement)` and re-resolve whenever the
664
+ active theme changes — color chips, hex/rgb values and the type-scale
665
+ preview all reskin without a reload. Added an `Action (semantic primary)`
666
+ group covering the four `--action-primary-*` slots, an extended radii
667
+ preview that renders `--r-sm/md/lg` next to the `--radius-*` aliases, and
668
+ a Type scale section with sample lines at the resolved sizes.
669
+ - `<Example.Code>` snippets across every docs page now have a
670
+ copy-to-clipboard button. Reads `pre.textContent` (so syntax-highlight
671
+ spans are stripped automatically), shows `Copied` for ~1.5 s, and falls
672
+ back to a hidden-textarea + `execCommand('copy')` when the Async
673
+ Clipboard API is unavailable. Hover-to-reveal on pointer devices,
674
+ always-visible on touch and on focus, with `aria-label` swapping
675
+ between "Copy code to clipboard" and "Copied to clipboard".
676
+ ### Added — A11y contrast linter (Phase 7 differentiator)
677
+
678
+ - New `scripts/theme-a11y.js` (zero deps) implements the WCAG 2.2
679
+ §1.4.3 / §1.4.11 contrast-ratio formulas and is wired into
680
+ `scripts/theme-validator.js`. Every `npm run validate-themes` run now
681
+ audits 17 key token pairs per theme (text on `--paper`, status text
682
+ on subtle status surfaces, inverse text on action primary / `--ai`,
683
+ borders + focus rings + `--shu` against `--paper`). PASS/WARN/FAIL
684
+ with required-vs-actual ratios.
685
+ - **A11y FAILs fail the build by default (as of v0.7).** Every shipped
686
+ theme passes WCAG 2.2 AA across all 17 audited pairs after the v0.7
687
+ triage. `--border-default` is reclassified as decorative
688
+ (informational only) per WCAG 2.2 SC 1.4.11. Pass `--allow-a11y-fail`
689
+ to downgrade contrast FAILs to warnings (useful while authoring a new
690
+ theme); `--strict` is still accepted as a no-op for backwards compat.
691
+ - Translucent foregrounds are alpha-composited onto their background
692
+ before the ratio is computed; translucent backgrounds composite onto
693
+ `--paper` first, so the audited number matches what users see.
694
+ - New `--no-a11y` CLI flag on `theme-validator.js` to skip the audit
695
+ entirely; the contract check still runs.
696
+ - Color formats handled with no dependencies: hex (3/4/6/8 digit), `rgb()`,
697
+ `rgba()`, `hsl()`, `hsla()` (comma + space + slash-alpha syntaxes), 148
698
+ named colors, `transparent`. Modern spaces (`oklch`, `oklab`, `lab`,
699
+ `lch`, `hwb`, `color()`, `color-mix()`) report as **SKIP** with a reason.
700
+ - `var(--token)` references are resolved transitively against the theme's
701
+ own declarations (with `var(--x, fallback)` fallback support).
702
+ - Documented in [`CONTRACT.md`](./CONTRACT.md#a11y-contrast-wcag-22-aa)
703
+ including the audited pairs and the WARN buffer for tertiary / faint
704
+ ink. Source: WCAG 2.2 §1.4.3 / §1.4.11 — relative-luminance formula
705
+ with the standard `(L1+0.05)/(L2+0.05)` ratio.
706
+
707
+ ### Added — Boilerplate theme (recommended starter)
708
+
709
+ - New theme **Boilerplate** (`boilerplate-light` + `boilerplate-dark`) at
710
+ `public/themes/boilerplate/theme.css`. Both modes ship in a single file
711
+ and each declares the full 123-token contract.
712
+ - Design intent: a neutral, low-flourish, easy-to-override starter.
713
+ Slate-leaning grays + one clean blue accent (`#2563eb` / `#3b82f6`),
714
+ system UI sans-serif by default (no web fonts, no `@import` — fastest
715
+ possible first paint), `ui-monospace` code stack, subtle shadows,
716
+ standard 4 / 6 / 8 px radii. Goal: drop it in, accept defaults, get
717
+ something that looks "modern, clean, professional, and unsurprising."
718
+ - Bundled into the consolidated `public/theme.css` via
719
+ `scripts/bundle-companion-themes.mjs` (script extended to support
720
+ multiple `[data-theme]` blocks per source folder).
721
+ - Selectable in the docs UI: added to `<ThemeSelect>` (header dropdown),
722
+ `<ThemePicker>` (docs row), and the `/themes/gallery` page as the
723
+ first tile.
724
+ - Gates the v0.7 npm publish (per ROADMAP.md).
725
+
726
+ ### BREAKING CHANGES — Theme naming convention (Feature 2.14)
727
+
728
+ Every built-in theme name now carries a `-light` / `-dark` mode suffix.
729
+ Five of the six original themes are renamed; `terminal` stays
730
+ single-mode by design (CRT phosphor only — a "terminal-light" is no
731
+ longer terminal).
732
+
733
+ | v0.6 name | v0.7 name |
734
+ |----------------|---------------------|
735
+ | `sketchbook` | `sketchbook-light` |
736
+ | `press` | `press-light` |
737
+ | `graphite` | `graphite-dark` |
738
+ | `glass` | `glass-light` |
739
+ | `cupertino` | `cupertino-light` |
740
+
741
+ **Backward-compat aliases** ship in `public/theme.css` for the entire
742
+ 0.7.x line: `<html data-theme="sketchbook">` keeps resolving to the
743
+ sketchbook-light tokens, etc. The aliases are **removed in v0.8**
744
+ (US-2.14.3). Migration steps are in [`MIGRATION.md`](./MIGRATION.md).
745
+
746
+ The default attribute on `<html>` and the default cookie value both
747
+ become `sketchbook-light`. The `:root:not([data-theme])` fallback in
748
+ the consolidated bundle still selects sketchbook so a no-attribute
749
+ drop-in still works.
750
+
751
+ ### Changed — Theme system
752
+
753
+ - `public/theme.css` selectors renamed (with the v0.6 names retained as
754
+ comma-grouped alias selectors on each block).
755
+ - `public/themes/{press,graphite,glass,cupertino}/` folders renamed to
756
+ `{press-light,graphite-dark,glass-light,cupertino-light}/`. Per-theme
757
+ banner comments updated.
758
+ - `<ThemePicker>` and the `/themes` gallery emit suffixed IDs.
759
+ - Pre-hydration script in `app/layout.tsx` accepts both old and new
760
+ cookie values (old maps to alias selectors).
761
+ - Visual-regression baselines under `tests/__screenshots__/` renamed to
762
+ match the new theme IDs.
763
+
764
+ ### Added — Documentation
765
+
766
+ - [`MIGRATION.md`](./MIGRATION.md) — v0.7 migration steps for consumers
767
+ (theme renames, removal timeline, per-tier impact).
768
+ - [`THREE-TIERS.md`](./THREE-TIERS.md) — top-level doc for the canonical
769
+ three-tier authoring story (drop-in classes, SCSS mixins, bare tags),
770
+ same-button-three-ways demo, router architecture, and a picking-a-tier
771
+ table.
772
+ - New docs route `/docs/three-tiers` dogfoods the same story with live
773
+ Button previews next to each tier's code. Sidebar nav: "Three tiers"
774
+ sits between Introduction and Install under Getting started.
775
+ - `/docs/animation` rewritten as a live preview page: every keyframe in
776
+ `_animations.scss` rendered as a card in a responsive grid, with
777
+ hover/click/keyboard-driven replay for one-shot animations and
778
+ always-on previews for loopers. Cards show the `cia-anim-*` utility
779
+ class so readers can copy the trigger directly. Page reads from the
780
+ same motion tokens (`--duration-*`, `--ease`) so swapping themes via
781
+ the header dropdown or floating ThemePicker retimes every preview in
782
+ place. Reduced-motion safety net documented inline.
783
+
784
+ ### Changed — Documentation
785
+
786
+ - README "Two ways to use it" → "Three ways to use it" with a Tier 3
787
+ bare-tags section and a link to `THREE-TIERS.md`.
788
+
789
+ ### Added — Icons (Lucide `core` pack + per-theme override)
790
+
791
+ - **Default `core` icon pack** vendored from Lucide, shipping at
792
+ `public/icons/core/<name>.svg` — 49 glyphs (8 already shipped + 41
793
+ new) covering navigation, actions, status, communication, user /
794
+ security, and media. Source list and per-glyph mapping documented in
795
+ `roadmap/icons-proposal.md` and `scripts/icon-contract.json`.
796
+ - **Per-theme override mechanism** in `scss/_icons.scss`. The `m.svg`,
797
+ `m.svg-bg`, and `m.svg-text` mixins now emit
798
+ `var(--cia-icon-<name>, url('/icons/core/<name>.svg'))` as the icon
799
+ URL, so a theme overrides one glyph by declaring
800
+ `--cia-icon-<name>: url('/themes/<theme>/icons/core/<name>.svg')` on
801
+ `:root`. Resolution order: per-theme override → core pack → 404.
802
+ Mixin call signatures are unchanged (`m.svg(check)` still works).
803
+ - New SCSS variable `$icon-pack` (default `'core'`, re-exported as
804
+ `$theme-icon-pack`) decouples the pack folder from `$icon-path`.
805
+ - New machine-readable contract at `scripts/icon-contract.json` and a
806
+ validator at `scripts/icon-validator.js` (`npm run validate-icons`)
807
+ that mirror the theme-validator. The validator fails if a pack omits
808
+ any contract glyph.
809
+ - New script `scripts/vendor-lucide-core.mjs` (idempotent) regenerates
810
+ `public/icons/core/` from `lucide-static`.
811
+ - New `LICENSE-third-party` at the repo root attributing Lucide
812
+ (ISC + Feather-derived MIT subset).
813
+ - `CONTRACT.md` gains an "Icons contract" section covering the
814
+ resolution order, the canonical 49-glyph list, naming conventions,
815
+ and SVG file-format expectations.
816
+ - `AGENTS.md` gains a short "Icons" subsection pointing at
817
+ `CONTRACT.md` for the full spec.
818
+
819
+ The legacy flat-layout files at `public/icons/<name>.svg` (the original
820
+ 8 glyphs) remain on disk as a backward-compat copy; the mixin output now
821
+ resolves against `/icons/core/<name>.svg`.
822
+
823
+ ## [0.6.0] - 2026-04-25
824
+
825
+ First public release — the npm + CDN cut. The library, its docs, the
826
+ theme system, the React component layer, the test pipeline, and the
827
+ release/CDN automation all land together — designed as one system,
828
+ shipped as one cake. v1.0.0 is reserved for after the CDN smoke is
829
+ verified live and the API has stabilised in production usage.
830
+
831
+ ### Added — Library
832
+
833
+ - Six built-in themes: **Sketchbook** (default), **Press**, **Graphite**,
834
+ **Glass**, **Cupertino**, **Terminal**. All ship as `[data-theme="..."]`
835
+ blocks in a single consolidated `public/theme.css`; per-theme files
836
+ remain at `public/themes/<name>/theme.css` for external download.
837
+ - 123-token theme contract (`scripts/theme-contract.json`) + validator
838
+ (`scripts/theme-validator.js`) that gate every theme, consolidated or
839
+ standalone.
840
+ - ~120 SCSS mixins across `_mixins.scss`, `_layout.scss`, `_animations.scss`,
841
+ `_icons.scss`, and the `components/*.scss` partials. Mixin-first API.
842
+ - Token-driven runtime theming via `<html data-theme="...">` attribute +
843
+ cookie persistence. No FOUC, no `<link href>` mutation, no hydration
844
+ mismatch.
845
+ - Animation system: 12 named keyframes, motion tokens
846
+ (`--duration-fast/normal/slow`, `--ease`), `.cia-anim-*` and
847
+ `.cia-hover-*` utility classes, all respecting `prefers-reduced-motion`.
848
+ - Utility class set (`.cia-*` namespace) for spacing, flex, grid, text,
849
+ color, display, position, sizing — covered in
850
+ [`/docs/utilities`](./src/app/docs/utilities/page.tsx).
851
+ - Icon system in `scss/_icons.scss` with SVG and Font Awesome tracks; eight
852
+ starter SVGs in `public/icons/`.
853
+
854
+ ### Added — React component library
855
+
856
+ - 45 React components built on `forwardRef` + CSS Modules: Accordion,
857
+ Alert, Avatar, Badge, Breadcrumb, Button, Card, Checkbox, DataTable,
858
+ Divider, DocsSidebar, DraftStamp, Dropdown, Example, FormField, Input,
859
+ Label, LaunchGate, List, Logo, LogoMark, MenuItem, Modal, Pagination,
860
+ Popover, Post, Principle, Progress, Radio, Seal, SearchBar, Select,
861
+ SiteHeader, Skeleton, Slider, Spinner, StatChip, Switch, Tabs, Tag,
862
+ Textarea, ThemePicker, ThemeTile, TimelineItem, Toast, Tooltip.
863
+
864
+ ### Added — Documentation site
865
+
866
+ - Nested-route docs at `/docs` with shared shell (sidebar + on-this-page
867
+ TOC + prev/next footer + cookie-driven theme picker).
868
+ - 24 static-export pages including: getting started, install (CDN /
869
+ npm-SCSS / React-Next / download), tokens reference, mixin API, utility
870
+ class reference, animation reference, accessibility reference, recipes
871
+ (10 composed patterns), Bootstrap migration, Tailwind migration, theme
872
+ authoring guide, icon authoring guide, FAQ.
873
+ - LaunchGate component + `public/flags.json` for coming-soon and
874
+ announcement banner modes.
875
+
876
+ ### Added — Quality, CI, and release
877
+
878
+ - GitHub Actions CI workflow (`.github/workflows/ci.yml`): lint, SCSS
879
+ lint, theme validator, library bundle build, Next static export, docs
880
+ artifact upload.
881
+ - Playwright suite (`tests/`): 16 smoke tests, 5 axe-core a11y scans, 18
882
+ visual-regression baselines (6 themes × 3 routes). Parallel CI job.
883
+ - `semantic-release` pipeline (`.releaserc.json` +
884
+ `.github/workflows/release.yml`) gated on CI success — Conventional
885
+ Commits drive `CHANGELOG.md`, version bumps, GitHub releases, and npm
886
+ publish.
887
+ - CDN publish workflow (`.github/workflows/cdn-publish.yml`): on every
888
+ release, attaches `.tar.gz` + `.zip` bundles to the GitHub Release and
889
+ smoke-checks five jsDelivr URLs.
890
+ - Package shaped for distribution: `exports` map (CSS bundles + SCSS
891
+ source + per-theme files + figma tokens), `peerDependencies` (sass
892
+ optional), `engines.node >= 20`, `prepublishOnly` builds bundles.
893
+
894
+ ### Added — Community meta
895
+
896
+ - `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md` (Contributor Covenant 2.1
897
+ adoption), `SECURITY.md` (90-day coordinated disclosure),
898
+ `VERSIONING.md` (SemVer + deprecation lifecycle + Conventional Commits
899
+ mapping).
900
+ - Issue templates: bug report, feature request, theme submission,
901
+ question; pull-request template.
902
+ - README badges (CI status + Node 20 + MIT + semantic-release).
903
+
904
+ ### Changed — Mixin API consolidation
905
+
906
+ - **Buttons**: `btn-primary`, `btn-secondary`, `btn-outline`, `btn-ghost`,
907
+ and `btn-preset` are replaced by a single `btn($variant)` router. Status
908
+ variants (info / success / warning / error) are FREE via token
909
+ interpolation (`#{$variant}-default`, `#{$variant}-subtle`,
910
+ `#{$variant}-text`). The previous mixin names are gone — call sites
911
+ update to `@include btn(primary)`.
912
+ - **Tag**: `tag-base` + `tag-removable` are replaced by
913
+ `tag($removable: false)`.
914
+ - **List item**: `list-item` + `list-item-interactive` are replaced by
915
+ `list-item($interactive: false)`.
916
+ - **`nav-link`** removed — was an alias for `navbar-link`. Use
917
+ `navbar-link` directly.
918
+
919
+ ### Changed — Theme system
920
+
921
+ - Theme dispatch moved from runtime `<link href>` mutation to
922
+ `<html data-theme="...">` attribute + cookie. Eliminates Next 15 / React
923
+ 19 hydration warnings on docs routes. The previous `cia-theme-file`
924
+ localStorage key is replaced by a `cia-theme` cookie.
925
+ - **Numbered sizing scale migration (non-breaking refactor).** Numeric
926
+ keys (`1..N`) are now the authoritative source of truth for the internal
927
+ scale maps; t-shirt keys (`xs/sm/md/…`) layer on top as aliases that
928
+ resolve to the same values. Aligns with Radix, Open Props, IBM Carbon
929
+ conventions; unblocks numeric tokens (`--space-1..9`,
930
+ `--font-size-1..10`, …).
931
+
932
+ Both call styles continue to produce identical visual output —
933
+ `m.space(4)` and `m.space(md)` both resolve to `1rem`. The generator
934
+ emits both `--space-4` *and* `--space-md` at `:root` so themes can
935
+ declare either.
936
+
937
+ Mixin defaults flipped from t-shirt to numeric across `_mixins.scss`,
938
+ `_layout.scss`, and `components/*.scss` (~60 defaults). Theme
939
+ component tokens in `scss/theme/_components.scss` flipped too; radius
940
+ component tokens stayed t-shirt because the radius scale is
941
+ anchor-named (`sm/md/lg/xl/full`).
942
+
943
+ `$radius`, `$z-layers`, `$letter-spacings`, `$breakpoints`, and
944
+ container width aliases stay keyed by name (semantic anchor maps).
945
+
946
+ - Standardized dark/light theme selector on `[data-theme="..."]`. The
947
+ `.theme-dark` / `.theme-light` class selectors are removed from the
948
+ generator and documentation. For component-scoped theming, use the
949
+ `generate-scoped` mixin under your own selector.
950
+
951
+ ### Fixed
952
+
953
+ - Real fixes (not allowlist) for 7 axe-core serious violations:
954
+ color-contrast on home/footer; in-prose link contrast on
955
+ `/docs/install` + `/docs/tokens`; aria-prohibited-attr on token
956
+ swatches; aria-hidden-focus on the recipes-page modal demo;
957
+ scrollable-region-focusable on `<pre>` code samples.
958
+ - React 19 hydration mismatch on `/docs/*` routes — root cause was
959
+ `usePathname()` in `DocsNav` + `DocsPrevNext` resolving differently
960
+ between static-export build time and client hydration. Fixed with a
961
+ `mounted` gate in both components.
962
+ - 4 ESLint warnings: Popover useEffect deps, Avatar `<img>` →
963
+ `next/image`, Dropdown unused `_ref`, Radio unsupported
964
+ `aria-invalid`.
965
+ - Eliminated Sass "unquoted color-name in interpolation" warning by
966
+ quoting the `black` key in `$font-weights` (`scss/_system.scss`).
967
+ - Doc typo in `scss/README.md`: import example referenced a nonexistent
968
+ `primitives` module; corrected to `system`.
969
+
970
+ ### Removed
971
+
972
+ - Hex-coded `buttonold` scratch mixin (replaced by token-driven
973
+ `btn-preset`, then absorbed into `btn($variant)`).
974
+
975
+ ### Sizing scale alias tables
976
+
977
+ For reference — both call styles produce identical output. T-shirt aliases
978
+ remain available for legacy code; numbered keys are recommended for new code.
979
+
980
+ Space (`$spacing`, `$space`):
981
+ | t-shirt | numeric | value |
982
+ | ------- | ------- | -------- |
983
+ | xs | 1 | 0.5rem |
984
+ | sm | 2 | 0.75rem |
985
+ | — | 3 | 0.875rem |
986
+ | md | 4 | 1rem |
987
+ | lg | 5 | 1.5rem |
988
+ | xl | 6 | 2rem |
989
+ | 2xl | 7 | 3rem |
990
+ | 3xl | 8 | 4rem |
991
+ | 4xl | 9 | 6rem |
992
+
993
+ Extras outside the numbered scale: `0` / `none` (0), `2xs` (0.25rem).
994
+
995
+ Font size (`$font-sizes`):
996
+ | t-shirt | numeric | value |
997
+ | ------- | ------- | -------- |
998
+ | xs | 1 | 0.75rem |
999
+ | sm | 2 | 0.875rem |
1000
+ | base | 3 | 1rem |
1001
+ | lg | 4 | 1.125rem |
1002
+ | xl | 5 | 1.25rem |
1003
+ | 2xl | 6 | 1.5rem |
1004
+ | 3xl | 7 | 1.875rem |
1005
+ | 4xl | 8 | 2.25rem |
1006
+ | 5xl | 9 | 3rem |
1007
+ | 6xl | 10 | 3.75rem |
1008
+
1009
+ Line height (`$line-heights`):
1010
+ | named | numeric | value |
1011
+ | ------- | ------- | ----- |
1012
+ | none | 1 | 1 |
1013
+ | tight | 2 | 1.25 |
1014
+ | snug | 3 | 1.375 |
1015
+ | normal | 4 | 1.5 |
1016
+ | relaxed | 5 | 1.625 |
1017
+ | loose | 6 | 2 |
1018
+
1019
+ Shadow (`$shadows-light` / `$shadows-dark`):
1020
+ | t-shirt | numeric |
1021
+ | ------- | ------- |
1022
+ | sm | 1 |
1023
+ | md | 2 |
1024
+ | lg | 3 |
1025
+ | xl | 4 |
1026
+ | 2xl | 5 |
1027
+
1028
+ Semantic shadow keys (`inner`, `none`) remain named.
1029
+
1030
+ ## [0.1.0] - 2026-04-15
1031
+
1032
+ ### Added
1033
+ - Initial extraction of the SCSS design system from `boiler-project-ai`.
1034
+ - `package.json` with `build`, `build:min`, and `watch` scripts.
1035
+ - Top-level `README.md` with install and usage instructions.
1036
+ - `ROADMAP.md` outlining phases through v1.0.