@cosxai/ui 0.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 (109) hide show
  1. package/package.json +38 -0
  2. package/src/actionbar/ActionBar.tsx +436 -0
  3. package/src/actionbar/ActionBarButton.tsx +110 -0
  4. package/src/actionbar/ActionBarMenuGroup.tsx +106 -0
  5. package/src/actionbar/ActionBarProvider.tsx +76 -0
  6. package/src/actionbar/actionbar-context.ts +23 -0
  7. package/src/actionbar/index.ts +13 -0
  8. package/src/actionbar/types.ts +50 -0
  9. package/src/actionbar/useActionBarItems.ts +47 -0
  10. package/src/ambient/AmbientBackdrop.tsx +74 -0
  11. package/src/ambient/CommandInput.tsx +107 -0
  12. package/src/ambient/SuperbarStrip.tsx +36 -0
  13. package/src/ambient/index.ts +6 -0
  14. package/src/bento/BentoCell.tsx +66 -0
  15. package/src/bento/BentoGrid.tsx +42 -0
  16. package/src/bento/index.ts +2 -0
  17. package/src/command/CommandPalette.tsx +277 -0
  18. package/src/command/CommandProvider.tsx +57 -0
  19. package/src/command/command-context.ts +12 -0
  20. package/src/command/index.ts +6 -0
  21. package/src/command/rank.ts +45 -0
  22. package/src/command/types.ts +26 -0
  23. package/src/command/useCommandSource.ts +37 -0
  24. package/src/dialogs/DialogsProvider.tsx +216 -0
  25. package/src/dialogs/Modal.tsx +204 -0
  26. package/src/dialogs/Toast.tsx +85 -0
  27. package/src/dialogs/dialogs-context.ts +6 -0
  28. package/src/dialogs/index.ts +10 -0
  29. package/src/dialogs/types.ts +37 -0
  30. package/src/dialogs/useDialogs.ts +8 -0
  31. package/src/editorial/EditorialSpotlight.tsx +63 -0
  32. package/src/editorial/Folio.tsx +52 -0
  33. package/src/editorial/PlateMarker.tsx +33 -0
  34. package/src/editorial/RomanSection.tsx +65 -0
  35. package/src/editorial/RunningMarginalia.tsx +65 -0
  36. package/src/editorial/index.ts +10 -0
  37. package/src/frutiger/GlossyOrb.tsx +79 -0
  38. package/src/frutiger/SkyBackdrop.tsx +114 -0
  39. package/src/frutiger/index.ts +2 -0
  40. package/src/hooks/index.ts +5 -0
  41. package/src/hooks/useKeyboardHotkey.ts +80 -0
  42. package/src/hooks/useReducedMotion.ts +20 -0
  43. package/src/hooks/useViewport.ts +61 -0
  44. package/src/index.ts +26 -0
  45. package/src/layout/Breadcrumb.tsx +74 -0
  46. package/src/layout/LeftNavRail.tsx +126 -0
  47. package/src/layout/MobileTabBar.tsx +101 -0
  48. package/src/layout/NavItem.tsx +128 -0
  49. package/src/layout/NavSearchTrigger.tsx +88 -0
  50. package/src/layout/NavSection.tsx +40 -0
  51. package/src/layout/RightSidebarPanel.tsx +111 -0
  52. package/src/layout/Shell.tsx +91 -0
  53. package/src/layout/StickyBanner.tsx +83 -0
  54. package/src/layout/Topbar.tsx +68 -0
  55. package/src/layout/index.ts +22 -0
  56. package/src/layout/useNavRailState.ts +69 -0
  57. package/src/lib/cn.ts +7 -0
  58. package/src/lib/time-utils.ts +44 -0
  59. package/src/neobrutalism/Marquee.tsx +81 -0
  60. package/src/neobrutalism/Sticker.tsx +71 -0
  61. package/src/neobrutalism/index.ts +4 -0
  62. package/src/primitives/Avatar.tsx +53 -0
  63. package/src/primitives/Button.tsx +30 -0
  64. package/src/primitives/Card.tsx +41 -0
  65. package/src/primitives/Checkbox.tsx +78 -0
  66. package/src/primitives/CountBadge.tsx +50 -0
  67. package/src/primitives/Input.tsx +71 -0
  68. package/src/primitives/Kbd.tsx +45 -0
  69. package/src/primitives/PageHeader.tsx +77 -0
  70. package/src/primitives/Tag.tsx +56 -0
  71. package/src/primitives/Textarea.tsx +62 -0
  72. package/src/primitives/ToggleSwitch.tsx +79 -0
  73. package/src/primitives/Tooltip.tsx +171 -0
  74. package/src/primitives/index.ts +24 -0
  75. package/src/pwa/InstallPromptBanner.tsx +132 -0
  76. package/src/pwa/index.ts +4 -0
  77. package/src/pwa/manifest.template.json +20 -0
  78. package/src/pwa/registerSW.ts +55 -0
  79. package/src/riso/Halftone.tsx +85 -0
  80. package/src/riso/Misregister.tsx +63 -0
  81. package/src/riso/RisoStamp.tsx +76 -0
  82. package/src/riso/index.ts +3 -0
  83. package/src/sketch/HandUnderline.tsx +53 -0
  84. package/src/sketch/RoughArrow.tsx +91 -0
  85. package/src/sketch/RoughBox.tsx +73 -0
  86. package/src/sketch/StickyNote.tsx +56 -0
  87. package/src/sketch/index.ts +4 -0
  88. package/src/styles/base.css +80 -0
  89. package/src/styles/chrome-ambient.css +222 -0
  90. package/src/styles/chrome-bento.css +184 -0
  91. package/src/styles/chrome-editorial.css +145 -0
  92. package/src/styles/chrome-frutiger.css +364 -0
  93. package/src/styles/chrome-neobrutalism.css +315 -0
  94. package/src/styles/chrome-riso.css +328 -0
  95. package/src/styles/chrome-sketch.css +351 -0
  96. package/src/styles/chrome-swiss.css +232 -0
  97. package/src/styles/chrome-terminal.css +235 -0
  98. package/src/styles/fonts.css +22 -0
  99. package/src/styles/index.css +198 -0
  100. package/src/styles/tokens.css +976 -0
  101. package/src/terminal/AsciiBox.tsx +65 -0
  102. package/src/terminal/BrailleSpinner.tsx +46 -0
  103. package/src/terminal/index.ts +4 -0
  104. package/src/theme/ThemeProvider.tsx +93 -0
  105. package/src/theme/index.ts +5 -0
  106. package/src/theme/inline-script.ts +36 -0
  107. package/src/theme/theme-context.ts +7 -0
  108. package/src/theme/types.ts +22 -0
  109. package/src/theme/useTheme.ts +8 -0
@@ -0,0 +1,364 @@
1
+ /* Frutiger Aero / Glossy Revival chrome — Aero / Vista / iOS 6 /
2
+ Vision Pro Liquid Glass. Glossy buttons with a two-layer gradient
3
+ (aqua base + white gloss top half), glass cards with backdrop-
4
+ filter, soft blue-tinted shadows, outer glow on hover, deep navy
5
+ ink. Sparkle particles + shimmer sweeps are opt-in via classnames
6
+ so the chrome only "performs" when you want it to.
7
+
8
+ Implementation note: the sky-gradient canvas is applied via the
9
+ tokens.css `--ck-bg-canvas`. The kit's base layer already does
10
+ `body { background: var(--ck-bg-canvas); }` so the gradient
11
+ value carries through. */
12
+
13
+ /* Body — humanist sans, deep navy, slightly tighter letter-spacing
14
+ on hero text. */
15
+ html[data-ck-chrome="frutiger"] body {
16
+ font-family: "Avenir Next", "Calibre", "SF Pro Rounded", var(--ck-font-sans);
17
+ background-attachment: fixed;
18
+ letter-spacing: -0.005em;
19
+ }
20
+
21
+ html[data-ck-chrome="frutiger"] h1,
22
+ html[data-ck-chrome="frutiger"] .ck-h1 {
23
+ font-weight: 700;
24
+ letter-spacing: -0.01em;
25
+ line-height: 1.05;
26
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.8),
27
+ 0 2px 4px rgba(0, 100, 200, 0.18);
28
+ }
29
+ html[data-ck-chrome="frutiger"] h2,
30
+ html[data-ck-chrome="frutiger"] .ck-h2 {
31
+ font-weight: 600;
32
+ letter-spacing: -0.005em;
33
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6);
34
+ }
35
+ html[data-ck-chrome="frutiger"] h3,
36
+ html[data-ck-chrome="frutiger"] .ck-h3 {
37
+ font-weight: 600;
38
+ }
39
+
40
+ /* Dark mode: drop the white text-shadow (would look like a bug
41
+ against the navy canvas). */
42
+ html[data-ck-theme="dark"][data-ck-chrome="frutiger"] h1,
43
+ html[data-ck-theme="dark"][data-ck-chrome="frutiger"] h2,
44
+ html[data-ck-theme="dark"][data-ck-chrome="frutiger"] h3 {
45
+ text-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
46
+ }
47
+
48
+ /* ---------- Buttons — the signature glossy candy element ---------- */
49
+ html[data-ck-chrome="frutiger"] .ck-btn,
50
+ html[data-ck-chrome="frutiger"] .ck-actionbar-btn {
51
+ border-radius: 12px;
52
+ font-weight: 600;
53
+ letter-spacing: -0.005em;
54
+ height: 36px;
55
+ border: 1px solid rgba(255, 255, 255, 0.5);
56
+ box-shadow:
57
+ inset 0 1px 0 rgba(255, 255, 255, 0.6),
58
+ inset 0 -1px 0 rgba(0, 50, 120, 0.2),
59
+ 0 2px 8px rgba(0, 100, 200, 0.18);
60
+ transition:
61
+ box-shadow 200ms ease,
62
+ transform 200ms ease,
63
+ background 200ms ease;
64
+ }
65
+
66
+ html[data-ck-chrome="frutiger"] .ck-btn--primary,
67
+ html[data-ck-chrome="frutiger"] .ck-actionbar-btn--primary {
68
+ background:
69
+ var(--ck-frutiger-gloss),
70
+ var(--ck-frutiger-btn);
71
+ color: #FFFFFF;
72
+ text-shadow: 0 1px 0 rgba(0, 50, 120, 0.45);
73
+ border-color: rgba(2, 88, 155, 0.7);
74
+ }
75
+ html[data-ck-chrome="frutiger"] .ck-btn--primary:hover:not(:disabled),
76
+ html[data-ck-chrome="frutiger"] .ck-actionbar-btn--primary:hover:not(:disabled) {
77
+ background:
78
+ var(--ck-frutiger-gloss),
79
+ var(--ck-frutiger-btn-hover);
80
+ box-shadow:
81
+ inset 0 1px 0 rgba(255, 255, 255, 0.75),
82
+ inset 0 -1px 0 rgba(0, 50, 120, 0.2),
83
+ var(--ck-frutiger-glow);
84
+ }
85
+
86
+ html[data-ck-chrome="frutiger"] .ck-btn--secondary {
87
+ background:
88
+ linear-gradient(180deg, rgba(255,255,255,0.85) 0%, rgba(255,255,255,0.35) 50%, rgba(255,255,255,0.55) 100%);
89
+ color: var(--ck-text-primary);
90
+ border-color: rgba(255, 255, 255, 0.65);
91
+ backdrop-filter: blur(8px);
92
+ }
93
+ html[data-ck-chrome="frutiger"] .ck-btn--secondary:hover:not(:disabled) {
94
+ box-shadow:
95
+ inset 0 1px 0 rgba(255, 255, 255, 0.8),
96
+ inset 0 -1px 0 rgba(0, 50, 120, 0.18),
97
+ var(--ck-frutiger-glow-soft);
98
+ }
99
+
100
+ html[data-ck-chrome="frutiger"] .ck-btn--ghost {
101
+ background: rgba(255, 255, 255, 0.0);
102
+ border-color: transparent;
103
+ box-shadow: none;
104
+ color: var(--ck-text-primary);
105
+ }
106
+ html[data-ck-chrome="frutiger"] .ck-btn--ghost:hover:not(:disabled) {
107
+ background: rgba(255, 255, 255, 0.35);
108
+ border-color: rgba(255, 255, 255, 0.45);
109
+ box-shadow:
110
+ inset 0 1px 0 rgba(255, 255, 255, 0.6),
111
+ 0 1px 4px rgba(0, 100, 200, 0.14);
112
+ }
113
+
114
+ html[data-ck-chrome="frutiger"] .ck-btn:active:not(:disabled),
115
+ html[data-ck-chrome="frutiger"] .ck-actionbar-btn:active:not(:disabled) {
116
+ transform: translateY(1px);
117
+ }
118
+
119
+ /* ---------- Inputs — inset glass, glow on focus ---------- */
120
+ html[data-ck-chrome="frutiger"] .ck-input,
121
+ html[data-ck-chrome="frutiger"] .ck-textarea {
122
+ background:
123
+ linear-gradient(180deg, rgba(0, 50, 120, 0.06) 0%, rgba(255, 255, 255, 0.6) 18%);
124
+ border: 1px solid rgba(0, 60, 140, 0.18);
125
+ border-radius: 12px;
126
+ box-shadow:
127
+ inset 0 2px 4px rgba(0, 50, 120, 0.12),
128
+ 0 1px 0 rgba(255, 255, 255, 0.85);
129
+ color: var(--ck-text-primary);
130
+ }
131
+ html[data-ck-chrome="frutiger"] .ck-input::placeholder,
132
+ html[data-ck-chrome="frutiger"] .ck-textarea::placeholder {
133
+ color: rgba(56, 80, 122, 0.55);
134
+ }
135
+ html[data-ck-chrome="frutiger"] .ck-input:focus-visible,
136
+ html[data-ck-chrome="frutiger"] .ck-textarea:focus-visible {
137
+ outline: none;
138
+ border-color: var(--ck-accent) !important;
139
+ box-shadow:
140
+ inset 0 2px 4px rgba(0, 50, 120, 0.12),
141
+ var(--ck-frutiger-glow-soft) !important;
142
+ }
143
+
144
+ /* ---------- Cards — glass plate with top highlight + bottom shadow line */
145
+ html[data-ck-chrome="frutiger"] .ck-card {
146
+ background:
147
+ linear-gradient(180deg, rgba(255,255,255,0.78) 0%, rgba(255,255,255,0.55) 100%);
148
+ backdrop-filter: blur(20px) saturate(140%);
149
+ -webkit-backdrop-filter: blur(20px) saturate(140%);
150
+ border: 1px solid rgba(255, 255, 255, 0.6);
151
+ border-radius: 18px;
152
+ box-shadow:
153
+ inset 0 1px 0 rgba(255, 255, 255, 0.85),
154
+ inset 0 -1px 0 rgba(0, 50, 120, 0.14),
155
+ var(--ck-shadow-2);
156
+ position: relative;
157
+ }
158
+ html[data-ck-chrome="frutiger"] .ck-card__head {
159
+ background: transparent;
160
+ border-bottom: 1px solid rgba(0, 50, 120, 0.1);
161
+ padding: 14px 20px;
162
+ }
163
+ html[data-ck-chrome="frutiger"] .ck-card__foot {
164
+ background: transparent;
165
+ border-top: 1px solid rgba(0, 50, 120, 0.08);
166
+ padding: 12px 20px;
167
+ }
168
+
169
+ /* ---------- Tags — glossy pills ---------- */
170
+ html[data-ck-chrome="frutiger"] [data-ck-tag] {
171
+ border-radius: 999px !important;
172
+ padding: 3px 10px !important;
173
+ font-weight: 600 !important;
174
+ font-size: 11px !important;
175
+ letter-spacing: 0 !important;
176
+ text-transform: none !important;
177
+ border: 1px solid rgba(255, 255, 255, 0.5) !important;
178
+ box-shadow:
179
+ inset 0 1px 0 rgba(255, 255, 255, 0.7),
180
+ inset 0 -1px 0 rgba(0, 50, 120, 0.12),
181
+ 0 1px 3px rgba(0, 100, 200, 0.14) !important;
182
+ background:
183
+ linear-gradient(180deg, rgba(255,255,255,0.75) 0%, rgba(255,255,255,0.35) 100%) !important;
184
+ color: var(--ck-text-primary) !important;
185
+ }
186
+ html[data-ck-chrome="frutiger"] [data-ck-tag][data-tone="accent"] {
187
+ background:
188
+ linear-gradient(180deg, rgba(255,255,255,0.5) 0%, rgba(255,255,255,0) 50%),
189
+ linear-gradient(180deg, #4FC3F7 0%, #0288D1 100%) !important;
190
+ color: #FFFFFF !important;
191
+ text-shadow: 0 1px 0 rgba(0, 50, 120, 0.4);
192
+ border-color: rgba(2, 119, 189, 0.7) !important;
193
+ }
194
+ html[data-ck-chrome="frutiger"] [data-ck-tag][data-tone="success"] {
195
+ background:
196
+ linear-gradient(180deg, rgba(255,255,255,0.55) 0%, rgba(255,255,255,0) 50%),
197
+ linear-gradient(180deg, #DCFF66 0%, #C6FF00 100%) !important;
198
+ color: #2A3A00 !important;
199
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
200
+ border-color: rgba(120, 160, 0, 0.5) !important;
201
+ }
202
+ html[data-ck-chrome="frutiger"] [data-ck-tag][data-tone="warning"] {
203
+ background:
204
+ linear-gradient(180deg, rgba(255,255,255,0.5) 0%, rgba(255,255,255,0) 50%),
205
+ linear-gradient(180deg, #FFCA28 0%, #FF9800 100%) !important;
206
+ color: #4A2400 !important;
207
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4);
208
+ border-color: rgba(180, 100, 0, 0.5) !important;
209
+ }
210
+ html[data-ck-chrome="frutiger"] [data-ck-tag][data-tone="critical"] {
211
+ background:
212
+ linear-gradient(180deg, rgba(255,255,255,0.5) 0%, rgba(255,255,255,0) 50%),
213
+ linear-gradient(180deg, #FF7B7B 0%, #D32F2F 100%) !important;
214
+ color: #FFFFFF !important;
215
+ text-shadow: 0 1px 0 rgba(140, 20, 20, 0.6);
216
+ border-color: rgba(150, 30, 30, 0.7) !important;
217
+ }
218
+
219
+ /* ---------- Layout chrome ---------- */
220
+ html[data-ck-chrome="frutiger"] [data-ck-leftnav] {
221
+ background:
222
+ linear-gradient(180deg, rgba(255,255,255,0.7) 0%, rgba(255,255,255,0.45) 100%) !important;
223
+ backdrop-filter: blur(28px) saturate(150%);
224
+ -webkit-backdrop-filter: blur(28px) saturate(150%);
225
+ border-right: 1px solid rgba(255, 255, 255, 0.55);
226
+ box-shadow: inset -1px 0 0 rgba(0, 50, 120, 0.1),
227
+ 4px 0 24px rgba(0, 100, 200, 0.12);
228
+ }
229
+
230
+ html[data-ck-chrome="frutiger"] [data-ck-topbar] {
231
+ background:
232
+ linear-gradient(180deg, rgba(255,255,255,0.78) 0%, rgba(255,255,255,0.55) 100%) !important;
233
+ backdrop-filter: blur(28px) saturate(150%);
234
+ -webkit-backdrop-filter: blur(28px) saturate(150%);
235
+ border-bottom: 1px solid rgba(255, 255, 255, 0.5);
236
+ box-shadow:
237
+ inset 0 1px 0 rgba(255, 255, 255, 0.85),
238
+ 0 2px 12px rgba(0, 100, 200, 0.1);
239
+ }
240
+
241
+ /* NavItem — glassy pill, accent on active */
242
+ html[data-ck-chrome="frutiger"] [data-ck-navitem] {
243
+ background: transparent !important;
244
+ border-radius: 10px !important;
245
+ font-weight: 500 !important;
246
+ color: var(--ck-text-secondary) !important;
247
+ transition: background 200ms ease, box-shadow 200ms ease;
248
+ }
249
+ html[data-ck-chrome="frutiger"] [data-ck-navitem]:not([data-active="true"]):hover {
250
+ background:
251
+ linear-gradient(180deg, rgba(255,255,255,0.7) 0%, rgba(255,255,255,0.35) 100%) !important;
252
+ box-shadow:
253
+ inset 0 1px 0 rgba(255, 255, 255, 0.7),
254
+ 0 1px 4px rgba(0, 100, 200, 0.12) !important;
255
+ color: var(--ck-text-primary) !important;
256
+ }
257
+ html[data-ck-chrome="frutiger"] [data-ck-navitem][data-active="true"] {
258
+ background:
259
+ linear-gradient(180deg, rgba(255,255,255,0.55) 0%, rgba(255,255,255,0) 50%),
260
+ linear-gradient(180deg, #4FC3F7 0%, #0288D1 100%) !important;
261
+ color: #FFFFFF !important;
262
+ text-shadow: 0 1px 0 rgba(0, 50, 120, 0.4) !important;
263
+ box-shadow:
264
+ inset 0 1px 0 rgba(255, 255, 255, 0.6),
265
+ inset 0 -1px 0 rgba(0, 50, 120, 0.18),
266
+ 0 2px 8px rgba(0, 100, 200, 0.28) !important;
267
+ font-weight: 600 !important;
268
+ }
269
+
270
+ /* Search trigger */
271
+ html[data-ck-chrome="frutiger"] [data-ck-search-trigger] {
272
+ background:
273
+ linear-gradient(180deg, rgba(0, 50, 120, 0.06) 0%, rgba(255, 255, 255, 0.65) 18%) !important;
274
+ border: 1px solid rgba(0, 60, 140, 0.18) !important;
275
+ border-radius: 12px !important;
276
+ box-shadow:
277
+ inset 0 2px 4px rgba(0, 50, 120, 0.1),
278
+ 0 1px 0 rgba(255, 255, 255, 0.85) !important;
279
+ color: var(--ck-text-secondary) !important;
280
+ }
281
+
282
+ /* Action bar */
283
+ html[data-ck-chrome="frutiger"] [data-ck-actionbar] {
284
+ background:
285
+ linear-gradient(180deg, rgba(255,255,255,0.85) 0%, rgba(255,255,255,0.55) 100%) !important;
286
+ backdrop-filter: blur(28px) saturate(150%);
287
+ -webkit-backdrop-filter: blur(28px) saturate(150%);
288
+ border: 1px solid rgba(255, 255, 255, 0.6);
289
+ border-radius: 999px;
290
+ box-shadow:
291
+ inset 0 1px 0 rgba(255, 255, 255, 0.9),
292
+ inset 0 -1px 0 rgba(0, 50, 120, 0.14),
293
+ var(--ck-shadow-3);
294
+ }
295
+
296
+ /* Modal — frosted plate */
297
+ html[data-ck-chrome="frutiger"] [role="dialog"] > div:first-child {
298
+ background: rgba(135, 206, 235, 0.35);
299
+ backdrop-filter: blur(16px) saturate(160%);
300
+ -webkit-backdrop-filter: blur(16px) saturate(160%);
301
+ }
302
+ html[data-ck-chrome="frutiger"] [role="dialog"] > div > div {
303
+ background:
304
+ linear-gradient(180deg, rgba(255,255,255,0.88) 0%, rgba(255,255,255,0.65) 100%) !important;
305
+ backdrop-filter: blur(28px) saturate(160%);
306
+ -webkit-backdrop-filter: blur(28px) saturate(160%);
307
+ border: 1px solid rgba(255, 255, 255, 0.7);
308
+ border-radius: 22px;
309
+ box-shadow:
310
+ inset 0 1px 0 rgba(255, 255, 255, 0.9),
311
+ inset 0 -1px 0 rgba(0, 50, 120, 0.14),
312
+ var(--ck-shadow-3);
313
+ }
314
+
315
+ /* Code / pre blocks — semi-transparent glass too */
316
+ html[data-ck-chrome="frutiger"] pre,
317
+ html[data-ck-chrome="frutiger"] code {
318
+ background: rgba(255, 255, 255, 0.55) !important;
319
+ border: 1px solid rgba(255, 255, 255, 0.5);
320
+ border-radius: 10px;
321
+ color: var(--ck-text-primary);
322
+ }
323
+
324
+ /* ---------- Shimmer sweep — opt-in via .ck-frutiger-shimmer.
325
+ Diagonal white gradient sweeps across the element every few
326
+ seconds. Apply to "shiny" elements: progress fills, loading
327
+ pills, the hero CTA. */
328
+ @keyframes ck-frutiger-shimmer {
329
+ 0% { transform: translateX(-150%) skewX(-20deg); }
330
+ 60%, 100% { transform: translateX(250%) skewX(-20deg); }
331
+ }
332
+ .ck-frutiger-shimmer {
333
+ position: relative;
334
+ overflow: hidden;
335
+ }
336
+ .ck-frutiger-shimmer::after {
337
+ content: "";
338
+ position: absolute;
339
+ inset: 0;
340
+ pointer-events: none;
341
+ background: linear-gradient(110deg,
342
+ transparent 0%,
343
+ transparent 35%,
344
+ rgba(255, 255, 255, 0.55) 50%,
345
+ transparent 65%,
346
+ transparent 100%);
347
+ animation: ck-frutiger-shimmer 3.4s ease-in-out infinite;
348
+ }
349
+
350
+ /* Slow pulse for the "aero glow" — opt-in via .ck-frutiger-glow */
351
+ @keyframes ck-frutiger-glow-pulse {
352
+ 0%, 100% { box-shadow: 0 0 16px rgba(79, 195, 247, 0.35); }
353
+ 50% { box-shadow: 0 0 28px rgba(79, 195, 247, 0.65); }
354
+ }
355
+ .ck-frutiger-glow {
356
+ animation: ck-frutiger-glow-pulse 4.2s ease-in-out infinite;
357
+ }
358
+
359
+ @media (prefers-reduced-motion: reduce) {
360
+ .ck-frutiger-shimmer::after,
361
+ .ck-frutiger-glow {
362
+ animation: none;
363
+ }
364
+ }
@@ -0,0 +1,315 @@
1
+ /* Neobrutalism chrome — component overrides.
2
+ Token overrides live in tokens.css (palette + typography +
3
+ shadow primitives). This file ships the signature interactions:
4
+ 2 px black borders everywhere, 4 px offset hard shadows on
5
+ interactive elements, and the hover-translate effect that
6
+ pushes elements toward their shadow.
7
+ Loads alongside index.css; takes effect only when
8
+ html[data-ck-chrome="neobrutalism"] is set on the root. */
9
+
10
+ html[data-ck-chrome="neobrutalism"] body {
11
+ font-weight: 500;
12
+ font-feature-settings: "kern", "ss01";
13
+ }
14
+
15
+ /* ===== Buttons ============================================== */
16
+
17
+ /* Standard neobrut button — thick border, hard offset shadow.
18
+ On hover the element translates toward its shadow and the
19
+ shadow shrinks; on active it fully merges with the shadow.
20
+ This "physical push" reads as the signature interaction. */
21
+ html[data-ck-chrome="neobrutalism"] .ck-btn,
22
+ html[data-ck-chrome="neobrutalism"] .ck-actionbar-btn {
23
+ border: 2px solid var(--neobrut-ink);
24
+ border-radius: 5px;
25
+ box-shadow: 4px 4px 0 0 var(--neobrut-ink);
26
+ font-family: var(--ck-font-sans);
27
+ font-weight: 700;
28
+ text-transform: none;
29
+ letter-spacing: 0;
30
+ transition: transform 120ms ease, box-shadow 120ms ease, background 120ms ease;
31
+ }
32
+ html[data-ck-chrome="neobrutalism"] .ck-btn:hover:not(:disabled),
33
+ html[data-ck-chrome="neobrutalism"] .ck-actionbar-btn:hover:not(:disabled) {
34
+ transform: translate(2px, 2px);
35
+ box-shadow: 2px 2px 0 0 var(--neobrut-ink);
36
+ }
37
+ html[data-ck-chrome="neobrutalism"] .ck-btn:active:not(:disabled),
38
+ html[data-ck-chrome="neobrutalism"] .ck-actionbar-btn:active:not(:disabled) {
39
+ transform: translate(4px, 4px);
40
+ box-shadow: 0 0 0 0 var(--neobrut-ink);
41
+ }
42
+
43
+ html[data-ck-chrome="neobrutalism"] .ck-btn--primary {
44
+ background: var(--ck-accent);
45
+ color: #000;
46
+ }
47
+ html[data-ck-chrome="neobrutalism"] .ck-btn--primary:hover:not(:disabled) {
48
+ background: var(--ck-accent);
49
+ }
50
+ html[data-ck-chrome="neobrutalism"] .ck-btn--secondary,
51
+ html[data-ck-chrome="neobrutalism"] .ck-btn--ghost {
52
+ background: var(--ck-bg-surface);
53
+ color: var(--ck-text-primary);
54
+ }
55
+ html[data-ck-chrome="neobrutalism"] .ck-btn--secondary:hover:not(:disabled),
56
+ html[data-ck-chrome="neobrutalism"] .ck-btn--ghost:hover:not(:disabled) {
57
+ background: var(--ck-bg-surface);
58
+ }
59
+
60
+ /* ===== Cards ================================================ */
61
+
62
+ html[data-ck-chrome="neobrutalism"] .ck-card {
63
+ background: var(--ck-bg-surface);
64
+ border: 2px solid var(--neobrut-ink);
65
+ border-radius: 5px;
66
+ box-shadow: 4px 4px 0 0 var(--neobrut-ink);
67
+ }
68
+ /* No internal dividers + no footer tint — the reference card is
69
+ one cohesive chunky surface. Header eyebrow / body / footer
70
+ buttons all sit on the same near-black plane; chunky buttons
71
+ inside the footer provide their own visual separation via
72
+ border + shadow. */
73
+ html[data-ck-chrome="neobrutalism"] .ck-card__head {
74
+ border-bottom: none;
75
+ padding: 24px 24px 0;
76
+ }
77
+ html[data-ck-chrome="neobrutalism"] .ck-card__body {
78
+ padding: 16px 24px;
79
+ }
80
+ html[data-ck-chrome="neobrutalism"] .ck-card__foot {
81
+ border-top: none;
82
+ background: transparent;
83
+ padding: 0 24px 24px;
84
+ }
85
+
86
+ /* ===== Inputs / Textareas =================================== */
87
+
88
+ html[data-ck-chrome="neobrutalism"] .ck-input,
89
+ html[data-ck-chrome="neobrutalism"] .ck-textarea {
90
+ border: 2px solid var(--neobrut-ink);
91
+ border-radius: 5px;
92
+ font-family: var(--ck-font-sans);
93
+ font-weight: 500;
94
+ background: #FFFFFF;
95
+ color: #000000;
96
+ transition: box-shadow 120ms ease;
97
+ }
98
+ html[data-ck-theme="dark"][data-ck-chrome="neobrutalism"] .ck-input,
99
+ html[data-ck-theme="dark"][data-ck-chrome="neobrutalism"] .ck-textarea {
100
+ background: var(--ck-bg-surface);
101
+ color: var(--ck-text-primary);
102
+ }
103
+ html[data-ck-chrome="neobrutalism"] .ck-input:focus-visible,
104
+ html[data-ck-chrome="neobrutalism"] .ck-textarea:focus-visible {
105
+ outline: none;
106
+ border-color: var(--neobrut-ink) !important;
107
+ box-shadow: 4px 4px 0 0 var(--neobrut-ink);
108
+ }
109
+
110
+ /* ===== Typography =========================================== */
111
+
112
+ html[data-ck-chrome="neobrutalism"] h1,
113
+ html[data-ck-chrome="neobrutalism"] .ck-h1 {
114
+ font-family: var(--ck-font-display);
115
+ font-weight: 900;
116
+ letter-spacing: -0.02em;
117
+ line-height: 1;
118
+ }
119
+ html[data-ck-chrome="neobrutalism"] h2,
120
+ html[data-ck-chrome="neobrutalism"] .ck-h2 {
121
+ font-family: var(--ck-font-display);
122
+ font-weight: 800;
123
+ letter-spacing: -0.01em;
124
+ line-height: 1.05;
125
+ }
126
+ html[data-ck-chrome="neobrutalism"] h3,
127
+ html[data-ck-chrome="neobrutalism"] .ck-h3 {
128
+ font-weight: 700;
129
+ letter-spacing: -0.005em;
130
+ }
131
+
132
+ /* Eyebrow / tag — neobrut versions are filled pills, not the
133
+ tracked uppercase the editorial chrome uses. */
134
+ html[data-ck-chrome="neobrutalism"] .ck-tag {
135
+ letter-spacing: 0.02em;
136
+ font-weight: 700;
137
+ }
138
+
139
+ /* ===== Action bar =========================================== */
140
+
141
+ html[data-ck-chrome="neobrutalism"] [data-ck-actionbar] {
142
+ border: 2px solid var(--neobrut-ink);
143
+ border-radius: 5px;
144
+ box-shadow: 4px 4px 0 0 var(--neobrut-ink);
145
+ background: var(--ck-bg-surface);
146
+ }
147
+
148
+ /* ===== Layout chrome ======================================== */
149
+
150
+ /* Sidebar + topbar both pin to --ck-bg-surface so the chrome
151
+ layer is visually unified (light: paper white; dark: dark
152
+ gray near-black). The canvas behind the main content stays
153
+ the distinctive hue — cream in light, navy in dark — and the
154
+ chrome reads as a separate band around it.
155
+ Topbar gets !important too because <Topbar> sets bg via
156
+ inline style and we want this override to win across chromes. */
157
+ html[data-ck-chrome="neobrutalism"] [data-ck-leftnav],
158
+ html[data-ck-chrome="neobrutalism"] [data-ck-topbar] {
159
+ background: var(--ck-bg-surface) !important;
160
+ }
161
+ html[data-ck-chrome="neobrutalism"] [data-ck-leftnav] {
162
+ border-right: 2px solid var(--neobrut-ink);
163
+ }
164
+ html[data-ck-chrome="neobrutalism"] [data-ck-topbar] {
165
+ border-bottom: 2px solid var(--neobrut-ink);
166
+ }
167
+
168
+ /* ===== NavItem ============================================== */
169
+
170
+ /* Active state — accent fill, 2 px black border, hard black
171
+ offset shadow, black text. The reference site reserves the
172
+ chunky treatment for the active item; inactive rows are flat
173
+ text on the sidebar surface so the active one truly stands
174
+ out. Earlier I made every row chunky and it read noisy. */
175
+ html[data-ck-chrome="neobrutalism"] [data-ck-navitem][data-active="true"] {
176
+ background: var(--ck-accent) !important;
177
+ color: #000 !important;
178
+ border: 2px solid var(--neobrut-ink) !important;
179
+ box-shadow: 3px 3px 0 0 var(--neobrut-ink) !important;
180
+ border-radius: 5px !important;
181
+ font-weight: 700 !important;
182
+ }
183
+ html[data-ck-chrome="neobrutalism"] [data-ck-navitem]:not([data-active="true"]) {
184
+ background: transparent !important;
185
+ border: 2px solid transparent !important;
186
+ font-weight: 600 !important;
187
+ color: var(--ck-text-primary) !important;
188
+ }
189
+ html[data-ck-chrome="neobrutalism"] [data-ck-navitem]:not([data-active="true"]):hover {
190
+ background: var(--ck-bg-canvas) !important;
191
+ }
192
+
193
+ /* ===== Search trigger ====================================== */
194
+
195
+ html[data-ck-chrome="neobrutalism"] [data-ck-search-trigger] {
196
+ background: var(--ck-bg-surface) !important;
197
+ border: 2px solid var(--neobrut-ink) !important;
198
+ border-radius: 5px !important;
199
+ box-shadow: 3px 3px 0 0 var(--neobrut-ink) !important;
200
+ }
201
+ html[data-ck-chrome="neobrutalism"] [data-ck-search-trigger]:hover {
202
+ transform: translate(1.5px, 1.5px);
203
+ box-shadow: 1.5px 1.5px 0 0 var(--neobrut-ink) !important;
204
+ transition: transform 120ms ease, box-shadow 120ms ease;
205
+ }
206
+
207
+ /* ===== Tags ================================================= */
208
+
209
+ /* Every tag becomes a chunky filled pill with 2 px border + a
210
+ small hard shadow. Both filled and bare variants get the same
211
+ physical treatment — neobrutalism doesn't do "bare label".
212
+ Tone-specific colours come from the inline style on the
213
+ component; we just add the structural overrides. */
214
+ html[data-ck-chrome="neobrutalism"] [data-ck-tag] {
215
+ padding: 3px 8px !important;
216
+ border: 2px solid var(--neobrut-ink) !important;
217
+ border-radius: 4px !important;
218
+ box-shadow: 2px 2px 0 0 var(--neobrut-ink) !important;
219
+ font-weight: 700 !important;
220
+ letter-spacing: 0.04em !important;
221
+ /* Text on the saturated-tone fill is pure black in both modes —
222
+ same as main-foreground in the reference. */
223
+ color: #000 !important;
224
+ }
225
+
226
+ /* Bare tags (no `filled` prop) — set background from tone via
227
+ data-tone selector so the chunky pill still pops. */
228
+ html[data-ck-chrome="neobrutalism"] [data-ck-tag]:not([data-filled="true"])[data-tone="accent"] {
229
+ background: var(--ck-accent) !important;
230
+ }
231
+ html[data-ck-chrome="neobrutalism"] [data-ck-tag]:not([data-filled="true"])[data-tone="success"] {
232
+ background: var(--ck-success) !important;
233
+ }
234
+ html[data-ck-chrome="neobrutalism"] [data-ck-tag]:not([data-filled="true"])[data-tone="warning"] {
235
+ background: var(--ck-warning) !important;
236
+ }
237
+ html[data-ck-chrome="neobrutalism"] [data-ck-tag]:not([data-filled="true"])[data-tone="critical"] {
238
+ background: var(--ck-critical) !important;
239
+ }
240
+ html[data-ck-chrome="neobrutalism"] [data-ck-tag]:not([data-filled="true"])[data-tone="neutral"] {
241
+ background: var(--ck-bg-surface) !important;
242
+ }
243
+
244
+ /* ===== Modal backdrop ======================================= */
245
+
246
+ html[data-ck-chrome="neobrutalism"] [role="dialog"] > div:first-child {
247
+ background: rgba(0, 0, 0, 0.4);
248
+ backdrop-filter: none;
249
+ }
250
+ /* Modals get a bigger 8 px shadow per brief — heavier than
251
+ ambient cards because they demand attention. */
252
+ html[data-ck-chrome="neobrutalism"] [role="dialog"] > div > div {
253
+ border: 2px solid var(--neobrut-ink);
254
+ border-radius: 8px;
255
+ box-shadow: 8px 8px 0 0 var(--neobrut-ink);
256
+ }
257
+
258
+ /* ===== ChromeCard (docs theming page) =======================
259
+ Any button with aria-pressed (the chrome-picker cards on
260
+ /theming) — both active and inactive get the chunky 2 px
261
+ border + offset shadow. Active also gets the accent fill +
262
+ black-text override. */
263
+ html[data-ck-chrome="neobrutalism"] button[aria-pressed] {
264
+ border: 2px solid var(--neobrut-ink) !important;
265
+ border-radius: 6px !important;
266
+ box-shadow: 4px 4px 0 0 var(--neobrut-ink) !important;
267
+ transition: transform 120ms ease, box-shadow 120ms ease,
268
+ background 120ms ease !important;
269
+ }
270
+ html[data-ck-chrome="neobrutalism"] button[aria-pressed]:hover {
271
+ transform: translate(2px, 2px);
272
+ box-shadow: 2px 2px 0 0 var(--neobrut-ink) !important;
273
+ }
274
+ html[data-ck-chrome="neobrutalism"] button[aria-pressed="true"] {
275
+ background: var(--ck-accent) !important;
276
+ color: #000 !important;
277
+ }
278
+ html[data-ck-chrome="neobrutalism"] button[aria-pressed="true"] * {
279
+ color: #000 !important;
280
+ }
281
+
282
+ /* ===== Marquee animation ==================================== */
283
+
284
+ @keyframes ck-neobrut-marquee {
285
+ from {
286
+ transform: translateX(0);
287
+ }
288
+ to {
289
+ transform: translateX(-50%);
290
+ }
291
+ }
292
+
293
+ /* ===== Toggle / Checkbox visual touch ======================== */
294
+
295
+ html[data-ck-chrome="neobrutalism"] [role="checkbox"],
296
+ html[data-ck-chrome="neobrutalism"] [role="switch"] {
297
+ border-width: 2px !important;
298
+ border-color: var(--neobrut-ink) !important;
299
+ border-radius: 4px;
300
+ }
301
+ html[data-ck-chrome="neobrutalism"] [role="switch"] {
302
+ border-radius: 999px;
303
+ }
304
+
305
+ @media (prefers-reduced-motion: reduce) {
306
+ html[data-ck-chrome="neobrutalism"] .ck-btn,
307
+ html[data-ck-chrome="neobrutalism"] .ck-actionbar-btn {
308
+ transition: none;
309
+ }
310
+ html[data-ck-chrome="neobrutalism"] .ck-btn:hover:not(:disabled),
311
+ html[data-ck-chrome="neobrutalism"] .ck-actionbar-btn:hover:not(:disabled) {
312
+ transform: none;
313
+ box-shadow: 4px 4px 0 0 var(--neobrut-ink);
314
+ }
315
+ }