@nebutra/tokens 2.0.0 → 3.0.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/CHANGELOG.md +8 -0
- package/dist/brand-package/index.d.ts +11 -5
- package/dist/brand-package/index.js +15 -14
- package/dist/brand-package/index.js.map +1 -1
- package/dist/brand-package/use-brand.js +15 -14
- package/dist/brand-package/use-brand.js.map +1 -1
- package/dist/index.js +15 -14
- package/dist/index.js.map +1 -1
- package/dist/values.d.ts +1192 -0
- package/dist/values.js +518 -0
- package/dist/values.js.map +1 -0
- package/package.json +11 -5
- package/recipe.css +28 -2
- package/skins/cosmos.css +8 -8
- package/skins/gsap.css +8 -8
- package/skins/linear.css +8 -8
- package/skins/notion.css +8 -8
- package/skins/raycast.css +8 -8
- package/skins/stripe.css +8 -8
- package/skins/vanta.css +6 -6
- package/skins/vercel.css +8 -8
- package/styles.css +396 -140
package/styles.css
CHANGED
|
@@ -47,17 +47,17 @@
|
|
|
47
47
|
--nebutra-cyan-800: #057963;
|
|
48
48
|
--nebutra-cyan-900: #035143;
|
|
49
49
|
--nebutra-cyan-950: #012923;
|
|
50
|
-
--nebutra-neutral-50: #
|
|
51
|
-
--nebutra-neutral-100: #
|
|
52
|
-
--nebutra-neutral-200: #
|
|
53
|
-
--nebutra-neutral-300: #
|
|
54
|
-
--nebutra-neutral-400: #
|
|
55
|
-
--nebutra-neutral-500: #
|
|
56
|
-
--nebutra-neutral-600: #
|
|
57
|
-
--nebutra-neutral-700: #
|
|
58
|
-
--nebutra-neutral-800: #
|
|
59
|
-
--nebutra-neutral-900: #
|
|
60
|
-
--nebutra-neutral-950: #
|
|
50
|
+
--nebutra-neutral-50: #f9fafb;
|
|
51
|
+
--nebutra-neutral-100: #f3f4f6;
|
|
52
|
+
--nebutra-neutral-200: #e4e5e8;
|
|
53
|
+
--nebutra-neutral-300: #d2d4d8;
|
|
54
|
+
--nebutra-neutral-400: #9fa1a5;
|
|
55
|
+
--nebutra-neutral-500: #717377;
|
|
56
|
+
--nebutra-neutral-600: #515357;
|
|
57
|
+
--nebutra-neutral-700: #3f4044;
|
|
58
|
+
--nebutra-neutral-800: #26272a;
|
|
59
|
+
--nebutra-neutral-900: #18191c;
|
|
60
|
+
--nebutra-neutral-950: #0b0c0d;
|
|
61
61
|
--nebutra-gray-50: #fafafa;
|
|
62
62
|
--nebutra-gray-100: #f5f5f5;
|
|
63
63
|
--nebutra-gray-200: #e5e5e5;
|
|
@@ -96,20 +96,91 @@
|
|
|
96
96
|
--tracking-display: -0.04em; /** Hero H1 */
|
|
97
97
|
--tracking-heading: -0.03em; /** Section H2/H3 */
|
|
98
98
|
--tracking-tight: -0.015em; /** Body emphasis */
|
|
99
|
+
--tracking-label: 0.07em; /** Uppercase micro-labels. 0.07em is Vercel's measured eyebrow value (0.071em); open tracking keeps small caps legible. */
|
|
99
100
|
--leading-display: 1.05;
|
|
100
101
|
--leading-heading: 1.15;
|
|
102
|
+
--type-2xs-size: 0.6875rem;
|
|
103
|
+
--type-2xs-leading: 1.45;
|
|
104
|
+
--type-2xs-tracking: 0.01em;
|
|
105
|
+
--type-xs-size: 0.75rem;
|
|
106
|
+
--type-xs-leading: 1.4;
|
|
107
|
+
--type-xs-tracking: 0.005em;
|
|
108
|
+
--type-ui-size: 0.8125rem;
|
|
109
|
+
--type-ui-leading: 1.45;
|
|
110
|
+
--type-ui-tracking: 0em;
|
|
111
|
+
--type-sm-size: 0.875rem;
|
|
112
|
+
--type-sm-leading: 1.5;
|
|
113
|
+
--type-sm-tracking: 0em;
|
|
114
|
+
--type-base-size: 1rem;
|
|
115
|
+
--type-base-leading: 1.6;
|
|
116
|
+
--type-base-tracking: -0.005em;
|
|
117
|
+
--type-lg-size: 1.125rem;
|
|
118
|
+
--type-lg-leading: 1.55;
|
|
119
|
+
--type-lg-tracking: -0.01em;
|
|
120
|
+
--type-xl-size: 1.25rem;
|
|
121
|
+
--type-xl-leading: 1.45;
|
|
122
|
+
--type-xl-tracking: -0.012em;
|
|
123
|
+
--type-2xl-size: 1.5rem;
|
|
124
|
+
--type-2xl-leading: 1.33;
|
|
125
|
+
--type-2xl-tracking: -0.015em;
|
|
126
|
+
--type-3xl-size: 1.875rem;
|
|
127
|
+
--type-3xl-leading: 1.25;
|
|
128
|
+
--type-3xl-tracking: -0.02em;
|
|
129
|
+
--type-4xl-size: 2.25rem;
|
|
130
|
+
--type-4xl-leading: 1.15;
|
|
131
|
+
--type-4xl-tracking: -0.022em;
|
|
132
|
+
--type-5xl-size: 3rem;
|
|
133
|
+
--type-5xl-leading: 1.08;
|
|
134
|
+
--type-5xl-tracking: -0.028em;
|
|
135
|
+
--type-6xl-size: 3.75rem;
|
|
136
|
+
--type-6xl-leading: 1.04;
|
|
137
|
+
--type-6xl-tracking: -0.032em;
|
|
138
|
+
--type-7xl-size: 4.5rem;
|
|
139
|
+
--type-7xl-leading: 1;
|
|
140
|
+
--type-7xl-tracking: -0.035em;
|
|
141
|
+
--type-8xl-size: 6rem;
|
|
142
|
+
--type-8xl-leading: 1;
|
|
143
|
+
--type-8xl-tracking: -0.04em;
|
|
144
|
+
--type-9xl-size: 8rem;
|
|
145
|
+
--type-9xl-leading: 1;
|
|
146
|
+
--type-9xl-tracking: -0.045em;
|
|
147
|
+
--type-display-size: 1.25rem;
|
|
148
|
+
--type-display-leading: 1.45;
|
|
149
|
+
--type-display-tracking: -0.012em;
|
|
150
|
+
--type-body-size: 0.875rem;
|
|
151
|
+
--type-body-leading: 1.5;
|
|
152
|
+
--type-body-tracking: 0em;
|
|
153
|
+
--type-label-size: 0.75rem;
|
|
154
|
+
--type-label-leading: 1.4;
|
|
155
|
+
--type-label-tracking: 0.005em;
|
|
156
|
+
--type-meta-size: 0.6875rem;
|
|
157
|
+
--type-meta-leading: 1.45;
|
|
158
|
+
--type-meta-tracking: 0.01em;
|
|
159
|
+
--layer-raised: 10; /** Within a component: an element lifted over its siblings. */
|
|
160
|
+
--layer-sticky: 20; /** Sticky headers and table heads. */
|
|
161
|
+
--layer-floating: 30; /** Floating toolbars and canvas chrome anchored to content. */
|
|
162
|
+
--layer-nav: 40; /** App navigation and the shell's top bar. */
|
|
163
|
+
--layer-drawer: 60; /** Mobile navigation drawers and their toggles. */
|
|
164
|
+
--layer-banner: 90; /** Page-level banners: cookie consent, announcements. */
|
|
165
|
+
--layer-skip-link: 100; /** The skip link — above page chrome whenever it is focused. */
|
|
166
|
+
--layer-panel: 200; /** App-owned floating panels that are not overlays (locale switcher, search flyouts). */
|
|
167
|
+
--layer-backdrop: 1040; /** Overlay tier. Mirrors overlayZIndex in @nebutra/ui; a test keeps them equal. */
|
|
168
|
+
--layer-modal: 1050; /** Dialogs and sheets. */
|
|
169
|
+
--layer-popover: 1060; /** Popovers, menus, selects. */
|
|
170
|
+
--layer-tooltip: 1070; /** Tooltips. */
|
|
171
|
+
--layer-devtools: 9999; /** Developer and debug surfaces only — never product UI. */
|
|
101
172
|
--ring-hairline: inset 0 0 0 1px rgb(255 255 255 / 0.04); /** Etched-glass hairline (light mode value, dark mode override in themes/dark.json) */
|
|
102
173
|
--overlay-faint: rgb(0 0 0 / 0.06); /** Light-mode faint overlay (6% black) */
|
|
103
174
|
--font-sans:
|
|
104
|
-
var(--font-geist-sans), "Geist", var(--font-
|
|
105
|
-
|
|
175
|
+
var(--font-geist-sans), "Geist", var(--font-misans, "MiSans"), "PingFang SC", "Microsoft YaHei",
|
|
176
|
+
-apple-system, BlinkMacSystemFont, system-ui, sans-serif;
|
|
106
177
|
--font-cn:
|
|
107
|
-
var(--font-geist-sans), "Geist", var(--font-
|
|
108
|
-
|
|
178
|
+
var(--font-geist-sans), "Geist", var(--font-misans, "MiSans"), "PingFang SC", "Microsoft YaHei",
|
|
179
|
+
sans-serif; /** CJK-locale stack — same order as sans, minus the Latin-only system faces */
|
|
109
180
|
--font-display:
|
|
110
|
-
var(--font-
|
|
181
|
+
var(--font-dm-sans), "DM Sans", var(--font-misans, "MiSans"), "PingFang SC", sans-serif;
|
|
111
182
|
--font-heading:
|
|
112
|
-
var(--font-
|
|
183
|
+
var(--font-dm-sans), "DM Sans", var(--font-misans, "MiSans"), "PingFang SC", sans-serif;
|
|
113
184
|
--font-mono:
|
|
114
185
|
var(--font-geist-mono), "Geist Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
|
|
115
186
|
--brand-primary: #0033fe; /** Brand primary — 云毓蓝 */
|
|
@@ -153,17 +224,17 @@
|
|
|
153
224
|
--motion-duration-cinematic: 500ms;
|
|
154
225
|
--focus-ring: 0 0 0 2px hsl(var(--ring) / 0.4); /** Single-layer translucent focus ring (2026 pattern). Legacy box-shadow consumers stay compatible; modern surfaces should prefer the global :focus-visible outline rule in static/base.css. */
|
|
155
226
|
--neutral-1: #ffffff; /** app background */
|
|
156
|
-
--neutral-2: #
|
|
157
|
-
--neutral-3: #
|
|
158
|
-
--neutral-4: #
|
|
159
|
-
--neutral-5: #
|
|
160
|
-
--neutral-6: #
|
|
161
|
-
--neutral-7: #
|
|
162
|
-
--neutral-8: #
|
|
163
|
-
--neutral-9: #
|
|
164
|
-
--neutral-10: #
|
|
165
|
-
--neutral-11: #
|
|
166
|
-
--neutral-12: #
|
|
227
|
+
--neutral-2: #f9fafb; /** subtle background */
|
|
228
|
+
--neutral-3: #f3f4f6; /** component bg default */
|
|
229
|
+
--neutral-4: #e4e5e8; /** component bg hover */
|
|
230
|
+
--neutral-5: #d2d4d8; /** component bg active */
|
|
231
|
+
--neutral-6: #b9bbbf; /** subtle border — DERIVED at build time (scripts/derive-border-tier.mjs): OKLab lerp step5 → step9 at t=0.25. The $value here is a placeholder anchor only; the preprocessor overwrites it. */
|
|
232
|
+
--neutral-7: #a0a2a6; /** default border — DERIVED: OKLab lerp step5 → step9 at t=0.50. */
|
|
233
|
+
--neutral-8: #888a8e; /** hovered border — DERIVED: OKLab lerp step5 → step9 at t=0.75. */
|
|
234
|
+
--neutral-9: #717377; /** solid fill */
|
|
235
|
+
--neutral-10: #515357; /** solid fill hover */
|
|
236
|
+
--neutral-11: #3f4044; /** secondary text */
|
|
237
|
+
--neutral-12: #18191c; /** primary text */
|
|
167
238
|
--blue-1: #fafcfe; /** app tint — L* 99.01, C 0.003, hue 264. Radix blue-1 sits at L* 99.31 C 0.003. */
|
|
168
239
|
--blue-2: #f2f6fd; /** subtle background — L* 97.21, C 0.010. */
|
|
169
240
|
--blue-3: #e7eefc; /** component background default — L* 94.79, C 0.020. */
|
|
@@ -190,20 +261,20 @@
|
|
|
190
261
|
--cyan-11: #027a61; /** secondary text — L* 51.64, C 0.100. 5.17:1 on step 1. */
|
|
191
262
|
--cyan-12: #004133; /** primary text — L* 33.45, C 0.065. 11.35:1 on step 1. */
|
|
192
263
|
--cyan-contrast: #0d2b25; /** Label ink for the bright fill tier. Absolute near-black, identical in both modes, carrying a trace of the scale hue. A bright fill needs an explicit dark ink; comparing white against the scale's own step 12 picks white in dark mode, where step 12 is light, and measures 1.52:1. 10.35:1 on step 9, 9.40:1 on step 10. */
|
|
193
|
-
--background:
|
|
194
|
-
--foreground:
|
|
264
|
+
--background: 210 20% 98%; /** House canvas. Light is gray-50 under white cards (two-surface layering, as Vercel #fafafa/#fff); dark is OKLCH L 0.16, inside the near-black band every reference measures (Linear L 0.14, Raycast #040506). */
|
|
265
|
+
--foreground: 225 7.7% 10.2%;
|
|
195
266
|
--card: 0 0% 100%;
|
|
196
|
-
--card-foreground:
|
|
267
|
+
--card-foreground: 225 7.7% 10.2%;
|
|
197
268
|
--popover: 0 0% 100%;
|
|
198
|
-
--popover-foreground:
|
|
199
|
-
--primary:
|
|
269
|
+
--popover-foreground: 225 7.7% 10.2%;
|
|
270
|
+
--primary: 225 7.7% 10.2%; /** House action fill = ink, not blue (owner decision 2026-09-24). Every measured reference ships a solid near-black primary (Vercel #171717, Figma #000) and keeps its one saturated hue for a single signal. Blue now lives on --ring (focus, selection) only. */
|
|
200
271
|
--primary-foreground: 0 0% 100%;
|
|
201
|
-
--secondary:
|
|
202
|
-
--secondary-foreground:
|
|
203
|
-
--muted:
|
|
204
|
-
--muted-foreground:
|
|
205
|
-
--accent:
|
|
206
|
-
--accent-foreground:
|
|
272
|
+
--secondary: 220 14.3% 95.9%;
|
|
273
|
+
--secondary-foreground: 225 7.7% 10.2%;
|
|
274
|
+
--muted: 220 14.3% 95.9%;
|
|
275
|
+
--muted-foreground: 220 2.6% 45.5%;
|
|
276
|
+
--accent: 220 14.3% 95.9%;
|
|
277
|
+
--accent-foreground: 225 7.7% 10.2%; /** Softer brand blue — desaturated to match --primary, avoids 100% saturation glare on focus/accent */
|
|
207
278
|
--destructive: 0 84% 45%;
|
|
208
279
|
--destructive-foreground: 0 0% 100%;
|
|
209
280
|
--destructive-strong: 0 84% 45%; /** Red as FOREGROUND. In light mode --destructive already passes (5.42:1 on white), so this equals it; the token exists so consumers reference one name across themes. In DARK, --destructive is 0 63% 38% = 2.15:1 on --card, unreadable as text — see dark.json. Mirrors --warning-strong. */
|
|
@@ -215,17 +286,17 @@
|
|
|
215
286
|
--warning-strong: 38 92% 30%; /** Amber as FOREGROUND on a light surface. --warning is a fill: at 38 92% 50% it is 2.04:1 against --neutral-2, so it is unreadable as text or as an icon stroke. This darkened step is 5.17:1, which sits between --success (4.92) and --destructive (5.19) so the three status colours read with the same weight. Use --warning for fills with --warning-foreground on top; use this for amber text and icons. Destructive and success need no equivalent — they already pass AA as foreground. */
|
|
216
287
|
--info: 228 85% 56%;
|
|
217
288
|
--info-foreground: 0 0% 100%;
|
|
218
|
-
--border:
|
|
219
|
-
--input:
|
|
220
|
-
--ring: 222
|
|
221
|
-
--sidebar: 210
|
|
222
|
-
--sidebar-foreground:
|
|
223
|
-
--sidebar-primary: 228 85% 56
|
|
289
|
+
--border: 225 8% 90.2%;
|
|
290
|
+
--input: 225 8% 90.2%;
|
|
291
|
+
--ring: 222.8 85% 55.7%; /** The House blue. Focus rings, selection and links — the one saturated hue on a product screen. #2e65ee light / #6b93f5 dark. */
|
|
292
|
+
--sidebar: 210 20% 98%;
|
|
293
|
+
--sidebar-foreground: 225 7.7% 10.2%;
|
|
294
|
+
--sidebar-primary: 225 7.7% 10.2%; /** Current-page accent in the sidebar (icon tint + edge). Same value as --primary: the sidebar carried the superseded 228 85% 56% (#2f56ee, C 0.232), which the action-blue measurement trimmed to C 0.215. */
|
|
224
295
|
--sidebar-primary-foreground: 0 0% 100%;
|
|
225
|
-
--sidebar-accent:
|
|
226
|
-
--sidebar-accent-foreground:
|
|
227
|
-
--sidebar-border:
|
|
228
|
-
--sidebar-ring:
|
|
296
|
+
--sidebar-accent: 220 14.3% 95.9%;
|
|
297
|
+
--sidebar-accent-foreground: 225 7.7% 10.2%;
|
|
298
|
+
--sidebar-border: 225 8% 90.2%;
|
|
299
|
+
--sidebar-ring: 222.8 85% 55.7%;
|
|
229
300
|
--chart-1: 228 100% 50%;
|
|
230
301
|
--chart-2: 168 91% 49%;
|
|
231
302
|
--chart-3: 263 70% 66%;
|
|
@@ -374,17 +445,17 @@
|
|
|
374
445
|
--nebutra-cyan-800: #057963;
|
|
375
446
|
--nebutra-cyan-900: #035143;
|
|
376
447
|
--nebutra-cyan-950: #012923;
|
|
377
|
-
--nebutra-neutral-50: #
|
|
378
|
-
--nebutra-neutral-100: #
|
|
379
|
-
--nebutra-neutral-200: #
|
|
380
|
-
--nebutra-neutral-300: #
|
|
381
|
-
--nebutra-neutral-400: #
|
|
382
|
-
--nebutra-neutral-500: #
|
|
383
|
-
--nebutra-neutral-600: #
|
|
384
|
-
--nebutra-neutral-700: #
|
|
385
|
-
--nebutra-neutral-800: #
|
|
386
|
-
--nebutra-neutral-900: #
|
|
387
|
-
--nebutra-neutral-950: #
|
|
448
|
+
--nebutra-neutral-50: #f9fafb;
|
|
449
|
+
--nebutra-neutral-100: #f3f4f6;
|
|
450
|
+
--nebutra-neutral-200: #e4e5e8;
|
|
451
|
+
--nebutra-neutral-300: #d2d4d8;
|
|
452
|
+
--nebutra-neutral-400: #9fa1a5;
|
|
453
|
+
--nebutra-neutral-500: #717377;
|
|
454
|
+
--nebutra-neutral-600: #515357;
|
|
455
|
+
--nebutra-neutral-700: #3f4044;
|
|
456
|
+
--nebutra-neutral-800: #26272a;
|
|
457
|
+
--nebutra-neutral-900: #18191c;
|
|
458
|
+
--nebutra-neutral-950: #0b0c0d;
|
|
388
459
|
--nebutra-gray-50: #fafafa;
|
|
389
460
|
--nebutra-gray-100: #f5f5f5;
|
|
390
461
|
--nebutra-gray-200: #e5e5e5;
|
|
@@ -423,22 +494,93 @@
|
|
|
423
494
|
--tracking-display: -0.04em; /** Hero H1 */
|
|
424
495
|
--tracking-heading: -0.03em; /** Section H2/H3 */
|
|
425
496
|
--tracking-tight: -0.015em; /** Body emphasis */
|
|
497
|
+
--tracking-label: 0.07em; /** Uppercase micro-labels. 0.07em is Vercel's measured eyebrow value (0.071em); open tracking keeps small caps legible. */
|
|
426
498
|
--leading-display: 1.05;
|
|
427
499
|
--leading-heading: 1.15;
|
|
500
|
+
--type-2xs-size: 0.6875rem;
|
|
501
|
+
--type-2xs-leading: 1.45;
|
|
502
|
+
--type-2xs-tracking: 0.01em;
|
|
503
|
+
--type-xs-size: 0.75rem;
|
|
504
|
+
--type-xs-leading: 1.4;
|
|
505
|
+
--type-xs-tracking: 0.005em;
|
|
506
|
+
--type-ui-size: 0.8125rem;
|
|
507
|
+
--type-ui-leading: 1.45;
|
|
508
|
+
--type-ui-tracking: 0em;
|
|
509
|
+
--type-sm-size: 0.875rem;
|
|
510
|
+
--type-sm-leading: 1.5;
|
|
511
|
+
--type-sm-tracking: 0em;
|
|
512
|
+
--type-base-size: 1rem;
|
|
513
|
+
--type-base-leading: 1.6;
|
|
514
|
+
--type-base-tracking: -0.005em;
|
|
515
|
+
--type-lg-size: 1.125rem;
|
|
516
|
+
--type-lg-leading: 1.55;
|
|
517
|
+
--type-lg-tracking: -0.01em;
|
|
518
|
+
--type-xl-size: 1.25rem;
|
|
519
|
+
--type-xl-leading: 1.45;
|
|
520
|
+
--type-xl-tracking: -0.012em;
|
|
521
|
+
--type-2xl-size: 1.5rem;
|
|
522
|
+
--type-2xl-leading: 1.33;
|
|
523
|
+
--type-2xl-tracking: -0.015em;
|
|
524
|
+
--type-3xl-size: 1.875rem;
|
|
525
|
+
--type-3xl-leading: 1.25;
|
|
526
|
+
--type-3xl-tracking: -0.02em;
|
|
527
|
+
--type-4xl-size: 2.25rem;
|
|
528
|
+
--type-4xl-leading: 1.15;
|
|
529
|
+
--type-4xl-tracking: -0.022em;
|
|
530
|
+
--type-5xl-size: 3rem;
|
|
531
|
+
--type-5xl-leading: 1.08;
|
|
532
|
+
--type-5xl-tracking: -0.028em;
|
|
533
|
+
--type-6xl-size: 3.75rem;
|
|
534
|
+
--type-6xl-leading: 1.04;
|
|
535
|
+
--type-6xl-tracking: -0.032em;
|
|
536
|
+
--type-7xl-size: 4.5rem;
|
|
537
|
+
--type-7xl-leading: 1;
|
|
538
|
+
--type-7xl-tracking: -0.035em;
|
|
539
|
+
--type-8xl-size: 6rem;
|
|
540
|
+
--type-8xl-leading: 1;
|
|
541
|
+
--type-8xl-tracking: -0.04em;
|
|
542
|
+
--type-9xl-size: 8rem;
|
|
543
|
+
--type-9xl-leading: 1;
|
|
544
|
+
--type-9xl-tracking: -0.045em;
|
|
545
|
+
--type-display-size: 1.25rem;
|
|
546
|
+
--type-display-leading: 1.45;
|
|
547
|
+
--type-display-tracking: -0.012em;
|
|
548
|
+
--type-body-size: 0.875rem;
|
|
549
|
+
--type-body-leading: 1.5;
|
|
550
|
+
--type-body-tracking: 0em;
|
|
551
|
+
--type-label-size: 0.75rem;
|
|
552
|
+
--type-label-leading: 1.4;
|
|
553
|
+
--type-label-tracking: 0.005em;
|
|
554
|
+
--type-meta-size: 0.6875rem;
|
|
555
|
+
--type-meta-leading: 1.45;
|
|
556
|
+
--type-meta-tracking: 0.01em;
|
|
557
|
+
--layer-raised: 10; /** Within a component: an element lifted over its siblings. */
|
|
558
|
+
--layer-sticky: 20; /** Sticky headers and table heads. */
|
|
559
|
+
--layer-floating: 30; /** Floating toolbars and canvas chrome anchored to content. */
|
|
560
|
+
--layer-nav: 40; /** App navigation and the shell's top bar. */
|
|
561
|
+
--layer-drawer: 60; /** Mobile navigation drawers and their toggles. */
|
|
562
|
+
--layer-banner: 90; /** Page-level banners: cookie consent, announcements. */
|
|
563
|
+
--layer-skip-link: 100; /** The skip link — above page chrome whenever it is focused. */
|
|
564
|
+
--layer-panel: 200; /** App-owned floating panels that are not overlays (locale switcher, search flyouts). */
|
|
565
|
+
--layer-backdrop: 1040; /** Overlay tier. Mirrors overlayZIndex in @nebutra/ui; a test keeps them equal. */
|
|
566
|
+
--layer-modal: 1050; /** Dialogs and sheets. */
|
|
567
|
+
--layer-popover: 1060; /** Popovers, menus, selects. */
|
|
568
|
+
--layer-tooltip: 1070; /** Tooltips. */
|
|
569
|
+
--layer-devtools: 9999; /** Developer and debug surfaces only — never product UI. */
|
|
428
570
|
--ring-hairline: inset 0 0 0 1px rgb(255 255 255 / 0.06); /** Hairline override — more visible on dark background */
|
|
429
571
|
--overlay-faint: rgb(
|
|
430
572
|
255 255 255 / 0.06
|
|
431
573
|
); /** Dark-mode faint overlay (6% white) — inverted from light */
|
|
432
574
|
--font-sans:
|
|
433
|
-
var(--font-geist-sans), "Geist", var(--font-
|
|
434
|
-
|
|
575
|
+
var(--font-geist-sans), "Geist", var(--font-misans, "MiSans"), "PingFang SC", "Microsoft YaHei",
|
|
576
|
+
-apple-system, BlinkMacSystemFont, system-ui, sans-serif;
|
|
435
577
|
--font-cn:
|
|
436
|
-
var(--font-geist-sans), "Geist", var(--font-
|
|
437
|
-
|
|
578
|
+
var(--font-geist-sans), "Geist", var(--font-misans, "MiSans"), "PingFang SC", "Microsoft YaHei",
|
|
579
|
+
sans-serif; /** CJK-locale stack — same order as sans, minus the Latin-only system faces */
|
|
438
580
|
--font-display:
|
|
439
|
-
var(--font-
|
|
581
|
+
var(--font-dm-sans), "DM Sans", var(--font-misans, "MiSans"), "PingFang SC", sans-serif;
|
|
440
582
|
--font-heading:
|
|
441
|
-
var(--font-
|
|
583
|
+
var(--font-dm-sans), "DM Sans", var(--font-misans, "MiSans"), "PingFang SC", sans-serif;
|
|
442
584
|
--font-mono:
|
|
443
585
|
var(--font-geist-mono), "Geist Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
|
|
444
586
|
--brand-primary: #5c7cfa; /** Dark-mode brand primary — the identity blue lifted to nebutra-blue-400 so it stays visible on dark surfaces. This is the identity alias, not the functional fill: the dark solid fill is --blue-9 (#396ae2, white label 4.85:1). The two are deliberately separate now that the VI hex is no longer pinned into ramp slot 9. */
|
|
@@ -481,18 +623,18 @@
|
|
|
481
623
|
--motion-duration-reveal: 300ms;
|
|
482
624
|
--motion-duration-cinematic: 500ms;
|
|
483
625
|
--focus-ring: 0 0 0 2px hsl(var(--ring) / 0.4); /** Single-layer translucent focus ring (2026 pattern). Legacy box-shadow consumers stay compatible; modern surfaces should prefer the global :focus-visible outline rule in static/base.css. */
|
|
484
|
-
--neutral-1: #
|
|
485
|
-
--neutral-2: #
|
|
486
|
-
--neutral-3: #
|
|
487
|
-
--neutral-4: #
|
|
488
|
-
--neutral-5: #
|
|
626
|
+
--neutral-1: #0b0c0d;
|
|
627
|
+
--neutral-2: #18191c;
|
|
628
|
+
--neutral-3: #26272a;
|
|
629
|
+
--neutral-4: #3f4044;
|
|
630
|
+
--neutral-5: #515357;
|
|
489
631
|
--neutral-6: #666666; /** subtle border — DERIVED: OKLab lerp step5 → step9 at t=0.25, chroma forced to 0. The achromatic result is deliberate and preserves the documented intent of color.nebutra-gray ('used where blue undertone clashes — primarily dark-mode borders, dividers, elevation hairlines'). What was broken was the LIGHTNESS: gray-900/800/700 are darker than the slate background tier they sit above, so the border read as a hole rather than a hairline. */
|
|
490
|
-
--neutral-7: #
|
|
632
|
+
--neutral-7: #797979; /** default border — DERIVED: OKLab lerp step5 → step9 at t=0.50, chroma 0. */
|
|
491
633
|
--neutral-8: #8d8d8d; /** hovered border — DERIVED: OKLab lerp step5 → step9 at t=0.75, chroma 0. */
|
|
492
|
-
--neutral-9: #
|
|
493
|
-
--neutral-10: #
|
|
494
|
-
--neutral-11: #
|
|
495
|
-
--neutral-12: #
|
|
634
|
+
--neutral-9: #9fa1a5;
|
|
635
|
+
--neutral-10: #d2d4d8;
|
|
636
|
+
--neutral-11: #e4e5e8;
|
|
637
|
+
--neutral-12: #f9fafb;
|
|
496
638
|
--blue-1: #030815; /** app tint — L* 13.59, C 0.031, hue 264. */
|
|
497
639
|
--blue-2: #060f25; /** subtle background — L* 17.43, C 0.048. */
|
|
498
640
|
--blue-3: #09183b; /** component background default — L* 22.04, C 0.071. */
|
|
@@ -519,20 +661,20 @@
|
|
|
519
661
|
--cyan-11: #90fbdb; /** secondary text — L* 91.46, C 0.110. 15.68:1 on step 1. */
|
|
520
662
|
--cyan-12: #bdfde8; /** primary text — L* 94.54, C 0.070. 16.95:1 on step 1. */
|
|
521
663
|
--cyan-contrast: #0d2b25; /** Label ink for the bright fill tier. Absolute near-black, identical in both modes. 10.35:1 on step 9, 11.34:1 on step 10. */
|
|
522
|
-
--background:
|
|
523
|
-
--foreground:
|
|
524
|
-
--card:
|
|
525
|
-
--card-foreground:
|
|
526
|
-
--popover:
|
|
527
|
-
--popover-foreground:
|
|
528
|
-
--primary:
|
|
529
|
-
--primary-foreground:
|
|
530
|
-
--secondary:
|
|
531
|
-
--secondary-foreground:
|
|
532
|
-
--muted:
|
|
533
|
-
--muted-foreground:
|
|
534
|
-
--accent:
|
|
535
|
-
--accent-foreground: 228
|
|
664
|
+
--background: 220 11.1% 5.3%; /** House canvas. Light is gray-50 under white cards (two-surface layering, as Vercel #fafafa/#fff); dark is OKLCH L 0.16, inside the near-black band every reference measures (Linear L 0.14, Raycast #040506). */
|
|
665
|
+
--foreground: 228 23.8% 95.9%;
|
|
666
|
+
--card: 220 7.3% 8%;
|
|
667
|
+
--card-foreground: 228 23.8% 95.9%;
|
|
668
|
+
--popover: 225 7.7% 10.2%;
|
|
669
|
+
--popover-foreground: 228 23.8% 95.9%;
|
|
670
|
+
--primary: 228 23.8% 95.9%; /** House action fill = ink, not blue (owner decision 2026-09-24). Every measured reference ships a solid near-black primary (Vercel #171717, Figma #000) and keeps its one saturated hue for a single signal. Blue now lives on --ring (focus, selection) only. */
|
|
671
|
+
--primary-foreground: 220 11.1% 5.3%; /** White, matching light mode and matching --blue-contrast. It was near-black (222 14% 9%) when --primary was a LIGHT fill at L* 68.3, where dark ink read 6.20:1. Once --primary became a deep fill at L* 55.9 the pairing inverted and measured 3.74:1, below AA — the fill moved and the ink did not. The deep-fill tier takes white in both modes; --blue-contrast says the same thing, and they must agree because --primary and --blue-9 are now the same value. */
|
|
672
|
+
--secondary: 225 6.2% 12.5%;
|
|
673
|
+
--secondary-foreground: 228 23.8% 95.9%;
|
|
674
|
+
--muted: 225 6.2% 12.5%;
|
|
675
|
+
--muted-foreground: 228 2.6% 62.5%;
|
|
676
|
+
--accent: 225 6.2% 12.5%;
|
|
677
|
+
--accent-foreground: 228 23.8% 95.9%;
|
|
536
678
|
--destructive: 0 63% 38%;
|
|
537
679
|
--destructive-foreground: 210 18% 96%;
|
|
538
680
|
--destructive-strong: 0 80% 66%; /** Red as FOREGROUND on a dark surface. --destructive (0 63% 38%) is 2.15:1 on --card here — a fill only. Lightened to 5.18:1 on --card / 5.61:1 on --neutral-1, which sits alongside the light-mode 5.42:1 so red reads with the same weight in both themes. Use --destructive for fills with --destructive-foreground on top; use this for red text and icons. */
|
|
@@ -544,17 +686,17 @@
|
|
|
544
686
|
--warning-strong: 38 80% 52%; /** Amber as foreground on a dark surface. Unlike light mode this needs no adjustment — 38 80% 52% is already 7.98:1 against --neutral-1 — so it deliberately equals --warning. The token exists in both themes so consumers can reference one name. */
|
|
545
687
|
--info: 228 95% 72%;
|
|
546
688
|
--info-foreground: 222 14% 9%;
|
|
547
|
-
--border: 220
|
|
548
|
-
--input: 220
|
|
549
|
-
--ring:
|
|
550
|
-
--sidebar:
|
|
551
|
-
--sidebar-foreground:
|
|
552
|
-
--sidebar-primary: 228 95% 72
|
|
553
|
-
--sidebar-primary-foreground:
|
|
554
|
-
--sidebar-accent:
|
|
555
|
-
--sidebar-accent-foreground: 228
|
|
556
|
-
--sidebar-border:
|
|
557
|
-
--sidebar-ring:
|
|
689
|
+
--border: 220 3.6% 16.3%;
|
|
690
|
+
--input: 220 3.6% 16.3%;
|
|
691
|
+
--ring: 222.6 87.3% 69%; /** The House blue. Focus rings, selection and links — the one saturated hue on a product screen. #2e65ee light / #6b93f5 dark. */
|
|
692
|
+
--sidebar: 220 11.1% 5.3%;
|
|
693
|
+
--sidebar-foreground: 228 23.8% 95.9%;
|
|
694
|
+
--sidebar-primary: 228 23.8% 95.9%; /** Current-page accent in the sidebar. = blue-11 (#89aaee, L* 74.0, C 0.106), the ramp's measured secondary-text tier on dark (8.62:1 on step 1). Was 228 95% 72% — 95% chroma sat outside every measured band and matched no ramp step. */
|
|
695
|
+
--sidebar-primary-foreground: 220 11.1% 5.3%;
|
|
696
|
+
--sidebar-accent: 225 6.2% 12.5%;
|
|
697
|
+
--sidebar-accent-foreground: 228 23.8% 95.9%;
|
|
698
|
+
--sidebar-border: 225 6.2% 12.5%;
|
|
699
|
+
--sidebar-ring: 222.6 87.3% 69%;
|
|
558
700
|
--chart-1: 228 95% 67%;
|
|
559
701
|
--chart-2: 168 96% 54%;
|
|
560
702
|
--chart-3: 228 100% 82%;
|
|
@@ -715,6 +857,12 @@
|
|
|
715
857
|
--color-success-foreground: hsl(var(--success-foreground));
|
|
716
858
|
--color-warning: hsl(var(--warning));
|
|
717
859
|
--color-warning-foreground: hsl(var(--warning-foreground));
|
|
860
|
+
/* Status colours as INK (text, icon fill/stroke). --destructive / --warning /
|
|
861
|
+
--success are fills: amber is 2.0:1 as text in light, red 2.5:1 in dark.
|
|
862
|
+
text-destructive-strong etc. read at ~5:1 in both themes. */
|
|
863
|
+
--color-destructive-strong: hsl(var(--destructive-strong));
|
|
864
|
+
--color-warning-strong: hsl(var(--warning-strong));
|
|
865
|
+
--color-success-strong: hsl(var(--success-strong));
|
|
718
866
|
--color-info: hsl(var(--info));
|
|
719
867
|
--color-info-foreground: hsl(var(--info-foreground));
|
|
720
868
|
--color-border: hsl(var(--border));
|
|
@@ -889,6 +1037,66 @@
|
|
|
889
1037
|
--ease-in-out: var(--motion-ease-in-out);
|
|
890
1038
|
--ease-spring: var(--motion-ease-spring);
|
|
891
1039
|
|
|
1040
|
+
/* Type scale — see core.json:type. Indirect so a Brand Package can retune size,
|
|
1041
|
+
leading and tracking; each text-* utility sets all three. */
|
|
1042
|
+
--text-2xs: var(--type-2xs-size);
|
|
1043
|
+
--text-2xs--line-height: var(--type-2xs-leading);
|
|
1044
|
+
--text-2xs--letter-spacing: var(--type-2xs-tracking);
|
|
1045
|
+
--text-xs: var(--type-xs-size);
|
|
1046
|
+
--text-xs--line-height: var(--type-xs-leading);
|
|
1047
|
+
--text-xs--letter-spacing: var(--type-xs-tracking);
|
|
1048
|
+
--text-ui: var(--type-ui-size);
|
|
1049
|
+
--text-ui--line-height: var(--type-ui-leading);
|
|
1050
|
+
--text-ui--letter-spacing: var(--type-ui-tracking);
|
|
1051
|
+
--text-sm: var(--type-sm-size);
|
|
1052
|
+
--text-sm--line-height: var(--type-sm-leading);
|
|
1053
|
+
--text-sm--letter-spacing: var(--type-sm-tracking);
|
|
1054
|
+
--text-base: var(--type-base-size);
|
|
1055
|
+
--text-base--line-height: var(--type-base-leading);
|
|
1056
|
+
--text-base--letter-spacing: var(--type-base-tracking);
|
|
1057
|
+
--text-lg: var(--type-lg-size);
|
|
1058
|
+
--text-lg--line-height: var(--type-lg-leading);
|
|
1059
|
+
--text-lg--letter-spacing: var(--type-lg-tracking);
|
|
1060
|
+
--text-xl: var(--type-xl-size);
|
|
1061
|
+
--text-xl--line-height: var(--type-xl-leading);
|
|
1062
|
+
--text-xl--letter-spacing: var(--type-xl-tracking);
|
|
1063
|
+
--text-2xl: var(--type-2xl-size);
|
|
1064
|
+
--text-2xl--line-height: var(--type-2xl-leading);
|
|
1065
|
+
--text-2xl--letter-spacing: var(--type-2xl-tracking);
|
|
1066
|
+
--text-3xl: var(--type-3xl-size);
|
|
1067
|
+
--text-3xl--line-height: var(--type-3xl-leading);
|
|
1068
|
+
--text-3xl--letter-spacing: var(--type-3xl-tracking);
|
|
1069
|
+
--text-4xl: var(--type-4xl-size);
|
|
1070
|
+
--text-4xl--line-height: var(--type-4xl-leading);
|
|
1071
|
+
--text-4xl--letter-spacing: var(--type-4xl-tracking);
|
|
1072
|
+
--text-5xl: var(--type-5xl-size);
|
|
1073
|
+
--text-5xl--line-height: var(--type-5xl-leading);
|
|
1074
|
+
--text-5xl--letter-spacing: var(--type-5xl-tracking);
|
|
1075
|
+
--text-6xl: var(--type-6xl-size);
|
|
1076
|
+
--text-6xl--line-height: var(--type-6xl-leading);
|
|
1077
|
+
--text-6xl--letter-spacing: var(--type-6xl-tracking);
|
|
1078
|
+
--text-7xl: var(--type-7xl-size);
|
|
1079
|
+
--text-7xl--line-height: var(--type-7xl-leading);
|
|
1080
|
+
--text-7xl--letter-spacing: var(--type-7xl-tracking);
|
|
1081
|
+
--text-8xl: var(--type-8xl-size);
|
|
1082
|
+
--text-8xl--line-height: var(--type-8xl-leading);
|
|
1083
|
+
--text-8xl--letter-spacing: var(--type-8xl-tracking);
|
|
1084
|
+
--text-9xl: var(--type-9xl-size);
|
|
1085
|
+
--text-9xl--line-height: var(--type-9xl-leading);
|
|
1086
|
+
--text-9xl--letter-spacing: var(--type-9xl-tracking);
|
|
1087
|
+
--text-display: var(--type-display-size);
|
|
1088
|
+
--text-display--line-height: var(--type-display-leading);
|
|
1089
|
+
--text-display--letter-spacing: var(--type-display-tracking);
|
|
1090
|
+
--text-body: var(--type-body-size);
|
|
1091
|
+
--text-body--line-height: var(--type-body-leading);
|
|
1092
|
+
--text-body--letter-spacing: var(--type-body-tracking);
|
|
1093
|
+
--text-label: var(--type-label-size);
|
|
1094
|
+
--text-label--line-height: var(--type-label-leading);
|
|
1095
|
+
--text-label--letter-spacing: var(--type-label-tracking);
|
|
1096
|
+
--text-meta: var(--type-meta-size);
|
|
1097
|
+
--text-meta--line-height: var(--type-meta-leading);
|
|
1098
|
+
--text-meta--letter-spacing: var(--type-meta-tracking);
|
|
1099
|
+
|
|
892
1100
|
/* Motion — Durations (four-rail; see core.json:duration). Names denote intent, not relative speed. */
|
|
893
1101
|
--duration-micro: var(--motion-duration-micro);
|
|
894
1102
|
--duration-flow: var(--motion-duration-flow);
|
|
@@ -920,20 +1128,21 @@
|
|
|
920
1128
|
--spacing-{step} alias. --spacing itself (0.25rem arithmetic base) stays
|
|
921
1129
|
untouched. See static/base.css. */
|
|
922
1130
|
|
|
923
|
-
/* Font family — Geist keeps Latin + numerals,
|
|
924
|
-
CJK, system CJK faces behind
|
|
925
|
-
|
|
926
|
-
the two in sync
|
|
1131
|
+
/* Font family — Geist keeps Latin + numerals for body/UI, DM Sans sets Latin
|
|
1132
|
+
display and headings, self-hosted MiSans takes CJK, system CJK faces behind
|
|
1133
|
+
it. Order is the design decision; see the fontFamily $description in
|
|
1134
|
+
tokens/core.json. Mirror of those tokens — keep the two in sync
|
|
1135
|
+
(verify:parity compares them). */
|
|
927
1136
|
--font-sans:
|
|
928
|
-
var(--font-geist-sans), "Geist", var(--font-
|
|
929
|
-
|
|
1137
|
+
var(--font-geist-sans), "Geist", var(--font-misans, "MiSans"), "PingFang SC", "Microsoft YaHei",
|
|
1138
|
+
-apple-system, BlinkMacSystemFont, system-ui, sans-serif;
|
|
930
1139
|
--font-cn:
|
|
931
|
-
var(--font-geist-sans), "Geist", var(--font-
|
|
932
|
-
|
|
1140
|
+
var(--font-geist-sans), "Geist", var(--font-misans, "MiSans"), "PingFang SC", "Microsoft YaHei",
|
|
1141
|
+
sans-serif;
|
|
933
1142
|
--font-display:
|
|
934
|
-
var(--font-
|
|
1143
|
+
var(--font-dm-sans), "DM Sans", var(--font-misans, "MiSans"), "PingFang SC", sans-serif;
|
|
935
1144
|
--font-heading:
|
|
936
|
-
var(--font-
|
|
1145
|
+
var(--font-dm-sans), "DM Sans", var(--font-misans, "MiSans"), "PingFang SC", sans-serif;
|
|
937
1146
|
--font-mono:
|
|
938
1147
|
var(--font-geist-mono), "Geist Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
|
|
939
1148
|
}
|
|
@@ -1079,6 +1288,20 @@
|
|
|
1079
1288
|
border-r-transparent can override it. */
|
|
1080
1289
|
border-color: hsl(var(--border));
|
|
1081
1290
|
}
|
|
1291
|
+
|
|
1292
|
+
/* Headings take the display face. Layered (base) so any utility — font-*,
|
|
1293
|
+
font-semibold, a text-heading-* recipe — still wins; zero-specificity
|
|
1294
|
+
:where() so a component's own heading styles are never fought. The face
|
|
1295
|
+
and weight are variables, so a Brand Package retunes both. */
|
|
1296
|
+
:where(h1, h2, h3, h4, h5, h6) {
|
|
1297
|
+
font-family: var(--font-heading);
|
|
1298
|
+
font-weight: var(--font-weight-heading, 500);
|
|
1299
|
+
line-height: 1.25;
|
|
1300
|
+
}
|
|
1301
|
+
/* This is the ONLY heading rule. @nebutra/ui fonts.css and the web and
|
|
1302
|
+
landing globals each re-declared one (font-sans at 600), and whichever
|
|
1303
|
+
loaded last won: landing's h1 shipped in Geist 600 after the 2026-09-25
|
|
1304
|
+
decision set headings to DM Sans 500. */
|
|
1082
1305
|
}
|
|
1083
1306
|
|
|
1084
1307
|
body {
|
|
@@ -1090,8 +1313,15 @@ body {
|
|
|
1090
1313
|
"calt" 1;
|
|
1091
1314
|
}
|
|
1092
1315
|
|
|
1093
|
-
|
|
1094
|
-
|
|
1316
|
+
/* Smooth scrolling is an enhancement, never the default the whole document
|
|
1317
|
+
* inherits: it hijacks every programmatic scroll (route changes, focus jumps,
|
|
1318
|
+
* scrollIntoView) and turns them into long animated sweeps. The preference
|
|
1319
|
+
* gate makes the intent explicit; the reduced-motion block below forces
|
|
1320
|
+
* `auto` for users who ask for less motion. */
|
|
1321
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
1322
|
+
html {
|
|
1323
|
+
scroll-behavior: smooth;
|
|
1324
|
+
}
|
|
1095
1325
|
}
|
|
1096
1326
|
|
|
1097
1327
|
/*
|
|
@@ -1113,7 +1343,7 @@ html {
|
|
|
1113
1343
|
:focus-visible:not(
|
|
1114
1344
|
:where(input, textarea, select, [cmdk-input], [role="textbox"], [contenteditable="true"])
|
|
1115
1345
|
) {
|
|
1116
|
-
outline: 2px solid hsl(var(--ring)
|
|
1346
|
+
outline: 2px solid hsl(var(--ring));
|
|
1117
1347
|
outline-offset: 2px;
|
|
1118
1348
|
border-radius: inherit;
|
|
1119
1349
|
}
|
|
@@ -1133,24 +1363,6 @@ html {
|
|
|
1133
1363
|
}
|
|
1134
1364
|
}
|
|
1135
1365
|
|
|
1136
|
-
@keyframes accordion-down {
|
|
1137
|
-
from {
|
|
1138
|
-
height: 0;
|
|
1139
|
-
}
|
|
1140
|
-
to {
|
|
1141
|
-
height: var(--radix-accordion-content-height);
|
|
1142
|
-
}
|
|
1143
|
-
}
|
|
1144
|
-
|
|
1145
|
-
@keyframes accordion-up {
|
|
1146
|
-
from {
|
|
1147
|
-
height: var(--radix-accordion-content-height);
|
|
1148
|
-
}
|
|
1149
|
-
to {
|
|
1150
|
-
height: 0;
|
|
1151
|
-
}
|
|
1152
|
-
}
|
|
1153
|
-
|
|
1154
1366
|
@keyframes fade-in {
|
|
1155
1367
|
from {
|
|
1156
1368
|
opacity: 0;
|
|
@@ -1394,6 +1606,34 @@ html {
|
|
|
1394
1606
|
font-weight: 500;
|
|
1395
1607
|
}
|
|
1396
1608
|
|
|
1609
|
+
/* Tracking utilities over the tracking tokens — the scale itself is
|
|
1610
|
+
* Tailwind's, so per-size letter-spacing has to be applied where a heading
|
|
1611
|
+
* is rendered. Exposing the token as a utility keeps that application in
|
|
1612
|
+
* one vocabulary instead of every surface re-deriving an em value. */
|
|
1613
|
+
@utility tracking-display {
|
|
1614
|
+
letter-spacing: var(--tracking-display);
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
@utility tracking-heading {
|
|
1618
|
+
letter-spacing: var(--tracking-heading);
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1621
|
+
@utility tracking-label {
|
|
1622
|
+
letter-spacing: var(--tracking-label);
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
@utility tracking-tight-body {
|
|
1626
|
+
letter-spacing: var(--tracking-tight);
|
|
1627
|
+
}
|
|
1628
|
+
|
|
1629
|
+
@utility leading-display {
|
|
1630
|
+
line-height: var(--leading-display);
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
@utility leading-heading {
|
|
1634
|
+
line-height: var(--leading-heading);
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1397
1637
|
@utility text-label-20-strong {
|
|
1398
1638
|
font-family: var(--font-sans);
|
|
1399
1639
|
font-size: 1.25rem;
|
|
@@ -1718,18 +1958,29 @@ html {
|
|
|
1718
1958
|
|
|
1719
1959
|
/*
|
|
1720
1960
|
* flex-col + items-center:
|
|
1721
|
-
* 1) Direct children (incl. AnimateIn wrappers) get
|
|
1722
|
-
*
|
|
1723
|
-
* to min-content.
|
|
1961
|
+
* 1) Direct children (incl. AnimateIn wrappers) get min-width 0 so they can
|
|
1962
|
+
* wrap instead of forcing the column to min-content.
|
|
1724
1963
|
* 2) Nested prose (p/h*) under those columns takes width:100% so Chinese
|
|
1725
1964
|
* copy does not collapse to a 1-glyph strip. We deliberately do NOT set
|
|
1726
1965
|
* max-width here — leave Tailwind max-w-* / max-w-[…] in control.
|
|
1966
|
+
*
|
|
1967
|
+
* (1) used to also set `max-width: 100%`, which took that control away from
|
|
1968
|
+
* every utility it was written to defer to. `:is(html:lang(zh)) :is(.flex
|
|
1969
|
+
* .flex-col.items-center) > *` scores three classes; `.max-w-[20rem]` scores
|
|
1970
|
+
* one, so the cap lost — on CJK locales only. The footer newsletter field was
|
|
1971
|
+
* capped at 20rem in the markup and rendered 670px wide on /zh-Hans while the
|
|
1972
|
+
* English page was correct, which is the shape this class of bug always takes:
|
|
1973
|
+
* a global that only fires under :lang().
|
|
1974
|
+
*
|
|
1975
|
+
* min-width: 0 is what actually prevents the one-glyph strip. max-width: 100%
|
|
1976
|
+
* was doing nothing for it — a flex column child cannot exceed the line box
|
|
1977
|
+
* unless it is given an explicit larger width, and if it is, that is a
|
|
1978
|
+
* deliberate local decision this file should not silently overrule.
|
|
1727
1979
|
*/
|
|
1728
1980
|
:is(html:lang(zh), html:lang(ja), html:lang(ko))
|
|
1729
1981
|
:is(.flex.flex-col.items-center, .inline-flex.flex-col.items-center)
|
|
1730
1982
|
> * {
|
|
1731
1983
|
box-sizing: border-box;
|
|
1732
|
-
max-width: 100%;
|
|
1733
1984
|
min-width: 0;
|
|
1734
1985
|
}
|
|
1735
1986
|
|
|
@@ -1816,16 +2067,21 @@ html {
|
|
|
1816
2067
|
}
|
|
1817
2068
|
|
|
1818
2069
|
/* ─── Reduced Motion ─────────────────────────────────────── */
|
|
1819
|
-
/*
|
|
1820
|
-
*
|
|
1821
|
-
*
|
|
2070
|
+
/* Reduce, don't remove (WCAG 2.3.3, Apple HIG): movement and layout
|
|
2071
|
+
* animation stop, while opacity/colour transitions stay short so a state
|
|
2072
|
+
* change still reads as a change instead of an instant swap. Restricting
|
|
2073
|
+
* `transition-property` is what kills transform/height transitions without
|
|
2074
|
+
* touching the feedback that aids comprehension. Spinners and pulses are
|
|
2075
|
+
* functional progress indicators and keep their motion. */
|
|
1822
2076
|
@media (prefers-reduced-motion: reduce) {
|
|
1823
2077
|
*:not(.animate-spin):not(.animate-pulse):not(.animate-ping),
|
|
1824
2078
|
*:not(.animate-spin):not(.animate-pulse):not(.animate-ping)::before,
|
|
1825
2079
|
*:not(.animate-spin):not(.animate-pulse):not(.animate-ping)::after {
|
|
1826
2080
|
animation-duration: 0.01ms;
|
|
1827
2081
|
animation-iteration-count: 1;
|
|
1828
|
-
transition-
|
|
2082
|
+
transition-property:
|
|
2083
|
+
opacity, color, background-color, border-color, outline-color, fill, stroke, box-shadow;
|
|
2084
|
+
transition-duration: 120ms;
|
|
1829
2085
|
scroll-behavior: auto;
|
|
1830
2086
|
}
|
|
1831
2087
|
}
|