@nexub/themes 1.2.0 → 1.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.
Files changed (32) hide show
  1. package/package.json +10 -3
  2. package/src/base.css +159 -34
  3. package/src/bookub.css +1 -1
  4. package/src/dark.css +5 -121
  5. package/src/fonts/LICENSE-inter +93 -0
  6. package/src/fonts/LICENSE-plus-jakarta-sans +93 -0
  7. package/src/fonts/inter-cyrillic-ext-opsz-italic.woff2 +0 -0
  8. package/src/fonts/inter-cyrillic-ext-opsz-normal.woff2 +0 -0
  9. package/src/fonts/inter-cyrillic-opsz-italic.woff2 +0 -0
  10. package/src/fonts/inter-cyrillic-opsz-normal.woff2 +0 -0
  11. package/src/fonts/inter-greek-ext-opsz-italic.woff2 +0 -0
  12. package/src/fonts/inter-greek-ext-opsz-normal.woff2 +0 -0
  13. package/src/fonts/inter-greek-opsz-italic.woff2 +0 -0
  14. package/src/fonts/inter-greek-opsz-normal.woff2 +0 -0
  15. package/src/fonts/inter-latin-ext-opsz-italic.woff2 +0 -0
  16. package/src/fonts/inter-latin-ext-opsz-normal.woff2 +0 -0
  17. package/src/fonts/inter-latin-opsz-italic.woff2 +0 -0
  18. package/src/fonts/inter-latin-opsz-normal.woff2 +0 -0
  19. package/src/fonts/inter-vietnamese-opsz-italic.woff2 +0 -0
  20. package/src/fonts/inter-vietnamese-opsz-normal.woff2 +0 -0
  21. package/src/fonts/plus-jakarta-sans-latin-ext-wght-italic.woff2 +0 -0
  22. package/src/fonts/plus-jakarta-sans-latin-ext-wght-normal.woff2 +0 -0
  23. package/src/fonts/plus-jakarta-sans-latin-wght-italic.woff2 +0 -0
  24. package/src/fonts/plus-jakarta-sans-latin-wght-normal.woff2 +0 -0
  25. package/src/fonts/plus-jakarta-sans-vietnamese-wght-italic.woff2 +0 -0
  26. package/src/fonts/plus-jakarta-sans-vietnamese-wght-normal.woff2 +0 -0
  27. package/src/fonts.css +205 -0
  28. package/src/founderub.css +1 -1
  29. package/src/glass.css +100 -37
  30. package/src/leap.css +1 -1
  31. package/src/light.css +59 -33
  32. package/src/payub.css +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nexub/themes",
3
- "version": "1.2.0",
3
+ "version": "1.4.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",
@@ -36,7 +36,14 @@
36
36
  "./founderub": "./src/founderub.css"
37
37
  },
38
38
  "dependencies": {
39
- "@fontsource-variable/plus-jakarta-sans": "^5.3.0",
40
- "@nexub/tokens": "1.2.0"
39
+ "@nexub/tokens": "1.4.0"
40
+ },
41
+ "devDependencies": {
42
+ "@fontsource-variable/inter": "5.3.0",
43
+ "@fontsource-variable/plus-jakarta-sans": "^5.3.0"
44
+ },
45
+ "scripts": {
46
+ "build:fonts": "node scripts/build-fonts.mjs",
47
+ "test": "node --test scripts/*.test.mjs"
41
48
  }
42
49
  }
package/src/base.css CHANGED
@@ -2,12 +2,14 @@
2
2
  Global resets, focus ring, body, scrollbar, reduced-motion.
3
3
  Import this once at the root of your app before light.css or dark.css. */
4
4
 
5
- /* Plus Jakarta Sans — the Nexub DS typeface. Self-hosted (OFL-1.1) via
6
- Fontsource; variable weights 200–800, normal + italic. Subsets load on
7
- demand via unicode-range, so only the glyphs a page uses are fetched. */
8
- @import '@fontsource-variable/plus-jakarta-sans/wght.css';
9
- @import '@fontsource-variable/plus-jakarta-sans/wght-italic.css';
5
+ /* Plus Jakarta Sans — the Nexub DS typeface. Self-hosted (OFL-1.1, from
6
+ Fontsource); variable weights 200–800, normal + italic. Subsets load on
7
+ demand via unicode-range, so only the glyphs a page uses are fetched. Every
8
+ file is big enough that bundlers emit it rather than inline a data: URL,
9
+ so `font-src 'self'` works (see scripts/build-fonts.mjs). */
10
+ @import './fonts.css';
10
11
  @import '@nexub/tokens/css';
12
+ @import '@nexub/tokens/css/roles';
11
13
 
12
14
  /* ─── Semantic shorthand aliases ───────────────────────────────────────────
13
15
  Components reference these shorter names. They proxy the full token names
@@ -47,7 +49,7 @@
47
49
 
48
50
  /* Form-control boundaries (WCAG 1.4.11 needs >= 3:1 against the page).
49
51
  Separate from --color-border-default, which cards/dividers keep light. */
50
- --color-border-input: #848e9f;
52
+ --color-border-input: var(--color-outline);
51
53
 
52
54
  /* placeholder text (PKG-B01) */
53
55
  --color-text-placeholder: var(--color-text-muted);
@@ -59,26 +61,27 @@
59
61
  --color-text-warning: var(--color-semantic-warning-strong);
60
62
  --color-text-danger: var(--color-semantic-error-strong);
61
63
 
62
- /* Solid fills under white text. Fixed shades (they do NOT flip in dark mode)
63
- chosen so white text is >= 4.5:1 (WCAG AA). Brand themes override accent. */
64
- --color-fill-primary: var(--color-brand-primary-600);
65
- --color-fill-primary-hover: var(--color-brand-primary-700);
66
- --color-fill-info: var(--color-brand-primary-600);
67
- --color-fill-info-hover: var(--color-brand-primary-700);
68
- --color-fill-success: #047857;
69
- --color-fill-success-hover: #065f46;
70
- --color-fill-warning: #b45309;
71
- --color-fill-warning-hover: #92400e;
72
- --color-fill-danger: #b91c1c;
73
- --color-fill-danger-hover: #991b1b;
74
- --color-fill-leap: var(--color-accent-leap-600);
75
- --color-fill-leap-hover: var(--color-accent-leap-700);
76
- --color-fill-bookub: var(--color-accent-bookub-700);
77
- --color-fill-bookub-hover: var(--color-accent-bookub-800);
78
- --color-fill-payub: var(--color-accent-payub-600);
79
- --color-fill-payub-hover: var(--color-accent-payub-700);
80
- --color-fill-founderub: var(--color-accent-founderub-700);
81
- --color-fill-founderub-hover: var(--color-accent-founderub-800);
64
+ /* Solid fills under white text. Fixed palette tones (they do NOT flip in dark
65
+ mode): tone 40 vs white is >= 4.5:1 by HCT construction; hover = tone 30.
66
+ Brand themes override accent. Phase 2 moves components to on-* roles. */
67
+ --color-fill-primary: var(--color-palette-primary-40);
68
+ --color-fill-primary-hover: var(--color-palette-primary-30);
69
+ --color-fill-info: var(--color-palette-info-40);
70
+ --color-fill-info-hover: var(--color-palette-info-30);
71
+ --color-fill-success: var(--color-palette-success-40);
72
+ --color-fill-success-hover: var(--color-palette-success-30);
73
+ --color-fill-warning: var(--color-palette-warning-40);
74
+ --color-fill-warning-hover: var(--color-palette-warning-30);
75
+ --color-fill-danger: var(--color-palette-error-40);
76
+ --color-fill-danger-hover: var(--color-palette-error-30);
77
+ --color-fill-leap: var(--color-palette-leap-40);
78
+ --color-fill-leap-hover: var(--color-palette-leap-30);
79
+ --color-fill-bookub: var(--color-palette-bookub-40);
80
+ --color-fill-bookub-hover: var(--color-palette-bookub-30);
81
+ --color-fill-payub: var(--color-palette-payub-40);
82
+ --color-fill-payub-hover: var(--color-palette-payub-30);
83
+ --color-fill-founderub: var(--color-palette-founderub-40);
84
+ --color-fill-founderub-hover: var(--color-palette-founderub-30);
82
85
  --color-fill-accent: var(--color-fill-primary);
83
86
  --color-fill-accent-hover: var(--color-fill-primary-hover);
84
87
 
@@ -138,11 +141,14 @@ html {
138
141
  -webkit-font-smoothing: antialiased;
139
142
  -moz-osx-font-smoothing: grayscale;
140
143
  text-size-adjust: 100%;
144
+ /* never fake bold/italic; Inter's optical sizes follow font-size */
145
+ font-synthesis: none;
146
+ font-optical-sizing: auto;
141
147
  }
142
148
 
143
149
  /* Form controls don't inherit fonts by default — without this, apps that
144
150
  don't use Tailwind's preflight would render buttons/inputs in the system UI
145
- font instead of Plus Jakarta Sans. */
151
+ font instead of Inter. */
146
152
  button, input, select, textarea, optgroup {
147
153
  font-family: inherit;
148
154
  }
@@ -153,19 +159,25 @@ body {
153
159
  background: var(--gradient-hero-ambient);
154
160
  }
155
161
 
156
- /* Focus ring */
162
+ /* Focus ring: one ring for everything. The outline follows border-radius, so
163
+ it hugs capsules and fields. Contrast >= 3:1 on every surface (ring = primary). */
157
164
  :focus-visible {
158
- outline: 2px solid var(--color-ring-default);
159
- outline-offset: 3px;
160
- box-shadow: var(--shadow-focus);
165
+ outline: 3px solid var(--color-ring-default);
166
+ outline-offset: 2px;
161
167
  }
162
168
 
163
- /* Headings */
169
+ @media (forced-colors: active) {
170
+ :focus-visible { outline-color: Highlight; }
171
+ }
172
+
173
+ /* Headings: brand display face, balanced wrapping */
164
174
  h1, h2, h3, h4, h5, h6 {
165
175
  margin: 0;
176
+ font-family: var(--font-family-display);
166
177
  font-weight: var(--font-weight-bold);
167
178
  line-height: 1.2;
168
179
  color: var(--color-text-primary);
180
+ text-wrap: balance;
169
181
  }
170
182
 
171
183
  /* Paragraphs / lists */
@@ -173,11 +185,15 @@ p, ul, ol {
173
185
  margin: 0;
174
186
  }
175
187
 
188
+ p {
189
+ text-wrap: pretty;
190
+ }
191
+
176
192
  /* Links */
177
193
  a {
178
194
  color: var(--color-text-link);
179
195
  text-decoration: underline;
180
- text-underline-offset: 2px;
196
+ text-underline-offset: 0.3em;
181
197
  }
182
198
 
183
199
  a:hover {
@@ -198,7 +214,7 @@ code, kbd, pre, samp {
198
214
 
199
215
  /* Selection */
200
216
  ::selection {
201
- background-color: color-mix(in srgb, var(--color-brand-primary-500) 20%, transparent);
217
+ background-color: color-mix(in srgb, var(--color-primary) 20%, transparent);
202
218
  color: var(--color-text-primary);
203
219
  }
204
220
 
@@ -231,12 +247,121 @@ code, kbd, pre, samp {
231
247
  }
232
248
  }
233
249
 
250
+ /* ─── State layer (Calm Depth §4.2) ──────────────────────────────────────────
251
+ An overlay of the element's own text color (its on-* role) at the
252
+ --state-* opacity, so hover/focus/press read correctly on any fill, theme,
253
+ brand or glass. The ::before paints above the background, below content. */
254
+ .nx-state-layer { position: relative; isolation: isolate; }
255
+ .nx-state-layer::before {
256
+ content: '';
257
+ position: absolute;
258
+ inset: 0;
259
+ z-index: -1;
260
+ border-radius: inherit;
261
+ background: currentColor;
262
+ opacity: 0;
263
+ pointer-events: none;
264
+ transition: opacity var(--motion-spring-effects-fast-duration) var(--motion-spring-effects-fast-easing);
265
+ }
266
+ .nx-state-layer:hover::before { opacity: var(--state-hover); }
267
+ .nx-state-layer:focus-visible::before { opacity: var(--state-focus); }
268
+ .nx-state-layer:active::before { opacity: var(--state-pressed); }
269
+ .nx-state-layer:is(:disabled, [aria-disabled='true'], [data-disabled])::before { opacity: 0; }
270
+
271
+ /* Press feedback: a fast spatial spring, no ripple. */
272
+ .nx-press {
273
+ transition: transform var(--motion-spring-spatial-fast-duration) var(--motion-spring-spatial-fast-easing);
274
+ }
275
+ .nx-press:active:not(:disabled, [aria-disabled='true'], [data-disabled]) { transform: scale(0.97); }
276
+
277
+ /* ─── Density ────────────────────────────────────────────────────────────────
278
+ Compact shifts every control one step down the ladder (md 40 → 32). */
279
+ [data-density='compact'] {
280
+ --size-control-xs: 20px;
281
+ --size-control-sm: 24px;
282
+ --size-control-md: 32px;
283
+ --size-control-lg: 40px;
284
+ --size-control-xl: 48px;
285
+ }
286
+
234
287
  /* Logo-scroll marquee keyframe (used by LogoWall) */
235
288
  @keyframes logo-scroll {
236
289
  from { transform: translateX(0); }
237
290
  to { transform: translateX(-50%); }
238
291
  }
239
292
 
293
+ /* ─── App header (@nexub/patterns AppHeader) ─────────────────────────────────
294
+ One height for the fixed top header everywhere. Offset layouts with
295
+ var(--app-header-height); AppHeader's own spacer already does in flow. */
296
+ :root { --app-header-height: 64px; }
297
+
298
+ /* ─── Scroll lock (Sheet scrollLock="class") ─────────────────────────────────
299
+ A CSP-safe page scroll lock: @nexub/react toggles these classes on <html>
300
+ instead of injecting a <style> tag. The gutter class keeps the scrollbar's
301
+ space so the page doesn't shift sideways. */
302
+ html.nexub-scroll-lock { overflow: hidden; }
303
+ html.nexub-scroll-lock.nexub-scroll-gutter { scrollbar-gutter: stable; }
304
+
305
+ /* ─── Nexub mark gradient stops (<NexubMark variant="color">, <Logo>) ───────
306
+ Classes instead of style= attributes, which a strict CSP blocks in
307
+ server-rendered HTML. */
308
+ /* nexub-mark-stops:start — generated by packages/brand/scripts/build-assets.mjs */
309
+ .nxm-s-1{stop-color:var(--color-brand-mark-1)}
310
+ .nxm-s-2{stop-color:var(--color-brand-mark-2)}
311
+ .nxm-s-3{stop-color:var(--color-brand-mark-3)}
312
+ .nxm-s-4{stop-color:var(--color-brand-mark-4)}
313
+ .nxm-s-5{stop-color:var(--color-brand-mark-5)}
314
+ .nxm-s-6{stop-color:var(--color-brand-mark-6)}
315
+ .nxm-s-7{stop-color:var(--color-brand-mark-7)}
316
+ .nxm-s-8{stop-color:var(--color-brand-mark-8)}
317
+ .nxm-s-9{stop-color:var(--color-brand-mark-9)}
318
+ .nxm-s-10{stop-color:var(--color-brand-mark-10)}
319
+ .nxm-s-11{stop-color:var(--color-brand-mark-11)}
320
+ .nxm-s-12{stop-color:var(--color-brand-mark-12)}
321
+ .nxm-s-13{stop-color:var(--color-brand-mark-13)}
322
+ .nxm-s-14{stop-color:var(--color-brand-mark-14)}
323
+ .nxm-s-15{stop-color:var(--color-brand-mark-15)}
324
+ .nxm-s-16{stop-color:var(--color-brand-mark-16)}
325
+ .nxm-s-17{stop-color:var(--color-brand-mark-17)}
326
+ .nxm-s-18{stop-color:var(--color-brand-mark-18)}
327
+ .nxm-s-19{stop-color:var(--color-brand-mark-19)}
328
+ .nxm-s-20{stop-color:var(--color-brand-mark-20)}
329
+ .nxm-s-21{stop-color:var(--color-brand-mark-21)}
330
+ .nxm-s-22{stop-color:var(--color-brand-mark-22)}
331
+ .nxm-s-23{stop-color:var(--color-brand-mark-23)}
332
+ .nxm-s-24{stop-color:var(--color-brand-mark-24)}
333
+ .nxm-s-25{stop-color:var(--color-brand-mark-25)}
334
+ .nxm-s-26{stop-color:var(--color-brand-mark-26)}
335
+ .nxm-s-27{stop-color:var(--color-brand-mark-27)}
336
+ .nxm-s-28{stop-color:var(--color-brand-mark-28)}
337
+ .nxm-s-29{stop-color:var(--color-brand-mark-29)}
338
+ .nxm-s-30{stop-color:var(--color-brand-mark-30)}
339
+ .nxm-s-31{stop-color:var(--color-brand-mark-31)}
340
+ .nxm-s-32{stop-color:var(--color-brand-mark-32)}
341
+ .nxm-s-33{stop-color:var(--color-brand-mark-33)}
342
+ .nxm-s-34{stop-color:var(--color-brand-mark-34)}
343
+ .nxm-s-35{stop-color:var(--color-brand-mark-35)}
344
+ .nxm-s-36{stop-color:var(--color-brand-mark-36)}
345
+ .nxm-s-37{stop-color:var(--color-brand-mark-37)}
346
+ .nxm-s-38{stop-color:var(--color-brand-mark-38)}
347
+ .nxm-s-39{stop-color:var(--color-brand-mark-39)}
348
+ .nxm-s-40{stop-color:var(--color-brand-mark-40)}
349
+ .nxm-s-41{stop-color:var(--color-brand-mark-41)}
350
+ .nxm-s-42{stop-color:var(--color-brand-mark-42)}
351
+ .nxm-s-43{stop-color:var(--color-brand-mark-43)}
352
+ .nxm-s-44{stop-color:var(--color-brand-mark-44)}
353
+ .nxm-s-45{stop-color:var(--color-brand-mark-45)}
354
+ .nxm-s-46{stop-color:var(--color-brand-mark-46)}
355
+ .nxm-s-47{stop-color:var(--color-brand-mark-47)}
356
+ .nxm-o-0{stop-opacity:0}
357
+ /* nexub-mark-stops:end */
358
+
359
+ /* ─── Radix ScrollArea / Select viewports ────────────────────────────────────
360
+ Radix renders these rules in a <style> tag, which a strict CSP blocks. The
361
+ same rules here keep the native scrollbar hidden either way. */
362
+ [data-radix-scroll-area-viewport],[data-radix-select-viewport]{scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch}
363
+ [data-radix-scroll-area-viewport]::-webkit-scrollbar,[data-radix-select-viewport]::-webkit-scrollbar{display:none}
364
+
240
365
  /* ─── Drawer / Sheet (vaul 1.1.2) ─────────────────────────────────────────────
241
366
  vaul's own styles. vaul normally injects these in a <style> tag when
242
367
  @nexub/react loads, which strict CSP pages block; @nexub/react strips that
package/src/bookub.css CHANGED
@@ -13,7 +13,7 @@
13
13
  --color-accent-800: var(--color-accent-bookub-800);
14
14
  --color-accent-900: var(--color-accent-bookub-900);
15
15
  --color-accent-950: var(--color-accent-bookub-950);
16
- --color-ring-default: var(--color-accent-bookub-500);
16
+ --color-ring-default: var(--color-tertiary); /* generated per brand in roles.css; >= 3:1 on every surface */
17
17
  --color-fill-accent: var(--color-fill-bookub);
18
18
  --color-fill-accent-hover: var(--color-fill-bookub-hover);
19
19
  }
package/src/dark.css CHANGED
@@ -1,122 +1,6 @@
1
1
  /* @nexub/themes — dark.css
2
- Dark-mode semantic token overrides.
3
- Apply via [data-theme='dark'] on an ancestor (typically <html>),
4
- or automatically via prefers-color-scheme when no explicit theme is set. */
5
-
6
- [data-theme='dark'] {
7
- /* ── Background ─────────────────────────────────────────────────────── */
8
- --color-bg-default: #0b1220;
9
- --color-bg-subtle: #0f172a;
10
- --color-bg-muted: #1e293b;
11
- --color-bg-raised: #162032;
12
- --color-bg-inverse: #f8fafc;
13
-
14
- /* ── Text ────────────────────────────────────────────────────────────── */
15
- --color-text-primary: #f8fafc;
16
- --color-text-secondary: #cbd5e1;
17
- --color-text-muted: #94a3b8;
18
- --color-text-subtle: #64748b;
19
- --color-text-inverse: #0f172a;
20
- --color-text-link: #60a5fa;
21
- --color-text-disabled: #475569;
22
-
23
- /* ── Border ──────────────────────────────────────────────────────────── */
24
- --color-border-default: #1e293b;
25
- --color-border-subtle: #162032;
26
- --color-border-strong: #334155;
27
- --color-border-inverse: #cbd5e1;
28
- --color-border-input: #64748b;
29
-
30
- /* ── Ring ────────────────────────────────────────────────────────────── */
31
- --color-ring-default: #60a5fa;
32
- --color-ring-offset: #0b1220;
33
-
34
- /* ── Surface ─────────────────────────────────────────────────────────── */
35
- --color-surface-warm: #1c1a0a;
36
- --color-surface-muted: #0f172a;
37
- --color-surface-raised: #162032;
38
- --color-surface-sunken: #080d19;
39
- --color-surface-inverse: #f8fafc;
40
-
41
- /* ── Hero gradient ───────────────────────────────────────────────────── */
42
- --gradient-hero-ambient: radial-gradient(ellipse 80% 50% at 50% -20%, rgba(64,153,241,0.08) 0%, transparent 60%), #0b1220;
43
-
44
- /* ── Semantic success (dark) ─────────────────────────────────────────── */
45
- --color-semantic-success-default: #34d399;
46
- --color-semantic-success-bg: rgba(52, 211, 153, 0.10);
47
- --color-semantic-success-border: rgba(52, 211, 153, 0.25);
48
- --color-semantic-success-strong: #6ee7b7;
49
-
50
- /* ── Semantic error / danger (dark) ─────────────────────────────────── */
51
- --color-semantic-error-default: #f87171;
52
- --color-semantic-error-bg: rgba(248, 113, 113, 0.10);
53
- --color-semantic-error-border: rgba(248, 113, 113, 0.25);
54
- --color-semantic-error-strong: #fca5a5;
55
-
56
- /* ── Semantic warning (dark) ─────────────────────────────────────────── */
57
- --color-semantic-warning-default: #fbbf24;
58
- --color-semantic-warning-bg: rgba(251, 191, 36, 0.10);
59
- --color-semantic-warning-border: rgba(251, 191, 36, 0.25);
60
- --color-semantic-warning-strong: #fcd34d;
61
-
62
- /* ── Semantic info (dark) ────────────────────────────────────────────── */
63
- --color-semantic-info-default: #60a5fa;
64
- --color-semantic-info-bg: rgba(96, 165, 250, 0.10);
65
- --color-semantic-info-border: rgba(96, 165, 250, 0.25);
66
- --color-semantic-info-strong: #93c5fd;
67
- }
68
-
69
- @media (prefers-color-scheme: dark) {
70
- :root:not([data-theme]) {
71
- --color-bg-default: #0b1220;
72
- --color-bg-subtle: #0f172a;
73
- --color-bg-muted: #1e293b;
74
- --color-bg-raised: #162032;
75
- --color-bg-inverse: #f8fafc;
76
-
77
- --color-text-primary: #f8fafc;
78
- --color-text-secondary: #cbd5e1;
79
- --color-text-muted: #94a3b8;
80
- --color-text-subtle: #64748b;
81
- --color-text-inverse: #0f172a;
82
- --color-text-link: #60a5fa;
83
- --color-text-disabled: #475569;
84
-
85
- --color-border-default: #1e293b;
86
- --color-border-subtle: #162032;
87
- --color-border-strong: #334155;
88
- --color-border-inverse: #cbd5e1;
89
- --color-border-input: #64748b;
90
-
91
- --color-ring-default: #60a5fa;
92
- --color-ring-offset: #0b1220;
93
-
94
- --color-surface-warm: #1c1a0a;
95
- --color-surface-muted: #0f172a;
96
- --color-surface-raised: #162032;
97
- --color-surface-sunken: #080d19;
98
- --color-surface-inverse: #f8fafc;
99
-
100
- --gradient-hero-ambient: radial-gradient(ellipse 80% 50% at 50% -20%, rgba(64,153,241,0.08) 0%, transparent 60%), #0b1220;
101
-
102
- --color-semantic-success-default: #34d399;
103
- --color-semantic-success-bg: rgba(52, 211, 153, 0.10);
104
- --color-semantic-success-border: rgba(52, 211, 153, 0.25);
105
- --color-semantic-success-strong: #6ee7b7;
106
-
107
- --color-semantic-error-default: #f87171;
108
- --color-semantic-error-bg: rgba(248, 113, 113, 0.10);
109
- --color-semantic-error-border: rgba(248, 113, 113, 0.25);
110
- --color-semantic-error-strong: #fca5a5;
111
-
112
- --color-semantic-warning-default: #fbbf24;
113
- --color-semantic-warning-bg: rgba(251, 191, 36, 0.10);
114
- --color-semantic-warning-border: rgba(251, 191, 36, 0.25);
115
- --color-semantic-warning-strong: #fcd34d;
116
-
117
- --color-semantic-info-default: #60a5fa;
118
- --color-semantic-info-bg: rgba(96, 165, 250, 0.10);
119
- --color-semantic-info-border: rgba(96, 165, 250, 0.25);
120
- --color-semantic-info-strong: #93c5fd;
121
- }
122
- }
2
+ Dark mode needs no separate values any more: every color is a light-dark()
3
+ role (@nexub/tokens/css/roles), and roles.css sets color-scheme: dark for
4
+ [data-theme='dark'] (any ancestor) or, with no data-theme, for
5
+ prefers-color-scheme: dark. This file stays importable for existing setups;
6
+ it is intentionally empty. */
@@ -0,0 +1,93 @@
1
+ Copyright 2016 The Inter Project Authors (https://github.com/rsms/inter) Inter-Italic[opsz,wght].ttf: Copyright 2016 The Inter Project Authors (https://github.com/rsms/inter)
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ http://scripts.sil.org/OFL
6
+
7
+
8
+ -----------------------------------------------------------
9
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
+ -----------------------------------------------------------
11
+
12
+ PREAMBLE
13
+ The goals of the Open Font License (OFL) are to stimulate worldwide
14
+ development of collaborative font projects, to support the font creation
15
+ efforts of academic and linguistic communities, and to provide a free and
16
+ open framework in which fonts may be shared and improved in partnership
17
+ with others.
18
+
19
+ The OFL allows the licensed fonts to be used, studied, modified and
20
+ redistributed freely as long as they are not sold by themselves. The
21
+ fonts, including any derivative works, can be bundled, embedded,
22
+ redistributed and/or sold with any software provided that any reserved
23
+ names are not used by derivative works. The fonts and derivatives,
24
+ however, cannot be released under any other type of license. The
25
+ requirement for fonts to remain under this license does not apply
26
+ to any document created using the fonts or their derivatives.
27
+
28
+ DEFINITIONS
29
+ "Font Software" refers to the set of files released by the Copyright
30
+ Holder(s) under this license and clearly marked as such. This may
31
+ include source files, build scripts and documentation.
32
+
33
+ "Reserved Font Name" refers to any names specified as such after the
34
+ copyright statement(s).
35
+
36
+ "Original Version" refers to the collection of Font Software components as
37
+ distributed by the Copyright Holder(s).
38
+
39
+ "Modified Version" refers to any derivative made by adding to, deleting,
40
+ or substituting -- in part or in whole -- any of the components of the
41
+ Original Version, by changing formats or by porting the Font Software to a
42
+ new environment.
43
+
44
+ "Author" refers to any designer, engineer, programmer, technical
45
+ writer or other person who contributed to the Font Software.
46
+
47
+ PERMISSION & CONDITIONS
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
+ redistribute, and sell modified and unmodified copies of the Font
51
+ Software, subject to the following conditions:
52
+
53
+ 1) Neither the Font Software nor any of its individual components,
54
+ in Original or Modified Versions, may be sold by itself.
55
+
56
+ 2) Original or Modified Versions of the Font Software may be bundled,
57
+ redistributed and/or sold with any software, provided that each copy
58
+ contains the above copyright notice and this license. These can be
59
+ included either as stand-alone text files, human-readable headers or
60
+ in the appropriate machine-readable metadata fields within text or
61
+ binary files as long as those fields can be easily viewed by the user.
62
+
63
+ 3) No Modified Version of the Font Software may use the Reserved Font
64
+ Name(s) unless explicit written permission is granted by the corresponding
65
+ Copyright Holder. This restriction only applies to the primary font name as
66
+ presented to the users.
67
+
68
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
+ Software shall not be used to promote, endorse or advertise any
70
+ Modified Version, except to acknowledge the contribution(s) of the
71
+ Copyright Holder(s) and the Author(s) or with their explicit written
72
+ permission.
73
+
74
+ 5) The Font Software, modified or unmodified, in part or in whole,
75
+ must be distributed entirely under this license, and must not be
76
+ distributed under any other license. The requirement for fonts to
77
+ remain under this license does not apply to any document created
78
+ using the Font Software.
79
+
80
+ TERMINATION
81
+ This license becomes null and void if any of the above conditions are
82
+ not met.
83
+
84
+ DISCLAIMER
85
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
+ OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,93 @@
1
+ Copyright 2020 The Plus Jakarta Sans Project Authors (https://github.com/tokotype/PlusJakartaSans) PlusJakartaSans-Italic[wght].ttf: Copyright 2020 The Plus Jakarta Sans Project Authors (https://github.com/tokotype/PlusJakartaSans)
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ http://scripts.sil.org/OFL
6
+
7
+
8
+ -----------------------------------------------------------
9
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
+ -----------------------------------------------------------
11
+
12
+ PREAMBLE
13
+ The goals of the Open Font License (OFL) are to stimulate worldwide
14
+ development of collaborative font projects, to support the font creation
15
+ efforts of academic and linguistic communities, and to provide a free and
16
+ open framework in which fonts may be shared and improved in partnership
17
+ with others.
18
+
19
+ The OFL allows the licensed fonts to be used, studied, modified and
20
+ redistributed freely as long as they are not sold by themselves. The
21
+ fonts, including any derivative works, can be bundled, embedded,
22
+ redistributed and/or sold with any software provided that any reserved
23
+ names are not used by derivative works. The fonts and derivatives,
24
+ however, cannot be released under any other type of license. The
25
+ requirement for fonts to remain under this license does not apply
26
+ to any document created using the fonts or their derivatives.
27
+
28
+ DEFINITIONS
29
+ "Font Software" refers to the set of files released by the Copyright
30
+ Holder(s) under this license and clearly marked as such. This may
31
+ include source files, build scripts and documentation.
32
+
33
+ "Reserved Font Name" refers to any names specified as such after the
34
+ copyright statement(s).
35
+
36
+ "Original Version" refers to the collection of Font Software components as
37
+ distributed by the Copyright Holder(s).
38
+
39
+ "Modified Version" refers to any derivative made by adding to, deleting,
40
+ or substituting -- in part or in whole -- any of the components of the
41
+ Original Version, by changing formats or by porting the Font Software to a
42
+ new environment.
43
+
44
+ "Author" refers to any designer, engineer, programmer, technical
45
+ writer or other person who contributed to the Font Software.
46
+
47
+ PERMISSION & CONDITIONS
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
+ redistribute, and sell modified and unmodified copies of the Font
51
+ Software, subject to the following conditions:
52
+
53
+ 1) Neither the Font Software nor any of its individual components,
54
+ in Original or Modified Versions, may be sold by itself.
55
+
56
+ 2) Original or Modified Versions of the Font Software may be bundled,
57
+ redistributed and/or sold with any software, provided that each copy
58
+ contains the above copyright notice and this license. These can be
59
+ included either as stand-alone text files, human-readable headers or
60
+ in the appropriate machine-readable metadata fields within text or
61
+ binary files as long as those fields can be easily viewed by the user.
62
+
63
+ 3) No Modified Version of the Font Software may use the Reserved Font
64
+ Name(s) unless explicit written permission is granted by the corresponding
65
+ Copyright Holder. This restriction only applies to the primary font name as
66
+ presented to the users.
67
+
68
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
+ Software shall not be used to promote, endorse or advertise any
70
+ Modified Version, except to acknowledge the contribution(s) of the
71
+ Copyright Holder(s) and the Author(s) or with their explicit written
72
+ permission.
73
+
74
+ 5) The Font Software, modified or unmodified, in part or in whole,
75
+ must be distributed entirely under this license, and must not be
76
+ distributed under any other license. The requirement for fonts to
77
+ remain under this license does not apply to any document created
78
+ using the Font Software.
79
+
80
+ TERMINATION
81
+ This license becomes null and void if any of the above conditions are
82
+ not met.
83
+
84
+ DISCLAIMER
85
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
+ OTHER DEALINGS IN THE FONT SOFTWARE.
package/src/fonts.css ADDED
@@ -0,0 +1,205 @@
1
+ /* @nexub/themes — fonts.css. GENERATED by scripts/build-fonts.mjs, do not edit.
2
+ Inter + Plus Jakarta Sans (OFL-1.1, see fonts/LICENSE-*) from
3
+ @fontsource-variable/inter@5.3.0, @fontsource-variable/plus-jakarta-sans@5.3.0. Every file is over 8192 bytes so
4
+ bundlers emit it as a file instead of inlining a data: URL (strict-CSP safe).
5
+ Left out: plus-jakarta-sans-cyrillic-ext-wght-normal.woff2, plus-jakarta-sans-cyrillic-ext-wght-italic.woff2. */
6
+
7
+ /* inter-cyrillic-ext-opsz-normal */
8
+ @font-face {
9
+ font-family: 'Inter Variable';
10
+ font-style: normal;
11
+ font-display: swap;
12
+ font-weight: 100 900;
13
+ src: url(./fonts/inter-cyrillic-ext-opsz-normal.woff2) format('woff2-variations');
14
+ unicode-range: U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F;
15
+ }
16
+
17
+ /* inter-cyrillic-opsz-normal */
18
+ @font-face {
19
+ font-family: 'Inter Variable';
20
+ font-style: normal;
21
+ font-display: swap;
22
+ font-weight: 100 900;
23
+ src: url(./fonts/inter-cyrillic-opsz-normal.woff2) format('woff2-variations');
24
+ unicode-range: U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;
25
+ }
26
+
27
+ /* inter-greek-ext-opsz-normal */
28
+ @font-face {
29
+ font-family: 'Inter Variable';
30
+ font-style: normal;
31
+ font-display: swap;
32
+ font-weight: 100 900;
33
+ src: url(./fonts/inter-greek-ext-opsz-normal.woff2) format('woff2-variations');
34
+ unicode-range: U+1F00-1FFF;
35
+ }
36
+
37
+ /* inter-greek-opsz-normal */
38
+ @font-face {
39
+ font-family: 'Inter Variable';
40
+ font-style: normal;
41
+ font-display: swap;
42
+ font-weight: 100 900;
43
+ src: url(./fonts/inter-greek-opsz-normal.woff2) format('woff2-variations');
44
+ unicode-range: U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF;
45
+ }
46
+
47
+ /* inter-vietnamese-opsz-normal */
48
+ @font-face {
49
+ font-family: 'Inter Variable';
50
+ font-style: normal;
51
+ font-display: swap;
52
+ font-weight: 100 900;
53
+ src: url(./fonts/inter-vietnamese-opsz-normal.woff2) format('woff2-variations');
54
+ unicode-range: U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB;
55
+ }
56
+
57
+ /* inter-latin-ext-opsz-normal */
58
+ @font-face {
59
+ font-family: 'Inter Variable';
60
+ font-style: normal;
61
+ font-display: swap;
62
+ font-weight: 100 900;
63
+ src: url(./fonts/inter-latin-ext-opsz-normal.woff2) format('woff2-variations');
64
+ unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
65
+ }
66
+
67
+ /* inter-latin-opsz-normal */
68
+ @font-face {
69
+ font-family: 'Inter Variable';
70
+ font-style: normal;
71
+ font-display: swap;
72
+ font-weight: 100 900;
73
+ src: url(./fonts/inter-latin-opsz-normal.woff2) format('woff2-variations');
74
+ unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
75
+ }
76
+
77
+ /* inter-cyrillic-ext-opsz-italic */
78
+ @font-face {
79
+ font-family: 'Inter Variable';
80
+ font-style: italic;
81
+ font-display: swap;
82
+ font-weight: 100 900;
83
+ src: url(./fonts/inter-cyrillic-ext-opsz-italic.woff2) format('woff2-variations');
84
+ unicode-range: U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F;
85
+ }
86
+
87
+ /* inter-cyrillic-opsz-italic */
88
+ @font-face {
89
+ font-family: 'Inter Variable';
90
+ font-style: italic;
91
+ font-display: swap;
92
+ font-weight: 100 900;
93
+ src: url(./fonts/inter-cyrillic-opsz-italic.woff2) format('woff2-variations');
94
+ unicode-range: U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;
95
+ }
96
+
97
+ /* inter-greek-ext-opsz-italic */
98
+ @font-face {
99
+ font-family: 'Inter Variable';
100
+ font-style: italic;
101
+ font-display: swap;
102
+ font-weight: 100 900;
103
+ src: url(./fonts/inter-greek-ext-opsz-italic.woff2) format('woff2-variations');
104
+ unicode-range: U+1F00-1FFF;
105
+ }
106
+
107
+ /* inter-greek-opsz-italic */
108
+ @font-face {
109
+ font-family: 'Inter Variable';
110
+ font-style: italic;
111
+ font-display: swap;
112
+ font-weight: 100 900;
113
+ src: url(./fonts/inter-greek-opsz-italic.woff2) format('woff2-variations');
114
+ unicode-range: U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF;
115
+ }
116
+
117
+ /* inter-vietnamese-opsz-italic */
118
+ @font-face {
119
+ font-family: 'Inter Variable';
120
+ font-style: italic;
121
+ font-display: swap;
122
+ font-weight: 100 900;
123
+ src: url(./fonts/inter-vietnamese-opsz-italic.woff2) format('woff2-variations');
124
+ unicode-range: U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB;
125
+ }
126
+
127
+ /* inter-latin-ext-opsz-italic */
128
+ @font-face {
129
+ font-family: 'Inter Variable';
130
+ font-style: italic;
131
+ font-display: swap;
132
+ font-weight: 100 900;
133
+ src: url(./fonts/inter-latin-ext-opsz-italic.woff2) format('woff2-variations');
134
+ unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
135
+ }
136
+
137
+ /* inter-latin-opsz-italic */
138
+ @font-face {
139
+ font-family: 'Inter Variable';
140
+ font-style: italic;
141
+ font-display: swap;
142
+ font-weight: 100 900;
143
+ src: url(./fonts/inter-latin-opsz-italic.woff2) format('woff2-variations');
144
+ unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
145
+ }
146
+
147
+ /* plus-jakarta-sans-vietnamese-wght-normal */
148
+ @font-face {
149
+ font-family: 'Plus Jakarta Sans Variable';
150
+ font-style: normal;
151
+ font-display: swap;
152
+ font-weight: 200 800;
153
+ src: url(./fonts/plus-jakarta-sans-vietnamese-wght-normal.woff2) format('woff2-variations');
154
+ unicode-range: U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB;
155
+ }
156
+
157
+ /* plus-jakarta-sans-latin-ext-wght-normal */
158
+ @font-face {
159
+ font-family: 'Plus Jakarta Sans Variable';
160
+ font-style: normal;
161
+ font-display: swap;
162
+ font-weight: 200 800;
163
+ src: url(./fonts/plus-jakarta-sans-latin-ext-wght-normal.woff2) format('woff2-variations');
164
+ unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
165
+ }
166
+
167
+ /* plus-jakarta-sans-latin-wght-normal */
168
+ @font-face {
169
+ font-family: 'Plus Jakarta Sans Variable';
170
+ font-style: normal;
171
+ font-display: swap;
172
+ font-weight: 200 800;
173
+ src: url(./fonts/plus-jakarta-sans-latin-wght-normal.woff2) format('woff2-variations');
174
+ unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
175
+ }
176
+
177
+ /* plus-jakarta-sans-vietnamese-wght-italic */
178
+ @font-face {
179
+ font-family: 'Plus Jakarta Sans Variable';
180
+ font-style: italic;
181
+ font-display: swap;
182
+ font-weight: 200 800;
183
+ src: url(./fonts/plus-jakarta-sans-vietnamese-wght-italic.woff2) format('woff2-variations');
184
+ unicode-range: U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB;
185
+ }
186
+
187
+ /* plus-jakarta-sans-latin-ext-wght-italic */
188
+ @font-face {
189
+ font-family: 'Plus Jakarta Sans Variable';
190
+ font-style: italic;
191
+ font-display: swap;
192
+ font-weight: 200 800;
193
+ src: url(./fonts/plus-jakarta-sans-latin-ext-wght-italic.woff2) format('woff2-variations');
194
+ unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
195
+ }
196
+
197
+ /* plus-jakarta-sans-latin-wght-italic */
198
+ @font-face {
199
+ font-family: 'Plus Jakarta Sans Variable';
200
+ font-style: italic;
201
+ font-display: swap;
202
+ font-weight: 200 800;
203
+ src: url(./fonts/plus-jakarta-sans-latin-wght-italic.woff2) format('woff2-variations');
204
+ unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
205
+ }
package/src/founderub.css CHANGED
@@ -13,7 +13,7 @@
13
13
  --color-accent-800: var(--color-accent-founderub-800);
14
14
  --color-accent-900: var(--color-accent-founderub-900);
15
15
  --color-accent-950: var(--color-accent-founderub-950);
16
- --color-ring-default: var(--color-accent-founderub-500);
16
+ --color-ring-default: var(--color-tertiary); /* generated per brand in roles.css; >= 3:1 on every surface */
17
17
  --color-fill-accent: var(--color-fill-founderub);
18
18
  --color-fill-accent-hover: var(--color-fill-founderub-hover);
19
19
  }
package/src/glass.css CHANGED
@@ -1,44 +1,107 @@
1
1
  /* @nexub/themes — glass.css
2
- Liquid-glass MATERIAL layer. Orthogonal to light/dark: set data-material="glass"
3
- on a surface (components do this via surface="glass") IN ADDITION to the normal
4
- theme. Import once, after base/light/dark. Selectors mirror dark.css so the
5
- dark palette resolves both for an explicit [data-theme='dark'] and for the
6
- prefers-color-scheme auto case. */
2
+ Glass 2.0: a translucent MATERIAL for the floating control layer (bars,
3
+ toolbars, popovers, menus, sheets, dialogs). Orthogonal to light/dark: the
4
+ fill is the surface role (a light-dark() value), so dark glass needs no
5
+ separate rules. Components opt in with surface="glass", which sets
6
+ data-material="glass" and the glass utility classes (@nexub/react utils/glass).
7
7
 
8
+ Knobs, all optional, on the element or any ancestor:
9
+ data-glass="clear|balanced|tinted|off" user intensity dial (ThemeProvider)
10
+ data-glass-thickness="thin|regular|thick" size → blur + shadow (per component)
11
+ data-glass-variant="clear" over media only: low fill, bright bold content
12
+ data-glass-tint="primary" the one emphasised action
13
+ data-scroll-edge="soft|hard" sticky bars: fade content under the bar / opaque band
14
+ Import once, after base/light. */
15
+
16
+ /* ── Intensity dial (user preference, like iOS 27's clear → tinted slider) ── */
17
+ [data-glass='clear'] { --glass-dial: 0.35; }
18
+ [data-glass='balanced'] { --glass-dial: 0.62; }
19
+ [data-glass='tinted'] { --glass-dial: 0.85; }
20
+
21
+ /* ── Recipe ─────────────────────────────────────────────────────────────────── */
8
22
  [data-material='glass'] {
9
- --glass-bg: rgba(255, 255, 255, 0.55);
10
- --glass-border: rgba(255, 255, 255, 0.35);
11
- --glass-highlight: rgba(255, 255, 255, 0.65);
12
- --glass-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
13
- --glass-blur: 16px;
14
- }
15
-
16
- /* glass-on-dark — explicit theme */
17
- [data-theme='dark'] [data-material='glass'],
18
- [data-theme='dark'][data-material='glass'] {
19
- --glass-bg: rgba(20, 20, 24, 0.55);
20
- --glass-border: rgba(255, 255, 255, 0.12);
21
- --glass-highlight: rgba(255, 255, 255, 0.10);
22
- --glass-shadow: 0 8px 32px rgba(0, 0, 0, 0.45);
23
- }
24
-
25
- /* glass-on-dark — auto (no explicit theme + OS dark) */
26
- @media (prefers-color-scheme: dark) {
27
- :root:not([data-theme]) [data-material='glass'],
28
- :root:not([data-theme])[data-material='glass'] {
29
- --glass-bg: rgba(20, 20, 24, 0.55);
30
- --glass-border: rgba(255, 255, 255, 0.12);
31
- --glass-highlight: rgba(255, 255, 255, 0.10);
32
- --glass-shadow: 0 8px 32px rgba(0, 0, 0, 0.45);
33
- }
23
+ --glass-opacity: var(--glass-dial, 0.62);
24
+ --glass-tint: var(--color-surface);
25
+ --glass-blur: 16px;
26
+ --glass-saturate: 180%;
27
+ --glass-elevation: var(--elevation-2);
28
+
29
+ --glass-bg: color-mix(in oklch, var(--glass-tint) calc(var(--glass-opacity) * 100%), transparent);
30
+ /* Edge: a hairline plus a bright top specular and a faint bottom rim. */
31
+ --glass-border: light-dark(rgb(255 255 255 / 0.5), rgb(255 255 255 / 0.12));
32
+ --glass-highlight: light-dark(rgb(255 255 255 / 0.7), rgb(255 255 255 / 0.14));
33
+ --glass-rim: light-dark(rgb(255 255 255 / 0.2), rgb(255 255 255 / 0.04));
34
+ --glass-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
35
+ --glass-shadow: inset 0 1px 0 0 var(--glass-highlight), inset 0 -1px 0 0 var(--glass-rim), var(--glass-elevation);
36
+ }
37
+
38
+ /* Thickness scales with size, like Apple's material: more blur, deeper shadow. */
39
+ [data-material='glass'][data-glass-thickness='thin'] {
40
+ --glass-blur: 8px;
41
+ --glass-saturate: 170%;
42
+ --glass-elevation: var(--elevation-1);
43
+ }
44
+ [data-material='glass'][data-glass-thickness='thick'] {
45
+ --glass-blur: 28px;
46
+ --glass-elevation: var(--elevation-3);
47
+ }
48
+
49
+ /* Tint: the single emphasised action. Kept near-opaque so on-primary text holds. */
50
+ [data-material='glass'][data-glass-tint='primary'] {
51
+ --glass-tint: var(--color-primary);
52
+ --glass-opacity: max(var(--glass-dial, 0.62), 0.82);
53
+ }
54
+
55
+ /* Clear: over imagery/video only. A dim scrim instead of a surface fill. */
56
+ [data-material='glass'][data-glass-variant='clear'] {
57
+ --glass-bg: rgb(0 0 0 / calc(var(--glass-dial, 0.62) * 0.4));
58
+ --glass-blur: 6px;
59
+ --glass-border: rgb(255 255 255 / 0.22);
60
+ --glass-highlight: rgb(255 255 255 / 0.3);
34
61
  }
35
62
 
36
- /* a11y: drop translucency + blur when the user opts out — fall back to the
37
- solid surface tokens Card/Dialog/etc. already use. Load-bearing, not polish. */
38
- @media (prefers-reduced-transparency: reduce), (prefers-contrast: more) {
39
- [data-material='glass'] {
40
- --glass-bg: var(--color-bg-default);
41
- --glass-border: var(--color-border-default);
42
- --glass-blur: 0px;
63
+ /* Scroll edge (sticky bars): soft = content dissolves under the bar; hard = opaque band. */
64
+ [data-scroll-edge='soft'] {
65
+ -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 14px), transparent);
66
+ mask-image: linear-gradient(to bottom, #000 calc(100% - 14px), transparent);
67
+ border-bottom-color: transparent;
68
+ }
69
+ [data-material='glass'][data-scroll-edge='hard'] {
70
+ --glass-opacity: max(var(--glass-dial, 0.62), 0.9);
71
+ }
72
+
73
+ /* ── Solid fallbacks: load-bearing, not polish ──────────────────────────────── */
74
+ /* Each fallback sets the fill itself (solid tint) and doubles the attribute so
75
+ it outranks the two-attribute variant rules above (clear, tint, hard edge). */
76
+ [data-glass='off'] [data-material='glass'],
77
+ [data-glass='off'][data-material='glass'] {
78
+ --glass-bg: var(--glass-tint);
79
+ --glass-filter: none;
80
+ }
81
+ @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
82
+ [data-material='glass'][data-material='glass'] { --glass-opacity: 0.94; }
83
+ }
84
+ @media (prefers-reduced-transparency: reduce) {
85
+ [data-material='glass'][data-material='glass'] {
86
+ --glass-bg: var(--glass-tint);
87
+ --glass-filter: none;
88
+ }
89
+ }
90
+ @media (prefers-contrast: more) {
91
+ [data-material='glass'][data-material='glass'] {
92
+ --glass-bg: var(--glass-tint);
93
+ --glass-filter: none;
94
+ --glass-border: var(--color-outline);
95
+ outline: 2px solid var(--color-outline);
96
+ outline-offset: -2px;
97
+ }
98
+ }
99
+ @media (forced-colors: active) {
100
+ /* Through the vars: the component's utility classes outrank a plain
101
+ backdrop-filter declaration here. */
102
+ [data-material='glass'][data-material='glass'] {
103
+ --glass-bg: Canvas;
104
+ --glass-filter: none;
105
+ --glass-border: CanvasText;
43
106
  }
44
107
  }
package/src/leap.css CHANGED
@@ -13,7 +13,7 @@
13
13
  --color-accent-800: var(--color-accent-leap-800);
14
14
  --color-accent-900: var(--color-accent-leap-900);
15
15
  --color-accent-950: var(--color-accent-leap-950);
16
- --color-ring-default: var(--color-accent-leap-500);
16
+ --color-ring-default: var(--color-tertiary); /* generated per brand in roles.css; >= 3:1 on every surface */
17
17
  --color-fill-accent: var(--color-fill-leap);
18
18
  --color-fill-accent-hover: var(--color-fill-leap-hover);
19
19
  }
package/src/light.css CHANGED
@@ -1,37 +1,63 @@
1
1
  /* @nexub/themes — light.css
2
- Explicit light-mode semantic token assignments.
2
+ Legacy semantic names → Calm Depth color roles (@nexub/tokens/css/roles).
3
+ Roles are light-dark() values, so these aliases resolve per color-scheme:
4
+ light by default, dark under [data-theme='dark'] (or the OS when no
5
+ data-theme is set), at any depth. New code should use the role names
6
+ (--color-surface, --color-on-surface, …) directly.
3
7
  Import after base.css. */
4
8
 
5
- :root,
6
- [data-theme='light'] {
7
- --color-bg-default: #ffffff;
8
- --color-bg-subtle: #f8fafc;
9
- --color-bg-muted: #f1f5f9;
10
- --color-bg-raised: #ffffff;
11
- --color-bg-inverse: #0f172a;
12
-
13
- --color-text-primary: #0f172a;
14
- --color-text-secondary: #334155;
15
- --color-text-muted: #64748b;
16
- --color-text-subtle: #94a3b8;
17
- --color-text-inverse: #f8fafc;
18
- --color-text-link: #2563eb;
19
- --color-text-disabled: #94a3b8;
20
-
21
- --color-border-default: #e2e8f0;
22
- --color-border-subtle: #f1f5f9;
23
- --color-border-strong: #94a3b8;
24
- --color-border-inverse: #334155;
25
- --color-border-input: #848e9f;
26
-
27
- --color-ring-default: #4099f1;
28
- --color-ring-offset: #ffffff;
29
-
30
- --color-surface-warm: #fefce8;
31
- --color-surface-muted: #f8fafc;
32
- --color-surface-raised: #ffffff;
33
- --color-surface-sunken: #f1f5f9;
34
- --color-surface-inverse: #0f172a;
35
-
36
- --gradient-hero-ambient: radial-gradient(ellipse 80% 50% at 50% -20%, rgba(64,153,241,0.12) 0%, transparent 60%), radial-gradient(ellipse 60% 40% at 80% 80%, rgba(28,206,102,0.06) 0%, transparent 50%), #ffffff;
9
+ :root {
10
+ --color-bg-default: var(--color-surface);
11
+ --color-bg-subtle: var(--color-surface-container-low);
12
+ --color-bg-muted: var(--color-surface-container-high);
13
+ --color-bg-raised: var(--color-surface-elevated);
14
+ --color-bg-inverse: var(--color-inverse-surface);
15
+
16
+ --color-text-primary: var(--color-on-surface);
17
+ --color-text-secondary: var(--color-on-surface-variant);
18
+ --color-text-muted: var(--color-on-surface-muted);
19
+ --color-text-subtle: var(--color-outline);
20
+ --color-text-inverse: var(--color-inverse-on-surface);
21
+ --color-text-link: var(--color-primary);
22
+ --color-text-disabled: color-mix(in srgb, var(--color-on-surface) 38%, transparent);
23
+
24
+ --color-border-default: var(--color-outline-variant);
25
+ --color-border-subtle: var(--color-surface-container-high);
26
+ --color-border-strong: var(--color-outline);
27
+ --color-border-inverse: var(--color-inverse-on-surface);
28
+ /* Form-control boundaries: outline clears 3:1 (WCAG 1.4.11) on every surface. */
29
+ --color-border-input: var(--color-outline);
30
+
31
+ --color-ring-default: var(--color-primary);
32
+ --color-ring-offset: var(--color-surface);
33
+
34
+ --color-surface-warm: light-dark(#fefce8, #1c1a0a);
35
+ --color-surface-muted: var(--color-surface-container-low);
36
+ --color-surface-raised: var(--color-surface-elevated);
37
+ --color-surface-sunken: var(--color-surface-container-high);
38
+ --color-surface-inverse: var(--color-inverse-surface);
39
+
40
+ /* Semantic tones: default = the role, strong = text-safe on page and container,
41
+ bg = container, border = the role at 35%. */
42
+ --color-semantic-success-default: var(--color-success);
43
+ --color-semantic-success-strong: var(--color-on-success-container);
44
+ --color-semantic-success-bg: var(--color-success-container);
45
+ --color-semantic-success-border: color-mix(in srgb, var(--color-success) 35%, transparent);
46
+
47
+ --color-semantic-error-default: var(--color-error);
48
+ --color-semantic-error-strong: var(--color-on-error-container);
49
+ --color-semantic-error-bg: var(--color-error-container);
50
+ --color-semantic-error-border: color-mix(in srgb, var(--color-error) 35%, transparent);
51
+
52
+ --color-semantic-warning-default: var(--color-warning);
53
+ --color-semantic-warning-strong: var(--color-on-warning-container);
54
+ --color-semantic-warning-bg: var(--color-warning-container);
55
+ --color-semantic-warning-border: color-mix(in srgb, var(--color-warning) 35%, transparent);
56
+
57
+ --color-semantic-info-default: var(--color-info);
58
+ --color-semantic-info-strong: var(--color-on-info-container);
59
+ --color-semantic-info-bg: var(--color-info-container);
60
+ --color-semantic-info-border: color-mix(in srgb, var(--color-info) 35%, transparent);
61
+
62
+ --gradient-hero-ambient: radial-gradient(ellipse 80% 50% at 50% -20%, light-dark(rgb(64 153 241 / 0.12), rgb(64 153 241 / 0.08)) 0%, transparent 60%), radial-gradient(ellipse 60% 40% at 80% 80%, light-dark(rgb(28 206 102 / 0.06), transparent) 0%, transparent 50%), var(--color-surface);
37
63
  }
package/src/payub.css CHANGED
@@ -13,7 +13,7 @@
13
13
  --color-accent-800: var(--color-accent-payub-800);
14
14
  --color-accent-900: var(--color-accent-payub-900);
15
15
  --color-accent-950: var(--color-accent-payub-950);
16
- --color-ring-default: var(--color-accent-payub-500);
16
+ --color-ring-default: var(--color-tertiary); /* generated per brand in roles.css; >= 3:1 on every surface */
17
17
  --color-fill-accent: var(--color-fill-payub);
18
18
  --color-fill-accent-hover: var(--color-fill-payub-hover);
19
19
  }