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
@@ -0,0 +1,229 @@
1
+ @charset "UTF-8";
2
+ /* ============================================================
3
+ THEME — Terminal (VT100 CRT Phosphor)
4
+ -----------------------------------------------------------
5
+ This is the ONE FILE users swap to reskin their site.
6
+ Replace this file with any other theme.css to change the
7
+ entire look & feel. Tokens only — no component CSS lives here.
8
+
9
+ TOKEN CONTRACT
10
+ -----------------------------------------------------------
11
+ Every theme MUST declare every variable in this file, even
12
+ if it sets it to a neutral value (e.g. --blur-md: none;).
13
+ That's what guarantees a clean one-file swap.
14
+
15
+ Slots:
16
+ Surfaces : --paper, --paper-raised, --paper-sunk, --paper-glass
17
+ Ink : --ink, --ink-soft, --ink-faint, --graphite, --muted
18
+ Lines : --guide, --guide-soft, --hair, --hair-soft
19
+ Primary : --ai, --ai-ink, --ai-wash (cyan — terminal links)
20
+ Seal : --shu, --shu-wash (error red)
21
+ Accent : --ochre, --ochre-wash (warning amber)
22
+ Code : --code-bg/ink/muted/accent/green/blue
23
+ Type : --font-display/script/serif/sans/mono
24
+ Radius : --r-sm, --r-md, --r-lg
25
+ Shadow : --shadow-sm, --shadow-md, --shadow-lg
26
+ Blur : --blur-sm, --blur-md, --blur-lg (glass only; else 'none')
27
+ Glow : --glow-sm, --glow-md, --glow-lg (emphasis / rim / phosphor)
28
+ Motion : --duration-fast, --duration-normal, --duration-slow, --ease
29
+
30
+ FONT NOTE
31
+ -----------------------------------------------------------
32
+ A terminal has no serif and no handwritten script. To keep
33
+ the contract intact without breaking the mood, every font
34
+ slot — display, script, serif, sans, mono — points at
35
+ --font-mono. The contract survives; the CRT stays pure.
36
+ ============================================================ */
37
+ @import 'https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&family=IBM+Plex+Mono:wght@400;500;700&display=swap';
38
+ :root, :root[data-theme=terminal-dark] {
39
+ color-scheme: dark;
40
+ /* Surfaces — deep warm black chassis + phosphor haze */
41
+ --paper: #0A0E0A;
42
+ --paper-raised: #0F140F;
43
+ --paper-sunk: #070A07;
44
+ --paper-glass: rgba(79, 224, 120, 0.06);
45
+ /* Ink — phosphor green on the tube */
46
+ --ink: #4FE078;
47
+ --ink-soft: #2A8B42;
48
+ --ink-faint: #3DAF4F;
49
+ --graphite: #1A3D22;
50
+ --muted: #2A8B42;
51
+ /* Scanlines / rule lines */
52
+ --guide: #1E5E2F;
53
+ --guide-soft: #143618;
54
+ --hair: #2A8B42;
55
+ --hair-soft: #1E5E2F;
56
+ /* Primary accent — cyan (interactive links in a terminal) */
57
+ --ai: #7FDBFF;
58
+ --ai-ink: #5AB3D4;
59
+ --ai-wash: rgba(127, 219, 255, 0.10);
60
+ /* Seal — error red */
61
+ --shu: #FF5A5A;
62
+ --shu-wash: rgba(255, 90, 90, 0.10);
63
+ /* Accent — warning amber */
64
+ --ochre: #F0A030;
65
+ --ochre-wash: rgba(240, 160, 48, 0.10);
66
+ /* Code surface */
67
+ --code-bg: #070A07;
68
+ --code-ink: #4FE078;
69
+ --code-muted: #2A8B42;
70
+ --code-accent: #F0A030;
71
+ --code-green: #8FFCA8;
72
+ --code-blue: #7FDBFF;
73
+ /* Typography — mono everywhere (see FONT NOTE in header) */
74
+ --font-mono: 'JetBrains Mono', 'IBM Plex Mono', 'Fira Code', ui-monospace, Consolas, Menlo, 'Courier New', monospace;
75
+ --font-sans: var(--font-mono);
76
+ --font-serif: var(--font-mono);
77
+ --font-display: var(--font-mono);
78
+ --font-script: var(--font-mono);
79
+ /* Radius — a CRT has hard pixel corners */
80
+ --r-sm: 0;
81
+ --r-md: 0;
82
+ --r-lg: 0;
83
+ /* Shadows — a CRT doesn't cast, it emits. Keep subtle. */
84
+ --shadow-sm: 0 0 0 1px rgba(79, 224, 120, 0.20);
85
+ --shadow-md: 0 0 0 1px rgba(79, 224, 120, 0.30), 0 0 12px rgba(79, 224, 120, 0.15);
86
+ --shadow-lg: 0 0 0 1px rgba(79, 224, 120, 0.40), 0 0 24px rgba(79, 224, 120, 0.25);
87
+ --shadow-xl: 0 0 0 1px rgba(79, 224, 120, 0.50), 0 0 36px rgba(79, 224, 120, 0.30);
88
+ --shadow-2xl: 0 0 0 1px rgba(79, 224, 120, 0.60), 0 0 56px rgba(79, 224, 120, 0.40);
89
+ /* Blur — terminal has no frosted glass; declared so swap stays lossless */
90
+ --blur-sm: none;
91
+ --blur-md: none;
92
+ --blur-lg: none;
93
+ /* Glow — phosphor halo (this is where the theme sings) */
94
+ --glow-sm: 0 0 4px rgba(79, 224, 120, 0.25);
95
+ --glow-md: 0 0 8px rgba(79, 224, 120, 0.35);
96
+ --glow-lg: 0 0 16px rgba(79, 224, 120, 0.45);
97
+ /* Motion — terminals are instant */
98
+ --duration-fast: 100ms;
99
+ --duration-normal: 140ms;
100
+ --duration-slow: 220ms;
101
+ --ease: cubic-bezier(0.2, 0.0, 0.2, 1);
102
+ /* ----------------------------------------------------------
103
+ SEMANTIC ALIASES
104
+ -----------------------------------------------------------
105
+ Bridge the library's expected names to this theme's native
106
+ palette. Components can now write m.color(surface-default)
107
+ or var(--surface-default) and reskin with the theme
108
+ automatically.
109
+ ---------------------------------------------------------- */
110
+ /* Backgrounds (page-level) */
111
+ --background-default: var(--paper);
112
+ --background-subtle: var(--paper-sunk);
113
+ --background-navbar: var(--paper-raised);
114
+ /* Surfaces */
115
+ --surface-default: var(--paper);
116
+ --surface-raised: var(--paper-raised);
117
+ --surface-sunk: var(--paper-sunk);
118
+ --surface-muted: var(--paper-sunk);
119
+ --surface-subtle: var(--paper-raised);
120
+ --surface-emphasis: var(--ink);
121
+ --surface-glass: var(--paper-glass);
122
+ /* Text */
123
+ --text-primary: var(--ink);
124
+ --text-secondary: var(--ink-soft);
125
+ --text-muted: var(--ink-faint);
126
+ --text-tertiary: var(--muted);
127
+ --text-inverse: var(--paper);
128
+ --text-link: var(--ai);
129
+ --text-link-hover: var(--ai-ink);
130
+ /* Borders */
131
+ --border-default: var(--hair);
132
+ --border-subtle: var(--hair-soft);
133
+ --border-emphasis: var(--ink);
134
+ --border-focus: var(--ai);
135
+ /* Interactive (hover / active wash layers) — phosphor-green translucent overlays */
136
+ --interactive-hover: rgba(79, 224, 120, 0.08);
137
+ --interactive-active: rgba(79, 224, 120, 0.15);
138
+ /* Brand (identity — action-primary usually references these) */
139
+ --brand-primary: var(--ai);
140
+ --brand-primary-hover: var(--ai-ink);
141
+ /* Action (primary / secondary / tertiary) */
142
+ --action-primary-default: var(--ai);
143
+ --action-primary-hover: var(--ai-ink);
144
+ --action-primary-active: var(--ai-ink);
145
+ --action-primary-wash: var(--ai-wash);
146
+ --action-secondary-default: var(--shu);
147
+ --action-secondary-hover: var(--shu);
148
+ --action-secondary-active: var(--shu);
149
+ --action-secondary-wash: var(--shu-wash);
150
+ --action-tertiary-default: var(--ochre);
151
+ --action-tertiary-hover: var(--ochre);
152
+ --action-tertiary-active: var(--ochre);
153
+ --action-tertiary-wash: var(--ochre-wash);
154
+ /* Feedback / status (high-level semantic) */
155
+ --feedback-info: var(--ai);
156
+ --feedback-success: var(--code-green);
157
+ --feedback-warning: var(--ochre);
158
+ --feedback-error: var(--shu);
159
+ /* Status — info (three-part: default / subtle / text) — cyan */
160
+ --info-default: var(--ai);
161
+ --info-subtle: rgba(127, 219, 255, 0.12);
162
+ --info-text: #7FDBFF;
163
+ /* Status — success — bright phosphor */
164
+ --success-default: #8FFCA8;
165
+ --success-subtle: rgba(143, 252, 168, 0.12);
166
+ --success-text: #8FFCA8;
167
+ /* Status — warning — amber */
168
+ --warning-default: var(--ochre);
169
+ --warning-subtle: rgba(240, 160, 48, 0.12);
170
+ --warning-text: var(--ochre);
171
+ /* Status — error — red */
172
+ --error-default: var(--shu);
173
+ --error-subtle: rgba(255, 90, 90, 0.12);
174
+ --error-text: #FF7A7A;
175
+ /* ----------------------------------------------------------
176
+ LIBRARY SCALES (space / radius / type / motion / z)
177
+ -----------------------------------------------------------
178
+ The library mixins emit var(--space-<key>), var(--radius-<key>),
179
+ var(--font-primary), var(--font-size-<key>), var(--z-<key>), …
180
+ Themes declare the slots so those mixins always resolve.
181
+ ---------------------------------------------------------- */
182
+ /* Space scale (rem for accessibility — natural scale, same as Sketchbook) */
183
+ /* Spacing rhythm — THE knob for how dense or airy this theme feels.
184
+ The numbered scale is the source of truth: every component reads
185
+ var(--space-N), and the t-shirt aliases (--space-md, --space-lg …)
186
+ are emitted by the library as references to these, so they follow
187
+ automatically. Change a value here and the whole page re-proportions.
188
+ Halve them for a compact UI; raise 4/5/6 for an airy editorial feel. */
189
+ --space-0: 0; /* flush */
190
+ --space-1: 0.5rem; /* tight inner gap */
191
+ --space-2: 0.75rem; /* control padding */
192
+ --space-3: 0.875rem; /* (no t-shirt) */
193
+ --space-4: 1rem; /* default rhythm */
194
+ --space-5: 1.5rem; /* section gap */
195
+ --space-6: 2rem; /* block gap */
196
+ --space-7: 3rem; /* major gap */
197
+ --space-8: 4rem; /* page section */
198
+ --space-9: 6rem; /* hero rhythm */
199
+ /* Radius alias — CRT has hard pixel corners, so every slot is 0 */
200
+ --radius-sm: 0;
201
+ --radius-md: 0;
202
+ --radius-lg: 0;
203
+ --radius-xl: 0;
204
+ --radius-full: 0;
205
+ /* Typography — mono body + key scale slots (15px matches CRT body setting) */
206
+ --font-primary: var(--font-mono);
207
+ --font-size-base: 15px;
208
+ --line-height-normal: 1.5;
209
+ --font-weight-medium: 500;
210
+ /* Z-index layers (layering is universal) */
211
+ --z-sticky: 1020;
212
+ --z-dropdown: 1030;
213
+ --z-backdrop: 1040;
214
+ --z-modal: 1050;
215
+ --z-popover: 1060;
216
+ --z-tooltip: 1070;
217
+ /* ----------------------------------------------------------
218
+ OPTIONAL COMPONENT OVERRIDES (Feature 1.3)
219
+ -----------------------------------------------------------
220
+ Terminal-specific component expressions: zero radii on
221
+ buttons/cards/inputs and a subtle phosphor glow on cards
222
+ instead of a drop shadow.
223
+ ---------------------------------------------------------- */
224
+ --btn-radius: 0;
225
+ --card-radius: 0;
226
+ --input-radius: 0;
227
+ --card-shadow: var(--glow-sm);
228
+ --card-border: 1px solid var(--ink-faint);
229
+ }
@@ -0,0 +1,152 @@
1
+ @charset "UTF-8";
2
+ @import 'https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&family=IBM+Plex+Mono:wght@400;500;700&display=swap';
3
+ :root, :root[data-theme=terminal-light] {
4
+ color-scheme: light;
5
+ /* Surfaces — clear light gray paper */
6
+ --paper: #E8E8E8;
7
+ --paper-raised: #F5F5F5;
8
+ --paper-sunk: #D8D8D8;
9
+ --paper-glass: rgba(232, 232, 232, 0.85);
10
+ /* Ink — near-black mono */
11
+ --ink: #1A1A1A;
12
+ --ink-soft: #404040;
13
+ --ink-faint: #666;
14
+ --graphite: #0A0A0A;
15
+ --muted: #7C7C7C;
16
+ /* Hairlines — medium gray */
17
+ --guide: #B8B8B8;
18
+ --guide-soft: #C8C8C8;
19
+ --hair: #C0C0C0;
20
+ --hair-soft: #D8D8D8;
21
+ /* Primary accent — VS Code keyword blue */
22
+ --ai: #0451A5;
23
+ --ai-ink: #023268;
24
+ --ai-wash: rgba(4, 81, 165, 0.10);
25
+ /* Seal — error red */
26
+ --shu: #B91C1C;
27
+ --shu-wash: rgba(185, 28, 28, 0.10);
28
+ /* Accent — warning amber */
29
+ --ochre: #B45309;
30
+ --ochre-wash: rgba(180, 83, 9, 0.10);
31
+ /* Code surface */
32
+ --code-bg: #DDD;
33
+ --code-ink: #1A1A1A;
34
+ --code-muted: #5B5B5B;
35
+ --code-accent: #934407;
36
+ --code-green: #006A28;
37
+ --code-blue: #0451A5;
38
+ /* Typography — mono everywhere */
39
+ --font-mono: 'JetBrains Mono', 'IBM Plex Mono', 'Fira Code', ui-monospace, Consolas, Menlo, 'Courier New', monospace;
40
+ --font-sans: var(--font-mono);
41
+ --font-serif: var(--font-mono);
42
+ --font-display: var(--font-mono);
43
+ --font-script: var(--font-mono);
44
+ /* Radius — terminals are square */
45
+ --r-sm: 0;
46
+ --r-md: 0;
47
+ --r-lg: 0;
48
+ /* Shadows — hairline rings */
49
+ --shadow-sm: 0 0 0 1px rgba(26, 26, 26, 0.08);
50
+ --shadow-md: 0 0 0 1px rgba(26, 26, 26, 0.10), 0 1px 2px rgba(26, 26, 26, 0.06);
51
+ --shadow-lg: 0 0 0 1px rgba(26, 26, 26, 0.12), 0 2px 4px rgba(26, 26, 26, 0.08);
52
+ --shadow-xl: 0 0 0 1px rgba(26, 26, 26, 0.14), 0 4px 8px rgba(26, 26, 26, 0.10);
53
+ --shadow-2xl: 0 0 0 1px rgba(26, 26, 26, 0.16), 0 8px 16px rgba(26, 26, 26, 0.12);
54
+ /* Blur / glow — daylight, no emission */
55
+ --blur-sm: none;
56
+ --blur-md: none;
57
+ --blur-lg: none;
58
+ --glow-sm: 0 0 0 transparent;
59
+ --glow-md: 0 0 0 transparent;
60
+ --glow-lg: 0 0 0 transparent;
61
+ /* Motion — instant */
62
+ --duration-fast: 100ms;
63
+ --duration-normal: 140ms;
64
+ --duration-slow: 220ms;
65
+ --ease: cubic-bezier(0.2, 0.0, 0.2, 1);
66
+ /* Semantic aliases */
67
+ --background-default: var(--paper);
68
+ --background-subtle: var(--paper-sunk);
69
+ --background-navbar: var(--paper-raised);
70
+ --surface-default: var(--paper);
71
+ --surface-raised: var(--paper-raised);
72
+ --surface-sunk: var(--paper-sunk);
73
+ --surface-muted: var(--paper-sunk);
74
+ --surface-subtle: var(--paper-raised);
75
+ --surface-emphasis: var(--ink);
76
+ --surface-glass: var(--paper-glass);
77
+ --text-primary: var(--ink);
78
+ --text-secondary: var(--ink-soft);
79
+ --text-muted: var(--ink-faint);
80
+ --text-tertiary: var(--muted);
81
+ --text-inverse: var(--paper);
82
+ --text-link: var(--ai);
83
+ --text-link-hover: var(--ai-ink);
84
+ --border-default: var(--hair);
85
+ --border-subtle: var(--hair-soft);
86
+ --border-emphasis: var(--ink);
87
+ --border-focus: var(--ai);
88
+ --interactive-hover: rgba(26, 26, 26, 0.05);
89
+ --interactive-active: rgba(26, 26, 26, 0.10);
90
+ --brand-primary: var(--ai);
91
+ --brand-primary-hover: var(--ai-ink);
92
+ --action-primary-default: var(--ai);
93
+ --action-primary-hover: var(--ai-ink);
94
+ --action-primary-active: var(--ai-ink);
95
+ --action-primary-wash: var(--ai-wash);
96
+ --action-secondary-default: var(--shu);
97
+ --action-secondary-hover: var(--shu);
98
+ --action-secondary-active: var(--shu);
99
+ --action-secondary-wash: var(--shu-wash);
100
+ --action-tertiary-default: var(--ochre);
101
+ --action-tertiary-hover: var(--ochre);
102
+ --action-tertiary-active: var(--ochre);
103
+ --action-tertiary-wash: var(--ochre-wash);
104
+ --feedback-info: var(--ai);
105
+ --feedback-success: #083;
106
+ --feedback-warning: var(--ochre);
107
+ --feedback-error: var(--shu);
108
+ --info-default: var(--ai);
109
+ --info-subtle: rgba(4, 81, 165, 0.10);
110
+ --info-text: var(--ai-ink);
111
+ --success-default: #083;
112
+ --success-subtle: rgba(0, 136, 51, 0.10);
113
+ --success-text: #062;
114
+ --warning-default: var(--ochre);
115
+ --warning-subtle: rgba(180, 83, 9, 0.10);
116
+ --warning-text: #92400E;
117
+ --error-default: var(--shu);
118
+ --error-subtle: rgba(185, 28, 28, 0.10);
119
+ --error-text: #7F1D1D;
120
+ /* Library scales */
121
+ /* Spacing rhythm — THE knob for how dense or airy this theme feels.
122
+ The numbered scale is the source of truth: every component reads
123
+ var(--space-N), and the t-shirt aliases (--space-md, --space-lg …)
124
+ are emitted by the library as references to these, so they follow
125
+ automatically. Change a value here and the whole page re-proportions.
126
+ Halve them for a compact UI; raise 4/5/6 for an airy editorial feel. */
127
+ --space-0: 0; /* flush */
128
+ --space-1: 0.5rem; /* tight inner gap */
129
+ --space-2: 0.75rem; /* control padding */
130
+ --space-3: 0.875rem; /* (no t-shirt) */
131
+ --space-4: 1rem; /* default rhythm */
132
+ --space-5: 1.5rem; /* section gap */
133
+ --space-6: 2rem; /* block gap */
134
+ --space-7: 3rem; /* major gap */
135
+ --space-8: 4rem; /* page section */
136
+ --space-9: 6rem; /* hero rhythm */
137
+ --radius-sm: 0;
138
+ --radius-md: 0;
139
+ --radius-lg: 0;
140
+ --radius-xl: 0;
141
+ --radius-full: 0;
142
+ --font-primary: var(--font-mono);
143
+ --font-size-base: 15px;
144
+ --line-height-normal: 1.5;
145
+ --font-weight-medium: 500;
146
+ --z-sticky: 1020;
147
+ --z-dropdown: 1030;
148
+ --z-backdrop: 1040;
149
+ --z-modal: 1050;
150
+ --z-popover: 1060;
151
+ --z-tooltip: 1070;
152
+ }
@@ -0,0 +1,70 @@
1
+ # scripts
2
+
3
+ Small Node utilities that support the css-is-awesome workflow. No runtime deps.
4
+
5
+ ## theme-validator.js
6
+
7
+ Checks a `theme.css` against the token contract **and** runs a WCAG 2.2 AA
8
+ contrast audit on every theme. Every theme MUST declare every required custom
9
+ property so the "swap one file, reskin the site" model stays lossless, and
10
+ every audited contrast pair must meet AA so the system stays accessible by
11
+ default.
12
+
13
+ ### Run
14
+
15
+ ```bash
16
+ # Validate every theme (public/theme.css + public/themes/*/theme.css)
17
+ npm run validate-themes
18
+
19
+ # Validate a specific file
20
+ node scripts/theme-validator.js public/themes/graphite-dark/theme.css
21
+ ```
22
+
23
+ ### Flags
24
+
25
+ | Flag | Effect |
26
+ | --------------------- | ----------------------------------------------------------------------------------------------- |
27
+ | `--all` | Validate every `theme.css` under `public/` (CI mode) |
28
+ | `--no-a11y` | Skip the WCAG 2.2 AA contrast audit; contract check only |
29
+ | `--allow-a11y-fail` | Run the audit and report a11y FAILs, but do not exit non-zero on them (downgrade to soft) |
30
+ | `--strict` | Accepted as a **no-op** for backwards compatibility. A11y FAIL is now the default behaviour |
31
+
32
+ ### Output
33
+
34
+ ```
35
+ ✓ public/theme.css passes (78 tokens declared)
36
+ x public/themes/<name>/theme.css — 2 missing:
37
+ --text-link
38
+ --border-focus
39
+ ```
40
+
41
+ The a11y audit prints a per-theme line with `pass / warn / info / fail`
42
+ counts plus a one-liner per non-passing pair. Pairs flagged `decorative`
43
+ (currently `--border-default`) are reported as `info` with their actual
44
+ contrast ratio but never count as a FAIL — WCAG 2.2 SC 1.4.11 applies only to
45
+ graphical objects essential for understanding content.
46
+
47
+ ### Exit codes
48
+
49
+ | Code | Meaning |
50
+ | ---- | --------------------------------------------------------------------------------------------- |
51
+ | `0` | Every file/block declares every required contract token AND all audited pairs meet WCAG 2.2 AA (or `--allow-a11y-fail` was passed) |
52
+ | `1` | One or more files/blocks missing tokens (always fatal), OR an a11y FAIL (default as of v0.7) |
53
+ | `2` | Usage error (file not found, bad args) |
54
+
55
+ ### Contract
56
+
57
+ The authoritative required-token list lives in `scripts/theme-contract.json`.
58
+ It mirrors the `:root { ... }` block in `public/theme.css` (Sketchbook — the
59
+ reference theme). When the contract changes, update that JSON file, not the
60
+ validator.
61
+
62
+ The audited contrast pairs live in `scripts/theme-a11y.js` (`AUDIT_PAIRS`).
63
+ A pair carrying `decorative: true` is reported as `info` rather than `fail`
64
+ when it dips below its target ratio.
65
+
66
+ ### CI
67
+
68
+ Wired into `.github/workflows/ci.yml` via `npm run validate-themes`. A PR
69
+ that introduces an incomplete theme **or** an AA contrast regression on any
70
+ audited pair fails before merge.
@@ -0,0 +1,67 @@
1
+ {
2
+ "$schema": "./icon-contract.schema (informal)",
3
+ "version": "1",
4
+ "description": "Canonical icon pack contract. Every pack must declare every glyph in its `glyphs` list. The icon-validator (scripts/icon-validator.js) enforces completeness.",
5
+ "packs": {
6
+ "core": {
7
+ "description": "UI essentials. Bundled with css-is-awesome under public/icons/core/. Source: Lucide (ISC + MIT, see LICENSE-third-party).",
8
+ "glyphs": [
9
+ "arrow-right",
10
+ "check",
11
+ "chevron-down",
12
+ "close",
13
+ "download",
14
+ "edit",
15
+ "menu",
16
+ "search",
17
+
18
+ "arrow-left",
19
+ "arrow-up",
20
+ "arrow-down",
21
+ "chevron-up",
22
+ "chevron-left",
23
+ "chevron-right",
24
+ "external-link",
25
+ "home",
26
+
27
+ "upload",
28
+ "copy",
29
+ "share",
30
+ "trash",
31
+ "save",
32
+ "refresh",
33
+ "settings",
34
+ "filter",
35
+ "sort",
36
+ "plus",
37
+ "minus",
38
+ "more-horizontal",
39
+
40
+ "info",
41
+ "warning",
42
+ "error",
43
+ "success",
44
+ "help",
45
+ "loading",
46
+
47
+ "mail",
48
+ "bell",
49
+ "calendar",
50
+ "clock",
51
+ "message",
52
+
53
+ "user",
54
+ "users",
55
+ "lock",
56
+ "unlock",
57
+ "eye",
58
+ "eye-off",
59
+
60
+ "play",
61
+ "pause",
62
+ "star",
63
+ "heart"
64
+ ]
65
+ }
66
+ }
67
+ }