@stasho/ds 0.1.0 → 0.2.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.
@@ -2,70 +2,70 @@
2
2
  Layer 1: Color Scales, Gradients, Shadows, Fonts
3
3
  ────────────────────────────────────────────── */
4
4
  @theme {
5
- /* Primary (brand purple, H: 285.48) — 600 = brand #5100CD */
6
- --color-primary-50: oklch(0.96 0.02 301.63);
7
- --color-primary-100: oklch(0.93 0.040 285.48);
8
- --color-primary-200: oklch(0.87 0.080 285.48);
9
- --color-primary-300: oklch(0.77 0.140 285.48);
10
- --color-primary-400: oklch(0.64 0.210 285.48);
11
- --color-primary-500: oklch(0.50 0.254 285.48);
12
- --color-primary-600: oklch(0.372 0.254 285.48);
13
- --color-primary-700: oklch(0.31 0.224 285.48);
14
- --color-primary-800: oklch(0.25 0.174 285.48);
15
- --color-primary-900: oklch(0.20 0.114 285.48);
16
- --color-primary-950: oklch(0.15 0.064 285.48);
17
-
18
- /* Accent (brand lime, H: 121.30) — 300 = brand #D4FF00 */
19
- --color-accent-50: oklch(0.98 0.030 121.30);
20
- --color-accent-100: oklch(0.96 0.100 121.30);
21
- --color-accent-200: oklch(0.94 0.180 121.30);
22
- --color-accent-300: oklch(0.929 0.228 121.30);
23
- --color-accent-400: oklch(0.82 0.200 121.30);
24
- --color-accent-500: oklch(0.72 0.175 121.30);
25
- --color-accent-600: oklch(0.62 0.150 121.30);
26
- --color-accent-700: oklch(0.52 0.120 121.30);
27
- --color-accent-800: oklch(0.42 0.085 121.30);
28
- --color-accent-900: oklch(0.32 0.055 121.30);
29
- --color-accent-950: oklch(0.22 0.030 121.30);
30
-
31
- /* Success (green, H: 145) — 500 = #36D846 */
32
- --color-success-50: oklch(0.98 0.020 145);
33
- --color-success-100: oklch(0.94 0.050 145);
34
- --color-success-200: oklch(0.88 0.100 145);
35
- --color-success-300: oklch(0.81 0.160 145);
36
- --color-success-400: oklch(0.76 0.200 145);
37
- --color-success-500: oklch(0.72 0.230 145);
38
- --color-success-600: oklch(0.60 0.200 145);
39
- --color-success-700: oklch(0.50 0.170 145);
40
- --color-success-800: oklch(0.40 0.130 145);
41
- --color-success-900: oklch(0.30 0.085 145);
42
- --color-success-950: oklch(0.20 0.045 145);
43
-
44
- /* Warning (amber, H: 75) — 500 = #FBAE18 */
45
- --color-warning-50: oklch(0.98 0.020 75);
46
- --color-warning-100: oklch(0.95 0.050 75);
47
- --color-warning-200: oklch(0.90 0.100 75);
48
- --color-warning-300: oklch(0.86 0.140 75);
49
- --color-warning-400: oklch(0.83 0.165 75);
50
- --color-warning-500: oklch(0.80 0.180 75);
51
- --color-warning-600: oklch(0.70 0.165 75);
52
- --color-warning-700: oklch(0.60 0.140 75);
53
- --color-warning-800: oklch(0.48 0.110 75);
54
- --color-warning-900: oklch(0.35 0.075 75);
55
- --color-warning-950: oklch(0.24 0.045 75);
56
-
57
- /* Error (red, H: 12) — 600 = #DE3668 */
58
- --color-error-50: oklch(0.98 0.010 12);
59
- --color-error-100: oklch(0.93 0.040 12);
60
- --color-error-200: oklch(0.87 0.080 12);
61
- --color-error-300: oklch(0.79 0.130 12);
62
- --color-error-400: oklch(0.70 0.170 12);
63
- --color-error-500: oklch(0.63 0.200 12);
64
- --color-error-600: oklch(0.57 0.200 12);
65
- --color-error-700: oklch(0.48 0.175 12);
66
- --color-error-800: oklch(0.39 0.140 12);
67
- --color-error-900: oklch(0.30 0.095 12);
68
- --color-error-950: oklch(0.20 0.055 12);
5
+ /* Primary (Abyssal electric blue, H: 264) — 500 = brand #0040FF */
6
+ --color-primary-50: oklch(0.97 0.020 264);
7
+ --color-primary-100: oklch(0.94 0.045 264);
8
+ --color-primary-200: oklch(0.87 0.085 264);
9
+ --color-primary-300: oklch(0.77 0.140 264);
10
+ --color-primary-400: oklch(0.65 0.215 264);
11
+ --color-primary-500: oklch(0.50 0.280 264);
12
+ --color-primary-600: oklch(0.42 0.255 264);
13
+ --color-primary-700: oklch(0.34 0.220 264);
14
+ --color-primary-800: oklch(0.27 0.180 264);
15
+ --color-primary-900: oklch(0.19 0.135 264);
16
+ --color-primary-950: oklch(0.12 0.080 264);
17
+
18
+ /* Accent (Abyssal bright cyan, H: 215) — 300 = brand #00E1FA */
19
+ --color-accent-50: oklch(0.98 0.020 215);
20
+ --color-accent-100: oklch(0.95 0.040 215);
21
+ --color-accent-200: oklch(0.92 0.070 215);
22
+ --color-accent-300: oklch(0.85 0.130 215);
23
+ --color-accent-400: oklch(0.77 0.140 215);
24
+ --color-accent-500: oklch(0.67 0.140 215);
25
+ --color-accent-600: oklch(0.55 0.130 215);
26
+ --color-accent-700: oklch(0.45 0.115 215);
27
+ --color-accent-800: oklch(0.35 0.095 215);
28
+ --color-accent-900: oklch(0.25 0.075 215);
29
+ --color-accent-950: oklch(0.16 0.050 215);
30
+
31
+ /* Success (cool teal-green, H: 160) — 400 = brand #2BD58E */
32
+ --color-success-50: oklch(0.98 0.020 160);
33
+ --color-success-100: oklch(0.95 0.045 160);
34
+ --color-success-200: oklch(0.90 0.085 160);
35
+ --color-success-300: oklch(0.84 0.125 160);
36
+ --color-success-400: oklch(0.78 0.155 160);
37
+ --color-success-500: oklch(0.68 0.150 160);
38
+ --color-success-600: oklch(0.55 0.135 160);
39
+ --color-success-700: oklch(0.45 0.115 160);
40
+ --color-success-800: oklch(0.35 0.090 160);
41
+ --color-success-900: oklch(0.25 0.065 160);
42
+ --color-success-950: oklch(0.16 0.040 160);
43
+
44
+ /* Warning (Radix Amber-9, H: 87) — 400 = brand #ffc53d */
45
+ --color-warning-50: oklch(0.98 0.020 87);
46
+ --color-warning-100: oklch(0.95 0.050 87);
47
+ --color-warning-200: oklch(0.90 0.100 87);
48
+ --color-warning-300: oklch(0.87 0.140 87);
49
+ --color-warning-400: oklch(0.84 0.160 87);
50
+ --color-warning-500: oklch(0.78 0.165 87);
51
+ --color-warning-600: oklch(0.68 0.155 87);
52
+ --color-warning-700: oklch(0.58 0.135 87);
53
+ --color-warning-800: oklch(0.46 0.105 87);
54
+ --color-warning-900: oklch(0.34 0.075 87);
55
+ --color-warning-950: oklch(0.23 0.045 87);
56
+
57
+ /* Error (blood-orange, H: 25) — 500 = brand #FF3D00 */
58
+ --color-error-50: oklch(0.97 0.025 25);
59
+ --color-error-100: oklch(0.93 0.055 25);
60
+ --color-error-200: oklch(0.86 0.110 25);
61
+ --color-error-300: oklch(0.78 0.170 25);
62
+ --color-error-400: oklch(0.71 0.220 25);
63
+ --color-error-500: oklch(0.64 0.245 25);
64
+ --color-error-600: oklch(0.56 0.225 25);
65
+ --color-error-700: oklch(0.47 0.190 25);
66
+ --color-error-800: oklch(0.38 0.150 25);
67
+ --color-error-900: oklch(0.28 0.110 25);
68
+ --color-error-950: oklch(0.18 0.070 25);
69
69
 
70
70
  /* Destructive (alias → error, for shadcn/Tailwind convention compatibility) */
71
71
  --color-destructive-50: var(--color-error-50);
@@ -80,61 +80,78 @@
80
80
  --color-destructive-900: var(--color-error-900);
81
81
  --color-destructive-950: var(--color-error-950);
82
82
 
83
- /* Neutral (gray with slight purple tint, H: 265) */
84
- --color-neutral-50: oklch(0.98 0.003 265);
85
- --color-neutral-100: oklch(0.94 0.006 265);
86
- --color-neutral-200: oklch(0.90 0.008 265);
87
- --color-neutral-300: oklch(0.83 0.012 265);
88
- --color-neutral-400: oklch(0.71 0.015 265);
89
- --color-neutral-500: oklch(0.55 0.015 265);
90
- --color-neutral-600: oklch(0.45 0.014 265);
91
- --color-neutral-700: oklch(0.37 0.012 265);
92
- --color-neutral-800: oklch(0.29 0.010 265);
93
- --color-neutral-900: oklch(0.21 0.008 265);
94
- --color-neutral-950: oklch(0.14 0.005 265);
95
-
96
- /* Base (dark indigo, H: 280) — tone-sur-tone dark surface palette */
97
- --color-base-900: oklch(0.22 0.025 280);
98
- --color-base-800: oklch(0.28 0.030 280);
99
- --color-base-700: oklch(0.34 0.034 280);
83
+ /* Neutral (cool gray with subtle indigo tint, H: 273) */
84
+ --color-neutral-50: oklch(0.98 0.003 273);
85
+ --color-neutral-100: oklch(0.94 0.006 273);
86
+ --color-neutral-200: oklch(0.90 0.008 273);
87
+ --color-neutral-300: oklch(0.83 0.012 273);
88
+ --color-neutral-400: oklch(0.71 0.015 273);
89
+ --color-neutral-500: oklch(0.55 0.015 273);
90
+ --color-neutral-600: oklch(0.45 0.014 273);
91
+ --color-neutral-700: oklch(0.37 0.012 273);
92
+ --color-neutral-800: oklch(0.29 0.010 273);
93
+ --color-neutral-900: oklch(0.21 0.008 273);
94
+ --color-neutral-950: oklch(0.14 0.005 273);
95
+
96
+ /* Base (Observatory Mono dark surface ladder, H: 273) */
97
+ --color-base-700: oklch(0.21 0.005 273); /* #161718 raised (popovers) */
98
+ --color-base-800: oklch(0.18 0.004 273); /* #101111 elevated (modals) */
99
+ --color-base-900: oklch(0.16 0.003 273); /* #0d0d0d surface (panels) */
100
+ --color-base-950: oklch(0.10 0.002 273); /* #07080a void / background */
100
101
 
101
102
  /* Gradients */
102
- --gradient-main-base: linear-gradient(90deg, #141421 8.24%, #5100CD 71.81%);
103
- --gradient-main-dark: linear-gradient(90deg, #1C1C32 8.24%, #5100CD 71.81%);
104
- --gradient-lime: linear-gradient(90deg, #D6FF00 27.88%, #F5F7DB 100%);
105
- --gradient-success: linear-gradient(90deg, #36D846 0%, #63E570 100%);
106
- --gradient-warning: linear-gradient(90deg, #FFE814 0%, #FBAE18 100%);
107
- --gradient-error: linear-gradient(90deg, #FFAC89 0%, #DE3668 90.62%);
108
- --gradient-info: linear-gradient(90deg, #C8ADF0 22.66%, #5100CD 244.27%);
103
+ --gradient-main-base: linear-gradient(90deg, #00104D 8.24%, #0040FF 71.81%);
104
+ --gradient-main-dark: linear-gradient(90deg, #00041A 8.24%, #0040FF 71.81%);
105
+ --gradient-accent: linear-gradient(90deg, #00B8D4 0%, #00E1FA 100%);
106
+ --gradient-success: linear-gradient(90deg, #2BD58E 0%, #5DDFAB 100%);
107
+ --gradient-warning: linear-gradient(90deg, #FFE14D 0%, #FFC53D 100%);
108
+ --gradient-error: linear-gradient(90deg, #FF6A3D 0%, #FF3D00 100%);
109
+ --gradient-info: linear-gradient(90deg, #00E1FA 22.66%, #0040FF 244.27%);
109
110
  --gradient-destructive: var(--gradient-error);
110
111
 
111
- /* Shadows */
112
- --shadow-brand-sm: 0px 4px 4px oklch(0.372 0.254 285.48 / 0.15);
113
- --shadow-brand: 0px 4px 24px oklch(0.372 0.254 285.48 / 0.1);
114
- --shadow-brand-lg: 0px 4px 48px oklch(0.372 0.254 285.48 / 0.25);
112
+ /* Shadows — neutral elevation, no brand tint (Decision #87) */
113
+ --shadow-sm: 0px 2px 4px rgba(0, 0, 0, 0.10);
114
+ --shadow: 0px 4px 16px rgba(0, 0, 0, 0.20);
115
+ --shadow-lg: 0px 24px 60px rgba(0, 0, 0, 0.65);
115
116
 
116
117
  /* Fonts */
117
- --font-heading: "rigid-square", ui-sans-serif, system-ui, sans-serif;
118
- --font-sans: "Titillium Web", ui-sans-serif, system-ui, sans-serif;
119
- --font-mono: "Source Code Pro", ui-monospace, monospace;
118
+ --font-heading: "Anybody", ui-sans-serif, system-ui, sans-serif;
119
+ --font-sans: "Inter", ui-sans-serif, system-ui, sans-serif;
120
+ --font-mono: "Departure Mono", ui-monospace, monospace;
121
+
122
+ /* Radius vocabulary (Abyssal Void — 0/0/2/4, full reserved for round-by-design) */
123
+ --radius-sm: 0;
124
+ --radius-md: 0;
125
+ --radius-lg: 2px;
126
+ --radius-xl: 4px;
120
127
  }
121
128
 
122
129
  /* ──────────────────────────────────────────────
123
130
  Layer 2: Semantic Surface Tokens (theme-dependent)
124
131
  ────────────────────────────────────────────── */
125
132
  :root {
126
- --background: #F9F4FF;
127
- --foreground: #141421;
128
- --primary: var(--color-primary-600);
133
+ --background: oklch(0.99 0.005 270);
134
+ --foreground: oklch(0.22 0.015 270);
135
+
136
+ --primary: #0040FF;
129
137
  --primary-foreground: #ffffff;
130
- --accent: var(--color-accent-300);
131
- --accent-foreground: #141421;
132
- --muted: var(--color-primary-100);
133
- --muted-foreground: var(--color-neutral-500);
134
- --surface: var(--color-primary-50);
135
- --surface-foreground: #141421;
136
- --edge: var(--color-primary-200);
137
- --edge-hover: var(--color-primary-300);
138
+ --accent: #00E1FA;
139
+ --accent-foreground: #001014;
140
+ --success: #2BD58E;
141
+ --success-foreground: #00130a;
142
+ --warning: #ffc53d;
143
+ --warning-foreground: #1a1100;
144
+ --error: #FF3D00;
145
+ --error-foreground: #ffffff;
146
+
147
+ --muted: oklch(0.94 0.009 270);
148
+ --muted-foreground: oklch(0.55 0.014 270);
149
+ --surface: oklch(0.94 0.009 270);
150
+ --surface-foreground: oklch(0.22 0.015 270);
151
+ --edge: oklch(0.87 0.013 270);
152
+ --edge-hover: oklch(0.80 0.015 270);
153
+ --popover-bg: var(--surface);
154
+ --popover-border: var(--edge);
138
155
 
139
156
  --gradient-main: var(--gradient-main-base);
140
157
 
@@ -145,18 +162,28 @@
145
162
  }
146
163
 
147
164
  .theme-dark {
148
- --background: #141421;
149
- --foreground: #F9F4FF;
150
- --primary: var(--color-primary-400);
165
+ --background: #07080a;
166
+ --foreground: #f3f3f3;
167
+
168
+ --primary: #0040FF;
151
169
  --primary-foreground: #ffffff;
152
- --accent: var(--color-accent-300);
153
- --accent-foreground: #141421;
154
- --muted: var(--color-base-900);
155
- --muted-foreground: var(--color-neutral-400);
170
+ --accent: #00E1FA;
171
+ --accent-foreground: #001014;
172
+ --success: #2BD58E;
173
+ --success-foreground: #00130a;
174
+ --warning: #ffc53d;
175
+ --warning-foreground: #1a1100;
176
+ --error: #FF3D00;
177
+ --error-foreground: #ffffff;
178
+
179
+ --muted: var(--color-base-800);
180
+ --muted-foreground: oklch(0.62 0.012 273);
156
181
  --surface: var(--color-base-900);
157
- --surface-foreground: #F9F4FF;
158
- --edge: var(--color-base-800);
159
- --edge-hover: var(--color-base-700);
182
+ --surface-foreground: #f3f3f3;
183
+ --edge: rgba(255, 255, 255, 0.08);
184
+ --edge-hover: rgba(255, 255, 255, 0.14);
185
+ --popover-bg: var(--surface);
186
+ --popover-border: var(--edge);
160
187
 
161
188
  --gradient-main: var(--gradient-main-dark);
162
189
  }
@@ -171,12 +198,20 @@
171
198
  --color-primary-foreground: var(--primary-foreground);
172
199
  --color-accent: var(--accent);
173
200
  --color-accent-foreground: var(--accent-foreground);
201
+ --color-success: var(--success);
202
+ --color-success-foreground: var(--success-foreground);
203
+ --color-warning: var(--warning);
204
+ --color-warning-foreground: var(--warning-foreground);
205
+ --color-error: var(--error);
206
+ --color-error-foreground: var(--error-foreground);
174
207
  --color-muted: var(--muted);
175
208
  --color-muted-foreground: var(--muted-foreground);
176
209
  --color-surface: var(--surface);
177
210
  --color-surface-foreground: var(--surface-foreground);
178
211
  --color-edge: var(--edge);
179
212
  --color-edge-hover: var(--edge-hover);
213
+ --color-popover-bg: var(--popover-bg);
214
+ --color-popover-border: var(--popover-border);
180
215
  }
181
216
 
182
217
  /* ──────────────────────────────────────────────
@@ -188,7 +223,7 @@
188
223
  detected from source files. This directive feeds
189
224
  them directly into the candidate list.
190
225
  ────────────────────────────────────────────── */
191
- @source inline("group-data-[variant=pill]:relative group-data-[variant=pill]:z-10 group-data-[variant=pill]:rounded-full group-data-[variant=pill]:px-5 group-data-[variant=pill]:py-1.5 group-data-[variant=pill]:text-sm group-data-[variant=pill]:text-muted-foreground group-data-[variant=pill]:translate-y-0 group-data-[variant=pill]:hover:text-foreground group-data-[variant=pill]:data-[state=active]:text-white group-data-[variant=pill]:data-[state=active]:translate-y-0 group-data-[variant=pill]:focus-visible:ring-offset-0");
226
+ @source inline("group-data-[variant=pill]:relative group-data-[variant=pill]:z-10 group-data-[variant=pill]:rounded-[2px] group-data-[variant=pill]:px-5 group-data-[variant=pill]:py-1.5 group-data-[variant=pill]:text-sm group-data-[variant=pill]:text-muted-foreground group-data-[variant=pill]:translate-y-0 group-data-[variant=pill]:hover:text-accent-500 dark:group-data-[variant=pill]:hover:text-accent group-data-[variant=pill]:data-[state=active]:text-accent-500 dark:group-data-[variant=pill]:data-[state=active]:text-accent group-data-[variant=pill]:data-[state=active]:translate-y-0");
192
227
 
193
228
  /* ──────────────────────────────────────────────
194
229
  Utilities: gradient border effects
@@ -230,18 +265,18 @@
230
265
  var(--gradient-main) border-box;
231
266
  }
232
267
 
233
- .gradient-fill-lime {
234
- background: var(--gradient-lime) border-box;
268
+ .gradient-fill-accent {
269
+ background: var(--gradient-accent) border-box;
235
270
  }
236
- .gradient-fill-lime:hover {
271
+ .gradient-fill-accent:hover {
237
272
  background:
238
273
  linear-gradient(oklch(0 0 0 / 0.06), oklch(0 0 0 / 0.06)) border-box,
239
- var(--gradient-lime) border-box;
274
+ var(--gradient-accent) border-box;
240
275
  }
241
- .gradient-fill-lime:active {
276
+ .gradient-fill-accent:active {
242
277
  background:
243
278
  linear-gradient(oklch(0 0 0 / 0.12), oklch(0 0 0 / 0.12)) border-box,
244
- var(--gradient-lime) border-box;
279
+ var(--gradient-accent) border-box;
245
280
  }
246
281
 
247
282
  .gradient-fill-success {
@@ -260,182 +295,43 @@
260
295
  background: var(--gradient-info) border-box;
261
296
  }
262
297
 
263
- /* ── FX Grain Textures ───────────────────────────────── */
264
-
265
- /* Shared base: stacking context */
266
- .fx-grain-lg,
267
- .fx-grain-xs,
268
- .fx-grain-sm,
269
- .fx-grain-md {
270
- position: relative;
271
- isolation: isolate;
272
- }
273
-
274
- /* Shared ::after: texture overlay */
275
- :is(.fx-grain-lg, .fx-grain-xs, .fx-grain-sm, .fx-grain-md)::after {
276
- content: "";
277
- position: absolute;
278
- inset: 0;
279
- z-index: -1;
280
- border-radius: inherit;
281
- background-size: 400px 400px;
282
- background-repeat: repeat;
283
- pointer-events: none;
284
- }
285
-
286
- /* ── Light mode gradients ── */
287
-
288
- .fx-grain-lg {
289
- background-image: radial-gradient(
290
- 50% 50%,
291
- var(--color-primary-100) 0%,
292
- oklch(from var(--color-primary-100) l c h / 0.40) 100%
293
- );
294
- }
295
-
296
- .fx-grain-xs {
297
- background-image: radial-gradient(
298
- 50% 50%,
299
- oklch(from var(--color-primary-100) l c h / 0.40) 0%,
300
- oklch(from var(--color-primary-100) l c h / 0.40) 100%
301
- );
302
- }
303
-
304
- .fx-grain-sm {
305
- background-image: radial-gradient(
306
- 50% 50%,
307
- oklch(from var(--color-primary-100) l c h / 0.40) 0%,
308
- oklch(from var(--color-primary-100) l c h / 0.23) 100%
309
- );
310
- }
311
-
312
- .fx-grain-md {
313
- background: radial-gradient(
314
- 50% 50%,
315
- oklch(from var(--color-primary-100) l c h / 0.40) 0%,
316
- oklch(from var(--color-primary-100) l c h / 0.05) 100%
317
- ),
318
- oklch(from var(--color-primary-100) l c h / 0.40);
319
- }
320
-
321
- /* ── Dark mode gradients ── */
322
-
323
- .theme-dark .fx-grain-lg {
324
- background-image: radial-gradient(
325
- 50% 50%,
326
- var(--surface) 0%,
327
- oklch(from var(--surface) l c h / 0.57) 100%
328
- );
329
- }
330
-
331
- .theme-dark .fx-grain-xs {
332
- background-image: radial-gradient(
333
- 50% 50%,
334
- var(--surface) 0%,
335
- oklch(from var(--surface) l c h / 0.57) 100%
336
- );
337
- }
338
-
339
- .theme-dark .fx-grain-sm {
340
- background-image: radial-gradient(
341
- 50% 50%,
342
- var(--surface) 0%,
343
- oklch(from var(--surface) l c h / 0.25) 100%
344
- );
345
- }
346
-
347
- .theme-dark .fx-grain-md {
348
- background: radial-gradient(
349
- 50% 50%,
350
- oklch(from var(--surface) l c h / 0.40) 0%,
351
- oklch(from var(--surface) l c h / 0.05) 100%
352
- ),
353
- var(--surface);
354
- }
355
-
356
- /* ── Dark mode texture opacity overrides ── */
357
-
358
- .theme-dark .fx-grain-lg::after {
359
- opacity: 0.5;
360
- }
361
-
362
- .theme-dark .fx-grain-xs::after {
363
- opacity: 0.2;
364
- }
365
-
366
- .theme-dark .fx-grain-sm::after {
367
- opacity: 0.2;
368
- }
369
-
370
- .theme-dark .fx-grain-md::after {
371
- opacity: 0.35;
372
- }
373
-
374
- /* ── Texture overlays (::after) ── */
375
-
376
- /* Texture: scattered purple dots */
377
- .fx-grain-lg::after {
378
- background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iNDAwIiB3aWR0aD0iNDAwIj48ZmlsdGVyIGlkPSJmIj48ZmVUdXJidWxlbmNlIGJhc2VGcmVxdWVuY3k9Ii4yNSIgdHlwZT0iZnJhY3RhbE5vaXNlIiBudW1PY3RhdmVzPSIzIi8+PGZlQ29sb3JNYXRyaXggdmFsdWVzPSIwIDAgMCAwIDAuMSAwIDAgMCAwIDAgMCAwIDAgMCAwLjgwIDAgMCAwIDEwIC03LjI1Ii8+PC9maWx0ZXI+PHJlY3Qgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsdGVyPSJ1cmwoI2YpIi8+PC9zdmc+");
379
- opacity: 0.5;
380
- }
381
-
382
- .fx-grain-xs::after {
383
- background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iNDAwIiB3aWR0aD0iNDAwIj48ZmlsdGVyIGlkPSJmIj48ZmVUdXJidWxlbmNlIGJhc2VGcmVxdWVuY3k9Ii4yNSIgdHlwZT0iZnJhY3RhbE5vaXNlIiBudW1PY3RhdmVzPSIzIi8+PGZlQ29sb3JNYXRyaXggdmFsdWVzPSIwIDAgMCAwIDAuMSAwIDAgMCAwIDAgMCAwIDAgMCAwLjgwIDAgMCAwIDEwIC03LjI1Ii8+PC9maWx0ZXI+PHJlY3Qgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsdGVyPSJ1cmwoI2YpIi8+PC9zdmc+");
384
- opacity: 0.1;
385
- }
386
-
387
- .fx-grain-sm::after {
388
- background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iNDAwIiB3aWR0aD0iNDAwIj48ZmlsdGVyIGlkPSJmIj48ZmVUdXJidWxlbmNlIGJhc2VGcmVxdWVuY3k9Ii4yNSIgdHlwZT0iZnJhY3RhbE5vaXNlIiBudW1PY3RhdmVzPSIzIi8+PGZlQ29sb3JNYXRyaXggdmFsdWVzPSIwIDAgMCAwIDAuMSAwIDAgMCAwIDAgMCAwIDAgMCAwLjgwIDAgMCAwIDEwIC03LjI1Ii8+PC9maWx0ZXI+PHJlY3Qgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsdGVyPSJ1cmwoI2YpIi8+PC9zdmc+");
389
- opacity: 0.2;
390
- }
391
-
392
- .fx-grain-md::after {
393
- background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iNDAwIiB3aWR0aD0iNDAwIj48ZmlsdGVyIGlkPSJmIj48ZmVUdXJidWxlbmNlIGJhc2VGcmVxdWVuY3k9Ii4yNSIgdHlwZT0iZnJhY3RhbE5vaXNlIiBudW1PY3RhdmVzPSIzIi8+PGZlQ29sb3JNYXRyaXggdmFsdWVzPSIwIDAgMCAwIDAuMSAwIDAgMCAwIDAgMCAwIDAgMCAwLjgwIDAgMCAwIDEwIC03LjI1Ii8+PC9maWx0ZXI+PHJlY3Qgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsdGVyPSJ1cmwoI2YpIi8+PC9zdmc+");
394
- opacity: 0.35;
395
- }
396
-
397
298
  /* ── Alert gradient backgrounds ──────────────────────── */
398
- /* Variant gradient at 10% opacity over page background */
299
+ /* Variant hue concentrated at top, fading toward background */
399
300
 
400
301
  .alert-bg-warning {
401
302
  background:
402
- linear-gradient(90deg, oklch(from var(--color-warning-400) l c h / 0.1), oklch(from var(--color-warning-600) l c h / 0.1)),
303
+ linear-gradient(
304
+ 180deg,
305
+ oklch(from var(--warning) l c h / 0.18),
306
+ oklch(from var(--warning) l c h / 0.06)
307
+ ),
403
308
  var(--background);
404
309
  }
405
310
  .alert-bg-error {
406
311
  background:
407
- linear-gradient(90deg, oklch(from var(--color-error-300) l c h / 0.1), oklch(from var(--color-error-600) l c h / 0.1)),
312
+ linear-gradient(
313
+ 180deg,
314
+ oklch(from var(--error) l c h / 0.18),
315
+ oklch(from var(--error) l c h / 0.06)
316
+ ),
408
317
  var(--background);
409
318
  }
410
319
  .alert-bg-info {
411
320
  background:
412
- linear-gradient(90deg, oklch(from var(--color-primary-300) l c h / 0.1), oklch(from var(--color-primary-600) l c h / 0.1)),
321
+ linear-gradient(
322
+ 180deg,
323
+ oklch(from var(--accent) l c h / 0.18),
324
+ oklch(from var(--accent) l c h / 0.06)
325
+ ),
413
326
  var(--background);
414
327
  }
415
328
  .alert-bg-success {
416
329
  background:
417
- linear-gradient(90deg, oklch(from var(--color-success-400) l c h / 0.1), oklch(from var(--color-success-600) l c h / 0.1)),
418
- var(--background);
419
- }
420
-
421
- :is(.theme-dark .alert-bg-warning) {
422
- background:
423
- linear-gradient(90deg, oklch(from var(--color-warning-400) l c h / 0.15), oklch(from var(--color-warning-600) l c h / 0.15)),
424
- var(--background);
425
- }
426
- :is(.theme-dark .alert-bg-error) {
427
- background:
428
- linear-gradient(90deg, oklch(from var(--color-error-300) l c h / 0.15), oklch(from var(--color-error-600) l c h / 0.15)),
429
- var(--background);
430
- }
431
- :is(.theme-dark .alert-bg-info) {
432
- background:
433
- linear-gradient(90deg, oklch(from var(--color-primary-300) l c h / 0.15), oklch(from var(--color-primary-600) l c h / 0.15)),
434
- var(--background);
435
- }
436
- :is(.theme-dark .alert-bg-success) {
437
- background:
438
- linear-gradient(90deg, oklch(from var(--color-success-400) l c h / 0.15), oklch(from var(--color-success-600) l c h / 0.15)),
330
+ linear-gradient(
331
+ 180deg,
332
+ oklch(from var(--success) l c h / 0.18),
333
+ oklch(from var(--success) l c h / 0.06)
334
+ ),
439
335
  var(--background);
440
336
  }
441
337
 
@@ -456,4 +352,27 @@
456
352
  @keyframes ring-wave {
457
353
  0%, 100% { transform: scale(1); }
458
354
  50% { transform: scale(1.15); }
355
+ }
356
+
357
+ /* ── Button dual-dot chase (loading state) ───── */
358
+
359
+ @keyframes button-chase-a {
360
+ 0%, 100% { opacity: 1; }
361
+ 50% { opacity: 0.25; }
362
+ }
363
+
364
+ @keyframes button-chase-b {
365
+ 0%, 100% { opacity: 0.25; }
366
+ 50% { opacity: 1; }
367
+ }
368
+
369
+ .animate-button-chase-a { animation: button-chase-a 0.9s ease-in-out infinite; }
370
+ .animate-button-chase-b { animation: button-chase-b 0.9s ease-in-out infinite; }
371
+
372
+ @media (prefers-reduced-motion: reduce) {
373
+ .animate-button-chase-a,
374
+ .animate-button-chase-b {
375
+ animation: none;
376
+ opacity: 1;
377
+ }
459
378
  }
@@ -1,27 +0,0 @@
1
- import { cn } from "@ac/lib/cn";
2
-
3
- export function Spinner({ className }: { className?: string }) {
4
- return (
5
- <svg
6
- className={cn("animate-spin motion-reduce:animate-none", className)}
7
- xmlns="http://www.w3.org/2000/svg"
8
- fill="none"
9
- viewBox="0 0 24 24"
10
- aria-hidden="true"
11
- >
12
- <circle
13
- className="opacity-25"
14
- cx="12"
15
- cy="12"
16
- r="10"
17
- stroke="currentColor"
18
- strokeWidth="4"
19
- />
20
- <path
21
- className="opacity-75"
22
- fill="currentColor"
23
- d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
24
- />
25
- </svg>
26
- );
27
- }