@kitlangton/knobs 0.4.0-next.0 → 0.4.0-next.10

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 (74) hide show
  1. package/README.md +451 -54
  2. package/dist/dev/{chunk-7xgkerd2.js → chunk-3ygqgy1x.js} +23 -1
  3. package/dist/dev/{chunk-stbcgz1y.js → chunk-5pb7ymrd.js} +567 -471
  4. package/dist/dev/{chunk-t68smqkc.js → chunk-a7cjgy8x.js} +13 -11
  5. package/dist/dev/{chunk-pmkvb9ep.js → chunk-dyq4m24m.js} +2081 -507
  6. package/dist/dev/index.js +10 -5
  7. package/dist/index.js +25 -1
  8. package/dist/panel.js +3187 -1341
  9. package/dist/react.js +294 -6
  10. package/dist/review-react.js +18580 -0
  11. package/dist/review-solid.js +18482 -0
  12. package/dist/review.js +18488 -0
  13. package/dist/solid.js +292 -4
  14. package/dist/themes.js +1767 -7
  15. package/dist/types/core/adapter.d.ts +6 -2
  16. package/dist/types/core/appearance.d.ts +44 -0
  17. package/dist/types/core/glide.d.ts +7 -0
  18. package/dist/types/core/motion.d.ts +66 -0
  19. package/dist/types/core/root.d.ts +13 -0
  20. package/dist/types/core/store.d.ts +18 -5
  21. package/dist/types/core/theme.d.ts +10 -3
  22. package/dist/types/index.d.ts +2 -1
  23. package/dist/types/panel/gpu/color.d.ts +6 -0
  24. package/dist/types/panel/motion.d.ts +1 -1
  25. package/dist/types/panel/styles.d.ts +2 -3
  26. package/dist/types/review/font.d.ts +13 -0
  27. package/dist/types/review/foundations.d.ts +175 -0
  28. package/dist/types/review/index.d.ts +13 -0
  29. package/dist/types/review/react.d.ts +1 -0
  30. package/dist/types/review/solid.d.ts +1 -0
  31. package/dist/types/themes/define.d.ts +104 -0
  32. package/dist/types/themes/index.d.ts +16 -0
  33. package/dist/types/themes/knobs.d.ts +5 -0
  34. package/dist/types/themes/review.d.ts +8 -0
  35. package/dist/types/themes/void.d.ts +8 -0
  36. package/dist/types/tokens/color.d.ts +42 -0
  37. package/dist/types/tokens/css.d.ts +13 -0
  38. package/dist/types/tokens/evaluate.d.ts +8 -0
  39. package/dist/types/tokens/index.d.ts +4 -0
  40. package/dist/types/tokens/schema.d.ts +1280 -0
  41. package/dist/types/ui/bento-css.d.ts +1 -1
  42. package/dist/types/ui/compare-css.d.ts +1 -1
  43. package/dist/types/ui/compare-gpu.d.ts +6 -6
  44. package/dist/types/ui/compare-model.d.ts +85 -2
  45. package/dist/types/ui/compare.d.ts +18 -4
  46. package/dist/types/ui/diff.d.ts +4 -5
  47. package/dist/types/ui/history-css.d.ts +1 -0
  48. package/dist/types/ui/history-model.d.ts +249 -0
  49. package/dist/types/ui/history.d.ts +38 -0
  50. package/dist/types/ui/icons.d.ts +40 -0
  51. package/dist/types/ui/index.d.ts +9 -5
  52. package/dist/types/ui/look.d.ts +18 -13
  53. package/dist/types/ui/overlay-css.d.ts +1 -1
  54. package/dist/types/ui/player-css.d.ts +1 -0
  55. package/dist/types/ui/player.d.ts +51 -0
  56. package/dist/types/ui/readout-css.d.ts +1 -1
  57. package/dist/types/ui/readout-model.d.ts +5 -1
  58. package/dist/types/ui/review-look.d.ts +6 -0
  59. package/dist/types/ui/review-options.d.ts +28 -0
  60. package/dist/types/ui/rgba.d.ts +11 -0
  61. package/dist/types/ui/selection-pill-css.d.ts +1 -0
  62. package/dist/types/ui/selection-pill.d.ts +106 -0
  63. package/dist/types/ui/timeline-model.d.ts +27 -0
  64. package/dist/types/ui/timeline.d.ts +16 -1
  65. package/dist/types/ui/tree.d.ts +3 -2
  66. package/dist/types/ui/walkthrough-annotations.d.ts +42 -0
  67. package/dist/types/ui/walkthrough-blocks.d.ts +87 -0
  68. package/dist/types/ui/walkthrough-media.d.ts +30 -1
  69. package/dist/types/ui/walkthrough-model.d.ts +469 -5
  70. package/dist/types/ui/walkthrough.d.ts +27 -5
  71. package/dist/ui-react.js +8087 -2350
  72. package/dist/ui-solid.js +8100 -2363
  73. package/dist/ui.js +9751 -3963
  74. package/package.json +13 -1
@@ -2,10 +2,203 @@ import {
2
2
  isTypingTarget,
3
3
  GRADIENT_SAMPLES,
4
4
  Spring,
5
+ springMotion2,
5
6
  springEasing,
6
7
  springCss2,
8
+ SPRINGS2,
9
+ springLinear,
10
+ DEFAULT_LINEAR,
11
+ motionCss,
7
12
  storageKey
8
- } from "./chunk-7xgkerd2.js";
13
+ } from "./chunk-3ygqgy1x.js";
14
+
15
+ // src/core/theme.ts
16
+ var property = (k) => k.startsWith("--") ? k : `--k-${k}`;
17
+ function presetCss(preset) {
18
+ if (!/^[\w-]+$/.test(preset.name))
19
+ throw Error(`Invalid preset name: ${preset.name}`);
20
+ let at = `.knobs-root[data-preset="${preset.name}"]`, light = preset.light ?? {}, decls = Object.entries(preset.dark).map(([k, dark]) => {
21
+ let l = light[k];
22
+ return l === void 0 || String(l) === String(dark) ? `${property(k)}:${dark}` : `${property(k)}:light-dark(${l},${dark})`;
23
+ });
24
+ for (let [k, l] of Object.entries(light))
25
+ if (!(k in preset.dark) && k !== "color-scheme")
26
+ decls.push(`${property(k)}:${l}`);
27
+ return `${at}{${decls.join(";")}}${(preset.css ?? "").replaceAll("&", at)}`;
28
+ }
29
+ var glide = /* @__PURE__ */ springCss2({ duration: 0.185, bounce: 0.14 });
30
+ var problemsPreset = {
31
+ name: "problems",
32
+ dark: {
33
+ bg: "#161618",
34
+ surface: "rgba(255,255,255,.055)",
35
+ "surface-hi": "rgba(255,255,255,.11)",
36
+ line: "rgba(255,255,255,.075)",
37
+ "line-hi": "rgba(255,255,255,.12)",
38
+ text: "#f5f5f7",
39
+ label: "rgba(235,235,245,.62)",
40
+ dim: "rgba(235,235,245,.36)",
41
+ accent: "#0091ff",
42
+ modified: "#0091ff",
43
+ "seg-bg": "rgba(120,120,128,.16)",
44
+ "seg-active": "rgba(120,120,128,.24)",
45
+ "toggle-track": "rgba(120,120,128,.32)",
46
+ "toggle-thumb": "#fff",
47
+ rim: "transparent",
48
+ font: 'system-ui,-apple-system,BlinkMacSystemFont,"Helvetica Neue",sans-serif',
49
+ mono: '"Kit SF Mono",ui-monospace,Menlo,monospace',
50
+ "font-size": "13px",
51
+ "label-weight": 500,
52
+ row: "34px",
53
+ radius: "8px",
54
+ "panel-radius": "12px",
55
+ pad: "0px",
56
+ inset: "10px",
57
+ gap: "4px",
58
+ "row-gap": "4px",
59
+ glass: 0,
60
+ glow: 0,
61
+ blur: 0.6,
62
+ "hover-in": 0,
63
+ "hover-out": 100,
64
+ "handle-rest": 0.55,
65
+ handle: "var(--k-text)",
66
+ "handle-inset": "7.5px",
67
+ "fill-base": "transparent",
68
+ "fill-rest-mix": "24%",
69
+ "fill-hover-mix": "36%",
70
+ "fill-active-mix": "36%",
71
+ chrome: 0,
72
+ "group-transform": "none",
73
+ "value-font": "var(--k-mono)",
74
+ "unit-gap": "0px",
75
+ "unit-color": "currentColor",
76
+ "readout-mark": 1,
77
+ "group-size": "12px",
78
+ "group-color": "rgba(235,235,245,.62)",
79
+ "group-inset": "0px",
80
+ "group-tracking": "-.01em",
81
+ "group-divider": "rgba(255,255,255,.075)",
82
+ "group-divider-gap": "8px",
83
+ "curve-inset": "0px",
84
+ "curve-guide": "dashed",
85
+ "curve-dot": 0,
86
+ spring: "0.185 0.14",
87
+ "fill-ease": glide.easing,
88
+ "fill-ms": glide.duration
89
+ },
90
+ light: {
91
+ bg: "#fff",
92
+ surface: "rgba(0,0,0,.045)",
93
+ "surface-hi": "rgba(0,0,0,.09)",
94
+ line: "rgba(0,0,0,.07)",
95
+ "line-hi": "rgba(0,0,0,.11)",
96
+ text: "#000",
97
+ label: "rgba(60,60,67,.66)",
98
+ dim: "rgba(60,60,67,.38)",
99
+ accent: "#0088ff",
100
+ modified: "#0088ff",
101
+ "seg-bg": "rgba(120,120,128,.11)",
102
+ "seg-active": "#fff",
103
+ "toggle-track": "rgba(120,120,128,.2)",
104
+ "toggle-thumb": "#fff",
105
+ rim: "transparent",
106
+ "group-color": "rgba(60,60,67,.66)",
107
+ "group-divider": "rgba(0,0,0,.07)"
108
+ }
109
+ };
110
+
111
+ // src/core/appearance.ts
112
+ var MODES = {
113
+ dark: "dark",
114
+ light: "light",
115
+ auto: "system"
116
+ };
117
+ function resolveLook(options = {}, base) {
118
+ let t = options.theme, mode = typeof t === "string" ? MODES[t] : void 0, theme = typeof t === "object" ? t : base?.theme, preset = options.preset ?? base?.preset;
119
+ return {
120
+ ...theme ? { theme } : {},
121
+ appearance: options.appearance ?? mode ?? base?.appearance ?? "inherit",
122
+ ...preset ? { preset } : {}
123
+ };
124
+ }
125
+ var themes = /* @__PURE__ */ new Map;
126
+ function themeOf(el) {
127
+ let name = el.closest("[data-knobs-theme]")?.dataset.knobsTheme;
128
+ return name ? themes.get(name) : void 0;
129
+ }
130
+ var themeSelector = (name) => `:where(.knobs-root)[data-knobs-theme="${name}"]`;
131
+ function upsertStyle(doc, key, value, content) {
132
+ let existing = doc.querySelector(`style[${key}="${value}"]`);
133
+ if (existing) {
134
+ if (existing.textContent !== content)
135
+ existing.textContent = content;
136
+ return;
137
+ }
138
+ let style = doc.createElement("style");
139
+ style.setAttribute(key, value), style.textContent = content, doc.head.append(style);
140
+ }
141
+ function injectTheme(doc, theme) {
142
+ themes.set(theme.name, theme), upsertStyle(doc, "data-knobs-theme-css", theme.name, theme.css({ selector: themeSelector(theme.name) }));
143
+ }
144
+ var presets = /* @__PURE__ */ new Map;
145
+ function injectPreset(doc, preset) {
146
+ presets.set(preset.name, preset), upsertStyle(doc, "data-knobs-preset", preset.name, presetCss(preset));
147
+ }
148
+ var setAttr = (el, name, value) => {
149
+ if (value === void 0)
150
+ el.removeAttribute(name);
151
+ else if (el.getAttribute(name) !== value)
152
+ el.setAttribute(name, value);
153
+ };
154
+ function applyLook(el, look) {
155
+ let doc = el.ownerDocument;
156
+ if (look.theme)
157
+ injectTheme(doc, look.theme);
158
+ if (look.preset)
159
+ injectPreset(doc, look.preset);
160
+ if (setAttr(el, "data-knobs-theme", look.theme?.name), setAttr(el, "data-preset", look.preset?.name), setAttr(el, "data-appearance", look.appearance === "inherit" ? void 0 : look.appearance), look.appearance === "inherit")
161
+ followPage(el);
162
+ else
163
+ clearInherited(el);
164
+ }
165
+ var clearInherited = (el) => {
166
+ el.style.removeProperty("color-scheme"), el.style.removeProperty("--_k-light");
167
+ };
168
+ function resolveInherited(el) {
169
+ let parent = el.parentElement, win = el.ownerDocument.defaultView;
170
+ if (!parent || !win || el.hasAttribute("data-appearance"))
171
+ return;
172
+ if (parent.closest(".knobs-root"))
173
+ return clearInherited(el);
174
+ let scheme = win.getComputedStyle(parent).colorScheme.trim(), dark = /\bdark\b/.test(scheme), light = /\blight\b/.test(scheme);
175
+ if (!dark && !light)
176
+ return clearInherited(el);
177
+ let isLight = dark && light ? win.matchMedia?.("(prefers-color-scheme: light)").matches ?? !1 : light;
178
+ el.style.setProperty("color-scheme", "inherit"), el.style.setProperty("--_k-light", isLight ? "1" : "0");
179
+ }
180
+ var watched = /* @__PURE__ */ new WeakSet;
181
+ function followPage(el) {
182
+ let doc = el.ownerDocument, win = doc.defaultView;
183
+ if (!win)
184
+ return;
185
+ let run = () => resolveInherited(el);
186
+ if (el.isConnected)
187
+ run();
188
+ if (queueMicrotask(run), win.requestAnimationFrame?.(run), watched.has(doc))
189
+ return;
190
+ watched.add(doc);
191
+ let all = () => {
192
+ for (let root of doc.querySelectorAll(".knobs-root:not([data-appearance])"))
193
+ resolveInherited(root);
194
+ }, observer = new MutationObserver(all), attributeFilter = ["class", "data-theme", "data-appearance"];
195
+ if (observer.observe(doc.documentElement, { attributes: !0, attributeFilter }), doc.body)
196
+ observer.observe(doc.body, { attributes: !0, attributeFilter });
197
+ win.matchMedia?.("(prefers-color-scheme: light)").addEventListener?.("change", all);
198
+ }
199
+
200
+ // src/core/adapter.ts
201
+ var panelLook = (controls, look = {}) => resolveLook(look, resolveLook({ theme: controls.theme, appearance: controls.appearance }));
9
202
 
10
203
  // src/panel/icons.ts
11
204
  var ICONS = {
@@ -162,99 +355,8 @@ var rolling_css_default = `.rn-root {
162
355
  .rn-solid:not([data-rn-hydrated]) > .rn-mount { display: none; }
163
356
  `;
164
357
 
165
- // src/core/theme.ts
166
- var block = (tokens) => Object.entries(tokens).map(([k, v]) => `${k.startsWith("--") || k === "color-scheme" ? k : `--k-${k}`}:${v}`).join(";");
167
- function presetCss(preset) {
168
- if (!/^[\w-]+$/.test(preset.name))
169
- throw Error(`Invalid preset name: ${preset.name}`);
170
- let at = `.knobs-panel[data-preset="${preset.name}"]`, light = preset.light ? `:where(.knobs-panel)[data-preset="${preset.name}"][data-theme="light"],:where([data-knobs-theme="light"]) ${at}:not([data-theme="dark"]),:where(:root[data-theme="light"]) ${at}[data-theme="auto"]{${block(preset.light)}}@media(prefers-color-scheme:light){:where(:root:not([data-theme="dark"])) ${at}[data-theme="auto"]{${block(preset.light)}}}` : "";
171
- return `${at}{${block(preset.dark)}}${light}${(preset.css ?? "").replaceAll("&", at)}`;
172
- }
173
- var glide = /* @__PURE__ */ springCss2({ duration: 0.185, bounce: 0.14 });
174
- var problemsPreset = {
175
- name: "problems",
176
- dark: {
177
- bg: "#161618",
178
- surface: "rgba(255,255,255,.055)",
179
- "surface-hi": "rgba(255,255,255,.11)",
180
- line: "rgba(255,255,255,.075)",
181
- "line-hi": "rgba(255,255,255,.12)",
182
- text: "#f5f5f7",
183
- label: "rgba(235,235,245,.62)",
184
- dim: "rgba(235,235,245,.36)",
185
- accent: "#0091ff",
186
- modified: "#0091ff",
187
- "seg-bg": "rgba(120,120,128,.16)",
188
- "seg-active": "rgba(120,120,128,.24)",
189
- "toggle-track": "rgba(120,120,128,.32)",
190
- "toggle-thumb": "#fff",
191
- rim: "transparent",
192
- font: 'system-ui,-apple-system,BlinkMacSystemFont,"Helvetica Neue",sans-serif',
193
- mono: '"Kit SF Mono",ui-monospace,Menlo,monospace',
194
- "font-size": "13px",
195
- "label-weight": 500,
196
- row: "34px",
197
- radius: "8px",
198
- "panel-radius": "12px",
199
- pad: "0px",
200
- inset: "10px",
201
- gap: "4px",
202
- "row-gap": "4px",
203
- glass: 0,
204
- glow: 0,
205
- blur: 0.6,
206
- "hover-in": 0,
207
- "hover-out": 100,
208
- "handle-rest": 0.55,
209
- handle: "var(--k-text)",
210
- "handle-inset": "7.5px",
211
- "fill-base": "transparent",
212
- "fill-rest-mix": "24%",
213
- "fill-hover-mix": "36%",
214
- "fill-active-mix": "36%",
215
- chrome: 0,
216
- "group-transform": "none",
217
- "value-font": "var(--k-mono)",
218
- "unit-gap": "0px",
219
- "unit-color": "currentColor",
220
- "readout-mark": 1,
221
- "group-size": "12px",
222
- "group-color": "rgba(235,235,245,.62)",
223
- "group-inset": "0px",
224
- "group-tracking": "-.01em",
225
- "group-divider": "rgba(255,255,255,.075)",
226
- "group-divider-gap": "8px",
227
- "curve-inset": "0px",
228
- "curve-guide": "dashed",
229
- "curve-dot": 0,
230
- spring: "0.185 0.14",
231
- "fill-ease": glide.easing,
232
- "fill-ms": glide.duration
233
- },
234
- light: {
235
- bg: "#fff",
236
- surface: "rgba(0,0,0,.045)",
237
- "surface-hi": "rgba(0,0,0,.09)",
238
- line: "rgba(0,0,0,.07)",
239
- "line-hi": "rgba(0,0,0,.11)",
240
- text: "#000",
241
- label: "rgba(60,60,67,.66)",
242
- dim: "rgba(60,60,67,.38)",
243
- accent: "#0088ff",
244
- modified: "#0088ff",
245
- "seg-bg": "rgba(120,120,128,.11)",
246
- "seg-active": "#fff",
247
- "toggle-track": "rgba(120,120,128,.2)",
248
- "toggle-thumb": "#fff",
249
- rim: "transparent",
250
- "group-color": "rgba(60,60,67,.66)",
251
- "group-divider": "rgba(0,0,0,.07)",
252
- "color-scheme": "light"
253
- }
254
- };
255
-
256
358
  // src/panel/motion.ts
257
- var FILL = { omega: 30, zeta: 0.88 };
359
+ var FILL = springMotion2(SPRINGS2.default);
258
360
  var LEAD = { omega: 34, zeta: 0.86 }, TRAIL = { omega: 25, zeta: 1 }, trailScale = (blur) => 0.6 + 0.4 * clamp(blur, 0, 2);
259
361
 
260
362
  class Edges {
@@ -560,7 +662,7 @@ function digitHints(count, showing) {
560
662
  }
561
663
 
562
664
  // src/panel/crumbs.ts
563
- var glide2 = springEasing(2 * Math.PI / 0.3, 1), CRUMB_GLIDE = `${glide2.ms}ms ${glide2.easing}`, SLIDE = 5, GAP = 6, HINT_GAP = 10, SEP = "›";
665
+ var glide2 = springLinear(SPRINGS2.default), CRUMB_GLIDE = `${glide2.ms}ms ${glide2.easing}`, SLIDE = 5, GAP = 6, HINT_GAP = 10, SEP = "›";
564
666
  function createCrumbs(o) {
565
667
  let doc = o.header.ownerDocument, element = doc.createElement("div");
566
668
  element.className = "knobs-crumbs", element.setAttribute("aria-hidden", "true"), o.header.append(element);
@@ -673,38 +775,1549 @@ function createCrumbs(o) {
673
775
  };
674
776
  }
675
777
 
676
- // src/panel/styles.ts
677
- var lead = springEasing(LEAD.omega, LEAD.zeta), trail = springEasing(TRAIL.omega, TRAIL.zeta), fill = springEasing(FILL.omega, FILL.zeta), LEAD_T = `${lead.ms}ms var(--k-lead)`, TRAIL_T = `calc(${trail.ms}ms * (.6 + .4 * clamp(0, var(--k-blur), 2))) var(--k-trail)`, FILL_T = "calc(var(--k-fill-ms) * 1ms * clamp(var(--k-blur),.1,2)) var(--k-fill-ease)", SLIDE_T = "calc(var(--k-fill-ms) * 1ms) var(--k-fill-ease)", snappy = springEasing(2 * Math.PI / 0.25, 1), snappyOut = springEasing(2 * Math.PI / 0.2, 1), BLOOM_IN = `${snappy.ms}ms ${snappy.easing}`, BLOOM_OUT = `${snappyOut.ms}ms ${snappyOut.easing}`, DELAY = "var(--k-delay,0ms)", armed = springEasing(2 * Math.PI / 0.3, 1), ARMED_T = `${armed.ms}ms ${armed.easing}`, POINTER_ROW = ".knobs-panel[data-k-row-hover]:not([data-keyboard])", DELAYED = ".knobs-fill,.knobs-handle,.knobs-seg-pill,.knobs-toggle,.knobs-toggle i,.knobs-arm,.knobs-curve,.knobs-swatch,.knobs-strip-thumb,.knobs-pad>i,.knobs-ease-handle,.knobs-range-track,.knobs-range-fill,.knobs-range-thumb,.knobs-dial-hand,.knobs-grad,.knobs-grad-mini,.knobs-grad-mini>i,.knobs-grad-stop,.knobs-graph-pt", GRAD_N = GRADIENT_SAMPLES, gradStops = (at) => Array.from({ length: GRAD_N }, (_, i) => `var(--kgrad-${i}) ${at(i)}`).join(","), GRAD_STRIP = `linear-gradient(to right,${gradStops((i) => `calc(var(--kg-r) + (100% - var(--kg-r) * 2) * ${Number((i / (GRAD_N - 1)).toFixed(5))})`)})`, GRAD_MINI = `linear-gradient(to right,${gradStops((i) => `${Number((i / (GRAD_N - 1) * 100).toFixed(3))}%`)})`, GRAD_PROPS = Array.from({ length: GRAD_N }, (_, i) => `@property --kgrad-${i}{syntax:"<color>";inherits:false;initial-value:transparent}`).join(`
678
- `), COLOR_TOKENS = [
778
+ // src/tokens/color.ts
779
+ var clamp01 = (x) => Math.min(1, Math.max(0, x)), toLinear = (c) => c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4, toGamma = (c) => c <= 0.0031308 ? 12.92 * c : 1.055 * c ** 0.4166666666666667 - 0.055;
780
+ function linearToOklch([r, g, b, a]) {
781
+ let l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b), m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b), s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b), L = 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s, A = 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s, B = 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s, c = Math.hypot(A, B), h = c < 0.0000001 ? 0 : (Math.atan2(B, A) * 180 / Math.PI + 360) % 360;
782
+ return { l: L, c, h, alpha: a };
783
+ }
784
+ function oklchToLinear({ l: L, c, h, alpha = 1 }) {
785
+ let hr = h * Math.PI / 180, A = c * Math.cos(hr), B = c * Math.sin(hr), l = (L + 0.3963377774 * A + 0.2158037573 * B) ** 3, m = (L - 0.1055613458 * A - 0.0638541728 * B) ** 3, s = (L - 0.0894841775 * A - 1.291485548 * B) ** 3;
786
+ return [
787
+ 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,
788
+ -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,
789
+ -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s,
790
+ alpha
791
+ ];
792
+ }
793
+ var inGamut = ([r, g, b]) => [r, g, b].every((x) => x >= -0.00001 && x <= 1.00001);
794
+ function oklchToLinearInGamut(color) {
795
+ let rgb = oklchToLinear(color);
796
+ if (inGamut(rgb))
797
+ return clampRgba(rgb);
798
+ let lo = 0, hi = color.c;
799
+ for (let i = 0;i < 24; i++) {
800
+ let mid = (lo + hi) / 2;
801
+ if (rgb = oklchToLinear({ ...color, c: mid }), inGamut(rgb))
802
+ lo = mid;
803
+ else
804
+ hi = mid;
805
+ }
806
+ return clampRgba(oklchToLinear({ ...color, c: lo }));
807
+ }
808
+ var clampRgba = ([r, g, b, a]) => [clamp01(r), clamp01(g), clamp01(b), clamp01(a)];
809
+ function parseColor(input) {
810
+ let s = input.trim().toLowerCase();
811
+ if (s === "transparent")
812
+ return [0, 0, 0, 0];
813
+ if (s.startsWith("#")) {
814
+ let hex = s.slice(1);
815
+ if (hex.length === 3 || hex.length === 4)
816
+ hex = [...hex].map((ch) => ch + ch).join("");
817
+ if (!/^[0-9a-f]{6}([0-9a-f]{2})?$/.test(hex))
818
+ throw Error(`Invalid colour: ${input}`);
819
+ let n = (i) => Number.parseInt(hex.slice(i, i + 2), 16) / 255;
820
+ return [toLinear(n(0)), toLinear(n(2)), toLinear(n(4)), hex.length === 8 ? n(6) : 1];
821
+ }
822
+ let fn = /^(oklch|rgba?)\(([^)]*)\)$/.exec(s);
823
+ if (!fn)
824
+ throw Error(`Unsupported colour: ${input}`);
825
+ let parts = fn[2].split(/[\s,/]+/).filter(Boolean), num = (p, scale) => p === void 0 ? 1 : p.endsWith("%") ? Number.parseFloat(p) / 100 : Number.parseFloat(p) / scale;
826
+ if (fn[1] === "oklch") {
827
+ let l = num(parts[0], 1);
828
+ return oklchToLinearInGamut({
829
+ l,
830
+ c: Number.parseFloat(parts[1]),
831
+ h: Number.parseFloat(parts[2]),
832
+ alpha: num(parts[3], 1)
833
+ });
834
+ }
835
+ return [
836
+ toLinear(num(parts[0], 255)),
837
+ toLinear(num(parts[1], 255)),
838
+ toLinear(num(parts[2], 255)),
839
+ num(parts[3], 1)
840
+ ];
841
+ }
842
+ var toOklch = (input) => linearToOklch(parseColor(input)), byte = (c) => Math.round(clamp01(c) * 255).toString(16).padStart(2, "0");
843
+ function formatHex([r, g, b, a]) {
844
+ let rgb = `#${byte(toGamma(r))}${byte(toGamma(g))}${byte(toGamma(b))}`;
845
+ return a >= 0.9995 ? rgb : rgb + byte(a);
846
+ }
847
+ var oklchToHex = (color) => formatHex(oklchToLinearInGamut(color)), normalize = (input) => formatHex(parseColor(input));
848
+ function withAlpha(input, alpha) {
849
+ let [r, g, b, a] = parseColor(input);
850
+ return formatHex([r, g, b, a * alpha]);
851
+ }
852
+ function over(top, bottom) {
853
+ let t = parseColor(top), b = parseColor(bottom), a = t[3], mix = (i) => toLinear(toGamma(t[i]) * a + toGamma(b[i]) * (1 - a));
854
+ return formatHex([mix(0), mix(1), mix(2), 1]);
855
+ }
856
+ function apcaY(input) {
857
+ let [r, g, b] = parseColor(input).map(toGamma);
858
+ return 0.2126729 * r ** 2.4 + 0.7151522 * g ** 2.4 + 0.072175 * b ** 2.4;
859
+ }
860
+ function apca(text, background) {
861
+ let bgOpaque = parseColor(background)[3] < 1 ? over(background, "#000") : background, fg = parseColor(text)[3] < 1 ? over(text, bgOpaque) : text, soft = (y) => y > 0.022 ? y : y + (0.022 - y) ** 1.414, yt = soft(apcaY(fg)), yb = soft(apcaY(bgOpaque));
862
+ if (Math.abs(yb - yt) < 0.0005)
863
+ return 0;
864
+ if (yb > yt) {
865
+ let sapc = (yb ** 0.56 - yt ** 0.57) * 1.14;
866
+ return sapc < 0.1 ? 0 : (sapc - 0.027) * 100;
867
+ }
868
+ let sapc = (yb ** 0.65 - yt ** 0.62) * 1.14;
869
+ return sapc > -0.1 ? 0 : -(sapc + 0.027) * 100;
870
+ }
871
+
872
+ // src/tokens/schema.ts
873
+ var theme = { from: "theme" }, css = (s) => ({ css: s }), value = (s) => ({ value: s }), alpha = (pct, of = "var(--k-fg)") => `color-mix(in oklch,${of} calc(${pct}% * var(--k-contrast)),transparent)`, TOKENS = [
874
+ {
875
+ name: "accent",
876
+ tier: "input",
877
+ type: "color",
878
+ group: "Accent",
879
+ source: theme,
880
+ doc: "The one accent: primary actions, handles, focus. Hover, soft and selection derive from it in CSS.",
881
+ deprecated: ["--ku-accent"]
882
+ },
883
+ {
884
+ name: "contrast",
885
+ tier: "input",
886
+ type: "number",
887
+ group: "Inputs",
888
+ source: theme,
889
+ doc: "Contrast multiplier for fills and alpha borders (1 = default; the theme's 0–100 dial maps 50 → 1)."
890
+ },
891
+ {
892
+ name: "radius",
893
+ tier: "input",
894
+ type: "length",
895
+ group: "Shape",
896
+ source: theme,
897
+ doc: "Control corner radius. 0 squares everything, including capsules. Scales with density.",
898
+ deprecated: ["--ku-radius"],
899
+ resolve: "round(calc($ * (1 + (var(--_k-density) - 1) * 1.5)),2px)"
900
+ },
901
+ {
902
+ name: "density",
903
+ tier: "input",
904
+ type: "number",
905
+ group: "Size",
906
+ source: theme,
907
+ doc: "Size multiplier: compact .875, default 1, comfortable 1.1875."
908
+ },
909
+ {
910
+ name: "font",
911
+ tier: "input",
912
+ type: "font",
913
+ group: "Type",
914
+ source: theme,
915
+ doc: "UI font stack.",
916
+ deprecated: ["--ku-font"]
917
+ },
918
+ {
919
+ name: "mono",
920
+ tier: "input",
921
+ type: "font",
922
+ group: "Type",
923
+ source: theme,
924
+ doc: "Monospace font stack.",
925
+ deprecated: ["--ku-mono"]
926
+ },
927
+ {
928
+ name: "bg-page",
929
+ tier: "semantic",
930
+ type: "color",
931
+ group: "Surfaces",
932
+ source: theme,
933
+ doc: "The page behind panels; workspace backdrops.",
934
+ deprecated: ["--k-page", "--ku-page"]
935
+ },
936
+ {
937
+ name: "bg-inset",
938
+ tier: "semantic",
939
+ type: "color",
940
+ group: "Surfaces",
941
+ source: theme,
942
+ doc: "Wells sunk into a panel: tracks, inputs, segmented backgrounds."
943
+ },
944
+ {
945
+ name: "bg",
946
+ tier: "semantic",
947
+ type: "color",
948
+ group: "Surfaces",
949
+ source: theme,
950
+ doc: "The panel surface.",
951
+ deprecated: ["--ku-bg"]
952
+ },
953
+ {
954
+ name: "bg-raised",
955
+ tier: "semantic",
956
+ type: "color",
957
+ group: "Surfaces",
958
+ source: theme,
959
+ doc: "Raised within a panel: the active segment, cards on a panel."
960
+ },
961
+ {
962
+ name: "bg-overlay",
963
+ tier: "semantic",
964
+ type: "color",
965
+ group: "Surfaces",
966
+ source: theme,
967
+ doc: "Floating surfaces: menus, popovers, tooltips."
968
+ },
969
+ {
970
+ name: "fill",
971
+ tier: "semantic",
972
+ type: "color",
973
+ group: "Fills",
974
+ source: css(alpha(5.5)),
975
+ doc: "Resting fill for controls.",
976
+ deprecated: ["--k-surface", "--ku-surface"]
977
+ },
978
+ {
979
+ name: "fill-hover",
980
+ tier: "semantic",
981
+ type: "color",
982
+ group: "Fills",
983
+ source: css(alpha(8)),
984
+ doc: "Hovered fill."
985
+ },
986
+ {
987
+ name: "fill-selected",
988
+ tier: "semantic",
989
+ type: "color",
990
+ group: "Fills",
991
+ source: css(alpha(11)),
992
+ doc: "Pressed or selected fill.",
993
+ deprecated: ["--k-surface-hi", "--ku-surface-hi"]
994
+ },
995
+ {
996
+ name: "fg",
997
+ tier: "semantic",
998
+ type: "color",
999
+ group: "Foreground",
1000
+ source: theme,
1001
+ doc: "Primary text and icons (≥ Lc 90 on bg).",
1002
+ deprecated: ["--k-text", "--ku-text"]
1003
+ },
1004
+ {
1005
+ name: "fg-2",
1006
+ tier: "semantic",
1007
+ type: "color",
1008
+ group: "Foreground",
1009
+ source: theme,
1010
+ doc: "Secondary text: labels (≥ Lc 75).",
1011
+ deprecated: ["--k-label", "--ku-label"]
1012
+ },
1013
+ {
1014
+ name: "fg-3",
1015
+ tier: "semantic",
1016
+ type: "color",
1017
+ group: "Foreground",
1018
+ source: theme,
1019
+ doc: "Tertiary text: metadata, units, captions (≥ Lc 45).",
1020
+ deprecated: ["--k-dim", "--ku-dim"]
1021
+ },
1022
+ {
1023
+ name: "fg-4",
1024
+ tier: "semantic",
1025
+ type: "color",
1026
+ group: "Foreground",
1027
+ source: theme,
1028
+ doc: "Placeholder and disabled text (≥ Lc 30)."
1029
+ },
1030
+ {
1031
+ name: "border-subtle",
1032
+ tier: "semantic",
1033
+ type: "color",
1034
+ group: "Borders",
1035
+ source: css(alpha(6)),
1036
+ doc: "Hairline edges and dividers (below Lc 15 by design).",
1037
+ deprecated: ["--k-edge"]
1038
+ },
1039
+ {
1040
+ name: "border",
1041
+ tier: "semantic",
1042
+ type: "color",
1043
+ group: "Borders",
1044
+ source: css(alpha(10)),
1045
+ doc: "Default borders.",
1046
+ deprecated: ["--k-line", "--ku-line"]
1047
+ },
1048
+ {
1049
+ name: "border-strong",
1050
+ tier: "semantic",
1051
+ type: "color",
1052
+ group: "Borders",
1053
+ source: theme,
1054
+ doc: "Interactive edges (≥ Lc 15; solid).",
1055
+ deprecated: ["--k-line-hi", "--ku-line-hi"]
1056
+ },
1057
+ {
1058
+ name: "accent-hover",
1059
+ tier: "semantic",
1060
+ type: "color",
1061
+ group: "Accent",
1062
+ source: css("color-mix(in oklch,var(--k-accent) 90%,var(--k-bg))"),
1063
+ doc: "Hovered accent."
1064
+ },
1065
+ {
1066
+ name: "accent-soft",
1067
+ tier: "semantic",
1068
+ type: "color",
1069
+ group: "Accent",
1070
+ source: css("color-mix(in oklch,var(--k-accent) 15%,transparent)"),
1071
+ doc: "Accent tint behind accent content."
1072
+ },
1073
+ {
1074
+ name: "accent-fg",
1075
+ tier: "semantic",
1076
+ type: "color",
1077
+ group: "Accent",
1078
+ source: theme,
1079
+ doc: "Accent as text on bg (≥ Lc 60)."
1080
+ },
1081
+ {
1082
+ name: "on-accent",
1083
+ tier: "semantic",
1084
+ type: "color",
1085
+ group: "Accent",
1086
+ source: theme,
1087
+ doc: "Content placed on a solid accent."
1088
+ },
1089
+ { name: "ok", tier: "semantic", type: "color", group: "Status", source: theme, doc: "Success." },
1090
+ {
1091
+ name: "warn",
1092
+ tier: "semantic",
1093
+ type: "color",
1094
+ group: "Status",
1095
+ source: theme,
1096
+ doc: "Warning.",
1097
+ deprecated: ["--ku-warn"]
1098
+ },
1099
+ {
1100
+ name: "danger",
1101
+ tier: "semantic",
1102
+ type: "color",
1103
+ group: "Status",
1104
+ source: theme,
1105
+ doc: "Error, destructive. Put text on danger-soft rather than bare bg.",
1106
+ deprecated: ["--k-critical", "--ku-critical"]
1107
+ },
1108
+ {
1109
+ name: "info",
1110
+ tier: "semantic",
1111
+ type: "color",
1112
+ group: "Status",
1113
+ source: theme,
1114
+ doc: "Informational."
1115
+ },
1116
+ {
1117
+ name: "ok-soft",
1118
+ tier: "semantic",
1119
+ type: "color",
1120
+ group: "Status",
1121
+ source: css("color-mix(in oklch,var(--k-ok) 15%,transparent)"),
1122
+ doc: "Success tint."
1123
+ },
1124
+ {
1125
+ name: "warn-soft",
1126
+ tier: "semantic",
1127
+ type: "color",
1128
+ group: "Status",
1129
+ source: css("color-mix(in oklch,var(--k-warn) 15%,transparent)"),
1130
+ doc: "Warning tint."
1131
+ },
1132
+ {
1133
+ name: "danger-soft",
1134
+ tier: "semantic",
1135
+ type: "color",
1136
+ group: "Status",
1137
+ source: css("color-mix(in oklch,var(--k-danger) 15%,transparent)"),
1138
+ doc: "Danger tint."
1139
+ },
1140
+ {
1141
+ name: "info-soft",
1142
+ tier: "semantic",
1143
+ type: "color",
1144
+ group: "Status",
1145
+ source: css("color-mix(in oklch,var(--k-info) 15%,transparent)"),
1146
+ doc: "Info tint."
1147
+ },
1148
+ {
1149
+ name: "focus",
1150
+ tier: "semantic",
1151
+ type: "color",
1152
+ group: "Interaction",
1153
+ source: css("var(--k-accent)"),
1154
+ doc: "Focus ring colour (drawn as a 2px bg gap, then 2px of focus)."
1155
+ },
1156
+ {
1157
+ name: "selection",
1158
+ tier: "semantic",
1159
+ type: "color",
1160
+ group: "Interaction",
1161
+ source: css("color-mix(in oklch,var(--k-accent) 24%,transparent)"),
1162
+ doc: "Selected rows and ranges.",
1163
+ deprecated: ["--k-ui-select", "--ku-select"]
1164
+ },
1165
+ {
1166
+ name: "scrim",
1167
+ tier: "semantic",
1168
+ type: "color",
1169
+ group: "Interaction",
1170
+ source: theme,
1171
+ doc: "Dimming behind modal layers."
1172
+ },
1173
+ {
1174
+ name: "diff-add",
1175
+ tier: "semantic",
1176
+ type: "color",
1177
+ group: "Data",
1178
+ source: css("var(--k-ok)"),
1179
+ doc: "Added lines; line and word tints derive privately (12% / 38%)."
1180
+ },
1181
+ {
1182
+ name: "diff-del",
1183
+ tier: "semantic",
1184
+ type: "color",
1185
+ group: "Data",
1186
+ source: css("var(--k-danger)"),
1187
+ doc: "Deleted lines."
1188
+ },
1189
+ {
1190
+ name: "diff-mod",
1191
+ tier: "semantic",
1192
+ type: "color",
1193
+ group: "Data",
1194
+ source: css("var(--k-warn)"),
1195
+ doc: "Modified lines."
1196
+ },
1197
+ {
1198
+ name: "before",
1199
+ tier: "semantic",
1200
+ type: "color",
1201
+ group: "Data",
1202
+ source: css("var(--k-fg-3)"),
1203
+ doc: "Before in a comparison, and only Before: its label and side of the seam. Neutral unless a theme gives it a colour."
1204
+ },
1205
+ {
1206
+ name: "after",
1207
+ tier: "semantic",
1208
+ type: "color",
1209
+ group: "Data",
1210
+ source: css("var(--k-fg)"),
1211
+ doc: "After in a comparison, and only After."
1212
+ },
1213
+ {
1214
+ name: "series-1",
1215
+ tier: "semantic",
1216
+ type: "color",
1217
+ group: "Data",
1218
+ source: theme,
1219
+ doc: "Chart series 1."
1220
+ },
1221
+ {
1222
+ name: "series-2",
1223
+ tier: "semantic",
1224
+ type: "color",
1225
+ group: "Data",
1226
+ source: theme,
1227
+ doc: "Chart series 2."
1228
+ },
1229
+ {
1230
+ name: "series-3",
1231
+ tier: "semantic",
1232
+ type: "color",
1233
+ group: "Data",
1234
+ source: theme,
1235
+ doc: "Chart series 3."
1236
+ },
1237
+ {
1238
+ name: "series-4",
1239
+ tier: "semantic",
1240
+ type: "color",
1241
+ group: "Data",
1242
+ source: theme,
1243
+ doc: "Chart series 4."
1244
+ },
1245
+ {
1246
+ name: "series-5",
1247
+ tier: "semantic",
1248
+ type: "color",
1249
+ group: "Data",
1250
+ source: theme,
1251
+ doc: "Chart series 5."
1252
+ },
1253
+ {
1254
+ name: "series-6",
1255
+ tier: "semantic",
1256
+ type: "color",
1257
+ group: "Data",
1258
+ source: theme,
1259
+ doc: "Chart series 6."
1260
+ },
1261
+ {
1262
+ name: "radius-panel",
1263
+ tier: "semantic",
1264
+ type: "length",
1265
+ group: "Shape",
1266
+ source: css("calc(var(--k-radius) + var(--k-unit))"),
1267
+ doc: "Panel and card radius, concentric with controls.",
1268
+ deprecated: ["--k-panel-radius", "--ku-panel-radius"]
1269
+ },
1270
+ {
1271
+ name: "round",
1272
+ tier: "semantic",
1273
+ type: "length",
1274
+ group: "Shape",
1275
+ source: css("calc(var(--k-radius) * 999)"),
1276
+ doc: "Capsule radius that squares when --k-radius is 0. Use instead of 999px."
1277
+ },
1278
+ {
1279
+ name: "unit",
1280
+ tier: "semantic",
1281
+ type: "length",
1282
+ group: "Size",
1283
+ source: value("4px"),
1284
+ doc: "The spacing unit."
1285
+ },
1286
+ {
1287
+ name: "row",
1288
+ tier: "semantic",
1289
+ type: "length",
1290
+ group: "Size",
1291
+ source: css("round(calc(32px * var(--k-density)),2px)"),
1292
+ doc: "Row height.",
1293
+ deprecated: ["--ku-row"]
1294
+ },
1295
+ {
1296
+ name: "width",
1297
+ tier: "semantic",
1298
+ type: "length",
1299
+ group: "Size",
1300
+ source: value("288px"),
1301
+ doc: "Panel width."
1302
+ },
1303
+ {
1304
+ name: "space-inside",
1305
+ tier: "semantic",
1306
+ type: "length",
1307
+ group: "Space",
1308
+ source: css("var(--k-unit)"),
1309
+ doc: "Parts of one thing: an icon and its label, a meta line and its title."
1310
+ },
1311
+ {
1312
+ name: "space-sibling",
1313
+ tier: "semantic",
1314
+ type: "length",
1315
+ group: "Space",
1316
+ source: css("calc(var(--k-unit) * 2)"),
1317
+ doc: "Siblings in a group: buttons in a row, a list item's lines."
1318
+ },
1319
+ {
1320
+ name: "space-title",
1321
+ tier: "semantic",
1322
+ type: "length",
1323
+ group: "Space",
1324
+ source: css("calc(var(--k-unit) * 3)"),
1325
+ doc: "A heading and what it heads."
1326
+ },
1327
+ {
1328
+ name: "space-group",
1329
+ tier: "semantic",
1330
+ type: "length",
1331
+ group: "Space",
1332
+ source: css("calc(var(--k-unit) * 12)"),
1333
+ doc: "Groups inside a section (prose, video, diff), stacked media, feed items (a hairline in the middle)."
1334
+ },
1335
+ {
1336
+ name: "space-section",
1337
+ tier: "semantic",
1338
+ type: "length",
1339
+ group: "Space",
1340
+ source: css("calc(var(--k-unit) * 24)"),
1341
+ doc: "Sections of a page (the intro, the updates, each PR), a hairline in the middle."
1342
+ },
1343
+ {
1344
+ name: "space-column",
1345
+ tier: "semantic",
1346
+ type: "length",
1347
+ group: "Space",
1348
+ source: css("calc(var(--k-unit) * 6)"),
1349
+ doc: "Columns: a contents rail and the page, media side by side."
1350
+ },
1351
+ {
1352
+ name: "pad-page",
1353
+ tier: "semantic",
1354
+ type: "length",
1355
+ group: "Space",
1356
+ source: css("calc(var(--k-unit) * 6)"),
1357
+ doc: "A page's edge; 16px under 640px wide."
1358
+ },
1359
+ {
1360
+ name: "pad-card",
1361
+ tier: "semantic",
1362
+ type: "length",
1363
+ group: "Space",
1364
+ source: css("calc(var(--k-unit) * 3)"),
1365
+ doc: "Inside a card or popover."
1366
+ },
1367
+ {
1368
+ name: "type-heading",
1369
+ tier: "semantic",
1370
+ type: "length",
1371
+ group: "Type",
1372
+ source: value("20px"),
1373
+ doc: "A page's title, weight 500."
1374
+ },
1375
+ {
1376
+ name: "leading-heading",
1377
+ tier: "semantic",
1378
+ type: "length",
1379
+ group: "Type",
1380
+ source: value("28px"),
1381
+ doc: "Line height for type-heading."
1382
+ },
1383
+ {
1384
+ name: "type-title",
1385
+ tier: "semantic",
1386
+ type: "length",
1387
+ group: "Type",
1388
+ source: value("16px"),
1389
+ doc: "Section titles (under their kicker), weight 500."
1390
+ },
1391
+ {
1392
+ name: "leading-title",
1393
+ tier: "semantic",
1394
+ type: "length",
1395
+ group: "Type",
1396
+ source: value("24px"),
1397
+ doc: "Line height for type-title."
1398
+ },
1399
+ {
1400
+ name: "type-body",
1401
+ tier: "semantic",
1402
+ type: "length",
1403
+ group: "Type",
1404
+ source: value("13px"),
1405
+ doc: "Prose, questions, list rows, step titles; 400, or 500 for emphasis."
1406
+ },
1407
+ {
1408
+ name: "leading-body",
1409
+ tier: "semantic",
1410
+ type: "length",
1411
+ group: "Type",
1412
+ source: value("20px"),
1413
+ doc: "Line height for type-body."
1414
+ },
1415
+ {
1416
+ name: "type-label",
1417
+ tier: "semantic",
1418
+ type: "length",
1419
+ group: "Type",
1420
+ source: value("12px"),
1421
+ doc: "Mono inside body text: code and paths."
1422
+ },
1423
+ {
1424
+ name: "leading-label",
1425
+ tier: "semantic",
1426
+ type: "length",
1427
+ group: "Type",
1428
+ source: value("16px"),
1429
+ doc: "Line height for type-label."
1430
+ },
1431
+ {
1432
+ name: "type-small",
1433
+ tier: "semantic",
1434
+ type: "length",
1435
+ group: "Type",
1436
+ source: value("11px"),
1437
+ doc: "Meta, controls, keys, timestamps; mono inside labels."
1438
+ },
1439
+ {
1440
+ name: "leading-small",
1441
+ tier: "semantic",
1442
+ type: "length",
1443
+ group: "Type",
1444
+ source: value("16px"),
1445
+ doc: "Line height for type-small."
1446
+ },
1447
+ {
1448
+ name: "font-size",
1449
+ tier: "semantic",
1450
+ type: "length",
1451
+ group: "Type",
1452
+ source: css("round(calc(12px * (1 + (var(--k-density) - 1) * .5)),1px)"),
1453
+ doc: "Body size; a 5-step scale derives privately.",
1454
+ deprecated: ["--ku-font-size"]
1455
+ },
1456
+ {
1457
+ name: "value-font",
1458
+ tier: "semantic",
1459
+ type: "font",
1460
+ group: "Type",
1461
+ source: css("var(--k-font)"),
1462
+ doc: "Font for readouts and values (labPreset: mono).",
1463
+ deprecated: ["--ku-value-font"]
1464
+ },
1465
+ {
1466
+ name: "shadow-raised",
1467
+ tier: "semantic",
1468
+ type: "shadow",
1469
+ group: "Material",
1470
+ source: theme,
1471
+ doc: "Small lift for raised controls.",
1472
+ deprecated: ["--k-lift-shadow"]
1473
+ },
1474
+ {
1475
+ name: "shadow-overlay",
1476
+ tier: "semantic",
1477
+ type: "shadow",
1478
+ group: "Material",
1479
+ source: theme,
1480
+ doc: "Floating panels, menus, popovers.",
1481
+ deprecated: ["--k-shadow", "--ku-shadow"]
1482
+ },
1483
+ {
1484
+ name: "glass",
1485
+ tier: "semantic",
1486
+ type: "number",
1487
+ group: "Material",
1488
+ source: theme,
1489
+ doc: "Backdrop glass amount (0 = opaque)."
1490
+ },
1491
+ {
1492
+ name: "glow",
1493
+ tier: "semantic",
1494
+ type: "number",
1495
+ group: "Material",
1496
+ source: theme,
1497
+ doc: "Specular glow amount."
1498
+ },
1499
+ {
1500
+ name: "rim",
1501
+ tier: "semantic",
1502
+ type: "color",
1503
+ group: "Material",
1504
+ source: theme,
1505
+ doc: "Top-edge highlight hairline.",
1506
+ deprecated: ["--ku-rim"]
1507
+ },
1508
+ {
1509
+ name: "spring",
1510
+ tier: "semantic",
1511
+ type: "spring",
1512
+ group: "Motion",
1513
+ source: value("0.3 0"),
1514
+ doc: "Default spring as `duration bounce` (the motion module's `default`)."
1515
+ },
1516
+ {
1517
+ name: "hover-in",
1518
+ tier: "semantic",
1519
+ type: "number",
1520
+ group: "Motion",
1521
+ source: value("0"),
1522
+ doc: "Hover wash fade-in, unitless milliseconds.",
1523
+ deprecated: ["--ku-hover-in"]
1524
+ },
1525
+ {
1526
+ name: "hover-out",
1527
+ tier: "semantic",
1528
+ type: "number",
1529
+ group: "Motion",
1530
+ source: value("120"),
1531
+ doc: "Hover wash fade-out, unitless milliseconds.",
1532
+ deprecated: ["--ku-hover-out"]
1533
+ },
1534
+ {
1535
+ name: "z",
1536
+ tier: "semantic",
1537
+ type: "integer",
1538
+ group: "Motion",
1539
+ source: value("2147480000"),
1540
+ doc: "Base of knobs' stacking ladder; layers add small offsets."
1541
+ },
1542
+ {
1543
+ name: "slider-track",
1544
+ tier: "hook",
1545
+ type: "color",
1546
+ group: "Hooks",
1547
+ source: css("var(--k-fill)"),
1548
+ doc: "Slider track."
1549
+ },
1550
+ {
1551
+ name: "slider-fill",
1552
+ tier: "hook",
1553
+ type: "color",
1554
+ group: "Hooks",
1555
+ source: css("color-mix(in oklch,var(--k-accent) 20%,var(--k-fill-selected))"),
1556
+ doc: "Slider value fill.",
1557
+ deprecated: ["--k-fill-rest"]
1558
+ },
1559
+ {
1560
+ name: "slider-handle",
1561
+ tier: "hook",
1562
+ type: "color",
1563
+ group: "Hooks",
1564
+ source: css("var(--k-accent)"),
1565
+ doc: "Slider handle and range thumbs.",
1566
+ deprecated: ["--k-handle"]
1567
+ },
1568
+ {
1569
+ name: "toggle-thumb-off",
1570
+ tier: "hook",
1571
+ type: "color",
1572
+ group: "Hooks",
1573
+ source: css("#ffffff"),
1574
+ doc: "A switch's thumb while off, and the ring around colour and gradient thumbs.",
1575
+ deprecated: ["--k-thumb"]
1576
+ },
1577
+ {
1578
+ name: "toggle-track",
1579
+ tier: "hook",
1580
+ type: "color",
1581
+ group: "Hooks",
1582
+ source: css("var(--k-fill-selected)"),
1583
+ doc: "Toggle track, off."
1584
+ },
1585
+ {
1586
+ name: "toggle-track-on",
1587
+ tier: "hook",
1588
+ type: "color",
1589
+ group: "Hooks",
1590
+ source: css("var(--k-accent)"),
1591
+ doc: "Toggle track, on."
1592
+ },
1593
+ {
1594
+ name: "toggle-thumb",
1595
+ tier: "hook",
1596
+ type: "color",
1597
+ group: "Hooks",
1598
+ source: css("var(--k-on-accent)"),
1599
+ doc: "Toggle thumb."
1600
+ },
1601
+ {
1602
+ name: "segmented-track",
1603
+ tier: "hook",
1604
+ type: "color",
1605
+ group: "Hooks",
1606
+ source: css("var(--k-bg-inset)"),
1607
+ doc: "Segmented control background.",
1608
+ deprecated: ["--k-seg-bg", "--ku-seg-bg"]
1609
+ },
1610
+ {
1611
+ name: "segmented-active",
1612
+ tier: "hook",
1613
+ type: "color",
1614
+ group: "Hooks",
1615
+ source: css("var(--k-bg-raised)"),
1616
+ doc: "Active segment.",
1617
+ deprecated: ["--k-seg-active"]
1618
+ },
1619
+ {
1620
+ name: "timeline-playhead",
1621
+ tier: "hook",
1622
+ type: "color",
1623
+ group: "Hooks",
1624
+ source: css("var(--k-accent)"),
1625
+ doc: "Timeline playhead."
1626
+ },
1627
+ {
1628
+ name: "split-gutter",
1629
+ tier: "hook",
1630
+ type: "color",
1631
+ group: "Hooks",
1632
+ source: css("var(--k-border-subtle)"),
1633
+ doc: "Split pane divider.",
1634
+ deprecated: ["--k-ui-divider", "--ku-divider"]
1635
+ },
1636
+ {
1637
+ name: "compare-divider",
1638
+ tier: "hook",
1639
+ type: "color",
1640
+ group: "Hooks",
1641
+ source: css("var(--k-fg)"),
1642
+ doc: "Before/after divider line.",
1643
+ deprecated: ["--k-compare-line"]
1644
+ },
1645
+ {
1646
+ name: "compare-stage",
1647
+ tier: "hook",
1648
+ type: "color",
1649
+ group: "Hooks",
1650
+ source: css("var(--k-fill)"),
1651
+ doc: "Compare stage background."
1652
+ },
1653
+ {
1654
+ name: "activity-rail",
1655
+ tier: "hook",
1656
+ type: "color",
1657
+ group: "Hooks",
1658
+ source: css("var(--k-border-strong)"),
1659
+ doc: "Activity rail line.",
1660
+ deprecated: ["--k-activity-line"]
1661
+ },
1662
+ {
1663
+ name: "picker-card",
1664
+ tier: "hook",
1665
+ type: "color",
1666
+ group: "Hooks",
1667
+ source: css("var(--k-fill)"),
1668
+ doc: "Picker card."
1669
+ },
1670
+ {
1671
+ name: "pane-bg",
1672
+ tier: "hook",
1673
+ type: "color",
1674
+ group: "Hooks",
1675
+ source: css("var(--k-bg)"),
1676
+ doc: "knobs/ui pane card.",
1677
+ deprecated: ["--k-ui-pane", "--ku-pane-bg"]
1678
+ },
1679
+ {
1680
+ name: "button-bg",
1681
+ tier: "hook",
1682
+ type: "color",
1683
+ group: "Hooks",
1684
+ source: css("var(--k-fill)"),
1685
+ doc: "Button fill."
1686
+ },
1687
+ {
1688
+ name: "button-border",
1689
+ tier: "hook",
1690
+ type: "color",
1691
+ group: "Hooks",
1692
+ source: css("transparent"),
1693
+ doc: "Button border.",
1694
+ deprecated: ["--k-button-line"]
1695
+ },
1696
+ {
1697
+ name: "button-fg",
1698
+ tier: "hook",
1699
+ type: "color",
1700
+ group: "Hooks",
1701
+ source: css("var(--k-fg)"),
1702
+ doc: "Button text.",
1703
+ deprecated: ["--k-button-color"]
1704
+ },
1705
+ {
1706
+ name: "row-hover",
1707
+ tier: "hook",
1708
+ type: "color",
1709
+ group: "Hooks",
1710
+ source: css("color-mix(in oklch,var(--k-fill) 50%,transparent)"),
1711
+ doc: "Row hover wash."
1712
+ },
1713
+ {
1714
+ name: "group-label",
1715
+ tier: "hook",
1716
+ type: "color",
1717
+ group: "Hooks",
1718
+ source: css("var(--k-fg-3)"),
1719
+ doc: "Folder and group headings.",
1720
+ deprecated: ["--k-group-ink", "--k-group-color"]
1721
+ },
1722
+ {
1723
+ name: "modified",
1724
+ tier: "hook",
1725
+ type: "color",
1726
+ group: "Hooks",
1727
+ source: css("var(--k-fg-3)"),
1728
+ doc: "Marker for values changed from their default."
1729
+ },
1730
+ {
1731
+ name: "tray-pad",
1732
+ tier: "private",
1733
+ type: "length",
1734
+ group: "Private",
1735
+ source: css("calc(var(--k-unit) * .5)"),
1736
+ doc: "Padding inside a tray around its controls.",
1737
+ deprecated: ["--k-tray-pad"]
1738
+ },
1739
+ {
1740
+ name: "pad",
1741
+ tier: "private",
1742
+ type: "length",
1743
+ group: "Private",
1744
+ source: css("round(calc(10px * var(--k-density)),2px)"),
1745
+ doc: "Panel padding.",
1746
+ deprecated: ["--k-pad"]
1747
+ },
1748
+ {
1749
+ name: "inset",
1750
+ tier: "private",
1751
+ type: "length",
1752
+ group: "Private",
1753
+ source: css("var(--_k-pad)"),
1754
+ doc: "Row content inset.",
1755
+ deprecated: ["--k-inset", "--ku-inset"]
1756
+ },
1757
+ {
1758
+ name: "gap",
1759
+ tier: "private",
1760
+ type: "length",
1761
+ group: "Private",
1762
+ source: css("round(calc(var(--k-unit) * (1 + (var(--k-density) - 1) * 2.5)),1px)"),
1763
+ doc: "Gap between rows.",
1764
+ deprecated: ["--k-gap"]
1765
+ },
1766
+ {
1767
+ name: "radius-md",
1768
+ tier: "private",
1769
+ type: "length",
1770
+ group: "Private",
1771
+ source: css("max(0px,calc(var(--k-radius) - var(--_k-tray-pad)))"),
1772
+ doc: "Concentric radius one tray in.",
1773
+ deprecated: ["--k-radius-md"]
1774
+ },
1775
+ {
1776
+ name: "radius-sm",
1777
+ tier: "private",
1778
+ type: "length",
1779
+ group: "Private",
1780
+ source: css("max(0px,calc(var(--k-radius) - var(--_k-tray-pad) * 2))"),
1781
+ doc: "Concentric radius two trays in.",
1782
+ deprecated: ["--k-radius-sm"]
1783
+ },
1784
+ {
1785
+ name: "control-h",
1786
+ tier: "private",
1787
+ type: "length",
1788
+ group: "Private",
1789
+ source: css("calc(var(--k-row) - var(--k-unit) * 2)"),
1790
+ doc: "Control height inside a row.",
1791
+ deprecated: ["--k-control-h", "--ku-control-h"]
1792
+ },
1793
+ {
1794
+ name: "value-size",
1795
+ tier: "private",
1796
+ type: "length",
1797
+ group: "Private",
1798
+ source: css("calc(var(--k-font-size) - .5px)"),
1799
+ doc: "Readout size.",
1800
+ deprecated: ["--k-value-size", "--ku-value-size"]
1801
+ },
1802
+ {
1803
+ name: "text-title",
1804
+ tier: "private",
1805
+ type: "length",
1806
+ group: "Private",
1807
+ source: css("calc(var(--k-font-size) + 1px)"),
1808
+ doc: "Type scale: titles.",
1809
+ deprecated: ["--k-text-title"]
1810
+ },
1811
+ {
1812
+ name: "text-body",
1813
+ tier: "private",
1814
+ type: "length",
1815
+ group: "Private",
1816
+ source: css("var(--k-font-size)"),
1817
+ doc: "Type scale: body.",
1818
+ deprecated: ["--k-text-body"]
1819
+ },
1820
+ {
1821
+ name: "text-control",
1822
+ tier: "private",
1823
+ type: "length",
1824
+ group: "Private",
1825
+ source: css("calc(var(--k-font-size) - .5px)"),
1826
+ doc: "Type scale: controls.",
1827
+ deprecated: ["--k-text-control"]
1828
+ },
1829
+ {
1830
+ name: "text-meta",
1831
+ tier: "private",
1832
+ type: "length",
1833
+ group: "Private",
1834
+ source: css("calc(var(--k-font-size) - 1px)"),
1835
+ doc: "Type scale: metadata.",
1836
+ deprecated: ["--k-text-meta", "--ku-text-meta"]
1837
+ },
1838
+ {
1839
+ name: "text-cap",
1840
+ tier: "private",
1841
+ type: "length",
1842
+ group: "Private",
1843
+ source: css("calc(var(--k-font-size) - 2px)"),
1844
+ doc: "Type scale: caps and captions.",
1845
+ deprecated: ["--k-text-cap"]
1846
+ },
1847
+ {
1848
+ name: "weight",
1849
+ tier: "private",
1850
+ type: "number",
1851
+ group: "Private",
1852
+ source: value("400"),
1853
+ doc: "Body weight.",
1854
+ deprecated: ["--k-font-weight", "--ku-font-weight"]
1855
+ },
1856
+ {
1857
+ name: "weight-label",
1858
+ tier: "private",
1859
+ type: "number",
1860
+ group: "Private",
1861
+ source: value("500"),
1862
+ doc: "Label weight.",
1863
+ deprecated: ["--k-label-weight", "--ku-label-weight"]
1864
+ },
1865
+ {
1866
+ name: "weight-title",
1867
+ tier: "private",
1868
+ type: "number",
1869
+ group: "Private",
1870
+ source: value("600"),
1871
+ doc: "Title weight.",
1872
+ deprecated: ["--k-title-weight", "--ku-title-weight"]
1873
+ },
1874
+ {
1875
+ name: "focus-ring",
1876
+ tier: "private",
1877
+ type: "shadow",
1878
+ group: "Private",
1879
+ source: css("0 0 0 2px var(--k-bg),0 0 0 4px var(--k-focus)"),
1880
+ doc: "Two-layer focus ring: a bg gap, then the focus colour."
1881
+ },
1882
+ {
1883
+ name: "diff-add-line",
1884
+ tier: "private",
1885
+ type: "color",
1886
+ group: "Private",
1887
+ source: css("color-mix(in oklch,var(--k-diff-add) 12%,transparent)"),
1888
+ doc: "Added line tint."
1889
+ },
1890
+ {
1891
+ name: "diff-add-word",
1892
+ tier: "private",
1893
+ type: "color",
1894
+ group: "Private",
1895
+ source: css("color-mix(in oklch,var(--k-diff-add) 38%,transparent)"),
1896
+ doc: "Added word tint."
1897
+ },
1898
+ {
1899
+ name: "diff-del-line",
1900
+ tier: "private",
1901
+ type: "color",
1902
+ group: "Private",
1903
+ source: css("color-mix(in oklch,var(--k-diff-del) 12%,transparent)"),
1904
+ doc: "Deleted line tint."
1905
+ },
1906
+ {
1907
+ name: "diff-del-word",
1908
+ tier: "private",
1909
+ type: "color",
1910
+ group: "Private",
1911
+ source: css("color-mix(in oklch,var(--k-diff-del) 38%,transparent)"),
1912
+ doc: "Deleted word tint."
1913
+ },
1914
+ {
1915
+ name: "diff-mod-line",
1916
+ tier: "private",
1917
+ type: "color",
1918
+ group: "Private",
1919
+ source: css("color-mix(in oklch,var(--k-diff-mod) 12%,transparent)"),
1920
+ doc: "Modified line tint."
1921
+ },
1922
+ {
1923
+ name: "diff-mod-word",
1924
+ tier: "private",
1925
+ type: "color",
1926
+ group: "Private",
1927
+ source: css("color-mix(in oklch,var(--k-diff-mod) 38%,transparent)"),
1928
+ doc: "Modified word tint."
1929
+ }
1930
+ ], TOKEN_BY_NAME = new Map(TOKENS.map((t) => [t.name, t])), cssName = (t) => `${t.tier === "private" ? "--_k-" : "--k-"}${t.name}`, PROPERTY_TO_NAME = new Map(TOKENS.map((t) => [cssName(t), t.name])), tokenForProperty = (property) => PROPERTY_TO_NAME.get(property), DEPRECATED = new Map(TOKENS.flatMap((t) => (t.deprecated ?? []).map((old) => [old, cssName(t)])));
1931
+
1932
+ // src/tokens/css.ts
1933
+ function pair(def, dark, light) {
1934
+ if (dark === void 0 && light === void 0)
1935
+ return;
1936
+ if (dark === void 0 || light === void 0 || dark === light || def.type !== "color")
1937
+ return dark ?? light;
1938
+ return `light-dark(${light},${dark})`;
1939
+ }
1940
+ function declaredValue(theme, def) {
1941
+ let name = def.name, dark = theme.declared.dark[name], light = theme.declared.light[name];
1942
+ if (def.type === "color" && dark === void 0 !== (light === void 0))
1943
+ return pair(def, dark ?? theme.dark[name], light ?? theme.light[name]);
1944
+ return pair(def, dark, light);
1945
+ }
1946
+ var SCHEMES = [
1947
+ [":where(.knobs-root)", "light dark"],
1948
+ [
1949
+ ':where(.dark,.dark-theme,[data-theme="dark"],[data-appearance="dark"],[data-knobs-theme="dark"]) :where(.knobs-root)',
1950
+ "dark"
1951
+ ],
1952
+ [
1953
+ ':where(.light,.light-theme,[data-theme="light"],[data-appearance="light"],[data-knobs-theme="light"]) :where(.knobs-root)',
1954
+ "light"
1955
+ ],
1956
+ [":where(.knobs-root) :where(.knobs-root:not([data-appearance]))", "inherit"],
1957
+ [':where(.knobs-root[data-appearance="dark"])', "dark"],
1958
+ [':where(.knobs-root[data-appearance="light"])', "light"],
1959
+ [':where(.knobs-root[data-appearance="system"])', "light dark"],
1960
+ [':where(.knobs-root[data-appearance="inherit"])', "inherit"]
1961
+ ], APPEARANCE_CSS = SCHEMES.map(([selector, scheme]) => {
1962
+ let rule = `${selector}{color-scheme:${scheme};--_k-light:${scheme === "light" ? "1" : scheme === "inherit" ? "inherit" : "0"}}`;
1963
+ return scheme === "light dark" ? `${rule}
1964
+ @media(prefers-color-scheme:light){${selector}{--_k-light:1}}` : rule;
1965
+ }).join(`
1966
+ `), privately = (css) => css.replace(/var\(--k-([a-z0-9-]+)/g, (m, name) => tokenForProperty(`--k-${name}`) ? `var(--_k-${name}` : m);
1967
+ function resolver(def) {
1968
+ let reads = [...def.deprecated ?? []];
1969
+ if (def.tier !== "private")
1970
+ reads.push(cssName(def));
1971
+ let source = def.source, out = ("css" in source ? privately(source.css) : ("value" in source) && def.tier === "private" ? source.value : void 0) ?? "";
1972
+ for (let i = reads.length - 1;i >= 0; i--)
1973
+ out = out === "" ? `var(${reads[i]})` : `var(${reads[i]},${out})`;
1974
+ return def.resolve ? privately(def.resolve).replaceAll("$", out) : out;
1975
+ }
1976
+ function tokensCss(theme) {
1977
+ let root = [], resolved = [];
1978
+ for (let def of TOKENS) {
1979
+ let source = def.source, own = declaredValue(theme, def) ?? ("from" in source ? "" : ("value" in source) && def.tier !== "private" ? source.value : void 0);
1980
+ if (own !== void 0 && def.tier !== "private")
1981
+ root.push(`${cssName(def)}:${own}`);
1982
+ resolved.push(`--_k-${def.name}:${resolver(def)}`);
1983
+ }
1984
+ return `@layer knobs.tokens{
1985
+ :where(:root,:host){${root.join(";")}}
1986
+ :where(.knobs-root){${resolved.join(";")}}
1987
+ ${APPEARANCE_CSS}
1988
+ }`;
1989
+ }
1990
+ function themeCss(theme, selector) {
1991
+ let decls = [];
1992
+ for (let def of TOKENS) {
1993
+ let own = declaredValue(theme, def);
1994
+ if (own !== void 0)
1995
+ decls.push(`${cssName(def)}:${own}`);
1996
+ }
1997
+ return `@layer knobs.tokens{${selector}{${decls.join(";")}}}`;
1998
+ }
1999
+
2000
+ // src/tokens/evaluate.ts
2001
+ function splitTop(s) {
2002
+ let out = [], depth = 0, start = 0;
2003
+ for (let i = 0;i < s.length; i++) {
2004
+ let ch = s[i];
2005
+ if (ch === "(")
2006
+ depth++;
2007
+ else if (ch === ")")
2008
+ depth--;
2009
+ else if (ch === "," && depth === 0)
2010
+ out.push(s.slice(start, i).trim()), start = i + 1;
2011
+ }
2012
+ return out.push(s.slice(start).trim()), out;
2013
+ }
2014
+ var call = (s, fn) => s.startsWith(`${fn}(`) && s.endsWith(")") ? s.slice(fn.length + 1, -1) : void 0;
2015
+ function evaluate(input, lookup) {
2016
+ let s = input.trim(), v = call(s, "var");
2017
+ if (v !== void 0) {
2018
+ let [name, ...fallback] = splitTop(v), value = lookup(name);
2019
+ if (value !== void 0)
2020
+ return evaluate(value, lookup);
2021
+ if (fallback.length)
2022
+ return evaluate(fallback.join(","), lookup);
2023
+ throw Error(`Unresolved ${name}`);
2024
+ }
2025
+ let mix = call(s, "color-mix");
2026
+ if (mix !== void 0)
2027
+ return colorMix(mix, lookup);
2028
+ return normalize(s);
2029
+ }
2030
+ function percent(s, lookup) {
2031
+ let c = call(s, "calc");
2032
+ if (c === void 0)
2033
+ return Number.parseFloat(s) / 100;
2034
+ let [a, b] = c.split("*").map((x) => x.trim()), num = (x) => {
2035
+ let inner = call(x, "var");
2036
+ if (inner !== void 0)
2037
+ return Number.parseFloat(lookup(splitTop(inner)[0]) ?? Number.NaN.toString());
2038
+ return x.endsWith("%") ? Number.parseFloat(x) / 100 : Number.parseFloat(x);
2039
+ }, out = num(a) * num(b);
2040
+ if (!Number.isFinite(out))
2041
+ throw Error(`Bad percentage: ${s}`);
2042
+ return out;
2043
+ }
2044
+ function stop(s, lookup) {
2045
+ let m = /^(.*?)\s+((?:calc\(.*\))|(?:[\d.]+%))$/.exec(s);
2046
+ if (!m)
2047
+ return { color: evaluate(s, lookup) };
2048
+ return { color: evaluate(m[1], lookup), p: percent(m[2], lookup) };
2049
+ }
2050
+ function colorMix(args, lookup) {
2051
+ let [space, a, b] = splitTop(args);
2052
+ if (space !== "in oklch")
2053
+ throw Error(`Only color-mix(in oklch, …) is supported, got ${space}`);
2054
+ let x = stop(a, lookup), y = stop(b, lookup), p1 = x.p ?? (y.p === void 0 ? 0.5 : 1 - y.p), p2 = y.p ?? 1 - p1, sum = p1 + p2, scale = sum < 1 ? sum : 1;
2055
+ p1 /= sum, p2 /= sum;
2056
+ let ca = linearToOklch(parseColor(x.color)), cb = linearToOklch(parseColor(y.color)), a1 = ca.alpha ?? 1, a2 = cb.alpha ?? 1, alpha = a1 * p1 + a2 * p2;
2057
+ if (alpha <= 0)
2058
+ return "#00000000";
2059
+ let powerless = (c, alpha) => c.c < 0.0002 || alpha === 0, h1 = powerless(ca, a1) ? cb.h : ca.h, dh = (powerless(cb, a2) ? h1 : cb.h) - h1;
2060
+ if (dh > 180)
2061
+ dh -= 360;
2062
+ if (dh < -180)
2063
+ dh += 360;
2064
+ let pre = (u, v) => (u * a1 * p1 + v * a2 * p2) / alpha, rgb = oklchToLinear({
2065
+ l: pre(ca.l, cb.l),
2066
+ c: pre(ca.c, cb.c),
2067
+ h: (h1 + dh * p2 + 360) % 360
2068
+ });
2069
+ return formatHex([rgb[0], rgb[1], rgb[2], alpha * scale]);
2070
+ }
2071
+
2072
+ // src/themes/define.ts
2073
+ var DEFAULT_SANS = 'system-ui,-apple-system,"SF Pro Text",sans-serif', DEFAULT_MONO = '"SF Mono",SFMono-Regular,ui-monospace,Menlo,monospace', BASE = {
2074
+ gray: { hue: 0, chroma: 0 },
2075
+ accent: "#ffffff",
2076
+ contrast: 50,
2077
+ radius: 8,
2078
+ density: "default",
2079
+ material: "solid",
2080
+ font: { sans: DEFAULT_SANS, mono: DEFAULT_MONO },
2081
+ tokens: { dark: {}, light: {} }
2082
+ }, DENSITY = { compact: 0.875, default: 1, comfortable: 1.1875 }, SURFACES = {
2083
+ dark: { "bg-page": 14.5, "bg-inset": 19.6, bg: 22.6, "bg-raised": 25.7, "bg-overlay": 28.1 },
2084
+ light: { "bg-page": 92.6, "bg-inset": 94.6, bg: 97.1, "bg-raised": 100, "bg-overlay": 100 }
2085
+ }, INKS = {
2086
+ dark: { fg: 99.7, "fg-2": 76.7, "fg-3": 48.4, "fg-4": 31.9, "border-strong": 15.8 },
2087
+ light: { fg: 98.35, "fg-2": 78, "fg-3": 50, "fg-4": 34, "border-strong": 17 }
2088
+ }, APCA_BUDGET = {
2089
+ fg: 90,
2090
+ "fg-2": 75,
2091
+ "fg-3": 45,
2092
+ "fg-4": 30,
2093
+ "accent-fg": 60,
2094
+ "border-strong": 15
2095
+ }, TINT = { surface: { dark: 0.5, light: 0.7 }, fg: 1.35, ink: 1.5, border: 1.25 }, STATUS = {
2096
+ dark: {
2097
+ ok: [78, 0.15, 155],
2098
+ warn: [83, 0.14, 80],
2099
+ danger: [70, 0.18, 25],
2100
+ info: [75, 0.13, 240]
2101
+ },
2102
+ light: {
2103
+ ok: [52, 0.14, 150],
2104
+ warn: [60, 0.14, 65],
2105
+ danger: [55, 0.2, 27],
2106
+ info: [53, 0.15, 245]
2107
+ }
2108
+ }, SERIES_HUES = [250, 155, 75, 25, 305, 195], SERIES = { dark: { l: 74, c: 0.12 }, light: { l: 56, c: 0.14 } }, contrastMultiplier = (contrast) => 0.5 + Math.min(100, Math.max(0, contrast)) / 100;
2109
+ function fontStack(family, fallback) {
2110
+ if (family.includes(","))
2111
+ return family;
2112
+ let quoted = /\s/.test(family) && !/^["']/.test(family) ? `"${family}"` : family;
2113
+ return family === fallback ? family : `${quoted},${fallback}`;
2114
+ }
2115
+ function mergeInputs(parent, spec) {
2116
+ return {
2117
+ gray: { ...parent.gray, ...spec.gray },
2118
+ accent: spec.accent ?? parent.accent,
2119
+ contrast: spec.contrast ?? parent.contrast,
2120
+ radius: spec.radius ?? parent.radius,
2121
+ density: spec.density ?? parent.density,
2122
+ material: spec.material ?? parent.material,
2123
+ font: {
2124
+ sans: spec.font?.sans ? fontStack(spec.font.sans, DEFAULT_SANS) : parent.font.sans,
2125
+ mono: spec.font?.mono ? fontStack(spec.font.mono, DEFAULT_MONO) : parent.font.mono
2126
+ },
2127
+ tokens: {
2128
+ dark: { ...parent.tokens.dark, ...spec.tokens?.dark },
2129
+ light: { ...parent.tokens.light, ...spec.tokens?.light }
2130
+ }
2131
+ };
2132
+ }
2133
+ function meet(l, floor, bg, away, make) {
2134
+ let x = l;
2135
+ while (apca(make(x), bg) < floor + 0.5 && x >= 0 && x <= 100)
2136
+ x += away * 0.25;
2137
+ return make(Math.min(100, Math.max(0, x)));
2138
+ }
2139
+ function solve(target, bg, away, make) {
2140
+ let near = toOklch(bg).l * 100, far = away > 0 ? 100 : 0;
2141
+ if (apca(make(far), bg) <= target)
2142
+ return far;
2143
+ for (let i = 0;i < 30; i++) {
2144
+ let mid = (near + far) / 2;
2145
+ if (apca(make(mid), bg) < target)
2146
+ near = mid;
2147
+ else
2148
+ far = mid;
2149
+ }
2150
+ return far;
2151
+ }
2152
+ function accentPair(inputs) {
2153
+ if (typeof inputs.accent !== "string")
2154
+ return { ...inputs.accent };
2155
+ let dark = inputs.accent, o = toOklch(dark), light = o.c < 0.02 ? oklchToHex({ l: 0.227, c: inputs.gray.chroma, h: inputs.gray.hue }) : oklchToHex({ l: Math.min(0.6, Math.max(0.45, o.l - 0.15)), c: o.c * 1.1, h: o.h });
2156
+ return { dark, light };
2157
+ }
2158
+ function generate(inputs, appearance, accent) {
2159
+ let m = contrastMultiplier(inputs.contrast), { hue, chroma } = inputs.gray, neutral = (l, tint) => oklchToHex({ l: l / 100, c: chroma * tint, h: hue }), user = inputs.tokens[appearance], out = {}, surfaces = SURFACES[appearance];
2160
+ for (let [role, l] of Object.entries(surfaces)) {
2161
+ let spread = surfaces.bg + (l - surfaces.bg) * m;
2162
+ out[role] = user[role] ?? neutral(Math.min(100, Math.max(0, spread)), TINT.surface[appearance]);
2163
+ }
2164
+ let bg = out.bg, away = appearance === "dark" ? 1 : -1, inkSpread = 1 + (m - 1) * 0.4;
2165
+ for (let [role, target] of Object.entries(INKS[appearance])) {
2166
+ let tint = role === "fg" ? TINT.fg : role === "border-strong" ? TINT.border : TINT.ink, make = (x) => neutral(x, tint), l = solve(target * inkSpread, bg, away, make);
2167
+ out[role] = meet(l, APCA_BUDGET[role], bg, away, make);
2168
+ }
2169
+ out.accent = accent;
2170
+ let a = toOklch(accent);
2171
+ out["accent-fg"] = meet(a.l * 100, APCA_BUDGET["accent-fg"], bg, away, (x) => oklchToHex({ l: x / 100, c: a.c, h: a.h })), out["on-accent"] = apca("#111111", accent) >= apca("#ffffff", accent) ? "#111111" : "#ffffff";
2172
+ for (let [role, [l, c, h]] of Object.entries(STATUS[appearance]))
2173
+ out[role] = oklchToHex({ l: l / 100, c, h });
2174
+ let s = SERIES[appearance], start = a.c >= 0.04 ? a.h - SERIES_HUES[0] : 0;
2175
+ SERIES_HUES.forEach((h, i) => {
2176
+ out[`series-${i + 1}`] = oklchToHex({ l: s.l / 100, c: s.c, h: (h + start + 360) % 360 });
2177
+ }), out.scrim = appearance === "dark" ? "#00000099" : "#00000040", out.contrast = String(Math.round(m * 1000) / 1000), out.radius = `${inputs.radius}px`, out.density = String(DENSITY[inputs.density]), out.font = inputs.font.sans, out.mono = inputs.font.mono;
2178
+ let material = inputs.material;
2179
+ if (out.glass = material === "glass" ? "0.6" : "0", out.glow = material === "glass" ? "0.5" : "0", out.rim = material === "flat" ? "transparent" : appearance === "dark" ? "#ffffff1a" : "#ffffff99", material === "flat")
2180
+ out["border-subtle"] = over(withAlpha(out.fg, 0.06 * m), bg), out.border = over(withAlpha(out.fg, 0.1 * m), bg);
2181
+ return out;
2182
+ }
2183
+ function shadows(material, borderStrong) {
2184
+ if (material === "flat")
2185
+ return {
2186
+ "shadow-raised": "none",
2187
+ "shadow-overlay": `0 0 0 1px light-dark(${borderStrong.light},${borderStrong.dark})`
2188
+ };
2189
+ return {
2190
+ "shadow-raised": "0 1px 2px light-dark(#0000001f,#00000029)",
2191
+ "shadow-overlay": "0 12px 36px light-dark(#00000024,#00000085),0 1px 2px light-dark(#00000014,#0000004d)"
2192
+ };
2193
+ }
2194
+ function resolve(declared) {
2195
+ let raw = (name) => {
2196
+ let def = TOKEN_BY_NAME.get(name), own = declared[name];
2197
+ if (own !== void 0)
2198
+ return own;
2199
+ let source = def.source;
2200
+ if ("css" in source)
2201
+ return source.css;
2202
+ if ("value" in source)
2203
+ return source.value;
2204
+ throw Error(`Theme does not supply ${name}`);
2205
+ }, lookup = (property) => {
2206
+ let name = tokenForProperty(property);
2207
+ return name ? raw(name) : void 0;
2208
+ }, out = {};
2209
+ for (let t of TOKENS)
2210
+ out[t.name] = t.type === "color" ? evaluate(raw(t.name), lookup) : raw(t.name);
2211
+ return out;
2212
+ }
2213
+ function gpuOf(resolved) {
2214
+ let out = {};
2215
+ for (let t of TOKENS)
2216
+ if (t.type === "color")
2217
+ out[t.name] = parseColor(resolved[t.name]);
2218
+ return out;
2219
+ }
2220
+ function validate(name, inputs) {
2221
+ if (!/^[\w-]+$/.test(name))
2222
+ throw Error(`Invalid theme name: ${name}`);
2223
+ if (name === "dark" || name === "light")
2224
+ throw Error(`Reserved theme name: ${name}`);
2225
+ for (let appearance of ["dark", "light"])
2226
+ for (let key of Object.keys(inputs.tokens[appearance]))
2227
+ if (!TOKEN_BY_NAME.has(key))
2228
+ throw Error(`Unknown token in theme ${name}: ${key}`);
2229
+ }
2230
+ function defineTheme(spec) {
2231
+ let inputs = mergeInputs(spec.extends?.inputs ?? BASE, spec);
2232
+ validate(spec.name, inputs);
2233
+ let accent = accentPair(inputs), generated = {
2234
+ dark: generate(inputs, "dark", accent.dark),
2235
+ light: generate(inputs, "light", accent.light)
2236
+ }, material = shadows(inputs.material, {
2237
+ dark: inputs.tokens.dark["border-strong"] ?? generated.dark["border-strong"],
2238
+ light: inputs.tokens.light["border-strong"] ?? generated.light["border-strong"]
2239
+ }), declared = {
2240
+ dark: { ...generated.dark, ...material, ...inputs.tokens.dark },
2241
+ light: { ...generated.light, ...material, ...inputs.tokens.light }
2242
+ };
2243
+ for (let [key, dark] of Object.entries(declared.dark)) {
2244
+ let def = TOKEN_BY_NAME.get(key), light = declared.light[key];
2245
+ if (def.type !== "color" && light !== void 0 && light !== dark)
2246
+ throw Error(`Theme ${spec.name}: only colours may differ by appearance (${key})`);
2247
+ }
2248
+ let dark = resolve(declared.dark), light = resolve(declared.light), theme = {
2249
+ name: spec.name,
2250
+ inputs,
2251
+ dark,
2252
+ light,
2253
+ declared,
2254
+ gpu: { dark: gpuOf(dark), light: gpuOf(light) },
2255
+ css: (options) => options?.selector ? themeCss(theme, options.selector) : tokensCss(theme)
2256
+ };
2257
+ return theme;
2258
+ }
2259
+
2260
+ // src/themes/knobs.ts
2261
+ var knobs = defineTheme({
2262
+ name: "knobs",
2263
+ gray: { hue: 285, chroma: 0.004 },
2264
+ accent: { dark: "#ffffff", light: "#1c1c1e" },
2265
+ contrast: 50,
2266
+ radius: 8,
2267
+ density: "default",
2268
+ material: "glass"
2269
+ });
2270
+
2271
+ // src/core/glide.ts
2272
+ var COLOR_TOKENS = [
679
2273
  "bg",
680
- "surface",
681
- "surface-hi",
682
- "line",
683
- "line-hi",
684
- "text",
685
- "label",
686
- "dim",
2274
+ "fill",
2275
+ "fill-selected",
2276
+ "border",
2277
+ "border-strong",
2278
+ "fg",
2279
+ "fg-2",
2280
+ "fg-3",
687
2281
  "accent",
688
2282
  "modified",
689
- "seg-bg",
690
- "seg-active",
2283
+ "segmented-track",
2284
+ "segmented-active",
691
2285
  "toggle-track",
692
2286
  "toggle-thumb",
2287
+ "toggle-thumb-off",
2288
+ "slider-handle",
693
2289
  "rim",
694
- "edge",
695
- "page"
696
- ], LENGTH_TOKENS = ["pad", "inset", "row", "gap", "radius", "panel-radius", "font-size"], NUMBER_TOKENS = ["label-weight", "blur", "glow", "glass", "glass-tone"], ANIMATED = [...COLOR_TOKENS, ...LENGTH_TOKENS, ...NUMBER_TOKENS, "width"], TOKEN_TRANSITIONS = ANIMATED.map((t) => `--kt-${t} var(--k-token-t)`).join(","), register = (names, syntax, initial) => names.map((n) => `@property --kt-${n}{syntax:"${syntax}";inherits:false;initial-value:${initial}}`).join(`
697
- `), DRIVERS = `${register(COLOR_TOKENS, "<color>", "transparent")}
2290
+ "border-subtle",
2291
+ "bg-page"
2292
+ ], LENGTH_TOKENS = ["pad", "inset", "row", "gap", "radius", "radius-panel", "font-size"], NUMBER_TOKENS = ["weight-label", "blur", "glow", "glass", "glass-tone"], ANIMATED = [...COLOR_TOKENS, ...LENGTH_TOKENS, ...NUMBER_TOKENS, "width"], TOKEN_TRANSITIONS = ANIMATED.map((t) => `--kt-${t} var(--k-token-t)`).join(","), source = (t) => t === "blur" ? "--k-blur" : `--_k-${t}`, register = (names, syntax, initial) => names.map((n) => `@property --kt-${n}{syntax:"${syntax}";inherits:false;initial-value:${initial}}`).join(`
2293
+ `);
2294
+ var DRIVERS = `${register(COLOR_TOKENS, "<color>", "transparent")}
698
2295
  ${register(LENGTH_TOKENS, "<length>", "0px")}
699
2296
  ${register(NUMBER_TOKENS, "<number>", "0")}
700
2297
  ${register(["width"], "<length-percentage>", "288px")}
701
- .knobs-panel,.knobs-chip,.knobs-toast{${ANIMATED.map((t) => `--kt-${t}:var(--k-${t});--kv-${t}:var(--kt-${t})`).join(";")}}`, aliased = (css) => css.replace(new RegExp(`var\\(--k-(${ANIMATED.join("|")})\\)`, "g"), "var(--kv-$1)"), lightVars = `
702
- --k-bg:#f5f5f7;--k-surface:rgba(0,0,0,calc(.05 * var(--k-contrast)));--k-surface-hi:rgba(0,0,0,calc(.095 * var(--k-contrast)));--k-line:rgba(0,0,0,calc(.1 * var(--k-contrast)));--k-line-hi:rgba(0,0,0,calc(.2 * var(--k-contrast)));
703
- --k-text:rgba(0,0,0,.88);--k-label:rgba(60,60,67,.68);--k-dim:rgba(60,60,67,.5);--k-accent:#1c1c1e;--k-modified:rgba(0,0,0,.42);
704
- --k-seg-bg:rgba(0,0,0,.065);--k-seg-active:#fff;--k-toggle-track:rgba(0,0,0,.14);--k-toggle-thumb:#fff;--k-shadow:0 10px 32px rgba(0,0,0,.14),0 1px 3px rgba(0,0,0,.08);
705
- --k-rim:rgba(255,255,255,.6);--k-edge:rgba(0,0,0,calc(.07 * var(--k-contrast)));--k-glass-tone:1.08;--k-page:#e6e6eb;--k-group-ink:var(--k-dim);
706
- color-scheme:light;`, defaultsCss = `
707
- @property --k-fill{syntax:"<percentage>";inherits:false;initial-value:0%}
2298
+ :where(.knobs-panel,.knobs-chip,.knobs-notice,.knobs-ui){${ANIMATED.map((t) => `--kt-${t}:var(${source(t)});--kv-${t}:var(--kt-${t})`).join(";")};--k-token-t:calc(var(--k-fill-ms) * 1ms) var(--k-fill-ease)}
2299
+ :where(.knobs-ui){transition:${TOKEN_TRANSITIONS}}
2300
+ :root[data-knobs-scrub] :where(.knobs-chip,.knobs-ui){--k-token-t:0s}
2301
+ @media(prefers-reduced-motion:reduce){:where(.knobs-chip,.knobs-ui){--k-token-t:0s}}`, aliased = (css) => css.replace(new RegExp(`var\\(--_k-(${ANIMATED.join("|")})\\)`, "g"), "var(--kv-$1)").replace(/var\(--k-blur\)/g, "var(--kv-blur)");
2302
+
2303
+ // src/core/root.ts
2304
+ var ROOT_CLASS = "knobs-root", extras = `:where(.${ROOT_CLASS}){--_k-shadow-k:calc(var(--k-shadow-strength,calc(.48 - .32 * var(--_k-light,0))) / .48);--_k-glass-tone:var(--k-glass-tone,calc(.5 + .58 * var(--_k-light,0)));--_k-fill-base:var(--k-fill-base,var(--_k-fill-selected));--_k-fill-hover-mix:var(--k-fill-hover-mix,var(--k-fill-rest-mix,20%));--_k-reveal-ease:var(--k-ease,cubic-bezier(.2,.8,.2,1))}`, narrow = `@media(max-width:639.98px){:where(.${ROOT_CLASS}){--_k-pad-page:var(--k-pad-page,calc(var(--_k-unit) * 4))}}`, spring = `:where(:root,:host){--k-fill-ease:${DEFAULT_LINEAR.easing};--k-fill-ms:${DEFAULT_LINEAR.ms}}`, rootCss = `${tokensCss(knobs)}
2305
+ ${extras}
2306
+ ${narrow}
2307
+ ${spring}
2308
+ ${DRIVERS}
2309
+ ${motionCss}`;
2310
+ function injectTokens(doc) {
2311
+ if (doc.querySelector("style[data-knobs-tokens]"))
2312
+ return;
2313
+ let style = doc.createElement("style");
2314
+ style.dataset.knobsTokens = "", style.textContent = rootCss, doc.head.append(style);
2315
+ }
2316
+
2317
+ // src/panel/styles.ts
2318
+ var lead = springEasing(LEAD.omega, LEAD.zeta), trail = springEasing(TRAIL.omega, TRAIL.zeta), LEAD_T = `${lead.ms}ms var(--k-lead)`, TRAIL_T = `calc(${trail.ms}ms * (.6 + .4 * clamp(0, var(--k-blur), 2))) var(--k-trail)`, FILL_T = "calc(var(--k-fill-ms) * 1ms * clamp(var(--k-blur),.1,2)) var(--k-fill-ease)", SLIDE_T = "calc(var(--k-fill-ms) * 1ms) var(--k-fill-ease)", snappy = springLinear(SPRINGS2.snappy), snappyOut = springLinear({ duration: 0.2, bounce: 0 }), BLOOM_IN = `${snappy.ms}ms ${snappy.easing}`, BLOOM_OUT = `${snappyOut.ms}ms ${snappyOut.easing}`, DELAY = "var(--k-delay,0ms)", armed = springLinear(SPRINGS2.default), ARMED_T = `${armed.ms}ms ${armed.easing}`, POINTER_ROW = ".knobs-panel[data-k-row-hover]:not([data-keyboard])", DELAYED = ".knobs-fill,.knobs-handle,.knobs-seg-pill,.knobs-toggle,.knobs-toggle i,.knobs-arm,.knobs-curve,.knobs-swatch,.knobs-strip-thumb,.knobs-pad>i,.knobs-ease-handle,.knobs-range-track,.knobs-range-fill,.knobs-range-thumb,.knobs-dial-hand,.knobs-grad,.knobs-grad-mini,.knobs-grad-mini>i,.knobs-grad-stop,.knobs-graph-pt", GRAD_N = GRADIENT_SAMPLES, gradStops = (at) => Array.from({ length: GRAD_N }, (_, i) => `var(--kgrad-${i}) ${at(i)}`).join(","), GRAD_STRIP = `linear-gradient(to right,${gradStops((i) => `calc(var(--kg-r) + (100% - var(--kg-r) * 2) * ${Number((i / (GRAD_N - 1)).toFixed(5))})`)})`, GRAD_MINI = `linear-gradient(to right,${gradStops((i) => `${Number((i / (GRAD_N - 1) * 100).toFixed(3))}%`)})`, GRAD_PROPS = Array.from({ length: GRAD_N }, (_, i) => `@property --kgrad-${i}{syntax:"<color>";inherits:false;initial-value:transparent}`).join(`
2319
+ `), defaultsCss = `
2320
+ @property --_k-fill-at{syntax:"<percentage>";inherits:false;initial-value:0%}
708
2321
  @property --k-fill-mix{syntax:"<percentage>";inherits:false;initial-value:20%}
709
2322
  @property --k-readout{syntax:"<length>";inherits:true;initial-value:0px}
710
2323
  @property --k-copy{syntax:"<number>";inherits:true;initial-value:1}
@@ -712,7 +2325,6 @@ ${register(["width"], "<length-percentage>", "288px")}
712
2325
  @property --k-check-a{syntax:"<number>";inherits:true;initial-value:0}
713
2326
  @property --k-head-s{syntax:"<number>";inherits:true;initial-value:0}
714
2327
  @property --k-head-v{syntax:"<number>";inherits:true;initial-value:0}
715
- @property --kc-value-size{syntax:"<length>";inherits:true;initial-value:11.5px}
716
2328
  @property --k-armed{syntax:"<number>";inherits:false;initial-value:0}
717
2329
  @property --kr-lo{syntax:"<number>";inherits:true;initial-value:0}
718
2330
  @property --kpt-sel{syntax:"<number>";inherits:false;initial-value:1}
@@ -721,20 +2333,14 @@ ${register(["width"], "<length-percentage>", "288px")}
721
2333
  @property --kr-show-lo{syntax:"<number>";inherits:true;initial-value:0}
722
2334
  @property --kr-show-hi{syntax:"<number>";inherits:true;initial-value:0}
723
2335
  ${GRAD_PROPS}
2336
+ /* The panel's own dials (the design tokens come from the token sheet, core/root.ts). */
724
2337
  :where(:root,:host){
725
- --k-bg:#1c1c1e;--k-contrast:1;--k-surface:rgba(255,255,255,calc(.055 * var(--k-contrast)));--k-surface-hi:rgba(255,255,255,calc(.11 * var(--k-contrast)));--k-line:rgba(255,255,255,calc(.1 * var(--k-contrast)));--k-line-hi:rgba(255,255,255,calc(.18 * var(--k-contrast)));
726
- --k-text:rgba(255,255,255,.92);--k-label:rgba(255,255,255,.64);--k-dim:rgba(255,255,255,.42);--k-accent:#fff;--k-modified:rgba(255,255,255,.5);
727
- --k-seg-bg:rgba(0,0,0,.26);--k-seg-active:var(--k-surface-hi);--k-toggle-track:rgba(255,255,255,.14);--k-toggle-thumb:var(--k-bg);--k-shadow:0 12px 36px rgba(0,0,0,.52),0 1px 2px rgba(0,0,0,.3);
728
- --k-rim:rgba(255,255,255,.1);--k-edge:rgba(255,255,255,calc(.07 * var(--k-contrast)));--k-rim-width:1px;--k-glass-tone:.5;--k-page:#101012;
729
- --k-group-ink:rgba(255,255,255,.48);
730
- --k-unit:4px;--k-density:1;--k-width:288px;--k-row:round(calc(32px * var(--k-density)),2px);--k-pad:round(calc(10px * var(--k-density)),2px);--k-inset:var(--k-pad);--k-gap:round(calc(var(--k-unit) * var(--k-density)),1px);--k-radius:round(calc(8px * var(--k-density)),2px);--k-panel-radius:calc(var(--k-radius) + var(--k-unit));
731
- --k-font-size:round(calc(12px * var(--k-density)),.5px);--k-label-weight:500;--k-blur:1;--k-glow:0.5;--k-roll:320;--k-drag-roll:0;--k-cascade:12;--k-glass:0.6;
732
- --k-font:system-ui,-apple-system,"SF Pro Text",sans-serif;
733
- --k-mono:"SF Mono",SFMono-Regular,ui-monospace,Menlo,monospace;
734
- --k-spring:0.24 0.16;--k-ease:cubic-bezier(.2,.8,.2,1);--k-reveal-ease:var(--k-ease);
735
- --k-font-weight:400;--k-title-weight:600;--k-thumb:#fff;--k-lift:1;--k-frame:card;
736
- --k-row-gap:0px;--k-hover-in:0;--k-hover-out:120;--k-fill-base:var(--k-surface-hi);--k-fill-rest-mix:20%;--k-fill-hover-mix:var(--k-fill-rest-mix);--k-fill-active-mix:30%;--k-chrome:1;--k-handle:var(--k-accent);--k-handle-inset:0px;--k-handle-rest:0;--k-step-resist:0.25;--k-motion-blur:0;--k-range-blur:.5;--k-curve-blur:.5;--k-group-transform:uppercase;--k-value-font:var(--k-font);
737
- --k-lead:${lead.easing};--k-trail:${trail.easing};--k-fill-ease:${fill.easing};--k-fill-ms:${fill.ms};
2338
+ --k-rim-width:1px;
2339
+ --k-blur:1;--k-roll:320;--k-drag-roll:0;--k-cascade:12;
2340
+ --k-ease:cubic-bezier(.2,.8,.2,1);
2341
+ --k-lift:1;--k-frame:card;
2342
+ --k-row-gap:0px;--k-fill-rest-mix:20%;--k-fill-active-mix:30%;--k-chrome:1;--k-handle-inset:0px;--k-handle-rest:0;--k-step-resist:0.25;--k-motion-blur:0;--k-range-blur:.5;--k-curve-blur:.5;--k-group-transform:uppercase;
2343
+ --k-lead:${lead.easing};--k-trail:${trail.easing};
738
2344
  --k-lens-ms:180;--k-lens-lead:1;--k-lens-wash:.9;--k-lens-line:.65;--k-lens-panel-wash:.35;--k-lens-inset:0px;--k-lens-panel-inset:0px;
739
2345
  --k-armed-edge:.1;--k-armed-glow:0;--k-armed-glow-a:0;--k-title-rest:.6;--k-esc-hint-ms:1800;
740
2346
  }
@@ -742,45 +2348,23 @@ ${GRAD_PROPS}
742
2348
  @media(min-resolution:1.5dppx){:where(:root,:host){--k-rim-width:.67px}}
743
2349
  @media(min-resolution:2dppx){:where(:root,:host){--k-rim-width:.5px}}
744
2350
  @media(min-resolution:3dppx){:where(:root,:host){--k-rim-width:.34px}}
745
- :where(.knobs-panel,.knobs-chip,.knobs-toast)[data-theme="light"],
746
- :where([data-knobs-theme="light"]) :where(.knobs-panel,.knobs-chip,.knobs-toast):not([data-theme="dark"]),
747
- :where(:root[data-theme="light"]) :where(.knobs-panel,.knobs-chip,.knobs-toast)[data-theme="auto"]{${lightVars}}
748
- @media(prefers-color-scheme:light){
749
- :where(:root:not([data-theme="dark"])) :where(.knobs-panel,.knobs-chip,.knobs-toast)[data-theme="auto"]{${lightVars}}
750
- }
751
- :where(.knobs-panel)[data-density="compact"]{--k-density:.875;--k-row:28px;--k-gap:3px;--k-radius:6px;--k-panel-radius:calc(var(--k-radius) + var(--k-unit));--k-pad:8px;--k-inset:8px;--k-font-size:11px}
752
- :where(.knobs-panel)[data-density="comfortable"]{--k-density:1.1875;--k-row:38px;--k-gap:6px;--k-radius:10px;--k-panel-radius:calc(var(--k-radius) + var(--k-unit));--k-pad:12px;--k-inset:12px;--k-font-size:13px}
753
- `, css = `
2351
+ :where(.knobs-root)[data-density="compact"]{--k-density:.875}
2352
+ :where(.knobs-root)[data-density="comfortable"]{--k-density:1.1875}
2353
+ `, css2 = `
754
2354
  :where(.knobs-panel,.knobs-chip,.knobs-menu){
755
- --k-tray-pad:calc(var(--k-unit) * .5);
756
- --k-section-gap:calc(var(--k-gap) * 2);
757
- --k-group-gap:calc(var(--k-gap) * 3);
758
- /* Public sizes a host may set anywhere (:root, the panel, a preset); derived otherwise. */
759
- --kc-control-h:var(--k-control-h,calc(var(--k-row) - var(--k-unit) * 2));
760
- --kc-value-size:var(--k-value-size,calc(var(--k-font-size) - .5px));
761
- --k-action-h:calc(var(--k-row) - var(--k-unit));
762
- --k-track-h:calc(var(--k-row) - 14px);
2355
+ --k-section-gap:calc(var(--_k-gap) * 2);
2356
+ --k-group-gap:calc(var(--_k-gap) * 3);
2357
+ --k-action-h:calc(var(--_k-row) - var(--_k-unit));
2358
+ --k-track-h:calc(var(--_k-row) - 14px);
763
2359
  --k-icon-btn:22px;
764
2360
  --k-icon-size:14px;
765
2361
  --k-icon-sm:13px;
766
- --k-radius-md:max(0px,calc(var(--k-radius) - var(--k-tray-pad)));
767
- --k-radius-sm:max(0px,calc(var(--k-radius) - var(--k-tray-pad) * 2));
768
- /* Round things (switches, icon buttons, handles, thumbs): capsules, or square with --k-radius 0. */
769
- --k-round:calc(var(--k-radius) * 999);
770
- --k-lift-shadow:0 1px 2px rgba(0,0,0,calc(.16 * var(--k-lift)));
771
- --k-text-title:calc(var(--k-font-size) + 1px);
772
- --k-text-body:var(--k-font-size);
773
- --k-text-control:calc(var(--k-font-size) - .5px);
774
- --k-text-meta:calc(var(--k-font-size) - 1px);
775
- --k-text-cap:calc(var(--k-font-size) - 2px);
776
- --k-row-hover:color-mix(in srgb,var(--k-surface) 50%,transparent);
777
- --k-pill-bg:color-mix(in srgb,var(--k-accent) 18%,var(--k-seg-active));
778
- --k-pill-border:color-mix(in srgb,var(--k-accent) 18%,transparent);
779
- --k-fill-rest:color-mix(in srgb,var(--k-accent) var(--k-fill-rest-mix),var(--k-fill-base));
780
- --k-fill-active:color-mix(in srgb,var(--k-accent) var(--k-fill-active-mix),var(--k-fill-base));
2362
+ --k-pill-bg:color-mix(in srgb,var(--_k-accent) 18%,var(--_k-segmented-active));
2363
+ --k-pill-border:color-mix(in srgb,var(--_k-accent) 18%,transparent);
2364
+ --k-fill-active:color-mix(in srgb,var(--_k-accent) var(--k-fill-active-mix),var(--_k-fill-base));
781
2365
  --k-disabled-opacity:.32;
782
- --k-unit-gap:.28em;--k-unit-color:var(--k-dim);--k-readout-mark:0;
783
- --k-group-size:var(--k-text-cap);--k-group-color:var(--k-group-ink);--k-group-inset:var(--k-inset);--k-group-tracking:.04em;--k-group-divider:transparent;--k-group-divider-gap:0px;
2366
+ --k-unit-gap:.28em;--k-unit-color:var(--_k-fg-3);--k-readout-mark:0;
2367
+ --k-group-size:var(--_k-text-cap);--k-group-inset:var(--_k-inset);--k-group-tracking:.04em;--k-group-divider:transparent;--k-group-divider-gap:0px;
784
2368
  --k-curve-inset:6px;--k-curve-guide:solid;--k-curve-dot:1;
785
2369
  --k-hint-typed-opacity:.42;
786
2370
  }
@@ -790,11 +2374,11 @@ ${GRAD_PROPS}
790
2374
  .knobs-panel *:where(:not(.knobs-accessory,.knobs-accessory *,.knobs-live *)),.knobs-menu *{box-sizing:border-box;color:inherit;letter-spacing:inherit;word-spacing:inherit;line-height:inherit;text-transform:inherit;text-shadow:inherit;font-style:inherit}
791
2375
  /* Hover washes come in at --k-hover-in and leave at --k-hover-out (ms). Set per element, so a
792
2376
  hovered card doesn't hand its quick entrance to the rows inside it. */
793
- :where(.knobs-panel,.knobs-menu) *{--k-hover-t:calc(var(--k-hover-out) * 1ms)}
794
- :where(.knobs-panel,.knobs-menu) :is(:hover,.knobs-active){--k-hover-t:calc(var(--k-hover-in) * 1ms)}
2377
+ :where(.knobs-panel,.knobs-menu) *{--k-hover-t:calc(var(--_k-hover-out) * 1ms)}
2378
+ :where(.knobs-panel,.knobs-menu) :is(:hover,.knobs-active){--k-hover-t:calc(var(--_k-hover-in) * 1ms)}
795
2379
 
796
2380
  .knobs-panel,.knobs-chip{
797
- box-sizing:border-box;font:var(--k-font-weight) var(--k-font-size)/1.35 var(--k-font);color:var(--k-text);text-align:left;color-scheme:dark;
2381
+ box-sizing:border-box;font:var(--_k-weight) var(--_k-font-size)/1.35 var(--_k-font);color:var(--_k-fg);text-align:left;
798
2382
  -webkit-font-smoothing:antialiased;
799
2383
  }
800
2384
  /* Text properties a host page sets on its own elements (letter-spacing, capitals, shadows) stop
@@ -803,25 +2387,25 @@ ${GRAD_PROPS}
803
2387
  :where(.knobs-panel,.knobs-chip) :where(*,*::before,*::after){box-sizing:border-box}
804
2388
  .knobs-panel .rn-slot{box-sizing:content-box}
805
2389
  .knobs-panel [hidden],.knobs-panel[hidden],.knobs-chip[hidden]{display:none!important}
806
- .knobs-mono{font-family:var(--k-mono);font-variant-numeric:tabular-nums}
2390
+ .knobs-mono{font-family:var(--_k-mono);font-variant-numeric:tabular-nums}
807
2391
 
808
2392
  /* The chip: a round cog button, or a capsule with a label beside the cog. */
809
- .knobs-chip{position:fixed;z-index:2147480000;display:inline-flex;align-items:center;justify-content:center;gap:5px;width:26px;height:26px;padding:0;border-radius:999px;cursor:pointer;background:var(--k-bg);border:1px solid transparent;
810
- color:var(--k-label);font-size:var(--k-text-control);line-height:1;letter-spacing:.01em;white-space:nowrap;--k-chip-edge:var(--k-edge);box-shadow:0 0 0 var(--k-rim-width) var(--k-chip-edge),0 4px 16px rgba(0,0,0,.35),inset 0 var(--k-rim-width) 0 var(--k-rim);transition:color .15s,border-color .15s,transform .2s var(--k-ease),opacity .2s,scale .12s var(--k-ease),${TOKEN_TRANSITIONS};}
2393
+ .knobs-chip{position:fixed;z-index:2147480000;display:inline-flex;align-items:center;justify-content:center;gap:5px;width:26px;height:26px;padding:0;border-radius:999px;cursor:pointer;background:var(--_k-bg);border:1px solid transparent;
2394
+ color:var(--_k-fg-2);font-size:var(--_k-text-control);line-height:1;letter-spacing:.01em;white-space:nowrap;--k-chip-edge:var(--_k-border-subtle);box-shadow:0 0 0 var(--k-rim-width) var(--k-chip-edge),0 4px 16px rgba(0,0,0,calc(.35 * var(--_k-shadow-k,1))),inset 0 var(--k-rim-width) 0 var(--_k-rim);transition:color .15s,border-color .15s,transform .2s var(--k-ease),opacity .2s,scale .12s var(--k-ease),${TOKEN_TRANSITIONS};}
811
2395
  .knobs-chip[data-label]{width:auto;padding:0 10px 0 7px}
812
2396
  .knobs-chip .knobs-icon{display:block;flex:none;width:15px;height:15px}
813
- .knobs-chip:hover{color:var(--k-text);--k-chip-edge:var(--k-line-hi)}
2397
+ .knobs-chip:hover{color:var(--_k-fg);--k-chip-edge:var(--_k-border-strong)}
814
2398
  .knobs-chip[data-shown="true"]{transition:color .15s,border-color .15s,opacity .16s var(--k-ease),transform .22s var(--k-ease),scale .12s var(--k-ease),visibility 0s,${TOKEN_TRANSITIONS}}
815
2399
  .knobs-chip[data-shown="false"]{opacity:0;visibility:hidden;pointer-events:none;transform:translateY(-2px) scale(.94);transition:opacity .12s ease-in,transform .12s ease-in,visibility 0s .12s,${TOKEN_TRANSITIONS}}
816
2400
  /* A press squeezes it, easing in (morph.ts carries the squeeze on into the glass). */
817
2401
  .knobs-chip.knobs-chip[data-pressed]{scale:.94;transition:color .15s,border-color .15s,scale 50ms ease-in-out,${TOKEN_TRANSITIONS}}
818
- .knobs-chip:focus-visible{outline:none;color:var(--k-text);--k-chip-edge:var(--k-line-hi)}
2402
+ .knobs-chip:focus-visible{outline:none;color:var(--_k-fg);--k-chip-edge:var(--_k-border-strong)}
819
2403
  @media(prefers-reduced-motion:reduce){.knobs-chip.knobs-chip{scale:none;transform:none}}
820
2404
  /* "knobs on" / "knobs off" after the reveal shortcut. */
821
- .knobs-toast{position:fixed;left:50%;bottom:24px;z-index:2147480004;translate:-50% 0;padding:6px 12px;border-radius:999px;pointer-events:none;
822
- background:var(--k-bg);border:1px solid var(--k-line);box-shadow:0 4px 16px rgba(0,0,0,.35);color:var(--k-text);font:500 12px/1.2 var(--k-font);letter-spacing:.01em;
2405
+ .knobs-notice{position:fixed;left:50%;bottom:24px;z-index:2147480004;translate:-50% 0;padding:6px 12px;border-radius:999px;pointer-events:none;
2406
+ background:var(--_k-bg);border:1px solid var(--_k-border);box-shadow:0 4px 16px rgba(0,0,0,calc(.35 * var(--_k-shadow-k,1)));color:var(--_k-fg);font:500 12px/1.2 var(--_k-font);letter-spacing:.01em;
823
2407
  transition:opacity .18s var(--k-ease),scale .18s var(--k-ease)}
824
- .knobs-toast[data-shown="false"]{opacity:0;scale:.96;transition:opacity .16s ease-in,scale .16s ease-in}
2408
+ .knobs-notice[data-shown="false"]{opacity:0;scale:.96;transition:opacity .16s ease-in,scale .16s ease-in}
825
2409
 
826
2410
  /* Tokens glide on the panel spring. While a control is dragged (data-knobs-scrub) they follow it
827
2411
  step for step instead: the pointer already moves them continuously, and a declared transition
@@ -835,12 +2419,12 @@ ${GRAD_PROPS}
835
2419
  backdrop, toned toward the theme (--k-glass-tone dims it under dark panels) so text keeps its
836
2420
  contrast. Its edge is a hairline (--k-edge, --k-rim-width wide) and a hairline of light (--k-rim)
837
2421
  catches its top. */
838
- .knobs-panel{-webkit-user-select:none;user-select:none;transition:${TOKEN_TRANSITIONS},--k-armed ${ARMED_T};position:fixed;z-index:2147480001;width:var(--k-width);max-width:calc(100vw - 16px);max-height:calc(100dvh - 16px);overflow:auto;padding:var(--k-pad);
839
- background:color-mix(in srgb,var(--k-bg) calc(100% - var(--k-glass) * 20%),transparent);border:1px solid transparent;border-radius:var(--k-panel-radius);box-shadow:var(--k-shadow),0 0 0 var(--k-rim-width) var(--ka-edge),inset 0 var(--k-rim-width) 0 var(--k-rim),var(--ka-glow);scrollbar-width:thin;
2422
+ .knobs-panel{-webkit-user-select:none;user-select:none;transition:${TOKEN_TRANSITIONS},--k-armed ${ARMED_T};position:fixed;z-index:2147480001;width:var(--_k-width);max-width:calc(100vw - 16px);max-height:calc(100dvh - 16px);overflow:auto;padding:var(--_k-pad);
2423
+ background:color-mix(in srgb,var(--_k-bg) calc(100% - var(--_k-glass) * 20%),transparent);border:1px solid transparent;border-radius:var(--_k-radius-panel);box-shadow:var(--_k-shadow-overlay),0 0 0 var(--k-rim-width) var(--ka-edge),inset 0 var(--k-rim-width) 0 var(--_k-rim),var(--ka-glow);scrollbar-width:thin;
840
2424
  /* Armed (focus inside: keys come here), the edge takes the accent and a faint glow lifts it. */
841
- --ka-edge:color-mix(in srgb,var(--k-accent) calc(var(--k-armed) * var(--k-armed-edge) * 100%),var(--k-edge));
842
- --ka-glow:0 0 calc(var(--k-armed-glow) * 1px) color-mix(in srgb,var(--k-accent) calc(var(--k-armed) * var(--k-armed-glow-a) * var(--k-chrome,1) * 100%),transparent);
843
- --k-backdrop:blur(calc(var(--k-glass) * 24px)) saturate(calc(1 + var(--k-glass) * .8)) brightness(calc(1 + (var(--k-glass-tone) - 1) * var(--k-glass)));
2425
+ --ka-edge:color-mix(in srgb,var(--_k-accent) calc(var(--k-armed) * var(--k-armed-edge) * 100%),var(--_k-border-subtle));
2426
+ --ka-glow:0 0 calc(var(--k-armed-glow) * 1px) color-mix(in srgb,var(--_k-accent) calc(var(--k-armed) * var(--k-armed-glow-a) * var(--k-chrome,1) * 100%),transparent);
2427
+ --k-backdrop:blur(calc(var(--_k-glass) * 24px)) saturate(calc(1 + var(--_k-glass) * .8)) brightness(calc(1 + (var(--_k-glass-tone) - 1) * var(--_k-glass)));
844
2428
  -webkit-backdrop-filter:var(--k-backdrop);backdrop-filter:var(--k-backdrop);
845
2429
  animation:knobs-in .16s var(--k-ease);}
846
2430
  .knobs-panel[data-restored]{animation:none}
@@ -848,21 +2432,21 @@ ${GRAD_PROPS}
848
2432
  content, laid out at full size, is clipped to it and revealed top first. */
849
2433
  .knobs-panel[data-morphing]{background:transparent;border-color:transparent;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none;animation:none}
850
2434
  .knobs-morph{position:fixed;left:0;top:0;z-index:2147480001;pointer-events:none;box-sizing:border-box;--p:0;--spec:0;
851
- background:color-mix(in srgb,var(--k-bg) calc(100% - var(--k-glass) * 20% * var(--p)),transparent);border:1px solid transparent;
852
- box-shadow:0 0 0 var(--k-rim-width) var(--k-edge),inset 0 0 0 var(--k-rim-width) rgb(255 255 255/var(--spec)),inset 0 var(--k-rim-width) 0 color-mix(in srgb,var(--k-rim) calc(var(--p) * 100%),transparent);
853
- --k-backdrop:blur(calc(var(--k-glass) * 24px)) saturate(calc(1 + var(--k-glass) * .8)) brightness(calc(1 + (var(--k-glass-tone) - 1) * var(--k-glass)));
2435
+ background:color-mix(in srgb,var(--_k-bg) calc(100% - var(--_k-glass) * 20% * var(--p)),transparent);border:1px solid transparent;
2436
+ box-shadow:0 0 0 var(--k-rim-width) var(--_k-border-subtle),inset 0 0 0 var(--k-rim-width) rgb(255 255 255/var(--spec)),inset 0 var(--k-rim-width) 0 color-mix(in srgb,var(--_k-rim) calc(var(--p) * 100%),transparent);
2437
+ --k-backdrop:blur(calc(var(--_k-glass) * 24px)) saturate(calc(1 + var(--_k-glass) * .8)) brightness(calc(1 + (var(--_k-glass-tone) - 1) * var(--_k-glass)));
854
2438
  -webkit-backdrop-filter:var(--k-backdrop);backdrop-filter:var(--k-backdrop)}
855
2439
  .knobs-morph::before,.knobs-morph::after{content:"";position:absolute;inset:-1px;border-radius:inherit;pointer-events:none}
856
- .knobs-morph::before{box-shadow:0 4px 16px rgba(0,0,0,.35);opacity:calc(1 - var(--p))}
857
- .knobs-morph::after{box-shadow:var(--k-shadow);opacity:var(--p)}
2440
+ .knobs-morph::before{box-shadow:0 4px 16px rgba(0,0,0,calc(.35 * var(--_k-shadow-k,1)));opacity:calc(1 - var(--p))}
2441
+ .knobs-morph::after{box-shadow:var(--_k-shadow-overlay);opacity:var(--p)}
858
2442
  /* Meanwhile the chip is just its label, fading on the shape. */
859
2443
  .knobs-chip.knobs-chip[data-morph]{visibility:visible;pointer-events:auto;transform:none;transition:none;background:transparent;border-color:transparent;box-shadow:none}
860
- .knobs-panel.knobs-inline{position:relative;z-index:auto;left:auto!important;top:auto!important;max-width:100%;max-height:none;box-shadow:0 0 0 var(--k-rim-width) color-mix(in srgb,var(--ka-edge) calc(var(--k-chrome) * 100%),transparent),inset 0 var(--k-rim-width) 0 color-mix(in srgb,var(--k-rim) calc(var(--k-chrome) * 100%),transparent),var(--ka-glow);animation:none;
2444
+ .knobs-panel.knobs-inline{position:relative;z-index:auto;left:auto!important;top:auto!important;max-width:100%;max-height:none;box-shadow:0 0 0 var(--k-rim-width) color-mix(in srgb,var(--ka-edge) calc(var(--k-chrome) * 100%),transparent),inset 0 var(--k-rim-width) 0 color-mix(in srgb,var(--_k-rim) calc(var(--k-chrome) * 100%),transparent),var(--ka-glow);animation:none;
861
2445
  /* --k-chrome 0: an embedded panel sheds its card (background, border, rim) for the host's column,
862
2446
  border width too, so its rows line up with the column's edges. */
863
2447
  border-width:calc(var(--k-chrome) * 1px);
864
- background:color-mix(in srgb,color-mix(in srgb,var(--k-bg) calc(100% - var(--k-glass) * 20%),transparent) calc(var(--k-chrome) * 100%),transparent);border-color:transparent;
865
- --k-backdrop:blur(calc(var(--k-glass) * var(--k-chrome) * 24px)) saturate(calc(1 + var(--k-glass) * var(--k-chrome) * .8)) brightness(calc(1 + (var(--k-glass-tone) - 1) * var(--k-glass) * var(--k-chrome)))}
2448
+ background:color-mix(in srgb,color-mix(in srgb,var(--_k-bg) calc(100% - var(--_k-glass) * 20%),transparent) calc(var(--k-chrome) * 100%),transparent);border-color:transparent;
2449
+ --k-backdrop:blur(calc(var(--_k-glass) * var(--k-chrome) * 24px)) saturate(calc(1 + var(--_k-glass) * var(--k-chrome) * .8)) brightness(calc(1 + (var(--_k-glass-tone) - 1) * var(--_k-glass) * var(--k-chrome)))}
866
2450
  @keyframes knobs-in{from{opacity:0;transform:translateY(4px) scale(.985)}to{opacity:1;transform:none}}
867
2451
  @media(prefers-reduced-motion:reduce){.knobs-panel{animation:none}.knobs-panel *{transition:none!important}.knobs-keys .knobs-keys-text,.knobs-number,.knobs-cell-edit{animation:none}}
868
2452
 
@@ -870,13 +2454,13 @@ ${GRAD_PROPS}
870
2454
  input[type=text]{...}) and below every knobs rule that styles these elements, which are all
871
2455
  (0,1,1) or more and come later. */
872
2456
  :is(.knobs-panel,.knobs-menu) :is(button,input,select,textarea):where(:not(.knobs-accessory *)){all:revert;box-sizing:border-box;font:inherit;color:inherit;letter-spacing:inherit;text-transform:inherit;text-shadow:none;
873
- background:var(--k-surface);border:0;border-radius:var(--k-radius);min-width:0;box-shadow:none;outline:none}
2457
+ background:var(--_k-fill);border:0;border-radius:var(--_k-radius);min-width:0;box-shadow:none;outline:none}
874
2458
  :is(.knobs-panel,.knobs-menu) :is(header,strong,p,kbd,aside,mark):where(:not(.knobs-accessory *)){all:revert;box-sizing:border-box;margin:0;padding:0;font:inherit;color:inherit;letter-spacing:inherit;text-transform:inherit}
875
2459
  .knobs-panel .knobs-icon>path{fill:currentColor}
876
2460
  :is(.knobs-panel,.knobs-menu) :is(:focus,:focus-visible):where(:not(.knobs-accessory *)){outline:none}
877
2461
 
878
2462
  /* Header */
879
- .knobs-panel header{position:relative;display:flex;align-items:center;justify-content:space-between;gap:6px;cursor:grab;touch-action:none;padding:0 var(--k-inset) var(--k-section-gap);min-height:var(--k-icon-btn)}
2463
+ .knobs-panel header{position:relative;display:flex;align-items:center;justify-content:space-between;gap:6px;cursor:grab;touch-action:none;padding:0 var(--_k-inset) var(--k-section-gap);min-height:var(--k-icon-btn)}
880
2464
  .knobs-panel.knobs-inline header,.knobs-panel.knobs-inline header:active{cursor:default}
881
2465
  /* The title row stays pinned while the rows scroll under it, in the panel (it scrolls once it's
882
2466
  bounded) or, with .knobs-pin-ancestor (which also makes the panel overflow:visible), in the
@@ -892,8 +2476,8 @@ ${GRAD_PROPS}
892
2476
  @supports (animation-timeline:scroll()){
893
2477
  .knobs-panel:not(.knobs-page){scroll-timeline:--knobs-self block}
894
2478
  .knobs-panel.knobs-pin-ancestor:not(.knobs-page){overflow:visible;view-timeline:--knobs-view block}
895
- .knobs-panel:not(.knobs-page)>header{position:sticky;top:0;z-index:4;border-radius:max(0px,calc(var(--k-panel-radius) - 1px)) max(0px,calc(var(--k-panel-radius) - 1px)) 0 0;
896
- --k-head-on:max(var(--k-head-s),var(--k-head-v));--k-head-bg:color-mix(in srgb,var(--k-bg) 88%,transparent);
2479
+ .knobs-panel:not(.knobs-page)>header{position:sticky;top:0;z-index:4;border-radius:max(0px,calc(var(--_k-radius-panel) - 1px)) max(0px,calc(var(--_k-radius-panel) - 1px)) 0 0;
2480
+ --k-head-on:max(var(--k-head-s),var(--k-head-v));--k-head-bg:color-mix(in srgb,var(--_k-bg) 88%,transparent);
897
2481
  background:color-mix(in srgb,var(--k-head-bg) calc(var(--k-head-on) * 100%),transparent);
898
2482
  animation:knobs-head-s linear both;animation-timeline:--knobs-self;animation-range:0px 24px}
899
2483
  .knobs-panel.knobs-pin-ancestor:not(.knobs-page)>header{animation:knobs-head-v linear both;animation-timeline:--knobs-view;animation-range:exit-crossing 0px exit-crossing 24px}
@@ -903,41 +2487,41 @@ ${GRAD_PROPS}
903
2487
  .knobs-panel[data-gpu-active="true"]:not(.knobs-page)>header::after{display:none}
904
2488
  }
905
2489
  .knobs-panel header:active{cursor:grabbing}
906
- .knobs-panel header strong{flex:1;min-width:0;font-weight:var(--k-title-weight);font-size:var(--k-text-title);letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:opacity .2s var(--k-ease),color ${ARMED_T};
907
- color:color-mix(in srgb,var(--k-text) calc(var(--k-title-rest) * 100%),var(--k-label))}
2490
+ .knobs-panel header strong{flex:1;min-width:0;font-weight:var(--_k-weight-title);font-size:var(--_k-text-title);letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:opacity .2s var(--k-ease),color ${ARMED_T};
2491
+ color:color-mix(in srgb,var(--_k-fg) calc(var(--k-title-rest) * 100%),var(--_k-fg-2))}
908
2492
  /* At rest a panel's title is a little quiet; armed (keys come here) it's at full strength. */
909
- .knobs-panel[data-k-armed] header strong{color:var(--k-text)}
2493
+ .knobs-panel[data-k-armed] header strong{color:var(--_k-fg)}
910
2494
  /* The scope line beside the title (crumbs.ts): where keys go, and for a moment where Esc goes. */
911
- .knobs-crumbs{position:absolute;left:0;top:50%;height:0;pointer-events:none;white-space:nowrap;font-size:var(--k-text-meta);font-weight:var(--k-label-weight);line-height:1.2;letter-spacing:0;text-transform:none}
912
- .knobs-crumbs>*{position:absolute;left:0;top:0;translate:0 -50%;color:var(--k-dim);transition:opacity .2s var(--k-ease),translate ${CRUMB_GLIDE},color .2s var(--k-ease)}
2495
+ .knobs-crumbs{position:absolute;left:0;top:50%;height:0;pointer-events:none;white-space:nowrap;font-size:var(--_k-text-meta);font-weight:var(--_k-weight-label);line-height:1.2;letter-spacing:0;text-transform:none}
2496
+ .knobs-crumbs>*{position:absolute;left:0;top:0;translate:0 -50%;color:var(--_k-fg-3);transition:opacity .2s var(--k-ease),translate ${CRUMB_GLIDE},color .2s var(--k-ease)}
913
2497
  .knobs-crumbs>[data-leaving]{transition:opacity .14s cubic-bezier(.4,0,1,1),translate .14s cubic-bezier(.4,0,1,1)}
914
2498
  .knobs-crumbs>.knobs-crumb-crumb{pointer-events:auto;cursor:pointer}
915
- .knobs-crumbs>.knobs-crumb-crumb[data-deep]{color:var(--k-text)}
916
- .knobs-crumbs>.knobs-crumb-crumb:not([data-deep]):hover{color:var(--k-label)}
917
- .knobs-crumbs>.knobs-crumb-sep{color:color-mix(in srgb,var(--k-dim) 70%,transparent)}
918
- .knobs-crumbs>.knobs-crumb-esc{font-family:var(--k-mono);font-size:var(--k-text-cap);transition:opacity .35s var(--k-ease),translate ${CRUMB_GLIDE}}
2499
+ .knobs-crumbs>.knobs-crumb-crumb[data-deep]{color:var(--_k-fg)}
2500
+ .knobs-crumbs>.knobs-crumb-crumb:not([data-deep]):hover{color:var(--_k-fg-2)}
2501
+ .knobs-crumbs>.knobs-crumb-sep{color:color-mix(in srgb,var(--_k-fg-3) 70%,transparent)}
2502
+ .knobs-crumbs>.knobs-crumb-esc{font-family:var(--_k-mono);font-size:var(--_k-text-cap);transition:opacity .35s var(--k-ease),translate ${CRUMB_GLIDE}}
919
2503
  @media(prefers-reduced-motion:reduce){.knobs-panel .knobs-crumbs>*{transition:opacity .15s linear!important}}
920
2504
  .knobs-panel[data-gpu-active="true"] .knobs-crumbs>*{color:transparent!important}
921
2505
  /* Holding \\ shows the values from before the last change; the title dims meanwhile. */
922
2506
  .knobs-panel[data-comparing] header strong{opacity:.4}
923
2507
  .knobs-head-actions{display:flex;align-items:center;margin-right:calc((var(--k-icon-size) - var(--k-icon-btn)) / 2)}
924
- .knobs-head-split{margin-left:calc(var(--k-unit) * 1.5)}
2508
+ .knobs-head-split{margin-left:calc(var(--_k-unit) * 1.5)}
925
2509
  .knobs-icon{width:var(--k-icon-size);height:var(--k-icon-size);display:block;flex:none}
926
2510
  .knobs-die-icon{position:relative;display:block;width:var(--k-icon-size);height:var(--k-icon-size);flex:none}
927
2511
  .knobs-die-icon>canvas{position:absolute;margin:0}
928
2512
  .knobs-panel[data-gpu-active="true"] .knobs-die-icon>canvas{visibility:hidden}
929
2513
  /* The tools sit quiet (--k-dim) until the panel has the pointer or keyboard focus, then read as
930
2514
  labels, and as text under the pointer. */
931
- .knobs-panel header button{position:relative;width:var(--k-icon-btn);height:var(--k-icon-btn);padding:0;display:inline-flex;align-items:center;justify-content:center;color:var(--k-dim);background:transparent;border-radius:var(--k-round);cursor:pointer;font-size:12px;line-height:1;transition:background var(--k-hover-t),color var(--k-hover-t),opacity .15s}
932
- .knobs-panel:is(:hover,:has(:focus-visible)) header button{color:var(--k-label)}
933
- .knobs-panel header button:is(:hover:not([disabled]),:focus-visible),.knobs-panel header button[aria-expanded="true"]{background:var(--k-surface-hi);color:var(--k-text)}
2515
+ .knobs-panel header button{position:relative;width:var(--k-icon-btn);height:var(--k-icon-btn);padding:0;display:inline-flex;align-items:center;justify-content:center;color:var(--_k-fg-3);background:transparent;border-radius:var(--_k-round);cursor:pointer;font-size:12px;line-height:1;transition:background var(--k-hover-t),color var(--k-hover-t),opacity .15s}
2516
+ .knobs-panel:is(:hover,:has(:focus-visible)) header button{color:var(--_k-fg-2)}
2517
+ .knobs-panel header button:is(:hover:not([disabled]),:focus-visible),.knobs-panel header button[aria-expanded="true"]{background:var(--_k-fill-selected);color:var(--_k-fg)}
934
2518
  .knobs-panel header button[disabled]{opacity:var(--k-disabled-opacity);cursor:default}
935
2519
  /* The close X's ink sits a fifth of its box in from each side, a digit's barely: nudged right, its
936
2520
  ink ends where the values' digits do. */
937
2521
  .knobs-panel header .knobs-close>.knobs-icon{translate:calc(var(--k-icon-size) * .1) 0}
938
2522
  /* Undo · Redo sit apart from Reset · Copy · Random. Undo, Redo and Reset (and a group's reset)
939
2523
  keep their slots while they're away and bloom in and out of them: nothing beside them moves. */
940
- .knobs-head-history{display:flex;flex:none;margin-right:calc(var(--k-unit) * 1.5)}
2524
+ .knobs-head-history{display:flex;flex:none;margin-right:calc(var(--_k-unit) * 1.5)}
941
2525
  .knobs-panel :is(.knobs-head-actions,.knobs-group-head) button[data-shown]{transition:background var(--k-hover-t),color var(--k-hover-t),opacity ${BLOOM_IN},scale ${BLOOM_IN},filter 0s,visibility 0s}
942
2526
  .knobs-panel :is(.knobs-head-actions,.knobs-group-head) button[data-shown="false"]{opacity:0;scale:.9;filter:blur(2.5px);visibility:hidden;
943
2527
  transition:background var(--k-hover-t),color var(--k-hover-t),opacity ${BLOOM_OUT},scale ${BLOOM_OUT},filter ${BLOOM_OUT},visibility 0s ${snappyOut.ms}ms}
@@ -946,9 +2530,9 @@ ${GRAD_PROPS}
946
2530
  .knobs-panel :is(.knobs-head-actions,.knobs-group-head) button[data-shown="false"]{scale:1;filter:none;transition:opacity .15s,visibility 0s .15s!important}}
947
2531
  /* A press flash (flash.ts): from a key or a click, the button's wash brightens at once and eases
948
2532
  back to its own, its ink with it. Two names, so a second press restarts it. */
949
- @keyframes knobs-flash-a{from{background-color:var(--k-flash-bg);color:var(--k-text)}}
950
- @keyframes knobs-flash-b{from{background-color:var(--k-flash-bg);color:var(--k-text)}}
951
- .knobs-panel :is(header,.knobs-group-head) button{--k-flash-bg:color-mix(in srgb,var(--k-surface-hi),var(--k-text) 10%)}
2533
+ @keyframes knobs-flash-a{from{background-color:var(--k-flash-bg);color:var(--_k-fg)}}
2534
+ @keyframes knobs-flash-b{from{background-color:var(--k-flash-bg);color:var(--_k-fg)}}
2535
+ .knobs-panel :is(header,.knobs-group-head) button{--k-flash-bg:color-mix(in srgb,var(--_k-fill-selected),var(--_k-fg) 10%)}
952
2536
  .knobs-panel :is(header,.knobs-group-head) button[data-k-flash="a"]{animation:knobs-flash-a ${FLASH_MS}ms cubic-bezier(.33,1,.68,1)}
953
2537
  .knobs-panel :is(header,.knobs-group-head) button[data-k-flash="b"]{animation:knobs-flash-b ${FLASH_MS}ms cubic-bezier(.33,1,.68,1)}
954
2538
  /* Copied: the glyph shrinks away and a check draws itself in its place, held, then they trade
@@ -956,7 +2540,7 @@ ${GRAD_PROPS}
956
2540
  drawn) and --k-check-a (its opacity), which the GPU renderer reads too. */
957
2541
  .knobs-panel header .knobs-copy{--k-copy:1;--k-check:0;--k-check-a:0;
958
2542
  transition:background var(--k-hover-t),color var(--k-hover-t),opacity .15s,--k-copy ${BLOOM_IN} .04s,--k-check 0s .1s,--k-check-a .1s cubic-bezier(.4,0,1,1)}
959
- .knobs-panel header .knobs-copy[data-copied]{--k-copy:0;--k-check:1;--k-check-a:1;color:var(--k-text);
2543
+ .knobs-panel header .knobs-copy[data-copied]{--k-copy:0;--k-check:1;--k-check-a:1;color:var(--_k-fg);
960
2544
  transition:background var(--k-hover-t),color var(--k-hover-t),opacity .15s,--k-copy .1s cubic-bezier(.4,0,1,1),--k-check .18s cubic-bezier(.2,.8,.2,1) .03s,--k-check-a .04s linear .03s}
961
2545
  .knobs-copy>.knobs-icon:not(.knobs-check){opacity:var(--k-copy);scale:calc(.5 + .5 * var(--k-copy))}
962
2546
  .knobs-copy>.knobs-check{position:absolute;inset:0;margin:auto;opacity:var(--k-check-a)}
@@ -965,56 +2549,56 @@ ${GRAD_PROPS}
965
2549
  .knobs-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
966
2550
 
967
2551
  /* Shortcuts Popover */
968
- .knobs-popover{margin:0 0 var(--k-section-gap);padding:var(--k-section-gap) var(--k-inset);background:var(--k-surface-hi);border:1px solid var(--k-line);border-radius:var(--k-radius);font-size:var(--k-text-meta)}
2552
+ .knobs-popover{margin:0 0 var(--k-section-gap);padding:var(--k-section-gap) var(--_k-inset);background:var(--_k-fill-selected);border:1px solid var(--_k-border);border-radius:var(--_k-radius);font-size:var(--_k-text-meta)}
969
2553
  .knobs-popover-grid{display:grid;grid-template-columns:auto 1fr;gap:4px 12px;align-items:baseline}
970
- .knobs-popover-grid kbd{font:var(--k-text-cap)/1 var(--k-mono);font-variant-numeric:tabular-nums;color:var(--k-text);background:var(--k-seg-bg);padding:2px 5px;border-radius:var(--k-radius-sm);justify-self:start;white-space:nowrap}
971
- .knobs-popover-grid span{color:var(--k-label)}
2554
+ .knobs-popover-grid kbd{font:var(--_k-text-cap)/1 var(--_k-mono);font-variant-numeric:tabular-nums;color:var(--_k-fg);background:var(--_k-segmented-track);padding:2px 5px;border-radius:var(--_k-radius-sm);justify-self:start;white-space:nowrap}
2555
+ .knobs-popover-grid span{color:var(--_k-fg-2)}
972
2556
 
973
2557
  /* Custom Preset Strip */
974
- .knobs-presets{position:relative;display:flex;align-items:flex-start;gap:var(--k-tray-pad);margin:0 0 var(--k-section-gap);padding:var(--k-tray-pad);background:var(--k-seg-bg);border-radius:var(--k-radius);user-select:none;touch-action:none}
975
- .knobs-presets-track{position:relative;flex:1;min-width:0;display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,var(--k-preset-min,58px)),1fr));align-items:stretch;gap:var(--k-tray-pad)}
2558
+ .knobs-presets{position:relative;display:flex;align-items:flex-start;gap:var(--_k-tray-pad);margin:0 0 var(--k-section-gap);padding:var(--_k-tray-pad);background:var(--_k-segmented-track);border-radius:var(--_k-radius);user-select:none;touch-action:none}
2559
+ .knobs-presets-track{position:relative;flex:1;min-width:0;display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,var(--k-preset-min,58px)),1fr));align-items:stretch;gap:var(--_k-tray-pad)}
976
2560
  /* The selected pill is placed by its edges: the edge facing the move leads, the other trails. */
977
- .knobs-presets-pill{position:absolute;top:0;left:0;background:var(--k-pill-bg);border:0;border-radius:var(--k-button-radius,var(--k-radius-md));box-shadow:inset 0 0 0 var(--k-rim-width) var(--k-pill-border),inset 0 var(--k-rim-width) 0 var(--k-rim),var(--k-lift-shadow),0 0 calc(var(--k-glow) * 10px) color-mix(in srgb,var(--k-accent) 24%,transparent);pointer-events:none;
2561
+ .knobs-presets-pill{position:absolute;top:0;left:0;background:var(--k-pill-bg);border:0;border-radius:var(--k-button-radius,var(--_k-radius-md));box-shadow:inset 0 0 0 var(--k-rim-width) var(--k-pill-border),inset 0 var(--k-rim-width) 0 var(--_k-rim),var(--_k-shadow-raised),0 0 calc(var(--_k-glow) * 10px) color-mix(in srgb,var(--_k-accent) 24%,transparent);pointer-events:none;
978
2562
  transition:left ${TRAIL_T},right ${LEAD_T},top ${LEAD_T},opacity .15s,scale .15s}
979
2563
  .knobs-presets-pill[data-dir="left"]{transition:left ${LEAD_T},right ${TRAIL_T},top ${LEAD_T},opacity .15s,scale .15s}
980
- .knobs-panel .knobs-preset-chip{position:relative;z-index:1;height:var(--k-button-h,var(--kc-control-h));min-height:20px;padding:0 6px;font-size:var(--k-button-font-size,var(--k-text-control));font-weight:var(--k-label-weight);color:var(--k-button-color,var(--k-label));background:transparent!important;border-radius:var(--k-button-radius,var(--k-radius-md));cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .15s,background .15s,box-shadow .15s}
2564
+ .knobs-panel .knobs-preset-chip{position:relative;z-index:1;height:var(--k-button-h,var(--_k-control-h));min-height:20px;padding:0 6px;font-size:var(--k-button-font-size,var(--_k-text-control));font-weight:var(--_k-weight-label);color:var(--k-button-color,var(--_k-fg-2));background:transparent!important;border-radius:var(--k-button-radius,var(--_k-radius-md));cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .15s,background .15s,box-shadow .15s}
981
2565
  .knobs-panel[data-buttons] .knobs-presets{background:transparent;padding:0}
982
2566
  .knobs-panel[data-buttons] .knobs-preset-chip{background:var(--k-button-bg,transparent)!important;box-shadow:inset 0 0 0 1px var(--k-button-line,transparent)}
983
- .knobs-panel[data-buttons] .knobs-preset-chip:hover{background:var(--k-button-hover-bg,var(--k-surface-hi))!important;box-shadow:inset 0 0 0 1px var(--k-button-hover-line,var(--k-button-line,transparent))}
984
- .knobs-panel .knobs-preset-chip:hover{color:var(--k-text)}
985
- .knobs-panel .knobs-preset-chip[aria-checked="true"]{color:var(--k-text);font-weight:var(--k-title-weight)}
986
- .knobs-panel .knobs-preset-save{flex:none;width:calc((var(--k-inset) - var(--k-tray-pad)) * 2 + 8px);padding:0!important;color:var(--k-dim)!important;font-weight:400!important;font-size:var(--k-text-title)!important}
987
- .knobs-panel .knobs-preset-save:hover{color:var(--k-text)!important}
2567
+ .knobs-panel[data-buttons] .knobs-preset-chip:hover{background:var(--k-button-hover-bg,var(--_k-fill-selected))!important;box-shadow:inset 0 0 0 1px var(--k-button-hover-line,var(--k-button-line,transparent))}
2568
+ .knobs-panel .knobs-preset-chip:hover{color:var(--_k-fg)}
2569
+ .knobs-panel .knobs-preset-chip[aria-checked="true"]{color:var(--_k-fg);font-weight:var(--_k-weight-title)}
2570
+ .knobs-panel .knobs-preset-save{flex:none;width:calc((var(--_k-inset) - var(--_k-tray-pad)) * 2 + 8px);padding:0!important;color:var(--_k-fg-3)!important;font-weight:400!important;font-size:var(--_k-text-title)!important}
2571
+ .knobs-panel .knobs-preset-save:hover{color:var(--_k-fg)!important}
988
2572
  /* The active preset's modified mark: the values have drifted off it (a row's dot, in its corner). */
989
- .knobs-panel .knobs-preset-chip::after{content:"";position:absolute;top:4px;right:4px;width:4px;height:4px;border-radius:50%;background:var(--k-modified);opacity:0;transform:scale(.4);pointer-events:none;transition:opacity .16s ease-out,transform .28s cubic-bezier(.34,1.5,.64,1)}
2573
+ .knobs-panel .knobs-preset-chip::after{content:"";position:absolute;top:4px;right:4px;width:4px;height:4px;border-radius:50%;background:var(--_k-modified);opacity:0;transform:scale(.4);pointer-events:none;transition:opacity .16s ease-out,transform .28s cubic-bezier(.34,1.5,.64,1)}
990
2574
  .knobs-panel .knobs-preset-chip[data-drifted]::after{opacity:.95;transform:none}
991
2575
  /* Naming a saved preset: a field over its chip that opens out from the middle to the chip's width;
992
2576
  the chip's own name hides beneath it. Leaving, it fades. */
993
2577
  .knobs-panel .knobs-preset-chip[data-naming]{color:transparent!important}
994
- .knobs-panel .knobs-preset-name{position:absolute;z-index:2;box-sizing:border-box;min-width:0;margin:0;padding:0 6px;border:1px solid color-mix(in srgb,var(--k-accent) 55%,transparent);border-radius:var(--k-button-radius,var(--k-radius-md));outline:none;background:color-mix(in srgb,var(--k-accent) 10%,transparent);color:var(--k-text);caret-color:var(--k-accent);
995
- font-family:inherit;font-size:var(--k-button-font-size,var(--k-text-control));font-weight:var(--k-title-weight);letter-spacing:inherit;text-align:center;animation:knobs-name-in .25s cubic-bezier(.2,.8,.2,1);transition:opacity .11s cubic-bezier(.4,0,1,1)}
996
- .knobs-preset-name::selection{background:color-mix(in srgb,var(--k-accent) 24%,transparent);color:var(--k-text)}
2578
+ .knobs-panel .knobs-preset-name{position:absolute;z-index:2;box-sizing:border-box;min-width:0;margin:0;padding:0 6px;border:1px solid color-mix(in srgb,var(--_k-accent) 55%,transparent);border-radius:var(--k-button-radius,var(--_k-radius-md));outline:none;background:color-mix(in srgb,var(--_k-accent) 10%,transparent);color:var(--_k-fg);caret-color:var(--_k-accent);
2579
+ font-family:inherit;font-size:var(--k-button-font-size,var(--_k-text-control));font-weight:var(--_k-weight-title);letter-spacing:inherit;text-align:center;animation:knobs-name-in .25s cubic-bezier(.2,.8,.2,1);transition:opacity .11s cubic-bezier(.4,0,1,1)}
2580
+ .knobs-preset-name::selection{background:color-mix(in srgb,var(--_k-accent) 24%,transparent);color:var(--_k-fg)}
997
2581
  .knobs-panel .knobs-preset-name[data-leaving]{opacity:0;pointer-events:none}
998
2582
  @keyframes knobs-name-in{from{clip-path:inset(0 50% round 6px);opacity:.4}to{clip-path:inset(0 round 6px);opacity:1}}
999
2583
  @media(prefers-reduced-motion:reduce){.knobs-panel .knobs-preset-name{animation:knobs-fade .15s ease-out}}
1000
2584
 
1001
2585
  /* Group headers */
1002
- .knobs-group-head{display:flex;align-items:center;justify-content:space-between;gap:8px;min-height:20px;margin:var(--k-group-gap) 0 var(--k-gap);padding:0 var(--k-group-inset);color:var(--k-group-color);font-size:var(--k-group-size);font-weight:var(--k-title-weight);letter-spacing:var(--k-group-tracking);text-transform:var(--k-group-transform)}
2586
+ .knobs-group-head{display:flex;align-items:center;justify-content:space-between;gap:8px;min-height:20px;margin:var(--k-group-gap) 0 var(--_k-gap);padding:0 var(--k-group-inset);color:var(--_k-group-label);font-size:var(--k-group-size);font-weight:var(--_k-weight-title);letter-spacing:var(--k-group-tracking);text-transform:var(--k-group-transform)}
1003
2587
  .knobs-panel:not(.knobs-page) .knobs-group-head:not(:first-child){border-top:1px solid var(--k-group-divider);padding-top:var(--k-group-divider-gap)}
1004
2588
  .knobs-group-head:first-child{margin-top:0}
1005
- .knobs-group-head>span:last-child{display:flex;align-items:center;gap:var(--k-tray-pad);margin-right:calc((var(--k-icon-sm) - 20px) / 2)}
1006
- .knobs-group-head button{height:20px;padding:0 6px;font-size:var(--k-text-meta);font-weight:500;letter-spacing:0;text-transform:none;color:var(--k-label);background:transparent;border-radius:var(--k-radius-sm);cursor:pointer}
1007
- .knobs-group-head button:is(:hover:not([disabled]),:focus-visible){background:var(--k-surface-hi);color:var(--k-text)}
1008
- .knobs-group-head .knobs-group-reset{width:20px;padding:0;display:inline-flex;align-items:center;justify-content:center;border-radius:var(--k-round)}
2589
+ .knobs-group-head>span:last-child{display:flex;align-items:center;gap:var(--_k-tray-pad);margin-right:calc((var(--k-icon-sm) - 20px) / 2)}
2590
+ .knobs-group-head button{height:20px;padding:0 6px;font-size:var(--_k-text-meta);font-weight:500;letter-spacing:0;text-transform:none;color:var(--_k-fg-2);background:transparent;border-radius:var(--_k-radius-sm);cursor:pointer}
2591
+ .knobs-group-head button:is(:hover:not([disabled]),:focus-visible){background:var(--_k-fill-selected);color:var(--_k-fg)}
2592
+ .knobs-group-head .knobs-group-reset{width:20px;padding:0;display:inline-flex;align-items:center;justify-content:center;border-radius:var(--_k-round)}
1009
2593
  .knobs-group-head :is(.knobs-icon,.knobs-die-icon){width:var(--k-icon-sm);height:var(--k-icon-sm)}
1010
- .knobs-group-head .knobs-group-die{width:20px;padding:0;display:inline-flex;align-items:center;justify-content:center;border-radius:var(--k-round);color:var(--k-dim)}
2594
+ .knobs-group-head .knobs-group-die{width:20px;padding:0;display:inline-flex;align-items:center;justify-content:center;border-radius:var(--_k-round);color:var(--_k-fg-3)}
1011
2595
  .knobs-group-head .knobs-group-die[disabled]{opacity:var(--k-disabled-opacity);cursor:default}
1012
2596
  .knobs-panel .knobs-group-head button:where(:not(.knobs-group-reset)){transition:background var(--k-hover-t),color var(--k-hover-t),opacity .2s,transform .12s}
1013
2597
 
1014
2598
  /* Grouped cards: rows share one surface, split by hairlines that stay put whatever a row is doing */
1015
- .knobs-card{position:relative;margin-bottom:var(--k-section-gap);border-radius:var(--k-radius);background:var(--k-surface);overflow:hidden}
2599
+ .knobs-card{position:relative;margin-bottom:var(--k-section-gap);border-radius:var(--_k-radius);background:var(--_k-fill);overflow:hidden}
1016
2600
  .knobs-card:last-child{margin-bottom:0}
1017
- .knobs-card>*{position:relative;min-height:var(--k-row);transition:background var(--k-hover-t),opacity .2s}
2601
+ .knobs-card>*{position:relative;min-height:var(--_k-row);transition:background var(--k-hover-t),opacity .2s}
1018
2602
  .knobs-panel [data-tab-opacity]{transition:none!important}
1019
2603
  /* Rubber-band ends (drawStretch in give.ts): past a limit a control stretches about its far end
1020
2604
  and thins a little, its stretching corners rounding off; a row draws past its card's edge
@@ -1023,21 +2607,21 @@ ${GRAD_PROPS}
1023
2607
  .knobs-card[data-k-stretch]{overflow:visible}
1024
2608
  .knobs-card>:first-child{--k-rt:1}
1025
2609
  .knobs-card>:last-child{--k-rb:1}
1026
- .knobs-card>.knobs-stretching{--k-r:var(--k-radius);border-radius:calc(var(--k-r) * var(--k-rt,0)) calc(var(--k-r) * var(--k-rt,0)) calc(var(--k-r) * var(--k-rb,0)) calc(var(--k-r) * var(--k-rb,0))}
2610
+ .knobs-card>.knobs-stretching{--k-r:var(--_k-radius);border-radius:calc(var(--k-r) * var(--k-rt,0)) calc(var(--k-r) * var(--k-rt,0)) calc(var(--k-r) * var(--k-rb,0)) calc(var(--k-r) * var(--k-rb,0))}
1027
2611
  .knobs-card>.knobs-stretching[data-stretch="end"]{border-top-right-radius:calc(var(--k-r) * max(var(--k-rt,0),var(--k-sf)));border-bottom-right-radius:calc(var(--k-r) * max(var(--k-rb,0),var(--k-sf)))}
1028
2612
  .knobs-card>.knobs-stretching[data-stretch="start"]{border-top-left-radius:calc(var(--k-r) * max(var(--k-rt,0),var(--k-sf)));border-bottom-left-radius:calc(var(--k-r) * max(var(--k-rb,0),var(--k-sf)))}
1029
2613
  .knobs-stretching>:is(.knobs-track,.knobs-range-track){border-radius:inherit}
1030
2614
  .knobs-slider.knobs-stretching :is(.knobs-label,.knobs-value),.knobs-range.knobs-stretching .knobs-range-text{scale:calc(1 / var(--k-sx)) calc(1 / var(--k-sy))}
1031
- .knobs-slider.knobs-stretching .knobs-label{transform-origin:calc(var(--k-ox) - var(--k-inset)) 0}
1032
- .knobs-panel .knobs-slider.knobs-stretching .knobs-value{transform-origin:calc(var(--k-ox) - var(--k-w) + var(--k-inset) + 100%) 0}
2615
+ .knobs-slider.knobs-stretching .knobs-label{transform-origin:calc(var(--k-ox) - var(--_k-inset)) 0}
2616
+ .knobs-panel .knobs-slider.knobs-stretching .knobs-value{transform-origin:calc(var(--k-ox) - var(--k-w) + var(--_k-inset) + 100%) 0}
1033
2617
  .knobs-range.knobs-stretching .knobs-range-text{transform-origin:var(--k-sox) 50%}
1034
2618
  .knobs-stretching>:is(.knobs-strip-thumb,.knobs-pad-puck,.knobs-pad-home){transform:scale(calc(1 / var(--k-sx)),calc(1 / var(--k-sy)))}
1035
- .knobs-card>:hover,.knobs-card>.knobs-active{background:var(--k-row-hover)}
1036
- .knobs-card>*+*::before{content:"";position:absolute;z-index:1;left:0;right:0;top:0;height:1px;transform:scaleY(.5);transform-origin:top;background:var(--k-line);pointer-events:none;transition:opacity .15s}
1037
- .knobs-card>::after{content:"";position:absolute;z-index:2;inset:0;background:var(--k-surface-hi);opacity:0;pointer-events:none;transition:opacity .15s,box-shadow .15s}
2619
+ .knobs-card>:hover,.knobs-card>.knobs-active{background:var(--_k-row-hover)}
2620
+ .knobs-card>*+*::before{content:"";position:absolute;z-index:1;left:0;right:0;top:0;height:1px;transform:scaleY(.5);transform-origin:top;background:var(--_k-border);pointer-events:none;transition:opacity .15s}
2621
+ .knobs-card>::after{content:"";position:absolute;z-index:2;inset:0;background:var(--_k-fill-selected);opacity:0;pointer-events:none;transition:opacity .15s,box-shadow .15s}
1038
2622
  /* The card focus is on (a click on its empty area or heading, Esc from a row): a soft wash over all
1039
2623
  of it, for R and ⇧R acting on its group. */
1040
- :is(.knobs-card,.knobs-tile)::after{content:"";position:absolute;inset:0;border-radius:inherit;background:var(--k-surface);opacity:0;pointer-events:none;transition:opacity .2s var(--k-ease)}
2624
+ :is(.knobs-card,.knobs-tile)::after{content:"";position:absolute;inset:0;border-radius:inherit;background:var(--_k-fill);opacity:0;pointer-events:none;transition:opacity .2s var(--k-ease)}
1041
2625
  :is(.knobs-card,.knobs-tile)[data-k-scope]::after{opacity:1}
1042
2626
  .knobs-panel:focus{outline:none}
1043
2627
  .knobs-card>:has(:focus-visible)::after{opacity:1}
@@ -1048,18 +2632,18 @@ ${POINTER_ROW} :is(.knobs-card>*,.knobs-sub,.knobs-x-head):not(:hover)::after{op
1048
2632
  a soft wash and a hairline edge, placed from script (--kl-w, --kl-l). */
1049
2633
  .knobs-panel[data-k-lens] :is(.knobs-card>*,.knobs-sub,.knobs-x-head,.knobs-card,.knobs-tile)::after{opacity:0!important}
1050
2634
  .knobs-lens{position:absolute;left:0;top:0;z-index:2;width:0;height:0;opacity:0;pointer-events:none;box-sizing:border-box;contain:strict;will-change:transform,opacity;
1051
- background:color-mix(in srgb,var(--k-surface-hi) calc(var(--kl-w,0) * 100%),transparent);
1052
- box-shadow:inset 0 0 0 var(--k-rim-width) color-mix(in srgb,var(--k-line-hi) calc(var(--kl-l,0) * 100%),transparent)}
2635
+ background:color-mix(in srgb,var(--_k-fill-selected) calc(var(--kl-w,0) * 100%),transparent);
2636
+ box-shadow:inset 0 0 0 var(--k-rim-width) color-mix(in srgb,var(--_k-border-strong) calc(var(--kl-l,0) * 100%),transparent)}
1053
2637
  .knobs-panel[data-gpu-active="true"] .knobs-lens{visibility:hidden}
1054
- .knobs-panel .knobs-slider{height:var(--k-row);contain:layout style}
1055
- .knobs-panel .knobs-row:where(:not(.knobs-slider,.knobs-x,.knobs-spring)){display:flex;align-items:center;justify-content:space-between;gap:8px;height:var(--k-row);padding:0 var(--k-inset);contain:layout style}
1056
- .knobs-panel .knobs-row>span:first-child{color:var(--k-label);font-weight:var(--k-label-weight);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
1057
- .knobs-row>span:first-child::after{content:"";display:inline-block;width:4px;height:4px;margin-left:5px;border-radius:50%;background:var(--k-modified);vertical-align:middle;opacity:0;transform:scale(.4);transition:opacity .16s ease-out,transform .28s cubic-bezier(.34,1.5,.64,1)}
2638
+ .knobs-panel .knobs-slider{height:var(--_k-row);contain:layout style}
2639
+ .knobs-panel .knobs-row:where(:not(.knobs-slider,.knobs-x,.knobs-spring)){display:flex;align-items:center;justify-content:space-between;gap:8px;height:var(--_k-row);padding:0 var(--_k-inset);contain:layout style}
2640
+ .knobs-panel .knobs-row>span:first-child{color:var(--_k-fg-2);font-weight:var(--_k-weight-label);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
2641
+ .knobs-row>span:first-child::after{content:"";display:inline-block;width:4px;height:4px;margin-left:5px;border-radius:50%;background:var(--_k-modified);vertical-align:middle;opacity:0;transform:scale(.4);transition:opacity .16s ease-out,transform .28s cubic-bezier(.34,1.5,.64,1)}
1058
2642
  .knobs-modified.knobs-row>span:first-child::after{opacity:.95;transform:none}
1059
2643
  /* A locked row's lock sits just left of its readout (or its control), where the eye reads the value.
1060
2644
  Its room opens at once (it's right-aligned, so nothing beside it moves); the icon fades and
1061
2645
  scales in place. */
1062
- .knobs-lock{position:relative;flex:none;order:-1;display:inline-block;width:0;height:10px;color:var(--k-dim)}
2646
+ .knobs-lock{position:relative;flex:none;order:-1;display:inline-block;width:0;height:10px;color:var(--_k-fg-3)}
1063
2647
  .knobs-lock>svg{position:absolute;right:0;top:0;width:10px;height:10px;opacity:0;transform:scale(.5);transition:opacity .14s ease-in,transform .14s ease-in}
1064
2648
  .knobs-locked .knobs-lock{width:10px}
1065
2649
  .knobs-value>.knobs-lock>svg{right:6px}
@@ -1073,74 +2657,74 @@ ${POINTER_ROW} :is(.knobs-card>*,.knobs-sub,.knobs-x-head):not(:hover)::after{op
1073
2657
  The ticks and handle fade where the label and readout sit (--k-text-mask). The fill and handle
1074
2658
  are moved by transforms, never layout or background sizes, which snap to whole pixels: the
1075
2659
  edge and the handle's centre both land on the value's exact sub-pixel position, as on the GPU. */
1076
- .knobs-track{position:absolute;left:0;right:0;top:0;height:var(--k-row);overflow:hidden;contain:layout style paint;cursor:ew-resize;user-select:none;touch-action:none;transition:--k-readout .25s var(--k-ease);
1077
- --k-text-mask:linear-gradient(to right,transparent calc(var(--k-label-end,0px) + 4px),#000 calc(var(--k-label-end,0px) + 12px),#000 calc(100% - var(--k-inset) - var(--k-readout) - 12px),transparent calc(100% - var(--k-inset) - var(--k-readout) - 4px))}
2660
+ .knobs-track{position:absolute;left:0;right:0;top:0;height:var(--_k-row);overflow:hidden;contain:layout style paint;cursor:ew-resize;user-select:none;touch-action:none;transition:--k-readout .25s var(--k-ease);
2661
+ --k-text-mask:linear-gradient(to right,transparent calc(var(--k-label-end,0px) + 4px),#000 calc(var(--k-label-end,0px) + 12px),#000 calc(100% - var(--_k-inset) - var(--k-readout) - 12px),transparent calc(100% - var(--_k-inset) - var(--k-readout) - 4px))}
1078
2662
  .knobs-panel .knobs-track:focus-visible{outline:none;box-shadow:none}
1079
2663
  .knobs-marks,.knobs-handle-zone{position:absolute;inset:0;pointer-events:none;-webkit-mask:var(--k-text-mask);mask:var(--k-text-mask)}
1080
2664
  .knobs-marks>i{position:absolute;top:50%;width:1px;height:7px;border-radius:999px;transform:translate(-50%,-50%);background:transparent;transition:background .2s}
1081
- .knobs-fill{position:absolute;inset:0;pointer-events:none;--k-fill-mix:var(--k-fill-rest-mix);--k-fill-tint:color-mix(in srgb,var(--k-accent) var(--k-fill-mix),var(--k-fill-base));
1082
- background:var(--k-fill-tint);transform:translateX(calc(var(--k-fill) - 100%));transition:--k-fill-mix .15s}
1083
- .knobs-slider:hover .knobs-fill{--k-fill-mix:var(--k-fill-hover-mix)}
2665
+ .knobs-fill{position:absolute;inset:0;pointer-events:none;--k-fill-mix:var(--k-fill-rest-mix);--k-fill-tint:color-mix(in srgb,var(--_k-accent) var(--k-fill-mix),var(--_k-fill-base));
2666
+ background:var(--k-fill-tint);transform:translateX(calc(var(--_k-fill-at) - 100%));transition:--k-fill-mix .15s}
2667
+ .knobs-slider:hover .knobs-fill{--k-fill-mix:var(--_k-fill-hover-mix)}
1084
2668
  .knobs-active .knobs-fill,.knobs-active:hover .knobs-fill{--k-fill-mix:var(--k-fill-active-mix)}
1085
2669
  /* --k-motion-blur: a moving edge smears into a ramp as wide as its speed (--k-smear, px), as a
1086
2670
  horizontal box blur would; the handle widens and thins to match. */
1087
- .knobs-smear .knobs-fill{background:linear-gradient(to left,transparent,var(--k-fill-tint) calc(var(--k-smear) * 1px));transform:translateX(calc(var(--k-fill) - 100% + var(--k-smear) * .5px))}
2671
+ .knobs-smear .knobs-fill{background:linear-gradient(to left,transparent,var(--k-fill-tint) calc(var(--k-smear) * 1px));transform:translateX(calc(var(--_k-fill-at) - 100% + var(--k-smear) * .5px))}
1088
2672
  .knobs-smear .knobs-handle::before{scale:calc(1 + var(--k-smear) / 3) 1;opacity:calc(3 / (3 + var(--k-smear)))}
1089
2673
  .knobs-animate .knobs-fill,.knobs-animate .knobs-handle{transition:--k-fill ${SLIDE_T} ${DELAY},--k-fill-mix .15s,opacity .15s}
1090
2674
  /* The default: a short notch rising from the bottom edge, only while the row is in hand. The
1091
2675
  active preset's value hangs one from the top edge. */
1092
- .knobs-marks>.knobs-notch{top:auto;bottom:0;width:1.5px;height:4px;border-radius:999px 999px 0 0;transform:translateX(-50%);background:var(--k-accent);opacity:0;transition:opacity .2s,height .15s var(--k-ease)}
2676
+ .knobs-marks>.knobs-notch{top:auto;bottom:0;width:1.5px;height:4px;border-radius:999px 999px 0 0;transform:translateX(-50%);background:var(--_k-accent);opacity:0;transition:opacity .2s,height .15s var(--k-ease)}
1093
2677
  .knobs-marks>.knobs-base{top:0;bottom:auto;border-radius:0 0 999px 999px}
1094
2678
  .knobs-slider:is(:hover,.knobs-active,:has(:focus-visible)) .knobs-notch{opacity:.38}
1095
2679
  .knobs-slider.knobs-modified:is(:hover,.knobs-active,:has(:focus-visible)) .knobs-notch:not(.knobs-base){opacity:.55}
1096
2680
  .knobs-magnet .knobs-notch:not(.knobs-base),.knobs-held-base .knobs-base{opacity:.95;height:6px}
1097
2681
  /* Precision by distance: a fine ruler around the handle, a level for each halving of the rate,
1098
2682
  each finer, shorter and fainter than the last. */
1099
- .knobs-ruler{position:absolute;inset:0;pointer-events:none;--k-ruler-w:linear-gradient(to right,transparent calc(var(--k-fill) - ${RULER_FADE}px),#000 calc(var(--k-fill) - ${RULER_NEAR}px),#000 calc(var(--k-fill) + ${RULER_NEAR}px),transparent calc(var(--k-fill) + ${RULER_FADE}px));-webkit-mask:var(--k-ruler-w);mask:var(--k-ruler-w)}
2683
+ .knobs-ruler{position:absolute;inset:0;pointer-events:none;--k-ruler-w:linear-gradient(to right,transparent calc(var(--_k-fill-at) - ${RULER_FADE}px),#000 calc(var(--_k-fill-at) - ${RULER_NEAR}px),#000 calc(var(--_k-fill-at) + ${RULER_NEAR}px),transparent calc(var(--_k-fill-at) + ${RULER_FADE}px));-webkit-mask:var(--k-ruler-w);mask:var(--k-ruler-w)}
1100
2684
  .knobs-ruler>i{position:absolute;left:0;right:0;top:50%;opacity:0;translate:-.5px 0;transition:opacity .18s var(--k-ease)}
1101
- ${RULER.map(([n, h, a], i) => `.knobs-ruler>i:nth-child(${i + 1}){height:${h}px;margin-top:${-h / 2}px;background:repeating-linear-gradient(to right,color-mix(in srgb,var(--k-accent) ${a * 100}%,transparent) 0 1px,transparent 1px calc(100% / ${n}))}`).join(`
2685
+ ${RULER.map(([n, h, a], i) => `.knobs-ruler>i:nth-child(${i + 1}){height:${h}px;margin-top:${-h / 2}px;background:repeating-linear-gradient(to right,color-mix(in srgb,var(--_k-accent) ${a * 100}%,transparent) 0 1px,transparent 1px calc(100% / ${n}))}`).join(`
1102
2686
  `)}
1103
2687
  /* The handle is a full-width layer moved by the fill (translate's % is its own width, the track's). */
1104
- .knobs-handle{position:absolute;inset:0;pointer-events:none;transform:translateX(var(--k-fill));opacity:var(--k-handle-rest);transition:opacity .15s}
1105
- .knobs-handle::before{content:"";position:absolute;left:0;top:50%;width:3px;height:calc(var(--k-row) - 12px);margin-top:calc(6px - var(--k-row) / 2);translate:calc(-50% - var(--k-handle-inset)) 0;border-radius:var(--k-round);background:var(--k-handle);
1106
- box-shadow:0 0 calc(var(--k-glow) * 8px) color-mix(in srgb,var(--k-accent) 60%,transparent);transform:scaleX(calc(.25 + .75 * min(1, var(--k-handle-rest) * 4)));transition:transform .22s var(--k-ease)}
2688
+ .knobs-handle{position:absolute;inset:0;pointer-events:none;transform:translateX(var(--_k-fill-at));opacity:var(--k-handle-rest);transition:opacity .15s}
2689
+ .knobs-handle::before{content:"";position:absolute;left:0;top:50%;width:3px;height:calc(var(--_k-row) - 12px);margin-top:calc(6px - var(--_k-row) / 2);translate:calc(-50% - var(--k-handle-inset)) 0;border-radius:var(--_k-round);background:var(--_k-slider-handle);
2690
+ box-shadow:0 0 calc(var(--_k-glow) * 8px) color-mix(in srgb,var(--_k-accent) 60%,transparent);transform:scaleX(calc(.25 + .75 * min(1, var(--k-handle-rest) * 4)));transition:transform .22s var(--k-ease)}
1107
2691
  .knobs-slider:hover .knobs-handle,.knobs-track:focus-visible .knobs-handle{opacity:max(.65,var(--k-handle-rest))}
1108
2692
  .knobs-active .knobs-handle{opacity:.95}
1109
2693
  .knobs-slider:is(:hover,.knobs-active) .knobs-handle::before,.knobs-track:focus-visible .knobs-handle::before{transform:scaleX(1)}
1110
- .knobs-slider:is(:hover,:has(:focus-visible)) .knobs-marks>i:not(.knobs-notch){background:color-mix(in srgb,var(--k-accent) 15%,transparent)}
1111
- .knobs-active .knobs-marks>i:not(.knobs-notch){background:color-mix(in srgb,var(--k-accent) 22%,transparent)}
2694
+ .knobs-slider:is(:hover,:has(:focus-visible)) .knobs-marks>i:not(.knobs-notch){background:color-mix(in srgb,var(--_k-accent) 15%,transparent)}
2695
+ .knobs-active .knobs-marks>i:not(.knobs-notch){background:color-mix(in srgb,var(--_k-accent) 22%,transparent)}
1112
2696
  /* A focused slider the pointer has left for another row rests meanwhile (one row lit at a time). */
1113
2697
  ${POINTER_ROW} .knobs-slider:not(:hover,.knobs-active) .knobs-marks>i:not(.knobs-notch){background:transparent}
1114
2698
  ${POINTER_ROW} .knobs-slider:not(:hover,.knobs-active) .knobs-notch{opacity:0}
1115
2699
  ${POINTER_ROW} .knobs-slider:not(:hover,.knobs-active) .knobs-handle{opacity:var(--k-handle-rest)}
1116
2700
  ${POINTER_ROW} .knobs-slider:not(:hover,.knobs-active) .knobs-handle::before{transform:scaleX(calc(.25 + .75 * min(1, var(--k-handle-rest) * 4)))}
1117
- ${POINTER_ROW} .knobs-slider:not(:hover,.knobs-active) .knobs-value{color:var(--k-label)}
1118
- ${POINTER_ROW} .knobs-slider.knobs-modified:not(:hover,.knobs-active) .knobs-value{color:color-mix(in srgb,var(--k-modified) calc(var(--k-readout-mark) * 100%),var(--k-label))}
2701
+ ${POINTER_ROW} .knobs-slider:not(:hover,.knobs-active) .knobs-value{color:var(--_k-fg-2)}
2702
+ ${POINTER_ROW} .knobs-slider.knobs-modified:not(:hover,.knobs-active) .knobs-value{color:color-mix(in srgb,var(--_k-modified) calc(var(--k-readout-mark) * 100%),var(--_k-fg-2))}
1119
2703
  .knobs-digits{display:inline-flex;align-items:center;line-height:2.1;margin-block:-.375em;--rn-edge-fade:.5em}
1120
2704
  .knobs-unit{color:var(--k-unit-color);margin-left:var(--k-unit-gap)}
1121
2705
  /* --k-readout-mark (0 or 1): a modified value takes the modified colour behind a small dot. */
1122
- .knobs-value::before{content:"";flex:none;width:calc(5px * var(--k-readout-mark));height:5px;margin-right:calc(6px * var(--k-readout-mark));border-radius:50%;background:var(--k-modified);opacity:0;transform:scale(0);transition:opacity .16s ease,transform .3s cubic-bezier(.34,1.56,.64,1)}
1123
- :is(.knobs-slider,.knobs-sub).knobs-modified .knobs-value{color:color-mix(in srgb,var(--k-modified) calc(var(--k-readout-mark) * 100%),var(--k-label))}
1124
- :is(.knobs-slider,.knobs-sub).knobs-modified:is(.knobs-active,:has(.knobs-track:focus-visible)) .knobs-value{color:color-mix(in srgb,var(--k-modified) calc(var(--k-readout-mark) * 100%),var(--k-text))}
2706
+ .knobs-value::before{content:"";flex:none;width:calc(5px * var(--k-readout-mark));height:5px;margin-right:calc(6px * var(--k-readout-mark));border-radius:50%;background:var(--_k-modified);opacity:0;transform:scale(0);transition:opacity .16s ease,transform .3s cubic-bezier(.34,1.56,.64,1)}
2707
+ :is(.knobs-slider,.knobs-sub).knobs-modified .knobs-value{color:color-mix(in srgb,var(--_k-modified) calc(var(--k-readout-mark) * 100%),var(--_k-fg-2))}
2708
+ :is(.knobs-slider,.knobs-sub).knobs-modified:is(.knobs-active,:has(.knobs-track:focus-visible)) .knobs-value{color:color-mix(in srgb,var(--_k-modified) calc(var(--k-readout-mark) * 100%),var(--_k-fg))}
1125
2709
  :is(.knobs-slider,.knobs-sub).knobs-modified .knobs-value::before{opacity:var(--k-readout-mark);transform:none}
1126
- .knobs-label{position:absolute;left:var(--k-inset);top:50%;transform:translateY(-50%);max-width:calc(100% - var(--k-inset) * 2 - var(--k-readout,48px) - 8px - var(--k-accessory-w,0px));overflow:hidden;text-overflow:ellipsis;color:var(--k-label);font-weight:var(--k-label-weight);pointer-events:none;white-space:nowrap}
1127
- .knobs-panel .knobs-value{position:absolute;right:var(--k-inset);top:50%;transform:translateY(-50%);transform-origin:100% 0;display:inline-flex;align-items:center;justify-content:flex-end;gap:0;padding:4px 0 4px 8px;background:transparent!important;border-radius:0!important;line-height:1.35;overflow:visible;white-space:nowrap;
1128
- color:var(--k-label);font-family:var(--k-value-font);font-variant-numeric:tabular-nums;font-feature-settings:"tnum";font-size:var(--kc-value-size);
2710
+ .knobs-label{position:absolute;left:var(--_k-inset);top:50%;transform:translateY(-50%);max-width:calc(100% - var(--_k-inset) * 2 - var(--k-readout,48px) - 8px - var(--k-accessory-w,0px));overflow:hidden;text-overflow:ellipsis;color:var(--_k-fg-2);font-weight:var(--_k-weight-label);pointer-events:none;white-space:nowrap}
2711
+ .knobs-panel .knobs-value{position:absolute;right:var(--_k-inset);top:50%;transform:translateY(-50%);transform-origin:100% 0;display:inline-flex;align-items:center;justify-content:flex-end;gap:0;padding:4px 0 4px 8px;background:transparent!important;border-radius:0!important;line-height:1.35;overflow:visible;white-space:nowrap;
2712
+ color:var(--_k-fg-2);font-family:var(--_k-value-font);font-variant-numeric:tabular-nums;font-feature-settings:"tnum";font-size:var(--_k-value-size);
1129
2713
  cursor:text;transition:color .15s}
1130
- .knobs-active .knobs-value,.knobs-track:focus-visible .knobs-value{color:var(--k-text)}
2714
+ .knobs-active .knobs-value,.knobs-track:focus-visible .knobs-value{color:var(--_k-fg)}
1131
2715
  /* Editing: the digits' own text, in place (edit() gives it their right edge and width), with no
1132
2716
  box: a soft accent selection, an accent caret, and the unit still after it. */
1133
2717
  .knobs-panel :is(.knobs-number,.knobs-number-fit){position:absolute;top:50%;z-index:2;margin:0;padding:0 1px 0 0;border:0;border-radius:0;background:transparent;box-shadow:none;outline:none;
1134
- font-family:var(--k-value-font);font-size:var(--kc-value-size);font-variant-numeric:tabular-nums;font-feature-settings:"tnum";letter-spacing:normal;line-height:1.35;text-align:right;white-space:pre}
1135
- .knobs-panel .knobs-number{transform:translateY(-50%);color:var(--k-text);caret-color:var(--k-accent)}
1136
- .knobs-number::selection{background:color-mix(in srgb,var(--k-accent) 24%,transparent);color:var(--k-text)}
2718
+ font-family:var(--_k-value-font);font-size:var(--_k-value-size);font-variant-numeric:tabular-nums;font-feature-settings:"tnum";letter-spacing:normal;line-height:1.35;text-align:right;white-space:pre}
2719
+ .knobs-panel .knobs-number{transform:translateY(-50%);color:var(--_k-fg);caret-color:var(--_k-accent)}
2720
+ .knobs-number::selection{background:color-mix(in srgb,var(--_k-accent) 24%,transparent);color:var(--_k-fg)}
1137
2721
  .knobs-panel .knobs-number-fit{left:0;visibility:hidden;pointer-events:none}
1138
2722
  .knobs-editing .knobs-digits{visibility:hidden}
1139
2723
  .knobs-editing .knobs-value{pointer-events:none}
1140
2724
 
1141
2725
  /* Segmented choice */
1142
- .knobs-seg{position:relative;display:flex;flex-wrap:nowrap;align-items:center;justify-content:flex-end;gap:var(--k-tray-pad);height:var(--kc-control-h);padding:var(--k-tray-pad);max-width:76%;background:var(--k-seg-bg);border-radius:var(--k-radius-md)}
1143
- .knobs-seg-pill{position:absolute;top:var(--k-tray-pad);bottom:var(--k-tray-pad);left:0;right:100%;border-radius:var(--k-radius-sm);background:var(--k-pill-bg);box-shadow:var(--k-lift-shadow);pointer-events:none;
2726
+ .knobs-seg{position:relative;display:flex;flex-wrap:nowrap;align-items:center;justify-content:flex-end;gap:var(--_k-tray-pad);height:var(--_k-control-h);padding:var(--_k-tray-pad);max-width:76%;background:var(--_k-segmented-track);border-radius:var(--_k-radius-md)}
2727
+ .knobs-seg-pill{position:absolute;top:var(--_k-tray-pad);bottom:var(--_k-tray-pad);left:0;right:100%;border-radius:var(--_k-radius-sm);background:var(--k-pill-bg);box-shadow:var(--_k-shadow-raised);pointer-events:none;
1144
2728
  transition:left ${TRAIL_T} ${DELAY},right ${LEAD_T} ${DELAY},opacity .15s}
1145
2729
  .knobs-seg-pill[data-dir="left"]{transition:left ${LEAD_T} ${DELAY},right ${TRAIL_T} ${DELAY},opacity .15s}
1146
2730
  .knobs-seg-pill[data-off]{opacity:0}
@@ -1148,107 +2732,107 @@ ${POINTER_ROW} .knobs-slider.knobs-modified:not(:hover,.knobs-active) .knobs-val
1148
2732
  .knobs-smear-pill{margin-inline:calc(var(--k-smear) * -.5px);
1149
2733
  -webkit-mask:linear-gradient(to right,transparent,#000 calc(var(--k-smear) * 1px),#000 calc(100% - var(--k-smear) * 1px),transparent);
1150
2734
  mask:linear-gradient(to right,transparent,#000 calc(var(--k-smear) * 1px),#000 calc(100% - var(--k-smear) * 1px),transparent)}
1151
- .knobs-seg button{position:relative;z-index:1;display:inline-flex;align-items:center;justify-content:center;height:100%;padding:0 7px;font-size:var(--k-text-control);font-weight:var(--k-label-weight);white-space:nowrap;color:var(--k-label);background:transparent;cursor:pointer;border-radius:var(--k-radius-sm);transition:background var(--k-hover-t),color var(--k-hover-t)}
1152
- .knobs-seg button:is(:hover,:focus-visible){color:var(--k-text)}
1153
- .knobs-seg button[aria-checked=true]{color:var(--k-text)}
2735
+ .knobs-seg button{position:relative;z-index:1;display:inline-flex;align-items:center;justify-content:center;height:100%;padding:0 7px;font-size:var(--_k-text-control);font-weight:var(--_k-weight-label);white-space:nowrap;color:var(--_k-fg-2);background:transparent;cursor:pointer;border-radius:var(--_k-radius-sm);transition:background var(--k-hover-t),color var(--k-hover-t)}
2736
+ .knobs-seg button:is(:hover,:focus-visible){color:var(--_k-fg)}
2737
+ .knobs-seg button[aria-checked=true]{color:var(--_k-fg)}
1154
2738
 
1155
2739
  /* Long choices: a compact button that drops down a menu */
1156
- .knobs-panel .knobs-select{position:relative;display:inline-flex;align-items:center;gap:6px;min-width:0;max-width:62%;height:var(--kc-control-h);padding:0 6px 0 10px;background:var(--k-seg-bg);border-radius:var(--k-radius-md);color:var(--k-label);font-size:var(--k-text-control);font-weight:var(--k-label-weight);cursor:pointer;transition:background var(--k-hover-t),color var(--k-hover-t)}
1157
- .knobs-panel .knobs-select:is(:hover,:focus-visible,[aria-expanded="true"]),.knobs-panel .knobs-active>.knobs-select{background:var(--k-surface-hi);color:var(--k-text)}
2740
+ .knobs-panel .knobs-select{position:relative;display:inline-flex;align-items:center;gap:6px;min-width:0;max-width:62%;height:var(--_k-control-h);padding:0 6px 0 10px;background:var(--_k-segmented-track);border-radius:var(--_k-radius-md);color:var(--_k-fg-2);font-size:var(--_k-text-control);font-weight:var(--_k-weight-label);cursor:pointer;transition:background var(--k-hover-t),color var(--k-hover-t)}
2741
+ .knobs-panel .knobs-select:is(:hover,:focus-visible,[aria-expanded="true"]),.knobs-panel .knobs-active>.knobs-select{background:var(--_k-fill-selected);color:var(--_k-fg)}
1158
2742
  .knobs-select-value{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
1159
2743
  .knobs-panel .knobs-row-full .knobs-select{flex:1;max-width:none;justify-content:space-between}
1160
- .knobs-select .knobs-icon{width:calc(var(--k-icon-sm) - 2px);height:calc(var(--k-icon-sm) - 2px);color:var(--k-dim)}
2744
+ .knobs-select .knobs-icon{width:calc(var(--k-icon-sm) - 2px);height:calc(var(--k-icon-sm) - 2px);color:var(--_k-fg-3)}
1161
2745
  .knobs-menu[data-checks] .knobs-menu-item{padding-left:24px}
1162
2746
  .knobs-menu-item[aria-checked="true"]::before{content:"";position:absolute;left:9px;top:50%;width:7px;height:4px;margin-top:-3.5px;border:solid currentColor;border-width:0 0 1.5px 1.5px;transform:rotate(-45deg)}
1163
2747
 
1164
2748
  /* Action rows: a button the width of the row */
1165
2749
  .knobs-panel .knobs-action-row{padding:0}
1166
- .knobs-panel .knobs-action{width:100%;height:100%;padding:0 var(--k-inset);text-align:left;background:transparent;border-radius:0;color:var(--k-button-color,var(--k-text));font-size:var(--k-button-font-size,calc(var(--k-text-control) + .5px));font-weight:var(--k-label-weight);cursor:pointer;transition:color var(--k-hover-t),background var(--k-hover-t),box-shadow var(--k-hover-t)}
1167
- .knobs-panel .knobs-action:is(:hover,:focus-visible){color:var(--k-accent)}
2750
+ .knobs-panel .knobs-action{width:100%;height:100%;padding:0 var(--_k-inset);text-align:left;background:transparent;border-radius:0;color:var(--k-button-color,var(--_k-fg));font-size:var(--k-button-font-size,calc(var(--_k-text-control) + .5px));font-weight:var(--_k-weight-label);cursor:pointer;transition:color var(--k-hover-t),background var(--k-hover-t),box-shadow var(--k-hover-t)}
2751
+ .knobs-panel .knobs-action:is(:hover,:focus-visible){color:var(--_k-accent)}
1168
2752
  .knobs-panel .knobs-action:is(:active,.knobs-pressed){opacity:.7}
1169
- .knobs-panel .knobs-action.knobs-pressed{color:var(--k-accent)}
2753
+ .knobs-panel .knobs-action.knobs-pressed{color:var(--_k-accent)}
1170
2754
  /* A shortcut: its key cap at the row's end, the button taking the rest. */
1171
2755
  .knobs-panel .knobs-action-row[data-keyed]{gap:6px}
1172
2756
  .knobs-panel .knobs-action-row[data-keyed]>.knobs-action{flex:1 1 0;width:auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
1173
- .knobs-panel .knobs-action-row>.knobs-keys{order:1;margin-right:var(--k-inset)}
2757
+ .knobs-panel .knobs-action-row>.knobs-keys{order:1;margin-right:var(--_k-inset)}
1174
2758
  /* With a button fill or outline (--k-button-bg, --k-button-line), an action is a sized button in
1175
2759
  its row, and the presets strip a row of them, as toolbar buttons are. */
1176
- .knobs-panel[data-buttons] .knobs-action-row{padding:0 var(--k-inset)}
2760
+ .knobs-panel[data-buttons] .knobs-action-row{padding:0 var(--_k-inset)}
1177
2761
  .knobs-panel[data-buttons] .knobs-action-row[data-keyed]>.knobs-action{flex:0 1 auto;margin-right:auto}
1178
2762
  .knobs-panel[data-buttons] .knobs-action-row>.knobs-keys{margin-right:0}
1179
- .knobs-panel[data-buttons] .knobs-action{width:auto;max-width:100%;height:var(--k-button-h,var(--kc-control-h));padding:0 10px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
1180
- background:var(--k-button-bg,transparent);box-shadow:inset 0 0 0 1px var(--k-button-line,transparent);border-radius:var(--k-button-radius,var(--k-radius-md))}
1181
- .knobs-panel[data-buttons] .knobs-action:is(:hover,:focus-visible){color:var(--k-text);background:var(--k-button-hover-bg,var(--k-surface-hi));box-shadow:inset 0 0 0 1px var(--k-button-hover-line,var(--k-button-line,transparent))}
2763
+ .knobs-panel[data-buttons] .knobs-action{width:auto;max-width:100%;height:var(--k-button-h,var(--_k-control-h));padding:0 10px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
2764
+ background:var(--k-button-bg,transparent);box-shadow:inset 0 0 0 1px var(--k-button-line,transparent);border-radius:var(--k-button-radius,var(--_k-radius-md))}
2765
+ .knobs-panel[data-buttons] .knobs-action:is(:hover,:focus-visible){color:var(--_k-fg);background:var(--k-button-hover-bg,var(--_k-fill-selected));box-shadow:inset 0 0 0 1px var(--k-button-hover-line,var(--k-button-line,transparent))}
1182
2766
 
1183
2767
  /* Switch */
1184
2768
  /* The thumb spans two edges: the leading one springs ahead and the other follows, so it stretches
1185
2769
  into a capsule as it travels; a press widens it toward where it will go. */
1186
- .knobs-panel .knobs-toggle{position:relative;flex:none;width:32px;height:18px;padding:0;background:var(--k-toggle-track);border-radius:var(--k-round);cursor:pointer;transition:background .2s ${DELAY},box-shadow .2s ${DELAY}}
1187
- .knobs-panel .knobs-toggle[aria-checked=true]{background:var(--k-accent);box-shadow:0 0 calc(var(--k-glow) * 10px) color-mix(in srgb,var(--k-accent) 42%,transparent)}
1188
- .knobs-toggle i{position:absolute;top:var(--k-tray-pad);bottom:var(--k-tray-pad);left:var(--k-tray-pad);right:16px;border-radius:var(--k-round);background:var(--k-thumb);box-shadow:0 1px 2px rgba(0,0,0,calc(.25 * var(--k-lift)));transition:left ${LEAD_T} ${DELAY},right ${TRAIL_T} ${DELAY},background .2s ${DELAY}}
1189
- .knobs-toggle[aria-checked=true] i{left:16px;right:var(--k-tray-pad);background:var(--k-toggle-thumb);transition:left ${TRAIL_T} ${DELAY},right ${LEAD_T} ${DELAY},background .2s ${DELAY}}
2770
+ .knobs-panel .knobs-toggle{position:relative;flex:none;width:32px;height:18px;padding:0;background:var(--_k-toggle-track);border-radius:var(--_k-round);cursor:pointer;transition:background .2s ${DELAY},box-shadow .2s ${DELAY}}
2771
+ .knobs-panel .knobs-toggle[aria-checked=true]{background:var(--_k-accent);box-shadow:0 0 calc(var(--_k-glow) * 10px) color-mix(in srgb,var(--_k-accent) 42%,transparent)}
2772
+ .knobs-toggle i{position:absolute;top:var(--_k-tray-pad);bottom:var(--_k-tray-pad);left:var(--_k-tray-pad);right:16px;border-radius:var(--_k-round);background:var(--_k-toggle-thumb-off);box-shadow:0 1px 2px rgba(0,0,0,calc(.25 * var(--k-lift)));transition:left ${LEAD_T} ${DELAY},right ${TRAIL_T} ${DELAY},background .2s ${DELAY}}
2773
+ .knobs-toggle[aria-checked=true] i{left:16px;right:var(--_k-tray-pad);background:var(--_k-toggle-thumb);transition:left ${TRAIL_T} ${DELAY},right ${LEAD_T} ${DELAY},background .2s ${DELAY}}
1190
2774
  .knobs-toggle:active i{right:12px;transition:right ${LEAD_T},background .2s}
1191
- .knobs-toggle[aria-checked=true]:active i{left:12px;right:var(--k-tray-pad);transition:left ${LEAD_T},background .2s}
2775
+ .knobs-toggle[aria-checked=true]:active i{left:12px;right:var(--_k-tray-pad);transition:left ${LEAD_T},background .2s}
1192
2776
 
1193
2777
  /* Compound rows: a spring's two sliders beside its curve; disclosure rows with an editor body */
1194
2778
  .knobs-card>:is(.knobs-spring,.knobs-x):hover{background:transparent}
1195
2779
  .knobs-card>:is(.knobs-spring,.knobs-x):has(:focus-visible)::after{opacity:0}
1196
2780
  /* Selected rows: one accent-tinted wash, joined across neighbours. */
1197
- .knobs-panel .knobs-card>.knobs-selected{background:color-mix(in srgb,var(--k-accent) 10%,transparent)}
2781
+ .knobs-panel .knobs-card>.knobs-selected{background:color-mix(in srgb,var(--_k-accent) 10%,transparent)}
1198
2782
  .knobs-card>.knobs-selected+.knobs-selected::before{opacity:0}
1199
2783
  .knobs-spring{display:flex}
1200
2784
  .knobs-spring-tracks{position:relative;flex:1;min-width:0;overflow:hidden}
1201
2785
  .knobs-sub{position:relative;transition:background var(--k-hover-t)}
1202
- .knobs-sub:hover,.knobs-sub.knobs-active,.knobs-x-head:hover,.knobs-x-head[data-panned]{background:var(--k-row-hover)}
1203
- .knobs-sub+.knobs-sub::before{content:"";position:absolute;z-index:1;left:0;right:0;top:0;height:1px;transform:scaleY(.5);transform-origin:top;background:var(--k-line);pointer-events:none;transition:opacity .15s}
1204
- :is(.knobs-sub,.knobs-x-head)::after{content:"";position:absolute;z-index:2;inset:0;background:var(--k-surface-hi);opacity:0;pointer-events:none;transition:opacity .15s}
2786
+ .knobs-sub:hover,.knobs-sub.knobs-active,.knobs-x-head:hover,.knobs-x-head[data-panned]{background:var(--_k-row-hover)}
2787
+ .knobs-sub+.knobs-sub::before{content:"";position:absolute;z-index:1;left:0;right:0;top:0;height:1px;transform:scaleY(.5);transform-origin:top;background:var(--_k-border);pointer-events:none;transition:opacity .15s}
2788
+ :is(.knobs-sub,.knobs-x-head)::after{content:"";position:absolute;z-index:2;inset:0;background:var(--_k-fill-selected);opacity:0;pointer-events:none;transition:opacity .15s}
1205
2789
  :is(.knobs-sub:has(:focus-visible),.knobs-x-head:focus-visible)::after{opacity:1}
1206
- .knobs-spring-curve{position:relative;flex:none;width:calc(var(--k-row) * 2.5);margin:var(--k-gap) var(--k-inset) var(--k-gap) 0;border-radius:var(--k-radius-sm);background:var(--k-seg-bg);pointer-events:none}
2790
+ .knobs-spring-curve{position:relative;flex:none;width:calc(var(--_k-row) * 2.5);margin:var(--_k-gap) var(--_k-inset) var(--_k-gap) 0;border-radius:var(--_k-radius-sm);background:var(--_k-segmented-track);pointer-events:none}
1207
2791
  .knobs-panel :is(.knobs-spring-curve,.knobs-ease)>svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
1208
- .knobs-guide{fill:none;stroke:var(--k-line);stroke-width:1}
1209
- .knobs-arm{fill:none;stroke:var(--k-dim);stroke-width:1}
1210
- .knobs-curve{fill:none;stroke:var(--k-accent);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;transition:d ${FILL_T} ${DELAY}}
1211
- .knobs-spring-dot{position:absolute;left:0;top:0;width:5px;height:5px;margin:-2.5px;border-radius:50%;background:var(--k-accent);box-shadow:0 0 calc(var(--k-glow) * 8px) var(--k-accent);opacity:0;scale:var(--k-curve-dot)}
1212
- .knobs-guide-dashed{stroke:var(--k-line-hi)}
2792
+ .knobs-guide{fill:none;stroke:var(--_k-border);stroke-width:1}
2793
+ .knobs-arm{fill:none;stroke:var(--_k-fg-3);stroke-width:1}
2794
+ .knobs-curve{fill:none;stroke:var(--_k-accent);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;transition:d ${FILL_T} ${DELAY}}
2795
+ .knobs-spring-dot{position:absolute;left:0;top:0;width:5px;height:5px;margin:-2.5px;border-radius:50%;background:var(--_k-accent);box-shadow:0 0 calc(var(--_k-glow) * 8px) var(--_k-accent);opacity:0;scale:var(--k-curve-dot)}
2796
+ .knobs-guide-dashed{stroke:var(--_k-border-strong)}
1213
2797
  .knobs-spring:has(.knobs-active) .knobs-curve{transition:none}
1214
2798
 
1215
2799
  .knobs-panel :is(input,textarea,[contenteditable]){-webkit-user-select:text;user-select:text}
1216
- .knobs-x-head{position:relative;display:flex;align-items:center;justify-content:space-between;gap:8px;height:var(--k-row);padding:0 var(--k-inset);cursor:pointer;user-select:none;transition:background var(--k-hover-t)}
2800
+ .knobs-x-head{position:relative;display:flex;align-items:center;justify-content:space-between;gap:8px;height:var(--_k-row);padding:0 var(--_k-inset);cursor:pointer;user-select:none;transition:background var(--k-hover-t)}
1217
2801
  .knobs-x-head[data-panned]{cursor:ew-resize}
1218
2802
  .knobs-panel .knobs-x-head:focus-visible{outline:none;box-shadow:none}
1219
- .knobs-x-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--k-label);font-weight:var(--k-label-weight)}
1220
- .knobs-x-label::after{content:"";display:inline-block;width:4px;height:4px;margin-left:5px;border-radius:50%;background:var(--k-modified);vertical-align:middle;opacity:0;transform:scale(.4);transition:opacity .16s ease-out,transform .28s cubic-bezier(.34,1.5,.64,1)}
2803
+ .knobs-x-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--_k-fg-2);font-weight:var(--_k-weight-label)}
2804
+ .knobs-x-label::after{content:"";display:inline-block;width:4px;height:4px;margin-left:5px;border-radius:50%;background:var(--_k-modified);vertical-align:middle;opacity:0;transform:scale(.4);transition:opacity .16s ease-out,transform .28s cubic-bezier(.34,1.5,.64,1)}
1221
2805
  .knobs-modified .knobs-x-label::after{opacity:.95;transform:none}
1222
2806
  .knobs-x-sum{display:flex;align-items:center;gap:8px;min-width:0}
1223
- .knobs-x-read,.knobs-strip-read{color:var(--k-label);font-size:var(--kc-value-size);font-variant-numeric:tabular-nums;font-feature-settings:"tnum";white-space:nowrap}
2807
+ .knobs-x-read,.knobs-strip-read{color:var(--_k-fg-2);font-size:var(--_k-value-size);font-variant-numeric:tabular-nums;font-feature-settings:"tnum";white-space:nowrap}
1224
2808
  /* A name crossfading (reel.ts fadeText): the old one fades out over the new, where it was. */
1225
2809
  .knobs-x-read{position:relative}
1226
2810
  .knobs-ghost{position:absolute;right:0;top:0;white-space:nowrap;pointer-events:none}
1227
- .knobs-caret{width:10px;height:10px;flex:none;margin-right:-2.5px;color:var(--k-dim);transition:transform ${LEAD_T},color .15s}
2811
+ .knobs-caret{width:10px;height:10px;flex:none;margin-right:-2.5px;color:var(--_k-fg-3);transition:transform ${LEAD_T},color .15s}
1228
2812
  .knobs-caret path{fill:none;stroke:currentColor;stroke-width:1.4;stroke-linecap:round;stroke-linejoin:round}
1229
- .knobs-x-head:hover .knobs-caret{color:var(--k-label)}
2813
+ .knobs-x-head:hover .knobs-caret{color:var(--_k-fg-2)}
1230
2814
  .knobs-x-head[aria-expanded="true"] .knobs-caret{transform:rotate(90deg)}
1231
- .knobs-swatch{flex:none;width:var(--k-track-h);height:var(--k-track-h);border-radius:var(--k-radius-sm);box-shadow:inset 0 0 0 1px var(--k-line);transition:background-color .2s ${DELAY}}
1232
- .knobs-x-body{padding:0 var(--k-inset) var(--k-inset)}
2815
+ .knobs-swatch{flex:none;width:var(--k-track-h);height:var(--k-track-h);border-radius:var(--_k-radius-sm);box-shadow:inset 0 0 0 1px var(--_k-border);transition:background-color .2s ${DELAY}}
2816
+ .knobs-x-body{padding:0 var(--_k-inset) var(--_k-inset)}
1233
2817
  .knobs-strips{display:grid}
1234
2818
  .knobs-strip{display:grid;grid-template-columns:10px 1fr 36px;align-items:center;gap:8px;height:var(--k-action-h)}
1235
- .knobs-strip-label{color:var(--k-dim);font-size:var(--k-text-cap);font-weight:var(--k-title-weight);text-align:left}
2819
+ .knobs-strip-label{color:var(--_k-fg-3);font-size:var(--_k-text-cap);font-weight:var(--_k-weight-title);text-align:left}
1236
2820
  .knobs-strip-read{text-align:right}
1237
- .knobs-strip-track{position:relative;height:var(--k-track-h);border-radius:var(--k-round);box-shadow:inset 0 0 0 1px var(--k-line);cursor:ew-resize;touch-action:none}
1238
- .knobs-strip-thumb{position:absolute;top:50%;left:0;width:calc(var(--k-row) - 12px);height:calc(var(--k-row) - 12px);margin:calc(6px - var(--k-row) / 2);border-radius:var(--k-round);box-shadow:0 0 0 2px var(--k-thumb),0 1px 4px rgba(0,0,0,calc(.4 * var(--k-lift)));pointer-events:none;transition:left ${FILL_T} ${DELAY},background-color .2s ${DELAY},scale .2s var(--k-ease)}
2821
+ .knobs-strip-track{position:relative;height:var(--k-track-h);border-radius:var(--_k-round);box-shadow:inset 0 0 0 1px var(--_k-border);cursor:ew-resize;touch-action:none}
2822
+ .knobs-strip-thumb{position:absolute;top:50%;left:0;width:calc(var(--_k-row) - 12px);height:calc(var(--_k-row) - 12px);margin:calc(6px - var(--_k-row) / 2);border-radius:var(--_k-round);box-shadow:0 0 0 2px var(--_k-toggle-thumb-off),0 1px 4px rgba(0,0,0,calc(.4 * var(--k-lift)));pointer-events:none;transition:left ${FILL_T} ${DELAY},background-color .2s ${DELAY},scale .2s var(--k-ease)}
1239
2823
  .knobs-strip.knobs-active .knobs-strip-thumb{transition:background-color .2s,scale .2s var(--k-ease)}
1240
2824
  .knobs-strip:is(.knobs-active,:has(:focus-visible)) .knobs-strip-thumb{scale:1.1}
1241
- .knobs-pad,.knobs-ease{position:relative;border-radius:var(--k-radius-md);background:var(--k-seg-bg);touch-action:none}
1242
- .knobs-pad{height:calc(var(--k-row) * 4);cursor:crosshair;overflow:hidden}
2825
+ .knobs-pad,.knobs-ease{position:relative;border-radius:var(--_k-radius-md);background:var(--_k-segmented-track);touch-action:none}
2826
+ .knobs-pad{height:calc(var(--_k-row) * 4);cursor:crosshair;overflow:hidden}
1243
2827
  .knobs-pad>i{position:absolute;left:0;top:0;pointer-events:none;transition:translate ${FILL_T} ${DELAY},scale .2s var(--k-ease)}
1244
- .knobs-pad-v{bottom:0;width:1px;margin-left:-.5px;background:var(--k-line)}
1245
- .knobs-pad-h{right:0;height:1px;margin-top:-.5px;background:var(--k-line)}
1246
- .knobs-pad .knobs-pad-home{width:7px;height:7px;margin:-3.5px;border-radius:50%;box-shadow:inset 0 0 0 1px var(--k-dim);transition:none}
1247
- .knobs-pad-puck{width:12px;height:12px;margin:-6px;border-radius:var(--k-round);background:var(--k-accent);box-shadow:0 0 0 1.5px var(--k-bg),0 0 calc(var(--k-glow) * 10px) color-mix(in srgb,var(--k-accent) 50%,transparent)}
2828
+ .knobs-pad-v{bottom:0;width:1px;margin-left:-.5px;background:var(--_k-border)}
2829
+ .knobs-pad-h{right:0;height:1px;margin-top:-.5px;background:var(--_k-border)}
2830
+ .knobs-pad .knobs-pad-home{width:7px;height:7px;margin:-3.5px;border-radius:50%;box-shadow:inset 0 0 0 1px var(--_k-fg-3);transition:none}
2831
+ .knobs-pad-puck{width:12px;height:12px;margin:-6px;border-radius:var(--_k-round);background:var(--_k-accent);box-shadow:0 0 0 1.5px var(--_k-bg),0 0 calc(var(--_k-glow) * 10px) color-mix(in srgb,var(--_k-accent) 50%,transparent)}
1248
2832
  .knobs-pad.knobs-active>i{transition:scale .2s var(--k-ease)}
1249
2833
  .knobs-pad:is(.knobs-active,:focus-visible) .knobs-pad-puck{scale:1.2}
1250
- .knobs-ease{height:calc(var(--k-row) * 4.5)}
1251
- .knobs-panel .knobs-ease-handle{position:absolute;left:0;top:0;width:12px;height:12px;margin:-6px;padding:0;border-radius:var(--k-round);background:var(--k-bg);box-shadow:inset 0 0 0 2px var(--k-accent),0 1px 3px rgba(0,0,0,calc(.3 * var(--k-lift)));cursor:grab;touch-action:none;transition:scale .2s var(--k-ease)}
2834
+ .knobs-ease{height:calc(var(--_k-row) * 4.5)}
2835
+ .knobs-panel .knobs-ease-handle{position:absolute;left:0;top:0;width:12px;height:12px;margin:-6px;padding:0;border-radius:var(--_k-round);background:var(--_k-bg);box-shadow:inset 0 0 0 2px var(--_k-accent),0 1px 3px rgba(0,0,0,calc(.3 * var(--k-lift)));cursor:grab;touch-action:none;transition:scale .2s var(--k-ease)}
1252
2836
  .knobs-ease-handle::before{content:"";position:absolute;inset:-8px;border-radius:50%}
1253
2837
  /* The row's morph moves the curve, arms and handles each frame (ramp-morph.ts), so they don't
1254
2838
  transition. */
@@ -1256,18 +2840,18 @@ ${POINTER_ROW} .knobs-slider.knobs-modified:not(:hover,.knobs-active) .knobs-val
1256
2840
  .knobs-ease-handle:active{scale:1.2;cursor:grabbing}
1257
2841
  .knobs-ease-handle:focus-visible{scale:1.2}
1258
2842
  .knobs-ease-mini{flex:none;width:30px;height:var(--k-track-h);overflow:visible}
1259
- .knobs-ease-chips{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--k-tray-pad);margin-top:6px;padding:var(--k-tray-pad);border-radius:var(--k-radius-md);background:var(--k-seg-bg)}
1260
- .knobs-panel .knobs-ease-chip{min-width:0;height:calc(var(--k-row) - 10px);padding:0 6px;font-size:var(--k-text-control);font-weight:var(--k-label-weight);color:var(--k-label);background:transparent;border-radius:var(--k-radius-sm);cursor:pointer;white-space:nowrap;transition:background var(--k-hover-t),color var(--k-hover-t),box-shadow .15s}
1261
- .knobs-panel .knobs-ease-chip:is(:hover,:focus-visible){color:var(--k-text)}
1262
- .knobs-panel .knobs-ease-chip[aria-checked="true"]{color:var(--k-text);background:var(--k-pill-bg);box-shadow:var(--k-lift-shadow)}
2843
+ .knobs-ease-chips{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--_k-tray-pad);margin-top:6px;padding:var(--_k-tray-pad);border-radius:var(--_k-radius-md);background:var(--_k-segmented-track)}
2844
+ .knobs-panel .knobs-ease-chip{min-width:0;height:calc(var(--_k-row) - 10px);padding:0 6px;font-size:var(--_k-text-control);font-weight:var(--_k-weight-label);color:var(--_k-fg-2);background:transparent;border-radius:var(--_k-radius-sm);cursor:pointer;white-space:nowrap;transition:background var(--k-hover-t),color var(--k-hover-t),box-shadow .15s}
2845
+ .knobs-panel .knobs-ease-chip:is(:hover,:focus-visible){color:var(--_k-fg)}
2846
+ .knobs-panel .knobs-ease-chip[aria-checked="true"]{color:var(--_k-fg);background:var(--k-pill-bg);box-shadow:var(--_k-shadow-raised)}
1263
2847
 
1264
2848
  /* Gradients: a swatch strip with stop ticks in the head; a wide strip with a handle per stop (the
1265
2849
  selected one full size), then that stop's colour strips. The ramp runs a handle's radius in from
1266
2850
  each end, as the colour strips' do. */
1267
- .knobs-grad-mini{position:relative;flex:none;width:calc(var(--k-row) * 2.5);height:var(--k-track-h);border-radius:var(--k-radius-sm);box-shadow:inset 0 0 0 1px var(--k-line);background:${GRAD_MINI}}
1268
- .knobs-grad-mini>i{position:absolute;top:calc(100% + 2px);left:0;width:1px;height:3px;margin-left:-.5px;background:var(--k-dim);scale:1 var(--kgs-grow,1);transform-origin:top;transition:opacity .15s}
1269
- .knobs-grad{--kg-h:calc(var(--k-row) - 6px);--kg-r:calc(var(--kg-h) / 2);--kg-pin:round(calc(var(--kg-h) * .42),1px);position:relative;height:var(--kg-h);margin:2px 0 var(--k-gap);border-radius:var(--k-round);box-shadow:inset 0 0 0 1px var(--k-line);background:${GRAD_STRIP};cursor:pointer;touch-action:none;user-select:none;outline:none}
1270
- .knobs-grad-stop{position:absolute;top:50%;left:0;width:var(--kg-pin);height:calc(var(--kg-h) - 4px);margin:calc(2px - var(--kg-h) / 2) 0 0 calc(var(--kg-pin) / -2);border-radius:var(--k-round);box-shadow:0 0 0 2px var(--k-thumb),0 1px 4px rgba(0,0,0,calc(.4 * var(--k-lift)));pointer-events:none;
2851
+ .knobs-grad-mini{position:relative;flex:none;width:calc(var(--_k-row) * 2.5);height:var(--k-track-h);border-radius:var(--_k-radius-sm);box-shadow:inset 0 0 0 1px var(--_k-border);background:${GRAD_MINI}}
2852
+ .knobs-grad-mini>i{position:absolute;top:calc(100% + 2px);left:0;width:1px;height:3px;margin-left:-.5px;background:var(--_k-fg-3);scale:1 var(--kgs-grow,1);transform-origin:top;transition:opacity .15s}
2853
+ .knobs-grad{--kg-h:calc(var(--_k-row) - 6px);--kg-r:calc(var(--kg-h) / 2);--kg-pin:round(calc(var(--kg-h) * .42),1px);position:relative;height:var(--kg-h);margin:2px 0 var(--_k-gap);border-radius:var(--_k-round);box-shadow:inset 0 0 0 1px var(--_k-border);background:${GRAD_STRIP};cursor:pointer;touch-action:none;user-select:none;outline:none}
2854
+ .knobs-grad-stop{position:absolute;top:50%;left:0;width:var(--kg-pin);height:calc(var(--kg-h) - 4px);margin:calc(2px - var(--kg-h) / 2) 0 0 calc(var(--kg-pin) / -2);border-radius:var(--_k-round);box-shadow:0 0 0 2px var(--_k-toggle-thumb-off),0 1px 4px rgba(0,0,0,calc(.4 * var(--k-lift)));pointer-events:none;
1271
2855
  --kgs-sel:.78;scale:calc(var(--kgs-sel) * var(--kgs-grow,1));transition:--kgs-sel .2s var(--k-ease),opacity .15s}
1272
2856
  /* The row's morph moves the strip, stops and ticks each frame (ramp-morph.ts), so none transition
1273
2857
  but a stop's focus scale (--kgs-sel); its growth (--kgs-grow) buds it from the strip or merges it
@@ -1286,42 +2870,42 @@ ${POINTER_ROW} .knobs-slider.knobs-modified:not(:hover,.knobs-active) .knobs-val
1286
2870
  /* Curves: a mini curve in the head; a graph with a grid, points (the selected one filled) and a
1287
2871
  hover crosshair whose readout sits in the corner. */
1288
2872
  .knobs-curve-mini{flex:none;width:36px;height:var(--k-track-h);overflow:visible}
1289
- .knobs-graph{position:relative;height:calc(var(--k-row) * 4.5);border-radius:var(--k-radius-md);background:var(--k-seg-bg);cursor:crosshair;touch-action:none;user-select:none;outline:none;overflow:hidden}
2873
+ .knobs-graph{position:relative;height:calc(var(--_k-row) * 4.5);border-radius:var(--_k-radius-md);background:var(--_k-segmented-track);cursor:crosshair;touch-action:none;user-select:none;outline:none;overflow:hidden}
1290
2874
  .knobs-panel .knobs-graph>svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
1291
2875
  .knobs-graph>i{position:absolute;left:0;top:0;pointer-events:none}
1292
2876
  /* The row's morph places the line and points each frame (ramp-morph.ts), so neither transitions:
1293
2877
  a point's size is its focus scale (--kpt-sel, which does) times its growth (--kpt-grow, budding
1294
2878
  from the line or merging into a neighbour). */
1295
- .knobs-graph-pt{width:10px;height:10px;margin:-5px;border-radius:var(--k-round);background:var(--k-bg);box-shadow:inset 0 0 0 2px var(--k-accent),0 1px 3px rgba(0,0,0,calc(.3 * var(--k-lift)));
2879
+ .knobs-graph-pt{width:10px;height:10px;margin:-5px;border-radius:var(--_k-round);background:var(--_k-bg);box-shadow:inset 0 0 0 2px var(--_k-accent),0 1px 3px rgba(0,0,0,calc(.3 * var(--k-lift)));
1296
2880
  scale:calc(var(--kpt-sel) * var(--kpt-grow,1));transition:background-color .15s,--kpt-sel .2s var(--k-ease),opacity .15s}
1297
- .knobs-graph-pt[data-selected]{background:var(--k-accent)}
2881
+ .knobs-graph-pt[data-selected]{background:var(--_k-accent)}
1298
2882
  .knobs-graph:is(:focus-visible,.knobs-active) .knobs-graph-pt[data-selected]{--kpt-sel:1.2}
1299
2883
  .knobs-graph-pt[data-leaving]{opacity:.35;--kpt-sel:.7}
1300
2884
  .knobs-graph .knobs-curve,.knobs-curve-mini .knobs-curve{transition:none}
1301
2885
  .knobs-graph :is(.knobs-graph-v,.knobs-graph-h,.knobs-graph-dot,.knobs-graph-read){opacity:0;transition:opacity .15s}
1302
2886
  .knobs-graph[data-hover] :is(.knobs-graph-v,.knobs-graph-h,.knobs-graph-dot,.knobs-graph-read){opacity:1}
1303
- .knobs-graph-v{bottom:0;width:1px;margin-left:-.5px;background:var(--k-line-hi)}
1304
- .knobs-graph-h{right:0;height:1px;margin-top:-.5px;background:var(--k-line-hi)}
1305
- .knobs-graph-dot{width:5px;height:5px;margin:-2.5px;border-radius:50%;background:var(--k-accent)}
1306
- .knobs-graph-read{position:absolute;top:4px;right:4px;padding:1px 5px;border-radius:var(--k-radius-sm);background:var(--k-bg);color:var(--k-label);font-family:var(--k-value-font);font-size:var(--kc-value-size);font-variant-numeric:tabular-nums;font-feature-settings:"tnum";white-space:nowrap;pointer-events:none}
2887
+ .knobs-graph-v{bottom:0;width:1px;margin-left:-.5px;background:var(--_k-border-strong)}
2888
+ .knobs-graph-h{right:0;height:1px;margin-top:-.5px;background:var(--_k-border-strong)}
2889
+ .knobs-graph-dot{width:5px;height:5px;margin:-2.5px;border-radius:50%;background:var(--_k-accent)}
2890
+ .knobs-graph-read{position:absolute;top:4px;right:4px;padding:1px 5px;border-radius:var(--_k-radius-sm);background:var(--_k-bg);color:var(--_k-fg-2);font-family:var(--_k-value-font);font-size:var(--_k-value-size);font-variant-numeric:tabular-nums;font-feature-settings:"tnum";white-space:nowrap;pointer-events:none}
1307
2891
  .knobs-mixed :is(.knobs-curve-mini,.knobs-graph .knobs-curve,.knobs-graph-pt){opacity:0}
1308
2892
 
1309
2893
  /* Rows as separate bars (--k-row-gap above 0): each row carries its own surface, no hairlines.
1310
2894
  A spring stacks its curve over its two sliders. */
1311
2895
  .knobs-panel[data-rows] .knobs-card{display:flex;flex-direction:column;gap:var(--k-row-gap);background:transparent;overflow:visible}
1312
- .knobs-panel[data-rows] .knobs-card>*{background:var(--k-surface);border-radius:var(--k-radius);overflow:hidden;--k-rt:1;--k-rb:1}
1313
- .knobs-panel[data-rows] .knobs-card>:is(:hover,.knobs-active){background:color-mix(in srgb,var(--k-surface-hi) 50%,var(--k-surface))}
2896
+ .knobs-panel[data-rows] .knobs-card>*{background:var(--_k-fill);border-radius:var(--_k-radius);overflow:hidden;--k-rt:1;--k-rb:1}
2897
+ .knobs-panel[data-rows] .knobs-card>:is(:hover,.knobs-active){background:color-mix(in srgb,var(--_k-fill-selected) 50%,var(--_k-fill))}
1314
2898
  .knobs-panel[data-rows] :is(.knobs-card>*,.knobs-sub)::before{display:none}
1315
2899
  .knobs-panel[data-rows] .knobs-card>.knobs-subhead{background:transparent}
1316
2900
  .knobs-panel[data-rows] .knobs-card>.knobs-spring{flex-direction:column-reverse;gap:var(--k-row-gap);background:transparent;overflow:visible}
1317
2901
  .knobs-panel[data-rows] .knobs-spring-tracks{display:flex;flex-direction:column;gap:var(--k-row-gap);overflow:visible}
1318
- .knobs-panel[data-rows] .knobs-sub{background:var(--k-surface);border-radius:var(--k-radius);overflow:hidden}
1319
- .knobs-panel[data-rows] .knobs-sub:is(:hover,.knobs-active){background:color-mix(in srgb,var(--k-surface-hi) 50%,var(--k-surface))}
1320
- .knobs-panel[data-rows] .knobs-spring-curve{width:auto;height:calc(var(--k-row) * 2.8);margin:0;border-radius:var(--k-radius);background:var(--k-surface)}
2902
+ .knobs-panel[data-rows] .knobs-sub{background:var(--_k-fill);border-radius:var(--_k-radius);overflow:hidden}
2903
+ .knobs-panel[data-rows] .knobs-sub:is(:hover,.knobs-active){background:color-mix(in srgb,var(--_k-fill-selected) 50%,var(--_k-fill))}
2904
+ .knobs-panel[data-rows] .knobs-spring-curve{width:auto;height:calc(var(--_k-row) * 2.8);margin:0;border-radius:var(--_k-radius);background:var(--_k-fill)}
1321
2905
  /* --k-frame: flat. Groups are plain sections: no card surfaces, rows split by hairlines and a
1322
2906
  hairline over every group's label but the first. An inline panel sheds its own card and
1323
2907
  padding too, for a host's column or card, so nothing draws a card inside a card. */
1324
- :where(.knobs-panel)[data-frame="flat"]{--k-group-divider:var(--k-line);--k-group-divider-gap:var(--k-gap)}
2908
+ :where(.knobs-panel)[data-frame="flat"]{--k-group-divider:var(--_k-border);--k-group-divider-gap:var(--_k-gap)}
1325
2909
  :where(.knobs-panel.knobs-inline:not(.knobs-page))[data-frame="flat"]{--k-chrome:0;--k-pad:0px}
1326
2910
  .knobs-panel[data-frame="flat"] .knobs-card{background:transparent;border-radius:0}
1327
2911
  .knobs-panel[data-frame="flat"][data-rows] .knobs-card>*,.knobs-panel[data-frame="flat"][data-rows] .knobs-sub{background:transparent;border-radius:0}
@@ -1335,9 +2919,9 @@ ${POINTER_ROW} .knobs-slider.knobs-modified:not(:hover,.knobs-active) .knobs-val
1335
2919
  .knobs-slider:is([data-disabled],[data-readonly]):hover:not(:has(:focus-visible)) :is(.knobs-handle,.knobs-marks>i){opacity:var(--k-handle-rest);background-color:transparent}
1336
2920
  .knobs-slider:is([data-disabled],[data-readonly]):hover:not(:has(:focus-visible)) .knobs-handle::before{transform:scaleX(calc(.25 + .75 * min(1, var(--k-handle-rest) * 4)))}
1337
2921
  .knobs-panel :is([data-disabled],[data-readonly]) .knobs-value:hover{border-bottom-color:transparent}
1338
- .knobs-panel :is([data-disabled],[data-readonly]) .knobs-seg button:not([aria-checked=true]):hover{color:var(--k-label)}
1339
- .knobs-panel :is([data-disabled],[data-readonly]) .knobs-action:hover:not(:focus-visible){color:var(--k-text)}
1340
- .knobs-panel :is([data-disabled],[data-readonly]) .knobs-select:hover:not(:focus-visible){background:var(--k-seg-bg);color:var(--k-label)}
2922
+ .knobs-panel :is([data-disabled],[data-readonly]) .knobs-seg button:not([aria-checked=true]):hover{color:var(--_k-fg-2)}
2923
+ .knobs-panel :is([data-disabled],[data-readonly]) .knobs-action:hover:not(:focus-visible){color:var(--_k-fg)}
2924
+ .knobs-panel :is([data-disabled],[data-readonly]) .knobs-select:hover:not(:focus-visible){background:var(--_k-segmented-track);color:var(--_k-fg-2)}
1341
2925
  /* A mixed value (a multi-selection whose items differ) reads "—" until it's edited. */
1342
2926
  .knobs-mixed :is(.knobs-fill,.knobs-handle-zone,.knobs-marks){opacity:0}
1343
2927
  .knobs-panel .knobs-mixed .knobs-value>:is(.knobs-digits,.knobs-unit,.knobs-lock){display:none}
@@ -1346,63 +2930,63 @@ ${POINTER_ROW} .knobs-slider.knobs-modified:not(:hover,.knobs-active) .knobs-val
1346
2930
  .knobs-panel .knobs-toggle[aria-checked="mixed"] i{left:calc(50% - 7px);right:calc(50% - 7px)}
1347
2931
 
1348
2932
  /* Tabs: text over a hairline; the chosen one's underline slides to it, its leading edge first. */
1349
- .knobs-tabs{position:relative;display:flex;align-items:stretch;gap:calc(var(--k-unit) * 4);margin:0 0 var(--k-section-gap);padding:0 var(--k-inset);overflow:hidden;transition:opacity .2s var(--k-ease)}
1350
- .knobs-tabs::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1px;transform:scaleY(.5);transform-origin:bottom;background:var(--k-line);pointer-events:none}
1351
- .knobs-panel .knobs-tab{flex:none;height:calc(var(--k-row) - var(--k-unit));padding:0;background:transparent;border-radius:0;font-size:var(--k-text-control);font-weight:var(--k-label-weight);color:var(--k-label);white-space:nowrap;cursor:pointer;transition:color .15s}
1352
- .knobs-panel .knobs-tab:is(:hover,:focus-visible),.knobs-panel .knobs-tab[aria-selected="true"]{color:var(--k-text)}
1353
- .knobs-tabs-bar{position:absolute;bottom:0;left:0;right:100%;height:1.5px;border-radius:1px;background:var(--k-accent);pointer-events:none;transition:left ${TRAIL_T},right ${LEAD_T}}
2933
+ .knobs-tabs{position:relative;display:flex;align-items:stretch;gap:calc(var(--_k-unit) * 4);margin:0 0 var(--k-section-gap);padding:0 var(--_k-inset);overflow:hidden;transition:opacity .2s var(--k-ease)}
2934
+ .knobs-tabs::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1px;transform:scaleY(.5);transform-origin:bottom;background:var(--_k-border);pointer-events:none}
2935
+ .knobs-panel .knobs-tab{flex:none;height:calc(var(--_k-row) - var(--_k-unit));padding:0;background:transparent;border-radius:0;font-size:var(--_k-text-control);font-weight:var(--_k-weight-label);color:var(--_k-fg-2);white-space:nowrap;cursor:pointer;transition:color .15s}
2936
+ .knobs-panel .knobs-tab:is(:hover,:focus-visible),.knobs-panel .knobs-tab[aria-selected="true"]{color:var(--_k-fg)}
2937
+ .knobs-tabs-bar{position:absolute;bottom:0;left:0;right:100%;height:1.5px;border-radius:1px;background:var(--_k-accent);pointer-events:none;transition:left ${TRAIL_T},right ${LEAD_T}}
1354
2938
  .knobs-tabs-bar[data-dir="left"]{transition:left ${LEAD_T},right ${TRAIL_T}}
1355
2939
  /* A search spans every tab, so the strip steps back while it's on. */
1356
2940
  .knobs-panel[data-searching] .knobs-tabs{opacity:.4}
1357
2941
 
1358
2942
  /* Search: a field and its filter chips. Matches show in labels by colour alone. */
1359
- .knobs-search{display:flex;align-items:center;gap:var(--k-tray-pad);margin:0 0 var(--k-section-gap)}
1360
- .knobs-search-field{flex:1;min-width:0;display:flex;align-items:center;gap:6px;height:var(--kc-control-h);padding:0 8px;background:var(--k-seg-bg);border-radius:var(--k-radius-md);color:var(--k-dim);cursor:text}
2943
+ .knobs-search{display:flex;align-items:center;gap:var(--_k-tray-pad);margin:0 0 var(--k-section-gap)}
2944
+ .knobs-search-field{flex:1;min-width:0;display:flex;align-items:center;gap:6px;height:var(--_k-control-h);padding:0 8px;background:var(--_k-segmented-track);border-radius:var(--_k-radius-md);color:var(--_k-fg-3);cursor:text}
1361
2945
  .knobs-search-field>.knobs-icon{width:calc(var(--k-icon-sm) - 2px);height:calc(var(--k-icon-sm) - 2px)}
1362
- .knobs-panel .knobs-search input{flex:1;min-width:0;height:100%;padding:0;background:transparent;border-radius:0;color:var(--k-text);font-size:var(--k-text-control);-webkit-appearance:none;appearance:none}
1363
- .knobs-panel .knobs-search input::placeholder{color:var(--k-dim)}
2946
+ .knobs-panel .knobs-search input{flex:1;min-width:0;height:100%;padding:0;background:transparent;border-radius:0;color:var(--_k-fg);font-size:var(--_k-text-control);-webkit-appearance:none;appearance:none}
2947
+ .knobs-panel .knobs-search input::placeholder{color:var(--_k-fg-3)}
1364
2948
  .knobs-panel .knobs-search input::-webkit-search-cancel-button{display:none}
1365
- .knobs-panel .knobs-search-chip{flex:none;display:inline-flex;align-items:center;gap:5px;height:var(--kc-control-h);padding:0 8px;background:transparent;border-radius:var(--k-radius-md);box-shadow:inset 0 0 0 1px var(--k-line);color:var(--k-label);font-size:var(--k-text-meta);font-weight:var(--k-label-weight);white-space:nowrap;cursor:pointer;transition:background var(--k-hover-t),color var(--k-hover-t),box-shadow .15s,opacity .15s}
1366
- .knobs-panel .knobs-search-chip:is(:hover,:focus-visible){color:var(--k-text);box-shadow:inset 0 0 0 1px var(--k-line-hi)}
1367
- .knobs-panel .knobs-search-chip[aria-pressed="true"]{background:var(--k-pill-bg);box-shadow:inset 0 0 0 1px var(--k-pill-border);color:var(--k-text)}
2949
+ .knobs-panel .knobs-search-chip{flex:none;display:inline-flex;align-items:center;gap:5px;height:var(--_k-control-h);padding:0 8px;background:transparent;border-radius:var(--_k-radius-md);box-shadow:inset 0 0 0 1px var(--_k-border);color:var(--_k-fg-2);font-size:var(--_k-text-meta);font-weight:var(--_k-weight-label);white-space:nowrap;cursor:pointer;transition:background var(--k-hover-t),color var(--k-hover-t),box-shadow .15s,opacity .15s}
2950
+ .knobs-panel .knobs-search-chip:is(:hover,:focus-visible){color:var(--_k-fg);box-shadow:inset 0 0 0 1px var(--_k-border-strong)}
2951
+ .knobs-panel .knobs-search-chip[aria-pressed="true"]{background:var(--k-pill-bg);box-shadow:inset 0 0 0 1px var(--k-pill-border);color:var(--_k-fg)}
1368
2952
  .knobs-panel .knobs-search-chip[data-none]{opacity:.5}
1369
- .knobs-search-count{color:var(--k-dim);font-variant-numeric:tabular-nums}
1370
- .knobs-search-chip[aria-pressed="true"] .knobs-search-count{color:var(--k-label)}
1371
- .knobs-panel mark.knobs-match{background:none;color:var(--k-accent)}
2953
+ .knobs-search-count{color:var(--_k-fg-3);font-variant-numeric:tabular-nums}
2954
+ .knobs-search-chip[aria-pressed="true"] .knobs-search-count{color:var(--_k-fg-2)}
2955
+ .knobs-panel mark.knobs-match{background:none;color:var(--_k-accent)}
1372
2956
  .knobs-panel[data-gpu-active="true"] .knobs-search{position:relative;z-index:2147480003}
1373
2957
 
1374
2958
  /* Sub-headings: a flat heading inside the group's card, split off by the card's hairline. */
1375
- .knobs-panel .knobs-card>.knobs-subhead{display:flex;align-items:center;justify-content:space-between;gap:8px;min-height:0;height:calc(var(--k-row) - var(--k-unit) * 2);padding:0 var(--k-inset);color:var(--k-label);font-size:var(--k-text-meta);font-weight:var(--k-title-weight);cursor:pointer;user-select:none}
2959
+ .knobs-panel .knobs-card>.knobs-subhead{display:flex;align-items:center;justify-content:space-between;gap:8px;min-height:0;height:calc(var(--_k-row) - var(--_k-unit) * 2);padding:0 var(--_k-inset);color:var(--_k-fg-2);font-size:var(--_k-text-meta);font-weight:var(--_k-weight-title);cursor:pointer;user-select:none}
1376
2960
  .knobs-subhead-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
1377
2961
  .knobs-subhead[aria-expanded="true"] .knobs-caret{transform:rotate(90deg)}
1378
- .knobs-subhead:hover .knobs-caret{color:var(--k-label)}
2962
+ .knobs-subhead:hover .knobs-caret{color:var(--_k-fg-2)}
1379
2963
  .knobs-card>.knobs-subhead:focus-visible::after{opacity:1}
1380
2964
 
1381
2965
  /* Inspector rows: number cells, ranges, dials, seeds and key combinations. */
1382
2966
  .knobs-panel .knobs-insp{gap:8px}
1383
2967
  .knobs-panel .knobs-insp[data-kind="vec"]>span:first-child{flex-shrink:0;max-width:34%}
1384
- .knobs-cells{flex:0 1 auto;display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);gap:var(--k-tray-pad);width:calc(var(--k-row) * 5);max-width:64%}
1385
- .knobs-cells[data-wide]{width:calc(var(--k-row) * 7.5);max-width:72%}
1386
- .knobs-cell{position:relative;display:flex;align-items:center;justify-content:space-between;gap:3px;min-width:0;height:var(--kc-control-h);padding:0 5px;border-radius:var(--k-radius-md);background:var(--k-seg-bg);cursor:ew-resize;user-select:none;touch-action:none;outline:none;transition:background var(--k-hover-t)}
1387
- .knobs-cell:hover,.knobs-cell:focus-visible{background:color-mix(in srgb,var(--k-surface-hi) 70%,var(--k-seg-bg))}
1388
- .knobs-active .knobs-cell:focus,.knobs-cell[data-panned]{background:var(--k-surface-hi)}
1389
- .knobs-cell-axis{flex:none;font-style:normal;font-size:var(--k-text-cap);font-weight:var(--k-title-weight);color:var(--k-dim)}
1390
- .knobs-cell-read,.knobs-range-read,.knobs-angle-read,.knobs-seed-read{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--k-label);font-family:var(--k-value-font);font-size:var(--kc-value-size);font-variant-numeric:tabular-nums;font-feature-settings:"tnum"}
1391
- .knobs-cell:focus-visible .knobs-cell-read,.knobs-active .knobs-cell:focus .knobs-cell-read,.knobs-cell[data-panned] .knobs-cell-read{color:var(--k-text)}
1392
- .knobs-panel .knobs-link{flex:none;width:20px;height:20px;margin:0 -4px 0 auto;padding:0;display:inline-flex;align-items:center;justify-content:center;background:transparent;border-radius:var(--k-round);color:var(--k-dim);cursor:pointer;transition:background var(--k-hover-t),color var(--k-hover-t)}
1393
- .knobs-panel .knobs-link:hover{background:var(--k-surface-hi);color:var(--k-text)}
1394
- .knobs-panel .knobs-link[aria-pressed="true"]{color:var(--k-text)}
2968
+ .knobs-cells{flex:0 1 auto;display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);gap:var(--_k-tray-pad);width:calc(var(--_k-row) * 5);max-width:64%}
2969
+ .knobs-cells[data-wide]{width:calc(var(--_k-row) * 7.5);max-width:72%}
2970
+ .knobs-cell{position:relative;display:flex;align-items:center;justify-content:space-between;gap:3px;min-width:0;height:var(--_k-control-h);padding:0 5px;border-radius:var(--_k-radius-md);background:var(--_k-segmented-track);cursor:ew-resize;user-select:none;touch-action:none;outline:none;transition:background var(--k-hover-t)}
2971
+ .knobs-cell:hover,.knobs-cell:focus-visible{background:color-mix(in srgb,var(--_k-fill-selected) 70%,var(--_k-segmented-track))}
2972
+ .knobs-active .knobs-cell:focus,.knobs-cell[data-panned]{background:var(--_k-fill-selected)}
2973
+ .knobs-cell-axis{flex:none;font-style:normal;font-size:var(--_k-text-cap);font-weight:var(--_k-weight-title);color:var(--_k-fg-3)}
2974
+ .knobs-cell-read,.knobs-range-read,.knobs-angle-read,.knobs-seed-read{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--_k-fg-2);font-family:var(--_k-value-font);font-size:var(--_k-value-size);font-variant-numeric:tabular-nums;font-feature-settings:"tnum"}
2975
+ .knobs-cell:focus-visible .knobs-cell-read,.knobs-active .knobs-cell:focus .knobs-cell-read,.knobs-cell[data-panned] .knobs-cell-read{color:var(--_k-fg)}
2976
+ .knobs-panel .knobs-link{flex:none;width:20px;height:20px;margin:0 -4px 0 auto;padding:0;display:inline-flex;align-items:center;justify-content:center;background:transparent;border-radius:var(--_k-round);color:var(--_k-fg-3);cursor:pointer;transition:background var(--k-hover-t),color var(--k-hover-t)}
2977
+ .knobs-panel .knobs-link:hover{background:var(--_k-fill-selected);color:var(--_k-fg)}
2978
+ .knobs-panel .knobs-link[aria-pressed="true"]{color:var(--_k-fg)}
1395
2979
  .knobs-link .knobs-icon{width:var(--k-icon-sm);height:var(--k-icon-sm)}
1396
2980
  /* The inline editor over a readout: above the GPU canvas, which leaves that readout to it. */
1397
- .knobs-panel .knobs-cell-edit{position:absolute;z-index:3;right:calc(var(--k-inset) - 6px);top:50%;transform:translateY(-50%);width:calc(7ch + 12px);height:var(--kc-control-h);padding:0 6px;text-align:right;background:linear-gradient(var(--k-surface-hi),var(--k-surface-hi)),var(--k-bg);border:0;border-radius:var(--k-radius-md);outline:none;color:var(--k-text);caret-color:var(--k-accent);font-family:var(--k-value-font);font-variant-numeric:tabular-nums;font-size:var(--kc-value-size);animation:knobs-fade .12s ease-out}
2981
+ .knobs-panel .knobs-cell-edit{position:absolute;z-index:3;right:calc(var(--_k-inset) - 6px);top:50%;transform:translateY(-50%);width:calc(7ch + 12px);height:var(--_k-control-h);padding:0 6px;text-align:right;background:linear-gradient(var(--_k-fill-selected),var(--_k-fill-selected)),var(--_k-bg);border:0;border-radius:var(--_k-radius-md);outline:none;color:var(--_k-fg);caret-color:var(--_k-accent);font-family:var(--_k-value-font);font-variant-numeric:tabular-nums;font-size:var(--_k-value-size);animation:knobs-fade .12s ease-out}
1398
2982
  .knobs-cell.knobs-editing>:not(.knobs-cell-edit){visibility:hidden}
1399
2983
  .knobs-panel .knobs-cell>.knobs-cell-edit{inset:0;width:auto;height:auto;transform:none}
1400
2984
  .knobs-panel[data-gpu-active="true"] .knobs-cell-edit{z-index:2147480003}
1401
2985
 
1402
- .knobs-panel .knobs-row.knobs-range{display:block;height:var(--k-row);padding:0}
1403
- .knobs-range-track{position:absolute;inset:0;overflow:hidden;cursor:ew-resize;user-select:none;touch-action:none;transition:--kr-lo ${FILL_T} ${DELAY},--kr-hi ${FILL_T} ${DELAY};--kr-tint:var(--k-fill-rest)}
2986
+ .knobs-panel .knobs-row.knobs-range{display:block;height:var(--_k-row);padding:0}
2987
+ .knobs-range-track{position:absolute;inset:0;overflow:hidden;cursor:ew-resize;user-select:none;touch-action:none;transition:--kr-lo ${FILL_T} ${DELAY},--kr-hi ${FILL_T} ${DELAY};--kr-tint:var(--_k-slider-fill)}
1404
2988
  .knobs-range-fill{position:absolute;inset:0;transform-origin:0 0;transform:scaleX(0);background:var(--kr-tint);pointer-events:none;transition:transform ${FILL_T} ${DELAY},background .15s}
1405
- .knobs-range:hover .knobs-range-track{--kr-tint:color-mix(in srgb,var(--k-accent) var(--k-fill-hover-mix),var(--k-fill-base))}
2989
+ .knobs-range:hover .knobs-range-track{--kr-tint:color-mix(in srgb,var(--_k-accent) var(--_k-fill-hover-mix),var(--_k-fill-base))}
1406
2990
  .knobs-range.knobs-active .knobs-range-track{--kr-tint:var(--k-fill-active)}
1407
2991
  /* --k-range-blur: while the ends glide, the band is a gradient in the track's space whose ends ramp
1408
2992
  over their smears (--kr-smear-lo/hi, px; see inspector.ts), standing in for the scaled fill. */
@@ -1421,41 +3005,41 @@ ${POINTER_ROW} .knobs-slider.knobs-modified:not(:hover,.knobs-active) .knobs-val
1421
3005
  .knobs-range:not(.knobs-mixed):hover .knobs-range-text{--kr-show-lo:1;--kr-show-hi:1}
1422
3006
  .knobs-range:not(.knobs-mixed)[data-end-focus="lo"]:is([data-k-fv],.knobs-active) .knobs-range-text{--kr-show-lo:1}
1423
3007
  .knobs-range:not(.knobs-mixed)[data-end-focus="hi"]:is([data-k-fv],.knobs-active) .knobs-range-text{--kr-show-hi:1}
1424
- .knobs-range-thumb::before{content:"";position:absolute;left:0;top:50%;width:3px;height:calc(var(--k-row) - 12px);margin-top:calc(6px - var(--k-row) / 2);translate:-50% 0;border-radius:var(--k-round);background:var(--k-handle);opacity:0;scale:.25 1;transition:opacity .15s,scale .22s var(--k-ease)}
3008
+ .knobs-range-thumb::before{content:"";position:absolute;left:0;top:50%;width:3px;height:calc(var(--_k-row) - 12px);margin-top:calc(6px - var(--_k-row) / 2);translate:-50% 0;border-radius:var(--_k-round);background:var(--_k-slider-handle);opacity:0;scale:.25 1;transition:opacity .15s,scale .22s var(--k-ease)}
1425
3009
  .knobs-range:hover .knobs-range-thumb::before{opacity:.5}
1426
3010
  .knobs-range-thumb:focus-visible::before,.knobs-range.knobs-active .knobs-range-thumb:focus::before{opacity:.95;scale:1}
1427
- .knobs-range .knobs-label{max-width:calc(55% - var(--k-inset))}
1428
- .knobs-range-read{position:absolute;right:var(--k-inset);top:50%;transform:translateY(-50%);pointer-events:none}
1429
- .knobs-range.knobs-active .knobs-range-read,.knobs-range:has(:focus-visible) .knobs-range-read{color:var(--k-text)}
1430
- .knobs-range.knobs-modified .knobs-range-read{color:color-mix(in srgb,var(--k-modified) calc(var(--k-readout-mark) * 100%),var(--k-label))}
3011
+ .knobs-range .knobs-label{max-width:calc(55% - var(--_k-inset))}
3012
+ .knobs-range-read{position:absolute;right:var(--_k-inset);top:50%;transform:translateY(-50%);pointer-events:none}
3013
+ .knobs-range.knobs-active .knobs-range-read,.knobs-range:has(:focus-visible) .knobs-range-read{color:var(--_k-fg)}
3014
+ .knobs-range.knobs-modified .knobs-range-read{color:color-mix(in srgb,var(--_k-modified) calc(var(--k-readout-mark) * 100%),var(--_k-fg-2))}
1431
3015
  .knobs-range.knobs-editing .knobs-range-read{opacity:0}
1432
3016
 
1433
- .knobs-angle{display:inline-flex;align-items:center;gap:8px;height:var(--kc-control-h);margin-left:auto;cursor:ew-resize;user-select:none;touch-action:none;outline:none}
1434
- .knobs-angle:focus-visible .knobs-angle-read,.knobs-active .knobs-angle-read{color:var(--k-text)}
1435
- .knobs-dial{position:relative;flex:none;width:var(--kc-control-h);height:var(--kc-control-h);border-radius:50%;background:var(--k-seg-bg);box-shadow:inset 0 0 0 1px var(--k-line);cursor:grab;transition:box-shadow .15s}
1436
- .knobs-angle:is(:hover,:focus-visible) .knobs-dial,.knobs-active .knobs-dial{box-shadow:inset 0 0 0 1px var(--k-line-hi)}
3017
+ .knobs-angle{display:inline-flex;align-items:center;gap:8px;height:var(--_k-control-h);margin-left:auto;cursor:ew-resize;user-select:none;touch-action:none;outline:none}
3018
+ .knobs-angle:focus-visible .knobs-angle-read,.knobs-active .knobs-angle-read{color:var(--_k-fg)}
3019
+ .knobs-dial{position:relative;flex:none;width:var(--_k-control-h);height:var(--_k-control-h);border-radius:50%;background:var(--_k-segmented-track);box-shadow:inset 0 0 0 1px var(--_k-border);cursor:grab;transition:box-shadow .15s}
3020
+ .knobs-angle:is(:hover,:focus-visible) .knobs-dial,.knobs-active .knobs-dial{box-shadow:inset 0 0 0 1px var(--_k-border-strong)}
1437
3021
  .knobs-active .knobs-dial{cursor:grabbing}
1438
- .knobs-dial::after{content:"";position:absolute;left:50%;top:50%;width:3px;height:3px;margin:-1.5px;border-radius:50%;background:var(--k-accent)}
1439
- .knobs-dial-hand{position:absolute;left:50%;top:18%;bottom:50%;width:1.5px;margin-left:-.75px;border-radius:1px;background:var(--k-accent);transform-origin:50% 100%;transition:rotate ${FILL_T} ${DELAY}}
3022
+ .knobs-dial::after{content:"";position:absolute;left:50%;top:50%;width:3px;height:3px;margin:-1.5px;border-radius:50%;background:var(--_k-accent)}
3023
+ .knobs-dial-hand{position:absolute;left:50%;top:18%;bottom:50%;width:1.5px;margin-left:-.75px;border-radius:1px;background:var(--_k-accent);transform-origin:50% 100%;transition:rotate ${FILL_T} ${DELAY}}
1440
3024
  .knobs-active .knobs-dial-hand{transition:none}
1441
3025
  .knobs-insp.knobs-editing .knobs-angle-read,.knobs-insp.knobs-editing .knobs-seed-read{opacity:0}
1442
3026
 
1443
3027
  .knobs-panel .knobs-insp[data-kind="seed"]{gap:2px}
1444
- .knobs-seed{display:inline-flex;align-items:center;height:var(--kc-control-h);margin-left:auto;padding:0 4px;border-radius:var(--k-radius-sm);cursor:text;outline:none}
1445
- .knobs-seed:focus-visible .knobs-seed-read,.knobs-active>.knobs-seed .knobs-seed-read{color:var(--k-text)}
3028
+ .knobs-seed{display:inline-flex;align-items:center;height:var(--_k-control-h);margin-left:auto;padding:0 4px;border-radius:var(--_k-radius-sm);cursor:text;outline:none}
3029
+ .knobs-seed:focus-visible .knobs-seed-read,.knobs-active>.knobs-seed .knobs-seed-read{color:var(--_k-fg)}
1446
3030
  .knobs-seed-digits{display:inline-flex;align-items:center;line-height:2.1;margin-block:-.375em;--rn-edge-fade:.5em}
1447
3031
  .knobs-seed-read{display:inline-flex;align-items:center}
1448
3032
  .knobs-seed-read[data-mixed]::before{content:"—"}
1449
3033
  .knobs-seed-read[data-mixed]>.knobs-seed-digits{display:none}
1450
- .knobs-panel .knobs-seed-roll{flex:none;width:var(--k-icon-btn);height:var(--k-icon-btn);padding:0;display:inline-flex;align-items:center;justify-content:center;background:transparent;border-radius:var(--k-round);color:var(--k-dim);cursor:pointer;transition:background var(--k-hover-t),color var(--k-hover-t)}
1451
- .knobs-panel .knobs-seed-roll:hover{background:var(--k-surface-hi);color:var(--k-text)}
3034
+ .knobs-panel .knobs-seed-roll{flex:none;width:var(--k-icon-btn);height:var(--k-icon-btn);padding:0;display:inline-flex;align-items:center;justify-content:center;background:transparent;border-radius:var(--_k-round);color:var(--_k-fg-3);cursor:pointer;transition:background var(--k-hover-t),color var(--k-hover-t)}
3035
+ .knobs-panel .knobs-seed-roll:hover{background:var(--_k-fill-selected);color:var(--_k-fg)}
1452
3036
  .knobs-seed-roll .knobs-die-icon{width:var(--k-icon-sm);height:var(--k-icon-sm)}
1453
3037
 
1454
- .knobs-panel .knobs-keys{flex:none;display:inline-flex;align-items:center;justify-content:center;max-width:62%;height:var(--kc-control-h);padding:0 8px;overflow:hidden;background:var(--k-seg-bg);border-radius:var(--k-radius-md);color:var(--k-text);font-family:inherit;font-weight:inherit;font-size:var(--kc-value-size);letter-spacing:.08em;white-space:nowrap;cursor:pointer;transition:background var(--k-hover-t),color var(--k-hover-t)}
1455
- .knobs-panel .knobs-keys:is(:hover,:focus-visible){background:color-mix(in srgb,var(--k-surface-hi) 70%,var(--k-seg-bg))}
1456
- .knobs-panel .knobs-keys[data-empty]{color:var(--k-dim);letter-spacing:0}
3038
+ .knobs-panel .knobs-keys{flex:none;display:inline-flex;align-items:center;justify-content:center;max-width:62%;height:var(--_k-control-h);padding:0 8px;overflow:hidden;background:var(--_k-segmented-track);border-radius:var(--_k-radius-md);color:var(--_k-fg);font-family:inherit;font-weight:inherit;font-size:var(--_k-value-size);letter-spacing:.08em;white-space:nowrap;cursor:pointer;transition:background var(--k-hover-t),color var(--k-hover-t)}
3039
+ .knobs-panel .knobs-keys:is(:hover,:focus-visible){background:color-mix(in srgb,var(--_k-fill-selected) 70%,var(--_k-segmented-track))}
3040
+ .knobs-panel .knobs-keys[data-empty]{color:var(--_k-fg-3);letter-spacing:0}
1457
3041
  /* Listening: a soft accent wash, no ring, and the text breathing in "Type keys…" (keyCap). */
1458
- .knobs-panel .knobs-keys[aria-pressed="true"]{background:var(--k-pill-bg);color:var(--k-label)}
3042
+ .knobs-panel .knobs-keys[aria-pressed="true"]{background:var(--k-pill-bg);color:var(--_k-fg-2)}
1459
3043
  .knobs-keys[aria-pressed="true"] .knobs-keys-text{animation:knobs-breathe 1.6s ease-in-out infinite}
1460
3044
  @keyframes knobs-breathe{50%{opacity:.55}}
1461
3045
  .knobs-keys-text{min-width:0;overflow:hidden;text-overflow:ellipsis}
@@ -1466,35 +3050,35 @@ ${POINTER_ROW} .knobs-slider.knobs-modified:not(:hover,.knobs-active) .knobs-val
1466
3050
  /* Toolbars: icon, label and shortcut per button, in equal columns balanced across their rows
1467
3051
  (inspector.ts sets --k-tool-cols); one gap between them and around them. Buttons take the
1468
3052
  button tokens. */
1469
- .knobs-panel .knobs-row.knobs-toolbar{--k-tool-gap:max(4px,calc((var(--k-row) - var(--k-button-h,var(--kc-control-h))) / 2));display:grid;grid-template-columns:repeat(var(--k-tool-cols,1),minmax(0,1fr));gap:var(--k-tool-gap);height:auto;min-height:var(--k-row);padding:var(--k-tool-gap) var(--k-inset)}
3053
+ .knobs-panel .knobs-row.knobs-toolbar{--k-tool-gap:max(4px,calc((var(--_k-row) - var(--k-button-h,var(--_k-control-h))) / 2));display:grid;grid-template-columns:repeat(var(--k-tool-cols,1),minmax(0,1fr));gap:var(--k-tool-gap);height:auto;min-height:var(--_k-row);padding:var(--k-tool-gap) var(--_k-inset)}
1470
3054
  .knobs-card>.knobs-toolbar:hover{background:transparent}
1471
3055
  .knobs-card>.knobs-toolbar:has(:focus-visible)::after{opacity:0}
1472
- .knobs-panel .knobs-tool{display:flex;align-items:center;gap:6px;min-width:0;height:var(--k-button-h,var(--kc-control-h));padding:0 8px;background:var(--k-button-bg,var(--k-seg-bg));border-radius:var(--k-button-radius,var(--k-radius-md));box-shadow:inset 0 0 0 1px var(--k-button-line,transparent);
1473
- color:var(--k-button-color,var(--k-label));font-size:var(--k-button-font-size,var(--k-text-control));font-weight:var(--k-label-weight);white-space:nowrap;cursor:pointer;transition:background var(--k-hover-t),color .15s,box-shadow .15s,scale .12s var(--k-ease),opacity .15s}
1474
- .knobs-panel .knobs-tool:is(:hover:not([disabled]),:focus-visible){background:var(--k-button-hover-bg,var(--k-surface-hi));box-shadow:inset 0 0 0 1px var(--k-button-hover-line,var(--k-button-line,transparent));color:var(--k-text)}
3056
+ .knobs-panel .knobs-tool{display:flex;align-items:center;gap:6px;min-width:0;height:var(--k-button-h,var(--_k-control-h));padding:0 8px;background:var(--k-button-bg,var(--_k-segmented-track));border-radius:var(--k-button-radius,var(--_k-radius-md));box-shadow:inset 0 0 0 1px var(--k-button-line,transparent);
3057
+ color:var(--k-button-color,var(--_k-fg-2));font-size:var(--k-button-font-size,var(--_k-text-control));font-weight:var(--_k-weight-label);white-space:nowrap;cursor:pointer;transition:background var(--k-hover-t),color .15s,box-shadow .15s,scale .12s var(--k-ease),opacity .15s}
3058
+ .knobs-panel .knobs-tool:is(:hover:not([disabled]),:focus-visible){background:var(--k-button-hover-bg,var(--_k-fill-selected));box-shadow:inset 0 0 0 1px var(--k-button-hover-line,var(--k-button-line,transparent));color:var(--_k-fg)}
1475
3059
  .knobs-panel .knobs-tool:is(:active:not([disabled]),.knobs-pressed){scale:.96}
1476
3060
  .knobs-panel .knobs-tool[disabled]{opacity:var(--k-disabled-opacity);cursor:default}
1477
3061
  .knobs-tool .knobs-icon{flex:none;width:var(--k-icon-sm);height:var(--k-icon-sm)}
1478
3062
  .knobs-tool-label{min-width:0;overflow:hidden;text-overflow:ellipsis}
1479
3063
  /* The shortcut sits at the button's end, so a column of buttons lines their chips up. */
1480
- .knobs-panel .knobs-tool-key{flex:none;margin-left:auto;padding-left:4px;font:inherit;font-size:var(--k-text-cap);font-variant-numeric:tabular-nums;color:var(--k-dim);letter-spacing:.06em}
3064
+ .knobs-panel .knobs-tool-key{flex:none;margin-left:auto;padding-left:4px;font:inherit;font-size:var(--_k-text-cap);font-variant-numeric:tabular-nums;color:var(--_k-fg-3);letter-spacing:.06em}
1481
3065
  .knobs-panel :is([data-disabled],[data-readonly]) :is(.knobs-cell,.knobs-range-track,.knobs-angle,.knobs-dial,.knobs-seed,.knobs-keys,.knobs-tool){cursor:default}
1482
3066
 
1483
3067
  /* Row accessories (rowAccessory): the host's node, just after the label. */
1484
- .knobs-accessory{display:inline-flex;align-items:center;gap:var(--k-tray-pad);flex:none;min-width:0;color:var(--k-label)}
3068
+ .knobs-accessory{display:inline-flex;align-items:center;gap:var(--_k-tray-pad);flex:none;min-width:0;color:var(--_k-fg-2)}
1485
3069
  .knobs-accessory:empty{display:none}
1486
3070
  .knobs-panel .knobs-row:where(:not(.knobs-slider,.knobs-x,.knobs-spring))>.knobs-accessory{margin:0 auto 0 -4px}
1487
3071
  .knobs-track>.knobs-accessory{position:absolute;top:0;bottom:0;left:calc(var(--k-label-right,0px) + 4px);z-index:1}
1488
3072
  .knobs-x-head>.knobs-accessory{margin:0 auto 0 -4px}
1489
- .knobs-action-row>.knobs-accessory{position:absolute;top:0;bottom:0;right:var(--k-inset)}
3073
+ .knobs-action-row>.knobs-accessory{position:absolute;top:0;bottom:0;right:var(--_k-inset)}
1490
3074
  .knobs-action-row[data-keyed]>.knobs-accessory{position:static}
1491
3075
 
1492
3076
  /* Foldable groups (folded / groupFolded): the header toggles its card. */
1493
3077
  .knobs-panel .knobs-group-head[data-foldable]{cursor:pointer;user-select:none;transition:background var(--k-hover-t)}
1494
- .knobs-panel .knobs-group-head[data-foldable]:focus-visible{background:var(--k-surface)}
3078
+ .knobs-panel .knobs-group-head[data-foldable]:focus-visible{background:var(--_k-fill)}
1495
3079
  .knobs-group-head>span:last-child>.knobs-caret{margin:0 5px 0 3px}
1496
3080
  .knobs-group-head[aria-expanded="true"] .knobs-caret{transform:rotate(90deg)}
1497
- .knobs-group-head[data-foldable]:hover .knobs-caret{color:var(--k-label)}
3081
+ .knobs-group-head[data-foldable]:hover .knobs-caret{color:var(--_k-fg-2)}
1498
3082
 
1499
3083
  /* A choice row: the label keeps its words and the value takes the rest, truncating at its end
1500
3084
  (the whole value is in the menu and the button's tooltip); choice.ts sets how far the label may
@@ -1513,61 +3097,61 @@ ${POINTER_ROW} .knobs-slider.knobs-modified:not(:hover,.knobs-active) .knobs-val
1513
3097
  .knobs-hinting .knobs-hint-miss{opacity:var(--k-disabled-opacity);transition:opacity .1s}
1514
3098
  .knobs-hint-layer{position:absolute;left:0;top:0;width:0;height:0;pointer-events:none;z-index:5;animation:knobs-in .1s var(--k-ease)}
1515
3099
  /* The badges are <kbd>s, so they outrank the scoped reset's (0,1,1). */
1516
- .knobs-panel .knobs-hint{position:absolute;transform:translateY(-50%);display:inline-flex;align-items:center;height:15px;padding:0 4px;border-radius:var(--k-radius-sm);background:var(--k-accent);color:var(--k-bg);box-shadow:0 1px 3px rgba(0,0,0,calc(.35 * var(--k-lift)));
1517
- font:700 var(--k-text-cap)/1 var(--k-mono);letter-spacing:.04em;text-transform:uppercase;pointer-events:none}
3100
+ .knobs-panel .knobs-hint{position:absolute;transform:translateY(-50%);display:inline-flex;align-items:center;height:15px;padding:0 4px;border-radius:var(--_k-radius-sm);background:var(--_k-accent);color:var(--_k-bg);box-shadow:0 1px 3px rgba(0,0,0,calc(.35 * var(--k-lift)));
3101
+ font:700 var(--_k-text-cap)/1 var(--_k-mono);letter-spacing:.04em;text-transform:uppercase;pointer-events:none}
1518
3102
  .knobs-panel .knobs-hint[hidden]{display:none}
1519
3103
  .knobs-hint-typed{opacity:var(--k-hint-typed-opacity)}
1520
3104
  .knobs-hint-rest{opacity:1}
1521
3105
 
1522
3106
  /* A focused row's options: tiny digits in hint mode's look, once focus settles (optkeys.ts). */
1523
3107
  .knobs-optkeys{position:absolute;left:0;top:0;width:0;height:0;pointer-events:none;z-index:5}
1524
- .knobs-panel .knobs-optkey{position:absolute;transform:translateY(-50%);display:inline-flex;align-items:center;height:12px;padding:0 3px;border-radius:var(--k-radius-sm);background:var(--k-accent);color:var(--k-bg);box-shadow:0 1px 3px rgba(0,0,0,calc(.35 * var(--k-lift)));
1525
- font:700 calc(var(--k-text-cap) * .85)/1 var(--k-mono);letter-spacing:.04em;pointer-events:none;opacity:0;transition:opacity .12s var(--k-ease)}
3108
+ .knobs-panel .knobs-optkey{position:absolute;transform:translateY(-50%);display:inline-flex;align-items:center;height:12px;padding:0 3px;border-radius:var(--_k-radius-sm);background:var(--_k-accent);color:var(--_k-bg);box-shadow:0 1px 3px rgba(0,0,0,calc(.35 * var(--k-lift)));
3109
+ font:700 calc(var(--_k-text-cap) * .85)/1 var(--_k-mono);letter-spacing:.04em;pointer-events:none;opacity:0;transition:opacity .12s var(--k-ease)}
1526
3110
  .knobs-panel .knobs-optkey-range{transform:translate(-100%,-50%)}
1527
3111
  .knobs-panel .knobs-optkey[data-shown]{opacity:.85;transition-duration:.15s}
1528
3112
 
1529
3113
  /* Custom actions */
1530
- .knobs-panel .knobs-custom-actions{display:grid;grid-template-columns:repeat(auto-fit,minmax(96px,1fr));gap:var(--k-gap);margin-top:var(--k-section-gap)}
1531
- .knobs-panel .knobs-custom-actions button{height:var(--k-button-h,var(--k-action-h));min-height:24px;padding:0 8px;font-size:var(--k-button-font-size,var(--k-text-control));font-weight:var(--k-label-weight);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--k-button-color,var(--k-label));cursor:pointer;
1532
- background:var(--k-button-bg,var(--k-surface));border-radius:var(--k-button-radius,var(--k-radius));box-shadow:inset 0 0 0 1px var(--k-button-line,transparent);transition:background var(--k-hover-t),color var(--k-hover-t),opacity .15s,transform .12s,box-shadow .15s}
1533
- .knobs-panel .knobs-custom-actions button:is(:hover:not([disabled]),:focus-visible){background:var(--k-button-hover-bg,var(--k-surface-hi));box-shadow:inset 0 0 0 1px var(--k-button-hover-line,var(--k-button-line,transparent));color:var(--k-text)}
3114
+ .knobs-panel .knobs-custom-actions{display:grid;grid-template-columns:repeat(auto-fit,minmax(96px,1fr));gap:var(--_k-gap);margin-top:var(--k-section-gap)}
3115
+ .knobs-panel .knobs-custom-actions button{height:var(--k-button-h,var(--k-action-h));min-height:24px;padding:0 8px;font-size:var(--k-button-font-size,var(--_k-text-control));font-weight:var(--_k-weight-label);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--k-button-color,var(--_k-fg-2));cursor:pointer;
3116
+ background:var(--k-button-bg,var(--_k-fill));border-radius:var(--k-button-radius,var(--_k-radius));box-shadow:inset 0 0 0 1px var(--k-button-line,transparent);transition:background var(--k-hover-t),color var(--k-hover-t),opacity .15s,transform .12s,box-shadow .15s}
3117
+ .knobs-panel .knobs-custom-actions button:is(:hover:not([disabled]),:focus-visible){background:var(--k-button-hover-bg,var(--_k-fill-selected));box-shadow:inset 0 0 0 1px var(--k-button-hover-line,var(--k-button-line,transparent));color:var(--_k-fg)}
1534
3118
  .knobs-panel .knobs-custom-actions button:active:not([disabled]){transform:scale(.97)}
1535
3119
  .knobs-panel .knobs-tile-body>.knobs-custom-actions button[disabled]{opacity:var(--k-disabled-opacity);cursor:default}
1536
3120
 
1537
3121
  /* Variants Disclosure Drawer */
1538
- .knobs-transfer{display:grid;grid-template-columns:1fr 1fr;gap:var(--k-gap);margin-top:8px;padding-top:8px;border-top:1px solid var(--k-line)}
1539
- .knobs-transfer button{height:var(--k-button-h,24px);padding:0 8px;background:var(--k-button-bg,var(--k-surface));border-radius:var(--k-button-radius,var(--k-radius));box-shadow:inset 0 0 0 1px var(--k-button-line,transparent);font-size:var(--k-button-font-size,var(--k-text-meta));color:var(--k-button-color,var(--k-label));cursor:pointer;transition:background var(--k-hover-t),color var(--k-hover-t),box-shadow .15s}
1540
- .knobs-transfer button:is(:hover,:focus-visible){background:var(--k-button-hover-bg,var(--k-surface-hi));box-shadow:inset 0 0 0 1px var(--k-button-hover-line,var(--k-button-line,transparent));color:var(--k-text)}
3122
+ .knobs-transfer{display:grid;grid-template-columns:1fr 1fr;gap:var(--_k-gap);margin-top:8px;padding-top:8px;border-top:1px solid var(--_k-border)}
3123
+ .knobs-transfer button{height:var(--k-button-h,24px);padding:0 8px;background:var(--k-button-bg,var(--_k-fill));border-radius:var(--k-button-radius,var(--_k-radius));box-shadow:inset 0 0 0 1px var(--k-button-line,transparent);font-size:var(--k-button-font-size,var(--_k-text-meta));color:var(--k-button-color,var(--_k-fg-2));cursor:pointer;transition:background var(--k-hover-t),color var(--k-hover-t),box-shadow .15s}
3124
+ .knobs-transfer button:is(:hover,:focus-visible){background:var(--k-button-hover-bg,var(--_k-fill-selected));box-shadow:inset 0 0 0 1px var(--k-button-hover-line,var(--k-button-line,transparent));color:var(--_k-fg)}
1541
3125
  .knobs-sound-pref{grid-template-columns:1fr}
1542
3126
 
1543
3127
  /* Context menu: borrows its panel's tokens (see menu.ts) and floats above everything. */
1544
- .knobs-menu{position:fixed;z-index:2147480004;min-width:176px;padding:var(--k-unit);box-sizing:border-box;font:var(--k-font-weight) var(--k-text-control)/1.35 var(--k-font);color:var(--k-text);text-align:left;-webkit-font-smoothing:antialiased;
1545
- background:linear-gradient(var(--k-surface-hi),var(--k-surface-hi)),color-mix(in srgb,var(--k-bg) 90%,transparent);border:1px solid var(--k-line);border-radius:var(--k-radius);
1546
- box-shadow:var(--k-shadow),inset 0 1px 0 var(--k-rim);-webkit-backdrop-filter:blur(20px) saturate(1.6);backdrop-filter:blur(20px) saturate(1.6);outline:none;user-select:none}
3128
+ .knobs-menu{position:fixed;z-index:2147480004;min-width:176px;padding:var(--_k-unit);box-sizing:border-box;font:var(--_k-weight) var(--_k-text-control)/1.35 var(--_k-font);color:var(--_k-fg);text-align:left;-webkit-font-smoothing:antialiased;
3129
+ background:linear-gradient(var(--_k-fill-selected),var(--_k-fill-selected)),color-mix(in srgb,var(--_k-bg) 90%,transparent);border:1px solid var(--_k-border);border-radius:var(--_k-radius);
3130
+ box-shadow:var(--_k-shadow-overlay),inset 0 1px 0 var(--_k-rim);-webkit-backdrop-filter:blur(20px) saturate(1.6);backdrop-filter:blur(20px) saturate(1.6);outline:none;user-select:none}
1547
3131
  .knobs-menu{max-width:min(480px,calc(100vw - 12px))}
1548
3132
  .knobs-menu-list{max-height:min(360px,calc(100dvh - 120px));overflow-y:auto;overscroll-behavior:contain;scrollbar-width:thin}
1549
- .knobs-menu-item{position:relative;display:flex;align-items:center;justify-content:space-between;gap:24px;height:var(--kc-control-h);min-height:20px;padding:0 8px;border-radius:var(--k-radius-sm);cursor:default;white-space:nowrap;transition:background .08s}
3133
+ .knobs-menu-item{position:relative;display:flex;align-items:center;justify-content:space-between;gap:24px;height:var(--_k-control-h);min-height:20px;padding:0 8px;border-radius:var(--_k-radius-sm);cursor:default;white-space:nowrap;transition:background .08s}
1550
3134
  .knobs-menu-item>span{min-width:0;overflow:hidden;text-overflow:ellipsis}
1551
3135
  .knobs-menu-item[hidden]{display:none}
1552
3136
  /* The match shows by colour, not weight, so a filtered label keeps the width the menu measured. */
1553
- .knobs-menu-item>span[data-marked]{color:var(--k-label)}
1554
- .knobs-menu-item mark{background:none;color:var(--k-text)}
1555
- .knobs-menu .knobs-menu-search{display:block;width:100%;height:var(--kc-control-h);min-height:22px;margin:0 0 var(--k-unit);padding:0 8px;border:0;border-radius:var(--k-radius-sm);background:var(--k-seg-bg);color:var(--k-text);font:inherit;outline:none;-webkit-appearance:none;appearance:none}
1556
- .knobs-menu .knobs-menu-search::placeholder{color:var(--k-dim)}
3137
+ .knobs-menu-item>span[data-marked]{color:var(--_k-fg-2)}
3138
+ .knobs-menu-item mark{background:none;color:var(--_k-fg)}
3139
+ .knobs-menu .knobs-menu-search{display:block;width:100%;height:var(--_k-control-h);min-height:22px;margin:0 0 var(--_k-unit);padding:0 8px;border:0;border-radius:var(--_k-radius-sm);background:var(--_k-segmented-track);color:var(--_k-fg);font:inherit;outline:none;-webkit-appearance:none;appearance:none}
3140
+ .knobs-menu .knobs-menu-search::placeholder{color:var(--_k-fg-3)}
1557
3141
  .knobs-menu .knobs-menu-search::-webkit-search-cancel-button{display:none}
1558
3142
  .knobs-menu [hidden]{display:none!important}
1559
- .knobs-menu-empty{padding:0 8px;height:var(--kc-control-h);display:flex;align-items:center;color:var(--k-dim)}
1560
- .knobs-menu-item[data-active]{background:color-mix(in srgb,var(--k-accent) 14%,transparent)}
1561
- .knobs-menu-item[aria-disabled]{opacity:var(--k-disabled-opacity);color:var(--k-label)}
1562
- .knobs-menu-item kbd{font:var(--k-text-cap)/1 var(--k-mono);font-variant-numeric:tabular-nums;color:var(--k-dim);letter-spacing:0}
1563
- .knobs-menu-item[data-separated]{margin-top:calc(var(--k-unit) * 2 + 1px)}
1564
- .knobs-menu-item[data-separated]::before{content:"";position:absolute;left:8px;right:8px;top:calc(var(--k-unit) * -1 - 1px);height:1px;transform:scaleY(.5);background:var(--k-line)}
3143
+ .knobs-menu-empty{padding:0 8px;height:var(--_k-control-h);display:flex;align-items:center;color:var(--_k-fg-3)}
3144
+ .knobs-menu-item[data-active]{background:color-mix(in srgb,var(--_k-accent) 14%,transparent)}
3145
+ .knobs-menu-item[aria-disabled]{opacity:var(--k-disabled-opacity);color:var(--_k-fg-2)}
3146
+ .knobs-menu-item kbd{font:var(--_k-text-cap)/1 var(--_k-mono);font-variant-numeric:tabular-nums;color:var(--_k-fg-3);letter-spacing:0}
3147
+ .knobs-menu-item[data-separated]{margin-top:calc(var(--_k-unit) * 2 + 1px)}
3148
+ .knobs-menu-item[data-separated]::before{content:"";position:absolute;left:8px;right:8px;top:calc(var(--_k-unit) * -1 - 1px);height:1px;transform:scaleY(.5);background:var(--_k-border)}
1565
3149
 
1566
3150
  /* Status & Transfer Textarea */
1567
- .knobs-panel .knobs-status{margin:6px 0 0;padding:0 var(--k-inset);color:var(--k-label);font-size:var(--k-text-meta);overflow-wrap:anywhere}
3151
+ .knobs-panel .knobs-status{margin:6px 0 0;padding:0 var(--_k-inset);color:var(--_k-fg-2);font-size:var(--_k-text-meta);overflow-wrap:anywhere}
1568
3152
 
1569
- .knobs-panel textarea{width:100%;min-height:84px;margin-top:6px;padding:6px var(--k-inset);resize:vertical;font:var(--k-text-meta)/1.4 var(--k-mono)}
1570
- .knobs-panel .knobs-apply-btn{width:100%;height:26px;margin-top:var(--k-gap);font-size:var(--k-text-control);font-weight:500;color:var(--k-text);background:var(--k-surface-hi);cursor:pointer}
3153
+ .knobs-panel textarea{width:100%;min-height:84px;margin-top:6px;padding:6px var(--_k-inset);resize:vertical;font:var(--_k-text-meta)/1.4 var(--_k-mono)}
3154
+ .knobs-panel .knobs-apply-btn{width:100%;height:26px;margin-top:var(--_k-gap);font-size:var(--_k-text-control);font-weight:500;color:var(--_k-fg);background:var(--_k-fill-selected);cursor:pointer}
1571
3155
 
1572
3156
  /* WebGPU Overlay Active Mirror State */
1573
3157
  .knobs-panel[data-gpu-active="true"]{background:transparent!important;border-color:transparent!important;box-shadow:none!important;-webkit-backdrop-filter:none!important;backdrop-filter:none!important}
@@ -1606,26 +3190,26 @@ ${POINTER_ROW} .knobs-slider.knobs-modified:not(:hover,.knobs-active) .knobs-val
1606
3190
  /* Page: sections of cards in balanced columns, under a sticky glass header. The page scrolls the
1607
3191
  window, so nothing here may become a scroll container or a containing block for the fixed
1608
3192
  popover and status. Custom cards (.knobs-live) are drawn by the DOM in both renderers. */
1609
- .knobs-panel.knobs-page{width:auto;max-width:none;min-height:100dvh;padding:0 0 calc(var(--k-unit) * 16);border:0;border-radius:0;box-shadow:none;overflow:visible;background:var(--k-page);-webkit-backdrop-filter:none;backdrop-filter:none;
1610
- --k-page-pad:calc(var(--k-unit) * 8);--k-page-gap:calc(var(--k-unit) * 4)}
1611
- .knobs-panel.knobs-page[data-gpu-active="true"]{background:var(--k-page)!important}
1612
- .knobs-panel.knobs-page>header{position:sticky;top:0;z-index:3;display:grid;grid-template-columns:minmax(0,1fr) auto minmax(max-content,1fr);align-items:center;gap:var(--k-page-gap);min-height:calc(var(--k-row) + var(--k-unit) * 6);padding:calc(var(--k-unit) * 2.5) var(--k-page-pad);
1613
- background:color-mix(in srgb,var(--k-page) 84%,transparent);-webkit-backdrop-filter:blur(24px) saturate(1.6);backdrop-filter:blur(24px) saturate(1.6);border-bottom:1px solid transparent;transition:border-color .2s}
1614
- .knobs-panel.knobs-page>header[data-scrolled]{border-bottom-color:var(--k-line)}
1615
- .knobs-panel.knobs-page>header strong{font-size:calc(var(--k-font-size) + 3px);letter-spacing:-.015em;padding-left:calc(var(--k-pad) + var(--k-inset) + 1px)}
3193
+ .knobs-panel.knobs-page{width:auto;max-width:none;min-height:100dvh;padding:0 0 calc(var(--_k-unit) * 16);border:0;border-radius:0;box-shadow:none;overflow:visible;background:var(--_k-bg-page);-webkit-backdrop-filter:none;backdrop-filter:none;
3194
+ --k-page-pad:calc(var(--_k-unit) * 8);--k-page-gap:calc(var(--_k-unit) * 4)}
3195
+ .knobs-panel.knobs-page[data-gpu-active="true"]{background:var(--_k-bg-page)!important}
3196
+ .knobs-panel.knobs-page>header{position:sticky;top:0;z-index:3;display:grid;grid-template-columns:minmax(0,1fr) auto minmax(max-content,1fr);align-items:center;gap:var(--k-page-gap);min-height:calc(var(--_k-row) + var(--_k-unit) * 6);padding:calc(var(--_k-unit) * 2.5) var(--k-page-pad);
3197
+ background:color-mix(in srgb,var(--_k-bg-page) 84%,transparent);-webkit-backdrop-filter:blur(24px) saturate(1.6);backdrop-filter:blur(24px) saturate(1.6);border-bottom:1px solid transparent;transition:border-color .2s}
3198
+ .knobs-panel.knobs-page>header[data-scrolled]{border-bottom-color:var(--_k-border)}
3199
+ .knobs-panel.knobs-page>header strong{font-size:calc(var(--_k-font-size) + 3px);letter-spacing:-.015em;padding-left:calc(var(--_k-pad) + var(--_k-inset) + 1px)}
1616
3200
  .knobs-page>header .knobs-presets{margin:0;min-width:0;max-width:min(640px,46vw)}
1617
3201
  .knobs-page>header .knobs-presets-track{display:flex;flex-wrap:wrap}
1618
3202
  .knobs-page>header .knobs-preset-chip{flex:0 0 var(--k-preset-min,58px)}
1619
3203
  .knobs-page-tools{display:flex;align-items:center;justify-content:flex-end;min-width:0}
1620
- .knobs-page-tools .knobs-head-actions{margin-right:calc((var(--k-icon-size) - var(--k-icon-btn)) / 2 + var(--k-pad) + var(--k-inset) - var(--k-unit))}
1621
- .knobs-panel.knobs-page>header[data-narrow]{grid-template-columns:minmax(0,1fr) auto;row-gap:calc(var(--k-unit) * 2)}
3204
+ .knobs-page-tools .knobs-head-actions{margin-right:calc((var(--k-icon-size) - var(--k-icon-btn)) / 2 + var(--_k-pad) + var(--_k-inset) - var(--_k-unit))}
3205
+ .knobs-panel.knobs-page>header[data-narrow]{grid-template-columns:minmax(0,1fr) auto;row-gap:calc(var(--_k-unit) * 2)}
1622
3206
  .knobs-panel.knobs-page>header[data-narrow]>strong{grid-area:1/1}
1623
3207
  .knobs-panel.knobs-page>header[data-narrow] .knobs-page-tools{grid-area:1/2}
1624
3208
  .knobs-panel.knobs-page>header[data-narrow] .knobs-presets{grid-area:2/1/3/3;max-width:none}
1625
3209
  .knobs-page>header[data-narrow] .knobs-preset-chip{flex:1 0 var(--k-preset-min,58px)}
1626
3210
  @media(max-width:640px){
1627
- .knobs-panel.knobs-page{--k-page-pad:calc(var(--k-unit) * 4)}
1628
- .knobs-panel.knobs-page>header{grid-template-columns:minmax(0,1fr) auto;row-gap:calc(var(--k-unit) * 2)}
3211
+ .knobs-panel.knobs-page{--k-page-pad:calc(var(--_k-unit) * 4)}
3212
+ .knobs-panel.knobs-page>header{grid-template-columns:minmax(0,1fr) auto;row-gap:calc(var(--_k-unit) * 2)}
1629
3213
  .knobs-panel.knobs-page>header>strong{grid-area:1/1}
1630
3214
  .knobs-panel.knobs-page>header .knobs-page-tools{grid-area:1/2}
1631
3215
  .knobs-panel.knobs-page>header .knobs-presets{grid-area:2/1/3/3;max-width:none}
@@ -1633,27 +3217,27 @@ ${POINTER_ROW} .knobs-slider.knobs-modified:not(:hover,.knobs-active) .knobs-val
1633
3217
  }
1634
3218
  /* The jump strip (nav: true): a chip per section along the header's foot, the one in view
1635
3219
  underlined; it scrolls sideways when the chips don't fit. */
1636
- .knobs-page>header>.knobs-nav{grid-column:1/-1;margin:0 calc(var(--k-page-pad) * -1) calc(var(--k-unit) * -2.5);padding:0 calc(var(--k-page-pad) + var(--k-pad) + var(--k-inset) + 1px);gap:calc(var(--k-unit) * 5);overflow-x:auto;overflow-y:hidden;scrollbar-width:none;overscroll-behavior-x:contain}
3220
+ .knobs-page>header>.knobs-nav{grid-column:1/-1;margin:0 calc(var(--k-page-pad) * -1) calc(var(--_k-unit) * -2.5);padding:0 calc(var(--k-page-pad) + var(--_k-pad) + var(--_k-inset) + 1px);gap:calc(var(--_k-unit) * 5);overflow-x:auto;overflow-y:hidden;scrollbar-width:none;overscroll-behavior-x:contain}
1637
3221
  .knobs-page>header>.knobs-nav::-webkit-scrollbar{display:none}
1638
3222
  .knobs-page>header>.knobs-nav::after{display:none}
1639
- .knobs-panel.knobs-page>header>.knobs-nav .knobs-tab{display:inline-flex;align-items:center;width:auto;height:calc(var(--k-row) + var(--k-unit));padding:0;border-radius:0;font-size:var(--k-text-control);line-height:1.25;color:var(--k-label);background:transparent}
1640
- .knobs-panel.knobs-page>header>.knobs-nav .knobs-tab:is(:hover,:focus-visible,[aria-selected="true"]){color:var(--k-text);background:transparent}
1641
- .knobs-tab-count{margin-left:5px;font-size:var(--k-text-meta);font-weight:500;font-variant-numeric:tabular-nums;color:var(--k-modified)}
1642
- .knobs-panel.knobs-page .knobs-page-tools .knobs-custom-actions{display:flex;gap:var(--k-tray-pad);margin:0 calc(var(--k-unit) * 2) 0 0}
1643
- .knobs-panel.knobs-page .knobs-page-tools .knobs-custom-actions button{height:var(--k-icon-btn);min-height:0;padding:0 8px;background:transparent;border-radius:var(--k-round)}
1644
- .knobs-panel .knobs-filter{width:0;height:var(--kc-control-h);padding:0;margin:0;opacity:0;pointer-events:none;background:var(--k-seg-bg);border-radius:var(--k-radius-md);font-size:var(--k-text-control);color:var(--k-text);-webkit-appearance:none;appearance:none;
3223
+ .knobs-panel.knobs-page>header>.knobs-nav .knobs-tab{display:inline-flex;align-items:center;width:auto;height:calc(var(--_k-row) + var(--_k-unit));padding:0;border-radius:0;font-size:var(--_k-text-control);line-height:1.25;color:var(--_k-fg-2);background:transparent}
3224
+ .knobs-panel.knobs-page>header>.knobs-nav .knobs-tab:is(:hover,:focus-visible,[aria-selected="true"]){color:var(--_k-fg);background:transparent}
3225
+ .knobs-tab-count{margin-left:5px;font-size:var(--_k-text-meta);font-weight:500;font-variant-numeric:tabular-nums;color:var(--_k-modified)}
3226
+ .knobs-panel.knobs-page .knobs-page-tools .knobs-custom-actions{display:flex;gap:var(--_k-tray-pad);margin:0 calc(var(--_k-unit) * 2) 0 0}
3227
+ .knobs-panel.knobs-page .knobs-page-tools .knobs-custom-actions button{height:var(--k-icon-btn);min-height:0;padding:0 8px;background:transparent;border-radius:var(--_k-round)}
3228
+ .knobs-panel .knobs-filter{width:0;height:var(--_k-control-h);padding:0;margin:0;opacity:0;pointer-events:none;background:var(--_k-segmented-track);border-radius:var(--_k-radius-md);font-size:var(--_k-text-control);color:var(--_k-fg);-webkit-appearance:none;appearance:none;
1645
3229
  transition:width ${LEAD_T},padding ${LEAD_T},margin ${LEAD_T},opacity .18s}
1646
3230
  .knobs-panel .knobs-filter::-webkit-search-cancel-button{display:none}
1647
- .knobs-panel .knobs-filter::placeholder{color:var(--k-dim)}
1648
- .knobs-panel .knobs-filter[data-open]{width:min(200px,22vw);padding:0 10px;margin-right:calc(var(--k-unit) * 2);opacity:1;pointer-events:auto}
1649
- .knobs-panel.knobs-page>.knobs-popover{position:fixed;z-index:2147480003;top:calc(var(--k-head-h,56px) + var(--k-unit) * 2);right:var(--k-page-pad);width:min(360px,calc(100vw - 32px));max-height:calc(100dvh - var(--k-head-h,56px) - 32px);overflow:auto;margin:0;padding:var(--k-pad) var(--k-inset);
1650
- background:color-mix(in srgb,var(--k-bg) 94%,transparent);border-radius:var(--k-panel-radius);box-shadow:var(--k-shadow),inset 0 1px 0 var(--k-rim);-webkit-backdrop-filter:blur(24px) saturate(1.6);backdrop-filter:blur(24px) saturate(1.6)}
1651
- .knobs-panel.knobs-page>.knobs-status{position:fixed;z-index:2147480003;left:50%;bottom:calc(var(--k-unit) * 6);translate:-50% 0;max-width:min(480px,80vw);margin:0;padding:calc(var(--k-unit) * 2) calc(var(--k-unit) * 3.5);
1652
- background:var(--k-bg);border:1px solid var(--k-line);border-radius:var(--k-round);box-shadow:var(--k-shadow);color:var(--k-text)}
3231
+ .knobs-panel .knobs-filter::placeholder{color:var(--_k-fg-3)}
3232
+ .knobs-panel .knobs-filter[data-open]{width:min(200px,22vw);padding:0 10px;margin-right:calc(var(--_k-unit) * 2);opacity:1;pointer-events:auto}
3233
+ .knobs-panel.knobs-page>.knobs-popover{position:fixed;z-index:2147480003;top:calc(var(--k-head-h,56px) + var(--_k-unit) * 2);right:var(--k-page-pad);width:min(360px,calc(100vw - 32px));max-height:calc(100dvh - var(--k-head-h,56px) - 32px);overflow:auto;margin:0;padding:var(--_k-pad) var(--_k-inset);
3234
+ background:color-mix(in srgb,var(--_k-bg) 94%,transparent);border-radius:var(--_k-radius-panel);box-shadow:var(--_k-shadow-overlay),inset 0 1px 0 var(--_k-rim);-webkit-backdrop-filter:blur(24px) saturate(1.6);backdrop-filter:blur(24px) saturate(1.6)}
3235
+ .knobs-panel.knobs-page>.knobs-status{position:fixed;z-index:2147480003;left:50%;bottom:calc(var(--_k-unit) * 6);translate:-50% 0;max-width:min(480px,80vw);margin:0;padding:calc(var(--_k-unit) * 2) calc(var(--_k-unit) * 3.5);
3236
+ background:var(--_k-bg);border:1px solid var(--_k-border);border-radius:var(--_k-round);box-shadow:var(--_k-shadow-overlay);color:var(--_k-fg)}
1653
3237
  .knobs-sections{padding:0 var(--k-page-pad);overflow-x:clip;overflow-anchor:none}
1654
- .knobs-columns{display:grid;grid-template-columns:repeat(var(--k-cols,1),minmax(0,1fr));gap:var(--k-page-gap);align-items:start;padding-top:calc(var(--k-unit) * 3)}
3238
+ .knobs-columns{display:grid;grid-template-columns:repeat(var(--k-cols,1),minmax(0,1fr));gap:var(--k-page-gap);align-items:start;padding-top:calc(var(--_k-unit) * 3)}
1655
3239
  .knobs-column{display:flex;flex-direction:column;gap:var(--k-page-gap);min-width:0}
1656
- .knobs-section-head{margin:0 0 calc(var(--k-page-gap) * -.25);padding:0 calc(var(--k-pad) + var(--k-inset) + 1px);font:var(--k-title-weight) calc(var(--k-font-size) + 3px)/1.25 var(--k-font);letter-spacing:-.015em;color:var(--k-text);white-space:nowrap;
3240
+ .knobs-section-head{margin:0 0 calc(var(--k-page-gap) * -.25);padding:0 calc(var(--_k-pad) + var(--_k-inset) + 1px);font:var(--_k-weight-title) calc(var(--_k-font-size) + 3px)/1.25 var(--_k-font);letter-spacing:-.015em;color:var(--_k-fg);white-space:nowrap;
1657
3241
  display:grid;grid-template-columns:minmax(0,max-content) minmax(0,1fr) auto;align-items:center;column-gap:8px;isolation:isolate}
1658
3242
  .knobs-column>:not([hidden],[data-away])~.knobs-section-head{margin-top:calc(var(--k-page-gap) * .75)}
1659
3243
  .knobs-section-name{grid-area:1/1;min-width:0;overflow:hidden;text-overflow:ellipsis}
@@ -1662,35 +3246,35 @@ ${POINTER_ROW} .knobs-slider.knobs-modified:not(:hover,.knobs-active) .knobs-val
1662
3246
  .knobs-tile[data-away]{display:none}
1663
3247
  .knobs-section-head[data-foldable]{cursor:pointer;user-select:none}
1664
3248
  .knobs-section-head[data-folded]{margin-bottom:0}
1665
- .knobs-section-head[data-foldable]::before{content:"";position:absolute;z-index:-1;inset:-4px 0;border-radius:var(--k-radius-md);background:var(--k-surface);opacity:0;transition:opacity var(--k-hover-t)}
3249
+ .knobs-section-head[data-foldable]::before{content:"";position:absolute;z-index:-1;inset:-4px 0;border-radius:var(--_k-radius-md);background:var(--_k-fill);opacity:0;transition:opacity var(--k-hover-t)}
1666
3250
  .knobs-section-head[data-foldable]:focus-visible{outline:none}
1667
3251
  .knobs-section-head[data-foldable]:focus-visible::before{opacity:1}
1668
3252
  .knobs-section-head>.knobs-caret{grid-area:1/3;margin:0 calc((var(--k-icon-sm) - 20px) / 2 + 5px) 0 0;opacity:0;transition:transform ${LEAD_T},opacity .15s,color .15s}
1669
3253
  .knobs-section-head:is(:hover,:focus-visible,[data-folded])>.knobs-caret{opacity:1}
1670
- .knobs-section-head:hover>.knobs-caret{color:var(--k-label)}
3254
+ .knobs-section-head:hover>.knobs-caret{color:var(--_k-fg-2)}
1671
3255
  .knobs-section-head[aria-expanded="true"]>.knobs-caret{transform:rotate(90deg)}
1672
- .knobs-section-summary{display:none;grid-area:1/2;justify-self:end;min-width:0;overflow:hidden;text-overflow:ellipsis;font:500 var(--k-text-control)/1.25 var(--k-font);letter-spacing:0;color:var(--k-dim);font-variant-numeric:tabular-nums}
3256
+ .knobs-section-summary{display:none;grid-area:1/2;justify-self:end;min-width:0;overflow:hidden;text-overflow:ellipsis;font:500 var(--_k-text-control)/1.25 var(--_k-font);letter-spacing:0;color:var(--_k-fg-3);font-variant-numeric:tabular-nums}
1673
3257
  .knobs-section-head[data-folded]>.knobs-section-summary{display:block;animation:knobs-fade .2s var(--k-ease) both}
1674
- .knobs-section-desc,.knobs-group-desc{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font:var(--k-label-weight) var(--k-text-meta)/1.35 var(--k-font);letter-spacing:0;color:var(--k-dim);text-transform:none}
3258
+ .knobs-section-desc,.knobs-group-desc{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font:var(--_k-weight-label) var(--_k-text-meta)/1.35 var(--_k-font);letter-spacing:0;color:var(--_k-fg-3);text-transform:none}
1675
3259
  .knobs-section-desc{grid-area:2/1/3/4;margin-top:1px}
1676
3260
  .knobs-group-desc{padding:0 var(--k-group-inset)}
1677
3261
  .knobs-tile>.knobs-group-desc{margin:calc(2px - var(--k-head-gap)) 0 var(--k-head-gap)}
1678
3262
  .knobs-tile:is([data-foldable],[data-collapsible])>.knobs-group-desc{margin:2px 0 0}
1679
3263
  @keyframes knobs-fade{from{opacity:0}}
1680
- .knobs-tile{position:relative;min-width:0;padding:var(--k-pad);background:var(--k-bg);border:1px solid var(--k-line);border-radius:var(--k-panel-radius);box-shadow:inset 0 1px 0 var(--k-rim)}
3264
+ .knobs-tile{position:relative;min-width:0;padding:var(--_k-pad);background:var(--_k-bg);border:1px solid var(--_k-border);border-radius:var(--_k-radius-panel);box-shadow:inset 0 1px 0 var(--_k-rim)}
1681
3265
  .knobs-tile>.knobs-card{margin:0}
1682
3266
  .knobs-tile[data-foldable]>.knobs-group-head{margin-bottom:0}
1683
3267
  .knobs-tile[data-foldable]>.knobs-card{margin-top:var(--k-head-gap)}
1684
3268
  /* A card's header is compact: as tall as its 20px controls, then a gap and a half before its rows. */
1685
- .knobs-tile>.knobs-group-head{position:relative;margin:0 0 var(--k-head-gap);min-height:20px;color:var(--k-text);font-size:var(--k-text-title);font-weight:var(--k-title-weight);letter-spacing:-.01em;text-transform:none}
1686
- .knobs-panel.knobs-page{--k-head-gap:calc(var(--k-gap) * 1.5)}
3269
+ .knobs-tile>.knobs-group-head{position:relative;margin:0 0 var(--k-head-gap);min-height:20px;color:var(--_k-fg);font-size:var(--_k-text-title);font-weight:var(--_k-weight-title);letter-spacing:-.01em;text-transform:none}
3270
+ .knobs-panel.knobs-page{--k-head-gap:calc(var(--_k-gap) * 1.5)}
1687
3271
  /* The title wins the header's room: what's on the right (presets, a summary) gives way first. */
1688
3272
  .knobs-tile>.knobs-group-head>.knobs-group-title{flex:1 1 auto}
1689
3273
  .knobs-tile>.knobs-group-head>span:last-child{flex:0 1000 auto;min-width:0}
1690
3274
  .knobs-tile>.knobs-group-head :is(.knobs-group-reset,.knobs-group-die){flex:none}
1691
3275
  /* A folded card's header trades its controls (presets, reset, die) for a summary of the card. */
1692
- .knobs-group-ctl{display:flex;align-items:center;gap:var(--k-tray-pad);min-width:0}
1693
- .knobs-group-summary{display:none;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--k-dim);font-size:var(--k-text-control);font-weight:500;letter-spacing:0;font-variant-numeric:tabular-nums}
3276
+ .knobs-group-ctl{display:flex;align-items:center;gap:var(--_k-tray-pad);min-width:0}
3277
+ .knobs-group-summary{display:none;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--_k-fg-3);font-size:var(--_k-text-control);font-weight:500;letter-spacing:0;font-variant-numeric:tabular-nums}
1694
3278
  .knobs-tile[data-folded]>.knobs-group-head .knobs-group-summary:not(:empty){display:block}
1695
3279
  .knobs-tile[data-folded]>.knobs-group-head .knobs-group-ctl{display:none}
1696
3280
  .knobs-tile[data-fold-motion]>.knobs-group-head :is(.knobs-group-summary,.knobs-group-ctl){animation:knobs-fade .2s var(--k-ease) both}
@@ -1698,25 +3282,25 @@ ${POINTER_ROW} .knobs-slider.knobs-modified:not(:hover,.knobs-active) .knobs-val
1698
3282
  full), and what's highlighted on its own gets a dot in the gutter by its title. The veil and
1699
3283
  dot are written each frame on the panel spring (see page.ts). */
1700
3284
  .knobs-panel.knobs-page{--k-page-dim:.4}
1701
- .knobs-veil{position:absolute;inset:-1px;z-index:1;border-radius:inherit;background:var(--k-page);pointer-events:none}
1702
- .knobs-mark{position:absolute;top:50%;width:6px;height:6px;margin:-3px 0 0 -3px;border-radius:50%;background:var(--k-accent);pointer-events:none}
1703
- .knobs-tile>.knobs-mark{z-index:2;top:calc(var(--k-pad) + 10px);left:calc((var(--k-pad) + var(--k-inset) + 1px) / 2 - 1px)}
3285
+ .knobs-veil{position:absolute;inset:-1px;z-index:1;border-radius:inherit;background:var(--_k-bg-page);pointer-events:none}
3286
+ .knobs-mark{position:absolute;top:50%;width:6px;height:6px;margin:-3px 0 0 -3px;border-radius:50%;background:var(--_k-accent);pointer-events:none}
3287
+ .knobs-tile>.knobs-mark{z-index:2;top:calc(var(--_k-pad) + 10px);left:calc((var(--_k-pad) + var(--_k-inset) + 1px) / 2 - 1px)}
1704
3288
  .knobs-section-head{position:relative}
1705
- .knobs-section-head>.knobs-mark{left:calc((var(--k-pad) + var(--k-inset) + 1px) / 2)}
3289
+ .knobs-section-head>.knobs-mark{left:calc((var(--_k-pad) + var(--_k-inset) + 1px) / 2)}
1706
3290
  .knobs-group-title{display:grid;flex:1;min-width:0}
1707
3291
  .knobs-group-title>*{grid-area:1/1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;transition:opacity .15s}
1708
3292
  .knobs-peek{opacity:0;pointer-events:none}
1709
3293
  .knobs-group-head[data-peek] .knobs-group-label{opacity:0}
1710
3294
  .knobs-group-head[data-peek] .knobs-peek{opacity:1}
1711
- .knobs-group-head .knobs-chips.knobs-seg{flex:none;height:20px;max-width:none;gap:0;margin-right:var(--k-unit)}
1712
- .knobs-group-head .knobs-chips button{width:18px;height:100%;padding:0;font-size:var(--k-text-meta);font-weight:500;font-variant-numeric:tabular-nums;border-radius:var(--k-radius-sm);background:transparent}
1713
- .knobs-group-head .knobs-chips button[aria-checked="true"]{color:var(--k-text)}
3295
+ .knobs-group-head .knobs-chips.knobs-seg{flex:none;height:20px;max-width:none;gap:0;margin-right:var(--_k-unit)}
3296
+ .knobs-group-head .knobs-chips button{width:18px;height:100%;padding:0;font-size:var(--_k-text-meta);font-weight:500;font-variant-numeric:tabular-nums;border-radius:var(--_k-radius-sm);background:transparent}
3297
+ .knobs-group-head .knobs-chips button[aria-checked="true"]{color:var(--_k-fg)}
1714
3298
  /* Named presets: their names as segments beside the title, or a compact menu of them. */
1715
- .knobs-group-presets{display:flex;align-items:center;flex:0 1 auto;min-width:0;margin-right:var(--k-unit)}
1716
- .knobs-group-presets .knobs-seg{flex:none;height:20px;max-width:none;padding:var(--k-tray-pad)}
1717
- .knobs-group-presets .knobs-seg button{height:100%;padding:0 6px;font-size:var(--k-text-meta);font-weight:500;background:transparent}
1718
- .knobs-panel .knobs-group-presets .knobs-select{height:20px;max-width:11em;gap:3px;padding:0 3px 0 7px;font-size:var(--k-text-meta);font-weight:500;letter-spacing:0;text-transform:none}
1719
- .knobs-group-presets .knobs-select[data-none]{color:var(--k-dim)}
3299
+ .knobs-group-presets{display:flex;align-items:center;flex:0 1 auto;min-width:0;margin-right:var(--_k-unit)}
3300
+ .knobs-group-presets .knobs-seg{flex:none;height:20px;max-width:none;padding:var(--_k-tray-pad)}
3301
+ .knobs-group-presets .knobs-seg button{height:100%;padding:0 6px;font-size:var(--_k-text-meta);font-weight:500;background:transparent}
3302
+ .knobs-panel .knobs-group-presets .knobs-select{height:20px;max-width:11em;gap:3px;padding:0 3px 0 7px;font-size:var(--_k-text-meta);font-weight:500;letter-spacing:0;text-transform:none}
3303
+ .knobs-group-presets .knobs-select[data-none]{color:var(--_k-fg-3)}
1720
3304
  .knobs-group-presets .knobs-select .knobs-icon{width:calc(var(--k-icon-sm) - 3px);height:calc(var(--k-icon-sm) - 3px)}
1721
3305
  .knobs-tile-body{display:flex;flex-direction:column}
1722
3306
  .knobs-tile-body>.knobs-card{margin:0}
@@ -1728,35 +3312,25 @@ ${POINTER_ROW} .knobs-slider.knobs-modified:not(:hover,.knobs-active) .knobs-val
1728
3312
  .knobs-card>.knobs-item:focus-visible{outline:none}
1729
3313
  .knobs-card>.knobs-item:focus-visible::after{opacity:1}
1730
3314
  /* A collapsible custom card: its header toggles it, with a caret and, while folded, a summary. */
1731
- .knobs-live[data-collapsible]>.knobs-group-head{margin-bottom:0;cursor:pointer;border-radius:var(--k-radius-sm);transition:background var(--k-hover-t)}
1732
- .knobs-live[data-collapsible]>.knobs-group-head:focus-visible{background:var(--k-surface)}
3315
+ .knobs-live[data-collapsible]>.knobs-group-head{margin-bottom:0;cursor:pointer;border-radius:var(--_k-radius-sm);transition:background var(--k-hover-t)}
3316
+ .knobs-live[data-collapsible]>.knobs-group-head:focus-visible{background:var(--_k-fill)}
1733
3317
  .knobs-live[data-collapsible]>.knobs-tile-body{margin-top:var(--k-head-gap);transition:opacity var(--k-token-t)}
1734
3318
  .knobs-live[data-collapsed]>.knobs-tile-body{opacity:0}
1735
- .knobs-live>.knobs-tile-body[data-folding]{position:absolute;left:var(--k-pad);right:var(--k-pad);margin-top:0}
3319
+ .knobs-live>.knobs-tile-body[data-folding]{position:absolute;left:var(--_k-pad);right:var(--_k-pad);margin-top:0}
1736
3320
  .knobs-card-right{display:flex;align-items:center;gap:6px;min-width:0}
1737
3321
  .knobs-card-side{display:grid;justify-items:end;min-width:0}
1738
3322
  .knobs-card-side>*{grid-area:1/1;min-width:0;max-width:100%;transition:opacity var(--k-token-t)}
1739
- .knobs-card-summary{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--k-dim);font-size:var(--k-text-control);font-weight:500;letter-spacing:0;opacity:0;pointer-events:none}
3323
+ .knobs-card-summary{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--_k-fg-3);font-size:var(--_k-text-control);font-weight:500;letter-spacing:0;opacity:0;pointer-events:none}
1740
3324
  .knobs-live[data-collapsed] .knobs-card-summary{opacity:1;pointer-events:auto}
1741
3325
  .knobs-live[data-collapsed] .knobs-card-summary:not(:empty)~*{opacity:0;pointer-events:none}
1742
3326
  .knobs-card-right>.knobs-caret{margin-right:calc((var(--k-icon-sm) - 20px) / 2 + 5px)}
1743
- .knobs-live>.knobs-group-head:hover .knobs-caret{color:var(--k-label)}
3327
+ .knobs-live>.knobs-group-head:hover .knobs-caret{color:var(--_k-fg-2)}
1744
3328
  .knobs-live>.knobs-group-head[aria-expanded="true"] .knobs-caret{transform:rotate(90deg)}
1745
- .knobs-item-detail{flex:none;color:var(--k-dim);font-size:var(--k-text-control);font-variant-numeric:tabular-nums;white-space:nowrap}
1746
- `;
1747
- function injectPreset(doc, preset) {
1748
- let content = presetCss(preset), existing = doc.querySelector(`style[data-knobs-preset="${preset.name}"]`);
1749
- if (existing) {
1750
- if (existing.textContent !== content)
1751
- existing.textContent = content;
1752
- return;
1753
- }
1754
- let style = doc.createElement("style");
1755
- style.dataset.knobsPreset = preset.name, style.textContent = content, doc.head.append(style);
1756
- }
1757
- var keyboardQuietsHover = (css) => css.replaceAll(":hover", ":hover:where(:not([data-k-quiet]))"), withoutHas = (css) => css.replaceAll(":has(:focus-visible)", "[data-k-fv]").replaceAll(":has(.knobs-track:focus-visible)", '[data-k-fv="track"]').replaceAll(":has(.knobs-active)", "[data-k-active]");
3329
+ .knobs-item-detail{flex:none;color:var(--_k-fg-3);font-size:var(--_k-text-control);font-variant-numeric:tabular-nums;white-space:nowrap}
3330
+ `, keyboardQuietsHover = (css) => css.replaceAll(":hover", ":hover:where(:not([data-k-quiet]))"), withoutHas = (css) => css.replaceAll(":has(:focus-visible)", "[data-k-fv]").replaceAll(":has(.knobs-track:focus-visible)", '[data-k-fv="track"]').replaceAll(":has(.knobs-active)", "[data-k-active]"), panelCss = () => rolling_css_default + defaultsCss + keyboardQuietsHover(withoutHas(aliased(css2)));
1758
3331
  function injectStyles(doc) {
1759
- let content = rolling_css_default + DRIVERS + defaultsCss + keyboardQuietsHover(withoutHas(aliased(css))), existing = doc.querySelector("style[data-knobs-style]");
3332
+ injectTokens(doc);
3333
+ let content = panelCss(), existing = doc.querySelector("style[data-knobs-style]");
1760
3334
  if (existing) {
1761
3335
  if (existing.textContent !== content)
1762
3336
  existing.textContent = content;
@@ -2690,13 +4264,13 @@ function hintTokens(doc, groups) {
2690
4264
  return v;
2691
4265
  }
2692
4266
  return "";
2693
- }, panel = doc.querySelector(".knobs-panel"), piece = groups.find((g) => g.source && !g.source.paint)?.source?.root, pick = (k, fallback) => read(panel, [`--k-${k}`]) || read(piece, [`--ku-${k}`, `--k-${k}`]) || fallback;
4267
+ }, panel = doc.querySelector(".knobs-panel"), piece = groups.find((g) => g.source && !g.source.paint)?.source?.root, pick = (k, fallback) => read(panel, [`--_k-${k}`]) || read(piece, [`--_k-${k}`]) || fallback;
2694
4268
  return {
2695
4269
  "--kh-accent": pick("accent", "#fff"),
2696
4270
  "--kh-bg": pick("bg", "#1c1c1e"),
2697
4271
  "--kh-mono": pick("mono", "ui-monospace,Menlo,monospace"),
2698
- "--kh-radius": read(panel, ["--k-radius-sm"]) || "4px",
2699
- "--kh-size": read(panel, ["--k-text-cap"]) || "10px",
4272
+ "--kh-radius": read(panel, ["--_k-radius-sm"]) || "4px",
4273
+ "--kh-size": read(panel, ["--_k-text-cap"]) || "10px",
2700
4274
  "--kh-typed": read(panel, ["--k-hint-typed-opacity"]) || ".42",
2701
4275
  "--kh-lift": read(panel, ["--k-lift"]) || "1",
2702
4276
  "--kh-ease": read(panel, ["--k-ease"]) || "cubic-bezier(.2,.8,.2,1)"
@@ -2816,4 +4390,4 @@ function createLayer(doc) {
2816
4390
  };
2817
4391
  }
2818
4392
 
2819
- export { CHECK_POINTS, CHECK_PATH, iconPath, iconSvg, readSession, writeSession, rolling_css_default, presetCss, FILL, LEAD, trailScale, Edges, POP_MS, popScale, settleScale, VelocityTracker, clamp, Roll, rollTarget, numeral, entranceOffset, FLASH_MS, flash, flashOf, offRow, precisionRate, RULER, RULER_NEAR, RULER_FADE, rulerLevels, rulerAlpha, rulerDepth, THIN, THINNEST, thinOf, roundOf, stretchOf, stretchAt, giveRoom, detentScale, detentsOf, roundValues, unwarp, Notches, escapeTo, commandScope, scopeLabel, crumbTrail, escTarget, digitOption, digitHints, createCrumbs, DELAYED, injectPreset, injectStyles, resolveSound, sound, SOUND_PREF, soundPanel, changed, cue, createHintController, pageHints, toggleLayer };
4393
+ export { resolveLook, themeOf, applyLook, panelLook, CHECK_POINTS, CHECK_PATH, iconPath, iconSvg, readSession, writeSession, rolling_css_default, FILL, LEAD, trailScale, Edges, POP_MS, popScale, settleScale, VelocityTracker, clamp, Roll, rollTarget, numeral, entranceOffset, FLASH_MS, flash, flashOf, offRow, precisionRate, RULER, RULER_NEAR, RULER_FADE, rulerLevels, rulerAlpha, rulerDepth, THIN, THINNEST, thinOf, roundOf, stretchOf, stretchAt, giveRoom, detentScale, detentsOf, roundValues, unwarp, Notches, escapeTo, commandScope, scopeLabel, crumbTrail, escTarget, digitOption, digitHints, createCrumbs, TOKENS, knobs, aliased, injectTokens, DELAYED, injectStyles, resolveSound, sound, SOUND_PREF, soundPanel, changed, cue, createHintController, pageHints, toggleLayer };