@a4ui/core 0.3.0 â 0.4.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.
- package/README.md +58 -7
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1002 -712
- package/dist/layout/ThemedScenery.d.ts +20 -0
- package/dist/styles.css +399 -91
- package/dist/themes/index.d.ts +34 -0
- package/dist/themes/palettes.d.ts +42 -0
- package/package.json +18 -3
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { JSX } from 'solid-js';
|
|
2
|
+
/** Props for {@link ThemedScenery}. */
|
|
3
|
+
export interface ThemedSceneryProps {
|
|
4
|
+
/** Emoji/text glyphs scattered and gently floating across the backdrop. */
|
|
5
|
+
motifs: string[];
|
|
6
|
+
/** How many glyphs to render. @default 16 */
|
|
7
|
+
count?: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* A lightweight, theme-tinted backdrop for non-`space` themes: the same
|
|
11
|
+
* token-driven nebula as {@link SpaceBackground} plus slowly floating motif
|
|
12
|
+
* glyphs you pass in. Mount it as {@link AppShell}'s `background` (fixed z-0
|
|
13
|
+
* layer behind all content). Motion is skipped under `motionReduced()`.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* <AppShell background={<ThemedScenery motifs={['ðĶ', 'ðŋ', 'ðĶī']} />}>âĶ</AppShell>
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare function ThemedScenery(props: ThemedSceneryProps): JSX.Element;
|
package/dist/styles.css
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
--accent: 199 89% 55%;
|
|
24
24
|
--accent-foreground: 0 0% 100%;
|
|
25
25
|
--ring: 217 91% 52%;
|
|
26
|
-
--destructive: 0 72%
|
|
26
|
+
--destructive: 0 72% 52%;
|
|
27
27
|
--destructive-foreground: 0 0% 100%;
|
|
28
28
|
|
|
29
29
|
/* Semantic data colors (financial direction) â constant across themes. */
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
--accent: 199 89% 48%;
|
|
60
60
|
--accent-foreground: 0 0% 100%;
|
|
61
61
|
--ring: 217 91% 52%;
|
|
62
|
-
--destructive: 0 72%
|
|
62
|
+
--destructive: 0 72% 50%;
|
|
63
63
|
--destructive-foreground: 0 0% 100%;
|
|
64
64
|
}
|
|
65
65
|
|
|
@@ -75,57 +75,127 @@ body {
|
|
|
75
75
|
|
|
76
76
|
/* Route/page cross-fade (AppShell wraps routed content in a <Transition>). */
|
|
77
77
|
.page-enter-active,
|
|
78
|
-
.page-exit-active {
|
|
78
|
+
.page-exit-active {
|
|
79
|
+
transition: opacity 0.16s ease-out;
|
|
80
|
+
}
|
|
79
81
|
.page-enter,
|
|
80
|
-
.page-exit-to {
|
|
82
|
+
.page-exit-to {
|
|
83
|
+
opacity: 0;
|
|
84
|
+
}
|
|
81
85
|
|
|
82
86
|
/* Modal â MUST be @keyframes (Kobalte Dialog presence listens for
|
|
83
87
|
animationend, not transitionend, or the exit never resolves). */
|
|
84
|
-
@keyframes modal-overlay-in {
|
|
85
|
-
|
|
88
|
+
@keyframes modal-overlay-in {
|
|
89
|
+
from {
|
|
90
|
+
opacity: 0;
|
|
91
|
+
}
|
|
92
|
+
to {
|
|
93
|
+
opacity: 1;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
@keyframes modal-overlay-out {
|
|
97
|
+
from {
|
|
98
|
+
opacity: 1;
|
|
99
|
+
}
|
|
100
|
+
to {
|
|
101
|
+
opacity: 0;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
86
104
|
@keyframes modal-content-in {
|
|
87
|
-
from {
|
|
88
|
-
|
|
105
|
+
from {
|
|
106
|
+
opacity: 0;
|
|
107
|
+
transform: scale(0.96) translateY(4px);
|
|
108
|
+
}
|
|
109
|
+
to {
|
|
110
|
+
opacity: 1;
|
|
111
|
+
transform: scale(1) translateY(0);
|
|
112
|
+
}
|
|
89
113
|
}
|
|
90
114
|
@keyframes modal-content-out {
|
|
91
|
-
from {
|
|
92
|
-
|
|
115
|
+
from {
|
|
116
|
+
opacity: 1;
|
|
117
|
+
transform: scale(1) translateY(0);
|
|
118
|
+
}
|
|
119
|
+
to {
|
|
120
|
+
opacity: 0;
|
|
121
|
+
transform: scale(0.96) translateY(4px);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
.modal-overlay[data-expanded] {
|
|
125
|
+
animation: modal-overlay-in 0.15s ease-out;
|
|
126
|
+
}
|
|
127
|
+
.modal-overlay[data-closed] {
|
|
128
|
+
animation: modal-overlay-out 0.15s ease-in;
|
|
129
|
+
}
|
|
130
|
+
.modal-content[data-expanded] {
|
|
131
|
+
animation: modal-content-in 0.18s ease-out;
|
|
132
|
+
}
|
|
133
|
+
.modal-content[data-closed] {
|
|
134
|
+
animation: modal-content-out 0.15s ease-in;
|
|
93
135
|
}
|
|
94
|
-
.modal-overlay[data-expanded] { animation: modal-overlay-in 0.15s ease-out; }
|
|
95
|
-
.modal-overlay[data-closed] { animation: modal-overlay-out 0.15s ease-in; }
|
|
96
|
-
.modal-content[data-expanded] { animation: modal-content-in 0.18s ease-out; }
|
|
97
|
-
.modal-content[data-closed] { animation: modal-content-out 0.15s ease-in; }
|
|
98
136
|
|
|
99
137
|
/* Toast â same animationend-only presence mechanism as Dialog. */
|
|
100
138
|
@keyframes toast-in {
|
|
101
|
-
from {
|
|
102
|
-
|
|
139
|
+
from {
|
|
140
|
+
opacity: 0;
|
|
141
|
+
transform: translateX(16px);
|
|
142
|
+
}
|
|
143
|
+
to {
|
|
144
|
+
opacity: 1;
|
|
145
|
+
transform: translateX(0);
|
|
146
|
+
}
|
|
103
147
|
}
|
|
104
148
|
@keyframes toast-out {
|
|
105
|
-
from {
|
|
106
|
-
|
|
149
|
+
from {
|
|
150
|
+
opacity: 1;
|
|
151
|
+
transform: translateX(0);
|
|
152
|
+
}
|
|
153
|
+
to {
|
|
154
|
+
opacity: 0;
|
|
155
|
+
transform: translateX(16px);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
.toast-item[data-opened] {
|
|
159
|
+
animation: toast-in 0.2s ease-out;
|
|
160
|
+
}
|
|
161
|
+
.toast-item[data-closed] {
|
|
162
|
+
animation: toast-out 0.18s ease-in;
|
|
107
163
|
}
|
|
108
|
-
.toast-item[data-opened] { animation: toast-in 0.2s ease-out; }
|
|
109
|
-
.toast-item[data-closed] { animation: toast-out 0.18s ease-in; }
|
|
110
164
|
|
|
111
165
|
/* Table row enter/exit fade. */
|
|
112
166
|
.row-enter-active,
|
|
113
|
-
.row-exit-active {
|
|
167
|
+
.row-exit-active {
|
|
168
|
+
transition: opacity 0.15s ease-out;
|
|
169
|
+
}
|
|
114
170
|
.row-enter,
|
|
115
|
-
.row-exit-to {
|
|
171
|
+
.row-exit-to {
|
|
172
|
+
opacity: 0;
|
|
173
|
+
}
|
|
116
174
|
|
|
117
175
|
/* Drawer / Modal drawer-variant slide-over (Kobalte Dialog presence â
|
|
118
176
|
animationend keyframes, keyed off data-expanded/data-closed like Modal). */
|
|
119
177
|
@keyframes drawer-in {
|
|
120
|
-
from {
|
|
121
|
-
|
|
178
|
+
from {
|
|
179
|
+
transform: translateX(100%);
|
|
180
|
+
}
|
|
181
|
+
to {
|
|
182
|
+
transform: translateX(0);
|
|
183
|
+
}
|
|
122
184
|
}
|
|
123
185
|
@keyframes drawer-out {
|
|
124
|
-
from {
|
|
125
|
-
|
|
186
|
+
from {
|
|
187
|
+
transform: translateX(0);
|
|
188
|
+
}
|
|
189
|
+
to {
|
|
190
|
+
transform: translateX(100%);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
.drawer-content[data-expanded] {
|
|
194
|
+
animation: drawer-in 0.28s cubic-bezier(0.16, 1, 0.3, 1);
|
|
195
|
+
}
|
|
196
|
+
.drawer-content[data-closed] {
|
|
197
|
+
animation: drawer-out 0.2s ease-in;
|
|
126
198
|
}
|
|
127
|
-
.drawer-content[data-expanded] { animation: drawer-in 0.28s cubic-bezier(0.16, 1, 0.3, 1); }
|
|
128
|
-
.drawer-content[data-closed] { animation: drawer-out 0.2s ease-in; }
|
|
129
199
|
|
|
130
200
|
/* Reduced motion: resolve near-instantly rather than removing outright, so
|
|
131
201
|
libraries that gate DOM unmount on transitionend/animationend (Kobalte
|
|
@@ -149,56 +219,123 @@ body {
|
|
|
149
219
|
* content at z-index >= 10 (AppShell already does this). Bundled into
|
|
150
220
|
* `a4ui/styles.css` after the component surfaces. */
|
|
151
221
|
|
|
152
|
-
#space {
|
|
222
|
+
#space {
|
|
223
|
+
position: fixed;
|
|
224
|
+
inset: 0;
|
|
225
|
+
z-index: 0;
|
|
226
|
+
pointer-events: none;
|
|
227
|
+
overflow: hidden;
|
|
228
|
+
}
|
|
153
229
|
|
|
230
|
+
/* Nebula tinted from the active theme (--primary / --accent / --destructive), so
|
|
231
|
+
switching palettes recolors the whole backdrop. Space's tokens keep it blue. */
|
|
154
232
|
#space .sky {
|
|
155
|
-
position: absolute;
|
|
233
|
+
position: absolute;
|
|
234
|
+
inset: 0;
|
|
156
235
|
background:
|
|
157
|
-
radial-gradient(1200px 700px at 82% -8%, hsl(
|
|
158
|
-
radial-gradient(900px 600px at 8% 12%, hsl(
|
|
159
|
-
radial-gradient(1000px 800px at 50% 120%, hsl(
|
|
160
|
-
radial-gradient(700px 500px at 30% 55%, hsl(
|
|
236
|
+
radial-gradient(1200px 700px at 82% -8%, hsl(var(--primary) / 0.34), transparent 60%),
|
|
237
|
+
radial-gradient(900px 600px at 8% 12%, hsl(var(--accent) / 0.28), transparent 60%),
|
|
238
|
+
radial-gradient(1000px 800px at 50% 120%, hsl(var(--accent) / 0.22), transparent 55%),
|
|
239
|
+
radial-gradient(700px 500px at 30% 55%, hsl(var(--destructive) / 0.12), transparent 60%),
|
|
161
240
|
hsl(var(--background));
|
|
162
241
|
}
|
|
163
242
|
[data-theme='light'] #space .sky {
|
|
164
243
|
background:
|
|
165
|
-
radial-gradient(1100px 680px at 84% -10%, hsl(
|
|
166
|
-
radial-gradient(900px 600px at 6% 8%, hsl(
|
|
167
|
-
radial-gradient(1000px 820px at 50% 120%, hsl(
|
|
168
|
-
radial-gradient(700px 500px at 30% 55%, hsl(
|
|
244
|
+
radial-gradient(1100px 680px at 84% -10%, hsl(var(--primary) / 0.22), transparent 60%),
|
|
245
|
+
radial-gradient(900px 600px at 6% 8%, hsl(var(--accent) / 0.2), transparent 60%),
|
|
246
|
+
radial-gradient(1000px 820px at 50% 120%, hsl(var(--accent) / 0.16), transparent 55%),
|
|
247
|
+
radial-gradient(700px 500px at 30% 55%, hsl(var(--destructive) / 0.1), transparent 60%),
|
|
169
248
|
hsl(var(--background));
|
|
170
249
|
}
|
|
171
|
-
@keyframes nebulaShift {
|
|
250
|
+
@keyframes nebulaShift {
|
|
251
|
+
0%,
|
|
252
|
+
100% {
|
|
253
|
+
filter: hue-rotate(0deg);
|
|
254
|
+
}
|
|
255
|
+
50% {
|
|
256
|
+
filter: hue-rotate(18deg);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
172
259
|
|
|
173
260
|
/* Aurora â dark theme only */
|
|
174
261
|
#space .aurora {
|
|
175
|
-
position: absolute;
|
|
176
|
-
|
|
177
|
-
|
|
262
|
+
position: absolute;
|
|
263
|
+
top: -10%;
|
|
264
|
+
left: -10%;
|
|
265
|
+
right: -10%;
|
|
266
|
+
height: 46%;
|
|
267
|
+
background: linear-gradient(
|
|
268
|
+
180deg,
|
|
269
|
+
hsl(var(--accent) / 0.16),
|
|
270
|
+
hsl(var(--primary) / 0.1) 45%,
|
|
271
|
+
transparent 80%
|
|
272
|
+
);
|
|
273
|
+
filter: blur(40px);
|
|
274
|
+
opacity: 0.55;
|
|
275
|
+
mix-blend-mode: screen;
|
|
276
|
+
}
|
|
277
|
+
[data-theme='light'] #space .aurora {
|
|
278
|
+
display: none;
|
|
279
|
+
}
|
|
280
|
+
@keyframes auroraSway {
|
|
281
|
+
0%,
|
|
282
|
+
100% {
|
|
283
|
+
transform: translateX(-2%) scaleY(1);
|
|
284
|
+
opacity: 0.5;
|
|
285
|
+
}
|
|
286
|
+
50% {
|
|
287
|
+
transform: translateX(3%) scaleY(1.08);
|
|
288
|
+
opacity: 0.68;
|
|
289
|
+
}
|
|
178
290
|
}
|
|
179
|
-
[data-theme='light'] #space .aurora { display: none; }
|
|
180
|
-
@keyframes auroraSway { 0%,100% { transform: translateX(-2%) scaleY(1); opacity: .5; } 50% { transform: translateX(3%) scaleY(1.08); opacity: .68; } }
|
|
181
291
|
|
|
182
292
|
/* Randomized starfield â each star is generated in SpaceBackground.tsx with a
|
|
183
293
|
random position/size/brightness/bloom, so there's no visible tiling pattern.
|
|
184
294
|
Static (no drift): moving the field behind the frosted cards re-blurs every
|
|
185
295
|
frame and felt laggy; a subset twinkles for life instead. */
|
|
186
|
-
#space #starfield {
|
|
187
|
-
|
|
296
|
+
#space #starfield {
|
|
297
|
+
position: absolute;
|
|
298
|
+
inset: 0;
|
|
299
|
+
}
|
|
300
|
+
[data-theme='light'] #space #starfield {
|
|
301
|
+
opacity: 0.85;
|
|
302
|
+
}
|
|
188
303
|
/* A few stars drift smoothly like the satellite: each is a tiny element moving
|
|
189
304
|
via its own transform (GPU-composited, cheap), NOT the whole field. Uses
|
|
190
305
|
`alternate` so it eases out and back with no loop jump. Per-star --dx/--dy. */
|
|
191
|
-
@keyframes starDrift {
|
|
306
|
+
@keyframes starDrift {
|
|
307
|
+
from {
|
|
308
|
+
transform: translate(0, 0);
|
|
309
|
+
}
|
|
310
|
+
to {
|
|
311
|
+
transform: translate(var(--dx, 0), var(--dy, 0));
|
|
312
|
+
}
|
|
313
|
+
}
|
|
192
314
|
|
|
193
315
|
/* Rocket exhaust flame (custom SVG rocket in SpaceBackground.tsx) â flickers. */
|
|
194
|
-
.rk-flame {
|
|
195
|
-
|
|
316
|
+
.rk-flame {
|
|
317
|
+
transform-box: fill-box;
|
|
318
|
+
transform-origin: 50% 0%;
|
|
319
|
+
animation: rocketFlame 0.12s ease-in-out infinite alternate;
|
|
320
|
+
}
|
|
321
|
+
@keyframes rocketFlame {
|
|
322
|
+
from {
|
|
323
|
+
transform: scaleY(0.8);
|
|
324
|
+
opacity: 0.85;
|
|
325
|
+
}
|
|
326
|
+
to {
|
|
327
|
+
transform: scaleY(1.06);
|
|
328
|
+
opacity: 1;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
196
331
|
|
|
197
332
|
/* Legacy tiled star layers (kept for parity; the current SpaceBackground scatters
|
|
198
333
|
individual stars into #starfield instead). Sized generously: small dots nearly
|
|
199
334
|
vanish under backdrop-filter blur, so keep them >= 2.5px. */
|
|
200
335
|
#space .stars {
|
|
201
|
-
position: absolute;
|
|
336
|
+
position: absolute;
|
|
337
|
+
inset: -50%;
|
|
338
|
+
background-repeat: repeat;
|
|
202
339
|
background-image:
|
|
203
340
|
radial-gradient(4px 4px at 20px 30px, hsl(var(--foreground)), transparent),
|
|
204
341
|
radial-gradient(3.6px 3.6px at 120px 90px, hsl(var(--foreground)), transparent),
|
|
@@ -207,7 +344,9 @@ body {
|
|
|
207
344
|
radial-gradient(3.4px 3.4px at 380px 220px, hsl(330 80% 84%), transparent),
|
|
208
345
|
radial-gradient(3px 3px at 90px 190px, hsl(var(--foreground)), transparent),
|
|
209
346
|
radial-gradient(2.8px 2.8px at 260px 250px, hsl(48 90% 82%), transparent);
|
|
210
|
-
background-size: 420px 300px;
|
|
347
|
+
background-size: 420px 300px;
|
|
348
|
+
opacity: 1;
|
|
349
|
+
animation: drift 140s linear infinite;
|
|
211
350
|
}
|
|
212
351
|
[data-theme='light'] #space .stars {
|
|
213
352
|
background-image:
|
|
@@ -219,9 +358,15 @@ body {
|
|
|
219
358
|
radial-gradient(3px 3px at 90px 190px, hsl(40 90% 50%), transparent),
|
|
220
359
|
radial-gradient(2.8px 2.8px at 260px 250px, hsl(48 90% 52%), transparent);
|
|
221
360
|
}
|
|
222
|
-
#space .stars.s2 {
|
|
361
|
+
#space .stars.s2 {
|
|
362
|
+
background-size: 640px 480px;
|
|
363
|
+
opacity: 0.85;
|
|
364
|
+
animation-duration: 200s;
|
|
365
|
+
}
|
|
223
366
|
#space .stars.s3 {
|
|
224
|
-
background-size: 260px 190px;
|
|
367
|
+
background-size: 260px 190px;
|
|
368
|
+
opacity: 1;
|
|
369
|
+
animation-duration: 95s;
|
|
225
370
|
background-image:
|
|
226
371
|
radial-gradient(6px 6px at 40px 50px, hsl(var(--foreground)), transparent),
|
|
227
372
|
radial-gradient(5.6px 5.6px at 160px 130px, hsl(199 89% 85%), transparent),
|
|
@@ -229,77 +374,240 @@ body {
|
|
|
229
374
|
radial-gradient(5px 5px at 90px 20px, hsl(330 85% 85%), transparent);
|
|
230
375
|
}
|
|
231
376
|
[data-theme='light'] #space .stars.s3 {
|
|
232
|
-
opacity: .8;
|
|
377
|
+
opacity: 0.8;
|
|
233
378
|
background-image:
|
|
234
379
|
radial-gradient(6px 6px at 40px 50px, hsl(38 92% 50%), transparent),
|
|
235
380
|
radial-gradient(5.6px 5.6px at 160px 130px, hsl(45 95% 54%), transparent),
|
|
236
381
|
radial-gradient(5.8px 5.8px at 250px 40px, hsl(30 88% 48%), transparent),
|
|
237
382
|
radial-gradient(5px 5px at 90px 20px, hsl(50 92% 55%), transparent);
|
|
238
383
|
}
|
|
239
|
-
@keyframes drift {
|
|
384
|
+
@keyframes drift {
|
|
385
|
+
from {
|
|
386
|
+
transform: translate3d(0, 0, 0);
|
|
387
|
+
}
|
|
388
|
+
to {
|
|
389
|
+
transform: translate3d(-420px, -300px, 0);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
240
392
|
|
|
241
393
|
/* Individually-placed twinkling stars */
|
|
242
394
|
.twinkle {
|
|
243
|
-
position: absolute;
|
|
244
|
-
|
|
395
|
+
position: absolute;
|
|
396
|
+
width: 5px;
|
|
397
|
+
height: 5px;
|
|
398
|
+
border-radius: 50%;
|
|
399
|
+
background: hsl(var(--foreground));
|
|
400
|
+
box-shadow: 0 0 14px 3px hsl(var(--foreground) / 0.9);
|
|
245
401
|
animation: twinkle 3.2s ease-in-out infinite;
|
|
246
402
|
}
|
|
247
|
-
[data-theme='light'] .twinkle {
|
|
248
|
-
|
|
403
|
+
[data-theme='light'] .twinkle {
|
|
404
|
+
background: hsl(40 92% 50%);
|
|
405
|
+
box-shadow: 0 0 14px 3px hsl(40 92% 50% / 0.85);
|
|
406
|
+
}
|
|
407
|
+
@keyframes twinkle {
|
|
408
|
+
0%,
|
|
409
|
+
100% {
|
|
410
|
+
opacity: 0.25;
|
|
411
|
+
transform: scale(0.6);
|
|
412
|
+
}
|
|
413
|
+
50% {
|
|
414
|
+
opacity: 1;
|
|
415
|
+
transform: scale(1.15);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
249
418
|
|
|
250
419
|
/* Constellations â thin line art connecting a handful of stars */
|
|
251
|
-
#space .constellation {
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
420
|
+
#space .constellation {
|
|
421
|
+
position: absolute;
|
|
422
|
+
opacity: 1;
|
|
423
|
+
}
|
|
424
|
+
[data-theme='light'] #space .constellation {
|
|
425
|
+
opacity: 0.6;
|
|
426
|
+
}
|
|
427
|
+
[data-theme='light'] #space .constellation .cline {
|
|
428
|
+
stroke: hsl(38 92% 50%) !important;
|
|
429
|
+
}
|
|
430
|
+
[data-theme='light'] #space .constellation .cdot {
|
|
431
|
+
fill: hsl(222 47% 20%) !important;
|
|
432
|
+
}
|
|
255
433
|
|
|
256
434
|
/* Planets / moons â decorative, corner-anchored, gentle float */
|
|
257
|
-
.planet {
|
|
435
|
+
.planet {
|
|
436
|
+
border-radius: 50%;
|
|
437
|
+
}
|
|
258
438
|
.planet::after {
|
|
259
|
-
content: '';
|
|
260
|
-
|
|
439
|
+
content: '';
|
|
440
|
+
position: absolute;
|
|
441
|
+
inset: -34% -55%;
|
|
442
|
+
border-radius: 50%;
|
|
443
|
+
border: 3px solid hsl(var(--foreground) / 0.18);
|
|
444
|
+
transform: rotate(-24deg);
|
|
445
|
+
}
|
|
446
|
+
.planet-glow {
|
|
447
|
+
border-radius: 50%;
|
|
448
|
+
filter: blur(2px);
|
|
449
|
+
}
|
|
450
|
+
@keyframes floaty {
|
|
451
|
+
0%,
|
|
452
|
+
100% {
|
|
453
|
+
transform: translateY(0) rotate(0deg);
|
|
454
|
+
}
|
|
455
|
+
50% {
|
|
456
|
+
transform: translateY(-14px) rotate(4deg);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
.floaty {
|
|
460
|
+
animation: floaty 12s ease-in-out infinite;
|
|
461
|
+
}
|
|
462
|
+
.floaty.slow {
|
|
463
|
+
animation-duration: 18s;
|
|
261
464
|
}
|
|
262
|
-
.planet-glow { border-radius: 50%; filter: blur(2px); }
|
|
263
|
-
@keyframes floaty { 0%,100% { transform: translateY(0) rotate(0deg); } 50% { transform: translateY(-14px) rotate(4deg); } }
|
|
264
|
-
.floaty { animation: floaty 12s ease-in-out infinite; }
|
|
265
|
-
.floaty.slow { animation-duration: 18s; }
|
|
266
465
|
|
|
267
466
|
/* Asteroid belt (small drifting rocks) */
|
|
268
|
-
.asteroid {
|
|
269
|
-
|
|
467
|
+
.asteroid {
|
|
468
|
+
border-radius: 40% 55% 50% 45%;
|
|
469
|
+
background: hsl(var(--foreground) / 0.35);
|
|
470
|
+
}
|
|
471
|
+
@keyframes asteroidDrift {
|
|
472
|
+
0%,
|
|
473
|
+
100% {
|
|
474
|
+
transform: translate(0, 0) rotate(0deg);
|
|
475
|
+
}
|
|
476
|
+
50% {
|
|
477
|
+
transform: translate(-8px, 6px) rotate(25deg);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
270
480
|
|
|
271
481
|
/* Shooting star â bright core + tapered glowing trail */
|
|
272
482
|
.shooter {
|
|
273
|
-
position: absolute;
|
|
274
|
-
|
|
275
|
-
|
|
483
|
+
position: absolute;
|
|
484
|
+
height: 2.5px;
|
|
485
|
+
border-radius: 999px;
|
|
486
|
+
transform-origin: left center;
|
|
487
|
+
background: linear-gradient(
|
|
488
|
+
90deg,
|
|
489
|
+
hsla(0, 0%, 100%, 0) 0%,
|
|
490
|
+
hsla(199, 90%, 85%, 0.55) 55%,
|
|
491
|
+
hsla(0, 0%, 100%, 0.98) 100%
|
|
492
|
+
);
|
|
493
|
+
filter: blur(0.2px) drop-shadow(0 0 3px hsla(199, 90%, 80%, 0.5));
|
|
276
494
|
}
|
|
277
495
|
.shooter::before {
|
|
278
|
-
content: '';
|
|
279
|
-
|
|
280
|
-
|
|
496
|
+
content: '';
|
|
497
|
+
position: absolute;
|
|
498
|
+
right: -2px;
|
|
499
|
+
top: 50%;
|
|
500
|
+
width: 6px;
|
|
501
|
+
height: 6px;
|
|
502
|
+
border-radius: 50%;
|
|
503
|
+
transform: translateY(-50%);
|
|
504
|
+
background: radial-gradient(circle, #fff 0%, hsla(199, 95%, 88%, 0.95) 50%, transparent 75%);
|
|
505
|
+
box-shadow:
|
|
506
|
+
0 0 8px 2px #fff,
|
|
507
|
+
0 0 20px 7px hsla(199, 90%, 75%, 0.85),
|
|
508
|
+
0 0 38px 14px hsla(199, 90%, 60%, 0.4);
|
|
281
509
|
}
|
|
282
510
|
.shooter::after {
|
|
283
|
-
content: '';
|
|
284
|
-
|
|
511
|
+
content: '';
|
|
512
|
+
position: absolute;
|
|
513
|
+
left: 0;
|
|
514
|
+
top: 50%;
|
|
515
|
+
width: 55%;
|
|
516
|
+
height: 1px;
|
|
517
|
+
transform: translateY(-50%);
|
|
518
|
+
background: hsla(199, 85%, 92%, 0.65);
|
|
519
|
+
filter: blur(2px);
|
|
285
520
|
}
|
|
286
521
|
|
|
287
522
|
/* Satellite (drifting glyph, e.g. a lucide "satellite" icon) */
|
|
288
|
-
@keyframes satelliteDrift {
|
|
289
|
-
|
|
523
|
+
@keyframes satelliteDrift {
|
|
524
|
+
from {
|
|
525
|
+
transform: translate(0, 0) rotate(-18deg);
|
|
526
|
+
}
|
|
527
|
+
to {
|
|
528
|
+
transform: translate(126vw, 34vh) rotate(-18deg);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
#satellite {
|
|
532
|
+
animation: satelliteDrift 46s linear infinite;
|
|
533
|
+
}
|
|
290
534
|
|
|
291
535
|
/* Cursor-following ambient glow (nebula that trails the pointer) */
|
|
292
536
|
#cursorGlow {
|
|
293
|
-
border-radius: 50%;
|
|
294
|
-
|
|
295
|
-
|
|
537
|
+
border-radius: 50%;
|
|
538
|
+
transform: translate(-50%, -50%);
|
|
539
|
+
background: radial-gradient(circle, hsl(217 91% 60% / 0.1), transparent 70%);
|
|
540
|
+
opacity: 0;
|
|
541
|
+
transition: opacity 0.4s ease;
|
|
296
542
|
}
|
|
297
543
|
|
|
298
544
|
@media (prefers-reduced-motion: reduce) {
|
|
299
|
-
html:not(.force-motion) #space .stars,
|
|
300
|
-
html:not(.force-motion) .
|
|
301
|
-
html:not(.force-motion)
|
|
302
|
-
html:not(.force-motion)
|
|
303
|
-
html:not(.force-motion) #
|
|
304
|
-
.
|
|
545
|
+
html:not(.force-motion) #space .stars,
|
|
546
|
+
html:not(.force-motion) .twinkle,
|
|
547
|
+
html:not(.force-motion) .floaty,
|
|
548
|
+
html:not(.force-motion) .shooter,
|
|
549
|
+
html:not(.force-motion) #satellite,
|
|
550
|
+
html:not(.force-motion) .asteroid {
|
|
551
|
+
animation: none !important;
|
|
552
|
+
}
|
|
553
|
+
html:not(.force-motion) #cursorGlow {
|
|
554
|
+
display: none !important;
|
|
555
|
+
}
|
|
556
|
+
html:not(.force-motion) #space .sky,
|
|
557
|
+
html:not(.force-motion) #space .aurora {
|
|
558
|
+
animation: none !important;
|
|
559
|
+
}
|
|
560
|
+
.card.glow-edge::before {
|
|
561
|
+
display: none;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/* ---- Generic themed scenery (non-space themes) --------------------------
|
|
566
|
+
A themed nebula (same token-tinted gradients as the starfield) plus a field
|
|
567
|
+
of slowly floating motif glyphs â <ThemedScenery motifs={[...]} />. Lighter
|
|
568
|
+
than the bespoke SpaceBackground so every extra theme costs almost nothing. */
|
|
569
|
+
#scenery {
|
|
570
|
+
position: fixed;
|
|
571
|
+
inset: 0;
|
|
572
|
+
z-index: 0;
|
|
573
|
+
pointer-events: none;
|
|
574
|
+
overflow: hidden;
|
|
575
|
+
}
|
|
576
|
+
#scenery .themed-sky {
|
|
577
|
+
position: absolute;
|
|
578
|
+
inset: 0;
|
|
579
|
+
background:
|
|
580
|
+
radial-gradient(1200px 700px at 82% -8%, hsl(var(--primary) / 0.34), transparent 60%),
|
|
581
|
+
radial-gradient(900px 600px at 8% 12%, hsl(var(--accent) / 0.28), transparent 60%),
|
|
582
|
+
radial-gradient(1000px 800px at 50% 120%, hsl(var(--accent) / 0.22), transparent 55%),
|
|
583
|
+
radial-gradient(700px 500px at 30% 55%, hsl(var(--destructive) / 0.12), transparent 60%),
|
|
584
|
+
hsl(var(--background));
|
|
585
|
+
}
|
|
586
|
+
[data-theme='light'] #scenery .themed-sky {
|
|
587
|
+
background:
|
|
588
|
+
radial-gradient(1100px 680px at 84% -10%, hsl(var(--primary) / 0.22), transparent 60%),
|
|
589
|
+
radial-gradient(900px 600px at 6% 8%, hsl(var(--accent) / 0.2), transparent 60%),
|
|
590
|
+
radial-gradient(1000px 820px at 50% 120%, hsl(var(--accent) / 0.16), transparent 55%),
|
|
591
|
+
radial-gradient(700px 500px at 30% 55%, hsl(var(--destructive) / 0.1), transparent 60%),
|
|
592
|
+
hsl(var(--background));
|
|
593
|
+
}
|
|
594
|
+
#scenery .motif {
|
|
595
|
+
position: absolute;
|
|
596
|
+
user-select: none;
|
|
597
|
+
will-change: transform;
|
|
598
|
+
animation: motifFloat var(--dur, 9s) ease-in-out var(--delay, 0s) infinite;
|
|
599
|
+
}
|
|
600
|
+
@keyframes motifFloat {
|
|
601
|
+
0%,
|
|
602
|
+
100% {
|
|
603
|
+
transform: translateY(0) rotate(var(--r, 0deg));
|
|
604
|
+
}
|
|
605
|
+
50% {
|
|
606
|
+
transform: translateY(-16px) rotate(calc(var(--r, 0deg) + 5deg));
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
@media (prefers-reduced-motion: reduce) {
|
|
610
|
+
html:not(.force-motion) #scenery .motif {
|
|
611
|
+
animation: none !important;
|
|
612
|
+
}
|
|
305
613
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Palette, ThemeDefinition } from './palettes';
|
|
2
|
+
export type { Palette, ThemeDefinition } from './palettes';
|
|
3
|
+
export { themes, space, dino, doctor, scientist, soccer, TOKEN_ORDER } from './palettes';
|
|
4
|
+
/**
|
|
5
|
+
* Render a theme to the CSS you'd paste into your own stylesheet: a `:root`
|
|
6
|
+
* block (dark) plus a `:root[data-theme='light']` block. Same output the docs
|
|
7
|
+
* Theme Builder exports.
|
|
8
|
+
*/
|
|
9
|
+
export declare function themeToCss(theme: ThemeDefinition): string;
|
|
10
|
+
/** Render a theme's tokens to a `{ dark, light }` JSON object. */
|
|
11
|
+
export declare function themeToJson(theme: ThemeDefinition): {
|
|
12
|
+
dark: Palette;
|
|
13
|
+
light: Palette;
|
|
14
|
+
};
|
|
15
|
+
declare const activeTheme: import('solid-js').Accessor<ThemeDefinition>;
|
|
16
|
+
/** Reactive accessor for the currently applied theme. */
|
|
17
|
+
export { activeTheme };
|
|
18
|
+
/**
|
|
19
|
+
* Apply a theme's palette globally by injecting/replacing the
|
|
20
|
+
* `<style id="a4ui-theme">` element. No-op during SSR. Does not persist or update
|
|
21
|
+
* the reactive signal â use {@link selectTheme} for the full, persisted version.
|
|
22
|
+
*/
|
|
23
|
+
export declare function applyThemeDefinition(theme: ThemeDefinition): void;
|
|
24
|
+
/**
|
|
25
|
+
* Select the active theme by definition or name: applies it, updates the
|
|
26
|
+
* reactive {@link activeTheme} signal, and persists the choice to localStorage.
|
|
27
|
+
* Unknown names are ignored.
|
|
28
|
+
*/
|
|
29
|
+
export declare function selectTheme(theme: ThemeDefinition | string): void;
|
|
30
|
+
/**
|
|
31
|
+
* Restore the persisted theme (or fall back to Space) and apply it. Call once at
|
|
32
|
+
* startup. No-op during SSR.
|
|
33
|
+
*/
|
|
34
|
+
export declare function initTheme(): void;
|