@nexub/themes 1.3.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nexub/themes",
3
- "version": "1.3.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,9 +36,10 @@
36
36
  "./founderub": "./src/founderub.css"
37
37
  },
38
38
  "dependencies": {
39
- "@nexub/tokens": "1.3.0"
39
+ "@nexub/tokens": "1.4.0"
40
40
  },
41
41
  "devDependencies": {
42
+ "@fontsource-variable/inter": "5.3.0",
42
43
  "@fontsource-variable/plus-jakarta-sans": "^5.3.0"
43
44
  },
44
45
  "scripts": {
package/src/base.css CHANGED
@@ -9,6 +9,7 @@
9
9
  so `font-src 'self'` works (see scripts/build-fonts.mjs). */
10
10
  @import './fonts.css';
11
11
  @import '@nexub/tokens/css';
12
+ @import '@nexub/tokens/css/roles';
12
13
 
13
14
  /* ─── Semantic shorthand aliases ───────────────────────────────────────────
14
15
  Components reference these shorter names. They proxy the full token names
@@ -48,7 +49,7 @@
48
49
 
49
50
  /* Form-control boundaries (WCAG 1.4.11 needs >= 3:1 against the page).
50
51
  Separate from --color-border-default, which cards/dividers keep light. */
51
- --color-border-input: #848e9f;
52
+ --color-border-input: var(--color-outline);
52
53
 
53
54
  /* placeholder text (PKG-B01) */
54
55
  --color-text-placeholder: var(--color-text-muted);
@@ -60,26 +61,27 @@
60
61
  --color-text-warning: var(--color-semantic-warning-strong);
61
62
  --color-text-danger: var(--color-semantic-error-strong);
62
63
 
63
- /* Solid fills under white text. Fixed shades (they do NOT flip in dark mode)
64
- chosen so white text is >= 4.5:1 (WCAG AA). Brand themes override accent. */
65
- --color-fill-primary: var(--color-brand-primary-600);
66
- --color-fill-primary-hover: var(--color-brand-primary-700);
67
- --color-fill-info: var(--color-brand-primary-600);
68
- --color-fill-info-hover: var(--color-brand-primary-700);
69
- --color-fill-success: #047857;
70
- --color-fill-success-hover: #065f46;
71
- --color-fill-warning: #b45309;
72
- --color-fill-warning-hover: #92400e;
73
- --color-fill-danger: #b91c1c;
74
- --color-fill-danger-hover: #991b1b;
75
- --color-fill-leap: var(--color-accent-leap-600);
76
- --color-fill-leap-hover: var(--color-accent-leap-700);
77
- --color-fill-bookub: var(--color-accent-bookub-700);
78
- --color-fill-bookub-hover: var(--color-accent-bookub-800);
79
- --color-fill-payub: var(--color-accent-payub-600);
80
- --color-fill-payub-hover: var(--color-accent-payub-700);
81
- --color-fill-founderub: var(--color-accent-founderub-700);
82
- --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);
83
85
  --color-fill-accent: var(--color-fill-primary);
84
86
  --color-fill-accent-hover: var(--color-fill-primary-hover);
85
87
 
@@ -139,11 +141,14 @@ html {
139
141
  -webkit-font-smoothing: antialiased;
140
142
  -moz-osx-font-smoothing: grayscale;
141
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;
142
147
  }
143
148
 
144
149
  /* Form controls don't inherit fonts by default — without this, apps that
145
150
  don't use Tailwind's preflight would render buttons/inputs in the system UI
146
- font instead of Plus Jakarta Sans. */
151
+ font instead of Inter. */
147
152
  button, input, select, textarea, optgroup {
148
153
  font-family: inherit;
149
154
  }
@@ -154,19 +159,25 @@ body {
154
159
  background: var(--gradient-hero-ambient);
155
160
  }
156
161
 
157
- /* 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). */
158
164
  :focus-visible {
159
- outline: 2px solid var(--color-ring-default);
160
- outline-offset: 3px;
161
- box-shadow: var(--shadow-focus);
165
+ outline: 3px solid var(--color-ring-default);
166
+ outline-offset: 2px;
162
167
  }
163
168
 
164
- /* Headings */
169
+ @media (forced-colors: active) {
170
+ :focus-visible { outline-color: Highlight; }
171
+ }
172
+
173
+ /* Headings: brand display face, balanced wrapping */
165
174
  h1, h2, h3, h4, h5, h6 {
166
175
  margin: 0;
176
+ font-family: var(--font-family-display);
167
177
  font-weight: var(--font-weight-bold);
168
178
  line-height: 1.2;
169
179
  color: var(--color-text-primary);
180
+ text-wrap: balance;
170
181
  }
171
182
 
172
183
  /* Paragraphs / lists */
@@ -174,11 +185,15 @@ p, ul, ol {
174
185
  margin: 0;
175
186
  }
176
187
 
188
+ p {
189
+ text-wrap: pretty;
190
+ }
191
+
177
192
  /* Links */
178
193
  a {
179
194
  color: var(--color-text-link);
180
195
  text-decoration: underline;
181
- text-underline-offset: 2px;
196
+ text-underline-offset: 0.3em;
182
197
  }
183
198
 
184
199
  a:hover {
@@ -199,7 +214,7 @@ code, kbd, pre, samp {
199
214
 
200
215
  /* Selection */
201
216
  ::selection {
202
- 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);
203
218
  color: var(--color-text-primary);
204
219
  }
205
220
 
@@ -232,12 +247,54 @@ code, kbd, pre, samp {
232
247
  }
233
248
  }
234
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
+
235
287
  /* Logo-scroll marquee keyframe (used by LogoWall) */
236
288
  @keyframes logo-scroll {
237
289
  from { transform: translateX(0); }
238
290
  to { transform: translateX(-50%); }
239
291
  }
240
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
+
241
298
  /* ─── Scroll lock (Sheet scrollLock="class") ─────────────────────────────────
242
299
  A CSP-safe page scroll lock: @nexub/react toggles these classes on <html>
243
300
  instead of injecting a <style> tag. The gutter class keeps the scrollbar's
@@ -245,6 +302,60 @@ code, kbd, pre, samp {
245
302
  html.nexub-scroll-lock { overflow: hidden; }
246
303
  html.nexub-scroll-lock.nexub-scroll-gutter { scrollbar-gutter: stable; }
247
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
+
248
359
  /* ─── Radix ScrollArea / Select viewports ────────────────────────────────────
249
360
  Radix renders these rules in a <style> tag, which a strict CSP blocks. The
250
361
  same rules here keep the native scrollbar hidden either way. */
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.
package/src/fonts.css CHANGED
@@ -1,9 +1,149 @@
1
1
  /* @nexub/themes — fonts.css. GENERATED by scripts/build-fonts.mjs, do not edit.
2
- Plus Jakarta Sans (OFL-1.1, see fonts/LICENSE) from
3
- @fontsource-variable/plus-jakarta-sans@5.3.0. Every file is over 8192 bytes so
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
4
  bundlers emit it as a file instead of inlining a data: URL (strict-CSP safe).
5
5
  Left out: plus-jakarta-sans-cyrillic-ext-wght-normal.woff2, plus-jakarta-sans-cyrillic-ext-wght-italic.woff2. */
6
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
+
7
147
  /* plus-jakarta-sans-vietnamese-wght-normal */
8
148
  @font-face {
9
149
  font-family: 'Plus Jakarta Sans Variable';
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
  }