@nebutra/tokens 0.1.2 → 0.1.3

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