@nebutra/tokens 0.1.2 → 2.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/brands/README.md +66 -0
- package/brands/cosmos/DESIGN.md +356 -0
- package/brands/cosmos/brand.json +209 -0
- package/brands/cosmos/refero-tokens.json +312 -0
- package/brands/gsap/brand.json +18 -91
- package/brands/linear/DESIGN.md +478 -0
- package/brands/linear/brand.json +20 -76
- package/brands/notion/brand.json +20 -90
- package/brands/raycast/brand.json +19 -81
- package/brands/stripe/brand.json +17 -88
- package/brands/vanta/brand.json +17 -101
- package/brands/vercel/brand.json +17 -68
- package/dist/brand-package/index.d.ts +123 -0
- package/dist/brand-package/index.js +2316 -0
- package/dist/brand-package/index.js.map +1 -0
- package/dist/brand-package/use-brand.d.ts +2 -0
- package/dist/brand-package/use-brand.js +963 -0
- package/dist/brand-package/use-brand.js.map +1 -0
- package/dist/index.d.ts +81 -0
- package/dist/index.js +2581 -0
- package/dist/index.js.map +1 -0
- package/dist/use-brand-ClmvK_lC.d.ts +387 -0
- package/package.json +41 -10
- package/recipe.css +330 -1
- package/skins/README.md +2 -4
- package/skins/cosmos.css +239 -0
- package/skins/gsap.css +62 -138
- package/skins/linear.css +85 -132
- package/skins/notion.css +62 -141
- package/skins/raycast.css +68 -137
- package/skins/stripe.css +60 -143
- package/skins/vanta.css +60 -151
- package/skins/vercel.css +83 -128
- package/styles.css +477 -115
- package/.turbo/turbo-build.log +0 -8
- package/.turbo/turbo-typecheck.log +0 -4
- package/AGENTS.md +0 -45
- package/DESIGN.md +0 -357
- package/scripts/compile-brand-run.ts +0 -79
- package/scripts/compile-brand.mjs +0 -25
- package/scripts/emit-skins-run.ts +0 -62
- package/scripts/emit-skins.mjs +0 -31
- package/scripts/sync-styles.mjs +0 -29
- package/src/brand-package/__tests__/compile-refero.test.ts +0 -427
- package/src/brand-package/__tests__/emit-css.test.ts +0 -130
- package/src/brand-package/apply-brand.ts +0 -92
- package/src/brand-package/compile-helpers.ts +0 -170
- package/src/brand-package/compile-refero.ts +0 -69
- package/src/brand-package/emit-css.ts +0 -468
- package/src/brand-package/hex-to-hsl.ts +0 -100
- package/src/brand-package/index.ts +0 -71
- package/src/brand-package/infer-recipe.ts +0 -198
- package/src/brand-package/normalize.ts +0 -295
- package/src/brand-package/presets/context.ts +0 -17
- package/src/brand-package/presets/generic.ts +0 -214
- package/src/brand-package/presets/gsap.ts +0 -146
- package/src/brand-package/presets/index.ts +0 -31
- package/src/brand-package/presets/linear.ts +0 -183
- package/src/brand-package/presets/notion.ts +0 -208
- package/src/brand-package/presets/raycast.ts +0 -138
- package/src/brand-package/presets/recipe.ts +0 -61
- package/src/brand-package/presets/stripe.ts +0 -207
- package/src/brand-package/presets/vanta.ts +0 -220
- package/src/brand-package/presets/vercel.ts +0 -187
- package/src/brand-package/types.ts +0 -285
- package/src/brand-package/use-brand.ts +0 -207
- package/src/brand-package/validate.ts +0 -108
- package/src/index.ts +0 -67
- package/src/theme-provider.tsx +0 -246
- package/tsconfig.json +0 -11
- package/turbo.json +0 -15
package/recipe.css
CHANGED
|
@@ -11,6 +11,14 @@
|
|
|
11
11
|
* Tailwind utilities: bg-brand-mark / text-brand-mark (see @theme below).
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
+
@custom-variant hover {
|
|
15
|
+
@media (hover: hover) and (pointer: fine) {
|
|
16
|
+
&:hover {
|
|
17
|
+
@slot;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
14
22
|
:root {
|
|
15
23
|
/* ── Color roles (overridden by brand skins) ──────────────────── */
|
|
16
24
|
--role-action: var(--primary);
|
|
@@ -23,7 +31,8 @@
|
|
|
23
31
|
--btn-default-fg: hsl(var(--primary-foreground));
|
|
24
32
|
--btn-default-border: transparent;
|
|
25
33
|
--btn-default-border-width: 0px;
|
|
26
|
-
|
|
34
|
+
/* An image, never a colour — see the @property registration below. */
|
|
35
|
+
--btn-default-stroke-gradient: linear-gradient(transparent, transparent);
|
|
27
36
|
--btn-default-hover-bg: color-mix(in srgb, hsl(var(--primary)) 90%, transparent);
|
|
28
37
|
--btn-default-radius: var(--radius-button, var(--radius-md, 0.375rem));
|
|
29
38
|
--btn-default-shadow: 0 0 #0000;
|
|
@@ -42,6 +51,11 @@
|
|
|
42
51
|
--control-height-sm: 2rem; /* 32 */
|
|
43
52
|
--control-height-md: 2.5rem; /* 40 */
|
|
44
53
|
--control-height-lg: 3rem; /* 48 */
|
|
54
|
+
/* Icon-only triggers — orthogonal to the text-button ladder above.
|
|
55
|
+
apps use 28/32/36 rounded-md squares; circle uses the same boxes. */
|
|
56
|
+
--control-height-icon-sm: 1.75rem; /* 28 */
|
|
57
|
+
--control-height-icon-md: 2rem; /* 32 */
|
|
58
|
+
--control-height-icon-lg: 2.25rem; /* 36 */
|
|
45
59
|
--control-font-size-tiny: 0.6875rem; /* 11 */
|
|
46
60
|
--control-font-size-sm: 0.75rem; /* 12 */
|
|
47
61
|
--control-font-size-md: 0.875rem; /* 14 */
|
|
@@ -62,6 +76,321 @@
|
|
|
62
76
|
--badge-default-hover-bg: color-mix(in srgb, hsl(var(--brand-mark)) 80%, transparent);
|
|
63
77
|
}
|
|
64
78
|
|
|
79
|
+
/**
|
|
80
|
+
* The stroke slot is consumed as a background-image layer, so its value has to
|
|
81
|
+
* be an <image>. A colour there is not merely ignored: background-image becomes
|
|
82
|
+
* invalid as a whole and the browser drops every layer, including the solid
|
|
83
|
+
* brand fill in front of it. The button then renders with no background at all,
|
|
84
|
+
* while `color` — a separate declaration — keeps painting white text. That is
|
|
85
|
+
* what shipped: every default Button outside the gsap skin was white-on-white,
|
|
86
|
+
* because the slot held `transparent`, which is a colour.
|
|
87
|
+
*
|
|
88
|
+
* Registering the property makes that unrepresentable rather than merely
|
|
89
|
+
* discouraged. A colour written here now fails to parse against `<image>`, so
|
|
90
|
+
* the declaration is rejected and the slot keeps this initial value — the fill
|
|
91
|
+
* survives. Skins are generated, and a generator is exactly the place where one
|
|
92
|
+
* wrong branch reaches every brand at once.
|
|
93
|
+
*
|
|
94
|
+
* The var() fallbacks at the use sites stay as the unregistered path, so the
|
|
95
|
+
* recipe is still correct where @property is unsupported.
|
|
96
|
+
*/
|
|
97
|
+
@property --btn-default-stroke-gradient {
|
|
98
|
+
syntax: "<image>";
|
|
99
|
+
inherits: true;
|
|
100
|
+
initial-value: linear-gradient(transparent, transparent);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* ── Type contracts for every other recipe slot ───────────────────────────────
|
|
105
|
+
*
|
|
106
|
+
* Same reasoning, generalised. Each slot below is read from a typed CSS position
|
|
107
|
+
* (a colour, a length, a font weight), so a wrong-typed value written by a skin
|
|
108
|
+
* does not fail locally — it makes the whole consuming declaration invalid at
|
|
109
|
+
* computed-value time and the browser silently drops it. Registering the slot
|
|
110
|
+
* moves the failure to the slot itself: the bad value is rejected, the property
|
|
111
|
+
* keeps its initial-value, and the declaration that reads it still renders.
|
|
112
|
+
*
|
|
113
|
+
* Rules observed here:
|
|
114
|
+
* • `inherits: true` on every slot. Custom properties inherit by default, and
|
|
115
|
+
* every skin sets these on `:root` / `[data-theme]` for descendants to read.
|
|
116
|
+
* `inherits: false` would hand every non-root element the initial-value.
|
|
117
|
+
* • `initial-value` is computationally independent: absolute colours and `px`
|
|
118
|
+
* only. No `var()`, no `em`/`rem`, no `currentcolor`. The declared values in
|
|
119
|
+
* `:root` above are free to keep using `var()` and `rem` — the restriction
|
|
120
|
+
* applies to the initial-value alone. The px initials are the rem defaults
|
|
121
|
+
* resolved at a 16px root (0.375rem → 6px) so the fallback matches the
|
|
122
|
+
* factory ladder rather than inventing a new one.
|
|
123
|
+
* • Registering a `<length>` slot absolutises `rem` at computed-value time.
|
|
124
|
+
* Every skin writes `rem` or `px`, so this is a no-op today. A skin that
|
|
125
|
+
* wants element-relative sizing must not use `em` in these slots: it would
|
|
126
|
+
* resolve against the element's own font-size before the slot is read.
|
|
127
|
+
*/
|
|
128
|
+
|
|
129
|
+
/* ── Colour slots ─────────────────────────────────────────────────────────────
|
|
130
|
+
* Read inside `linear-gradient()` (button) and `background-color` (badge).
|
|
131
|
+
* Initial-values are the light-theme action blue (222.8 85% 55.7%) and its
|
|
132
|
+
* white foreground, i.e. the factory default rendered without a skin.
|
|
133
|
+
*/
|
|
134
|
+
@property --btn-default-bg {
|
|
135
|
+
syntax: "<color>";
|
|
136
|
+
inherits: true;
|
|
137
|
+
initial-value: hsl(222.8 85% 55.7%);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
@property --btn-default-fg {
|
|
141
|
+
syntax: "<color>";
|
|
142
|
+
inherits: true;
|
|
143
|
+
initial-value: #ffffff;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
@property --btn-default-border {
|
|
147
|
+
syntax: "<color>";
|
|
148
|
+
inherits: true;
|
|
149
|
+
initial-value: transparent;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
@property --btn-default-hover-bg {
|
|
153
|
+
syntax: "<color>";
|
|
154
|
+
inherits: true;
|
|
155
|
+
initial-value: hsl(222.8 85% 55.7%);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
@property --badge-default-bg {
|
|
159
|
+
syntax: "<color>";
|
|
160
|
+
inherits: true;
|
|
161
|
+
initial-value: hsl(222.8 85% 55.7%);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
@property --badge-default-fg {
|
|
165
|
+
syntax: "<color>";
|
|
166
|
+
inherits: true;
|
|
167
|
+
initial-value: #ffffff;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
@property --badge-default-border {
|
|
171
|
+
syntax: "<color>";
|
|
172
|
+
inherits: true;
|
|
173
|
+
initial-value: transparent;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
@property --badge-default-hover-bg {
|
|
177
|
+
syntax: "<color>";
|
|
178
|
+
inherits: true;
|
|
179
|
+
initial-value: hsl(222.8 85% 55.7%);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/* ── Length slots ─────────────────────────────────────────────────────────────
|
|
183
|
+
* `border-width` and the control ladder are plain lengths. Radii and padding go
|
|
184
|
+
* into `border-radius` / `padding`, which both accept percentages, so those get
|
|
185
|
+
* `<length-percentage>` — a skin expressing a pill as `50%` stays legal.
|
|
186
|
+
*/
|
|
187
|
+
@property --btn-default-border-width {
|
|
188
|
+
syntax: "<length>";
|
|
189
|
+
inherits: true;
|
|
190
|
+
initial-value: 0px;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
@property --btn-default-radius {
|
|
194
|
+
syntax: "<length-percentage>";
|
|
195
|
+
inherits: true;
|
|
196
|
+
initial-value: 6px;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
@property --btn-default-padding-y {
|
|
200
|
+
syntax: "<length-percentage>";
|
|
201
|
+
inherits: true;
|
|
202
|
+
initial-value: 8px;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
@property --btn-default-padding-x {
|
|
206
|
+
syntax: "<length-percentage>";
|
|
207
|
+
inherits: true;
|
|
208
|
+
initial-value: 16px;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
@property --badge-default-radius {
|
|
212
|
+
syntax: "<length-percentage>";
|
|
213
|
+
inherits: true;
|
|
214
|
+
initial-value: 9999px;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
@property --radius-button {
|
|
218
|
+
syntax: "<length-percentage>";
|
|
219
|
+
inherits: true;
|
|
220
|
+
initial-value: 6px;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
@property --radius-card {
|
|
224
|
+
syntax: "<length-percentage>";
|
|
225
|
+
inherits: true;
|
|
226
|
+
initial-value: 12px;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
@property --radius-badge {
|
|
230
|
+
syntax: "<length-percentage>";
|
|
231
|
+
inherits: true;
|
|
232
|
+
initial-value: 9999px;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
@property --radius-inputs {
|
|
236
|
+
syntax: "<length-percentage>";
|
|
237
|
+
inherits: true;
|
|
238
|
+
initial-value: 6px;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
@property --radius-pill {
|
|
242
|
+
syntax: "<length-percentage>";
|
|
243
|
+
inherits: true;
|
|
244
|
+
initial-value: 9999px;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
@property --control-height-tiny {
|
|
248
|
+
syntax: "<length>";
|
|
249
|
+
inherits: true;
|
|
250
|
+
initial-value: 24px;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
@property --control-height-sm {
|
|
254
|
+
syntax: "<length>";
|
|
255
|
+
inherits: true;
|
|
256
|
+
initial-value: 32px;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
@property --control-height-md {
|
|
260
|
+
syntax: "<length>";
|
|
261
|
+
inherits: true;
|
|
262
|
+
initial-value: 40px;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
@property --control-height-lg {
|
|
266
|
+
syntax: "<length>";
|
|
267
|
+
inherits: true;
|
|
268
|
+
initial-value: 48px;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
@property --control-height-icon-sm {
|
|
272
|
+
syntax: "<length>";
|
|
273
|
+
inherits: true;
|
|
274
|
+
initial-value: 28px;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
@property --control-height-icon-md {
|
|
278
|
+
syntax: "<length>";
|
|
279
|
+
inherits: true;
|
|
280
|
+
initial-value: 32px;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
@property --control-height-icon-lg {
|
|
284
|
+
syntax: "<length>";
|
|
285
|
+
inherits: true;
|
|
286
|
+
initial-value: 36px;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
@property --control-font-size-tiny {
|
|
290
|
+
syntax: "<length>";
|
|
291
|
+
inherits: true;
|
|
292
|
+
initial-value: 11px;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
@property --control-font-size-sm {
|
|
296
|
+
syntax: "<length>";
|
|
297
|
+
inherits: true;
|
|
298
|
+
initial-value: 12px;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
@property --control-font-size-md {
|
|
302
|
+
syntax: "<length>";
|
|
303
|
+
inherits: true;
|
|
304
|
+
initial-value: 14px;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
@property --control-font-size-lg {
|
|
308
|
+
syntax: "<length>";
|
|
309
|
+
inherits: true;
|
|
310
|
+
initial-value: 16px;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/* ── Numeric slots ────────────────────────────────────────────────────────────
|
|
314
|
+
* `font-weight` also accepts `normal` / `bold` in CSS, so those two idents are
|
|
315
|
+
* spelled into the syntax rather than excluded. `bolder` / `lighter` are left
|
|
316
|
+
* out on purpose: they are parent-relative and cannot survive as a slot value.
|
|
317
|
+
* Every skin currently writes a number (300–700).
|
|
318
|
+
*/
|
|
319
|
+
@property --font-weight-medium {
|
|
320
|
+
syntax: "<number> | normal | bold";
|
|
321
|
+
inherits: true;
|
|
322
|
+
initial-value: 500;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
@property --font-weight-heading {
|
|
326
|
+
syntax: "<number> | normal | bold";
|
|
327
|
+
inherits: true;
|
|
328
|
+
initial-value: 600;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/* ── Genuinely untypeable: box-shadow lists ───────────────────────────────────
|
|
332
|
+
* These four are consumed as `box-shadow`, and the `@property` syntax grammar
|
|
333
|
+
* has no `<shadow>` component — its component names are limited to <length>,
|
|
334
|
+
* <number>, <percentage>, <length-percentage>, <color>, <image>, <url>,
|
|
335
|
+
* <integer>, <angle>, <time>, <resolution>, <transform-function>,
|
|
336
|
+
* <transform-list>, <custom-ident> and <string>, with only `+` / `#`
|
|
337
|
+
* multipliers. A shadow list ("0 1px 2px 0 rgb(…)", possibly comma-separated)
|
|
338
|
+
* cannot be spelled in that grammar, so `*` is the honest answer, not a
|
|
339
|
+
* shortcut. These slots therefore remain unguarded and a colour written into
|
|
340
|
+
* one still voids the `box-shadow` declaration that reads it. The audit script
|
|
341
|
+
* is the backstop for them.
|
|
342
|
+
*/
|
|
343
|
+
@property --btn-default-shadow {
|
|
344
|
+
syntax: "*";
|
|
345
|
+
inherits: true;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
@property --elevation-card {
|
|
349
|
+
syntax: "*";
|
|
350
|
+
inherits: true;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
@property --elevation-control {
|
|
354
|
+
syntax: "*";
|
|
355
|
+
inherits: true;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
@property --elevation-raised {
|
|
359
|
+
syntax: "*";
|
|
360
|
+
inherits: true;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/* ── Genuinely untypeable: bare HSL channel triplets ──────────────────────────
|
|
364
|
+
* These carry channels ("222 47% 11%"), not colours — they exist to be wrapped
|
|
365
|
+
* as `hsl(var(--brand-mark))` / `hsl(var(--brand-mark) / 0.08)`, which is what
|
|
366
|
+
* makes the alpha-suffix idiom possible. `<color>` would reject every one of
|
|
367
|
+
* them. There is also no typed spelling for the triplet: `@property` syntax has
|
|
368
|
+
* no space-separated component composition and no <number-percentage>, so
|
|
369
|
+
* "<number> <percentage> <percentage>" is not expressible. `*` is correct here.
|
|
370
|
+
* The type error these slots invite is the inverse one — writing a full colour
|
|
371
|
+
* (`#0033FE`) where channels are expected, which the audit script catches at
|
|
372
|
+
* the `hsl()` call site.
|
|
373
|
+
*/
|
|
374
|
+
@property --role-action {
|
|
375
|
+
syntax: "*";
|
|
376
|
+
inherits: true;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
@property --role-action-fg {
|
|
380
|
+
syntax: "*";
|
|
381
|
+
inherits: true;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
@property --brand-mark {
|
|
385
|
+
syntax: "*";
|
|
386
|
+
inherits: true;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
@property --brand-mark-foreground {
|
|
390
|
+
syntax: "*";
|
|
391
|
+
inherits: true;
|
|
392
|
+
}
|
|
393
|
+
|
|
65
394
|
/* Tailwind v4: brand-mark as first-class color (Logo / BrandMark / badge) */
|
|
66
395
|
@theme inline {
|
|
67
396
|
--color-brand-mark: hsl(var(--brand-mark));
|
package/skins/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Design skins & Brand Packages
|
|
2
2
|
|
|
3
3
|
**Goal:** Create Center users swap a **design language** by applying one **Brand Package**.
|
|
4
|
-
This package is a *carrier* (roles + free elev/radii
|
|
4
|
+
This package is a *carrier* (roles + free elev/radii), not a list of brand hacks.
|
|
5
5
|
|
|
6
6
|
## Two layers
|
|
7
7
|
|
|
@@ -130,11 +130,9 @@ const { iframeRef, apply: preview, writePreviewDocument } = useBrandIframePrevie
|
|
|
130
130
|
// preview(brand) or writePreviewDocument(brand, "<button class='btn-brand-default'>CTA</button>")
|
|
131
131
|
```
|
|
132
132
|
|
|
133
|
-
### Fonts
|
|
133
|
+
### Fonts
|
|
134
134
|
|
|
135
135
|
- `typography.faces[]` → emitted as `@font-face` (swap URL for Create Center CDN/upload).
|
|
136
|
-
- `zones.product` / `zones.marketing` → CSS vars + `[data-zone="…"]` / `.zone-…` consumers.
|
|
137
|
-
- Marketing may use 224px display; product stays compact.
|
|
138
136
|
|
|
139
137
|
### design-sync
|
|
140
138
|
|
package/skins/cosmos.css
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brand carrier skin: Cosmos (cosmos) v2.0.0
|
|
3
|
+
* darkDefault=false dualMode=true button=solid
|
|
4
|
+
* fonts=0 mode=global
|
|
5
|
+
* Contract: roles.action → --primary; roles.brand → --brand-mark (never default CTA)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
:root,
|
|
9
|
+
html[data-brand="cosmos"] {
|
|
10
|
+
/* ── Color roles (carrier) ── */
|
|
11
|
+
--role-canvas: 30 20% 96%;
|
|
12
|
+
--role-canvas-fg: 0 0% 5%;
|
|
13
|
+
--role-surface: 0 0% 100%;
|
|
14
|
+
--role-surface-fg: 0 0% 5%;
|
|
15
|
+
--role-action: 0 0% 5%;
|
|
16
|
+
--role-action-fg: 30 20% 96%;
|
|
17
|
+
--role-quiet: 0 0% 100%;
|
|
18
|
+
--role-quiet-fg: 0 0% 5%;
|
|
19
|
+
--role-muted: 30 20% 96%;
|
|
20
|
+
--role-muted-fg: 12 2% 42%;
|
|
21
|
+
--role-border: 30 5% 85%;
|
|
22
|
+
--role-input: 30 5% 85%;
|
|
23
|
+
--role-ring: 0 0% 5%;
|
|
24
|
+
--role-brand: 0 0% 5%;
|
|
25
|
+
--role-brand-fg: 30 20% 96%;
|
|
26
|
+
--brand-mark: 0 0% 5%;
|
|
27
|
+
--brand-mark-foreground: 30 20% 96%;
|
|
28
|
+
|
|
29
|
+
/* ── shadcn bridge (primary = action CTA) ── */
|
|
30
|
+
--background: 30 20% 96%;
|
|
31
|
+
--foreground: 0 0% 5%;
|
|
32
|
+
--card: 0 0% 100%;
|
|
33
|
+
--card-foreground: 0 0% 5%;
|
|
34
|
+
--popover: 0 0% 100%;
|
|
35
|
+
--popover-foreground: 0 0% 5%;
|
|
36
|
+
--primary: 0 0% 5%;
|
|
37
|
+
--primary-foreground: 30 20% 96%;
|
|
38
|
+
--secondary: 0 0% 100%;
|
|
39
|
+
--secondary-foreground: 0 0% 5%;
|
|
40
|
+
--muted: 30 20% 96%;
|
|
41
|
+
--muted-foreground: 12 2% 42%;
|
|
42
|
+
--accent: 0 0% 5%;
|
|
43
|
+
--accent-foreground: 30 20% 96%;
|
|
44
|
+
--destructive: 4 76% 40%;
|
|
45
|
+
--destructive-foreground: 0 0% 100%;
|
|
46
|
+
--border: 30 5% 85%;
|
|
47
|
+
--input: 30 5% 85%;
|
|
48
|
+
--ring: 0 0% 5%;
|
|
49
|
+
--success: 134 62% 40%;
|
|
50
|
+
--success-foreground: 0 0% 100%;
|
|
51
|
+
--info: 12 2% 42%;
|
|
52
|
+
--info-foreground: 0 0% 100%;
|
|
53
|
+
--sidebar: 0 0% 100%;
|
|
54
|
+
--sidebar-foreground: 0 0% 5%;
|
|
55
|
+
--sidebar-primary: 0 0% 5%;
|
|
56
|
+
--sidebar-primary-foreground: 30 20% 96%;
|
|
57
|
+
--sidebar-accent: 0 0% 5%;
|
|
58
|
+
--sidebar-accent-foreground: 30 20% 96%;
|
|
59
|
+
--sidebar-border: 30 5% 85%;
|
|
60
|
+
--sidebar-ring: 0 0% 5%;
|
|
61
|
+
--brand-primary: hsl(0 0% 5%);
|
|
62
|
+
--brand-accent: hsl(0 0% 5%);
|
|
63
|
+
--brand-accent-foreground: hsl(30 20% 96%);
|
|
64
|
+
--brand-tertiary: hsl(0 0% 5%);
|
|
65
|
+
--brand-gradient: hsl(var(--primary));
|
|
66
|
+
--brand-gradient-reverse: hsl(var(--primary));
|
|
67
|
+
--brand-gradient-vertical: hsl(var(--primary));
|
|
68
|
+
--brand-gradient-radial: hsl(var(--primary));
|
|
69
|
+
|
|
70
|
+
/* ── Neutral ramp, anchored on this language's roles ── */
|
|
71
|
+
--neutral-1: hsl(30 20% 96%);
|
|
72
|
+
--neutral-2: hsl(0 0% 100%);
|
|
73
|
+
--neutral-3: color-mix(in oklab, hsl(30 5% 85%) 20%, hsl(0 0% 100%));
|
|
74
|
+
--neutral-4: color-mix(in oklab, hsl(30 5% 85%) 40%, hsl(0 0% 100%));
|
|
75
|
+
--neutral-5: color-mix(in oklab, hsl(30 5% 85%) 60%, hsl(0 0% 100%));
|
|
76
|
+
--neutral-6: color-mix(in oklab, hsl(30 5% 85%) 80%, hsl(0 0% 100%));
|
|
77
|
+
--neutral-7: hsl(30 5% 85%);
|
|
78
|
+
--neutral-8: color-mix(in oklab, hsl(12 2% 42%) 25%, hsl(30 5% 85%));
|
|
79
|
+
--neutral-9: color-mix(in oklab, hsl(12 2% 42%) 50%, hsl(30 5% 85%));
|
|
80
|
+
--neutral-10: color-mix(in oklab, hsl(12 2% 42%) 75%, hsl(30 5% 85%));
|
|
81
|
+
--neutral-11: hsl(12 2% 42%);
|
|
82
|
+
--neutral-12: hsl(0 0% 5%);
|
|
83
|
+
|
|
84
|
+
/* Recipe (action language + free elev/radii) */
|
|
85
|
+
/* Shape slots */
|
|
86
|
+
--btn-default-radius: 16px;
|
|
87
|
+
--radius-button: 16px;
|
|
88
|
+
--radius-buttons: 16px;
|
|
89
|
+
--radius-md: min(16px, 16px);
|
|
90
|
+
--radius-card: 16px;
|
|
91
|
+
--radius-lg: 16px;
|
|
92
|
+
--radius-badge: 16px;
|
|
93
|
+
--badge-default-radius: 16px;
|
|
94
|
+
--radius-inputs: 16px;
|
|
95
|
+
--input-radius: 16px;
|
|
96
|
+
--radius-pill: 9999px;
|
|
97
|
+
|
|
98
|
+
/* Free elevation (carrier-provided CSS shadows) */
|
|
99
|
+
--elevation-card: 0 0 #0000;
|
|
100
|
+
--elevation-control: 0 0 #0000;
|
|
101
|
+
--elevation-raised: 0 0 #0000;
|
|
102
|
+
--elevation-xs: 0 0 #0000;
|
|
103
|
+
--elevation-sm: 0 0 #0000;
|
|
104
|
+
--elevation-md: 0 0 #0000;
|
|
105
|
+
--elevation-lg: 0 0 #0000;
|
|
106
|
+
--btn-default-shadow: 0 0 #0000;
|
|
107
|
+
--btn-default-bg: hsl(var(--primary));
|
|
108
|
+
--btn-default-fg: hsl(var(--primary-foreground));
|
|
109
|
+
--btn-default-border-width: 0px;
|
|
110
|
+
--btn-default-border: transparent;
|
|
111
|
+
--btn-default-stroke-gradient: linear-gradient(transparent, transparent);
|
|
112
|
+
--btn-default-hover-bg: color-mix(in srgb, hsl(var(--primary)) 90%, transparent);
|
|
113
|
+
--badge-default-bg: hsl(var(--secondary));
|
|
114
|
+
--badge-default-fg: hsl(var(--secondary-foreground));
|
|
115
|
+
--badge-default-border: transparent;
|
|
116
|
+
--badge-default-hover-bg: color-mix(in srgb, hsl(var(--secondary)) 90%, white);
|
|
117
|
+
|
|
118
|
+
/* Typography */
|
|
119
|
+
--font-sans:
|
|
120
|
+
var(--font-reg-fraunces), "Fraunces", "GT Super", Georgia,
|
|
121
|
+
var(--font-noto-sans-sc, "Noto Sans SC"), "PingFang SC", ui-serif, serif;
|
|
122
|
+
--font-cn:
|
|
123
|
+
var(--font-reg-fraunces), "Fraunces", "GT Super", Georgia,
|
|
124
|
+
var(--font-noto-sans-sc, "Noto Sans SC"), "PingFang SC", ui-serif, serif;
|
|
125
|
+
--font-heading:
|
|
126
|
+
var(--font-reg-fraunces), "Fraunces", "GT Super", Georgia,
|
|
127
|
+
var(--font-noto-sans-sc, "Noto Sans SC"), "PingFang SC", ui-serif, serif;
|
|
128
|
+
--font-display:
|
|
129
|
+
var(--font-reg-fraunces), "Fraunces", "GT Super", Georgia,
|
|
130
|
+
var(--font-noto-sans-sc, "Noto Sans SC"), "PingFang SC", ui-serif, serif;
|
|
131
|
+
--font-mono: var(--font-jetbrains-mono), "JetBrains Mono", ui-monospace, monospace;
|
|
132
|
+
--font-weight-heading: 350;
|
|
133
|
+
|
|
134
|
+
/* Motion */
|
|
135
|
+
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
|
|
136
|
+
--motion-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
|
|
137
|
+
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
|
138
|
+
--motion-ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
|
139
|
+
--duration-micro: 80ms;
|
|
140
|
+
--motion-duration-micro: 80ms;
|
|
141
|
+
--duration-flow: 180ms;
|
|
142
|
+
--motion-duration-flow: 180ms;
|
|
143
|
+
--duration-reveal: 180ms;
|
|
144
|
+
--motion-duration-reveal: 180ms;
|
|
145
|
+
--duration-cinematic: 320ms;
|
|
146
|
+
--motion-duration-cinematic: 320ms;
|
|
147
|
+
|
|
148
|
+
/* Spacing */
|
|
149
|
+
--space-source-xs: 0.5rem;
|
|
150
|
+
--space-source-sm: 1rem;
|
|
151
|
+
--space-source-md: 1.25rem;
|
|
152
|
+
--space-source-lg: 1.5rem;
|
|
153
|
+
--space-source-xl: 2rem;
|
|
154
|
+
--space-source-2xl: 3rem;
|
|
155
|
+
|
|
156
|
+
/* Taxonomy / decorative (not product CTA) */
|
|
157
|
+
--brand-category-linen-canvas: #f7f5f3;
|
|
158
|
+
--brand-category-ink-black: #0d0d0d;
|
|
159
|
+
--brand-category-paper-white: #ffffff;
|
|
160
|
+
--brand-category-stone: #6e6a69;
|
|
161
|
+
--brand-category-pebble: #9a9796;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.dark,
|
|
165
|
+
html.dark[data-brand="cosmos"] {
|
|
166
|
+
/* ── Color roles (carrier) ── */
|
|
167
|
+
--role-canvas: 0 0% 5%;
|
|
168
|
+
--role-canvas-fg: 30 20% 96%;
|
|
169
|
+
--role-surface: 0 0% 11%;
|
|
170
|
+
--role-surface-fg: 30 20% 96%;
|
|
171
|
+
--role-action: 30 20% 96%;
|
|
172
|
+
--role-action-fg: 0 0% 5%;
|
|
173
|
+
--role-quiet: 0 0% 14%;
|
|
174
|
+
--role-quiet-fg: 30 20% 96%;
|
|
175
|
+
--role-muted: 0 0% 11%;
|
|
176
|
+
--role-muted-fg: 15 2% 60%;
|
|
177
|
+
--role-border: 0 1% 18%;
|
|
178
|
+
--role-input: 0 1% 18%;
|
|
179
|
+
--role-ring: 30 20% 96%;
|
|
180
|
+
--role-brand: 30 20% 96%;
|
|
181
|
+
--role-brand-fg: 0 0% 5%;
|
|
182
|
+
--brand-mark: 30 20% 96%;
|
|
183
|
+
--brand-mark-foreground: 0 0% 5%;
|
|
184
|
+
|
|
185
|
+
/* ── shadcn bridge (primary = action CTA) ── */
|
|
186
|
+
--background: 0 0% 5%;
|
|
187
|
+
--foreground: 30 20% 96%;
|
|
188
|
+
--card: 0 0% 11%;
|
|
189
|
+
--card-foreground: 30 20% 96%;
|
|
190
|
+
--popover: 0 0% 11%;
|
|
191
|
+
--popover-foreground: 30 20% 96%;
|
|
192
|
+
--primary: 30 20% 96%;
|
|
193
|
+
--primary-foreground: 0 0% 5%;
|
|
194
|
+
--secondary: 0 0% 14%;
|
|
195
|
+
--secondary-foreground: 30 20% 96%;
|
|
196
|
+
--muted: 0 0% 11%;
|
|
197
|
+
--muted-foreground: 15 2% 60%;
|
|
198
|
+
--accent: 30 20% 96%;
|
|
199
|
+
--accent-foreground: 0 0% 5%;
|
|
200
|
+
--destructive: 4 76% 40%;
|
|
201
|
+
--destructive-foreground: 0 0% 100%;
|
|
202
|
+
--border: 0 1% 18%;
|
|
203
|
+
--input: 0 1% 18%;
|
|
204
|
+
--ring: 30 20% 96%;
|
|
205
|
+
--success: 134 62% 40%;
|
|
206
|
+
--success-foreground: 0 0% 100%;
|
|
207
|
+
--info: 12 2% 42%;
|
|
208
|
+
--info-foreground: 0 0% 100%;
|
|
209
|
+
--sidebar: 0 0% 11%;
|
|
210
|
+
--sidebar-foreground: 30 20% 96%;
|
|
211
|
+
--sidebar-primary: 30 20% 96%;
|
|
212
|
+
--sidebar-primary-foreground: 0 0% 5%;
|
|
213
|
+
--sidebar-accent: 30 20% 96%;
|
|
214
|
+
--sidebar-accent-foreground: 0 0% 5%;
|
|
215
|
+
--sidebar-border: 0 1% 18%;
|
|
216
|
+
--sidebar-ring: 30 20% 96%;
|
|
217
|
+
--brand-primary: hsl(30 20% 96%);
|
|
218
|
+
--brand-accent: hsl(30 20% 96%);
|
|
219
|
+
--brand-accent-foreground: hsl(0 0% 5%);
|
|
220
|
+
--brand-tertiary: hsl(30 20% 96%);
|
|
221
|
+
--brand-gradient: hsl(var(--primary));
|
|
222
|
+
--brand-gradient-reverse: hsl(var(--primary));
|
|
223
|
+
--brand-gradient-vertical: hsl(var(--primary));
|
|
224
|
+
--brand-gradient-radial: hsl(var(--primary));
|
|
225
|
+
|
|
226
|
+
/* ── Neutral ramp, anchored on this language's roles ── */
|
|
227
|
+
--neutral-1: hsl(0 0% 5%);
|
|
228
|
+
--neutral-2: hsl(0 0% 11%);
|
|
229
|
+
--neutral-3: color-mix(in oklab, hsl(0 1% 18%) 20%, hsl(0 0% 11%));
|
|
230
|
+
--neutral-4: color-mix(in oklab, hsl(0 1% 18%) 40%, hsl(0 0% 11%));
|
|
231
|
+
--neutral-5: color-mix(in oklab, hsl(0 1% 18%) 60%, hsl(0 0% 11%));
|
|
232
|
+
--neutral-6: color-mix(in oklab, hsl(0 1% 18%) 80%, hsl(0 0% 11%));
|
|
233
|
+
--neutral-7: hsl(0 1% 18%);
|
|
234
|
+
--neutral-8: color-mix(in oklab, hsl(15 2% 60%) 25%, hsl(0 1% 18%));
|
|
235
|
+
--neutral-9: color-mix(in oklab, hsl(15 2% 60%) 50%, hsl(0 1% 18%));
|
|
236
|
+
--neutral-10: color-mix(in oklab, hsl(15 2% 60%) 75%, hsl(0 1% 18%));
|
|
237
|
+
--neutral-11: hsl(15 2% 60%);
|
|
238
|
+
--neutral-12: hsl(30 20% 96%);
|
|
239
|
+
}
|