@nexub/themes 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -3
- package/src/base.css +8 -627
- package/src/core.css +631 -0
- package/src/marketing.css +194 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nexub/themes",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "CSS theme files for Nexub Design System — light, dark, and brand themes (Leap, Bookub, Payub, Founderub) as importable CSS.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/Nexub-AI/nexub-ds#readme",
|
|
@@ -27,6 +27,8 @@
|
|
|
27
27
|
],
|
|
28
28
|
"exports": {
|
|
29
29
|
"./base": "./src/base.css",
|
|
30
|
+
"./core": "./src/core.css",
|
|
31
|
+
"./fonts": "./src/fonts.css",
|
|
30
32
|
"./light": "./src/light.css",
|
|
31
33
|
"./dark": "./src/dark.css",
|
|
32
34
|
"./glass": "./src/glass.css",
|
|
@@ -34,10 +36,11 @@
|
|
|
34
36
|
"./leap": "./src/leap.css",
|
|
35
37
|
"./bookub": "./src/bookub.css",
|
|
36
38
|
"./payub": "./src/payub.css",
|
|
37
|
-
"./founderub": "./src/founderub.css"
|
|
39
|
+
"./founderub": "./src/founderub.css",
|
|
40
|
+
"./marketing": "./src/marketing.css"
|
|
38
41
|
},
|
|
39
42
|
"dependencies": {
|
|
40
|
-
"@nexub/tokens": "3.
|
|
43
|
+
"@nexub/tokens": "3.1.0"
|
|
41
44
|
},
|
|
42
45
|
"devDependencies": {
|
|
43
46
|
"@fontsource-variable/inter": "5.3.0",
|
package/src/base.css
CHANGED
|
@@ -1,635 +1,16 @@
|
|
|
1
1
|
/* @nexub/themes — base.css
|
|
2
|
-
Global resets, focus ring, body, scrollbar, reduced-motion.
|
|
2
|
+
Global resets, focus ring, body, scrollbar, reduced-motion (core.css), plus
|
|
3
|
+
the Nexub fonts and the ambient page backdrop.
|
|
3
4
|
Import this once at the root of your app before light.css or dark.css. */
|
|
4
5
|
|
|
5
|
-
/* Plus Jakarta Sans — the Nexub DS
|
|
6
|
-
Fontsource); variable weights
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
/* Plus Jakarta Sans and Inter — the Nexub DS typefaces. Self-hosted (OFL-1.1,
|
|
7
|
+
from Fontsource); variable weights, normal + italic. Subsets load on demand
|
|
8
|
+
via unicode-range, so only the glyphs a page uses are fetched. Every file is
|
|
9
|
+
big enough that bundlers emit it rather than inline a data: URL, so
|
|
10
|
+
`font-src 'self'` works (see scripts/build-fonts.mjs). */
|
|
10
11
|
@import './fonts.css';
|
|
11
|
-
@import '
|
|
12
|
-
@import '@nexub/tokens/css/roles';
|
|
13
|
-
|
|
14
|
-
/* ─── Theme tokens beside the color roles ─────────────────────────────────
|
|
15
|
-
3.0 removed the legacy semantic aliases (--color-success-500,
|
|
16
|
-
--color-text-info, …); use the roles. `npx nexub-migrate --write` moves old
|
|
17
|
-
code over. */
|
|
18
|
-
:root {
|
|
19
|
-
/* Focus ring follows the theme's ring tokens (the tokens default is a fixed
|
|
20
|
-
white/blue pair, wrong in dark mode and brand themes). */
|
|
21
|
-
--shadow-focus: 0 0 0 2px var(--color-ring-offset), 0 0 0 4px var(--color-ring-default);
|
|
22
|
-
|
|
23
|
-
/* Solid fills under white text. Fixed palette tones (they do NOT flip in dark
|
|
24
|
-
mode): tone 40 vs white is >= 4.5:1 by HCT construction; hover = tone 30.
|
|
25
|
-
Brand themes override accent. Phase 2 moves components to on-* roles. */
|
|
26
|
-
--color-fill-primary: var(--color-palette-primary-40);
|
|
27
|
-
--color-fill-primary-hover: var(--color-palette-primary-30);
|
|
28
|
-
--color-fill-info: var(--color-palette-info-40);
|
|
29
|
-
--color-fill-info-hover: var(--color-palette-info-30);
|
|
30
|
-
--color-fill-success: var(--color-palette-success-40);
|
|
31
|
-
--color-fill-success-hover: var(--color-palette-success-30);
|
|
32
|
-
--color-fill-warning: var(--color-palette-warning-40);
|
|
33
|
-
--color-fill-warning-hover: var(--color-palette-warning-30);
|
|
34
|
-
--color-fill-danger: var(--color-palette-error-40);
|
|
35
|
-
--color-fill-danger-hover: var(--color-palette-error-30);
|
|
36
|
-
--color-fill-leap: var(--color-palette-leap-40);
|
|
37
|
-
--color-fill-leap-hover: var(--color-palette-leap-30);
|
|
38
|
-
--color-fill-bookub: var(--color-palette-bookub-40);
|
|
39
|
-
--color-fill-bookub-hover: var(--color-palette-bookub-30);
|
|
40
|
-
--color-fill-payub: var(--color-palette-payub-40);
|
|
41
|
-
--color-fill-payub-hover: var(--color-palette-payub-30);
|
|
42
|
-
--color-fill-founderub: var(--color-palette-founderub-40);
|
|
43
|
-
--color-fill-founderub-hover: var(--color-palette-founderub-30);
|
|
44
|
-
--color-fill-accent: var(--color-fill-primary);
|
|
45
|
-
--color-fill-accent-hover: var(--color-fill-primary-hover);
|
|
46
|
-
|
|
47
|
-
/* scrim behind modal surfaces (Dialog, AlertDialog, Sheet/Drawer, CommandPalette) */
|
|
48
|
-
--color-overlay: rgb(0 0 0 / 0.5);
|
|
49
|
-
|
|
50
|
-
/* accent fallback — used without any brand theme applied (PKG-B03) */
|
|
51
|
-
--color-accent-500: var(--color-brand-primary-500);
|
|
52
|
-
--color-accent-600: var(--color-brand-primary-600);
|
|
53
|
-
|
|
54
|
-
/* brand tone shorthands — aliased from full token names (PKG-B02) */
|
|
55
|
-
--color-leap-50: var(--color-accent-leap-50);
|
|
56
|
-
--color-leap-100: var(--color-accent-leap-100);
|
|
57
|
-
--color-leap-600: var(--color-accent-leap-600);
|
|
58
|
-
--color-leap-700: var(--color-accent-leap-700);
|
|
59
|
-
--color-leap-bg: rgba(99, 102, 241, 0.10);
|
|
60
|
-
--color-leap-border: rgba(99, 102, 241, 0.25);
|
|
61
|
-
|
|
62
|
-
--color-bookub-50: var(--color-accent-bookub-50);
|
|
63
|
-
--color-bookub-100: var(--color-accent-bookub-100);
|
|
64
|
-
--color-bookub-600: var(--color-accent-bookub-600);
|
|
65
|
-
--color-bookub-700: var(--color-accent-bookub-700);
|
|
66
|
-
--color-bookub-bg: rgba(16, 185, 129, 0.10);
|
|
67
|
-
--color-bookub-border: rgba(16, 185, 129, 0.25);
|
|
68
|
-
|
|
69
|
-
--color-payub-50: var(--color-accent-payub-50);
|
|
70
|
-
--color-payub-100: var(--color-accent-payub-100);
|
|
71
|
-
--color-payub-600: var(--color-accent-payub-600);
|
|
72
|
-
--color-payub-700: var(--color-accent-payub-700);
|
|
73
|
-
--color-payub-bg: rgba(139, 92, 246, 0.10);
|
|
74
|
-
--color-payub-border: rgba(139, 92, 246, 0.25);
|
|
75
|
-
|
|
76
|
-
--color-founderub-50: var(--color-accent-founderub-50);
|
|
77
|
-
--color-founderub-100: var(--color-accent-founderub-100);
|
|
78
|
-
--color-founderub-600: var(--color-accent-founderub-600);
|
|
79
|
-
--color-founderub-700: var(--color-accent-founderub-700);
|
|
80
|
-
--color-founderub-bg: rgba(245, 158, 11, 0.10);
|
|
81
|
-
--color-founderub-border: rgba(245, 158, 11, 0.25);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
*, *::before, *::after {
|
|
85
|
-
box-sizing: border-box;
|
|
86
|
-
border-color: var(--color-outline-variant);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
html {
|
|
90
|
-
font-family: var(--font-family-sans);
|
|
91
|
-
/* 100%, not 16px: tokens are in rem (3.0) and follow the user's browser font size. */
|
|
92
|
-
font-size: 100%;
|
|
93
|
-
line-height: 1.6;
|
|
94
|
-
color: var(--color-on-surface);
|
|
95
|
-
background-color: var(--color-surface);
|
|
96
|
-
scroll-behavior: smooth;
|
|
97
|
-
-webkit-font-smoothing: antialiased;
|
|
98
|
-
-moz-osx-font-smoothing: grayscale;
|
|
99
|
-
text-size-adjust: 100%;
|
|
100
|
-
/* never fake bold/italic; Inter's optical sizes follow font-size */
|
|
101
|
-
font-synthesis: none;
|
|
102
|
-
font-optical-sizing: auto;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/* Form controls don't inherit fonts by default — without this, apps that
|
|
106
|
-
don't use Tailwind's preflight would render buttons/inputs in the system UI
|
|
107
|
-
font instead of Inter. */
|
|
108
|
-
button, input, select, textarea, optgroup {
|
|
109
|
-
font-family: inherit;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/* Pointer cursor on buttons. Tailwind v3's preflight set it; v4's doesn't, so
|
|
113
|
-
this keeps Nexub buttons the same on both. Zero specificity (:where), so any
|
|
114
|
-
cursor-* utility and v3's preflight still win. */
|
|
115
|
-
:where(button:not(:disabled), [role='button']:not(:disabled)) {
|
|
116
|
-
cursor: pointer;
|
|
117
|
-
}
|
|
12
|
+
@import './core.css';
|
|
118
13
|
|
|
119
14
|
body {
|
|
120
|
-
min-height: 100vh;
|
|
121
|
-
margin: 0;
|
|
122
15
|
background: var(--gradient-hero-ambient);
|
|
123
16
|
}
|
|
124
|
-
|
|
125
|
-
/* Focus ring: one ring for everything. The outline follows border-radius, so
|
|
126
|
-
it hugs capsules and fields. Contrast >= 3:1 on every surface (ring = primary). */
|
|
127
|
-
:focus-visible {
|
|
128
|
-
outline: 3px solid var(--color-ring-default);
|
|
129
|
-
outline-offset: 2px;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
@media (forced-colors: active) {
|
|
133
|
-
:focus-visible { outline-color: Highlight; }
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/* Headings: brand display face, balanced wrapping */
|
|
137
|
-
h1, h2, h3, h4, h5, h6 {
|
|
138
|
-
margin: 0;
|
|
139
|
-
font-family: var(--font-family-display);
|
|
140
|
-
font-weight: var(--font-weight-bold);
|
|
141
|
-
line-height: 1.2;
|
|
142
|
-
color: var(--color-on-surface);
|
|
143
|
-
text-wrap: balance;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/* Paragraphs / lists */
|
|
147
|
-
p, ul, ol {
|
|
148
|
-
margin: 0;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
p {
|
|
152
|
-
text-wrap: pretty;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/* Links */
|
|
156
|
-
a {
|
|
157
|
-
color: var(--color-primary);
|
|
158
|
-
text-decoration: underline;
|
|
159
|
-
text-underline-offset: 0.3em;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
a:hover {
|
|
163
|
-
opacity: 0.8;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/* Images */
|
|
167
|
-
img, video, svg {
|
|
168
|
-
display: block;
|
|
169
|
-
max-width: 100%;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/* Code */
|
|
173
|
-
code, kbd, pre, samp {
|
|
174
|
-
font-family: var(--font-family-mono);
|
|
175
|
-
font-size: 0.875em;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/* Selection */
|
|
179
|
-
::selection {
|
|
180
|
-
background-color: color-mix(in srgb, var(--color-primary) 20%, transparent);
|
|
181
|
-
color: var(--color-on-surface);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/* Scrollbar (webkit) */
|
|
185
|
-
::-webkit-scrollbar {
|
|
186
|
-
width: 8px;
|
|
187
|
-
height: 8px;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
::-webkit-scrollbar-track {
|
|
191
|
-
background: var(--color-surface-container-low);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
::-webkit-scrollbar-thumb {
|
|
195
|
-
background: var(--color-outline);
|
|
196
|
-
border-radius: var(--radius-full);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
::-webkit-scrollbar-thumb:hover {
|
|
200
|
-
background: var(--color-on-surface-muted);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/* Reduced motion */
|
|
204
|
-
/* Reduced motion: everything is instant, except the designed fallbacks
|
|
205
|
-
(nx-motion, nx-reveal), which keep their crossfade with no travel. */
|
|
206
|
-
@media (prefers-reduced-motion: reduce) {
|
|
207
|
-
*:not(.nx-motion, .nx-reveal), *::before, *::after {
|
|
208
|
-
animation-duration: 0.01ms !important;
|
|
209
|
-
animation-iteration-count: 1 !important;
|
|
210
|
-
transition-duration: 0.01ms !important;
|
|
211
|
-
scroll-behavior: auto !important;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/* ─── State layer (Calm Depth §4.2) ──────────────────────────────────────────
|
|
216
|
-
An overlay of the element's own text color (its on-* role) at the
|
|
217
|
-
--state-* opacity, so hover/focus/press read correctly on any fill, theme,
|
|
218
|
-
brand or glass. The ::before paints above the background, below content. */
|
|
219
|
-
.nx-state-layer { position: relative; isolation: isolate; }
|
|
220
|
-
.nx-state-layer::before {
|
|
221
|
-
content: '';
|
|
222
|
-
position: absolute;
|
|
223
|
-
inset: 0;
|
|
224
|
-
z-index: -1;
|
|
225
|
-
border-radius: inherit;
|
|
226
|
-
background: currentColor;
|
|
227
|
-
opacity: 0;
|
|
228
|
-
pointer-events: none;
|
|
229
|
-
transition: opacity var(--motion-spring-effects-fast-duration) var(--motion-spring-effects-fast-easing);
|
|
230
|
-
}
|
|
231
|
-
.nx-state-layer:hover::before { opacity: var(--state-hover); }
|
|
232
|
-
.nx-state-layer:focus-visible::before { opacity: var(--state-focus); }
|
|
233
|
-
.nx-state-layer:active::before { opacity: var(--state-pressed); }
|
|
234
|
-
.nx-state-layer:is(:disabled, [aria-disabled='true'], [data-disabled])::before { opacity: 0; }
|
|
235
|
-
|
|
236
|
-
/* Press feedback: a fast spatial spring, no ripple. */
|
|
237
|
-
.nx-press {
|
|
238
|
-
transition: transform var(--motion-spring-spatial-fast-duration) var(--motion-spring-spatial-fast-easing);
|
|
239
|
-
}
|
|
240
|
-
.nx-press:active:not(:disabled, [aria-disabled='true'], [data-disabled]) { transform: scale(0.97); }
|
|
241
|
-
|
|
242
|
-
/* ─── Enter / exit (overlays, menus, tooltips, toasts) ───────────────────────
|
|
243
|
-
Opacity rides the effects spring; position and scale ride the spatial
|
|
244
|
-
spring, so a little overshoot reads as physical without flashing.
|
|
245
|
-
Keyframes, not transitions: Radix keeps closing content mounted until its
|
|
246
|
-
exit animation ends. Standalone translate/scale compose with the
|
|
247
|
-
component's own transform (e.g. a centred dialog's -50% offsets).
|
|
248
|
-
Modifiers set where the layer comes from: --nx-x, --nx-y, --nx-scale. */
|
|
249
|
-
@keyframes nx-fade-in { from { opacity: 0; } }
|
|
250
|
-
@keyframes nx-fade-out { to { opacity: 0; } }
|
|
251
|
-
@keyframes nx-move-in { from { translate: var(--nx-x, 0) var(--nx-y, 0); scale: var(--nx-scale, 1); } }
|
|
252
|
-
@keyframes nx-move-out { to { translate: var(--nx-x, 0) var(--nx-y, 0); scale: var(--nx-scale, 1); } }
|
|
253
|
-
|
|
254
|
-
.nx-motion:is([data-state='open'], [data-state='delayed-open'], [data-state='instant-open'], [data-motion^='from-']) {
|
|
255
|
-
animation:
|
|
256
|
-
nx-fade-in var(--motion-spring-effects-default-duration) var(--motion-spring-effects-default-easing),
|
|
257
|
-
nx-move-in var(--motion-spring-spatial-default-duration) var(--motion-spring-spatial-default-easing);
|
|
258
|
-
}
|
|
259
|
-
/* Exit is quicker than enter and never overshoots. */
|
|
260
|
-
.nx-motion:is([data-state='closed'], [data-motion^='to-']) {
|
|
261
|
-
animation:
|
|
262
|
-
nx-fade-out var(--motion-spring-effects-fast-duration) var(--motion-spring-effects-fast-easing) forwards,
|
|
263
|
-
nx-move-out var(--motion-spring-effects-fast-duration) var(--motion-spring-effects-fast-easing) forwards;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
/* Floating layers grow from their trigger: a small scale plus a 4px nudge
|
|
267
|
-
away from the side they open on (Radix sets data-side). Components set
|
|
268
|
-
transform-origin to Radix's --radix-*-transform-origin. */
|
|
269
|
-
.nx-pop { --nx-scale: 0.96; }
|
|
270
|
-
.nx-pop[data-side='bottom'] { --nx-y: -4px; }
|
|
271
|
-
.nx-pop[data-side='top'] { --nx-y: 4px; }
|
|
272
|
-
.nx-pop[data-side='left'] { --nx-x: 4px; }
|
|
273
|
-
.nx-pop[data-side='right'] { --nx-x: -4px; }
|
|
274
|
-
/* Modal dialogs rise slightly as they scale in. */
|
|
275
|
-
.nx-dialog { --nx-scale: 0.96; --nx-y: 8px; }
|
|
276
|
-
/* NavigationMenu content slides in from the item's direction. */
|
|
277
|
-
.nx-motion:is([data-motion='from-start'], [data-motion='to-start']) { --nx-x: -24px; }
|
|
278
|
-
.nx-motion:is([data-motion='from-end'], [data-motion='to-end']) { --nx-x: 24px; }
|
|
279
|
-
|
|
280
|
-
/* Reduced motion: a designed fallback, not a cut. Keep the crossfade, drop
|
|
281
|
-
the travel and scale. */
|
|
282
|
-
@media (prefers-reduced-motion: reduce) {
|
|
283
|
-
.nx-motion { --nx-x: 0px !important; --nx-y: 0px !important; --nx-scale: 1 !important; }
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
/* Stagger: children of .nx-stagger rise in one after another (40ms apart, up
|
|
287
|
-
to the 12th; later ones arrive with the 12th). Set --nx-stagger to change
|
|
288
|
-
the step. Re-key the parent to replay. */
|
|
289
|
-
.nx-stagger > * {
|
|
290
|
-
--nx-y: 8px;
|
|
291
|
-
animation:
|
|
292
|
-
nx-fade-in var(--motion-spring-effects-default-duration) var(--motion-spring-effects-default-easing) both,
|
|
293
|
-
nx-move-in var(--motion-spring-spatial-default-duration) var(--motion-spring-spatial-default-easing) both;
|
|
294
|
-
animation-delay: calc(var(--nx-i, 0) * var(--nx-stagger, 40ms));
|
|
295
|
-
}
|
|
296
|
-
.nx-stagger > :nth-child(2) { --nx-i: 1; }
|
|
297
|
-
.nx-stagger > :nth-child(3) { --nx-i: 2; }
|
|
298
|
-
.nx-stagger > :nth-child(4) { --nx-i: 3; }
|
|
299
|
-
.nx-stagger > :nth-child(5) { --nx-i: 4; }
|
|
300
|
-
.nx-stagger > :nth-child(6) { --nx-i: 5; }
|
|
301
|
-
.nx-stagger > :nth-child(7) { --nx-i: 6; }
|
|
302
|
-
.nx-stagger > :nth-child(8) { --nx-i: 7; }
|
|
303
|
-
.nx-stagger > :nth-child(9) { --nx-i: 8; }
|
|
304
|
-
.nx-stagger > :nth-child(10) { --nx-i: 9; }
|
|
305
|
-
.nx-stagger > :nth-child(11) { --nx-i: 10; }
|
|
306
|
-
.nx-stagger > :nth-child(n + 12) { --nx-i: 11; }
|
|
307
|
-
|
|
308
|
-
/* ListTransition items: grow in from zero height and fade in; exit collapses
|
|
309
|
-
and fades (quicker, no overshoot). Rows animate via grid-template-rows so
|
|
310
|
-
the item needs no measured height. */
|
|
311
|
-
.nx-list-item { display: grid; grid-template-rows: 1fr; }
|
|
312
|
-
.nx-list-item-inner { min-height: 0; overflow: hidden; }
|
|
313
|
-
@keyframes nx-rows-in { from { grid-template-rows: 0fr; } }
|
|
314
|
-
@keyframes nx-rows-out { to { grid-template-rows: 0fr; } }
|
|
315
|
-
.nx-list-item[data-state='enter'] {
|
|
316
|
-
animation:
|
|
317
|
-
nx-rows-in var(--motion-spring-spatial-default-duration) var(--motion-spring-spatial-default-easing),
|
|
318
|
-
nx-fade-in var(--motion-spring-effects-default-duration) var(--motion-spring-effects-default-easing);
|
|
319
|
-
}
|
|
320
|
-
.nx-list-item[data-state='exit'] {
|
|
321
|
-
pointer-events: none;
|
|
322
|
-
animation:
|
|
323
|
-
nx-rows-out var(--motion-spring-effects-default-duration) var(--motion-spring-effects-default-easing) forwards,
|
|
324
|
-
nx-fade-out var(--motion-spring-effects-fast-duration) var(--motion-spring-effects-fast-easing) forwards;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
/* SkeletonSwap: skeleton and content share one grid cell and crossfade. */
|
|
328
|
-
.nx-swap { display: grid; }
|
|
329
|
-
.nx-swap > * { grid-area: 1 / 1; min-width: 0; }
|
|
330
|
-
.nx-swap-in { animation: nx-fade-in var(--motion-spring-effects-default-duration) var(--motion-spring-effects-default-easing) both; }
|
|
331
|
-
.nx-swap-out {
|
|
332
|
-
pointer-events: none;
|
|
333
|
-
animation: nx-fade-out var(--motion-spring-effects-default-duration) var(--motion-spring-effects-default-easing) forwards;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
@media (prefers-reduced-motion: reduce) {
|
|
337
|
-
.nx-stagger > * { --nx-y: 0px; animation-delay: 0s; }
|
|
338
|
-
.nx-list-item[data-state='enter'] { animation: nx-fade-in var(--motion-spring-effects-default-duration) var(--motion-spring-effects-default-easing); }
|
|
339
|
-
.nx-list-item[data-state='exit'] { animation: nx-fade-out var(--motion-spring-effects-fast-duration) var(--motion-spring-effects-fast-easing) forwards; }
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
/* ─── Cards: lift, press, sheen ──────────────────────────────────────────────
|
|
343
|
-
Lift: hover raises 2px on the spatial spring with elevation 1 → 2; leaving
|
|
344
|
-
settles faster on the effects spring (a transition uses the *destination*
|
|
345
|
-
state's timing). Press sinks to 0.99. Hover only where a real pointer
|
|
346
|
-
hovers, so touch never gets a stuck lift. */
|
|
347
|
-
.nx-lift {
|
|
348
|
-
transition:
|
|
349
|
-
translate var(--motion-spring-effects-fast-duration) var(--motion-spring-effects-fast-easing),
|
|
350
|
-
scale var(--motion-spring-effects-fast-duration) var(--motion-spring-effects-fast-easing),
|
|
351
|
-
box-shadow var(--motion-spring-effects-fast-duration) var(--motion-spring-effects-fast-easing);
|
|
352
|
-
}
|
|
353
|
-
@media (hover: hover) {
|
|
354
|
-
.nx-lift:hover {
|
|
355
|
-
translate: 0 -2px;
|
|
356
|
-
transition:
|
|
357
|
-
translate var(--motion-spring-spatial-default-duration) var(--motion-spring-spatial-default-easing),
|
|
358
|
-
scale var(--motion-spring-spatial-fast-duration) var(--motion-spring-spatial-fast-easing),
|
|
359
|
-
box-shadow var(--motion-spring-effects-default-duration) var(--motion-spring-effects-default-easing);
|
|
360
|
-
}
|
|
361
|
-
/* Glass keeps its own shadow (it carries the specular edge). */
|
|
362
|
-
.nx-lift:not([data-material='glass']):hover { box-shadow: var(--elevation-2); }
|
|
363
|
-
}
|
|
364
|
-
.nx-lift:active { translate: 0 0; scale: 0.99; }
|
|
365
|
-
@media (prefers-reduced-motion: reduce) {
|
|
366
|
-
.nx-lift:hover, .nx-lift:active { translate: none; scale: none; }
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
/* Sheen (opt-in): a soft light that follows the pointer across the surface,
|
|
370
|
-
plus a brighter rim where the pointer is nearest the edge. JS sets
|
|
371
|
-
--nx-mx/--nx-my through the CSSOM (CSP-safe); --nx-sheen fades it in.
|
|
372
|
-
Primary-tinted on light surfaces, white on dark and on glass. Off for touch
|
|
373
|
-
(no hover), reduced motion and reduced transparency. */
|
|
374
|
-
@property --nx-sheen { syntax: '<number>'; inherits: true; initial-value: 0; }
|
|
375
|
-
.nx-sheen {
|
|
376
|
-
position: relative;
|
|
377
|
-
--nx-sheen-tint: light-dark(var(--color-primary), #fff);
|
|
378
|
-
background-image: radial-gradient(
|
|
379
|
-
28rem circle at var(--nx-mx, 50%) var(--nx-my, 0%),
|
|
380
|
-
color-mix(in srgb, var(--nx-sheen-tint) calc(var(--nx-sheen) * 9%), transparent),
|
|
381
|
-
transparent 70%
|
|
382
|
-
);
|
|
383
|
-
transition: --nx-sheen var(--motion-spring-effects-fast-duration) var(--motion-spring-effects-fast-easing);
|
|
384
|
-
}
|
|
385
|
-
.nx-sheen::after {
|
|
386
|
-
content: '';
|
|
387
|
-
position: absolute;
|
|
388
|
-
inset: -1px;
|
|
389
|
-
padding: 1px;
|
|
390
|
-
border-radius: inherit;
|
|
391
|
-
pointer-events: none;
|
|
392
|
-
background: radial-gradient(
|
|
393
|
-
14rem circle at var(--nx-mx, 50%) var(--nx-my, 0%),
|
|
394
|
-
color-mix(in srgb, var(--nx-sheen-tint) calc(var(--nx-sheen) * 70%), transparent),
|
|
395
|
-
transparent 70%
|
|
396
|
-
);
|
|
397
|
-
-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
|
|
398
|
-
-webkit-mask-composite: xor;
|
|
399
|
-
mask-composite: exclude;
|
|
400
|
-
}
|
|
401
|
-
[data-material='glass'].nx-sheen { --nx-sheen-tint: #fff; }
|
|
402
|
-
/* On a sheen surface the light is the hover feedback; the grey state layer
|
|
403
|
-
would wash it out. Press still darkens. */
|
|
404
|
-
.nx-sheen.nx-state-layer:hover:not(:active)::before { opacity: 0; }
|
|
405
|
-
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
|
|
406
|
-
.nx-sheen:hover {
|
|
407
|
-
--nx-sheen: 1;
|
|
408
|
-
transition: --nx-sheen var(--motion-spring-effects-default-duration) var(--motion-spring-effects-default-easing);
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
@media (prefers-reduced-transparency: reduce) {
|
|
412
|
-
.nx-sheen { background-image: none; }
|
|
413
|
-
.nx-sheen::after { display: none; }
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
/* ─── AI: thinking indicator ─────────────────────────────────────────────────
|
|
417
|
-
nx-morph: a small shape that breathes between a circle and a soft squircle
|
|
418
|
-
on the expressive spring. nx-shimmer: a decorative light sweep across label
|
|
419
|
-
text (the text stays in the DOM). Reduced motion: both static. */
|
|
420
|
-
@keyframes nx-morph {
|
|
421
|
-
from { border-radius: 50%; rotate: 0deg; }
|
|
422
|
-
to { border-radius: 38% 62% 38% 62% / 62% 38% 62% 38%; rotate: 90deg; }
|
|
423
|
-
}
|
|
424
|
-
@keyframes nx-shimmer {
|
|
425
|
-
from { background-position: 100% 0; }
|
|
426
|
-
to { background-position: -100% 0; }
|
|
427
|
-
}
|
|
428
|
-
@media (prefers-reduced-motion: no-preference) {
|
|
429
|
-
.nx-morph {
|
|
430
|
-
animation: nx-morph calc(var(--motion-spring-expressive-slow-duration) * 2)
|
|
431
|
-
var(--motion-spring-expressive-slow-easing) infinite alternate;
|
|
432
|
-
}
|
|
433
|
-
.nx-shimmer {
|
|
434
|
-
background-image: linear-gradient(90deg,
|
|
435
|
-
currentColor 0%, currentColor 40%, var(--color-on-surface) 50%, currentColor 60%, currentColor 100%);
|
|
436
|
-
background-size: 200% 100%;
|
|
437
|
-
-webkit-background-clip: text;
|
|
438
|
-
background-clip: text;
|
|
439
|
-
-webkit-text-fill-color: transparent;
|
|
440
|
-
/* A steady sweep: linear, not a spring (a spring would pulse each loop). */
|
|
441
|
-
animation: nx-shimmer 2s linear infinite;
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
@media (forced-colors: active) {
|
|
445
|
-
.nx-shimmer { background: none; -webkit-text-fill-color: currentColor; }
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
/* Streaming caret: a steady blink while text is arriving. */
|
|
449
|
-
@keyframes nx-caret { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }
|
|
450
|
-
.nx-caret { animation: nx-caret 1s steps(1, end) infinite; }
|
|
451
|
-
@media (prefers-reduced-motion: reduce) {
|
|
452
|
-
.nx-caret { animation: none; }
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
/* ─── Touch targets ─────────────────────────────────────────────────────────
|
|
456
|
-
Small controls keep their visual size but get an invisible 44×44 hit area
|
|
457
|
-
on touch screens (Apple HIG, WCAG 2.5.5). Uses ::after; the state layer
|
|
458
|
-
uses ::before. */
|
|
459
|
-
@media (pointer: coarse) {
|
|
460
|
-
.nx-hit { position: relative; }
|
|
461
|
-
.nx-hit::after {
|
|
462
|
-
content: '';
|
|
463
|
-
position: absolute;
|
|
464
|
-
left: 50%;
|
|
465
|
-
top: 50%;
|
|
466
|
-
width: max(100%, 44px);
|
|
467
|
-
height: max(100%, 44px);
|
|
468
|
-
translate: -50% -50%;
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
/* ─── Micro-moments ──────────────────────────────────────────────────────────
|
|
473
|
-
Reveal: content replacing a skeleton crossfades in (no travel). */
|
|
474
|
-
.nx-reveal {
|
|
475
|
-
animation: nx-fade-in var(--motion-spring-effects-default-duration) var(--motion-spring-effects-default-easing);
|
|
476
|
-
}
|
|
477
|
-
/* Check draw: a checkmark path (pathLength="1") draws itself in. */
|
|
478
|
-
@keyframes nx-draw { from { stroke-dashoffset: 1; } }
|
|
479
|
-
.nx-check-draw {
|
|
480
|
-
stroke-dasharray: 1;
|
|
481
|
-
animation: nx-draw var(--motion-spring-effects-default-duration) var(--motion-spring-effects-default-easing);
|
|
482
|
-
}
|
|
483
|
-
@media (prefers-reduced-motion: reduce) {
|
|
484
|
-
.nx-check-draw { animation: none; }
|
|
485
|
-
}
|
|
486
|
-
/* Shake: a short horizontal "no" on the spatial-fast spring (async Button error). */
|
|
487
|
-
@keyframes nx-shake {
|
|
488
|
-
0%, 100% { translate: 0; }
|
|
489
|
-
20% { translate: -4px; }
|
|
490
|
-
40% { translate: 4px; }
|
|
491
|
-
60% { translate: -3px; }
|
|
492
|
-
80% { translate: 2px; }
|
|
493
|
-
}
|
|
494
|
-
.nx-shake {
|
|
495
|
-
animation: nx-shake var(--motion-spring-spatial-fast-duration) var(--motion-spring-spatial-fast-easing);
|
|
496
|
-
}
|
|
497
|
-
@media (prefers-reduced-motion: reduce) {
|
|
498
|
-
.nx-shake { animation: none; }
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
/* ─── Density ────────────────────────────────────────────────────────────────
|
|
502
|
-
Compact shifts every control one step down the ladder (md 40 → 32px at a 16px root). */
|
|
503
|
-
[data-density='compact'] {
|
|
504
|
-
--size-control-xs: 1.25rem;
|
|
505
|
-
--size-control-sm: 1.5rem;
|
|
506
|
-
--size-control-md: 2rem;
|
|
507
|
-
--size-control-lg: 2.5rem;
|
|
508
|
-
--size-control-xl: 3rem;
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
/* Logo-scroll marquee keyframe (used by LogoWall) */
|
|
512
|
-
@keyframes logo-scroll {
|
|
513
|
-
from { transform: translateX(0); }
|
|
514
|
-
to { transform: translateX(-50%); }
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
/* ─── App header (@nexub/patterns AppHeader) ─────────────────────────────────
|
|
518
|
-
One height for the fixed top header everywhere. Offset layouts with
|
|
519
|
-
var(--app-header-height); AppHeader's own spacer already does in flow. */
|
|
520
|
-
:root { --app-header-height: 64px; }
|
|
521
|
-
/* condense: scroll-driven, no JS. The page spacer stays 64px; only the bar
|
|
522
|
-
tightens. Glass keeps its own shadow. */
|
|
523
|
-
@keyframes nx-condense { to { height: 52px; } }
|
|
524
|
-
@keyframes nx-condense-lift { to { height: 52px; box-shadow: var(--elevation-1); } }
|
|
525
|
-
@supports (animation-timeline: scroll()) {
|
|
526
|
-
[data-condense] {
|
|
527
|
-
animation: nx-condense-lift linear both;
|
|
528
|
-
animation-timeline: scroll(root);
|
|
529
|
-
animation-range: 0 64px;
|
|
530
|
-
}
|
|
531
|
-
[data-condense][data-material='glass'] { animation-name: nx-condense; }
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
/* ─── Scroll lock (Sheet scrollLock="class") ─────────────────────────────────
|
|
535
|
-
A CSP-safe page scroll lock: @nexub/react toggles these classes on <html>
|
|
536
|
-
instead of injecting a <style> tag. The gutter class keeps the scrollbar's
|
|
537
|
-
space so the page doesn't shift sideways. */
|
|
538
|
-
html.nexub-scroll-lock { overflow: hidden; }
|
|
539
|
-
html.nexub-scroll-lock.nexub-scroll-gutter { scrollbar-gutter: stable; }
|
|
540
|
-
|
|
541
|
-
/* ─── Nexub mark gradient stops (<NexubMark variant="color">, <Logo>) ───────
|
|
542
|
-
Classes instead of style= attributes, which a strict CSP blocks in
|
|
543
|
-
server-rendered HTML. */
|
|
544
|
-
/* nexub-mark-stops:start — generated by packages/brand/scripts/build-assets.mjs */
|
|
545
|
-
.nxm-s-1{stop-color:var(--color-brand-mark-1)}
|
|
546
|
-
.nxm-s-2{stop-color:var(--color-brand-mark-2)}
|
|
547
|
-
.nxm-s-3{stop-color:var(--color-brand-mark-3)}
|
|
548
|
-
.nxm-s-4{stop-color:var(--color-brand-mark-4)}
|
|
549
|
-
.nxm-s-5{stop-color:var(--color-brand-mark-5)}
|
|
550
|
-
.nxm-s-6{stop-color:var(--color-brand-mark-6)}
|
|
551
|
-
.nxm-s-7{stop-color:var(--color-brand-mark-7)}
|
|
552
|
-
.nxm-s-8{stop-color:var(--color-brand-mark-8)}
|
|
553
|
-
.nxm-s-9{stop-color:var(--color-brand-mark-9)}
|
|
554
|
-
.nxm-s-10{stop-color:var(--color-brand-mark-10)}
|
|
555
|
-
.nxm-s-11{stop-color:var(--color-brand-mark-11)}
|
|
556
|
-
.nxm-s-12{stop-color:var(--color-brand-mark-12)}
|
|
557
|
-
.nxm-s-13{stop-color:var(--color-brand-mark-13)}
|
|
558
|
-
.nxm-s-14{stop-color:var(--color-brand-mark-14)}
|
|
559
|
-
.nxm-s-15{stop-color:var(--color-brand-mark-15)}
|
|
560
|
-
.nxm-s-16{stop-color:var(--color-brand-mark-16)}
|
|
561
|
-
.nxm-s-17{stop-color:var(--color-brand-mark-17)}
|
|
562
|
-
.nxm-s-18{stop-color:var(--color-brand-mark-18)}
|
|
563
|
-
.nxm-s-19{stop-color:var(--color-brand-mark-19)}
|
|
564
|
-
.nxm-s-20{stop-color:var(--color-brand-mark-20)}
|
|
565
|
-
.nxm-s-21{stop-color:var(--color-brand-mark-21)}
|
|
566
|
-
.nxm-s-22{stop-color:var(--color-brand-mark-22)}
|
|
567
|
-
.nxm-s-23{stop-color:var(--color-brand-mark-23)}
|
|
568
|
-
.nxm-s-24{stop-color:var(--color-brand-mark-24)}
|
|
569
|
-
.nxm-s-25{stop-color:var(--color-brand-mark-25)}
|
|
570
|
-
.nxm-s-26{stop-color:var(--color-brand-mark-26)}
|
|
571
|
-
.nxm-s-27{stop-color:var(--color-brand-mark-27)}
|
|
572
|
-
.nxm-s-28{stop-color:var(--color-brand-mark-28)}
|
|
573
|
-
.nxm-s-29{stop-color:var(--color-brand-mark-29)}
|
|
574
|
-
.nxm-s-30{stop-color:var(--color-brand-mark-30)}
|
|
575
|
-
.nxm-s-31{stop-color:var(--color-brand-mark-31)}
|
|
576
|
-
.nxm-s-32{stop-color:var(--color-brand-mark-32)}
|
|
577
|
-
.nxm-s-33{stop-color:var(--color-brand-mark-33)}
|
|
578
|
-
.nxm-s-34{stop-color:var(--color-brand-mark-34)}
|
|
579
|
-
.nxm-s-35{stop-color:var(--color-brand-mark-35)}
|
|
580
|
-
.nxm-s-36{stop-color:var(--color-brand-mark-36)}
|
|
581
|
-
.nxm-s-37{stop-color:var(--color-brand-mark-37)}
|
|
582
|
-
.nxm-s-38{stop-color:var(--color-brand-mark-38)}
|
|
583
|
-
.nxm-s-39{stop-color:var(--color-brand-mark-39)}
|
|
584
|
-
.nxm-s-40{stop-color:var(--color-brand-mark-40)}
|
|
585
|
-
.nxm-s-41{stop-color:var(--color-brand-mark-41)}
|
|
586
|
-
.nxm-s-42{stop-color:var(--color-brand-mark-42)}
|
|
587
|
-
.nxm-s-43{stop-color:var(--color-brand-mark-43)}
|
|
588
|
-
.nxm-s-44{stop-color:var(--color-brand-mark-44)}
|
|
589
|
-
.nxm-s-45{stop-color:var(--color-brand-mark-45)}
|
|
590
|
-
.nxm-s-46{stop-color:var(--color-brand-mark-46)}
|
|
591
|
-
.nxm-s-47{stop-color:var(--color-brand-mark-47)}
|
|
592
|
-
.nxm-o-0{stop-opacity:0}
|
|
593
|
-
/* nexub-mark-stops:end */
|
|
594
|
-
|
|
595
|
-
/* ─── Radix ScrollArea / Select viewports ────────────────────────────────────
|
|
596
|
-
Radix renders these rules in a <style> tag, which a strict CSP blocks. The
|
|
597
|
-
same rules here keep the native scrollbar hidden either way. */
|
|
598
|
-
[data-radix-scroll-area-viewport],[data-radix-select-viewport]{scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch}
|
|
599
|
-
[data-radix-scroll-area-viewport]::-webkit-scrollbar,[data-radix-select-viewport]::-webkit-scrollbar{display:none}
|
|
600
|
-
|
|
601
|
-
/* ─── Drawer / Sheet (vaul 1.1.2) ─────────────────────────────────────────────
|
|
602
|
-
vaul's own styles. vaul normally injects these in a <style> tag when
|
|
603
|
-
@nexub/react loads, which strict CSP pages block; @nexub/react strips that
|
|
604
|
-
and ships them here instead. Verbatim copy: the @nexub/react build fails if
|
|
605
|
-
it no longer matches vaul. One rule is left out: vaul's invalid
|
|
606
|
-
`[data-vaul-handle-hitarea]:{…}` media rule, which browsers ignore and strict
|
|
607
|
-
CSS parsers (lightningcss, Turbopack) reject. */
|
|
608
|
-
[data-vaul-drawer]{touch-action:none;will-change:transform;transition:transform .5s cubic-bezier(.32, .72, 0, 1);animation-duration:.5s;animation-timing-function:cubic-bezier(0.32,0.72,0,1)}[data-vaul-drawer][data-vaul-snap-points=false][data-vaul-drawer-direction=bottom][data-state=open]{animation-name:slideFromBottom}[data-vaul-drawer][data-vaul-snap-points=false][data-vaul-drawer-direction=bottom][data-state=closed]{animation-name:slideToBottom}[data-vaul-drawer][data-vaul-snap-points=false][data-vaul-drawer-direction=top][data-state=open]{animation-name:slideFromTop}[data-vaul-drawer][data-vaul-snap-points=false][data-vaul-drawer-direction=top][data-state=closed]{animation-name:slideToTop}[data-vaul-drawer][data-vaul-snap-points=false][data-vaul-drawer-direction=left][data-state=open]{animation-name:slideFromLeft}[data-vaul-drawer][data-vaul-snap-points=false][data-vaul-drawer-direction=left][data-state=closed]{animation-name:slideToLeft}[data-vaul-drawer][data-vaul-snap-points=false][data-vaul-drawer-direction=right][data-state=open]{animation-name:slideFromRight}[data-vaul-drawer][data-vaul-snap-points=false][data-vaul-drawer-direction=right][data-state=closed]{animation-name:slideToRight}[data-vaul-drawer][data-vaul-snap-points=true][data-vaul-drawer-direction=bottom]{transform:translate3d(0,var(--initial-transform,100%),0)}[data-vaul-drawer][data-vaul-snap-points=true][data-vaul-drawer-direction=top]{transform:translate3d(0,calc(var(--initial-transform,100%) * -1),0)}[data-vaul-drawer][data-vaul-snap-points=true][data-vaul-drawer-direction=left]{transform:translate3d(calc(var(--initial-transform,100%) * -1),0,0)}[data-vaul-drawer][data-vaul-snap-points=true][data-vaul-drawer-direction=right]{transform:translate3d(var(--initial-transform,100%),0,0)}[data-vaul-drawer][data-vaul-delayed-snap-points=true][data-vaul-drawer-direction=top]{transform:translate3d(0,var(--snap-point-height,0),0)}[data-vaul-drawer][data-vaul-delayed-snap-points=true][data-vaul-drawer-direction=bottom]{transform:translate3d(0,var(--snap-point-height,0),0)}[data-vaul-drawer][data-vaul-delayed-snap-points=true][data-vaul-drawer-direction=left]{transform:translate3d(var(--snap-point-height,0),0,0)}[data-vaul-drawer][data-vaul-delayed-snap-points=true][data-vaul-drawer-direction=right]{transform:translate3d(var(--snap-point-height,0),0,0)}[data-vaul-overlay][data-vaul-snap-points=false]{animation-duration:.5s;animation-timing-function:cubic-bezier(0.32,0.72,0,1)}[data-vaul-overlay][data-vaul-snap-points=false][data-state=open]{animation-name:fadeIn}[data-vaul-overlay][data-state=closed]{animation-name:fadeOut}[data-vaul-animate=false]{animation:none!important}[data-vaul-overlay][data-vaul-snap-points=true]{opacity:0;transition:opacity .5s cubic-bezier(.32, .72, 0, 1)}[data-vaul-overlay][data-vaul-snap-points=true]{opacity:1}[data-vaul-drawer]:not([data-vaul-custom-container=true])::after{content:'';position:absolute;background:inherit;background-color:inherit}[data-vaul-drawer][data-vaul-drawer-direction=top]::after{top:initial;bottom:100%;left:0;right:0;height:200%}[data-vaul-drawer][data-vaul-drawer-direction=bottom]::after{top:100%;bottom:initial;left:0;right:0;height:200%}[data-vaul-drawer][data-vaul-drawer-direction=left]::after{left:initial;right:100%;top:0;bottom:0;width:200%}[data-vaul-drawer][data-vaul-drawer-direction=right]::after{left:100%;right:initial;top:0;bottom:0;width:200%}[data-vaul-overlay][data-vaul-snap-points=true]:not([data-vaul-snap-points-overlay=true]):not(
|
|
609
|
-
[data-state=closed]
|
|
610
|
-
){opacity:0}[data-vaul-overlay][data-vaul-snap-points-overlay=true]{opacity:1}[data-vaul-handle]{display:block;position:relative;opacity:.7;background:#e2e2e4;margin-left:auto;margin-right:auto;height:5px;width:32px;border-radius:1rem;touch-action:pan-y}[data-vaul-handle]:active,[data-vaul-handle]:hover{opacity:1}[data-vaul-handle-hitarea]{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:max(100%,2.75rem);height:max(100%,2.75rem);touch-action:inherit}@media (hover:hover) and (pointer:fine){[data-vaul-drawer]{user-select:none}}@keyframes fadeIn{from{opacity:0}to{opacity:1}}@keyframes fadeOut{to{opacity:0}}@keyframes slideFromBottom{from{transform:translate3d(0,var(--initial-transform,100%),0)}to{transform:translate3d(0,0,0)}}@keyframes slideToBottom{to{transform:translate3d(0,var(--initial-transform,100%),0)}}@keyframes slideFromTop{from{transform:translate3d(0,calc(var(--initial-transform,100%) * -1),0)}to{transform:translate3d(0,0,0)}}@keyframes slideToTop{to{transform:translate3d(0,calc(var(--initial-transform,100%) * -1),0)}}@keyframes slideFromLeft{from{transform:translate3d(calc(var(--initial-transform,100%) * -1),0,0)}to{transform:translate3d(0,0,0)}}@keyframes slideToLeft{to{transform:translate3d(calc(var(--initial-transform,100%) * -1),0,0)}}@keyframes slideFromRight{from{transform:translate3d(var(--initial-transform,100%),0,0)}to{transform:translate3d(0,0,0)}}@keyframes slideToRight{to{transform:translate3d(var(--initial-transform,100%),0,0)}}
|
|
611
|
-
|
|
612
|
-
/* Drawer / Sheet on our springs. vaul's copy above stays verbatim (tsup checks
|
|
613
|
-
it); these override its .5s iOS curve. Enter rides spatial, exit is quicker
|
|
614
|
-
on effects and never overshoots. Placed after vaul's rules so ties win. */
|
|
615
|
-
.nx-drawer[data-vaul-drawer][data-vaul-snap-points='false'] {
|
|
616
|
-
animation-duration: var(--motion-spring-spatial-default-duration);
|
|
617
|
-
animation-timing-function: var(--motion-spring-spatial-default-easing);
|
|
618
|
-
}
|
|
619
|
-
.nx-drawer[data-vaul-drawer][data-vaul-snap-points='false'][data-state='closed'] {
|
|
620
|
-
animation-duration: var(--motion-spring-effects-default-duration);
|
|
621
|
-
animation-timing-function: var(--motion-spring-effects-default-easing);
|
|
622
|
-
}
|
|
623
|
-
.nx-drawer-overlay[data-vaul-overlay][data-vaul-snap-points='false'] {
|
|
624
|
-
animation-duration: var(--motion-spring-effects-default-duration);
|
|
625
|
-
animation-timing-function: var(--motion-spring-effects-default-easing);
|
|
626
|
-
}
|
|
627
|
-
.nx-drawer-overlay[data-vaul-overlay][data-state='closed'] {
|
|
628
|
-
animation-duration: var(--motion-spring-effects-fast-duration);
|
|
629
|
-
animation-timing-function: var(--motion-spring-effects-fast-easing);
|
|
630
|
-
}
|
|
631
|
-
/* Reduced motion: the panel fades instead of sliding. */
|
|
632
|
-
@media (prefers-reduced-motion: reduce) {
|
|
633
|
-
.nx-drawer[data-vaul-drawer][data-vaul-snap-points='false'][data-state='open'] { animation-name: fadeIn; }
|
|
634
|
-
.nx-drawer[data-vaul-drawer][data-vaul-snap-points='false'][data-state='closed'] { animation-name: fadeOut; }
|
|
635
|
-
}
|