@jaimevalasek/aioson 1.30.1 → 1.33.1

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 (136) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +19 -6
  3. package/docs/design-previews/cognitive-core-ui-auth.html +95 -0
  4. package/docs/design-previews/cognitive-core-ui-kanban.html +231 -0
  5. package/docs/design-previews/cognitive-core-ui-list-detail.html +174 -0
  6. package/docs/design-previews/cognitive-core-ui-preview.css +1315 -0
  7. package/docs/design-previews/cognitive-core-ui-settings.html +142 -0
  8. package/docs/design-previews/cognitive-core-ui-website.html +190 -1009
  9. package/docs/design-previews/cognitive-core-ui.html +281 -463
  10. package/docs/design-previews/index.html +83 -31
  11. package/docs/en/5-reference/cli-reference.md +1 -1
  12. package/docs/pt/5-referencia/comandos-cli.md +1 -1
  13. package/docs/pt/5-referencia/harness-retro.md +2 -1
  14. package/package.json +1 -1
  15. package/src/cli.js +38 -21
  16. package/src/commands/classify.js +389 -327
  17. package/src/commands/harness-retro-promote.js +387 -0
  18. package/src/commands/prototype-check.js +163 -0
  19. package/src/commands/verify-implementation.js +428 -0
  20. package/src/commands/workflow-next.js +222 -9
  21. package/src/constants.js +569 -511
  22. package/src/lib/retro/retro-render.js +10 -1
  23. package/src/lib/retro/retro-sources.js +45 -27
  24. package/src/lib/retro/verification-reports.js +230 -0
  25. package/src/runtime-store.js +13 -9
  26. package/src/verification/evidence-bundle.js +251 -0
  27. package/src/verification/ledger-store.js +221 -0
  28. package/src/verification/path-policy.js +74 -0
  29. package/src/verification/policy-engine.js +95 -0
  30. package/src/verification/prompt-package.js +314 -0
  31. package/src/verification/redaction.js +77 -0
  32. package/src/verification/report-parser.js +132 -0
  33. package/src/verification/report-store.js +97 -0
  34. package/src/verification/result.js +16 -0
  35. package/src/verification/runners/index.js +319 -0
  36. package/src/verification/runtime-telemetry.js +144 -0
  37. package/src/verification/schema.js +276 -0
  38. package/src/verification/source-discovery.js +153 -0
  39. package/template/.aioson/agents/analyst.md +9 -6
  40. package/template/.aioson/agents/briefing-refiner.md +22 -0
  41. package/template/.aioson/agents/briefing.md +69 -12
  42. package/template/.aioson/agents/design-hybrid-forge.md +18 -14
  43. package/template/.aioson/agents/dev.md +23 -10
  44. package/template/.aioson/agents/deyvin.md +3 -2
  45. package/template/.aioson/agents/product.md +15 -11
  46. package/template/.aioson/agents/qa.md +13 -4
  47. package/template/.aioson/agents/scope-check.md +19 -5
  48. package/template/.aioson/agents/sheldon.md +4 -3
  49. package/template/.aioson/agents/ux-ui.md +3 -2
  50. package/template/.aioson/docs/feature-expansion-taxonomy.md +31 -3
  51. package/template/.aioson/docs/play/README.md +2 -0
  52. package/template/.aioson/docs/play/agent-usage-guide.md +7 -1
  53. package/template/.aioson/docs/play/app-compatibility-guide.md +6 -1
  54. package/template/.aioson/docs/play/auth-services-and-testing.md +16 -1
  55. package/template/.aioson/docs/play/manifest-and-runtime.md +23 -0
  56. package/template/.aioson/docs/prototype-contract.md +81 -0
  57. package/template/.aioson/skills/design/aurora-command-ui/SKILL.md +266 -243
  58. package/template/.aioson/skills/design/aurora-command-ui/references/art-direction.md +293 -293
  59. package/template/.aioson/skills/design/aurora-command-ui/references/components.md +827 -827
  60. package/template/.aioson/skills/design/aurora-command-ui/references/dashboards.md +250 -250
  61. package/template/.aioson/skills/design/aurora-command-ui/references/design-tokens.md +585 -585
  62. package/template/.aioson/skills/design/aurora-command-ui/references/motion.md +365 -365
  63. package/template/.aioson/skills/design/aurora-command-ui/references/patterns.md +485 -482
  64. package/template/.aioson/skills/design/aurora-command-ui/references/websites.md +386 -387
  65. package/template/.aioson/skills/design/bold-editorial-ui/SKILL.md +228 -205
  66. package/template/.aioson/skills/design/bold-editorial-ui/references/art-direction.md +338 -338
  67. package/template/.aioson/skills/design/bold-editorial-ui/references/components.md +977 -977
  68. package/template/.aioson/skills/design/bold-editorial-ui/references/dashboards.md +218 -218
  69. package/template/.aioson/skills/design/bold-editorial-ui/references/design-tokens.md +326 -326
  70. package/template/.aioson/skills/design/bold-editorial-ui/references/motion.md +461 -461
  71. package/template/.aioson/skills/design/bold-editorial-ui/references/patterns.md +293 -293
  72. package/template/.aioson/skills/design/bold-editorial-ui/references/websites.md +352 -352
  73. package/template/.aioson/skills/design/clean-saas-ui/SKILL.md +233 -210
  74. package/template/.aioson/skills/design/clean-saas-ui/references/art-direction.md +319 -319
  75. package/template/.aioson/skills/design/clean-saas-ui/references/components.md +365 -365
  76. package/template/.aioson/skills/design/clean-saas-ui/references/dashboards.md +196 -196
  77. package/template/.aioson/skills/design/clean-saas-ui/references/design-tokens.md +244 -244
  78. package/template/.aioson/skills/design/clean-saas-ui/references/motion.md +235 -235
  79. package/template/.aioson/skills/design/clean-saas-ui/references/patterns.md +215 -215
  80. package/template/.aioson/skills/design/clean-saas-ui/references/websites.md +295 -295
  81. package/template/.aioson/skills/design/cognitive-core-ui/SKILL.md +239 -203
  82. package/template/.aioson/skills/design/cognitive-core-ui/references/art-direction.md +339 -339
  83. package/template/.aioson/skills/design/cognitive-core-ui/references/components.md +417 -407
  84. package/template/.aioson/skills/design/cognitive-core-ui/references/dashboards.md +289 -272
  85. package/template/.aioson/skills/design/cognitive-core-ui/references/design-tokens.md +525 -524
  86. package/template/.aioson/skills/design/cognitive-core-ui/references/motion.md +279 -279
  87. package/template/.aioson/skills/design/cognitive-core-ui/references/patterns.md +355 -289
  88. package/template/.aioson/skills/design/cognitive-core-ui/references/websites.md +443 -437
  89. package/template/.aioson/skills/design/glassmorphism-ui/SKILL.md +245 -222
  90. package/template/.aioson/skills/design/glassmorphism-ui/references/art-direction.md +159 -159
  91. package/template/.aioson/skills/design/glassmorphism-ui/references/components.md +498 -498
  92. package/template/.aioson/skills/design/glassmorphism-ui/references/dashboards.md +236 -236
  93. package/template/.aioson/skills/design/glassmorphism-ui/references/design-tokens.md +274 -274
  94. package/template/.aioson/skills/design/glassmorphism-ui/references/motion.md +355 -355
  95. package/template/.aioson/skills/design/glassmorphism-ui/references/patterns.md +198 -198
  96. package/template/.aioson/skills/design/glassmorphism-ui/references/websites.md +307 -307
  97. package/template/.aioson/skills/design/interface-design/SKILL.md +68 -47
  98. package/template/.aioson/skills/design/interface-design/references/components-and-states.md +105 -105
  99. package/template/.aioson/skills/design/interface-design/references/design-directions.md +101 -101
  100. package/template/.aioson/skills/design/interface-design/references/handoff-and-quality.md +92 -71
  101. package/template/.aioson/skills/design/interface-design/references/intent-and-domain.md +74 -74
  102. package/template/.aioson/skills/design/interface-design/references/tokens-and-depth.md +173 -173
  103. package/template/.aioson/skills/design/neo-brutalist-ui/SKILL.md +236 -213
  104. package/template/.aioson/skills/design/neo-brutalist-ui/references/art-direction.md +228 -228
  105. package/template/.aioson/skills/design/neo-brutalist-ui/references/components.md +855 -855
  106. package/template/.aioson/skills/design/neo-brutalist-ui/references/dashboards.md +334 -334
  107. package/template/.aioson/skills/design/neo-brutalist-ui/references/design-tokens.md +342 -342
  108. package/template/.aioson/skills/design/neo-brutalist-ui/references/motion.md +286 -286
  109. package/template/.aioson/skills/design/neo-brutalist-ui/references/patterns.md +458 -458
  110. package/template/.aioson/skills/design/neo-brutalist-ui/references/websites.md +723 -723
  111. package/template/.aioson/skills/design/premium-command-center-ui/SKILL.md +83 -62
  112. package/template/.aioson/skills/design/premium-command-center-ui/references/operations.md +74 -74
  113. package/template/.aioson/skills/design/premium-command-center-ui/references/patterns.md +116 -116
  114. package/template/.aioson/skills/design/premium-command-center-ui/references/validation.md +47 -47
  115. package/template/.aioson/skills/design/premium-command-center-ui/references/visual-system.md +215 -215
  116. package/template/.aioson/skills/design/pt.squarespace.com/.skill-meta.json +31 -31
  117. package/template/.aioson/skills/design/pt.squarespace.com/SKILL.md +94 -66
  118. package/template/.aioson/skills/design/pt.squarespace.com/references/components.md +366 -366
  119. package/template/.aioson/skills/design/pt.squarespace.com/references/design-tokens.md +150 -150
  120. package/template/.aioson/skills/design/pt.squarespace.com/references/motion.md +270 -270
  121. package/template/.aioson/skills/design/pt.squarespace.com/references/patterns.md +189 -189
  122. package/template/.aioson/skills/design/pt.squarespace.com/references/websites.md +161 -161
  123. package/template/.aioson/skills/design/warm-craft-ui/SKILL.md +232 -209
  124. package/template/.aioson/skills/design/warm-craft-ui/references/art-direction.md +324 -324
  125. package/template/.aioson/skills/design/warm-craft-ui/references/components.md +508 -508
  126. package/template/.aioson/skills/design/warm-craft-ui/references/dashboards.md +223 -223
  127. package/template/.aioson/skills/design/warm-craft-ui/references/design-tokens.md +374 -374
  128. package/template/.aioson/skills/design/warm-craft-ui/references/motion.md +356 -356
  129. package/template/.aioson/skills/design/warm-craft-ui/references/patterns.md +288 -288
  130. package/template/.aioson/skills/design/warm-craft-ui/references/websites.md +289 -289
  131. package/template/.aioson/skills/process/briefing-expansion-scout/SKILL.md +25 -3
  132. package/template/.aioson/skills/process/design-hybrid-forge/SKILL.md +5 -3
  133. package/template/.aioson/skills/process/design-hybrid-forge/references/external-source-ingestion.md +89 -0
  134. package/template/.aioson/skills/process/product-scope-expansion/SKILL.md +29 -2
  135. package/template/.aioson/skills/process/prototype-forge/SKILL.md +92 -0
  136. package/template/.aioson/skills/process/sheldon-expansion-audit/SKILL.md +23 -2
@@ -1,855 +1,855 @@
1
- # Components — Neo-Brutalist UI
2
-
3
- All components follow three universal rules:
4
- 1. **Border on everything**: every interactive or container element has a visible border. No borderless components.
5
- 2. **Hard shadow direction**: all shadows go bottom-right (positive x, positive y). Consistent across all components.
6
- 3. **Push mechanic**: every clickable element with a hard shadow implements the push on `:active` (shadow disappears + `translate` equal to shadow offset).
7
-
8
- ---
9
-
10
- ## 1. Brutalist Card
11
-
12
- The foundational container. Everything derives from this.
13
-
14
- ```css
15
- .card {
16
- background: var(--bg-surface);
17
- border: var(--border-thicker);
18
- box-shadow: var(--shadow-md);
19
- border-radius: var(--radius-none);
20
- padding: var(--space-6);
21
- }
22
-
23
- .card:hover {
24
- box-shadow: var(--shadow-lg);
25
- transition: box-shadow 80ms ease;
26
- }
27
-
28
- /* Interactive card variant */
29
- .card--interactive:active {
30
- box-shadow: none;
31
- transform: translate(4px, 4px);
32
- transition: box-shadow 60ms linear, transform 60ms linear;
33
- }
34
- ```
35
-
36
- ---
37
-
38
- ## 2. Stat Card
39
-
40
- Brutalist Card + big mono number.
41
-
42
- ```css
43
- .stat-card {
44
- /* extends .card */
45
- padding: var(--space-5) var(--space-6);
46
- }
47
-
48
- .stat-card__number {
49
- font-family: var(--font-mono);
50
- font-size: var(--text-3xl);
51
- font-weight: var(--weight-bold);
52
- color: var(--text-heading);
53
- letter-spacing: var(--tracking-tight);
54
- }
55
-
56
- .stat-card__label {
57
- font-family: var(--font-mono);
58
- font-size: var(--text-xs);
59
- font-weight: var(--weight-medium);
60
- text-transform: uppercase;
61
- letter-spacing: var(--tracking-wider);
62
- color: var(--text-secondary);
63
- }
64
-
65
- /* Trend badge: green bg for positive, red for negative */
66
- .stat-card__trend {
67
- display: inline-block;
68
- background: var(--semantic-green-dim);
69
- color: var(--semantic-green);
70
- border: var(--border-subtle);
71
- border-radius: var(--radius-none);
72
- padding: 2px var(--space-2);
73
- font-family: var(--font-mono);
74
- font-size: var(--text-xs);
75
- }
76
- ```
77
-
78
- ---
79
-
80
- ## 3. Feature Card
81
-
82
- Brutalist Card with icon area.
83
-
84
- ```css
85
- .feature-card__icon-area {
86
- width: 48px;
87
- height: 48px;
88
- background: var(--accent);
89
- border: var(--border-thick);
90
- border-radius: var(--radius-none);
91
- display: flex;
92
- align-items: center;
93
- justify-content: center;
94
- margin-bottom: var(--space-4);
95
- }
96
-
97
- .feature-card__title {
98
- font-family: var(--font-display);
99
- font-size: var(--text-lg);
100
- font-weight: var(--weight-bold);
101
- color: var(--text-heading);
102
- margin-bottom: var(--space-2);
103
- }
104
-
105
- .feature-card__description {
106
- font-family: var(--font-body);
107
- font-size: var(--text-sm);
108
- color: var(--text-secondary);
109
- line-height: 1.6;
110
- }
111
- ```
112
-
113
- ---
114
-
115
- ## 4. Button — Primary
116
-
117
- The most important component. Must feel physical.
118
-
119
- ```css
120
- .btn-primary {
121
- background: var(--accent);
122
- color: var(--accent-contrast);
123
- border: var(--border-thicker);
124
- box-shadow: var(--shadow-md);
125
- border-radius: var(--radius-none);
126
- height: var(--control-md);
127
- padding: 0 var(--space-6);
128
- font-family: var(--font-display);
129
- font-size: var(--text-sm);
130
- font-weight: var(--weight-bold);
131
- text-transform: uppercase;
132
- letter-spacing: var(--tracking-wide);
133
- cursor: pointer;
134
- transition: box-shadow var(--transition-fast);
135
- }
136
-
137
- .btn-primary:hover {
138
- box-shadow: var(--shadow-lg);
139
- }
140
-
141
- .btn-primary:active {
142
- box-shadow: none;
143
- transform: translate(4px, 4px);
144
- transition: box-shadow var(--transition-push), transform var(--transition-push);
145
- }
146
-
147
- .btn-primary:focus-visible {
148
- outline: 2px solid var(--accent);
149
- outline-offset: 2px;
150
- }
151
-
152
- /* Large CTA variant */
153
- .btn-primary--lg {
154
- height: var(--control-lg);
155
- padding: 0 var(--space-8);
156
- font-size: var(--text-base);
157
- box-shadow: var(--shadow-lg);
158
- }
159
-
160
- .btn-primary--lg:hover { box-shadow: var(--shadow-xl); }
161
- .btn-primary--lg:active { transform: translate(6px, 6px); }
162
- ```
163
-
164
- ---
165
-
166
- ## 5. Button — Secondary
167
-
168
- ```css
169
- .btn-secondary {
170
- background: transparent;
171
- color: var(--text-heading);
172
- border: var(--border-thicker);
173
- box-shadow: var(--shadow-sm);
174
- border-radius: var(--radius-none);
175
- height: var(--control-md);
176
- padding: 0 var(--space-6);
177
- font-family: var(--font-display);
178
- font-size: var(--text-sm);
179
- font-weight: var(--weight-bold);
180
- text-transform: uppercase;
181
- letter-spacing: var(--tracking-wide);
182
- cursor: pointer;
183
- transition: box-shadow var(--transition-fast), background var(--transition-fast);
184
- }
185
-
186
- .btn-secondary:hover {
187
- background: var(--bg-elevated);
188
- box-shadow: var(--shadow-md);
189
- }
190
-
191
- .btn-secondary:active {
192
- box-shadow: none;
193
- transform: translate(2px, 2px);
194
- transition: box-shadow var(--transition-push), transform var(--transition-push);
195
- }
196
- ```
197
-
198
- ---
199
-
200
- ## 6. Button — Pill
201
-
202
- Playful contrast to the square default.
203
-
204
- ```css
205
- .btn-pill {
206
- background: var(--accent);
207
- color: var(--accent-contrast);
208
- border: var(--border-thick);
209
- box-shadow: var(--shadow-sm);
210
- border-radius: var(--radius-full);
211
- height: var(--control-sm);
212
- padding: 0 var(--space-5);
213
- font-family: var(--font-display);
214
- font-size: var(--text-sm);
215
- font-weight: var(--weight-bold);
216
- cursor: pointer;
217
- }
218
-
219
- .btn-pill:hover { box-shadow: var(--shadow-md); }
220
- .btn-pill:active { box-shadow: none; transform: translate(2px, 2px); }
221
- ```
222
-
223
- ---
224
-
225
- ## 7. Input
226
-
227
- ```css
228
- .input {
229
- background: var(--bg-surface);
230
- color: var(--text-primary);
231
- border: var(--border-thick);
232
- border-radius: var(--radius-none);
233
- height: var(--control-md);
234
- padding: 0 var(--space-4);
235
- font-family: var(--font-body);
236
- font-size: var(--text-sm);
237
- width: 100%;
238
- transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
239
- }
240
-
241
- .input::placeholder {
242
- font-family: var(--font-mono);
243
- color: var(--text-muted);
244
- }
245
-
246
- .input:focus {
247
- outline: none;
248
- border-color: var(--accent);
249
- box-shadow: var(--shadow-accent);
250
- }
251
-
252
- .input:disabled {
253
- background: var(--bg-elevated);
254
- color: var(--text-disabled);
255
- cursor: not-allowed;
256
- }
257
- ```
258
-
259
- ---
260
-
261
- ## 8. Textarea
262
-
263
- ```css
264
- .textarea {
265
- /* extends .input */
266
- height: auto;
267
- min-height: 120px;
268
- padding: var(--space-3) var(--space-4);
269
- resize: vertical;
270
- line-height: 1.6;
271
- }
272
- ```
273
-
274
- ---
275
-
276
- ## 9. Select
277
-
278
- ```css
279
- .select {
280
- /* extends .input */
281
- appearance: none;
282
- background-image: url("data:image/svg+xml,%3Csvg width='12' height='8' viewBox='0 0 12 8' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1L6 7L11 1' stroke='%231A1A1A' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E");
283
- background-repeat: no-repeat;
284
- background-position: right var(--space-4) center;
285
- padding-right: var(--space-10);
286
- cursor: pointer;
287
- }
288
-
289
- /* Dropdown */
290
- .select-dropdown {
291
- background: var(--bg-surface);
292
- border: var(--border-thicker);
293
- box-shadow: var(--shadow-lg);
294
- border-radius: var(--radius-none);
295
- padding: var(--space-2) 0;
296
- }
297
-
298
- .select-option {
299
- padding: var(--space-2) var(--space-4);
300
- font-family: var(--font-body);
301
- font-size: var(--text-sm);
302
- cursor: pointer;
303
- }
304
-
305
- .select-option:hover {
306
- background: var(--bg-elevated);
307
- }
308
-
309
- .select-option--active {
310
- background: var(--accent);
311
- color: var(--accent-contrast);
312
- font-weight: var(--weight-bold);
313
- }
314
- ```
315
-
316
- ---
317
-
318
- ## 10. Checkbox
319
-
320
- ```css
321
- .checkbox {
322
- width: 20px;
323
- height: 20px;
324
- border: var(--border-thick);
325
- border-radius: var(--radius-none);
326
- background: var(--bg-surface);
327
- appearance: none;
328
- cursor: pointer;
329
- position: relative;
330
- flex-shrink: 0;
331
- }
332
-
333
- .checkbox:checked {
334
- background: var(--accent);
335
- }
336
-
337
- /* Bold checkmark — 2px stroke minimum */
338
- .checkbox:checked::after {
339
- content: '';
340
- position: absolute;
341
- left: 4px;
342
- top: 1px;
343
- width: 8px;
344
- height: 12px;
345
- border-right: 2.5px solid var(--accent-contrast);
346
- border-bottom: 2.5px solid var(--accent-contrast);
347
- transform: rotate(45deg);
348
- }
349
-
350
- .checkbox:focus-visible {
351
- outline: 2px solid var(--accent);
352
- outline-offset: 2px;
353
- }
354
- ```
355
-
356
- ---
357
-
358
- ## 11. Toggle
359
-
360
- Brutalist variant: square, not round.
361
-
362
- ```css
363
- .toggle {
364
- width: 48px;
365
- height: 24px;
366
- border: var(--border-thick);
367
- border-radius: var(--radius-none); /* SQUARE — brutalist signature */
368
- background: var(--bg-elevated);
369
- cursor: pointer;
370
- position: relative;
371
- transition: background var(--transition-base);
372
- }
373
-
374
- .toggle:checked {
375
- background: var(--accent);
376
- }
377
-
378
- .toggle-thumb {
379
- width: 16px;
380
- height: 16px;
381
- background: var(--bg-surface);
382
- border: var(--border-thick);
383
- border-radius: var(--radius-none); /* SQUARE thumb */
384
- position: absolute;
385
- top: 2px;
386
- left: 2px;
387
- transition: transform var(--transition-base);
388
- }
389
-
390
- .toggle:checked .toggle-thumb {
391
- transform: translateX(24px);
392
- }
393
- ```
394
-
395
- ---
396
-
397
- ## 12. Badge
398
-
399
- ```css
400
- .badge {
401
- display: inline-flex;
402
- align-items: center;
403
- height: 22px;
404
- padding: 0 var(--space-3);
405
- border: var(--border-thick);
406
- border-radius: var(--radius-full); /* PILL — contrast with card radius 0 */
407
- font-family: var(--font-mono);
408
- font-size: var(--text-xs);
409
- font-weight: var(--weight-medium);
410
- text-transform: uppercase;
411
- letter-spacing: var(--tracking-wide);
412
- white-space: nowrap;
413
- }
414
-
415
- .badge--accent { background: var(--accent); color: var(--accent-contrast); }
416
- .badge--green { background: var(--semantic-green-dim); color: var(--semantic-green); }
417
- .badge--amber { background: var(--semantic-amber-dim); color: var(--semantic-amber); }
418
- .badge--red { background: var(--semantic-red-dim); color: var(--semantic-red); }
419
- .badge--blue { background: var(--semantic-blue-dim); color: var(--semantic-blue); }
420
- .badge--neutral { background: var(--bg-elevated); color: var(--text-secondary); }
421
- ```
422
-
423
- ---
424
-
425
- ## 13. Tag / Chip (dismissible)
426
-
427
- ```css
428
- .tag {
429
- /* extends .badge */
430
- border-radius: var(--radius-full);
431
- gap: var(--space-2);
432
- }
433
-
434
- .tag__close {
435
- width: 16px;
436
- height: 16px;
437
- background: none;
438
- border: none;
439
- cursor: pointer;
440
- font-size: 12px;
441
- font-weight: var(--weight-bold);
442
- color: currentColor;
443
- display: flex;
444
- align-items: center;
445
- justify-content: center;
446
- padding: 0;
447
- }
448
- ```
449
-
450
- ---
451
-
452
- ## 14. Table
453
-
454
- Full-grid borders — the brutalist data table signature.
455
-
456
- ```css
457
- .table {
458
- width: 100%;
459
- border-collapse: collapse;
460
- border: var(--border-thick);
461
- font-size: var(--text-sm);
462
- }
463
-
464
- .table th,
465
- .table td {
466
- border: var(--border-subtle); /* ALL cells bordered */
467
- padding: var(--space-3) var(--space-4);
468
- text-align: left;
469
- }
470
-
471
- .table thead {
472
- background: var(--bg-elevated);
473
- }
474
-
475
- .table th {
476
- font-family: var(--font-mono);
477
- font-size: var(--text-xs);
478
- font-weight: var(--weight-medium);
479
- text-transform: uppercase;
480
- letter-spacing: var(--tracking-wider);
481
- color: var(--text-secondary);
482
- }
483
-
484
- /* Data cells: mono for numbers, dates, IDs */
485
- .table td[data-type="number"],
486
- .table td[data-type="date"],
487
- .table td[data-type="id"],
488
- .table td[data-type="status"] {
489
- font-family: var(--font-mono);
490
- }
491
-
492
- .table tbody tr:hover {
493
- background: var(--bg-elevated);
494
- transition: background 60ms ease;
495
- }
496
-
497
- /* Sort arrow */
498
- .table th[aria-sort] {
499
- cursor: pointer;
500
- }
501
-
502
- .table th[aria-sort]::after {
503
- content: ' ↕';
504
- font-size: 10px;
505
- color: var(--text-muted);
506
- }
507
-
508
- .table th[aria-sort="ascending"]::after { content: ' ↑'; color: var(--text-heading); }
509
- .table th[aria-sort="descending"]::after { content: ' ↓'; color: var(--text-heading); }
510
- ```
511
-
512
- Tables never stack into card lists on mobile — they scroll horizontally:
513
- ```css
514
- .table-container {
515
- overflow-x: auto;
516
- -webkit-overflow-scrolling: touch;
517
- }
518
- ```
519
-
520
- ---
521
-
522
- ## 15. Modal
523
-
524
- ```css
525
- .modal-backdrop {
526
- position: fixed;
527
- inset: 0;
528
- background: color-mix(in srgb, var(--bg-void) 70%, transparent);
529
- /* NO backdrop-filter blur — brutalist has zero blur */
530
- z-index: var(--z-overlay);
531
- }
532
-
533
- .modal {
534
- background: var(--bg-surface);
535
- border: var(--border-thicker);
536
- box-shadow: var(--shadow-xl);
537
- border-radius: var(--radius-none);
538
- padding: var(--space-8);
539
- max-width: 540px;
540
- width: 90%;
541
- position: relative;
542
- z-index: var(--z-modal);
543
- }
544
-
545
- .modal__header {
546
- border-bottom: var(--border-thick);
547
- padding-bottom: var(--space-4);
548
- margin-bottom: var(--space-6);
549
- display: flex;
550
- justify-content: space-between;
551
- align-items: center;
552
- }
553
-
554
- .modal__title {
555
- font-family: var(--font-display);
556
- font-size: var(--text-lg);
557
- font-weight: var(--weight-bold);
558
- color: var(--text-heading);
559
- }
560
-
561
- .modal__close {
562
- width: 32px;
563
- height: 32px;
564
- border: var(--border-thick);
565
- background: none;
566
- cursor: pointer;
567
- font-size: 18px;
568
- font-weight: var(--weight-bold);
569
- display: flex;
570
- align-items: center;
571
- justify-content: center;
572
- }
573
-
574
- .modal__close:hover { background: var(--bg-elevated); }
575
- .modal__close:active { transform: translate(2px, 2px); box-shadow: none; }
576
- ```
577
-
578
- ---
579
-
580
- ## 16. Toast
581
-
582
- ```css
583
- .toast {
584
- background: var(--bg-surface);
585
- border: var(--border-thicker);
586
- box-shadow: var(--shadow-md);
587
- border-radius: var(--radius-none);
588
- padding: var(--space-4) var(--space-5);
589
- padding-left: calc(var(--space-5) + 4px); /* room for accent bar */
590
- min-width: 280px;
591
- max-width: 420px;
592
- position: relative;
593
- overflow: hidden;
594
- }
595
-
596
- /* Left accent bar — 4px color indicator */
597
- .toast::before {
598
- content: '';
599
- position: absolute;
600
- left: 0;
601
- top: 0;
602
- bottom: 0;
603
- width: 4px;
604
- }
605
-
606
- .toast--success::before { background: var(--semantic-green); }
607
- .toast--error::before { background: var(--semantic-red); }
608
- .toast--warning::before { background: var(--semantic-amber); }
609
- .toast--info::before { background: var(--semantic-blue); }
610
-
611
- .toast__message {
612
- font-family: var(--font-mono);
613
- font-size: var(--text-sm);
614
- color: var(--text-primary);
615
- }
616
-
617
- /* Position: top-right so shadow is visible */
618
- .toast-container {
619
- position: fixed;
620
- top: var(--space-6);
621
- right: var(--space-6);
622
- z-index: var(--z-toast);
623
- display: flex;
624
- flex-direction: column;
625
- gap: var(--space-3);
626
- }
627
- ```
628
-
629
- ---
630
-
631
- ## 17. Tooltip
632
-
633
- ```css
634
- .tooltip {
635
- background: var(--text-heading); /* near-black in light, near-white in dark */
636
- color: var(--bg-base);
637
- border: var(--border-thick);
638
- border-color: var(--text-heading);
639
- border-radius: var(--radius-none);
640
- padding: var(--space-1) var(--space-3);
641
- font-family: var(--font-mono);
642
- font-size: var(--text-xs);
643
- white-space: nowrap;
644
- pointer-events: none;
645
- }
646
- ```
647
-
648
- ---
649
-
650
- ## 18. Progress Bar
651
-
652
- Thick — more substantial than other skills.
653
-
654
- ```css
655
- .progress {
656
- height: 12px; /* thicker than standard */
657
- border: var(--border-thick);
658
- border-radius: var(--radius-none);
659
- background: var(--bg-elevated);
660
- overflow: hidden;
661
- }
662
-
663
- .progress__fill {
664
- height: 100%;
665
- background: var(--accent);
666
- border-radius: var(--radius-none);
667
- transition: width var(--transition-slow);
668
- }
669
-
670
- .progress--success .progress__fill { background: var(--semantic-green); }
671
- .progress--danger .progress__fill { background: var(--semantic-red); }
672
- ```
673
-
674
- ---
675
-
676
- ## 19. Avatar
677
-
678
- ```css
679
- .avatar {
680
- border: var(--border-thicker);
681
- border-radius: var(--radius-none); /* SQUARE — brutalist default */
682
- overflow: hidden;
683
- flex-shrink: 0;
684
- background: var(--bg-elevated);
685
- }
686
-
687
- .avatar--circle { border-radius: var(--radius-full); } /* Round variant */
688
-
689
- .avatar--sm { width: 32px; height: 32px; }
690
- .avatar--md { width: 40px; height: 40px; }
691
- .avatar--lg { width: 56px; height: 56px; }
692
- ```
693
-
694
- ---
695
-
696
- ## 20. Divider
697
-
698
- ```css
699
- .divider {
700
- border: none;
701
- border-top: var(--border-thick);
702
- width: 100%;
703
- margin: var(--space-4) 0;
704
- }
705
-
706
- .divider--dashed {
707
- border-top-style: dashed;
708
- }
709
-
710
- .divider--double {
711
- border-top: var(--border-subtle);
712
- box-shadow: 0 3px 0 var(--border-color); /* visual double — border + shadow line */
713
- }
714
- ```
715
-
716
- ---
717
-
718
- ## 21. Marquee
719
-
720
- For announcement bars and promotional strips.
721
-
722
- ```css
723
- .marquee {
724
- height: 40px;
725
- background: var(--accent);
726
- border-top: var(--border-thick);
727
- border-bottom: var(--border-thick);
728
- overflow: hidden;
729
- display: flex;
730
- align-items: center;
731
- }
732
-
733
- .marquee__track {
734
- display: flex;
735
- gap: var(--space-16);
736
- animation: marquee 20s linear infinite;
737
- white-space: nowrap;
738
- }
739
-
740
- .marquee__text {
741
- font-family: var(--font-mono);
742
- font-size: var(--text-sm);
743
- font-weight: var(--weight-bold);
744
- color: var(--accent-contrast);
745
- text-transform: uppercase;
746
- letter-spacing: var(--tracking-wide);
747
- }
748
-
749
- @keyframes marquee {
750
- from { transform: translateX(0); }
751
- to { transform: translateX(-50%); }
752
- }
753
-
754
- @media (prefers-reduced-motion: reduce) {
755
- .marquee__track { animation: none; }
756
- }
757
- ```
758
-
759
- ---
760
-
761
- ## 22. Code Block
762
-
763
- ```css
764
- .code-block {
765
- background: var(--bg-elevated);
766
- border: var(--border-thicker);
767
- border-radius: var(--radius-none);
768
- overflow: hidden;
769
- }
770
-
771
- /* Colored tab header with filename */
772
- .code-block__header {
773
- background: var(--accent);
774
- color: var(--accent-contrast);
775
- border-bottom: var(--border-thick);
776
- padding: var(--space-2) var(--space-4);
777
- font-family: var(--font-mono);
778
- font-size: var(--text-xs);
779
- font-weight: var(--weight-bold);
780
- display: flex;
781
- justify-content: space-between;
782
- align-items: center;
783
- }
784
-
785
- .code-block__copy {
786
- background: none;
787
- border: var(--border-thick);
788
- color: var(--accent-contrast);
789
- font-family: var(--font-mono);
790
- font-size: var(--text-xs);
791
- padding: 2px var(--space-2);
792
- cursor: pointer;
793
- border-radius: var(--radius-none);
794
- }
795
-
796
- .code-block__body {
797
- padding: var(--space-5);
798
- overflow-x: auto;
799
- }
800
-
801
- .code-block pre, .code-block code {
802
- font-family: var(--font-mono);
803
- font-size: var(--text-sm);
804
- color: var(--text-primary);
805
- line-height: 1.7;
806
- }
807
- ```
808
-
809
- ---
810
-
811
- ## 23. Sticker Badge
812
-
813
- The signature decorative element of this skill.
814
-
815
- ```css
816
- .sticker {
817
- display: inline-block;
818
- background: var(--accent);
819
- color: var(--accent-contrast);
820
- border: var(--border-thick);
821
- box-shadow: var(--shadow-sm);
822
- border-radius: var(--radius-none);
823
- padding: var(--space-1) var(--space-3);
824
- font-family: var(--font-mono);
825
- font-size: var(--text-xs);
826
- font-weight: var(--weight-bold);
827
- text-transform: uppercase;
828
- letter-spacing: var(--tracking-wide);
829
- transform: rotate(-2deg); /* subtle tilt — sticker energy */
830
- transform-origin: center;
831
- }
832
-
833
- /* Variants */
834
- .sticker--new { background: var(--accent-green); transform: rotate(-1deg); }
835
- .sticker--hot { background: var(--accent-red); color: white; transform: rotate(2deg); }
836
- .sticker--beta { background: var(--accent-blue); color: white; transform: rotate(-2deg); }
837
- .sticker--accent { background: var(--accent); transform: rotate(1.5deg); }
838
-
839
- /* No animation — stickers are static by default */
840
- ```
841
-
842
- ---
843
-
844
- ## Component Rules Summary
845
-
846
- | Rule | Detail |
847
- |------|--------|
848
- | Border on everything | Every interactive or container element must have a visible border. Min 2px solid. |
849
- | Shadow direction | All hard shadows point bottom-right. Never top-left, never scattered. |
850
- | Push mechanic | Every element with `box-shadow` implements shadow-remove + translate on `:active`. |
851
- | Mono for data | Numbers, dates, IDs, status text, labels, metadata → `font-family: var(--font-mono)`. |
852
- | Square toggle | Toggle uses `border-radius: 0`. This is the brutalist signature, not a mistake. |
853
- | Max 2 accents per page | Indie/devtool/zine modes: max 2 accent colors. Creative Playground: up to 4. |
854
- | No blur anywhere | No `box-shadow` with blur-radius > 0. No `backdrop-filter: blur()`. Zero blur everywhere. |
855
- | No radius in between | Components are `--radius-none` (0) or `--radius-full` (pills). Never 4–16px unless explicitly specified in a token. |
1
+ # Components — Neo-Brutalist UI
2
+
3
+ All components follow three universal rules:
4
+ 1. **Border on everything**: every interactive or container element has a visible border. No borderless components.
5
+ 2. **Hard shadow direction**: all shadows go bottom-right (positive x, positive y). Consistent across all components.
6
+ 3. **Push mechanic**: every clickable element with a hard shadow implements the push on `:active` (shadow disappears + `translate` equal to shadow offset).
7
+
8
+ ---
9
+
10
+ ## 1. Brutalist Card
11
+
12
+ The foundational container. Everything derives from this.
13
+
14
+ ```css
15
+ .card {
16
+ background: var(--bg-surface);
17
+ border: var(--border-thicker);
18
+ box-shadow: var(--shadow-md);
19
+ border-radius: var(--radius-none);
20
+ padding: var(--space-6);
21
+ }
22
+
23
+ .card:hover {
24
+ box-shadow: var(--shadow-lg);
25
+ transition: box-shadow 80ms ease;
26
+ }
27
+
28
+ /* Interactive card variant */
29
+ .card--interactive:active {
30
+ box-shadow: none;
31
+ transform: translate(4px, 4px);
32
+ transition: box-shadow 60ms linear, transform 60ms linear;
33
+ }
34
+ ```
35
+
36
+ ---
37
+
38
+ ## 2. Stat Card
39
+
40
+ Brutalist Card + big mono number.
41
+
42
+ ```css
43
+ .stat-card {
44
+ /* extends .card */
45
+ padding: var(--space-5) var(--space-6);
46
+ }
47
+
48
+ .stat-card__number {
49
+ font-family: var(--font-mono);
50
+ font-size: var(--text-3xl);
51
+ font-weight: var(--weight-bold);
52
+ color: var(--text-heading);
53
+ letter-spacing: var(--tracking-tight);
54
+ }
55
+
56
+ .stat-card__label {
57
+ font-family: var(--font-mono);
58
+ font-size: var(--text-xs);
59
+ font-weight: var(--weight-medium);
60
+ text-transform: uppercase;
61
+ letter-spacing: var(--tracking-wider);
62
+ color: var(--text-secondary);
63
+ }
64
+
65
+ /* Trend badge: green bg for positive, red for negative */
66
+ .stat-card__trend {
67
+ display: inline-block;
68
+ background: var(--semantic-green-dim);
69
+ color: var(--semantic-green);
70
+ border: var(--border-subtle);
71
+ border-radius: var(--radius-none);
72
+ padding: 2px var(--space-2);
73
+ font-family: var(--font-mono);
74
+ font-size: var(--text-xs);
75
+ }
76
+ ```
77
+
78
+ ---
79
+
80
+ ## 3. Feature Card
81
+
82
+ Brutalist Card with icon area.
83
+
84
+ ```css
85
+ .feature-card__icon-area {
86
+ width: 48px;
87
+ height: 48px;
88
+ background: var(--accent);
89
+ border: var(--border-thick);
90
+ border-radius: var(--radius-none);
91
+ display: flex;
92
+ align-items: center;
93
+ justify-content: center;
94
+ margin-bottom: var(--space-4);
95
+ }
96
+
97
+ .feature-card__title {
98
+ font-family: var(--font-display);
99
+ font-size: var(--text-lg);
100
+ font-weight: var(--weight-bold);
101
+ color: var(--text-heading);
102
+ margin-bottom: var(--space-2);
103
+ }
104
+
105
+ .feature-card__description {
106
+ font-family: var(--font-body);
107
+ font-size: var(--text-sm);
108
+ color: var(--text-secondary);
109
+ line-height: 1.6;
110
+ }
111
+ ```
112
+
113
+ ---
114
+
115
+ ## 4. Button — Primary
116
+
117
+ The most important component. Must feel physical.
118
+
119
+ ```css
120
+ .btn-primary {
121
+ background: var(--accent);
122
+ color: var(--accent-contrast);
123
+ border: var(--border-thicker);
124
+ box-shadow: var(--shadow-md);
125
+ border-radius: var(--radius-none);
126
+ height: var(--control-md);
127
+ padding: 0 var(--space-6);
128
+ font-family: var(--font-display);
129
+ font-size: var(--text-sm);
130
+ font-weight: var(--weight-bold);
131
+ text-transform: uppercase;
132
+ letter-spacing: var(--tracking-wide);
133
+ cursor: pointer;
134
+ transition: box-shadow var(--transition-fast);
135
+ }
136
+
137
+ .btn-primary:hover {
138
+ box-shadow: var(--shadow-lg);
139
+ }
140
+
141
+ .btn-primary:active {
142
+ box-shadow: none;
143
+ transform: translate(4px, 4px);
144
+ transition: box-shadow var(--transition-push), transform var(--transition-push);
145
+ }
146
+
147
+ .btn-primary:focus-visible {
148
+ outline: 2px solid var(--accent);
149
+ outline-offset: 2px;
150
+ }
151
+
152
+ /* Large CTA variant */
153
+ .btn-primary--lg {
154
+ height: var(--control-lg);
155
+ padding: 0 var(--space-8);
156
+ font-size: var(--text-base);
157
+ box-shadow: var(--shadow-lg);
158
+ }
159
+
160
+ .btn-primary--lg:hover { box-shadow: var(--shadow-xl); }
161
+ .btn-primary--lg:active { transform: translate(6px, 6px); }
162
+ ```
163
+
164
+ ---
165
+
166
+ ## 5. Button — Secondary
167
+
168
+ ```css
169
+ .btn-secondary {
170
+ background: transparent;
171
+ color: var(--text-heading);
172
+ border: var(--border-thicker);
173
+ box-shadow: var(--shadow-sm);
174
+ border-radius: var(--radius-none);
175
+ height: var(--control-md);
176
+ padding: 0 var(--space-6);
177
+ font-family: var(--font-display);
178
+ font-size: var(--text-sm);
179
+ font-weight: var(--weight-bold);
180
+ text-transform: uppercase;
181
+ letter-spacing: var(--tracking-wide);
182
+ cursor: pointer;
183
+ transition: box-shadow var(--transition-fast), background var(--transition-fast);
184
+ }
185
+
186
+ .btn-secondary:hover {
187
+ background: var(--bg-elevated);
188
+ box-shadow: var(--shadow-md);
189
+ }
190
+
191
+ .btn-secondary:active {
192
+ box-shadow: none;
193
+ transform: translate(2px, 2px);
194
+ transition: box-shadow var(--transition-push), transform var(--transition-push);
195
+ }
196
+ ```
197
+
198
+ ---
199
+
200
+ ## 6. Button — Pill
201
+
202
+ Playful contrast to the square default.
203
+
204
+ ```css
205
+ .btn-pill {
206
+ background: var(--accent);
207
+ color: var(--accent-contrast);
208
+ border: var(--border-thick);
209
+ box-shadow: var(--shadow-sm);
210
+ border-radius: var(--radius-full);
211
+ height: var(--control-sm);
212
+ padding: 0 var(--space-5);
213
+ font-family: var(--font-display);
214
+ font-size: var(--text-sm);
215
+ font-weight: var(--weight-bold);
216
+ cursor: pointer;
217
+ }
218
+
219
+ .btn-pill:hover { box-shadow: var(--shadow-md); }
220
+ .btn-pill:active { box-shadow: none; transform: translate(2px, 2px); }
221
+ ```
222
+
223
+ ---
224
+
225
+ ## 7. Input
226
+
227
+ ```css
228
+ .input {
229
+ background: var(--bg-surface);
230
+ color: var(--text-primary);
231
+ border: var(--border-thick);
232
+ border-radius: var(--radius-none);
233
+ height: var(--control-md);
234
+ padding: 0 var(--space-4);
235
+ font-family: var(--font-body);
236
+ font-size: var(--text-sm);
237
+ width: 100%;
238
+ transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
239
+ }
240
+
241
+ .input::placeholder {
242
+ font-family: var(--font-mono);
243
+ color: var(--text-muted);
244
+ }
245
+
246
+ .input:focus {
247
+ outline: none;
248
+ border-color: var(--accent);
249
+ box-shadow: var(--shadow-accent);
250
+ }
251
+
252
+ .input:disabled {
253
+ background: var(--bg-elevated);
254
+ color: var(--text-disabled);
255
+ cursor: not-allowed;
256
+ }
257
+ ```
258
+
259
+ ---
260
+
261
+ ## 8. Textarea
262
+
263
+ ```css
264
+ .textarea {
265
+ /* extends .input */
266
+ height: auto;
267
+ min-height: 120px;
268
+ padding: var(--space-3) var(--space-4);
269
+ resize: vertical;
270
+ line-height: 1.6;
271
+ }
272
+ ```
273
+
274
+ ---
275
+
276
+ ## 9. Select
277
+
278
+ ```css
279
+ .select {
280
+ /* extends .input */
281
+ appearance: none;
282
+ background-image: url("data:image/svg+xml,%3Csvg width='12' height='8' viewBox='0 0 12 8' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1L6 7L11 1' stroke='%231A1A1A' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E");
283
+ background-repeat: no-repeat;
284
+ background-position: right var(--space-4) center;
285
+ padding-right: var(--space-10);
286
+ cursor: pointer;
287
+ }
288
+
289
+ /* Dropdown */
290
+ .select-dropdown {
291
+ background: var(--bg-surface);
292
+ border: var(--border-thicker);
293
+ box-shadow: var(--shadow-lg);
294
+ border-radius: var(--radius-none);
295
+ padding: var(--space-2) 0;
296
+ }
297
+
298
+ .select-option {
299
+ padding: var(--space-2) var(--space-4);
300
+ font-family: var(--font-body);
301
+ font-size: var(--text-sm);
302
+ cursor: pointer;
303
+ }
304
+
305
+ .select-option:hover {
306
+ background: var(--bg-elevated);
307
+ }
308
+
309
+ .select-option--active {
310
+ background: var(--accent);
311
+ color: var(--accent-contrast);
312
+ font-weight: var(--weight-bold);
313
+ }
314
+ ```
315
+
316
+ ---
317
+
318
+ ## 10. Checkbox
319
+
320
+ ```css
321
+ .checkbox {
322
+ width: 20px;
323
+ height: 20px;
324
+ border: var(--border-thick);
325
+ border-radius: var(--radius-none);
326
+ background: var(--bg-surface);
327
+ appearance: none;
328
+ cursor: pointer;
329
+ position: relative;
330
+ flex-shrink: 0;
331
+ }
332
+
333
+ .checkbox:checked {
334
+ background: var(--accent);
335
+ }
336
+
337
+ /* Bold checkmark — 2px stroke minimum */
338
+ .checkbox:checked::after {
339
+ content: '';
340
+ position: absolute;
341
+ left: 4px;
342
+ top: 1px;
343
+ width: 8px;
344
+ height: 12px;
345
+ border-right: 2.5px solid var(--accent-contrast);
346
+ border-bottom: 2.5px solid var(--accent-contrast);
347
+ transform: rotate(45deg);
348
+ }
349
+
350
+ .checkbox:focus-visible {
351
+ outline: 2px solid var(--accent);
352
+ outline-offset: 2px;
353
+ }
354
+ ```
355
+
356
+ ---
357
+
358
+ ## 11. Toggle
359
+
360
+ Brutalist variant: square, not round.
361
+
362
+ ```css
363
+ .toggle {
364
+ width: 48px;
365
+ height: 24px;
366
+ border: var(--border-thick);
367
+ border-radius: var(--radius-none); /* SQUARE — brutalist signature */
368
+ background: var(--bg-elevated);
369
+ cursor: pointer;
370
+ position: relative;
371
+ transition: background var(--transition-base);
372
+ }
373
+
374
+ .toggle:checked {
375
+ background: var(--accent);
376
+ }
377
+
378
+ .toggle-thumb {
379
+ width: 16px;
380
+ height: 16px;
381
+ background: var(--bg-surface);
382
+ border: var(--border-thick);
383
+ border-radius: var(--radius-none); /* SQUARE thumb */
384
+ position: absolute;
385
+ top: 2px;
386
+ left: 2px;
387
+ transition: transform var(--transition-base);
388
+ }
389
+
390
+ .toggle:checked .toggle-thumb {
391
+ transform: translateX(24px);
392
+ }
393
+ ```
394
+
395
+ ---
396
+
397
+ ## 12. Badge
398
+
399
+ ```css
400
+ .badge {
401
+ display: inline-flex;
402
+ align-items: center;
403
+ height: 22px;
404
+ padding: 0 var(--space-3);
405
+ border: var(--border-thick);
406
+ border-radius: var(--radius-full); /* PILL — contrast with card radius 0 */
407
+ font-family: var(--font-mono);
408
+ font-size: var(--text-xs);
409
+ font-weight: var(--weight-medium);
410
+ text-transform: uppercase;
411
+ letter-spacing: var(--tracking-wide);
412
+ white-space: nowrap;
413
+ }
414
+
415
+ .badge--accent { background: var(--accent); color: var(--accent-contrast); }
416
+ .badge--green { background: var(--semantic-green-dim); color: var(--semantic-green); }
417
+ .badge--amber { background: var(--semantic-amber-dim); color: var(--semantic-amber); }
418
+ .badge--red { background: var(--semantic-red-dim); color: var(--semantic-red); }
419
+ .badge--blue { background: var(--semantic-blue-dim); color: var(--semantic-blue); }
420
+ .badge--neutral { background: var(--bg-elevated); color: var(--text-secondary); }
421
+ ```
422
+
423
+ ---
424
+
425
+ ## 13. Tag / Chip (dismissible)
426
+
427
+ ```css
428
+ .tag {
429
+ /* extends .badge */
430
+ border-radius: var(--radius-full);
431
+ gap: var(--space-2);
432
+ }
433
+
434
+ .tag__close {
435
+ width: 16px;
436
+ height: 16px;
437
+ background: none;
438
+ border: none;
439
+ cursor: pointer;
440
+ font-size: 12px;
441
+ font-weight: var(--weight-bold);
442
+ color: currentColor;
443
+ display: flex;
444
+ align-items: center;
445
+ justify-content: center;
446
+ padding: 0;
447
+ }
448
+ ```
449
+
450
+ ---
451
+
452
+ ## 14. Table
453
+
454
+ Full-grid borders — the brutalist data table signature.
455
+
456
+ ```css
457
+ .table {
458
+ width: 100%;
459
+ border-collapse: collapse;
460
+ border: var(--border-thick);
461
+ font-size: var(--text-sm);
462
+ }
463
+
464
+ .table th,
465
+ .table td {
466
+ border: var(--border-subtle); /* ALL cells bordered */
467
+ padding: var(--space-3) var(--space-4);
468
+ text-align: left;
469
+ }
470
+
471
+ .table thead {
472
+ background: var(--bg-elevated);
473
+ }
474
+
475
+ .table th {
476
+ font-family: var(--font-mono);
477
+ font-size: var(--text-xs);
478
+ font-weight: var(--weight-medium);
479
+ text-transform: uppercase;
480
+ letter-spacing: var(--tracking-wider);
481
+ color: var(--text-secondary);
482
+ }
483
+
484
+ /* Data cells: mono for numbers, dates, IDs */
485
+ .table td[data-type="number"],
486
+ .table td[data-type="date"],
487
+ .table td[data-type="id"],
488
+ .table td[data-type="status"] {
489
+ font-family: var(--font-mono);
490
+ }
491
+
492
+ .table tbody tr:hover {
493
+ background: var(--bg-elevated);
494
+ transition: background 60ms ease;
495
+ }
496
+
497
+ /* Sort arrow */
498
+ .table th[aria-sort] {
499
+ cursor: pointer;
500
+ }
501
+
502
+ .table th[aria-sort]::after {
503
+ content: ' ↕';
504
+ font-size: 10px;
505
+ color: var(--text-muted);
506
+ }
507
+
508
+ .table th[aria-sort="ascending"]::after { content: ' ↑'; color: var(--text-heading); }
509
+ .table th[aria-sort="descending"]::after { content: ' ↓'; color: var(--text-heading); }
510
+ ```
511
+
512
+ Tables never stack into card lists on mobile — they scroll horizontally:
513
+ ```css
514
+ .table-container {
515
+ overflow-x: auto;
516
+ -webkit-overflow-scrolling: touch;
517
+ }
518
+ ```
519
+
520
+ ---
521
+
522
+ ## 15. Modal
523
+
524
+ ```css
525
+ .modal-backdrop {
526
+ position: fixed;
527
+ inset: 0;
528
+ background: color-mix(in srgb, var(--bg-void) 70%, transparent);
529
+ /* NO backdrop-filter blur — brutalist has zero blur */
530
+ z-index: var(--z-overlay);
531
+ }
532
+
533
+ .modal {
534
+ background: var(--bg-surface);
535
+ border: var(--border-thicker);
536
+ box-shadow: var(--shadow-xl);
537
+ border-radius: var(--radius-none);
538
+ padding: var(--space-8);
539
+ max-width: 540px;
540
+ width: 90%;
541
+ position: relative;
542
+ z-index: var(--z-modal);
543
+ }
544
+
545
+ .modal__header {
546
+ border-bottom: var(--border-thick);
547
+ padding-bottom: var(--space-4);
548
+ margin-bottom: var(--space-6);
549
+ display: flex;
550
+ justify-content: space-between;
551
+ align-items: center;
552
+ }
553
+
554
+ .modal__title {
555
+ font-family: var(--font-display);
556
+ font-size: var(--text-lg);
557
+ font-weight: var(--weight-bold);
558
+ color: var(--text-heading);
559
+ }
560
+
561
+ .modal__close {
562
+ width: 32px;
563
+ height: 32px;
564
+ border: var(--border-thick);
565
+ background: none;
566
+ cursor: pointer;
567
+ font-size: 18px;
568
+ font-weight: var(--weight-bold);
569
+ display: flex;
570
+ align-items: center;
571
+ justify-content: center;
572
+ }
573
+
574
+ .modal__close:hover { background: var(--bg-elevated); }
575
+ .modal__close:active { transform: translate(2px, 2px); box-shadow: none; }
576
+ ```
577
+
578
+ ---
579
+
580
+ ## 16. Toast
581
+
582
+ ```css
583
+ .toast {
584
+ background: var(--bg-surface);
585
+ border: var(--border-thicker);
586
+ box-shadow: var(--shadow-md);
587
+ border-radius: var(--radius-none);
588
+ padding: var(--space-4) var(--space-5);
589
+ padding-left: calc(var(--space-5) + 4px); /* room for accent bar */
590
+ min-width: 280px;
591
+ max-width: 420px;
592
+ position: relative;
593
+ overflow: hidden;
594
+ }
595
+
596
+ /* Left accent bar — 4px color indicator */
597
+ .toast::before {
598
+ content: '';
599
+ position: absolute;
600
+ left: 0;
601
+ top: 0;
602
+ bottom: 0;
603
+ width: 4px;
604
+ }
605
+
606
+ .toast--success::before { background: var(--semantic-green); }
607
+ .toast--error::before { background: var(--semantic-red); }
608
+ .toast--warning::before { background: var(--semantic-amber); }
609
+ .toast--info::before { background: var(--semantic-blue); }
610
+
611
+ .toast__message {
612
+ font-family: var(--font-mono);
613
+ font-size: var(--text-sm);
614
+ color: var(--text-primary);
615
+ }
616
+
617
+ /* Position: top-right so shadow is visible */
618
+ .toast-container {
619
+ position: fixed;
620
+ top: var(--space-6);
621
+ right: var(--space-6);
622
+ z-index: var(--z-toast);
623
+ display: flex;
624
+ flex-direction: column;
625
+ gap: var(--space-3);
626
+ }
627
+ ```
628
+
629
+ ---
630
+
631
+ ## 17. Tooltip
632
+
633
+ ```css
634
+ .tooltip {
635
+ background: var(--text-heading); /* near-black in light, near-white in dark */
636
+ color: var(--bg-base);
637
+ border: var(--border-thick);
638
+ border-color: var(--text-heading);
639
+ border-radius: var(--radius-none);
640
+ padding: var(--space-1) var(--space-3);
641
+ font-family: var(--font-mono);
642
+ font-size: var(--text-xs);
643
+ white-space: nowrap;
644
+ pointer-events: none;
645
+ }
646
+ ```
647
+
648
+ ---
649
+
650
+ ## 18. Progress Bar
651
+
652
+ Thick — more substantial than other skills.
653
+
654
+ ```css
655
+ .progress {
656
+ height: 12px; /* thicker than standard */
657
+ border: var(--border-thick);
658
+ border-radius: var(--radius-none);
659
+ background: var(--bg-elevated);
660
+ overflow: hidden;
661
+ }
662
+
663
+ .progress__fill {
664
+ height: 100%;
665
+ background: var(--accent);
666
+ border-radius: var(--radius-none);
667
+ transition: width var(--transition-slow);
668
+ }
669
+
670
+ .progress--success .progress__fill { background: var(--semantic-green); }
671
+ .progress--danger .progress__fill { background: var(--semantic-red); }
672
+ ```
673
+
674
+ ---
675
+
676
+ ## 19. Avatar
677
+
678
+ ```css
679
+ .avatar {
680
+ border: var(--border-thicker);
681
+ border-radius: var(--radius-none); /* SQUARE — brutalist default */
682
+ overflow: hidden;
683
+ flex-shrink: 0;
684
+ background: var(--bg-elevated);
685
+ }
686
+
687
+ .avatar--circle { border-radius: var(--radius-full); } /* Round variant */
688
+
689
+ .avatar--sm { width: 32px; height: 32px; }
690
+ .avatar--md { width: 40px; height: 40px; }
691
+ .avatar--lg { width: 56px; height: 56px; }
692
+ ```
693
+
694
+ ---
695
+
696
+ ## 20. Divider
697
+
698
+ ```css
699
+ .divider {
700
+ border: none;
701
+ border-top: var(--border-thick);
702
+ width: 100%;
703
+ margin: var(--space-4) 0;
704
+ }
705
+
706
+ .divider--dashed {
707
+ border-top-style: dashed;
708
+ }
709
+
710
+ .divider--double {
711
+ border-top: var(--border-subtle);
712
+ box-shadow: 0 3px 0 var(--border-color); /* visual double — border + shadow line */
713
+ }
714
+ ```
715
+
716
+ ---
717
+
718
+ ## 21. Marquee
719
+
720
+ For announcement bars and promotional strips.
721
+
722
+ ```css
723
+ .marquee {
724
+ height: 40px;
725
+ background: var(--accent);
726
+ border-top: var(--border-thick);
727
+ border-bottom: var(--border-thick);
728
+ overflow: hidden;
729
+ display: flex;
730
+ align-items: center;
731
+ }
732
+
733
+ .marquee__track {
734
+ display: flex;
735
+ gap: var(--space-16);
736
+ animation: marquee 20s linear infinite;
737
+ white-space: nowrap;
738
+ }
739
+
740
+ .marquee__text {
741
+ font-family: var(--font-mono);
742
+ font-size: var(--text-sm);
743
+ font-weight: var(--weight-bold);
744
+ color: var(--accent-contrast);
745
+ text-transform: uppercase;
746
+ letter-spacing: var(--tracking-wide);
747
+ }
748
+
749
+ @keyframes marquee {
750
+ from { transform: translateX(0); }
751
+ to { transform: translateX(-50%); }
752
+ }
753
+
754
+ @media (prefers-reduced-motion: reduce) {
755
+ .marquee__track { animation: none; }
756
+ }
757
+ ```
758
+
759
+ ---
760
+
761
+ ## 22. Code Block
762
+
763
+ ```css
764
+ .code-block {
765
+ background: var(--bg-elevated);
766
+ border: var(--border-thicker);
767
+ border-radius: var(--radius-none);
768
+ overflow: hidden;
769
+ }
770
+
771
+ /* Colored tab header with filename */
772
+ .code-block__header {
773
+ background: var(--accent);
774
+ color: var(--accent-contrast);
775
+ border-bottom: var(--border-thick);
776
+ padding: var(--space-2) var(--space-4);
777
+ font-family: var(--font-mono);
778
+ font-size: var(--text-xs);
779
+ font-weight: var(--weight-bold);
780
+ display: flex;
781
+ justify-content: space-between;
782
+ align-items: center;
783
+ }
784
+
785
+ .code-block__copy {
786
+ background: none;
787
+ border: var(--border-thick);
788
+ color: var(--accent-contrast);
789
+ font-family: var(--font-mono);
790
+ font-size: var(--text-xs);
791
+ padding: 2px var(--space-2);
792
+ cursor: pointer;
793
+ border-radius: var(--radius-none);
794
+ }
795
+
796
+ .code-block__body {
797
+ padding: var(--space-5);
798
+ overflow-x: auto;
799
+ }
800
+
801
+ .code-block pre, .code-block code {
802
+ font-family: var(--font-mono);
803
+ font-size: var(--text-sm);
804
+ color: var(--text-primary);
805
+ line-height: 1.7;
806
+ }
807
+ ```
808
+
809
+ ---
810
+
811
+ ## 23. Sticker Badge
812
+
813
+ The signature decorative element of this skill.
814
+
815
+ ```css
816
+ .sticker {
817
+ display: inline-block;
818
+ background: var(--accent);
819
+ color: var(--accent-contrast);
820
+ border: var(--border-thick);
821
+ box-shadow: var(--shadow-sm);
822
+ border-radius: var(--radius-none);
823
+ padding: var(--space-1) var(--space-3);
824
+ font-family: var(--font-mono);
825
+ font-size: var(--text-xs);
826
+ font-weight: var(--weight-bold);
827
+ text-transform: uppercase;
828
+ letter-spacing: var(--tracking-wide);
829
+ transform: rotate(-2deg); /* subtle tilt — sticker energy */
830
+ transform-origin: center;
831
+ }
832
+
833
+ /* Variants */
834
+ .sticker--new { background: var(--accent-green); transform: rotate(-1deg); }
835
+ .sticker--hot { background: var(--accent-red); color: white; transform: rotate(2deg); }
836
+ .sticker--beta { background: var(--accent-blue); color: white; transform: rotate(-2deg); }
837
+ .sticker--accent { background: var(--accent); transform: rotate(1.5deg); }
838
+
839
+ /* No animation — stickers are static by default */
840
+ ```
841
+
842
+ ---
843
+
844
+ ## Component Rules Summary
845
+
846
+ | Rule | Detail |
847
+ |------|--------|
848
+ | Border on everything | Every interactive or container element must have a visible border. Min 2px solid. |
849
+ | Shadow direction | All hard shadows point bottom-right. Never top-left, never scattered. |
850
+ | Push mechanic | Every element with `box-shadow` implements shadow-remove + translate on `:active`. |
851
+ | Mono for data | Numbers, dates, IDs, status text, labels, metadata → `font-family: var(--font-mono)`. |
852
+ | Square toggle | Toggle uses `border-radius: 0`. This is the brutalist signature, not a mistake. |
853
+ | Max 2 accents per page | Indie/devtool/zine modes: max 2 accent colors. Creative Playground: up to 4. |
854
+ | No blur anywhere | No `box-shadow` with blur-radius > 0. No `backdrop-filter: blur()`. Zero blur everywhere. |
855
+ | No radius in between | Components are `--radius-none` (0) or `--radius-full` (pills). Never 4–16px unless explicitly specified in a token. |