astralkit 0.3.0 → 0.3.2

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.
@@ -1,543 +1,543 @@
1
- /* ══════════════════════════════════════════════════════════
2
- AstralKit — Component CSS & Primitives
3
-
4
- Tokens live in astralkit-theme.css (v3/:root) or
5
- astralkit-theme-v4.css (v4/@theme). This file contains
6
- only base resets, component primitives, and utility classes.
7
-
8
- All CSS is UNLAYERED. No @layer declarations.
9
- Compatible with Tailwind v3 and v4.
10
- ══════════════════════════════════════════════════════════ */
11
-
12
- /* ── Base resets (unlayered — always applies) ── */
13
- a { text-decoration: none; }
14
- html {
15
- -webkit-font-smoothing: antialiased;
16
- -moz-osx-font-smoothing: grayscale;
17
- scroll-padding-top: var(--height-ak-nav, 4.5rem);
18
- scroll-padding-bottom: var(--spacing-ak-mobile-bar, 4.5rem);
19
- }
20
-
21
- /* ══════════════════════════════════════════════════════════
22
- TOKENS are now in astralkit-theme.css (v3) or astralkit-theme-v4.css (v4).
23
- This file contains only component CSS, primitives, and base resets.
24
- ══════════════════════════════════════════════════════════ */
25
- /* ══════════════════════════════════════════════════════════
26
- COMPONENT PRIMITIVES
27
- Unlayered — source order determines cascade priority.
28
- Component dark modifiers (e.g. .ak-sidebar-panel--dark) beat
29
- [data-theme="dark"] because they come later in the file.
30
- ══════════════════════════════════════════════════════════ */
31
- @import "./primitives/focus.css";
32
- @import "./primitives/typography.css";
33
- @import "./primitives/icons.css";
34
- @import "./primitives/sidebar.css";
35
- @import "./primitives/avatar.css";
36
- @import "./primitives/navigation.css";
37
- @import "./primitives/badges.css";
38
- @import "./primitives/mobile.css";
39
- @import "./primitives/animations.css";
40
- @import "./primitives/layout.css";
41
- @import "./primitives/accounts.css";
42
- @import "./primitives/forms.css";
43
- @import "./primitives/effects.css";
44
-
45
- @keyframes ak-skeleton-shimmer {
46
- 100% { transform: translateX(100%); }
47
- }
48
-
49
- /* Note: The unlayered override block that was here (170 lines) has been
50
- removed. With @layer gone, all primitive declarations are unlayered and
51
- compete with Tailwind preflight via specificity (.class > *). */
52
-
53
- /* ══════════════════════════════════════════════════════════
54
- Neobrutalist interaction helper
55
- Apply `.ak-brutal-press` to any element that has a brutal shadow
56
- to get the signature "push into shadow" press effect:
57
- - default: 4px 4px shadow + translate(0,0)
58
- - hover: 2px 2px shadow + translate(2px,2px)
59
- - active: 0px 0px shadow + translate(4px,4px) — fully pressed
60
- Works with any --shadow-ak-brutal-* size.
61
- Respects prefers-reduced-motion via the rule below.
62
- ══════════════════════════════════════════════════════════ */
63
- .ak-brutal-press {
64
- transition: transform 0.15s ease, box-shadow 0.15s ease;
65
- }
66
- .ak-brutal-press:hover {
67
- transform: translate(2px, 2px);
68
- box-shadow: var(--shadow-ak-brutal-sm);
69
- }
70
- .ak-brutal-press:active {
71
- transform: translate(4px, 4px);
72
- box-shadow: 0 0 0 0 var(--color-ak-brutal-ink);
73
- }
74
-
75
- /* ══════════════════════════════════════════════════════════
76
- Form Primitives — Checkbox, Radio, Switch, Range, OTP
77
- Styles that require pseudo-elements, attribute selectors,
78
- vendor prefixes, or keyframes — things Tailwind can't do.
79
- Components use Tailwind for everything else (layout, spacing,
80
- colors, fonts). These are the minimal CSS escape hatches.
81
- ══════════════════════════════════════════════════════════ */
82
-
83
- /* ── Checkbox ── */
84
- .ak-check {
85
- appearance: none;
86
- width: 22px; height: 22px;
87
- border: 2px solid var(--color-ak-border-strong);
88
- border-radius: 6px;
89
- cursor: pointer; position: relative;
90
- transition: all 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
91
- flex-shrink: 0;
92
- }
93
- .ak-check:hover { border-color: var(--color-ak-primary); }
94
- .ak-check:checked {
95
- background: var(--color-ak-primary);
96
- border-color: var(--color-ak-primary);
97
- }
98
- .ak-check:checked::after {
99
- content: '';
100
- position: absolute; left: 6px; top: 2px;
101
- width: 6px; height: 11px;
102
- border: solid var(--color-ak-on-primary);
103
- border-width: 0 2.5px 2.5px 0;
104
- transform: rotate(45deg);
105
- }
106
- .ak-check:focus-visible {
107
- outline: 2px solid var(--color-ak-primary);
108
- outline-offset: 2px;
109
- }
110
- .ak-check:disabled { cursor: not-allowed; opacity: 0.5; }
111
-
112
- /* ── Radio ── */
113
- .ak-radio {
114
- appearance: none;
115
- width: 22px; height: 22px;
116
- border: 2px solid var(--color-ak-border-strong);
117
- border-radius: 50%;
118
- cursor: pointer; position: relative;
119
- transition: all 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
120
- flex-shrink: 0;
121
- background: var(--color-ak-bg);
122
- }
123
- .ak-radio:hover { border-color: var(--color-ak-primary); }
124
- .ak-radio:checked {
125
- border-color: var(--color-ak-primary);
126
- background: var(--color-ak-primary);
127
- }
128
- .ak-radio:checked::after {
129
- content: '';
130
- position: absolute; top: 50%; left: 50%;
131
- transform: translate(-50%, -50%);
132
- width: 8px; height: 8px;
133
- border-radius: 50%;
134
- background: var(--color-ak-on-primary);
135
- }
136
- .ak-radio:focus-visible {
137
- outline: 2px solid var(--color-ak-primary);
138
- outline-offset: 2px;
139
- }
140
- .ak-radio:disabled { cursor: not-allowed; opacity: 0.5; }
141
-
142
- /* ── Switch ── */
143
- .ak-switch-track {
144
- position: relative; width: 52px; height: 28px;
145
- background: var(--color-ak-border-strong);
146
- border-radius: 9999px;
147
- transition: background-color 0.2s;
148
- }
149
- .ak-switch[aria-checked="true"] .ak-switch-track {
150
- background: var(--color-ak-primary);
151
- }
152
- .ak-switch-knob {
153
- position: absolute; top: 3px; left: 3px;
154
- width: 22px; height: 22px;
155
- background: var(--color-ak-on-primary);
156
- border-radius: 50%;
157
- transition: transform 0.2s;
158
- }
159
- .ak-switch[aria-checked="true"] .ak-switch-knob {
160
- transform: translateX(24px);
161
- }
162
- .ak-switch:focus-visible .ak-switch-track {
163
- outline: 2px solid var(--color-ak-primary);
164
- outline-offset: 2px;
165
- }
166
- /* Size: Small */
167
- .ak-switch-sm .ak-switch-track { width: 44px; height: 24px; }
168
- .ak-switch-sm .ak-switch-knob { width: 18px; height: 18px; }
169
- .ak-switch-sm[aria-checked="true"] .ak-switch-knob { transform: translateX(20px); }
170
- /* Size: Large */
171
- .ak-switch-lg .ak-switch-track { width: 64px; height: 34px; }
172
- .ak-switch-lg .ak-switch-knob { width: 28px; height: 28px; }
173
- .ak-switch-lg[aria-checked="true"] .ak-switch-knob { transform: translateX(30px); }
174
-
175
- /* Color tracks */
176
- .ak-switch-success[aria-checked="true"] .ak-switch-track { background: var(--color-ak-success); }
177
- .ak-switch-danger[aria-checked="true"] .ak-switch-track { background: var(--color-ak-danger); }
178
-
179
- /* Icon switch — default (72×36)
180
- Track icons are absolutely positioned at left/right edges.
181
- Knob is absolute and slides over them. Knob icon shows the active state icon. */
182
- .ak-switch-with-icons .ak-switch-track { width: 72px; height: 36px; }
183
- .ak-switch-with-icons .ak-switch-knob {
184
- width: 30px; height: 30px; z-index: 2;
185
- display: flex; align-items: center; justify-content: center;
186
- }
187
- .ak-switch-with-icons[aria-checked="true"] .ak-switch-knob { transform: translateX(36px); }
188
- /* Track icons — absolute, centered vertically at left/right */
189
- .ak-switch-track-icon {
190
- position: absolute; top: 50%; transform: translateY(-50%);
191
- z-index: 1; line-height: 1; font-size: 14px;
192
- display: flex; align-items: center; justify-content: center;
193
- transition: opacity 0.2s;
194
- }
195
- .ak-switch-track-icon:first-child { left: 10px; }
196
- .ak-switch-track-icon:last-child { right: 10px; }
197
- /* Off state: left icon hidden (behind knob), right icon visible */
198
- .ak-switch-with-icons .ak-switch-track-icon:first-child { opacity: 0; }
199
- .ak-switch-with-icons .ak-switch-track-icon:last-child { color: var(--color-ak-on-primary); opacity: 0.7; }
200
- /* On state: left icon visible, right icon hidden (behind knob) */
201
- .ak-switch-with-icons[aria-checked="true"] .ak-switch-track-icon:first-child { color: var(--color-ak-on-primary); opacity: 0.7; }
202
- .ak-switch-with-icons[aria-checked="true"] .ak-switch-track-icon:last-child { opacity: 0; }
203
- /* Knob icon */
204
- .ak-switch-knob-icon { font-size: 14px; color: var(--color-ak-text); line-height: 1; }
205
-
206
- /* Icon switch — lg (88×44) */
207
- .ak-switch-icons-lg .ak-switch-track { width: 88px; height: 44px; }
208
- .ak-switch-icons-lg .ak-switch-knob { width: 38px; height: 38px; }
209
- .ak-switch-icons-lg[aria-checked="true"] .ak-switch-knob { transform: translateX(44px); }
210
- .ak-switch-icons-lg .ak-switch-track-icon:first-child { left: 12px; }
211
- .ak-switch-icons-lg .ak-switch-track-icon:last-child { right: 12px; }
212
- .ak-switch-icons-lg .ak-switch-track-icon,
213
- .ak-switch-icons-lg .ak-switch-knob-icon { font-size: 18px; }
214
- /* Icon switch — xl (104×52) */
215
- .ak-switch-icons-xl .ak-switch-track { width: 104px; height: 52px; }
216
- .ak-switch-icons-xl .ak-switch-knob { width: 46px; height: 46px; }
217
- .ak-switch-icons-xl[aria-checked="true"] .ak-switch-knob { transform: translateX(52px); }
218
- .ak-switch-icons-xl .ak-switch-track-icon:first-child { left: 14px; }
219
- .ak-switch-icons-xl .ak-switch-track-icon:last-child { right: 14px; }
220
- .ak-switch-icons-xl .ak-switch-track-icon,
221
- .ak-switch-icons-xl .ak-switch-knob-icon { font-size: 22px; }
222
- /* Icon switch — xxl (120×60) */
223
- .ak-switch-icons-xxl .ak-switch-track { width: 120px; height: 60px; }
224
- .ak-switch-icons-xxl .ak-switch-knob { width: 54px; height: 54px; }
225
- .ak-switch-icons-xxl[aria-checked="true"] .ak-switch-knob { transform: translateX(60px); }
226
- .ak-switch-icons-xxl .ak-switch-track-icon:first-child { left: 16px; }
227
- .ak-switch-icons-xxl .ak-switch-track-icon:last-child { right: 16px; }
228
- .ak-switch-icons-xxl .ak-switch-track-icon,
229
- .ak-switch-icons-xxl .ak-switch-knob-icon { font-size: 26px; }
230
-
231
- /* Reversed field (switch left, label right) */
232
- .ak-switch-field-reversed { flex-direction: row-reverse; justify-content: flex-end; }
233
- /* Status text beside switch */
234
- .ak-switch-status { font-size: var(--text-ak-fl-base); font-weight: 600; color: var(--color-ak-text-muted); min-width: 24px; }
235
-
236
- @media (prefers-reduced-motion: reduce) {
237
- .ak-switch-track, .ak-switch-knob, .ak-switch-track-icon { transition: none; }
238
- }
239
-
240
- /* ── Range Slider ── */
241
- .ak-range input[type="range"] {
242
- --range-track: var(--color-ak-border);
243
- --range-fill: var(--color-ak-text);
244
- -webkit-appearance: none; appearance: none;
245
- width: 100%; height: 3rem;
246
- background: transparent; cursor: pointer;
247
- margin: 0; padding: 0;
248
- }
249
- .ak-range input[type="range"]::-webkit-slider-runnable-track {
250
- height: 6px; border-radius: 999px;
251
- background: linear-gradient(to right, var(--range-fill) var(--ak-fill, 0%), var(--range-track) var(--ak-fill, 0%));
252
- }
253
- .ak-range input[type="range"]::-webkit-slider-thumb {
254
- -webkit-appearance: none; appearance: none;
255
- width: 1.5rem; height: 1.5rem; margin-top: -0.5625rem;
256
- border: 4px solid var(--color-ak-text); border-radius: 999px;
257
- background: var(--color-ak-bg);
258
- transition: transform 0.15s ease, box-shadow 0.15s ease;
259
- box-shadow: 0 1px 3px rgba(0,0,0,0.12);
260
- }
261
- .ak-range input[type="range"]::-moz-range-track {
262
- height: 6px; border-radius: 999px;
263
- background: var(--range-track);
264
- }
265
- .ak-range input[type="range"]::-moz-range-progress {
266
- height: 6px; border-radius: 999px;
267
- background: var(--range-fill);
268
- }
269
- .ak-range input[type="range"]::-moz-range-thumb {
270
- width: 1rem; height: 1rem;
271
- border: 4px solid var(--color-ak-text); border-radius: 999px;
272
- background: var(--color-ak-bg);
273
- transition: transform 0.15s ease;
274
- box-shadow: 0 1px 3px rgba(0,0,0,0.12);
275
- }
276
- .ak-range input[type="range"]:hover::-webkit-slider-thumb { transform: scale(1.15); }
277
- .ak-range input[type="range"]:hover::-moz-range-thumb { transform: scale(1.15); }
278
- .ak-range input[type="range"]:focus-visible { outline: none; }
279
- .ak-range input[type="range"]:focus-visible::-webkit-slider-thumb {
280
- box-shadow: 0 0 0 4px var(--color-ak-bg), 0 0 0 7px var(--color-ak-primary);
281
- transform: scale(1.15);
282
- }
283
- .ak-range input[type="range"]:focus-visible::-moz-range-thumb {
284
- box-shadow: 0 0 0 4px var(--color-ak-bg), 0 0 0 7px var(--color-ak-primary);
285
- transform: scale(1.15);
286
- }
287
-
288
- /* ── Range Dual Track ── */
289
- .ak-dual-track { pointer-events: none; position: absolute; left: 0; right: 0; height: 6px; border-radius: 999px; background: var(--color-ak-border); z-index: 1; }
290
- .ak-dual-fill { position: absolute; height: 100%; border-radius: 999px; background: var(--color-ak-text); z-index: 0; }
291
- .ak-dual-input { pointer-events: none; position: absolute; left: 0; width: 100%; height: 3rem; background: transparent; z-index: 3; }
292
- .ak-dual-input::-webkit-slider-runnable-track { height: 6px; background: transparent !important; }
293
- .ak-dual-input::-webkit-slider-thumb { pointer-events: auto; position: relative; z-index: 10; }
294
- .ak-dual-input::-moz-range-track, .ak-dual-input::-moz-range-progress { background: transparent !important; }
295
- .ak-dual-input::-moz-range-thumb { pointer-events: auto; position: relative; z-index: 10; }
296
-
297
- /* ── Number Input Spinbutton Hide ── */
298
- .ak-stepper input,
299
- .ak-qty input,
300
- .ak-range input[type="number"] {
301
- -moz-appearance: textfield; appearance: textfield;
302
- }
303
- .ak-stepper input::-webkit-outer-spin-button,
304
- .ak-stepper input::-webkit-inner-spin-button,
305
- .ak-qty input::-webkit-outer-spin-button,
306
- .ak-qty input::-webkit-inner-spin-button,
307
- .ak-range input[type="number"]::-webkit-outer-spin-button,
308
- .ak-range input[type="number"]::-webkit-inner-spin-button {
309
- -webkit-appearance: none; margin: 0;
310
- }
311
-
312
- /* ── OTP Input ── */
313
- .ak-otp-input {
314
- width: 56px; height: 64px; text-align: center;
315
- font-size: var(--text-ak-2xl); font-weight: 700;
316
- border: 2px solid var(--color-ak-border); border-radius: 0.75rem;
317
- outline: none; background: var(--color-ak-bg); color: var(--color-ak-text);
318
- transition: border-color 0.15s ease, background-color 0.15s ease;
319
- caret-color: var(--color-ak-primary);
320
- }
321
- .ak-otp-input::placeholder { color: var(--color-ak-text-muted); }
322
- .ak-otp-input:hover { border-color: var(--color-ak-border-strong); }
323
- .ak-otp-input:focus-visible {
324
- outline: 2px solid var(--color-ak-primary);
325
- outline-offset: 2px;
326
- border-color: var(--color-ak-primary);
327
- background: var(--color-ak-surface);
328
- }
329
- .ak-otp-input.has-value { border-color: var(--color-ak-text); font-weight: 800; }
330
- @media (max-width: 400px) {
331
- .ak-otp-input { width: 44px; height: 52px; font-size: var(--text-ak-xl); }
332
- }
333
-
334
- /* ── Color Picker Swatch ── */
335
- .ak-color-swatch:hover { border-color: var(--color-ak-border-strong); }
336
- .ak-color-swatch:active { transform: scale(0.95); transition-duration: 0.1s; }
337
- .ak-color-swatch.selected { border-color: var(--color-ak-text); }
338
-
339
- /* ── File Upload ── */
340
- @keyframes ak-spin { to { transform: rotate(360deg); } }
341
- .ak-spinner { animation: ak-spin 0.8s linear infinite; }
342
- .ak-dropzone { transition: border-color 0.2s ease, background-color 0.2s ease; }
343
- .ak-dropzone:hover { border-color: var(--color-ak-border-strong); background: var(--color-ak-hover); }
344
- .ak-dropzone.drag-over { border-color: var(--color-ak-primary); background: var(--color-ak-primary-subtle); }
345
- .ak-file-row { transition: background-color 0.15s ease, border-color 0.15s ease; }
346
- .ak-file-row:hover { background: var(--color-ak-hover); border-color: var(--color-ak-border-strong); }
347
- .ak-progress-fill { transition: width 0.3s ease; }
348
-
349
- /* ── Star Rating ── */
350
- .ak-star-btn {
351
- display: inline-flex; align-items: center; justify-content: center;
352
- width: 48px; height: 48px; cursor: pointer;
353
- border: none; background: none; padding: 0;
354
- border-radius: 8px;
355
- color: var(--color-ak-text-disabled);
356
- transition: color 0.15s, transform 0.15s;
357
- }
358
- .ak-star-btn.filled { color: var(--color-ak-text); }
359
- .ak-star-btn:hover { transform: scale(1.1); }
360
- .ak-star-btn:focus-visible { outline: 2px solid var(--color-ak-primary); outline-offset: 2px; }
361
- .ak-star-btn.ak-star-sm { width: 40px; height: 40px; }
362
- .ak-star-btn.ak-star-sm .ak-star-icon { font-size: 20px; }
363
- .ak-star-icon { font-size: 28px; }
364
- .ak-star-btn.ak-star-lg { width: 56px; height: 56px; }
365
- .ak-star-btn.ak-star-lg .ak-star-icon { font-size: 36px; }
366
-
367
- /* ── Switch Layout ── */
368
- .ak-switch {
369
- display: inline-flex; align-items: center; justify-content: center;
370
- background: none; border: none; padding: 8px 0; cursor: pointer;
371
- border-radius: 9999px; flex-shrink: 0; min-height: 44px;
372
- }
373
- .ak-switch:focus { outline: none; }
374
- .ak-switch:disabled, .ak-switch[aria-disabled="true"] { opacity: 0.5; cursor: not-allowed; }
375
- .ak-switch-field {
376
- display: flex; align-items: center; justify-content: space-between;
377
- gap: 16px; min-height: 52px;
378
- }
379
- .ak-switch-label-wrap { display: flex; flex-direction: column; gap: 4px; cursor: pointer; flex: 1; min-width: 0; }
380
- .ak-switch-field:has(.ak-switch:disabled) .ak-switch-label-wrap,
381
- .ak-switch-field:has(.ak-switch[aria-disabled="true"]) .ak-switch-label-wrap { cursor: default; }
382
- /* When icon is present, use grid so icon spans full height and text+helper align */
383
- .ak-switch-label-wrap:has(.ak-switch-label-icon) {
384
- display: grid;
385
- grid-template-columns: 2.75rem 1fr;
386
- grid-template-rows: auto auto;
387
- column-gap: 14px;
388
- row-gap: 2px;
389
- align-items: center;
390
- }
391
- .ak-switch-label-wrap:has(.ak-switch-label-icon) .ak-switch-label-icon {
392
- grid-column: 1;
393
- grid-row: 1 / -1;
394
- align-self: center;
395
- }
396
- .ak-switch-label-wrap:has(.ak-switch-label-icon) .ak-switch-label {
397
- grid-column: 2;
398
- grid-row: 1;
399
- }
400
- .ak-switch-label-wrap:has(.ak-switch-label-icon) .ak-switch-helper {
401
- grid-column: 2;
402
- grid-row: 2;
403
- }
404
- .ak-switch-label {
405
- font-size: var(--text-ak-fl-lg); font-weight: 700; color: var(--color-ak-text);
406
- }
407
- .ak-switch-helper { font-size: var(--text-ak-fl-base); color: var(--color-ak-text-secondary); }
408
- .ak-switch-label-icon {
409
- font-size: 1.5rem; color: var(--color-ak-text-secondary); line-height: 1; flex-shrink: 0;
410
- width: 2.75rem; height: 2.75rem;
411
- display: flex; align-items: center; justify-content: center;
412
- background: var(--color-ak-surface); border-radius: 0.75rem;
413
- }
414
- .ak-switch-card {
415
- border: 2px solid var(--color-ak-border); border-radius: 0.75rem;
416
- padding: 20px 24px; transition: border-color 0.2s;
417
- }
418
- .ak-switch-card-active {
419
- border-color: var(--color-ak-primary); background: var(--color-ak-primary-subtle);
420
- }
421
- .ak-switch-compact .ak-switch-field { padding: 16px 0; }
422
- .ak-switch-compact .ak-switch-field + .ak-switch-field { border-top: 1px solid var(--color-ak-border); }
423
- .ak-switch-compact .ak-switch-label { font-size: var(--text-ak-fl-base); }
424
- .ak-switch-compact .ak-switch-helper { font-size: var(--text-ak-fl-sm); }
425
- .ak-switch-value { font-size: var(--text-ak-fl-base); font-weight: 600; color: var(--color-ak-text); min-width: 32px; text-align: right; }
426
- .ak-switch-value-muted { color: var(--color-ak-text-secondary); font-weight: 400; }
427
- .ak-switch-group { border: none; padding: 0; margin: 0; }
428
- .ak-switch-group-legend { font-size: var(--text-ak-fl-base); font-weight: 700; color: var(--color-ak-text-secondary); padding: 0; margin-bottom: 16px; text-transform: uppercase; letter-spacing: 0.05em; }
429
- .ak-switch-section { border: 2px solid var(--color-ak-border); border-radius: 0.75rem; padding: 24px; }
430
- .ak-switch-section .ak-switch-group-legend { font-size: var(--text-ak-fl-lg); margin-bottom: 16px; padding: 0 8px; text-transform: none; letter-spacing: normal; }
431
- .ak-switch-section .ak-switch-field + .ak-switch-field {
432
- border-top: 1px solid var(--color-ak-border-subtle); padding-top: 16px; margin-top: 16px;
433
- }
434
- .ak-form-section { max-width: 640px; }
435
-
436
- /* ── Number Stepper Button Press ── */
437
- .ak-stepper-btn:active:not([aria-disabled="true"]) {
438
- transform: translate(2px, 2px);
439
- box-shadow: 2px 2px 0 0 var(--color-ak-brutal-ink) !important;
440
- }
441
- .ak-stepper-btn[aria-disabled="true"] { pointer-events: none; opacity: 0.3; }
442
-
443
- /* ── Quantity Selector ── */
444
- .ak-qty-btn { transition: all 0.15s ease; }
445
- .ak-qty-btn:active:not([aria-disabled="true"]) { transform: scale(0.96); }
446
- .ak-qty-btn[aria-disabled="true"] { opacity: 0.3; cursor: not-allowed; }
447
-
448
- /* ── Shared Keyframes ── */
449
- @keyframes ak-fadeInUp {
450
- from { opacity: 0; transform: translateY(8px); }
451
- to { opacity: 1; transform: translateY(0); }
452
- }
453
- @keyframes ak-slideIn {
454
- from { opacity: 0; transform: translateY(-8px) scale(0.98); }
455
- to { opacity: 1; transform: translateY(0) scale(1); }
456
- }
457
- @keyframes ak-fadeOut {
458
- from { opacity: 1; transform: translateY(0) scale(1); }
459
- to { opacity: 0; transform: translateY(-8px) scale(0.98); }
460
- }
461
- @keyframes ak-swipeOut {
462
- from { transform: translateX(var(--radix-toast-swipe-end-x)); }
463
- to { transform: translateX(100%); }
464
- }
465
-
466
- /* ── Glass Panel (split-screen logins) ── */
467
- .ak-glass-panel {
468
- background: rgba(255, 255, 255, 0.03);
469
- backdrop-filter: blur(12px);
470
- -webkit-backdrop-filter: blur(12px);
471
- border: 1px solid rgba(255, 255, 255, 0.1);
472
- }
473
-
474
- /* ── Grid Pattern Background ── */
475
- .ak-bg-grid-pattern {
476
- background-image: linear-gradient(to right, rgba(255,255,255,0.06) 1px, transparent 1px),
477
- linear-gradient(to bottom, rgba(255,255,255,0.06) 1px, transparent 1px);
478
- background-size: 40px 40px;
479
- }
480
-
481
- /* ── Toggle Group ── */
482
- .ak-toggle-group {
483
- display: inline-flex; background: var(--color-ak-surface-2);
484
- border-radius: 8px; padding: 4px; gap: 4px;
485
- }
486
- .ak-toggle-group-item {
487
- display: inline-flex; align-items: center; justify-content: center; gap: 6px;
488
- background: none; border: none; padding: 0 16px; min-height: 44px;
489
- font-family: inherit; font-size: var(--text-ak-base, 1rem); font-weight: 600;
490
- color: var(--color-ak-text-secondary); border-radius: 8px; cursor: pointer;
491
- transition: background-color 0.2s, color 0.2s; white-space: nowrap; line-height: 1;
492
- }
493
- .ak-toggle-group-item[aria-checked="true"],
494
- .ak-toggle-group-item[aria-pressed="true"] {
495
- background: var(--color-ak-bg); color: var(--color-ak-text);
496
- }
497
- .ak-toggle-group-item[aria-checked="false"]:not(:disabled):hover,
498
- .ak-toggle-group-item[aria-pressed="false"]:not(:disabled):hover {
499
- color: var(--color-ak-text); background: var(--color-ak-hover);
500
- }
501
- .ak-toggle-group-item:focus { outline: none; }
502
- .ak-toggle-group-item:focus-visible { outline: 2px solid var(--color-ak-primary); outline-offset: 2px; }
503
- .ak-toggle-group-item:disabled { opacity: 0.4; cursor: not-allowed; }
504
- .ak-toggle-group[aria-disabled="true"] { opacity: 0.5; }
505
- .ak-toggle-group[aria-disabled="true"] .ak-toggle-group-item { cursor: not-allowed; }
506
- .ak-toggle-group-item i { font-size: 20px; line-height: 1; }
507
- .ak-toggle-group-item-icon { padding: 0 14px; }
508
- /* Toggle group — small */
509
- .ak-toggle-group-sm { padding: 3px; gap: 3px; }
510
- .ak-toggle-group-sm .ak-toggle-group-item { min-height: 44px; padding: 0 12px; font-size: var(--text-ak-sm, 0.875rem); }
511
- .ak-toggle-group-sm .ak-toggle-group-item i { font-size: 18px; }
512
- .ak-toggle-group-sm .ak-toggle-group-item-icon { padding: 0 12px; }
513
- /* Toggle group — large */
514
- .ak-toggle-group-lg { padding: 5px; gap: 5px; }
515
- .ak-toggle-group-lg .ak-toggle-group-item { min-height: 52px; padding: 0 24px; font-size: var(--text-ak-lg, 1.125rem); }
516
- .ak-toggle-group-lg .ak-toggle-group-item i { font-size: 24px; }
517
- .ak-toggle-group-lg .ak-toggle-group-item-icon { padding: 0 18px; }
518
-
519
- /* ── Resizable Panel Cursors ── */
520
- body.ak-col-resizing, body.ak-col-resizing * {
521
- cursor: col-resize !important; user-select: none !important; -webkit-user-select: none !important;
522
- }
523
- body.ak-ew-resizing, body.ak-ew-resizing * {
524
- cursor: ew-resize !important; user-select: none !important; -webkit-user-select: none !important;
525
- }
526
-
527
- /* ── Focus Ring Utility ── */
528
- .ak-focus-ring:focus-visible { outline: 2px solid var(--color-ak-primary); outline-offset: 2px; }
529
-
530
- /* ── Price Fade Transition ── */
531
- .ak-price-fade { transition: opacity 0.15s ease-in-out; }
532
-
533
- /* Reduced motion — unlayered so it overrides everything */
534
- @media (prefers-reduced-motion: reduce) {
535
- *, *::before, *::after {
536
- animation-duration: 0.01ms !important;
537
- transition-duration: 0.01ms !important;
538
- }
539
- .ak-star-btn:hover { transform: none !important; }
540
- .ak-stepper-btn:active { transform: none !important; }
541
- @keyframes ak-slideIn { from { opacity: 0; } to { opacity: 1; } }
542
- @keyframes ak-fadeOut { from { opacity: 1; } to { opacity: 0; } }
543
- }
1
+ /* ══════════════════════════════════════════════════════════
2
+ AstralKit — Component CSS & Primitives
3
+
4
+ Tokens live in astralkit-theme.css (v3/:root) or
5
+ astralkit-theme-v4.css (v4/@theme). This file contains
6
+ only base resets, component primitives, and utility classes.
7
+
8
+ All CSS is UNLAYERED. No @layer declarations.
9
+ Compatible with Tailwind v3 and v4.
10
+ ══════════════════════════════════════════════════════════ */
11
+
12
+ /* ── Base resets (unlayered — always applies) ── */
13
+ a { text-decoration: none; }
14
+ html {
15
+ -webkit-font-smoothing: antialiased;
16
+ -moz-osx-font-smoothing: grayscale;
17
+ scroll-padding-top: var(--height-ak-nav, 4.5rem);
18
+ scroll-padding-bottom: var(--spacing-ak-mobile-bar, 4.5rem);
19
+ }
20
+
21
+ /* ══════════════════════════════════════════════════════════
22
+ TOKENS are now in astralkit-theme.css (v3) or astralkit-theme-v4.css (v4).
23
+ This file contains only component CSS, primitives, and base resets.
24
+ ══════════════════════════════════════════════════════════ */
25
+ /* ══════════════════════════════════════════════════════════
26
+ COMPONENT PRIMITIVES
27
+ Unlayered — source order determines cascade priority.
28
+ Component dark modifiers (e.g. .ak-sidebar-panel--dark) beat
29
+ [data-theme="dark"] because they come later in the file.
30
+ ══════════════════════════════════════════════════════════ */
31
+ @import "./primitives/focus.css";
32
+ @import "./primitives/typography.css";
33
+ @import "./primitives/icons.css";
34
+ @import "./primitives/sidebar.css";
35
+ @import "./primitives/avatar.css";
36
+ @import "./primitives/navigation.css";
37
+ @import "./primitives/badges.css";
38
+ @import "./primitives/mobile.css";
39
+ @import "./primitives/animations.css";
40
+ @import "./primitives/layout.css";
41
+ @import "./primitives/accounts.css";
42
+ @import "./primitives/forms.css";
43
+ @import "./primitives/effects.css";
44
+
45
+ @keyframes ak-skeleton-shimmer {
46
+ 100% { transform: translateX(100%); }
47
+ }
48
+
49
+ /* Note: The unlayered override block that was here (170 lines) has been
50
+ removed. With @layer gone, all primitive declarations are unlayered and
51
+ compete with Tailwind preflight via specificity (.class > *). */
52
+
53
+ /* ══════════════════════════════════════════════════════════
54
+ Neobrutalist interaction helper
55
+ Apply `.ak-brutal-press` to any element that has a brutal shadow
56
+ to get the signature "push into shadow" press effect:
57
+ - default: 4px 4px shadow + translate(0,0)
58
+ - hover: 2px 2px shadow + translate(2px,2px)
59
+ - active: 0px 0px shadow + translate(4px,4px) — fully pressed
60
+ Works with any --shadow-ak-brutal-* size.
61
+ Respects prefers-reduced-motion via the rule below.
62
+ ══════════════════════════════════════════════════════════ */
63
+ .ak-brutal-press {
64
+ transition: transform 0.15s ease, box-shadow 0.15s ease;
65
+ }
66
+ .ak-brutal-press:hover {
67
+ transform: translate(2px, 2px);
68
+ box-shadow: var(--shadow-ak-brutal-sm);
69
+ }
70
+ .ak-brutal-press:active {
71
+ transform: translate(4px, 4px);
72
+ box-shadow: 0 0 0 0 var(--color-ak-brutal-ink);
73
+ }
74
+
75
+ /* ══════════════════════════════════════════════════════════
76
+ Form Primitives — Checkbox, Radio, Switch, Range, OTP
77
+ Styles that require pseudo-elements, attribute selectors,
78
+ vendor prefixes, or keyframes — things Tailwind can't do.
79
+ Components use Tailwind for everything else (layout, spacing,
80
+ colors, fonts). These are the minimal CSS escape hatches.
81
+ ══════════════════════════════════════════════════════════ */
82
+
83
+ /* ── Checkbox ── */
84
+ .ak-check {
85
+ appearance: none;
86
+ width: 22px; height: 22px;
87
+ border: 2px solid var(--color-ak-border-strong);
88
+ border-radius: 6px;
89
+ cursor: pointer; position: relative;
90
+ transition: all 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
91
+ flex-shrink: 0;
92
+ }
93
+ .ak-check:hover { border-color: var(--color-ak-primary); }
94
+ .ak-check:checked {
95
+ background: var(--color-ak-primary);
96
+ border-color: var(--color-ak-primary);
97
+ }
98
+ .ak-check:checked::after {
99
+ content: '';
100
+ position: absolute; left: 6px; top: 2px;
101
+ width: 6px; height: 11px;
102
+ border: solid var(--color-ak-on-primary);
103
+ border-width: 0 2.5px 2.5px 0;
104
+ transform: rotate(45deg);
105
+ }
106
+ .ak-check:focus-visible {
107
+ outline: 2px solid var(--color-ak-primary);
108
+ outline-offset: 2px;
109
+ }
110
+ .ak-check:disabled { cursor: not-allowed; opacity: 0.5; }
111
+
112
+ /* ── Radio ── */
113
+ .ak-radio {
114
+ appearance: none;
115
+ width: 22px; height: 22px;
116
+ border: 2px solid var(--color-ak-border-strong);
117
+ border-radius: 50%;
118
+ cursor: pointer; position: relative;
119
+ transition: all 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
120
+ flex-shrink: 0;
121
+ background: var(--color-ak-bg);
122
+ }
123
+ .ak-radio:hover { border-color: var(--color-ak-primary); }
124
+ .ak-radio:checked {
125
+ border-color: var(--color-ak-primary);
126
+ background: var(--color-ak-primary);
127
+ }
128
+ .ak-radio:checked::after {
129
+ content: '';
130
+ position: absolute; top: 50%; left: 50%;
131
+ transform: translate(-50%, -50%);
132
+ width: 8px; height: 8px;
133
+ border-radius: 50%;
134
+ background: var(--color-ak-on-primary);
135
+ }
136
+ .ak-radio:focus-visible {
137
+ outline: 2px solid var(--color-ak-primary);
138
+ outline-offset: 2px;
139
+ }
140
+ .ak-radio:disabled { cursor: not-allowed; opacity: 0.5; }
141
+
142
+ /* ── Switch ── */
143
+ .ak-switch-track {
144
+ position: relative; width: 52px; height: 28px;
145
+ background: var(--color-ak-border-strong);
146
+ border-radius: 9999px;
147
+ transition: background-color 0.2s;
148
+ }
149
+ .ak-switch[aria-checked="true"] .ak-switch-track {
150
+ background: var(--color-ak-primary);
151
+ }
152
+ .ak-switch-knob {
153
+ position: absolute; top: 3px; left: 3px;
154
+ width: 22px; height: 22px;
155
+ background: var(--color-ak-on-primary);
156
+ border-radius: 50%;
157
+ transition: transform 0.2s;
158
+ }
159
+ .ak-switch[aria-checked="true"] .ak-switch-knob {
160
+ transform: translateX(24px);
161
+ }
162
+ .ak-switch:focus-visible .ak-switch-track {
163
+ outline: 2px solid var(--color-ak-primary);
164
+ outline-offset: 2px;
165
+ }
166
+ /* Size: Small */
167
+ .ak-switch-sm .ak-switch-track { width: 44px; height: 24px; }
168
+ .ak-switch-sm .ak-switch-knob { width: 18px; height: 18px; }
169
+ .ak-switch-sm[aria-checked="true"] .ak-switch-knob { transform: translateX(20px); }
170
+ /* Size: Large */
171
+ .ak-switch-lg .ak-switch-track { width: 64px; height: 34px; }
172
+ .ak-switch-lg .ak-switch-knob { width: 28px; height: 28px; }
173
+ .ak-switch-lg[aria-checked="true"] .ak-switch-knob { transform: translateX(30px); }
174
+
175
+ /* Color tracks */
176
+ .ak-switch-success[aria-checked="true"] .ak-switch-track { background: var(--color-ak-success); }
177
+ .ak-switch-danger[aria-checked="true"] .ak-switch-track { background: var(--color-ak-danger); }
178
+
179
+ /* Icon switch — default (72×36)
180
+ Track icons are absolutely positioned at left/right edges.
181
+ Knob is absolute and slides over them. Knob icon shows the active state icon. */
182
+ .ak-switch-with-icons .ak-switch-track { width: 72px; height: 36px; }
183
+ .ak-switch-with-icons .ak-switch-knob {
184
+ width: 30px; height: 30px; z-index: 2;
185
+ display: flex; align-items: center; justify-content: center;
186
+ }
187
+ .ak-switch-with-icons[aria-checked="true"] .ak-switch-knob { transform: translateX(36px); }
188
+ /* Track icons — absolute, centered vertically at left/right */
189
+ .ak-switch-track-icon {
190
+ position: absolute; top: 50%; transform: translateY(-50%);
191
+ z-index: 1; line-height: 1; font-size: 14px;
192
+ display: flex; align-items: center; justify-content: center;
193
+ transition: opacity 0.2s;
194
+ }
195
+ .ak-switch-track-icon:first-child { left: 10px; }
196
+ .ak-switch-track-icon:last-child { right: 10px; }
197
+ /* Off state: left icon hidden (behind knob), right icon visible */
198
+ .ak-switch-with-icons .ak-switch-track-icon:first-child { opacity: 0; }
199
+ .ak-switch-with-icons .ak-switch-track-icon:last-child { color: var(--color-ak-on-primary); opacity: 0.7; }
200
+ /* On state: left icon visible, right icon hidden (behind knob) */
201
+ .ak-switch-with-icons[aria-checked="true"] .ak-switch-track-icon:first-child { color: var(--color-ak-on-primary); opacity: 0.7; }
202
+ .ak-switch-with-icons[aria-checked="true"] .ak-switch-track-icon:last-child { opacity: 0; }
203
+ /* Knob icon */
204
+ .ak-switch-knob-icon { font-size: 14px; color: var(--color-ak-text); line-height: 1; }
205
+
206
+ /* Icon switch — lg (88×44) */
207
+ .ak-switch-icons-lg .ak-switch-track { width: 88px; height: 44px; }
208
+ .ak-switch-icons-lg .ak-switch-knob { width: 38px; height: 38px; }
209
+ .ak-switch-icons-lg[aria-checked="true"] .ak-switch-knob { transform: translateX(44px); }
210
+ .ak-switch-icons-lg .ak-switch-track-icon:first-child { left: 12px; }
211
+ .ak-switch-icons-lg .ak-switch-track-icon:last-child { right: 12px; }
212
+ .ak-switch-icons-lg .ak-switch-track-icon,
213
+ .ak-switch-icons-lg .ak-switch-knob-icon { font-size: 18px; }
214
+ /* Icon switch — xl (104×52) */
215
+ .ak-switch-icons-xl .ak-switch-track { width: 104px; height: 52px; }
216
+ .ak-switch-icons-xl .ak-switch-knob { width: 46px; height: 46px; }
217
+ .ak-switch-icons-xl[aria-checked="true"] .ak-switch-knob { transform: translateX(52px); }
218
+ .ak-switch-icons-xl .ak-switch-track-icon:first-child { left: 14px; }
219
+ .ak-switch-icons-xl .ak-switch-track-icon:last-child { right: 14px; }
220
+ .ak-switch-icons-xl .ak-switch-track-icon,
221
+ .ak-switch-icons-xl .ak-switch-knob-icon { font-size: 22px; }
222
+ /* Icon switch — xxl (120×60) */
223
+ .ak-switch-icons-xxl .ak-switch-track { width: 120px; height: 60px; }
224
+ .ak-switch-icons-xxl .ak-switch-knob { width: 54px; height: 54px; }
225
+ .ak-switch-icons-xxl[aria-checked="true"] .ak-switch-knob { transform: translateX(60px); }
226
+ .ak-switch-icons-xxl .ak-switch-track-icon:first-child { left: 16px; }
227
+ .ak-switch-icons-xxl .ak-switch-track-icon:last-child { right: 16px; }
228
+ .ak-switch-icons-xxl .ak-switch-track-icon,
229
+ .ak-switch-icons-xxl .ak-switch-knob-icon { font-size: 26px; }
230
+
231
+ /* Reversed field (switch left, label right) */
232
+ .ak-switch-field-reversed { flex-direction: row-reverse; justify-content: flex-end; }
233
+ /* Status text beside switch */
234
+ .ak-switch-status { font-size: var(--text-ak-fl-base); font-weight: 600; color: var(--color-ak-text-muted); min-width: 24px; }
235
+
236
+ @media (prefers-reduced-motion: reduce) {
237
+ .ak-switch-track, .ak-switch-knob, .ak-switch-track-icon { transition: none; }
238
+ }
239
+
240
+ /* ── Range Slider ── */
241
+ .ak-range input[type="range"] {
242
+ --range-track: var(--color-ak-border);
243
+ --range-fill: var(--color-ak-text);
244
+ -webkit-appearance: none; appearance: none;
245
+ width: 100%; height: 3rem;
246
+ background: transparent; cursor: pointer;
247
+ margin: 0; padding: 0;
248
+ }
249
+ .ak-range input[type="range"]::-webkit-slider-runnable-track {
250
+ height: 6px; border-radius: 999px;
251
+ background: linear-gradient(to right, var(--range-fill) var(--ak-fill, 0%), var(--range-track) var(--ak-fill, 0%));
252
+ }
253
+ .ak-range input[type="range"]::-webkit-slider-thumb {
254
+ -webkit-appearance: none; appearance: none;
255
+ width: 1.5rem; height: 1.5rem; margin-top: -0.5625rem;
256
+ border: 4px solid var(--color-ak-text); border-radius: 999px;
257
+ background: var(--color-ak-bg);
258
+ transition: transform 0.15s ease, box-shadow 0.15s ease;
259
+ box-shadow: 0 1px 3px rgba(0,0,0,0.12);
260
+ }
261
+ .ak-range input[type="range"]::-moz-range-track {
262
+ height: 6px; border-radius: 999px;
263
+ background: var(--range-track);
264
+ }
265
+ .ak-range input[type="range"]::-moz-range-progress {
266
+ height: 6px; border-radius: 999px;
267
+ background: var(--range-fill);
268
+ }
269
+ .ak-range input[type="range"]::-moz-range-thumb {
270
+ width: 1rem; height: 1rem;
271
+ border: 4px solid var(--color-ak-text); border-radius: 999px;
272
+ background: var(--color-ak-bg);
273
+ transition: transform 0.15s ease;
274
+ box-shadow: 0 1px 3px rgba(0,0,0,0.12);
275
+ }
276
+ .ak-range input[type="range"]:hover::-webkit-slider-thumb { transform: scale(1.15); }
277
+ .ak-range input[type="range"]:hover::-moz-range-thumb { transform: scale(1.15); }
278
+ .ak-range input[type="range"]:focus-visible { outline: none; }
279
+ .ak-range input[type="range"]:focus-visible::-webkit-slider-thumb {
280
+ box-shadow: 0 0 0 4px var(--color-ak-bg), 0 0 0 7px var(--color-ak-primary);
281
+ transform: scale(1.15);
282
+ }
283
+ .ak-range input[type="range"]:focus-visible::-moz-range-thumb {
284
+ box-shadow: 0 0 0 4px var(--color-ak-bg), 0 0 0 7px var(--color-ak-primary);
285
+ transform: scale(1.15);
286
+ }
287
+
288
+ /* ── Range Dual Track ── */
289
+ .ak-dual-track { pointer-events: none; position: absolute; left: 0; right: 0; height: 6px; border-radius: 999px; background: var(--color-ak-border); z-index: 1; }
290
+ .ak-dual-fill { position: absolute; height: 100%; border-radius: 999px; background: var(--color-ak-text); z-index: 0; }
291
+ .ak-dual-input { pointer-events: none; position: absolute; left: 0; width: 100%; height: 3rem; background: transparent; z-index: 3; }
292
+ .ak-dual-input::-webkit-slider-runnable-track { height: 6px; background: transparent !important; }
293
+ .ak-dual-input::-webkit-slider-thumb { pointer-events: auto; position: relative; z-index: 10; }
294
+ .ak-dual-input::-moz-range-track, .ak-dual-input::-moz-range-progress { background: transparent !important; }
295
+ .ak-dual-input::-moz-range-thumb { pointer-events: auto; position: relative; z-index: 10; }
296
+
297
+ /* ── Number Input Spinbutton Hide ── */
298
+ .ak-stepper input,
299
+ .ak-qty input,
300
+ .ak-range input[type="number"] {
301
+ -moz-appearance: textfield; appearance: textfield;
302
+ }
303
+ .ak-stepper input::-webkit-outer-spin-button,
304
+ .ak-stepper input::-webkit-inner-spin-button,
305
+ .ak-qty input::-webkit-outer-spin-button,
306
+ .ak-qty input::-webkit-inner-spin-button,
307
+ .ak-range input[type="number"]::-webkit-outer-spin-button,
308
+ .ak-range input[type="number"]::-webkit-inner-spin-button {
309
+ -webkit-appearance: none; margin: 0;
310
+ }
311
+
312
+ /* ── OTP Input ── */
313
+ .ak-otp-input {
314
+ width: 56px; height: 64px; text-align: center;
315
+ font-size: var(--text-ak-2xl); font-weight: 700;
316
+ border: 2px solid var(--color-ak-border); border-radius: 0.75rem;
317
+ outline: none; background: var(--color-ak-bg); color: var(--color-ak-text);
318
+ transition: border-color 0.15s ease, background-color 0.15s ease;
319
+ caret-color: var(--color-ak-primary);
320
+ }
321
+ .ak-otp-input::placeholder { color: var(--color-ak-text-muted); }
322
+ .ak-otp-input:hover { border-color: var(--color-ak-border-strong); }
323
+ .ak-otp-input:focus-visible {
324
+ outline: 2px solid var(--color-ak-primary);
325
+ outline-offset: 2px;
326
+ border-color: var(--color-ak-primary);
327
+ background: var(--color-ak-surface);
328
+ }
329
+ .ak-otp-input.has-value { border-color: var(--color-ak-text); font-weight: 800; }
330
+ @media (max-width: 400px) {
331
+ .ak-otp-input { width: 44px; height: 52px; font-size: var(--text-ak-xl); }
332
+ }
333
+
334
+ /* ── Color Picker Swatch ── */
335
+ .ak-color-swatch:hover { border-color: var(--color-ak-border-strong); }
336
+ .ak-color-swatch:active { transform: scale(0.95); transition-duration: 0.1s; }
337
+ .ak-color-swatch.selected { border-color: var(--color-ak-text); }
338
+
339
+ /* ── File Upload ── */
340
+ @keyframes ak-spin { to { transform: rotate(360deg); } }
341
+ .ak-spinner { animation: ak-spin 0.8s linear infinite; }
342
+ .ak-dropzone { transition: border-color 0.2s ease, background-color 0.2s ease; }
343
+ .ak-dropzone:hover { border-color: var(--color-ak-border-strong); background: var(--color-ak-hover); }
344
+ .ak-dropzone.drag-over { border-color: var(--color-ak-primary); background: var(--color-ak-primary-subtle); }
345
+ .ak-file-row { transition: background-color 0.15s ease, border-color 0.15s ease; }
346
+ .ak-file-row:hover { background: var(--color-ak-hover); border-color: var(--color-ak-border-strong); }
347
+ .ak-progress-fill { transition: width 0.3s ease; }
348
+
349
+ /* ── Star Rating ── */
350
+ .ak-star-btn {
351
+ display: inline-flex; align-items: center; justify-content: center;
352
+ width: 48px; height: 48px; cursor: pointer;
353
+ border: none; background: none; padding: 0;
354
+ border-radius: 8px;
355
+ color: var(--color-ak-text-disabled);
356
+ transition: color 0.15s, transform 0.15s;
357
+ }
358
+ .ak-star-btn.filled { color: var(--color-ak-text); }
359
+ .ak-star-btn:hover { transform: scale(1.1); }
360
+ .ak-star-btn:focus-visible { outline: 2px solid var(--color-ak-primary); outline-offset: 2px; }
361
+ .ak-star-btn.ak-star-sm { width: 40px; height: 40px; }
362
+ .ak-star-btn.ak-star-sm .ak-star-icon { font-size: 20px; }
363
+ .ak-star-icon { font-size: 28px; }
364
+ .ak-star-btn.ak-star-lg { width: 56px; height: 56px; }
365
+ .ak-star-btn.ak-star-lg .ak-star-icon { font-size: 36px; }
366
+
367
+ /* ── Switch Layout ── */
368
+ .ak-switch {
369
+ display: inline-flex; align-items: center; justify-content: center;
370
+ background: none; border: none; padding: 8px 0; cursor: pointer;
371
+ border-radius: 9999px; flex-shrink: 0; min-height: 44px;
372
+ }
373
+ .ak-switch:focus { outline: none; }
374
+ .ak-switch:disabled, .ak-switch[aria-disabled="true"] { opacity: 0.5; cursor: not-allowed; }
375
+ .ak-switch-field {
376
+ display: flex; align-items: center; justify-content: space-between;
377
+ gap: 16px; min-height: 52px;
378
+ }
379
+ .ak-switch-label-wrap { display: flex; flex-direction: column; gap: 4px; cursor: pointer; flex: 1; min-width: 0; }
380
+ .ak-switch-field:has(.ak-switch:disabled) .ak-switch-label-wrap,
381
+ .ak-switch-field:has(.ak-switch[aria-disabled="true"]) .ak-switch-label-wrap { cursor: default; }
382
+ /* When icon is present, use grid so icon spans full height and text+helper align */
383
+ .ak-switch-label-wrap:has(.ak-switch-label-icon) {
384
+ display: grid;
385
+ grid-template-columns: 2.75rem 1fr;
386
+ grid-template-rows: auto auto;
387
+ column-gap: 14px;
388
+ row-gap: 2px;
389
+ align-items: center;
390
+ }
391
+ .ak-switch-label-wrap:has(.ak-switch-label-icon) .ak-switch-label-icon {
392
+ grid-column: 1;
393
+ grid-row: 1 / -1;
394
+ align-self: center;
395
+ }
396
+ .ak-switch-label-wrap:has(.ak-switch-label-icon) .ak-switch-label {
397
+ grid-column: 2;
398
+ grid-row: 1;
399
+ }
400
+ .ak-switch-label-wrap:has(.ak-switch-label-icon) .ak-switch-helper {
401
+ grid-column: 2;
402
+ grid-row: 2;
403
+ }
404
+ .ak-switch-label {
405
+ font-size: var(--text-ak-fl-lg); font-weight: 700; color: var(--color-ak-text);
406
+ }
407
+ .ak-switch-helper { font-size: var(--text-ak-fl-base); color: var(--color-ak-text-secondary); }
408
+ .ak-switch-label-icon {
409
+ font-size: 1.5rem; color: var(--color-ak-text-secondary); line-height: 1; flex-shrink: 0;
410
+ width: 2.75rem; height: 2.75rem;
411
+ display: flex; align-items: center; justify-content: center;
412
+ background: var(--color-ak-surface); border-radius: 0.75rem;
413
+ }
414
+ .ak-switch-card {
415
+ border: 2px solid var(--color-ak-border); border-radius: 0.75rem;
416
+ padding: 20px 24px; transition: border-color 0.2s;
417
+ }
418
+ .ak-switch-card-active {
419
+ border-color: var(--color-ak-primary); background: var(--color-ak-primary-subtle);
420
+ }
421
+ .ak-switch-compact .ak-switch-field { padding: 16px 0; }
422
+ .ak-switch-compact .ak-switch-field + .ak-switch-field { border-top: 1px solid var(--color-ak-border); }
423
+ .ak-switch-compact .ak-switch-label { font-size: var(--text-ak-fl-base); }
424
+ .ak-switch-compact .ak-switch-helper { font-size: var(--text-ak-fl-sm); }
425
+ .ak-switch-value { font-size: var(--text-ak-fl-base); font-weight: 600; color: var(--color-ak-text); min-width: 32px; text-align: right; }
426
+ .ak-switch-value-muted { color: var(--color-ak-text-secondary); font-weight: 400; }
427
+ .ak-switch-group { border: none; padding: 0; margin: 0; }
428
+ .ak-switch-group-legend { font-size: var(--text-ak-fl-base); font-weight: 700; color: var(--color-ak-text-secondary); padding: 0; margin-bottom: 16px; text-transform: uppercase; letter-spacing: 0.05em; }
429
+ .ak-switch-section { border: 2px solid var(--color-ak-border); border-radius: 0.75rem; padding: 24px; }
430
+ .ak-switch-section .ak-switch-group-legend { font-size: var(--text-ak-fl-lg); margin-bottom: 16px; padding: 0 8px; text-transform: none; letter-spacing: normal; }
431
+ .ak-switch-section .ak-switch-field + .ak-switch-field {
432
+ border-top: 1px solid var(--color-ak-border-subtle); padding-top: 16px; margin-top: 16px;
433
+ }
434
+ .ak-form-section { max-width: 640px; }
435
+
436
+ /* ── Number Stepper Button Press ── */
437
+ .ak-stepper-btn:active:not([aria-disabled="true"]) {
438
+ transform: translate(2px, 2px);
439
+ box-shadow: 2px 2px 0 0 var(--color-ak-brutal-ink) !important;
440
+ }
441
+ .ak-stepper-btn[aria-disabled="true"] { pointer-events: none; opacity: 0.3; }
442
+
443
+ /* ── Quantity Selector ── */
444
+ .ak-qty-btn { transition: all 0.15s ease; }
445
+ .ak-qty-btn:active:not([aria-disabled="true"]) { transform: scale(0.96); }
446
+ .ak-qty-btn[aria-disabled="true"] { opacity: 0.3; cursor: not-allowed; }
447
+
448
+ /* ── Shared Keyframes ── */
449
+ @keyframes ak-fadeInUp {
450
+ from { opacity: 0; transform: translateY(8px); }
451
+ to { opacity: 1; transform: translateY(0); }
452
+ }
453
+ @keyframes ak-slideIn {
454
+ from { opacity: 0; transform: translateY(-8px) scale(0.98); }
455
+ to { opacity: 1; transform: translateY(0) scale(1); }
456
+ }
457
+ @keyframes ak-fadeOut {
458
+ from { opacity: 1; transform: translateY(0) scale(1); }
459
+ to { opacity: 0; transform: translateY(-8px) scale(0.98); }
460
+ }
461
+ @keyframes ak-swipeOut {
462
+ from { transform: translateX(var(--radix-toast-swipe-end-x)); }
463
+ to { transform: translateX(100%); }
464
+ }
465
+
466
+ /* ── Glass Panel (split-screen logins) ── */
467
+ .ak-glass-panel {
468
+ background: rgba(255, 255, 255, 0.03);
469
+ backdrop-filter: blur(12px);
470
+ -webkit-backdrop-filter: blur(12px);
471
+ border: 1px solid rgba(255, 255, 255, 0.1);
472
+ }
473
+
474
+ /* ── Grid Pattern Background ── */
475
+ .ak-bg-grid-pattern {
476
+ background-image: linear-gradient(to right, rgba(255,255,255,0.06) 1px, transparent 1px),
477
+ linear-gradient(to bottom, rgba(255,255,255,0.06) 1px, transparent 1px);
478
+ background-size: 40px 40px;
479
+ }
480
+
481
+ /* ── Toggle Group ── */
482
+ .ak-toggle-group {
483
+ display: inline-flex; background: var(--color-ak-surface-2);
484
+ border-radius: 8px; padding: 4px; gap: 4px;
485
+ }
486
+ .ak-toggle-group-item {
487
+ display: inline-flex; align-items: center; justify-content: center; gap: 6px;
488
+ background: none; border: none; padding: 0 16px; min-height: 44px;
489
+ font-family: inherit; font-size: var(--text-ak-base, 1rem); font-weight: 600;
490
+ color: var(--color-ak-text-secondary); border-radius: 8px; cursor: pointer;
491
+ transition: background-color 0.2s, color 0.2s; white-space: nowrap; line-height: 1;
492
+ }
493
+ .ak-toggle-group-item[aria-checked="true"],
494
+ .ak-toggle-group-item[aria-pressed="true"] {
495
+ background: var(--color-ak-bg); color: var(--color-ak-text);
496
+ }
497
+ .ak-toggle-group-item[aria-checked="false"]:not(:disabled):hover,
498
+ .ak-toggle-group-item[aria-pressed="false"]:not(:disabled):hover {
499
+ color: var(--color-ak-text); background: var(--color-ak-hover);
500
+ }
501
+ .ak-toggle-group-item:focus { outline: none; }
502
+ .ak-toggle-group-item:focus-visible { outline: 2px solid var(--color-ak-primary); outline-offset: 2px; }
503
+ .ak-toggle-group-item:disabled { opacity: 0.4; cursor: not-allowed; }
504
+ .ak-toggle-group[aria-disabled="true"] { opacity: 0.5; }
505
+ .ak-toggle-group[aria-disabled="true"] .ak-toggle-group-item { cursor: not-allowed; }
506
+ .ak-toggle-group-item i { font-size: 20px; line-height: 1; }
507
+ .ak-toggle-group-item-icon { padding: 0 14px; }
508
+ /* Toggle group — small */
509
+ .ak-toggle-group-sm { padding: 3px; gap: 3px; }
510
+ .ak-toggle-group-sm .ak-toggle-group-item { min-height: 44px; padding: 0 12px; font-size: var(--text-ak-sm, 0.875rem); }
511
+ .ak-toggle-group-sm .ak-toggle-group-item i { font-size: 18px; }
512
+ .ak-toggle-group-sm .ak-toggle-group-item-icon { padding: 0 12px; }
513
+ /* Toggle group — large */
514
+ .ak-toggle-group-lg { padding: 5px; gap: 5px; }
515
+ .ak-toggle-group-lg .ak-toggle-group-item { min-height: 52px; padding: 0 24px; font-size: var(--text-ak-lg, 1.125rem); }
516
+ .ak-toggle-group-lg .ak-toggle-group-item i { font-size: 24px; }
517
+ .ak-toggle-group-lg .ak-toggle-group-item-icon { padding: 0 18px; }
518
+
519
+ /* ── Resizable Panel Cursors ── */
520
+ body.ak-col-resizing, body.ak-col-resizing * {
521
+ cursor: col-resize !important; user-select: none !important; -webkit-user-select: none !important;
522
+ }
523
+ body.ak-ew-resizing, body.ak-ew-resizing * {
524
+ cursor: ew-resize !important; user-select: none !important; -webkit-user-select: none !important;
525
+ }
526
+
527
+ /* ── Focus Ring Utility ── */
528
+ .ak-focus-ring:focus-visible { outline: 2px solid var(--color-ak-primary); outline-offset: 2px; }
529
+
530
+ /* ── Price Fade Transition ── */
531
+ .ak-price-fade { transition: opacity 0.15s ease-in-out; }
532
+
533
+ /* Reduced motion — unlayered so it overrides everything */
534
+ @media (prefers-reduced-motion: reduce) {
535
+ *, *::before, *::after {
536
+ animation-duration: 0.01ms !important;
537
+ transition-duration: 0.01ms !important;
538
+ }
539
+ .ak-star-btn:hover { transform: none !important; }
540
+ .ak-stepper-btn:active { transform: none !important; }
541
+ @keyframes ak-slideIn { from { opacity: 0; } to { opacity: 1; } }
542
+ @keyframes ak-fadeOut { from { opacity: 1; } to { opacity: 0; } }
543
+ }