@ttoss/fsl-theme 1.1.13 → 1.1.15

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 (91) hide show
  1. package/dist/Types-BiBa17RL.d.cts +1427 -0
  2. package/dist/Types-BiBa17RL.d.mts +1427 -0
  3. package/dist/baseBundle-DxvXyhGa.mjs +17 -0
  4. package/dist/baseBundle-iEFf5nqT.cjs +22 -0
  5. package/dist/{esm/chunk-SE5Z52RE.js → createTheme-BLNYztZU.mjs} +76 -172
  6. package/dist/createTheme-Cv6RP9D6.cjs +1825 -0
  7. package/dist/css.cjs +48 -0
  8. package/dist/{css.d.ts → css.d.cts} +67 -63
  9. package/dist/css.d.mts +168 -0
  10. package/dist/css.mjs +42 -0
  11. package/dist/dataviz/index.cjs +45 -0
  12. package/dist/dataviz/{index.d.ts → index.d.cts} +9 -5
  13. package/dist/dataviz/index.d.mts +66 -0
  14. package/dist/dataviz/index.mjs +39 -0
  15. package/dist/dtcg.cjs +115 -0
  16. package/dist/{dtcg.d.ts → dtcg.d.cts} +9 -7
  17. package/dist/dtcg.d.mts +51 -0
  18. package/dist/dtcg.mjs +112 -0
  19. package/dist/helpers-4p4-QVt_.cjs +258 -0
  20. package/dist/helpers-CaswNJMy.mjs +211 -0
  21. package/dist/{index.d.ts → index-CsIjfw86.d.cts} +42 -34
  22. package/dist/index-nJrjI0BA.d.mts +94 -0
  23. package/dist/index.cjs +16 -0
  24. package/dist/index.d.cts +6 -0
  25. package/dist/index.d.mts +6 -0
  26. package/dist/index.mjs +7 -0
  27. package/dist/{react.d.ts → react-CGa6FlNL.d.cts} +130 -106
  28. package/dist/react-DnKxR2gK.d.mts +370 -0
  29. package/dist/react-EUwpdvY7.cjs +481 -0
  30. package/dist/react.cjs +12 -0
  31. package/dist/react.d.cts +4 -0
  32. package/dist/react.d.mts +4 -0
  33. package/dist/react.mjs +412 -0
  34. package/dist/runtime-entry.cjs +9 -0
  35. package/dist/runtime-entry.d.cts +3 -0
  36. package/dist/runtime-entry.d.mts +3 -0
  37. package/dist/runtime-entry.mjs +3 -0
  38. package/dist/{runtime-entry.d.ts → ssrScript-BVysxDws.d.cts} +26 -23
  39. package/dist/ssrScript-BVysxDws.d.mts +98 -0
  40. package/dist/ssrScript-CRfrN8Pm.cjs +202 -0
  41. package/dist/ssrScript-D3kGPQpi.mjs +179 -0
  42. package/dist/themes/bruttal.cjs +75 -0
  43. package/dist/themes/bruttal.d.cts +3 -0
  44. package/dist/themes/bruttal.d.mts +3 -0
  45. package/dist/themes/bruttal.mjs +72 -0
  46. package/dist/themes/corporate.cjs +34 -0
  47. package/dist/themes/corporate.d.cts +3 -0
  48. package/dist/themes/corporate.d.mts +3 -0
  49. package/dist/{esm/chunk-TPMN75JM.js → themes/corporate.mjs} +7 -5
  50. package/dist/themes/oca.cjs +34 -0
  51. package/dist/themes/oca.d.cts +3 -0
  52. package/dist/themes/oca.d.mts +3 -0
  53. package/dist/{esm/chunk-DU4QDQUC.js → themes/oca.mjs} +7 -5
  54. package/dist/themes/ventures.cjs +34 -0
  55. package/dist/themes/ventures.d.cts +3 -0
  56. package/dist/themes/ventures.d.mts +3 -0
  57. package/dist/{esm/chunk-BXKVVQEP.js → themes/ventures.mjs} +7 -5
  58. package/dist/toCssVars-CYZCe-on.mjs +286 -0
  59. package/dist/toCssVars-DudHKvt2.cjs +297 -0
  60. package/dist/{esm/chunk-4Q4P3JBB.js → tokenRegistry-DjgSN3oU.mjs} +23 -20
  61. package/dist/tokenRegistry-OhaJ9sPJ.cjs +199 -0
  62. package/dist/vars.cjs +127 -0
  63. package/dist/{vars.d.ts → vars.d.cts} +8 -7
  64. package/dist/vars.d.mts +128 -0
  65. package/dist/vars.mjs +123 -0
  66. package/dist/withDataviz-B4pVsOwV.cjs +192 -0
  67. package/dist/{esm/chunk-FBVUI2PK.js → withDataviz-DY5s7R51.mjs} +40 -12
  68. package/package.json +20 -20
  69. package/dist/Types-6tR0_2Ss.d.ts +0 -1452
  70. package/dist/esm/chunk-5PWPAQMC.js +0 -9
  71. package/dist/esm/chunk-HRNXVRS3.js +0 -54
  72. package/dist/esm/chunk-IJGA42O6.js +0 -141
  73. package/dist/esm/chunk-PQPQNZ73.js +0 -262
  74. package/dist/esm/chunk-UMRQ4OTX.js +0 -11
  75. package/dist/esm/chunk-VL6EGE6Z.js +0 -222
  76. package/dist/esm/chunk-WVQSTQD5.js +0 -192
  77. package/dist/esm/css.js +0 -6
  78. package/dist/esm/dataviz/index.js +0 -19
  79. package/dist/esm/dtcg.js +0 -65
  80. package/dist/esm/index.js +0 -10
  81. package/dist/esm/react.js +0 -8
  82. package/dist/esm/runtime-entry.js +0 -4
  83. package/dist/esm/themes/bruttal.js +0 -6
  84. package/dist/esm/themes/corporate.js +0 -6
  85. package/dist/esm/themes/oca.js +0 -6
  86. package/dist/esm/themes/ventures.js +0 -6
  87. package/dist/esm/vars.js +0 -28
  88. package/dist/themes/bruttal.d.ts +0 -5
  89. package/dist/themes/corporate.d.ts +0 -5
  90. package/dist/themes/oca.d.ts +0 -5
  91. package/dist/themes/ventures.d.ts +0 -5
@@ -0,0 +1,1427 @@
1
+
2
+ //#region src/dataviz/Types.d.ts
3
+ type Scale1To8 = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
4
+ type Scale1To7 = 1 | 2 | 3 | 4 | 5 | 6 | 7;
5
+ type Scale1To6 = 1 | 2 | 3 | 4 | 5 | 6;
6
+ /**
7
+ * Core data visualization token tree.
8
+ *
9
+ * Contains non-color encoding primitives only.
10
+ * Color tokens are sourced directly from `core.colors.*` — no separate dataviz
11
+ * color palette is needed. Semantic dataviz color tokens reference `core.colors.*`.
12
+ *
13
+ * Placed at `theme.core.dataviz` — optional extension of `ThemeTokens`.
14
+ */
15
+ interface CoreDataviz {
16
+ /** Mark shapes for categorical differentiation (e.g. 'circle', 'square'). */
17
+ shape: Record<Scale1To8, RawValue>;
18
+ /** Fill patterns for area/region differentiation (e.g. 'diagonal-stripes'). */
19
+ pattern: Record<Scale1To6, RawValue>;
20
+ /** Stroke dash patterns as SVG-compatible dash-array strings. */
21
+ stroke: {
22
+ solid: RawValue;
23
+ dashed: RawValue;
24
+ dotted: RawValue;
25
+ };
26
+ /**
27
+ * Analytical opacity primitives.
28
+ * Distinct from foundation opacity — used as encoding channels, not UI effects.
29
+ */
30
+ opacity: {
31
+ /** Geographic/spatial context reduction behind overlays. */context: NumericValue; /** De-emphasis of non-highlighted data marks. */
32
+ muted: NumericValue; /** Visual signal of estimated or uncertain data. */
33
+ uncertainty: NumericValue;
34
+ };
35
+ }
36
+ /**
37
+ * Semantic categorical and scale color roles.
38
+ *
39
+ * Paths (in code: semantic.dataviz.color.*):
40
+ * dataviz.color.series.1..8
41
+ * dataviz.color.scale.sequential.1..7
42
+ * dataviz.color.scale.diverging.neg3..pos3
43
+ * dataviz.color.reference.baseline / target
44
+ * dataviz.color.state.highlight / muted / selected
45
+ * dataviz.color.status.missing / suppressed / not-applicable
46
+ */
47
+ interface SemanticDatavizColor {
48
+ /**
49
+ * Categorical series identity — 8 named, unordered roles.
50
+ * Use for nominal categories, named series, distinct groups.
51
+ */
52
+ series: Record<Scale1To8, TokenRef>;
53
+ scale: {
54
+ /**
55
+ * Ordered magnitude — 7 steps from low (1) to high (7).
56
+ * Use for quantitative ranges and progressive intensity.
57
+ */
58
+ sequential: Record<Scale1To7, TokenRef>;
59
+ /**
60
+ * Midpoint comparison — 7 named positions around a true center.
61
+ * Only use when the data has a meaningful midpoint (zero, baseline, target).
62
+ */
63
+ diverging: {
64
+ neg3: TokenRef;
65
+ neg2: TokenRef;
66
+ neg1: TokenRef; /** Neutral midpoint class. */
67
+ neutral: TokenRef;
68
+ pos1: TokenRef;
69
+ pos2: TokenRef;
70
+ pos3: TokenRef;
71
+ };
72
+ };
73
+ reference: {
74
+ /** Color for a baseline or reference level (e.g. average, goal). */baseline: TokenRef; /** Color for a target or objective line. */
75
+ target: TokenRef;
76
+ };
77
+ state: {
78
+ /** Emphasized / highlighted data mark. */highlight: TokenRef; /** De-emphasized / non-highlighted data mark. */
79
+ muted: TokenRef; /** User-selected or actively focused data mark. */
80
+ selected: TokenRef;
81
+ };
82
+ status: {
83
+ /** Value is absent or unavailable. */missing: TokenRef; /** Value is withheld for confidentiality or publication rules. */
84
+ suppressed: TokenRef; /** Value is structurally absent (not measured or not applicable). */
85
+ na: TokenRef;
86
+ };
87
+ }
88
+ /**
89
+ * Semantic non-color encoding roles.
90
+ *
91
+ * Paths: dataviz.encoding.*
92
+ */
93
+ interface SemanticDatavizEncoding {
94
+ shape: {
95
+ /** Series identity through mark shape — use for redundant differentiation. */series: Record<Scale1To8, TokenRef>;
96
+ };
97
+ pattern: {
98
+ /** Series identity through fill texture — use for filled marks and overlays. */series: Record<Scale1To6, TokenRef>;
99
+ };
100
+ stroke: {
101
+ /** Stroke style for analytical reference guides or baselines. */reference: TokenRef; /** Stroke style for projected or forward-looking data segments. */
102
+ forecast: TokenRef; /** Stroke style for uncertain or estimated bounds. */
103
+ uncertainty: TokenRef;
104
+ };
105
+ opacity: {
106
+ /** Opacity for contextual elements behind overlay data. */context: TokenRef; /** Opacity for de-emphasized (non-highlighted) data marks. */
107
+ muted: TokenRef; /** Opacity for representing estimated or uncertain data visually. */
108
+ uncertainty: TokenRef;
109
+ };
110
+ }
111
+ /**
112
+ * Semantic geospatial overlay roles.
113
+ *
114
+ * Defines only the contextual relationship between overlays and geography.
115
+ * Geospatial overlays use `dataviz.color.*` and `dataviz.encoding.*` for
116
+ * analytical meaning — these tokens cover only spatial context.
117
+ *
118
+ * Paths: dataviz.geo.*
119
+ */
120
+ interface SemanticDatavizGeo {
121
+ context: {
122
+ /** Reduced background wash for geographic base layer. */muted: TokenRef; /** Color for supportive boundary lines (region outlines, coastlines). */
123
+ boundary: TokenRef; /** Color for contextual geographic labels (city names, region labels). */
124
+ label: TokenRef;
125
+ };
126
+ state: {
127
+ /** Fill or stroke for a spatially selected region. */selection: TokenRef; /** Fill or stroke for spatially focused region (keyboard / pointer focus). */
128
+ focus: TokenRef;
129
+ };
130
+ }
131
+ /**
132
+ * Full semantic data visualization token tree.
133
+ *
134
+ * Placed at `theme.semantic.dataviz` — optional extension of `ThemeTokens`.
135
+ * This is the **public API** of the Data Visualization extension.
136
+ * Components and patterns must consume only these tokens.
137
+ */
138
+ interface SemanticDataviz {
139
+ color: SemanticDatavizColor;
140
+ encoding: SemanticDatavizEncoding;
141
+ geo: SemanticDatavizGeo;
142
+ }
143
+ //#endregion
144
+ //#region src/families/primitives.d.ts
145
+ /** A raw CSS value (color hex, px, clamp expression, etc.) */
146
+ type RawValue = string;
147
+ /** A numeric raw value (font weight, opacity, line-height, z-index, etc.) */
148
+ type NumericValue = number;
149
+ /**
150
+ * A reference to a core token, expressed as `{token.path}`.
151
+ *
152
+ * Optionally narrowed to a path prefix family for autocomplete and typo
153
+ * catching at high-leverage positions. Defaults to `string` — fully open —
154
+ * which preserves the original (untyped-path) behavior for any external code
155
+ * importing `TokenRef` directly.
156
+ *
157
+ * Narrowed aliases cover every semantic family. The only remaining open
158
+ * `TokenRef` is `SemanticFocus.ring.color`, which intentionally references a
159
+ * `semantic.*` path rather than a `core.*` one.
160
+ *
161
+ * @example
162
+ * ```ts
163
+ * // open — accepts any '{...}' string
164
+ * const ref: TokenRef = '{core.colors.brand.500}';
165
+ *
166
+ * // narrowed — '{core.spacing.|' autocompletes; '{core.colorz.…}' errors
167
+ * const gap: TokenRef<`core.spacing.${string}`> = '{core.spacing.4}';
168
+ * ```
169
+ */
170
+ type TokenRef<TPath extends string = string> = `{${TPath}}`;
171
+ /** Reference into the `core.colors.*` namespace. */
172
+ type CoreColorRef = TokenRef<`core.colors.${string}`>;
173
+ /** Reference into the `core.spacing.*` namespace. */
174
+ type CoreSpacingRef = TokenRef<`core.spacing.${string}`>;
175
+ /** Reference into the `core.sizing.*` namespace. */
176
+ type CoreSizingRef = TokenRef<`core.sizing.${string}`>;
177
+ /** Reference into the `core.font.scale.*` namespace (responsive size ramp). */
178
+ type CoreFontScaleRef = TokenRef<`core.font.scale.${string}`>;
179
+ /** Reference into the `core.font.*` namespace (family, weight, leading, tracking, optical, numeric). */
180
+ type CoreFontRef = TokenRef<`core.font.${string}`>;
181
+ /** Reference into the `core.elevation.*` namespace. */
182
+ type CoreElevationRef = TokenRef<`core.elevation.${string}`>;
183
+ /** Reference into the `core.radii.*` namespace. */
184
+ type CoreRadiiRef = TokenRef<`core.radii.${string}`>;
185
+ /** Reference into the `core.border.*` namespace (width and style sub-families). */
186
+ type CoreBorderRef = TokenRef<`core.border.${string}`>;
187
+ /** Reference into the `core.opacity.*` namespace. */
188
+ type CoreOpacityRef = TokenRef<`core.opacity.${string}`>;
189
+ /** Reference into the `core.motion.*` namespace (duration and easing sub-families). */
190
+ type CoreMotionRef = TokenRef<`core.motion.${string}`>;
191
+ /** Reference into the `core.zIndex.*` namespace. */
192
+ type CoreZIndexRef = TokenRef<`core.zIndex.${string}`>;
193
+ /**
194
+ * Recursive partial type. Every nested property becomes optional,
195
+ * enabling selective overrides at any depth.
196
+ */
197
+ type DeepPartial<T> = T extends object ? { [P in keyof T]?: DeepPartial<T[P]> } : T;
198
+ //#endregion
199
+ //#region src/families/borders.d.ts
200
+ /**
201
+ * Core line widths — intent-free primitives.
202
+ * `selected` and `focused` must resolve to a width strictly greater than `default`.
203
+ * Never reference these directly from components — use semantic border tokens.
204
+ */
205
+ interface CoreBorderWidths {
206
+ none: RawValue;
207
+ default: RawValue;
208
+ selected: RawValue;
209
+ focused: RawValue;
210
+ }
211
+ /**
212
+ * Core line styles — intent-free primitives.
213
+ * Default to `solid`; use `dashed` or `dotted` only when the pattern truly requires it.
214
+ */
215
+ interface CoreBorderStyles {
216
+ solid: RawValue;
217
+ dashed: RawValue;
218
+ dotted: RawValue;
219
+ none: RawValue;
220
+ }
221
+ /** Intent-free line primitives — width and style only. */
222
+ interface CoreBorder {
223
+ width: CoreBorderWidths;
224
+ style: CoreBorderStyles;
225
+ }
226
+ /**
227
+ * Shared shape for every semantic line contract: width + style references only.
228
+ * Color is never part of this contract — pair with semantic color tokens.
229
+ * @see SemanticColors — for border color tokens per UX context.
230
+ */
231
+ interface SemanticBorderOutline {
232
+ width: CoreBorderRef;
233
+ style: CoreBorderRef;
234
+ }
235
+ /**
236
+ * Semantic line contracts — the stable API consumed by components.
237
+ *
238
+ * Four canonical contracts (borders.md §Canonical semantic set):
239
+ * @see borders.md
240
+ * - `divider` — structural separator between content groups
241
+ * - `outline.surface` — boundary of containing surfaces (cards, panels, dialogs)
242
+ * - `outline.control` — boundary of interactive controls (buttons, inputs, toggles)
243
+ * - `outline.selected` — stronger-thickness indicator for selected/current state
244
+ *
245
+ * Rules:
246
+ * - Components consume these tokens only — never `core.border.*` directly.
247
+ * - `outline.selected` must resolve to a width strictly greater than `outline.{surface,control}`.
248
+ * - Color meaning stays in the color system; these tokens define geometry only.
249
+ * - Do not add component-specific tokens (`border.input`, `border.card`, etc.).
250
+ *
251
+ * @adr ADR-011 — `outline.selected` lives inside `outline.*` (shape grouping); `focus.ring` stays separate (accessibility contract + color field).
252
+ */
253
+ interface SemanticBorder {
254
+ /**
255
+ * Structural separator between content groups (low emphasis).
256
+ * Use when splitting list rows, sections, toolbar regions, or grouped fields
257
+ * — anywhere the line *separates* without enclosing.
258
+ * Pair with a low-emphasis color (`informational.muted.border.default`); do
259
+ * not use to enclose a surface or control — those are `outline.surface` /
260
+ * `outline.control`.
261
+ */
262
+ divider: SemanticBorderOutline;
263
+ outline: {
264
+ /**
265
+ * Boundary of a containing surface (card, panel, dialog, menu, grouped region).
266
+ * Use when the element *contains* other content and needs a visible edge.
267
+ * Pair with `informational.{role}.border.{state}` colors and (optionally)
268
+ * `semantic.elevation.surface.*`; do not use for interactive controls — those
269
+ * are `outline.control`.
270
+ */
271
+ surface: SemanticBorderOutline;
272
+ /**
273
+ * Boundary of an interactive control (button, input, toggle, chip, segmented item).
274
+ * Use when the element is interactive and needs a visible edge at rest.
275
+ * Pair with `{ux}.{role}.border.{state}` colors per FSL UX context; do not
276
+ * use for containing surfaces — those are `outline.surface`.
277
+ */
278
+ control: SemanticBorderOutline;
279
+ /**
280
+ * Stronger-thickness boundary expressing selected / current state.
281
+ * Use when selection or current-item status is communicated by line weight
282
+ * (active tab, selected row, chosen card).
283
+ * Resolves to a width strictly greater than `outline.{surface,control}`. Do
284
+ * not use for keyboard focus — that is `semantic.focus.ring`.
285
+ */
286
+ selected: SemanticBorderOutline;
287
+ };
288
+ }
289
+ //#endregion
290
+ //#region src/families/breakpoints.d.ts
291
+ interface CoreBreakpoints {
292
+ sm: RawValue;
293
+ md: RawValue;
294
+ lg: RawValue;
295
+ xl: RawValue;
296
+ '2xl': RawValue;
297
+ }
298
+ //#endregion
299
+ //#region src/families/colors.d.ts
300
+ /**
301
+ * Unified color scale steps (0–1000).
302
+ * Themes may use any subset; step 500 is always required as the canonical mid-point.
303
+ */
304
+ type CoreColorStep = 0 | 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 1000;
305
+ /**
306
+ * Palette scale — partial record over CoreColorStep with 500 required.
307
+ * Sparse palettes (100/300/500/700/900) and dense palettes (0–1000) both conform.
308
+ */
309
+ type CoreColorScale = Partial<Record<CoreColorStep, RawValue>> & {
310
+ 500: RawValue;
311
+ };
312
+ /**
313
+ * Core color tokens — intent-free palette primitives.
314
+ *
315
+ * Rules:
316
+ * - Core names define palette families and scale positions, never usage.
317
+ * - No semantic naming (no `danger`, `warning`, `link`, `surface`, etc.).
318
+ * - No mode naming (core values are immutable across modes).
319
+ * - No component naming (no `cardBg`, `inputBorder`, etc.).
320
+ *
321
+ * @see colors.md
322
+ */
323
+ interface CoreColors {
324
+ /** Primary brand identity color scale. */
325
+ brand: CoreColorScale;
326
+ /**
327
+ * Zero-saturation anchor scale (greyscale/slate).
328
+ * Provides surfaces, text contrast, dividers, and subdued UI.
329
+ * Named `neutral` by convention — not a semantic role, purely a palette family.
330
+ * Use step 0 for white-end and step 1000 for black-end.
331
+ */
332
+ neutral: CoreColorScale;
333
+ /**
334
+ * Open hue families. Themes define which they need (red, green, yellow, blue, etc.).
335
+ * No fixed set is required beyond `brand` and `neutral`.
336
+ */
337
+ [hue: string]: CoreColorScale;
338
+ }
339
+ /** Base interaction states — available in every UX context.
340
+ * `selected` is NOT included here — it is added only by the UX contexts
341
+ * where set-membership semantics apply (input, navigation, informational).
342
+ * Action context uses `pressed` for toggle state instead (FSL Lexicon §7).
343
+ */
344
+ interface BaseColorStates {
345
+ /** Resting / base state. The colour rendered when no other state asserts. */
346
+ default: CoreColorRef;
347
+ /** Pointer is currently over the element. Do not use for keyboard focus — that is `focused`. */
348
+ hover?: CoreColorRef;
349
+ /** Pointer or key is currently *down* on the element — transient, lasts only while held. Releases back to `default` / `hover`. Do not use for persistent toggle state — that is `pressed`. */
350
+ active?: CoreColorRef;
351
+ /** Element has keyboard or programmatic focus. Pair with `semantic.focus.ring.color` when no `{ux}.{role}` context applies. */
352
+ focused?: CoreColorRef;
353
+ /** Element is non-interactive. Carries the contrast guarantees that `semantic.opacity.disabled` cannot — prefer this for controls and text over opacity. */
354
+ disabled?: CoreColorRef;
355
+ /**
356
+ * Valid drag-and-drop destination during an active drag (FSL Lexicon §7).
357
+ * Applies wherever drop-target semantics are valid: file inputs, collection rows,
358
+ * informational surfaces, and any other entity that accepts dropped items.
359
+ */
360
+ droptarget?: CoreColorRef;
361
+ }
362
+ /** `action` context: adds `pressed` for toggle controls and `expanded` for disclosure triggers and open menus. */
363
+ interface ActionColorStates extends BaseColorStates {
364
+ /** Toggle button is currently engaged — *persistent*, not transient. Use for toolbar toggles ("Bold" pressed). Do not confuse with `active` (the brief moment of clicking). */
365
+ pressed?: CoreColorRef;
366
+ /** Disclosure trigger or menu button is currently open. Use for buttons that own an open popup, menu, or panel. */
367
+ expanded?: CoreColorRef;
368
+ }
369
+ /** `input` context: adds `checked`, `indeterminate`, `pressed`, `expanded` for form controls.
370
+ *
371
+ * Validation failure is *not* a state — it is an Evaluation (FSL Lexicon §5).
372
+ * Components that fail validation render with the `input.negative.*` role,
373
+ * not with an `invalid` state on `input.primary.*`. This avoids dual
374
+ * representation of the same semantic concept and keeps FSL §7 State Law
375
+ * intact ("States are not free-form"). React Aria's `isInvalid` flag maps
376
+ * to selecting the `negative` role, not to a new state.
377
+ *
378
+ * Structural Role → token mapping (FSL Lexicon §2): a part declared with
379
+ * Structural Role `validationMessage` consumes `input.negative.text.*` for
380
+ * its text dimension (and `input.negative.{background,border}.*` if it
381
+ * carries those dimensions). `validationMessage` is anatomy (which part);
382
+ * `input.negative.*` is the visual contract (which value). The same
383
+ * Evaluation token lawfully serves multiple Structural Roles — this is the
384
+ * intended single-source semantics, not duplication. */
385
+ interface InputColorStates extends BaseColorStates {
386
+ /** Element is **one of many** in a set and the user picked it (segment in a segmented control, picker option). Do not use for two-state controls — those are `checked`. */
387
+ selected?: CoreColorRef;
388
+ /** **Two-state control** that is currently on — checkbox, radio, switch. Do not use for selection from a set — that is `selected`. */
389
+ checked?: CoreColorRef;
390
+ /** Boolean control in a mixed / unknown state — e.g. parent checkbox over partially-checked children. */
391
+ indeterminate?: CoreColorRef;
392
+ /** Persistent engaged state of a toggle-style input (e.g. a switch rendered as a button). See `ActionColorStates.pressed` for the disambiguation against `active`. */
393
+ pressed?: CoreColorRef;
394
+ /** Combobox / select / disclosure-style input is currently open. */
395
+ expanded?: CoreColorRef;
396
+ }
397
+ /** `navigation` context: adds `selected`, `current`, `visited`, `expanded`. */
398
+ interface NavigationColorStates extends BaseColorStates {
399
+ /** Tab / item is **one of many** in the set and the user picked it. May coexist with `current` when the selected item also represents the live route. */
400
+ selected?: CoreColorRef;
401
+ /** Element is the user's **current location** in the navigation set — active route, current step in a wizard. Do not use for set-membership without a routing meaning — that is `selected`. */
402
+ current?: CoreColorRef;
403
+ /** Link points to a URL the user has visited. */
404
+ visited?: CoreColorRef;
405
+ /** Disclosure-style nav item (collapsible section, expandable submenu) is currently open. */
406
+ expanded?: CoreColorRef;
407
+ }
408
+ /** `informational` context: adds `selected`, `visited`, `expanded`.
409
+ *
410
+ * `expanded` covers in-place disclosure on presentational surfaces (accordions,
411
+ * collapsible panels, expandable cards). `Disclosure` Entity Kinds project to
412
+ * `informational` per FSL identity (in-place reveal, not movement across
413
+ * destinations — FSL Lexicon §1). */
414
+ interface InformationalColorStates extends BaseColorStates {
415
+ /** Presentational element is **one of many** and the user picked it (selectable list row, focused card in a deck). */
416
+ selected?: CoreColorRef;
417
+ /** Visited link rendered inside informational content. */
418
+ visited?: CoreColorRef;
419
+ /** Accordion / collapsible panel / `<details>` is currently open — in-place reveal (FSL Lexicon §1). */
420
+ expanded?: CoreColorRef;
421
+ }
422
+ /**
423
+ * `feedback` context state set — feedback components are not interactive triggers (FSL §7).
424
+ * Legal states: `default`, `focused` (focusable wrapper or close button), `disabled`.
425
+ * `hover`, `active`, `selected`, `pressed`, `expanded`, `droptarget` are illegal.
426
+ */
427
+ interface FeedbackColorStates {
428
+ /** Resting / base state. The colour rendered when no other state asserts. */
429
+ default: CoreColorRef;
430
+ /** Element has keyboard or programmatic focus — e.g. a focusable close button inside the feedback component. */
431
+ focused?: CoreColorRef;
432
+ /** Element is non-interactive. Prefer this over `opacity.disabled` for controls and text that carry colour contrast guarantees. */
433
+ disabled?: CoreColorRef;
434
+ }
435
+ /**
436
+ * Color dimensions for a given UX context.
437
+ * Each dimension is optional — components choose which they consume.
438
+ * (e.g. a text link uses only `text`; a ghost button uses `text` + `border`)
439
+ */
440
+ interface ColorDimensionOf<S extends BaseColorStates> {
441
+ /** Fills and surface backgrounds. Use for any colored area larger than a line. */
442
+ background?: S;
443
+ /** Outlines, separators, rings, and other line-color pairings. For line *geometry* (width, style) consume `semantic.borders.*` instead — this dimension is colour only. */
444
+ border?: S;
445
+ /** Readable foreground — labels, paragraphs, and text-like icons that inherit `currentColor`. */
446
+ text?: S;
447
+ }
448
+ /** `action`: triggers actions or changes state. Roles: primary | secondary | accent | muted | negative */
449
+ interface ActionColorRoles {
450
+ /** The single most important action on the view. Only one `primary` per `{ux}` per view — if two compete, the loser is `secondary`. */
451
+ primary: ColorDimensionOf<ActionColorStates>;
452
+ /** Alternative action that coexists with the primary one. Use when two actions share the surface and neither dominates. */
453
+ secondary: ColorDimensionOf<ActionColorStates>;
454
+ /** Highlighted action that draws attention without being the main path ("Try the new…" promo button). */
455
+ accent: ColorDimensionOf<ActionColorStates>;
456
+ /** Low-priority action — helper button, optional control, dismiss / cancel ghost. */
457
+ muted: ColorDimensionOf<ActionColorStates>;
458
+ /** Action whose intent is adverse: failure, invalid result, or destructive consequence (delete, cancel paid plan). Outcome (success / warning) lives in `feedback.*`, not here. */
459
+ negative: ColorDimensionOf<ActionColorStates>;
460
+ }
461
+ /** `input`: data entry, selection, form controls. Roles: primary | secondary | muted | positive | caution | negative */
462
+ interface InputColorRoles {
463
+ /** Default input role — the brand-influenced active style for the canonical control on the form. */
464
+ primary: ColorDimensionOf<InputColorStates>;
465
+ /** Alternative input role coexisting with `primary` — e.g. a secondary search field on the same surface. */
466
+ secondary: ColorDimensionOf<InputColorStates>;
467
+ /** Low-priority input — quiet text field, ghost search, optional metadata input. */
468
+ muted: ColorDimensionOf<InputColorStates>;
469
+ /** Input whose value reports success / completion / validity confirmed (e.g. "available" username field after async check). */
470
+ positive: ColorDimensionOf<InputColorStates>;
471
+ /** Input whose value carries risk that needs attention but does not block submission. */
472
+ caution: ColorDimensionOf<InputColorStates>;
473
+ /** Input whose value failed validation — maps from React Aria `isInvalid`. Validation failure is *not* a state on `primary`; it selects this role (FSL Lexicon §5). */
474
+ negative: ColorDimensionOf<InputColorStates>;
475
+ }
476
+ /** `navigation`: movement and orientation. Roles: primary | secondary | accent | muted */
477
+ interface NavigationColorRoles {
478
+ /** The dominant navigation surface on the view — main top nav, primary sidebar. */
479
+ primary: ColorDimensionOf<NavigationColorStates>;
480
+ /** Secondary navigation that coexists with the primary one — sub-nav, in-page tabs. */
481
+ secondary: ColorDimensionOf<NavigationColorStates>;
482
+ /** Highlighted nav item that draws attention without being the main path — "What's new", featured destination. */
483
+ accent: ColorDimensionOf<NavigationColorStates>;
484
+ /** Low-priority nav — footer links, breadcrumb separators, optional sub-items. */
485
+ muted: ColorDimensionOf<NavigationColorStates>;
486
+ }
487
+ /** `feedback`: reactive system/user-result messages. Roles: primary | muted | positive | caution | negative */
488
+ interface FeedbackColorRoles {
489
+ /** Neutral / informational feedback that carries no valence — "Auto-saved", "Connected". */
490
+ primary: ColorDimensionOf<FeedbackColorStates>;
491
+ /** Quiet feedback that should not steal attention — inline hints, low-priority status text. */
492
+ muted: ColorDimensionOf<FeedbackColorStates>;
493
+ /** Feedback reporting success, completion, or validity confirmed. */
494
+ positive: ColorDimensionOf<FeedbackColorStates>;
495
+ /** Feedback reporting risk that needs attention but does not block the user. */
496
+ caution: ColorDimensionOf<FeedbackColorStates>;
497
+ /** Feedback reporting failure or an invalid system state. */
498
+ negative: ColorDimensionOf<FeedbackColorStates>;
499
+ }
500
+ /** `informational`: informational surfaces and readable content. Roles: primary | secondary | accent | muted | positive | caution | negative */
501
+ interface InformationalColorRoles {
502
+ /** Dominant content / surface on the view — page background, main panel, the card the user is reading. */
503
+ primary: ColorDimensionOf<InformationalColorStates>;
504
+ /** Supporting content / surface coexisting with `primary` — sidebar panel, secondary card. */
505
+ secondary: ColorDimensionOf<InformationalColorStates>;
506
+ /** Highlighted content that draws attention without being the main path — featured callout, promo tile. */
507
+ accent: ColorDimensionOf<InformationalColorStates>;
508
+ /** Low-priority content — helper text, dividers, captions, metadata. */
509
+ muted: ColorDimensionOf<InformationalColorStates>;
510
+ /** Informational surface or text reporting success / completion (e.g. "All up to date" empty state). */
511
+ positive: ColorDimensionOf<InformationalColorStates>;
512
+ /** Informational surface or text carrying caution — warning panel, advisory note. */
513
+ caution: ColorDimensionOf<InformationalColorStates>;
514
+ /** Informational surface or text reporting failure or invalid state — error empty state, broken-state panel. */
515
+ negative: ColorDimensionOf<InformationalColorStates>;
516
+ }
517
+ /**
518
+ * Semantic colour API — the only colour contract components consume.
519
+ *
520
+ * Pick the UX context by asking *what kind of UI is this?* (colors.md §"UX contexts in 60 seconds"):
521
+ * is the user about to **act**, **type**, **move**, **hear back**, or just **see / contain** something?
522
+ *
523
+ * Token grammar: `{ux}.{role}.{dimension}.{state}`. Legal combinations are
524
+ * enforced by the type system; see colors.md §Legal Combinations.
525
+ *
526
+ * @see colors.md
527
+ */
528
+ interface SemanticColors {
529
+ /** Anything the user **triggers** — buttons, toggles, menu items, action icons. Pick when the user is about to *act*. */
530
+ action: ActionColorRoles;
531
+ /** Anything the user **enters or selects data into** — text fields, selects, checkboxes, radios. Pick when the user is about to *type / pick a value*. */
532
+ input: InputColorRoles;
533
+ /** Anything that **moves the user** between views or sections — links, tabs, breadcrumbs, pagination. Pick when the user is about to *go somewhere*. */
534
+ navigation: NavigationColorRoles;
535
+ /** Surfaces that **report the outcome** of an action or system event — toasts, alerts, banners, inline validation. Pick when the system is *reporting back*. */
536
+ feedback: FeedbackColorRoles;
537
+ /**
538
+ * **Presentational surfaces** — hold, group, layer, frame, or display content; never drive a transaction.
539
+ * Body text, page backgrounds, cards, panels, dialogs, dividers, list rows, accordions.
540
+ * Interactivity is not a tiebreaker: a focusable Card or expandable accordion is still `informational` —
541
+ * its purpose is presentational. Focusability is covered by `semantic.focus.ring.*`; disclosure by the `expanded` state.
542
+ */
543
+ informational: InformationalColorRoles;
544
+ }
545
+ //#endregion
546
+ //#region src/families/elevation.d.ts
547
+ /**
548
+ * Open shadow recipe ramp — themes define as many levels as needed.
549
+ * Every key referenced by a semantic token must resolve to a defined entry here.
550
+ */
551
+ type CoreElevationLevels = Record<string, RawValue>;
552
+ /**
553
+ * Core elevation primitives — shadow recipe ramps.
554
+ *
555
+ * - `level` — base recipes (standard opacity), used by default in light themes
556
+ * - `emphatic` — high-opacity recipes for surfaces needing stronger depth contrast
557
+ * (e.g., on dark or heavily-colored backgrounds)
558
+ *
559
+ * Both ramps are open `Record<string, RawValue>` — themes define as many levels as
560
+ * needed. Every key referenced by a semantic token must be defined here.
561
+ *
562
+ * Future expansion (non-breaking): add optional sibling ramps as needed.
563
+ * @see elevation.md
564
+ */
565
+ interface CoreElevation {
566
+ /** Base shadow recipes — standard opacity, light-surface defaults. */
567
+ level: CoreElevationLevels;
568
+ /**
569
+ * High-opacity shadow recipes for surfaces needing stronger depth contrast.
570
+ * Mode-agnostic: expresses shadow weight, not a mode label.
571
+ * Themes include this ramp when a dark alternate requires higher-opacity recipes.
572
+ */
573
+ emphatic?: CoreElevationLevels;
574
+ }
575
+ interface SemanticElevation {
576
+ /**
577
+ * Shadow-based surface strata — the primary depth contract.
578
+ * Maps each stratum to a shadow recipe (core elevation reference).
579
+ */
580
+ surface: {
581
+ /** Surfaces flush with the page */flat: CoreElevationRef; /** Cards and panels */
582
+ raised: CoreElevationRef; /** Dropdowns, popovers, floating surfaces */
583
+ overlay: CoreElevationRef; /** Dialogs and blocking sheets */
584
+ blocking: CoreElevationRef;
585
+ };
586
+ /**
587
+ * Tonal overlay tokens — optional surface color treatments paired with shadows
588
+ * to preserve depth perception in dark or heavily-colored themes.
589
+ *
590
+ * Each token typically resolves to a color overlay (e.g., `color-mix`, rgba surface).
591
+ * Omit when the product does not use tonal elevation.
592
+ * When present, must cover the same strata that carry visible shadows.
593
+ * @see elevation.md — "Surface + Shadow"
594
+ */
595
+ tonal?: {
596
+ /**
597
+ * Tonal surface treatment paired with `surface.raised`.
598
+ * Use when the raised stratum needs an additional color overlay (typical in
599
+ * dark themes where shadow alone is insufficient).
600
+ * Pair with `surface.raised`; do not use without the matching shadow contract.
601
+ */
602
+ raised: CoreColorRef;
603
+ /**
604
+ * Tonal surface treatment paired with `surface.overlay`.
605
+ * Use when the overlay stratum (dropdowns, popovers) needs reinforced
606
+ * tonal lift over the page beneath.
607
+ * Pair with `surface.overlay`; resolves to a stronger overlay than `tonal.raised`.
608
+ */
609
+ overlay: CoreColorRef;
610
+ /**
611
+ * Tonal surface treatment paired with `surface.blocking`.
612
+ * Use when the blocking stratum (dialogs, sheets) needs the strongest
613
+ * tonal separation from the page beneath the scrim.
614
+ * Pair with `surface.blocking` and `semantic.overlay.scrim`; resolves to
615
+ * the strongest tonal overlay in the contract.
616
+ */
617
+ blocking: CoreColorRef;
618
+ };
619
+ }
620
+ //#endregion
621
+ //#region src/families/focus.d.ts
622
+ interface SemanticFocus {
623
+ ring: SemanticBorderOutline & {
624
+ /**
625
+ * System-wide focus ring colour — cross-cutting infrastructure (model.md §6).
626
+ *
627
+ * Use this when the component has no obvious FSL Entity Kind
628
+ * (focusable Card, profile chip, custom widget). For components with a clear
629
+ * `{ux}`, prefer `{ux}.{role}.border.focused` instead.
630
+ *
631
+ * Must reference a semantic token so mode overrides remap it automatically.
632
+ */
633
+ color: TokenRef<`semantic.${string}`>;
634
+ };
635
+ }
636
+ //#endregion
637
+ //#region src/families/motion.d.ts
638
+ interface CoreMotionDurations {
639
+ none: RawValue;
640
+ xs: RawValue;
641
+ sm: RawValue;
642
+ md: RawValue;
643
+ lg: RawValue;
644
+ xl: RawValue;
645
+ }
646
+ interface CoreMotionEasings {
647
+ standard: RawValue;
648
+ enter: RawValue;
649
+ exit: RawValue;
650
+ linear: RawValue;
651
+ }
652
+ /** Core motion primitives — duration steps and easing curves. Components consume only semantic motion tokens. */
653
+ interface CoreMotion {
654
+ duration: CoreMotionDurations;
655
+ easing: CoreMotionEasings;
656
+ }
657
+ /** A duration + easing pair that fully specifies motion for one use-case. */
658
+ interface SemanticMotionSpec {
659
+ duration: CoreMotionRef;
660
+ easing: CoreMotionRef;
661
+ }
662
+ interface SemanticMotion {
663
+ /**
664
+ * Immediate response to a discrete user input on a single element.
665
+ * Use when animating hover, press, toggle, or small confirmation tweaks
666
+ * (color/scale/opacity changes on the element itself).
667
+ * Do not use for elements entering or leaving the layout — those are
668
+ * `transition.enter` / `transition.exit`.
669
+ */
670
+ feedback: SemanticMotionSpec;
671
+ transition: {
672
+ /**
673
+ * Element appearing into rest position (overlay, surface, revealed content).
674
+ * Use when an element transitions *from* hidden/absent *to* visible.
675
+ * Pair with `transition.exit` on the inverse phase; do not use for the
676
+ * resting element's response to input — that is `feedback`.
677
+ */
678
+ enter: SemanticMotionSpec;
679
+ /**
680
+ * Element leaving rest position (overlay closing, content dismissing).
681
+ * Use when an element transitions *from* visible *to* hidden/absent.
682
+ * Symmetric counterpart of `transition.enter`; the exit phase is shorter
683
+ * by default to keep dismissal feeling responsive.
684
+ */
685
+ exit: SemanticMotionSpec;
686
+ };
687
+ /**
688
+ * Attention-drawing motion for a relevant in-place change.
689
+ * Use when the user must notice that something changed (status update,
690
+ * value reconciliation, error appearing on a field).
691
+ * Stronger than `feedback`; do not use for routine state changes — that is
692
+ * `feedback`. May collapse to minimal motion in static themes.
693
+ */
694
+ emphasis: SemanticMotionSpec;
695
+ /**
696
+ * Ambient, non-essential motion (loops, parallax, idle flourishes).
697
+ * Use only when motion is never required for understanding the UI.
698
+ * Always disabled by default in static or reduced-motion themes; do not use
699
+ * for any motion the user must perceive to operate the interface.
700
+ */
701
+ decorative: SemanticMotionSpec;
702
+ }
703
+ //#endregion
704
+ //#region src/families/opacity.d.ts
705
+ /** Intent-free opacity scale. Components must use `SemanticOpacity` — never this directly.
706
+ * Invariant: `0 ≤ 25 ≤ 50 ≤ 75 ≤ 100`, all in `[0, 1]`, no two adjacent steps equal. */
707
+ interface CoreOpacity {
708
+ 100: NumericValue;
709
+ 75: NumericValue;
710
+ 50: NumericValue;
711
+ 25: NumericValue;
712
+ 0: NumericValue;
713
+ }
714
+ /** Stable opacity contracts for components. Each must resolve to `(0, 1)` exclusive.
715
+ *
716
+ * Opacity is a whole-element modifier — never a substitute for a semantic
717
+ * color, state, or hierarchy token (opacity.md §"What Opacity Should Not Do").
718
+ * If only one dimension (background, text, border) should become translucent,
719
+ * use a semantic color with alpha instead.
720
+ */
721
+ interface SemanticOpacity {
722
+ /**
723
+ * Backdrop dimming for a blocking foreground layer.
724
+ * Use when rendering the layer that sits *behind* a modal, dialog, drawer, or sheet
725
+ * to attenuate the page underneath.
726
+ * Pair with `semantic.overlay.scrim` (the colored backdrop fill); do not use on the
727
+ * foreground surface itself — that surface stays fully opaque.
728
+ */
729
+ scrim: CoreOpacityRef;
730
+ /**
731
+ * De-emphasis veil for content during in-flight asynchronous work.
732
+ * Use when content must remain visible (so the user keeps spatial context) while a
733
+ * fetch / mutation / long task is pending.
734
+ * Do not use for permanent disabled state — that is `disabled`. Remove the moment
735
+ * the work resolves.
736
+ */
737
+ loading: CoreOpacityRef;
738
+ /**
739
+ * Dimming for image-like media in a disabled state (avatars, thumbnails, illustrations).
740
+ * Use when the disabled element has no semantic color contract that can carry the state
741
+ * (i.e. it is a visual asset, not a control).
742
+ * Do not use for disabled controls or text — those consume `{ux}.{role}.{dimension}.disabled`
743
+ * color tokens, which carry the contrast guarantees opacity cannot.
744
+ */
745
+ disabled: CoreOpacityRef;
746
+ }
747
+ //#endregion
748
+ //#region src/families/overlay.d.ts
749
+ interface SemanticOverlay {
750
+ /** Modal backdrop color — full CSS color including alpha. */
751
+ scrim: RawValue;
752
+ }
753
+ //#endregion
754
+ //#region src/families/radii.d.ts
755
+ /**
756
+ * Core radius scale — intent-free corner curvature primitives.
757
+ * Ordered: none < sm < md < lg < xl << full.
758
+ *
759
+ * **Never reference core radii directly from components.**
760
+ * Components consume only semantic radii (`radii.control`, `radii.surface`, `radii.round`).
761
+ */
762
+ interface CoreRadii {
763
+ none: RawValue;
764
+ sm: RawValue;
765
+ md: RawValue;
766
+ lg: RawValue;
767
+ xl: RawValue;
768
+ /**
769
+ * Fully-rounded intent (`9999px`).
770
+ * Expresses shape intent — perfect circles still depend on element dimensions.
771
+ */
772
+ full: RawValue;
773
+ }
774
+ /**
775
+ * Semantic radius contracts — stable shape API consumed by components.
776
+ *
777
+ * Pick by structural role:
778
+ * - `control` → interactive element (button, input, toggle, chip)
779
+ * - `surface` → containing surface (card, panel, dialog, menu)
780
+ * - `round` → explicitly fully-rounded shape intent (pill, capsule, avatar)
781
+ *
782
+ * @see radii.md — Decision Matrix and Rules of Engagement.
783
+ */
784
+ interface SemanticRadii {
785
+ /** Radius for interactive controls and touchable UI elements. */
786
+ control: CoreRadiiRef;
787
+ /** Radius for surfaces that contain or group content. */
788
+ surface: CoreRadiiRef;
789
+ /** Full-round shape intent for pills, capsules, and circular affordances. */
790
+ round: CoreRadiiRef;
791
+ }
792
+ //#endregion
793
+ //#region src/families/sizing.d.ts
794
+ type CoreSizeRampUI = Record<1 | 2 | 3 | 4 | 5 | 6 | 7 | 8, RawValue>;
795
+ type CoreSizeRampLayout = Record<1 | 2 | 3 | 4 | 5 | 6, RawValue>;
796
+ interface CoreSizeRelative {
797
+ em: RawValue;
798
+ rem: RawValue;
799
+ }
800
+ interface CoreSizeBehavior {
801
+ auto: RawValue;
802
+ full: RawValue;
803
+ fit: RawValue;
804
+ min: RawValue;
805
+ max: RawValue;
806
+ }
807
+ interface CoreSizeViewport {
808
+ height: {
809
+ full: RawValue;
810
+ };
811
+ width: {
812
+ full: RawValue;
813
+ };
814
+ }
815
+ /** Three-step hit target size ramp (min / base / prominent). */
816
+ interface CoreSizeHitScale {
817
+ min: RawValue;
818
+ base: RawValue;
819
+ prominent: RawValue;
820
+ }
821
+ /**
822
+ * Hit target sizes split by pointer type.
823
+ * `toCssVars` automatically injects the `coarse` values under `@media (any-pointer: coarse)`.
824
+ */
825
+ interface CoreSizeHit {
826
+ /** Fine pointer (mouse/trackpad) hit targets */
827
+ fine: CoreSizeHitScale;
828
+ /** Coarse pointer (touch) hit targets */
829
+ coarse: CoreSizeHitScale;
830
+ }
831
+ interface CoreSizing {
832
+ ramp: {
833
+ ui: CoreSizeRampUI;
834
+ layout: CoreSizeRampLayout;
835
+ };
836
+ relative: CoreSizeRelative;
837
+ behavior: CoreSizeBehavior;
838
+ viewport: CoreSizeViewport;
839
+ hit: CoreSizeHit;
840
+ }
841
+ interface SemanticSizing {
842
+ /**
843
+ * Ergonomic hit targets. Each token resolves to the **fine-pointer** value.
844
+ * The CSS output layer (`toCssVars`) automatically injects coarse-pointer
845
+ * overrides inside `@media (any-pointer: coarse)` — no component code needed.
846
+ *
847
+ * Fine-pointer values (`core.sizing.hit.fine.*`) may use `clamp(floor, preferred, max)`
848
+ * where `floor` is a fixed `Npx` ergonomic minimum — this guarantees accessibility
849
+ * while allowing themes to express density preferences (e.g. via the rem scale).
850
+ * Coarse-pointer values (`core.sizing.hit.coarse.*`) are always fixed `px`.
851
+ */
852
+ hit: {
853
+ /** Minimum interactive area for small / secondary targets (icon-only buttons, toolbar items). Enforce via `min-width` / `min-height`; not a visual size. */min: CoreSizingRef; /** Default interactive area for standard buttons, inputs, and toggles. Pick when no other step applies. */
854
+ base: CoreSizingRef; /** Prominent interactive area for high-emphasis or low-density targets (CTAs, dialog actions). */
855
+ prominent: CoreSizingRef;
856
+ };
857
+ /**
858
+ * Visual glyph dimensions. Set on the icon element itself; never used to
859
+ * gate the hit target that wraps it (that is `hit.*`).
860
+ */
861
+ icon: {
862
+ /** Compact glyph — dense UI, inline indicators, list-row icons. */sm: CoreSizingRef; /** Default glyph — pick this when no other step applies. */
863
+ md: CoreSizingRef; /** Prominent glyph — emphasis or feature icons. */
864
+ lg: CoreSizingRef;
865
+ };
866
+ /**
867
+ * Visual identity object dimensions (avatars, profile photos, brand marks,
868
+ * entity logos). Carries the *visual* size only — the surrounding hit target,
869
+ * if any, is sized via `hit.*`.
870
+ */
871
+ identity: {
872
+ /** Compact identity — list rows, dense lists, mention chips. */sm: CoreSizingRef; /** Default identity — toolbar, navigation, standard avatar slots. */
873
+ md: CoreSizingRef; /** Prominent identity — profile cards, feature surfaces. */
874
+ lg: CoreSizingRef; /** Hero identity — landing surfaces, brand-leading sections. */
875
+ xl: CoreSizingRef;
876
+ };
877
+ measure: {
878
+ /**
879
+ * Typed as `RawValue` by design: `ch` units cannot be expressed as a core
880
+ * token reference. Override with a validated character-based `clamp()`
881
+ * expression only — never px or rem.
882
+ */
883
+ reading: RawValue;
884
+ };
885
+ surface: {
886
+ /**
887
+ * Maximum width of a structural surface (page shell, content column,
888
+ * card / panel / dialog wrapper).
889
+ * Use as `max-width` on the *outer* surface wrapper.
890
+ * Pair with `gutter.page` for inline padding; do not use for line-length
891
+ * readability — that is `measure.reading`.
892
+ */
893
+ maxWidth: CoreSizingRef;
894
+ };
895
+ viewport: {
896
+ height: {
897
+ /**
898
+ * Full-height layouts using dynamic viewport units (`100dvh`).
899
+ * Use intentionally — only when a region must occupy the full viewport
900
+ * height (app shells, full-screen modals, mobile splash regions).
901
+ * Do not use `100vh` directly — dynamic units handle mobile chrome correctly.
902
+ */
903
+ full: CoreSizingRef;
904
+ };
905
+ width: {
906
+ /**
907
+ * Full-width layouts using dynamic viewport units (`100dvw`).
908
+ * Use intentionally — only when a region must span the full viewport
909
+ * width (full-bleed banners, edge-to-edge surfaces).
910
+ * Do not use `100vw` directly — dynamic units avoid scrollbar overflow.
911
+ */
912
+ full: CoreSizingRef;
913
+ };
914
+ };
915
+ }
916
+ //#endregion
917
+ //#region src/families/spacing.d.ts
918
+ interface CoreSpacingEngine {
919
+ /** Responsive base unit — container-first clamp formula */
920
+ unit: RawValue;
921
+ /** Optional container-aware variant */
922
+ unitCq?: RawValue;
923
+ }
924
+ interface CoreSpacingSteps {
925
+ /** Responsive engine primitives — internal, not for direct component use */
926
+ engine: CoreSpacingEngine;
927
+ 0: RawValue;
928
+ 1: RawValue;
929
+ 2: RawValue;
930
+ 3: RawValue;
931
+ 4: RawValue;
932
+ 6: RawValue;
933
+ 8: RawValue;
934
+ 12: RawValue;
935
+ 16: RawValue;
936
+ }
937
+ interface InsetSteps {
938
+ /** Compact step — tight controls / dense surfaces. */
939
+ sm: CoreSpacingRef;
940
+ /** Default step — standard controls and surfaces. Pick this when no other step applies. */
941
+ md: CoreSpacingRef;
942
+ /** Roomy step — prominent controls / spacious surfaces. */
943
+ lg: CoreSpacingRef;
944
+ }
945
+ interface GapStackSteps {
946
+ /** Tight vertical rhythm — micro-clusters within a single field. */
947
+ xs: CoreSpacingRef;
948
+ /** Medium vertical rhythm — sibling lines inside a form group. */
949
+ sm: CoreSpacingRef;
950
+ /** Default vertical rhythm — pick this when no other step applies. */
951
+ md: CoreSpacingRef;
952
+ /** Roomy vertical rhythm — separating distinct content clusters within a surface. */
953
+ lg: CoreSpacingRef;
954
+ /** Section-level rhythm — separating major sections of a page. */
955
+ xl: CoreSpacingRef;
956
+ }
957
+ interface GapInlineSteps {
958
+ /** Visual-only tight grouping (icon + label inside a single target). Never between focusable targets — use `separation.interactive.min`. */
959
+ xs: CoreSpacingRef;
960
+ /** Inline grouping — same magnitude as `gap.stack.xs`. */
961
+ sm: CoreSpacingRef;
962
+ /** Looser inline grouping — same magnitude as `gap.stack.sm`. */
963
+ md: CoreSpacingRef;
964
+ /** Spacious inline grouping — same magnitude as `gap.stack.md`. */
965
+ lg: CoreSpacingRef;
966
+ /** Wide inline grouping — same magnitude as `gap.stack.lg`. */
967
+ xl: CoreSpacingRef;
968
+ }
969
+ interface SemanticSpacing {
970
+ /**
971
+ * Internal padding *inside* an element (CSS `padding`).
972
+ * Use when the spacing lives between an element's edge and its own content;
973
+ * never for the distance between siblings — that is `gap.*`.
974
+ */
975
+ inset: {
976
+ /**
977
+ * Padding inside an interactive control (button, input, chip, toggle).
978
+ * Use on elements with a hit target and a single inner content cluster.
979
+ * Pair with `inset.surface` on the containing surface; do not use for
980
+ * containing surfaces — those are `inset.surface`.
981
+ */
982
+ control: InsetSteps;
983
+ /**
984
+ * Padding inside a containing surface (card, panel, dialog, menu, section).
985
+ * Use on elements that *contain* other content blocks and need a margin
986
+ * between their edge and the inner cluster.
987
+ * Must be ≥ `inset.control` at the same step (validation rule); do not use
988
+ * for the inner controls themselves — those are `inset.control`.
989
+ */
990
+ surface: InsetSteps;
991
+ };
992
+ /**
993
+ * Distance *between* siblings (CSS `gap` on Flex/Grid containers).
994
+ * Use when laying out a sequence of sibling elements; never for internal
995
+ * padding (that is `inset.*`) and never for page/section structural padding
996
+ * (that is `gutter.*`).
997
+ */
998
+ gap: {
999
+ /**
1000
+ * Vertical rhythm between stacked siblings (column layouts, lists, form fields).
1001
+ * Use when items flow along the block axis and rhythm carries hierarchy.
1002
+ * Pair with `gap.inline` for horizontal groupings; do not use for items
1003
+ * arranged along the inline axis — those are `gap.inline`.
1004
+ */
1005
+ stack: GapStackSteps;
1006
+ /**
1007
+ * Horizontal grouping between inline siblings (icon + label, toolbar items, chip rows).
1008
+ * Use when items flow along the inline axis as a visual group.
1009
+ * `gap.inline.xs` is *visual-only* — never use it between independently
1010
+ * focusable interactive targets (use `separation.interactive.min` instead).
1011
+ */
1012
+ inline: GapInlineSteps;
1013
+ };
1014
+ /**
1015
+ * Structural outer padding for page-level and section-level layout regions.
1016
+ * `page` and `section` may use a `clamp()` expression with embedded `{token.path}` refs
1017
+ * (e.g. `clamp({core.space.4}, {core.space.6}, {core.space.12})`).
1018
+ * Typed as `RawValue` to allow both simple refs and responsive clamp expressions.
1019
+ */
1020
+ gutter: {
1021
+ /**
1022
+ * Outer padding bounding the page's content column.
1023
+ * Use as inline padding on the top-level page container.
1024
+ * Bounded `clamp()` contract by spec; do not use for inner sections — that
1025
+ * is `gutter.section`.
1026
+ */
1027
+ page: RawValue;
1028
+ /**
1029
+ * Outer padding separating a section's content from its parent's gutter.
1030
+ * Use on inner section wrappers nested inside a `gutter.page` container.
1031
+ * Bounded `clamp()` contract by spec; resolves tighter than `gutter.page`.
1032
+ */
1033
+ section: RawValue;
1034
+ };
1035
+ /**
1036
+ * Ergonomic separation between independently actionable targets in dense clusters.
1037
+ * May use a `clamp()` expression with an embedded `{token.path}` ref
1038
+ * (e.g. `clamp(8px, {core.space.2}, 12px)`).
1039
+ */
1040
+ separation: {
1041
+ interactive: {
1042
+ /**
1043
+ * Minimum gap between adjacent interactive targets (toolbar buttons,
1044
+ * paginator arrows, segmented controls, dense menu items).
1045
+ * Use only between elements the user can click/tap/focus independently.
1046
+ * Do not use for visual-only groupings — that is `gap.inline.xs`.
1047
+ */
1048
+ min: RawValue;
1049
+ };
1050
+ };
1051
+ }
1052
+ //#endregion
1053
+ //#region src/families/typography.d.ts
1054
+ interface CoreFontFamilies {
1055
+ sans: RawValue;
1056
+ mono: RawValue;
1057
+ serif?: RawValue;
1058
+ }
1059
+ interface CoreFontWeights {
1060
+ regular: NumericValue;
1061
+ medium: NumericValue;
1062
+ semibold: NumericValue;
1063
+ bold: NumericValue;
1064
+ }
1065
+ interface CoreFontLeading {
1066
+ tight: NumericValue;
1067
+ snug: NumericValue;
1068
+ normal: NumericValue;
1069
+ relaxed: NumericValue;
1070
+ }
1071
+ interface CoreFontTracking {
1072
+ tight: RawValue;
1073
+ normal: RawValue;
1074
+ wide: RawValue;
1075
+ }
1076
+ /**
1077
+ * Core font optical sizing primitives — exhaustive enumeration of the CSS
1078
+ * `font-optical-sizing` property values. Closed set by spec, not by choice.
1079
+ *
1080
+ * Mapping (token → CSS keyword):
1081
+ * - `auto` → `auto` (let the UA opt into optical sizing for variable fonts)
1082
+ * - `none` → `none` (disable optical adjustments)
1083
+ *
1084
+ * The wrapper exists to satisfy the `CoreFontRef` invariant of `TextStyle`
1085
+ * (semantic styles reference core tokens only) and to register entries in the
1086
+ * CSS variable pipeline — not to enable per-theme variation, which the CSS
1087
+ * spec does not permit.
1088
+ */
1089
+ interface CoreFontOptical {
1090
+ auto: RawValue;
1091
+ none: RawValue;
1092
+ }
1093
+ /**
1094
+ * Core font numeric variant primitives — figure shape, alignment, and special glyph
1095
+ * features exposed by the CSS `font-variant-numeric` property.
1096
+ *
1097
+ * The set covers the standalone keyword values of the CSS spec; combinations
1098
+ * (e.g. `tabular-nums slashed-zero`) are composed at the consumer site by
1099
+ * concatenating these values, not encoded as additional tokens.
1100
+ *
1101
+ * Mapping (token → CSS keyword):
1102
+ * - `proportional` → `proportional-nums` (default figure widths)
1103
+ * - `tabular` → `tabular-nums` (uniform-width figures; dashboards, tables)
1104
+ * - `lining` → `lining-nums` (cap-height figures)
1105
+ * - `oldstyle` → `oldstyle-nums` (text-figure variants for body copy)
1106
+ * - `slashedZero` → `slashed-zero` (zero disambiguation; financial/code contexts)
1107
+ * - `ordinal` → `ordinal` (1st, 2nd, 3rd ordinal markers)
1108
+ * - `normal` → `normal` (reset to UA defaults)
1109
+ *
1110
+ * The wrapper exists to satisfy the `CoreFontRef` invariant of `TextStyle`
1111
+ * (semantic styles reference core tokens only) and to register entries in the
1112
+ * CSS variable pipeline — not to enable per-theme variation of the keyword
1113
+ * values themselves, which are fixed by the CSS spec.
1114
+ */
1115
+ interface CoreFontNumeric {
1116
+ proportional: RawValue;
1117
+ tabular: RawValue;
1118
+ lining: RawValue;
1119
+ oldstyle: RawValue;
1120
+ slashedZero: RawValue;
1121
+ ordinal: RawValue;
1122
+ normal: RawValue;
1123
+ }
1124
+ type RampScale6 = Record<1 | 2 | 3 | 4 | 5 | 6, RawValue>;
1125
+ /**
1126
+ * Responsive font size scale — text and display size ramps.
1127
+ * Both ramps use `clamp()` expressions with container query units (cqi) as the
1128
+ * preferred fluid step, with viewport-safe fallbacks emitted by `toCssVars`.
1129
+ */
1130
+ interface CoreFontScale {
1131
+ /** Body text, labels, and dense UI typography */
1132
+ text: RampScale6;
1133
+ /** Headings, titles, and high-hierarchy display text */
1134
+ display: RampScale6;
1135
+ }
1136
+ /** Core font primitive set — family, weight, leading (line height), tracking (letter spacing), optical sizing, numeric variant references, and the responsive size scale. */
1137
+ interface CoreFont {
1138
+ family: CoreFontFamilies;
1139
+ weight: CoreFontWeights;
1140
+ leading: CoreFontLeading;
1141
+ tracking: CoreFontTracking;
1142
+ optical: CoreFontOptical;
1143
+ numeric: CoreFontNumeric;
1144
+ /** Responsive font size scale. @see CoreFontScale */
1145
+ scale: CoreFontScale;
1146
+ }
1147
+ /** Composite text style — groups 5–7 font token references that define a single typographic role. References core tokens only. */
1148
+ interface TextStyle {
1149
+ fontFamily: CoreFontRef;
1150
+ fontSize: CoreFontScaleRef;
1151
+ fontWeight: CoreFontRef;
1152
+ lineHeight: CoreFontRef;
1153
+ letterSpacing: CoreFontRef;
1154
+ fontOpticalSizing?: CoreFontRef;
1155
+ fontVariantNumeric?: CoreFontRef;
1156
+ }
1157
+ /**
1158
+ * Three-step size scale within a single text family.
1159
+ * Step is the *relative* hierarchy inside the family — never an absolute size.
1160
+ * Same step across families is not interchangeable: `display.md` and `body.md`
1161
+ * share only the step name, not the role.
1162
+ */
1163
+ interface TextStyleLgMdSm {
1164
+ /** Largest step of this family — strongest hierarchy *within* the family. Use for the most prominent instance of this role on the surface. */
1165
+ lg: TextStyle;
1166
+ /** Default step of this family — the unmarked choice. Use unless the surface explicitly calls for `lg` or `sm`. */
1167
+ md: TextStyle;
1168
+ /** Smallest step of this family — compact / dense usage. Use when space is constrained or when the text is secondary within the role. */
1169
+ sm: TextStyle;
1170
+ }
1171
+ /**
1172
+ * Two-step size scale (no `lg`) for families where a hero step is not meaningful.
1173
+ * @see TextStyleLgMdSm — for the rationale of step semantics.
1174
+ */
1175
+ interface TextStyleMdSm {
1176
+ /** Default step of this family — the unmarked choice. */
1177
+ md: TextStyle;
1178
+ /** Smallest step of this family — compact / dense usage. */
1179
+ sm: TextStyle;
1180
+ }
1181
+ /**
1182
+ * Semantic text styles — the only typography API consumed by components.
1183
+ *
1184
+ * Family is the typographic *role* (where in the interface this text sits);
1185
+ * step (`lg`/`md`/`sm`) is the relative size *within* the role. The pair
1186
+ * `family × step` selects one composite style; never mix `display.sm` with
1187
+ * `headline.lg` to "shrink a display" — pick the family whose role matches.
1188
+ *
1189
+ * HTML semantics (`h1…h6`, `p`, `label`) and visual style are decoupled —
1190
+ * `as="h2"` carries document structure; `text.title.md` carries appearance.
1191
+ *
1192
+ * @see typography.md — Text Families table.
1193
+ */
1194
+ interface SemanticText {
1195
+ /**
1196
+ * High-impact hero text — landing surfaces and prominent page headers.
1197
+ * Use sparingly; reserved for the single most important text on a page.
1198
+ * Pair with `headline` for the next hierarchy step; do not use for section
1199
+ * headings inside content — those are `headline`.
1200
+ */
1201
+ display: TextStyleLgMdSm;
1202
+ /**
1203
+ * Section or page headings that structure scanning of the document.
1204
+ * Use for the primary headings inside content (page title, major section breaks).
1205
+ * Below `display` in hierarchy, above `title`. Do not use for surface chrome
1206
+ * (card / panel / dialog headers) — those are `title`.
1207
+ */
1208
+ headline: TextStyleLgMdSm;
1209
+ /**
1210
+ * Titles for *surfaces* — cards, panels, dialogs, sheets, menus, structured sections.
1211
+ * Use as the heading of a contained surface, not the heading of a content section.
1212
+ * Pair with `body` / `label` inside the same surface; do not use for top-level
1213
+ * page or document headings — those are `headline` / `display`.
1214
+ */
1215
+ title: TextStyleLgMdSm;
1216
+ /**
1217
+ * Default reading text — paragraphs, descriptions, long-form content.
1218
+ * Use for any text the user will *read* rather than *scan* or *select*.
1219
+ * Optimized for readability; do not use for short UI strings or labels —
1220
+ * those are `label`.
1221
+ */
1222
+ body: TextStyleLgMdSm;
1223
+ /**
1224
+ * Short UI strings — field labels, button text, badges, metadata, captions.
1225
+ * Use for compact, scan-only text that names or describes adjacent UI.
1226
+ * Do not use for prose the user must read in sequence — that is `body`.
1227
+ */
1228
+ label: TextStyleLgMdSm;
1229
+ /**
1230
+ * Monospaced text for code snippets, logs, identifiers, or technical data.
1231
+ * Use whenever the text must align by character cell or distinguish similar
1232
+ * glyphs (`Il1O0`).
1233
+ * Do not use for UI strings that merely *look* technical — that is `body` or `label`.
1234
+ */
1235
+ code: TextStyleMdSm;
1236
+ }
1237
+ //#endregion
1238
+ //#region src/families/z-index.d.ts
1239
+ /**
1240
+ * Intent-free z-index level scale. Components must use `SemanticZIndex` — never this directly.
1241
+ * Ordering invariant (strictly ascending): `level.0 < level.1 < level.2 < level.3 < level.4`.
1242
+ * `level.0` must be ≥ 0. Adjacent levels must differ by ≥ 10.
1243
+ */
1244
+ type CoreZIndexLevels = Record<0 | 1 | 2 | 3 | 4, NumericValue>;
1245
+ interface CoreZIndex {
1246
+ level: CoreZIndexLevels;
1247
+ }
1248
+ /**
1249
+ * Stable application strata consumed by components. Top-layer browser elements
1250
+ * (modal dialogs / popovers promoted by the platform) are out of scope.
1251
+ *
1252
+ * Tokens express *cross-component layer relationships* only — never local
1253
+ * layering inside a single component, never visual depth (that is `elevation`).
1254
+ * Stratum picked must match the element's *blocking behaviour* and *persistence*,
1255
+ * not its component name (no `z.dropdown`, `z.toast`, etc.).
1256
+ */
1257
+ interface SemanticZIndex {
1258
+ layer: {
1259
+ /**
1260
+ * Page content in normal document flow.
1261
+ * Use when the element participates in the default application stratum and
1262
+ * has no claim above sibling content.
1263
+ * Do not use to "reset" stacking inside a component — local layering is
1264
+ * the component's own concern.
1265
+ */
1266
+ base: CoreZIndexRef;
1267
+ /**
1268
+ * Anchored bars that follow scroll while staying inside the app stack.
1269
+ * Use when building sticky headers, sticky navigation, or persistent
1270
+ * anchored toolbars.
1271
+ * Pair with `position: sticky`; do not use for non-anchored floating
1272
+ * surfaces — those are `overlay`.
1273
+ */
1274
+ sticky: CoreZIndexRef;
1275
+ /**
1276
+ * Non-blocking floating surfaces above sticky and base content.
1277
+ * Use when building dropdowns, menus, popovers, or floating panels that
1278
+ * the user can dismiss by interacting elsewhere.
1279
+ * Do not use for surfaces that block the page behind them — those are
1280
+ * `blocking`.
1281
+ */
1282
+ overlay: CoreZIndexRef;
1283
+ /**
1284
+ * Surfaces that sit above other overlays and prevent interaction behind them.
1285
+ * Use when building dialogs, sheets, or blocking drawers paired with a scrim.
1286
+ * Pair with `semantic.overlay.scrim` and `semantic.opacity.scrim`; do not
1287
+ * use for non-blocking floating panels — those are `overlay`.
1288
+ */
1289
+ blocking: CoreZIndexRef;
1290
+ /**
1291
+ * Highest application-controlled stratum before the browser top layer.
1292
+ * Use when building transient notifications that must surface above any
1293
+ * other app stratum (toasts, tooltip-like transient overlays).
1294
+ * Do not use for persistent UI — `transient` implies the element is
1295
+ * short-lived and self-dismissing.
1296
+ */
1297
+ transient: CoreZIndexRef;
1298
+ };
1299
+ }
1300
+ //#endregion
1301
+ //#region src/Types.d.ts
1302
+ /**
1303
+ * Full ttoss Design Tokens Theme contract.
1304
+ *
1305
+ * Two layers:
1306
+ * - `core` — raw primitives and responsive engines (immutable across modes)
1307
+ * - `semantic` — stable aliases consumed by components (remapped per mode)
1308
+ *
1309
+ * Extensions are optional properties inside `core` and `semantic`.
1310
+ * When present they follow the same `core → semantic` contract.
1311
+ */
1312
+ interface ThemeTokens {
1313
+ core: {
1314
+ colors: CoreColors;
1315
+ elevation: CoreElevation;
1316
+ font: CoreFont;
1317
+ spacing: CoreSpacingSteps;
1318
+ sizing: CoreSizing;
1319
+ radii: CoreRadii;
1320
+ border: CoreBorder;
1321
+ opacity: CoreOpacity;
1322
+ motion: CoreMotion;
1323
+ zIndex: CoreZIndex; /** Viewport threshold scale. Core-only — no semantic layer. @see CoreBreakpoints */
1324
+ breakpoints: CoreBreakpoints;
1325
+ /**
1326
+ * Data Visualization extension — analytical color palettes and non-color
1327
+ * encoding primitives. Optional: omit when the theme does not support dataviz.
1328
+ */
1329
+ dataviz?: CoreDataviz;
1330
+ };
1331
+ semantic: {
1332
+ colors: SemanticColors;
1333
+ elevation: SemanticElevation;
1334
+ text: SemanticText;
1335
+ spacing: SemanticSpacing;
1336
+ sizing: SemanticSizing;
1337
+ radii: SemanticRadii;
1338
+ border: SemanticBorder;
1339
+ focus: SemanticFocus;
1340
+ overlay: SemanticOverlay;
1341
+ opacity: SemanticOpacity;
1342
+ motion: SemanticMotion;
1343
+ zIndex: SemanticZIndex;
1344
+ /**
1345
+ * Data Visualization extension — semantic roles for analytical color,
1346
+ * non-color encodings, and geospatial overlays.
1347
+ * Optional: omit when the theme does not support dataviz.
1348
+ *
1349
+ * This is the **public API** of the dataviz extension.
1350
+ * Components consume these tokens; never `core.dataviz.*` directly.
1351
+ */
1352
+ dataviz?: SemanticDataviz;
1353
+ };
1354
+ }
1355
+ /**
1356
+ * Semantic-only overrides for the alternate color mode.
1357
+ *
1358
+ * Core tokens are immutable across modes. Only semantic token references
1359
+ * may change — remapping to different core tokens for the alternate mode.
1360
+ *
1361
+ * Uses `DeepPartial`: every nested key is optional. Omitting a key inherits
1362
+ * the value from the base theme (see `deepMerge` in `roots/helpers.ts`,
1363
+ * which treats `undefined` and absent keys identically). An alternate
1364
+ * supplies only the leaves that differ from the base.
1365
+ *
1366
+ * @see {@link modes.md} — "Modes remap semantic references, not core values."
1367
+ */
1368
+ interface ModeOverride {
1369
+ semantic: DeepPartial<ThemeTokens['semantic']>;
1370
+ }
1371
+ /**
1372
+ * A theme bundle packages a complete `ThemeTokens` (the base)
1373
+ * with an optional semantic-only override for the alternate color mode.
1374
+ *
1375
+ * - `baseMode` declares which mode the `base` theme represents.
1376
+ * - `alternate` remaps only semantic token references that differ in the
1377
+ * opposite mode. Core token values stay immutable.
1378
+ *
1379
+ * **Why only two modes?** `prefers-color-scheme` is binary (`light` / `dark`);
1380
+ * that is the only axis `ThemeBundle` addresses. High-contrast, reduced-motion,
1381
+ * and coarse-pointer are orthogonal CSS `@media` axes — they are handled by
1382
+ * the dedicated blocks emitted by `toCssVars` and are not additional modes.
1383
+ * Proposals to generalize to `Record<ModeName, ModeOverride>` conflate these
1384
+ * independent axes and should be rejected.
1385
+ *
1386
+ * When no `alternate` is provided, the theme is single-mode.
1387
+ *
1388
+ * @example
1389
+ * ```ts
1390
+ * const bundle: ThemeBundle = {
1391
+ * baseMode: 'light',
1392
+ * base: baseTheme,
1393
+ * alternate: {
1394
+ * semantic: {
1395
+ * colors: {
1396
+ * informational: { primary: { background: { default: '{core.colors.neutral.900}' } } },
1397
+ * },
1398
+ * },
1399
+ * },
1400
+ * };
1401
+ * ```
1402
+ */
1403
+ interface ThemeBundle {
1404
+ /**
1405
+ * Which color mode the `base` theme represents.
1406
+ * Constrained to `'light' | 'dark'` because `prefers-color-scheme` is binary.
1407
+ */
1408
+ baseMode: 'light' | 'dark';
1409
+ /** Complete theme for the base mode. */
1410
+ base: ThemeTokens;
1411
+ /**
1412
+ * Semantic remapping overrides for the opposite mode.
1413
+ * Only semantic references that differ need to be listed — core tokens are shared.
1414
+ */
1415
+ alternate?: ModeOverride;
1416
+ }
1417
+ /**
1418
+ * The semantic token layer of a theme. This is the **only** part of the token
1419
+ * system that components should consume — never `core.*` tokens directly.
1420
+ *
1421
+ * Obtain via `useTokens()` inside a `<ThemeProvider theme={...}>`.
1422
+ *
1423
+ * @see {@link useTokens}
1424
+ */
1425
+ type SemanticTokens = ThemeTokens['semantic'];
1426
+ //#endregion
1427
+ export { DeepPartial as a, ThemeTokens as i, SemanticTokens as n, CoreDataviz as o, ThemeBundle as r, SemanticDataviz as s, ModeOverride as t };