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

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 (43) hide show
  1. package/README.md +288 -43
  2. package/dist/dev/{chunk-stbcgz1y.js → chunk-1qzffbpa.js} +443 -451
  3. package/dist/dev/{chunk-7xgkerd2.js → chunk-3ygqgy1x.js} +23 -1
  4. package/dist/dev/{chunk-pmkvb9ep.js → chunk-8mabjeyk.js} +1920 -507
  5. package/dist/dev/{chunk-t68smqkc.js → chunk-ayb292zj.js} +13 -11
  6. package/dist/dev/index.js +10 -5
  7. package/dist/index.js +25 -1
  8. package/dist/panel.js +2900 -1320
  9. package/dist/react.js +294 -6
  10. package/dist/solid.js +292 -4
  11. package/dist/themes.js +1509 -7
  12. package/dist/types/core/adapter.d.ts +6 -2
  13. package/dist/types/core/appearance.d.ts +44 -0
  14. package/dist/types/core/glide.d.ts +7 -0
  15. package/dist/types/core/motion.d.ts +66 -0
  16. package/dist/types/core/root.d.ts +13 -0
  17. package/dist/types/core/store.d.ts +18 -5
  18. package/dist/types/core/theme.d.ts +10 -3
  19. package/dist/types/index.d.ts +2 -1
  20. package/dist/types/panel/gpu/color.d.ts +6 -0
  21. package/dist/types/panel/motion.d.ts +1 -1
  22. package/dist/types/panel/styles.d.ts +2 -3
  23. package/dist/types/themes/define.d.ts +104 -0
  24. package/dist/types/themes/index.d.ts +11 -0
  25. package/dist/types/themes/knobs.d.ts +5 -0
  26. package/dist/types/themes/void.d.ts +8 -0
  27. package/dist/types/tokens/color.d.ts +42 -0
  28. package/dist/types/tokens/css.d.ts +13 -0
  29. package/dist/types/tokens/evaluate.d.ts +8 -0
  30. package/dist/types/tokens/index.d.ts +4 -0
  31. package/dist/types/tokens/schema.d.ts +1100 -0
  32. package/dist/types/ui/bento-css.d.ts +1 -1
  33. package/dist/types/ui/compare-css.d.ts +1 -1
  34. package/dist/types/ui/index.d.ts +1 -1
  35. package/dist/types/ui/look.d.ts +18 -13
  36. package/dist/types/ui/overlay-css.d.ts +1 -1
  37. package/dist/types/ui/readout-css.d.ts +1 -1
  38. package/dist/types/ui/readout-model.d.ts +5 -1
  39. package/dist/types/ui/rgba.d.ts +11 -0
  40. package/dist/ui-react.js +2320 -676
  41. package/dist/ui-solid.js +2320 -676
  42. package/dist/ui.js +2552 -906
  43. package/package.json +1 -1
package/dist/ui-react.js CHANGED
@@ -93,6 +93,30 @@ function springCss(value) {
93
93
  return { easing, duration: ms };
94
94
  }
95
95
 
96
+ // src/core/motion.ts
97
+ var SPRINGS, FADE, CLOSE, MOTION, reducedMotion = (win) => win?.matchMedia?.("(prefers-reduced-motion: reduce)").matches ?? false, springLinear = (spring) => {
98
+ const { omega, zeta } = springMotion(spring);
99
+ return springEasing(omega, zeta);
100
+ }, names, linear, SPRING_TOKEN, DEFAULT_LINEAR, motionCss;
101
+ var init_motion = __esm(() => {
102
+ SPRINGS = {
103
+ instant: { duration: 0.1, bounce: 0 },
104
+ snappy: { duration: 0.25, bounce: 0 },
105
+ default: { duration: 0.3, bounce: 0 },
106
+ calm: { duration: 0.4, bounce: 0 },
107
+ smooth: { duration: 0.45, bounce: 0 }
108
+ };
109
+ FADE = { duration: 0.16, bounce: 0 };
110
+ CLOSE = { duration: 0.18, bounce: 0 };
111
+ MOTION = Object.fromEntries(Object.entries(SPRINGS).map(([name, spring]) => [name, springMotion(spring)]));
112
+ names = Object.keys(SPRINGS);
113
+ linear = Object.fromEntries(names.map((n) => [n, springLinear(SPRINGS[n])]));
114
+ SPRING_TOKEN = `${SPRINGS.default.duration} ${SPRINGS.default.bounce}`;
115
+ DEFAULT_LINEAR = linear.default;
116
+ motionCss = `:where(:root,:host){${names.map((n) => `--_k-motion-${n}:${linear[n].easing};--_k-motion-${n}-ms:${linear[n].ms}`).join(";")}}
117
+ @media(prefers-reduced-motion:reduce){:where(:root,:host){${names.map((n) => `--_k-motion-${n}-ms:0`).join(";")}}}`;
118
+ });
119
+
96
120
  // src/panel/rolling-css.ts
97
121
  var rolling_css_default = `.rn-root {
98
122
  display: inline-block;
@@ -196,11 +220,18 @@ var rolling_css_default = `.rn-root {
196
220
  function presetCss(preset) {
197
221
  if (!/^[\w-]+$/.test(preset.name))
198
222
  throw new Error(`Invalid preset name: ${preset.name}`);
199
- const at = `.knobs-panel[data-preset="${preset.name}"]`;
200
- const 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)}}}` : "";
201
- return `${at}{${block(preset.dark)}}${light}${(preset.css ?? "").replaceAll("&", at)}`;
223
+ const at = `.knobs-root[data-preset="${preset.name}"]`;
224
+ const light = preset.light ?? {};
225
+ const decls = Object.entries(preset.dark).map(([k, dark]) => {
226
+ const l = light[k];
227
+ return l === undefined || String(l) === String(dark) ? `${property(k)}:${dark}` : `${property(k)}:light-dark(${l},${dark})`;
228
+ });
229
+ for (const [k, l] of Object.entries(light))
230
+ if (!(k in preset.dark) && k !== "color-scheme")
231
+ decls.push(`${property(k)}:${l}`);
232
+ return `${at}{${decls.join(";")}}${(preset.css ?? "").replaceAll("&", at)}`;
202
233
  }
203
- var block = (tokens) => Object.entries(tokens).map(([k, v]) => `${k.startsWith("--") || k === "color-scheme" ? k : `--k-${k}`}:${v}`).join(";"), glide, problemsPreset;
234
+ var property = (k) => k.startsWith("--") ? k : `--k-${k}`, glide, problemsPreset;
204
235
  var init_theme = __esm(() => {
205
236
  glide = /* @__PURE__ */ springCss({ duration: 0.185, bounce: 0.14 });
206
237
  problemsPreset = {
@@ -280,44 +311,166 @@ var init_theme = __esm(() => {
280
311
  "toggle-thumb": "#fff",
281
312
  rim: "transparent",
282
313
  "group-color": "rgba(60,60,67,.66)",
283
- "group-divider": "rgba(0,0,0,.07)",
284
- "color-scheme": "light"
314
+ "group-divider": "rgba(0,0,0,.07)"
285
315
  }
286
316
  };
287
317
  });
288
318
 
319
+ // src/core/appearance.ts
320
+ function resolveLook(options = {}, base) {
321
+ const t = options.theme;
322
+ const mode = typeof t === "string" ? MODES[t] : undefined;
323
+ const theme = typeof t === "object" ? t : base?.theme;
324
+ const preset = options.preset ?? base?.preset;
325
+ return {
326
+ ...theme ? { theme } : {},
327
+ appearance: options.appearance ?? mode ?? base?.appearance ?? "inherit",
328
+ ...preset ? { preset } : {}
329
+ };
330
+ }
331
+ function themeOf(el) {
332
+ const name = el.closest("[data-knobs-theme]")?.dataset.knobsTheme;
333
+ return name ? themes.get(name) : undefined;
334
+ }
335
+ function upsertStyle(doc, key, value, content) {
336
+ const existing = doc.querySelector(`style[${key}="${value}"]`);
337
+ if (existing) {
338
+ if (existing.textContent !== content)
339
+ existing.textContent = content;
340
+ return;
341
+ }
342
+ const style = doc.createElement("style");
343
+ style.setAttribute(key, value);
344
+ style.textContent = content;
345
+ doc.head.append(style);
346
+ }
347
+ function injectTheme(doc, theme) {
348
+ themes.set(theme.name, theme);
349
+ upsertStyle(doc, "data-knobs-theme-css", theme.name, theme.css({ selector: themeSelector(theme.name) }));
350
+ }
351
+ function injectPreset(doc, preset) {
352
+ presets.set(preset.name, preset);
353
+ upsertStyle(doc, "data-knobs-preset", preset.name, presetCss(preset));
354
+ }
355
+ function applyLook(el, look) {
356
+ const doc = el.ownerDocument;
357
+ if (look.theme)
358
+ injectTheme(doc, look.theme);
359
+ if (look.preset)
360
+ injectPreset(doc, look.preset);
361
+ setAttr(el, "data-knobs-theme", look.theme?.name);
362
+ setAttr(el, "data-preset", look.preset?.name);
363
+ setAttr(el, "data-appearance", look.appearance === "inherit" ? undefined : look.appearance);
364
+ if (look.appearance === "inherit")
365
+ followPage(el);
366
+ else
367
+ clearInherited(el);
368
+ }
369
+ function resolveInherited(el) {
370
+ const parent = el.parentElement;
371
+ const win = el.ownerDocument.defaultView;
372
+ if (!parent || !win || el.hasAttribute("data-appearance"))
373
+ return;
374
+ if (parent.closest(".knobs-root"))
375
+ return clearInherited(el);
376
+ const scheme = win.getComputedStyle(parent).colorScheme.trim();
377
+ const dark = /\bdark\b/.test(scheme);
378
+ const light = /\blight\b/.test(scheme);
379
+ if (!dark && !light)
380
+ return clearInherited(el);
381
+ const isLight = dark && light ? win.matchMedia?.("(prefers-color-scheme: light)").matches ?? false : light;
382
+ el.style.setProperty("color-scheme", "inherit");
383
+ el.style.setProperty("--_k-light", isLight ? "1" : "0");
384
+ }
385
+ function followPage(el) {
386
+ const doc = el.ownerDocument;
387
+ const win = doc.defaultView;
388
+ if (!win)
389
+ return;
390
+ const run = () => resolveInherited(el);
391
+ if (el.isConnected)
392
+ run();
393
+ queueMicrotask(run);
394
+ win.requestAnimationFrame?.(run);
395
+ if (watched.has(doc))
396
+ return;
397
+ watched.add(doc);
398
+ const all = () => {
399
+ for (const root of doc.querySelectorAll(".knobs-root:not([data-appearance])"))
400
+ resolveInherited(root);
401
+ };
402
+ const observer = new MutationObserver(all);
403
+ const attributeFilter = ["class", "data-theme", "data-appearance"];
404
+ observer.observe(doc.documentElement, { attributes: true, attributeFilter });
405
+ if (doc.body)
406
+ observer.observe(doc.body, { attributes: true, attributeFilter });
407
+ win.matchMedia?.("(prefers-color-scheme: light)").addEventListener?.("change", all);
408
+ }
409
+ function lookAt(el) {
410
+ const win = el.ownerDocument.defaultView;
411
+ const light = win?.getComputedStyle(el).getPropertyValue("--_k-light").trim() === "1";
412
+ const theme = themeOf(el);
413
+ const name = el.closest("[data-preset]")?.dataset.preset;
414
+ const preset = name ? presets.get(name) : undefined;
415
+ return {
416
+ ...theme ? { theme } : {},
417
+ appearance: light ? "light" : "dark",
418
+ ...preset ? { preset } : {}
419
+ };
420
+ }
421
+ var MODES, themes, themeSelector = (name) => `:where(.knobs-root)[data-knobs-theme="${name}"]`, presets, setAttr = (el, name, value) => {
422
+ if (value === undefined)
423
+ el.removeAttribute(name);
424
+ else if (el.getAttribute(name) !== value)
425
+ el.setAttribute(name, value);
426
+ }, clearInherited = (el) => {
427
+ el.style.removeProperty("color-scheme");
428
+ el.style.removeProperty("--_k-light");
429
+ }, watched;
430
+ var init_appearance = __esm(() => {
431
+ init_theme();
432
+ MODES = {
433
+ dark: "dark",
434
+ light: "light",
435
+ auto: "system"
436
+ };
437
+ themes = new Map;
438
+ presets = new Map;
439
+ watched = new WeakSet;
440
+ });
441
+
289
442
  // src/ui/activity-css.ts
290
443
  var open, activityCss;
291
444
  var init_activity_css = __esm(() => {
292
- open = springEasing(2 * Math.PI / 0.22, 1);
445
+ init_motion();
446
+ open = springLinear(SPRINGS.snappy);
293
447
  activityCss = `
294
448
  :where(.knobs-activity,.knobs-activity *){box-sizing:border-box}
295
- :where(.knobs-activity){color-scheme:dark}
296
449
  .knobs-ui.knobs-activity{position:relative;display:block;height:100%;overflow:auto;overflow-anchor:none;outline:none;scrollbar-width:none;overscroll-behavior:contain;user-select:none;-webkit-user-select:none;
297
- font:var(--ku-font-weight) var(--ku-font-size)/1.35 var(--ku-font);color:var(--ku-text);text-align:left;letter-spacing:normal;-webkit-font-smoothing:antialiased;
298
- --ka-gutter:var(--k-activity-gutter,28px);--ka-row:var(--k-activity-row,var(--ku-row));--ka-row-child:var(--k-activity-row-child,calc(var(--ka-row) - 6px));
299
- --ka-line:var(--k-activity-line,var(--ku-line-hi));--ka-select:var(--k-activity-select,var(--ku-wash-hi));--ka-hover:var(--k-activity-hover,var(--ku-wash));
300
- --ka-you:var(--k-activity-you,light-dark(#007aff,#0a84ff));--ka-agent:var(--k-activity-agent,var(--ku-label));--ka-proposal:var(--k-activity-proposal,var(--ku-text));
301
- --ka-review:var(--k-activity-review,var(--ku-text));--ka-pr:var(--k-activity-pr,light-dark(#8944ab,#bf5af2));--ka-build:var(--k-activity-build,var(--ku-label));
302
- --ka-blocked:var(--k-activity-blocked,var(--ku-warn));--ka-shipped:var(--k-activity-shipped,light-dark(#248a3d,#30d158));--ka-open-ease:${open.easing};--ka-open-ms:${open.ms}ms}
450
+ font:var(--_k-weight) var(--_k-font-size)/1.35 var(--_k-font);color:var(--_k-fg);text-align:left;letter-spacing:normal;-webkit-font-smoothing:antialiased;
451
+ --ka-gutter:var(--k-activity-gutter,28px);--ka-row:var(--k-activity-row,var(--_k-row));--ka-row-child:var(--k-activity-row-child,calc(var(--ka-row) - 6px));
452
+ --ka-line:var(--_k-activity-rail);--ka-select:var(--k-activity-select,var(--_ku-wash-hi));--ka-hover:var(--k-activity-hover,var(--_ku-wash));
453
+ --ka-you:var(--k-activity-you,var(--_k-info));--ka-agent:var(--k-activity-agent,var(--_k-fg-2));--ka-proposal:var(--k-activity-proposal,var(--_k-fg));
454
+ --ka-review:var(--k-activity-review,var(--_k-fg));--ka-pr:var(--k-activity-pr,var(--_k-series-5));--ka-build:var(--k-activity-build,var(--_k-fg-2));
455
+ --ka-blocked:var(--k-activity-blocked,var(--_k-warn));--ka-shipped:var(--k-activity-shipped,var(--_k-ok));--ka-open-ease:${open.easing};--ka-open-ms:${open.ms}ms}
303
456
  .knobs-activity [hidden]{display:none!important}
304
457
  /* Clipped below: the content grows on a spring, so a new last row shows as the rail makes room. */
305
458
  .knobs-activity-space{position:relative;width:100%;overflow-x:visible;overflow-y:clip;pointer-events:none}
306
- .knobs-activity-line{position:absolute;top:0;left:calc(var(--ku-row-x) + var(--ka-gutter) / 2 - 1px);width:2px;height:100%;overflow:visible;pointer-events:none;z-index:1}
459
+ .knobs-activity-line{position:absolute;top:0;left:calc(var(--_ku-row-x) + var(--ka-gutter) / 2 - 1px);width:2px;height:100%;overflow:visible;pointer-events:none;z-index:1}
307
460
  .knobs-activity-line path{fill:none;stroke:var(--ka-line);stroke-width:1px}
308
461
  /* The selection's tint: a wash that glides between rows, shown only once keys move it. It leaves
309
462
  in 100 ms when the pointer is used, and comes back at once. */
310
- .knobs-activity-hl{position:absolute;left:var(--ku-row-x);right:var(--ku-row-x);top:0;height:0;border-radius:var(--ku-row-radius);background:var(--ka-select);opacity:0;
463
+ .knobs-activity-hl{position:absolute;left:var(--_ku-row-x);right:var(--_ku-row-x);top:0;height:0;border-radius:var(--_ku-row-radius);background:var(--ka-select);opacity:0;
311
464
  transition:opacity 100ms ease-out;pointer-events:none;will-change:transform}
312
465
  .knobs-activity[data-keys] .knobs-activity-hl{opacity:1;transition:none}
313
- .knobs-activity-row{position:absolute;left:var(--ku-row-x);right:var(--ku-row-x);top:0;display:flex;align-items:center;height:var(--ka-row);padding-right:calc(var(--ku-inset) - 4px);
314
- color:var(--ku-text);white-space:nowrap;cursor:default;will-change:transform;transform-origin:calc(var(--ka-gutter) / 2) 50%;pointer-events:auto;--ka-tint:var(--ka-agent)}
466
+ .knobs-activity-row{position:absolute;left:var(--_ku-row-x);right:var(--_ku-row-x);top:0;display:flex;align-items:center;height:var(--ka-row);padding-right:calc(var(--_k-inset) - 4px);
467
+ color:var(--_k-fg);white-space:nowrap;cursor:default;will-change:transform;transform-origin:calc(var(--ka-gutter) / 2) 50%;pointer-events:auto;--ka-tint:var(--ka-agent)}
315
468
  .knobs-activity-row[data-leaving]{pointer-events:none}
316
469
  .knobs-activity-row[data-depth="1"]{height:var(--ka-row-child)}
317
470
  .knobs-activity-row>*{position:relative}
318
471
  /* Hover: in at once, out over 100 ms; not while keys drive the selection. */
319
- .knobs-activity-row::before{content:"";position:absolute;inset:0;border-radius:var(--ku-row-radius);background:var(--ka-hover);opacity:0;transition:opacity calc(var(--k-hover-out,100) * 1ms) ease-out;pointer-events:none}
320
- .knobs-activity:not([data-keys]) .knobs-activity-row:not([data-leaving]):hover::before{opacity:1;transition-duration:calc(var(--k-hover-in,0) * 1ms)}
472
+ .knobs-activity-row::before{content:"";position:absolute;inset:0;border-radius:var(--_ku-row-radius);background:var(--ka-hover);opacity:0;transition:opacity calc(var(--_k-hover-out,100) * 1ms) ease-out;pointer-events:none}
473
+ .knobs-activity:not([data-keys]) .knobs-activity-row:not([data-leaving]):hover::before{opacity:1;transition-duration:calc(var(--_k-hover-in,0) * 1ms)}
321
474
  .knobs-activity-row[data-kind="you"]{--ka-tint:var(--ka-you)}
322
475
  .knobs-activity-row[data-kind="agent"]{--ka-tint:var(--ka-agent)}
323
476
  .knobs-activity-row[data-kind="proposal"]{--ka-tint:var(--ka-proposal)}
@@ -329,7 +482,7 @@ var init_activity_css = __esm(() => {
329
482
  /* The node: the kind's icon on the line (which stops clear of it), or a small dot inside a group. */
330
483
  .knobs-activity-node{flex:none;display:flex;align-items:center;justify-content:center;width:var(--ka-gutter);height:100%;color:var(--ka-tint)}
331
484
  .knobs-activity-node svg{display:block;width:14px;height:14px}
332
- .knobs-activity-glyph{display:flex;align-items:center;justify-content:center;width:14px;height:14px;font-size:calc(var(--ku-font-size) - 1px);line-height:1}
485
+ .knobs-activity-glyph{display:flex;align-items:center;justify-content:center;width:14px;height:14px;font-size:calc(var(--_k-font-size) - 1px);line-height:1}
333
486
  .knobs-activity-node::before{content:"";position:absolute;left:50%;top:50%;width:22px;height:22px;margin:-11px 0 0 -11px;border-radius:50%;background:color-mix(in srgb,var(--ka-tint) 15%,transparent);
334
487
  opacity:0;scale:.8;transition:opacity .16s ease-out,scale var(--ka-open-ms) var(--ka-open-ease)}
335
488
  .knobs-activity-row[aria-selected="true"] .knobs-activity-node::before{opacity:1;scale:1}
@@ -341,48 +494,48 @@ var init_activity_css = __esm(() => {
341
494
  .knobs-activity-row[data-depth="1"] .knobs-activity-node::before,.knobs-activity-row[data-depth="1"] .knobs-activity-node::after{width:13px;height:13px;margin:-6.5px 0 0 -6.5px}
342
495
  /* The words: who in the text colour, then the title, one line that fades where it's cut off. */
343
496
  .knobs-activity-main{flex:1;min-width:0;overflow:hidden;white-space:nowrap}
344
- .knobs-activity-actor{margin-right:6px;font-weight:var(--ku-label-weight);color:var(--ku-text)}
497
+ .knobs-activity-actor{margin-right:6px;font-weight:var(--_k-weight-label);color:var(--_k-fg)}
345
498
  .knobs-activity-actor:empty{display:none}
346
- .knobs-activity-title{color:var(--ku-label)}
347
- .knobs-activity-row[data-depth="1"] .knobs-activity-main{font-size:var(--ku-text-meta)}
348
- .knobs-activity-row[data-depth="1"] .knobs-activity-actor{font-weight:var(--ku-font-weight);color:var(--ku-label)}
349
- .knobs-activity-row[data-depth="1"] .knobs-activity-title{color:var(--ku-dim)}
350
- .knobs-activity-row[aria-selected="true"] .knobs-activity-title{color:var(--ku-text)}
499
+ .knobs-activity-title{color:var(--_k-fg-2)}
500
+ .knobs-activity-row[data-depth="1"] .knobs-activity-main{font-size:var(--_k-text-meta)}
501
+ .knobs-activity-row[data-depth="1"] .knobs-activity-actor{font-weight:var(--_k-weight);color:var(--_k-fg-2)}
502
+ .knobs-activity-row[data-depth="1"] .knobs-activity-title{color:var(--_k-fg-3)}
503
+ .knobs-activity-row[aria-selected="true"] .knobs-activity-title{color:var(--_k-fg)}
351
504
  .knobs-activity-row[data-dimmed] :is(.knobs-activity-main,.knobs-activity-meta){opacity:.55}
352
505
  .knobs-activity-row[data-dimmed] .knobs-activity-node{opacity:.6}
353
506
  /* Trailing: thumbnails, a duration chip, the group's chevron and the time. */
354
- .knobs-activity-meta{flex:none;display:flex;align-items:center;gap:6px;margin-left:8px;color:var(--ku-dim);font-size:var(--ku-text-meta);font-variant-numeric:tabular-nums}
507
+ .knobs-activity-meta{flex:none;display:flex;align-items:center;gap:6px;margin-left:8px;color:var(--_k-fg-3);font-size:var(--_k-text-meta);font-variant-numeric:tabular-nums}
355
508
  .knobs-activity-meta:empty{display:none}
356
509
  .knobs-activity-thumbs{display:flex;gap:3px}
357
- .knobs-activity-thumbs img{display:block;width:18px;height:18px;border-radius:4px;object-fit:cover;background:var(--ku-surface);box-shadow:inset 0 0 0 .5px var(--ku-line)}
510
+ .knobs-activity-thumbs img{display:block;width:18px;height:18px;border-radius:4px;object-fit:cover;background:var(--_k-fill);box-shadow:inset 0 0 0 .5px var(--_k-border)}
358
511
  .knobs-activity-row[data-depth="1"] .knobs-activity-thumbs img{width:15px;height:15px}
359
512
  :where(.knobs-ui) .knobs-activity-chip{all:revert;box-sizing:border-box;display:inline-flex;align-items:center;gap:4px;height:18px;padding:0 6px 0 5px;border:0;margin:0;border-radius:9px;
360
- background:var(--ku-surface);color:var(--ku-label);font:inherit;font-variant-numeric:tabular-nums;letter-spacing:inherit;outline:none;transition:background calc(var(--k-hover-out,100) * 1ms) ease-out}
513
+ background:var(--_k-fill);color:var(--_k-fg-2);font:inherit;font-variant-numeric:tabular-nums;letter-spacing:inherit;outline:none;transition:background calc(var(--_k-hover-out,100) * 1ms) ease-out}
361
514
  .knobs-activity-chip svg{width:8px;height:8px}
362
515
  button.knobs-activity-chip{cursor:pointer}
363
- button.knobs-activity-chip:hover{background:var(--ku-surface-hi);color:var(--ku-text);transition-duration:0s}
364
- .knobs-activity-caret{display:flex;width:12px;height:12px;color:var(--ku-dim);transition:rotate .18s var(--ku-ease)}
516
+ button.knobs-activity-chip:hover{background:var(--_k-fill-selected);color:var(--_k-fg);transition-duration:0s}
517
+ .knobs-activity-caret{display:flex;width:12px;height:12px;color:var(--_k-fg-3);transition:rotate .18s var(--_ku-ease)}
365
518
  .knobs-activity-caret svg{width:10px;height:10px;margin:1px}
366
519
  .knobs-activity-row[aria-expanded="true"] .knobs-activity-caret{rotate:90deg;transition:rotate var(--ka-open-ms) var(--ka-open-ease)}
367
520
  .knobs-activity-time{min-width:2ch;text-align:right;white-space:nowrap}
368
521
  .knobs-activity-time:empty{display:none}
369
- .knobs-activity-empty{padding:10px var(--ku-inset);color:var(--ku-dim)}
522
+ .knobs-activity-empty{padding:10px var(--_k-inset);color:var(--_k-fg-3)}
370
523
  @media(prefers-reduced-motion:reduce){.knobs-activity :where(*,::before,::after){transition:none!important;animation:none!important}}
371
524
  `;
372
525
  });
373
526
 
374
527
  // src/ui/bento-css.ts
375
528
  var bentoCss = `
376
- .knobs-ui.knobs-bento{--ku-bento-radius:var(--k-ui-bento-radius,max(0px,calc(var(--ku-radius) - 5px)));
377
- position:relative;width:100%;height:100%;overflow:hidden auto;outline:none;background:var(--k-ui-bento-bg,var(--ku-page));
529
+ .knobs-ui.knobs-bento{--_ku-bento-radius:var(--k-ui-bento-radius,max(0px,calc(var(--_k-radius) - 5px)));
530
+ position:relative;width:100%;height:100%;overflow:hidden auto;outline:none;background:var(--k-ui-bento-bg,var(--_k-bg-page));
378
531
  scrollbar-width:thin;scrollbar-gutter:stable;overscroll-behavior:contain;touch-action:pan-y;user-select:none;-webkit-user-select:none;
379
- font:var(--ku-font-weight) var(--ku-font-size)/1.35 var(--ku-font);color:var(--ku-text);letter-spacing:normal;text-align:left}
380
- .knobs-bento[data-frame="flat"]{--ku-bento-radius:var(--k-ui-bento-radius,0px)}
532
+ font:var(--_k-weight) var(--_k-font-size)/1.35 var(--_k-font);color:var(--_k-fg);letter-spacing:normal;text-align:left}
533
+ .knobs-bento[data-frame="flat"]{--_ku-bento-radius:var(--k-ui-bento-radius,0px)}
381
534
  .knobs-bento[data-pending] .knobs-bento-space{visibility:hidden}
382
535
  :where(.knobs-bento-space,.knobs-bento-space *){box-sizing:border-box}
383
536
  .knobs-bento-space{position:relative;width:100%}
384
- .knobs-bento-tile{position:absolute;left:0;top:0;transform-origin:0 0;overflow:hidden;border-radius:var(--ku-bento-radius);
385
- background:var(--ku-surface);contain:strict;cursor:zoom-in}
537
+ .knobs-bento-tile{position:absolute;left:0;top:0;transform-origin:0 0;overflow:hidden;border-radius:var(--_ku-bento-radius);
538
+ background:var(--_k-fill);contain:strict;cursor:zoom-in}
386
539
  .knobs-bento-tile[data-focus]{z-index:2;cursor:zoom-out}
387
540
  .knobs-bento-tile[data-focus][data-live]{cursor:auto}
388
541
  .knobs-bento-img{display:block;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .18s cubic-bezier(.2,.8,.2,1);-webkit-user-drag:none}
@@ -390,49 +543,49 @@ var bentoCss = `
390
543
  .knobs-bento-tile[data-instant] .knobs-bento-img{transition:none}
391
544
  .knobs-bento-body{position:absolute;inset:0;pointer-events:none}
392
545
  .knobs-bento-tile[data-focus] .knobs-bento-body{pointer-events:auto}
393
- .knobs-bento-label{position:absolute;left:9px;right:9px;bottom:7px;color:#fff;font-size:var(--ku-text-meta);line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
394
- text-shadow:0 0 6px rgba(0,0,0,.55),0 0 1px rgba(0,0,0,.5);opacity:0;pointer-events:none;transition:opacity calc(var(--ku-hover-out) * 1ms)}
546
+ .knobs-bento-label{position:absolute;left:9px;right:9px;bottom:7px;color:#fff;font-size:var(--_k-text-meta);line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
547
+ text-shadow:0 0 6px rgba(0,0,0,.55),0 0 1px rgba(0,0,0,.5);opacity:0;pointer-events:none;transition:opacity calc(var(--_k-hover-out) * 1ms)}
395
548
  .knobs-bento:not([data-keyboard]) .knobs-bento-tile:hover .knobs-bento-label,
396
549
  .knobs-bento[data-keyboard]:focus .knobs-bento-tile[data-active] .knobs-bento-label,
397
- .knobs-bento-tile[data-focus] .knobs-bento-label{opacity:1;transition-duration:calc(var(--ku-hover-in) * 1ms)}
550
+ .knobs-bento-tile[data-focus] .knobs-bento-label{opacity:1;transition-duration:calc(var(--_k-hover-in) * 1ms)}
398
551
  /* A pick: a small dot in the accent, ringed in the page so it reads on any picture. */
399
- .knobs-bento-tile::after{content:"";position:absolute;top:8px;right:8px;width:8px;height:8px;border-radius:50%;background:var(--ku-accent);
400
- box-shadow:0 0 0 1.5px color-mix(in srgb,var(--ku-page) 70%,transparent);opacity:0;scale:.4;pointer-events:none;
401
- transition:opacity .11s cubic-bezier(.4,0,1,1),scale var(--ku-ease-ms) var(--ku-ease)}
402
- .knobs-bento-tile[aria-selected="true"]::after{opacity:1;scale:1;transition:opacity .15s cubic-bezier(.2,.8,.2,1),scale var(--ku-ease-ms) var(--ku-ease)}
403
- .knobs-bento-wash{position:absolute;left:0;top:0;width:100px;height:100px;transform-origin:0 0;z-index:3;pointer-events:none;border-radius:var(--ku-bento-radius);
404
- background:color-mix(in srgb,var(--ku-accent) 12%,transparent);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--ku-accent) 45%,transparent);
552
+ .knobs-bento-tile::after{content:"";position:absolute;top:8px;right:8px;width:8px;height:8px;border-radius:50%;background:var(--_k-accent);
553
+ box-shadow:0 0 0 1.5px color-mix(in srgb,var(--_k-bg-page) 70%,transparent);opacity:0;scale:.4;pointer-events:none;
554
+ transition:opacity .11s cubic-bezier(.4,0,1,1),scale var(--_ku-ease-ms) var(--_ku-ease)}
555
+ .knobs-bento-tile[aria-selected="true"]::after{opacity:1;scale:1;transition:opacity .15s cubic-bezier(.2,.8,.2,1),scale var(--_ku-ease-ms) var(--_ku-ease)}
556
+ .knobs-bento-wash{position:absolute;left:0;top:0;width:100px;height:100px;transform-origin:0 0;z-index:3;pointer-events:none;border-radius:var(--_ku-bento-radius);
557
+ background:color-mix(in srgb,var(--_k-accent) 12%,transparent);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--_k-accent) 45%,transparent);
405
558
  opacity:0;transition:opacity .15s}
406
559
  .knobs-bento[data-keyboard]:focus:not([data-zoomed]) .knobs-bento-wash[data-on]{opacity:1}
407
- .knobs-bento-scrim{position:absolute;left:0;top:0;width:100%;z-index:1;background:var(--k-ui-scrim,var(--k-ui-bento-bg,var(--ku-page)));opacity:0;pointer-events:none;cursor:zoom-out}
560
+ .knobs-bento-scrim{position:absolute;left:0;top:0;width:100%;z-index:1;background:var(--k-ui-scrim,var(--k-ui-bento-bg,var(--_k-bg-page)));opacity:0;pointer-events:none;cursor:zoom-out}
408
561
  .knobs-bento[data-zoomed] .knobs-bento-scrim{pointer-events:auto}
409
- .knobs-bento-head{position:absolute;left:0;top:0;display:flex;align-items:flex-end;padding:0 0 6px 2px;color:var(--ku-label);font-weight:var(--ku-label-weight);
410
- font-size:var(--ku-text-meta);white-space:nowrap;pointer-events:none}
562
+ .knobs-bento-head{position:absolute;left:0;top:0;display:flex;align-items:flex-end;padding:0 0 6px 2px;color:var(--_k-fg-2);font-weight:var(--_k-weight-label);
563
+ font-size:var(--_k-text-meta);white-space:nowrap;pointer-events:none}
411
564
  `;
412
565
 
413
566
  // src/ui/compare-css.ts
414
567
  var compareCss = `
415
568
  :where(.knobs-compare,.knobs-compare *,.knobs-cmp-strip,.knobs-cmp-strip *){box-sizing:border-box}
416
- .knobs-ui.knobs-compare{--ku-cmp-diff:var(--k-compare-diff,#7dcf9c);--ku-cmp-line:var(--k-compare-line,#fff);
417
- --ku-cmp-stage:var(--k-compare-stage,var(--ku-surface));
569
+ .knobs-ui.knobs-compare{--_ku-cmp-diff:var(--k-compare-diff,var(--_k-ok));--_ku-cmp-line:var(--_k-compare-divider);
570
+ --_ku-cmp-stage:var(--_k-compare-stage);
418
571
  display:flex;flex-direction:column;gap:6px;width:100%;height:100%;min-height:160px;outline:none;user-select:none;-webkit-user-select:none;
419
- font:var(--ku-font-weight) var(--ku-font-size)/1.35 var(--ku-font);color:var(--ku-text);letter-spacing:normal;text-align:left}
572
+ font:var(--_k-weight) var(--_k-font-size)/1.35 var(--_k-font);color:var(--_k-fg);letter-spacing:normal;text-align:left}
420
573
  :where(.knobs-ui) :is(.knobs-cmp-mode,.knobs-cmp-toggle){all:revert;box-sizing:border-box;font:inherit;color:inherit;letter-spacing:inherit;background:transparent;border:0;margin:0;padding:0;outline:none;box-shadow:none}
421
574
  .knobs-cmp-bar{flex:none;display:flex;align-items:center;gap:2px;height:24px;padding:0 2px}
422
575
  .knobs-cmp-modes{display:flex;align-items:center;gap:2px}
423
- .knobs-ui .knobs-cmp-mode,.knobs-ui .knobs-cmp-toggle{height:22px;padding:0 7px;border-radius:max(0px,calc(var(--ku-radius) - 2px));color:var(--ku-dim);cursor:pointer;white-space:nowrap;
576
+ .knobs-ui .knobs-cmp-mode,.knobs-ui .knobs-cmp-toggle{height:22px;padding:0 7px;border-radius:max(0px,calc(var(--_k-radius) - 2px));color:var(--_k-fg-3);cursor:pointer;white-space:nowrap;
424
577
  transition:color .15s,background .15s}
425
- .knobs-ui .knobs-cmp-mode:is(:hover,:focus-visible),.knobs-ui .knobs-cmp-toggle:is(:hover,:focus-visible){color:var(--ku-text);background:var(--ku-wash)}
426
- .knobs-ui .knobs-cmp-mode[aria-checked="true"],.knobs-ui .knobs-cmp-toggle[aria-pressed="true"]{color:var(--ku-text);font-weight:var(--ku-label-weight)}
578
+ .knobs-ui .knobs-cmp-mode:is(:hover,:focus-visible),.knobs-ui .knobs-cmp-toggle:is(:hover,:focus-visible){color:var(--_k-fg);background:var(--_ku-wash)}
579
+ .knobs-ui .knobs-cmp-mode[aria-checked="true"],.knobs-ui .knobs-cmp-toggle[aria-pressed="true"]{color:var(--_k-fg);font-weight:var(--_k-weight-label)}
427
580
  .knobs-cmp-fill{flex:1}
428
581
  .knobs-cmp-toggle[hidden]{display:none}
429
582
  /* One surface: on a card (a walkthrough's step, a split's pane, anything .knobs-surface) or marked
430
583
  data-nested, the stage drops its fill and the sides sit on that card. */
431
- :where(.knobs-surface,.knobs-pane:not([data-nested])>.knobs-pane-clip) .knobs-ui.knobs-compare,.knobs-ui.knobs-compare[data-nested]{--ku-cmp-stage:var(--k-compare-stage,transparent)}
584
+ :where(.knobs-surface,.knobs-pane:not([data-nested])>.knobs-pane-clip) .knobs-ui.knobs-compare,.knobs-ui.knobs-compare[data-nested]{--_ku-cmp-stage:var(--k-compare-stage,transparent)}
432
585
  /* In a page's flow (a container with no height), it takes the height its sides need. */
433
586
  .knobs-ui.knobs-compare[data-auto]{height:auto}
434
587
  .knobs-compare[data-auto] .knobs-cmp-stage{flex:none;min-height:0}
435
- .knobs-cmp-stage{position:relative;flex:1;min-height:96px;overflow:hidden;border-radius:var(--ku-panel-radius);background:var(--ku-cmp-stage);touch-action:pan-y;outline:none}
588
+ .knobs-cmp-stage{position:relative;flex:1;min-height:96px;overflow:hidden;border-radius:var(--_k-radius-panel);background:var(--_ku-cmp-stage);touch-action:pan-y;outline:none}
436
589
  .knobs-compare[data-frame="flat"] .knobs-cmp-stage{border-radius:0}
437
590
  .knobs-compare[data-mode="wipe"] .knobs-cmp-stage{cursor:ew-resize}
438
591
  /* Unzoomed, a finger still scrolls the page up and down; zoomed, the stage takes every gesture. */
@@ -444,37 +597,37 @@ var compareCss = `
444
597
  .knobs-cmp-media{position:absolute;left:0;top:0;display:block;max-width:none;margin:0;padding:0;border:0;object-fit:fill;transform-origin:0 0;pointer-events:none;will-change:transform}
445
598
  .knobs-compare[data-renderer="gpu"] .knobs-cmp-media{opacity:0}
446
599
  /* Glass: what's behind shows through, blurred, on the knobs tokens. */
447
- .knobs-cmp-label,.knobs-cmp-zoom{background:color-mix(in srgb,var(--ku-bg) 52%,transparent);-webkit-backdrop-filter:blur(14px) saturate(1.6);backdrop-filter:blur(14px) saturate(1.6);
448
- box-shadow:inset 0 0 0 .5px var(--ku-line),inset 0 1px 0 var(--ku-rim),0 2px 10px rgba(0,0,0,.18)}
449
- .knobs-cmp-label{position:absolute;left:0;top:0;padding:1px 7px;border-radius:999px;font-size:var(--ku-text-meta);line-height:16px;color:var(--ku-label);white-space:nowrap;pointer-events:none;will-change:transform;transition:color .15s}
450
- .knobs-cmp-label[data-lit]{color:var(--ku-text)}
451
- .knobs-cmp-label[data-dim]{color:var(--ku-dim)}
600
+ .knobs-cmp-label,.knobs-cmp-zoom{background:color-mix(in srgb,var(--_k-bg) 52%,transparent);-webkit-backdrop-filter:blur(14px) saturate(1.6);backdrop-filter:blur(14px) saturate(1.6);
601
+ box-shadow:inset 0 0 0 .5px var(--_k-border),inset 0 1px 0 var(--_k-rim),0 2px 10px rgba(0,0,0,calc(.18 * var(--_k-shadow-k,1)))}
602
+ .knobs-cmp-label{position:absolute;left:0;top:0;padding:1px 7px;border-radius:999px;font-size:var(--_k-text-meta);line-height:16px;color:var(--_k-fg-2);white-space:nowrap;pointer-events:none;will-change:transform;transition:color .15s}
603
+ .knobs-cmp-label[data-lit]{color:var(--_k-fg)}
604
+ .knobs-cmp-label[data-dim]{color:var(--_k-fg-3)}
452
605
  /* The wipe: a hairline down the line with a grip at its middle; a wider strip takes the hand and
453
606
  the keys (a slider). It fades with the mode. */
454
607
  .knobs-cmp-handle{cursor:ew-resize;position:absolute;left:-12px;top:0;width:24px;height:0;opacity:0;pointer-events:none;outline:none;will-change:transform;transition:opacity .18s cubic-bezier(.4,0,1,1)}
455
608
  .knobs-cmp-handle[data-on]{opacity:1;pointer-events:auto;transition:opacity .22s cubic-bezier(.2,.8,.2,1)}
456
- .knobs-cmp-handle::before{content:"";position:absolute;top:0;bottom:0;left:11.5px;width:1px;background:var(--ku-cmp-line);box-shadow:0 0 0 .5px rgba(0,0,0,.28),0 0 6px rgba(0,0,0,.25)}
457
- .knobs-cmp-handle::after{content:"";position:absolute;top:50%;left:9px;width:6px;height:28px;margin-top:-14px;border-radius:3px;background:var(--ku-cmp-line);
458
- box-shadow:0 1px 3px rgba(0,0,0,.35),0 0 0 .5px rgba(0,0,0,.2);transition:scale .18s var(--ku-ease),box-shadow .15s}
609
+ .knobs-cmp-handle::before{content:"";position:absolute;top:0;bottom:0;left:11.5px;width:1px;background:var(--_ku-cmp-line);box-shadow:0 0 0 .5px rgba(0,0,0,.28),0 0 6px rgba(0,0,0,.25)}
610
+ .knobs-cmp-handle::after{content:"";position:absolute;top:50%;left:9px;width:6px;height:28px;margin-top:-14px;border-radius:3px;background:var(--_ku-cmp-line);
611
+ box-shadow:0 1px 3px rgba(0,0,0,.35),0 0 0 .5px rgba(0,0,0,.2);transition:scale .18s var(--_ku-ease),box-shadow .15s}
459
612
  .knobs-compare[data-dragging] .knobs-cmp-handle::after{scale:1.12}
460
- .knobs-cmp-handle:focus-visible::after,.knobs-compare[data-keyboard] .knobs-cmp-handle:focus::after{box-shadow:0 1px 3px rgba(0,0,0,.35),0 0 0 3px color-mix(in srgb,var(--ku-accent) 40%,transparent)}
613
+ .knobs-cmp-handle:focus-visible::after,.knobs-compare[data-keyboard] .knobs-cmp-handle:focus::after{box-shadow:0 1px 3px rgba(0,0,0,.35),0 0 0 3px color-mix(in srgb,var(--_k-accent) 40%,transparent)}
461
614
  /* The split's hairline, down the middle side by side. */
462
- .knobs-cmp-split{position:absolute;left:0;top:0;width:1px;height:0;margin-left:-.5px;background:color-mix(in srgb,var(--ku-bg) 72%,transparent);pointer-events:none;will-change:transform,opacity}
615
+ .knobs-cmp-split{position:absolute;left:0;top:0;width:1px;height:0;margin-left:-.5px;background:color-mix(in srgb,var(--_k-bg) 72%,transparent);pointer-events:none;will-change:transform,opacity}
463
616
  /* Zoomed: how far, and a way back, in the stage's corner; it fades in and out, nothing shifts. */
464
617
  .knobs-cmp-zoom{position:absolute;right:8px;bottom:8px;display:flex;align-items:center;gap:4px;height:26px;padding:0 3px 0 10px;border-radius:999px;
465
- color:var(--ku-text);font-size:var(--ku-text-meta);font-variant-numeric:tabular-nums;font-feature-settings:"tnum";white-space:nowrap;
618
+ color:var(--_k-fg);font-size:var(--_k-text-meta);font-variant-numeric:tabular-nums;font-feature-settings:"tnum";white-space:nowrap;
466
619
  opacity:0;scale:.96;pointer-events:none;transition:opacity .16s cubic-bezier(.4,0,1,1),scale .16s cubic-bezier(.4,0,1,1)}
467
620
  .knobs-cmp-zoom[data-on]{opacity:1;scale:1;pointer-events:auto;transition:opacity .2s cubic-bezier(.2,.8,.2,1),scale .2s cubic-bezier(.2,.8,.2,1)}
468
621
  :where(.knobs-ui) .knobs-cmp-zoom-reset{all:revert;box-sizing:border-box;font:inherit;letter-spacing:inherit;margin:0;border:0;outline:none;box-shadow:none;
469
- height:20px;padding:0 8px;border-radius:999px;background:transparent;color:var(--ku-label);cursor:pointer;transition:color .15s,background .15s}
470
- :where(.knobs-ui) .knobs-cmp-zoom-reset:is(:hover,:focus-visible){color:var(--ku-text);background:color-mix(in srgb,var(--ku-text) 12%,transparent)}
471
- .knobs-cmp-note{position:absolute;left:50%;top:50%;translate:-50% -50%;color:var(--ku-dim);font-size:var(--ku-text-meta);pointer-events:none}
622
+ height:20px;padding:0 8px;border-radius:999px;background:transparent;color:var(--_k-fg-2);cursor:pointer;transition:color .15s,background .15s}
623
+ :where(.knobs-ui) .knobs-cmp-zoom-reset:is(:hover,:focus-visible){color:var(--_k-fg);background:color-mix(in srgb,var(--_k-fg) 12%,transparent)}
624
+ .knobs-cmp-note{position:absolute;left:50%;top:50%;translate:-50% -50%;color:var(--_k-fg-3);font-size:var(--_k-text-meta);pointer-events:none}
472
625
  .knobs-cmp-note:empty{display:none}
473
626
  .knobs-cmp-strip-host{flex:none;height:60px;min-height:0}
474
627
  .knobs-cmp-timeline-host{flex:none;height:56px;min-height:0}
475
628
  /* The frame strip: Before over After per column, a difference bar under them, a dot where it peaks. */
476
- .knobs-ui.knobs-cmp-strip{--ku-cmp-diff:var(--k-compare-diff,#7dcf9c);position:relative;width:100%;height:100%;min-height:40px;overflow:hidden;cursor:col-resize;touch-action:none;
477
- font:var(--ku-font-weight) var(--ku-font-size)/1.35 var(--ku-font);color:var(--ku-text)}
629
+ .knobs-ui.knobs-cmp-strip{--_ku-cmp-diff:var(--k-compare-diff,var(--_k-ok));position:relative;width:100%;height:100%;min-height:40px;overflow:hidden;cursor:col-resize;touch-action:none;
630
+ font:var(--_k-weight) var(--_k-font-size)/1.35 var(--_k-font);color:var(--_k-fg)}
478
631
  .knobs-cmp-strip>canvas{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none}
479
632
  @media(prefers-reduced-motion:reduce){:is(.knobs-compare,.knobs-cmp-strip) :where(*,::before,::after){transition-duration:.12s!important}}
480
633
  `;
@@ -483,135 +636,136 @@ var compareCss = `
483
636
  var overlayCss = `
484
637
  .knobs-layers{position:fixed;inset:0;z-index:2147480005;pointer-events:none}
485
638
  .knobs-layers>.knobs-layer,.knobs-ui.knobs-toast{position:fixed;left:0;top:0;box-sizing:border-box;pointer-events:auto;outline:none;
486
- font:var(--ku-font-weight) var(--ku-font-size)/1.4 var(--ku-font);color:var(--ku-text);letter-spacing:normal;text-align:left;text-transform:none;
639
+ font:var(--_k-weight) var(--_k-font-size)/1.4 var(--_k-font);color:var(--_k-fg);letter-spacing:normal;text-align:left;text-transform:none;
487
640
  -webkit-font-smoothing:antialiased;will-change:transform,opacity,filter}
488
641
  /* The overlays' own elements stop a host's element rules; what you put in a popover is yours. */
489
642
  :where(.knobs-layers,.knobs-toast) :is(.knobs-kbd,.knobs-mitem,.knobs-menu-sep,.knobs-palette-input,.knobs-palette-label>mark,.knobs-confirm-title,.knobs-confirm-body,.knobs-confirm-btn,.knobs-toast-action){all:revert;box-sizing:border-box;font:inherit;color:inherit;letter-spacing:inherit;
490
643
  background:transparent;border:0;margin:0;padding:0;outline:none;box-shadow:none}
491
644
  .knobs-layers .knobs-layer *{box-sizing:border-box}
492
645
  /* A floating surface: frosted, a hairline rim, a soft shadow. */
493
- .knobs-layers>:is(.knobs-popover-layer,.knobs-palette,.knobs-confirm,.knobs-menu-layer){background:color-mix(in srgb,var(--ku-bg) 88%,transparent);
494
- -webkit-backdrop-filter:blur(28px) saturate(1.7);backdrop-filter:blur(28px) saturate(1.7);border-radius:var(--ku-panel-radius);
495
- box-shadow:0 0 0 .5px var(--ku-line-hi),inset 0 1px 0 var(--ku-rim),0 12px 40px rgba(0,0,0,.36),0 2px 8px rgba(0,0,0,.18)}
646
+ .knobs-layers>:is(.knobs-popover-layer,.knobs-palette,.knobs-confirm,.knobs-menu-layer){background:color-mix(in srgb,var(--_k-bg) 88%,transparent);
647
+ -webkit-backdrop-filter:blur(28px) saturate(1.7);backdrop-filter:blur(28px) saturate(1.7);border-radius:var(--_k-radius-panel);
648
+ box-shadow:0 0 0 .5px var(--_k-border-strong),inset 0 1px 0 var(--_k-rim),0 12px 40px rgba(0,0,0,calc(.36 * var(--_k-shadow-k,1))),0 2px 8px rgba(0,0,0,calc(.18 * var(--_k-shadow-k,1)))}
496
649
  .knobs-layers>.knobs-popover-layer{min-width:120px;max-width:min(420px,calc(100vw - 16px));padding:6px}
497
- .knobs-popover-layer .knobs-popover-text{padding:4px 6px;color:var(--ku-label)}
650
+ .knobs-popover-layer .knobs-popover-text{padding:4px 6px;color:var(--_k-fg-2)}
498
651
 
499
652
  /* Menus: rows of the panel's control height, a soft wash on the active one (never an outline),
500
653
  concentric corners inside the surface. */
501
654
  .knobs-layers>.knobs-menu-layer{display:flex;flex-direction:column;min-width:184px;max-width:min(340px,calc(100vw - 16px));max-height:calc(100vh - 16px);overflow:auto;padding:5px;
502
655
  scrollbar-width:thin;overscroll-behavior:contain;user-select:none;-webkit-user-select:none}
503
- .knobs-menu-layer .knobs-mitem{position:relative;display:flex;align-items:center;gap:8px;flex:none;height:max(22px,calc(var(--ku-row) - 6px));padding:0 8px;
504
- border-radius:max(0px,calc(var(--ku-panel-radius) - 5px));color:var(--ku-text);cursor:default;white-space:nowrap}
505
- .knobs-menu-layer .knobs-mitem[data-active],.knobs-menu-layer .knobs-mitem[data-open]{background:var(--ku-wash-hi)}
506
- .knobs-menu-layer .knobs-mitem[data-destructive]{color:var(--ku-critical)}
507
- .knobs-menu-layer .knobs-mitem[data-destructive][data-active]{background:color-mix(in srgb,var(--ku-critical) 16%,transparent)}
656
+ .knobs-menu-layer .knobs-mitem{position:relative;display:flex;align-items:center;gap:8px;flex:none;height:max(22px,calc(var(--_k-row) - 6px));padding:0 8px;
657
+ border-radius:max(0px,calc(var(--_k-radius-panel) - 5px));color:var(--_k-fg);cursor:default;white-space:nowrap}
658
+ .knobs-menu-layer .knobs-mitem[data-active],.knobs-menu-layer .knobs-mitem[data-open]{background:var(--_ku-wash-hi)}
659
+ .knobs-menu-layer .knobs-mitem[data-destructive]{color:var(--_k-danger)}
660
+ .knobs-menu-layer .knobs-mitem[data-destructive][data-active]{background:color-mix(in srgb,var(--_k-danger) 16%,transparent)}
508
661
  .knobs-menu-layer .knobs-mitem[aria-disabled="true"]{opacity:.38}
509
- .knobs-menu-layer .knobs-menu-lead{flex:none;display:flex;align-items:center;justify-content:center;width:14px;margin-left:-2px;color:var(--ku-label);font-size:calc(var(--ku-font-size) - 1px)}
662
+ .knobs-menu-layer .knobs-menu-lead{flex:none;display:flex;align-items:center;justify-content:center;width:14px;margin-left:-2px;color:var(--_k-fg-2);font-size:calc(var(--_k-font-size) - 1px)}
510
663
  .knobs-menu-layer .knobs-mitem[data-destructive] .knobs-menu-lead,.knobs-menu-layer .knobs-mitem[aria-checked="true"] .knobs-menu-lead{color:inherit}
511
664
  .knobs-menu-layer .knobs-menu-lead svg{width:13px;height:13px}
512
665
  .knobs-menu-layer .knobs-menu-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis}
513
- .knobs-menu-layer .knobs-menu-hint{flex:none;color:var(--ku-dim)}
666
+ .knobs-menu-layer .knobs-menu-hint{flex:none;color:var(--_k-fg-3)}
514
667
  .knobs-menu-layer .knobs-menu-keys{display:inline-flex;gap:2px;flex:none;margin-left:12px}
515
- .knobs-menu-layer .knobs-mitem[data-active] .knobs-kbd{background:color-mix(in srgb,var(--ku-text) 14%,transparent);color:var(--ku-text)}
516
- .knobs-menu-layer .knobs-menu-caret{flex:none;display:flex;margin-left:8px;margin-right:-3px;color:var(--ku-dim)}
668
+ .knobs-menu-layer .knobs-mitem[data-active] .knobs-kbd{background:color-mix(in srgb,var(--_k-fg) 14%,transparent);color:var(--_k-fg)}
669
+ .knobs-menu-layer .knobs-menu-caret{flex:none;display:flex;margin-left:8px;margin-right:-3px;color:var(--_k-fg-3)}
517
670
  .knobs-menu-layer .knobs-menu-caret svg{width:10px;height:10px}
518
- .knobs-menu-layer .knobs-menu-sep{flex:none;height:1px;margin:4px 8px;background:var(--ku-line)}
671
+ .knobs-menu-layer .knobs-menu-sep{flex:none;height:1px;margin:4px 8px;background:var(--_k-border)}
519
672
 
520
673
  .knobs-layers>.knobs-tooltip{display:inline-flex;align-items:center;gap:7px;max-width:300px;padding:4px 8px;pointer-events:none;white-space:nowrap;
521
- font-size:calc(var(--ku-font-size) - .5px);background:var(--ku-bg);color:var(--ku-text);border-radius:min(var(--ku-radius),6px);
522
- box-shadow:0 0 0 .5px var(--ku-line-hi),0 4px 14px rgba(0,0,0,.3)}
674
+ font-size:calc(var(--_k-font-size) - .5px);background:var(--_k-bg);color:var(--_k-fg);border-radius:min(var(--_k-radius),6px);
675
+ box-shadow:0 0 0 .5px var(--_k-border-strong),0 4px 14px rgba(0,0,0,calc(.3 * var(--_k-shadow-k,1)))}
523
676
  .knobs-tooltip .knobs-tooltip-text{overflow:hidden;text-overflow:ellipsis}
524
677
  .knobs-layer :is(.knobs-tooltip-keys,.knobs-palette-keys){display:inline-flex;gap:2px;flex:none}
525
678
  .knobs-layer .knobs-tooltip-keys[hidden]{display:none}
526
679
  .knobs-layer .knobs-kbd{display:inline-flex;align-items:center;justify-content:center;min-width:17px;height:17px;padding:0 4px;
527
- border-radius:min(var(--ku-radius),4px);background:var(--ku-surface-hi);color:var(--ku-label);font:500 calc(var(--ku-font-size) - 1.5px)/1 var(--ku-font)}
680
+ border-radius:min(var(--_k-radius),4px);background:var(--_k-fill-selected);color:var(--_k-fg-2);font:500 calc(var(--_k-font-size) - 1.5px)/1 var(--_k-font)}
528
681
 
529
682
  .knobs-layers>.knobs-palette{left:50%;top:max(48px,15vh);translate:-50% 0;transform-origin:50% 0;display:flex;flex-direction:column;
530
683
  width:min(580px,calc(100vw - 32px));max-height:min(460px,72vh);overflow:hidden}
531
- .knobs-palette .knobs-palette-field{display:flex;align-items:center;gap:10px;flex:none;height:46px;padding:0 16px;border-bottom:1px solid var(--ku-line);color:var(--ku-dim)}
684
+ .knobs-palette .knobs-palette-field{display:flex;align-items:center;gap:10px;flex:none;height:46px;padding:0 16px;border-bottom:1px solid var(--_k-border);color:var(--_k-fg-3)}
532
685
  .knobs-palette .knobs-palette-field svg{width:15px;height:15px;flex:none}
533
- .knobs-palette .knobs-palette-input{flex:1;min-width:0;height:100%;font-size:calc(var(--ku-font-size) + 3px);color:var(--ku-text);caret-color:var(--ku-accent)}
534
- .knobs-palette .knobs-palette-input::placeholder{color:var(--ku-dim)}
686
+ .knobs-palette .knobs-palette-input{flex:1;min-width:0;height:100%;font-size:calc(var(--_k-font-size) + 3px);color:var(--_k-fg);caret-color:var(--_k-accent)}
687
+ .knobs-palette .knobs-palette-input::placeholder{color:var(--_k-fg-3)}
535
688
  .knobs-palette .knobs-palette-list{position:relative;flex:1;min-height:0;overflow:auto;padding:6px;scrollbar-width:thin;overscroll-behavior:contain}
536
- .knobs-palette .knobs-palette-hl{position:absolute;left:6px;right:6px;top:0;border-radius:max(0px,calc(var(--ku-panel-radius) - 6px));background:var(--ku-wash-hi);opacity:0;pointer-events:none;
537
- transition:transform var(--ku-ease-ms) var(--ku-ease),height var(--ku-ease-ms) var(--ku-ease),opacity .12s}
538
- .knobs-palette .knobs-palette-section{padding:10px 10px 4px;color:var(--ku-dim);font-size:calc(var(--ku-font-size) - 1px);font-weight:var(--ku-label-weight);user-select:none}
689
+ .knobs-palette .knobs-palette-hl{position:absolute;left:6px;right:6px;top:0;border-radius:max(0px,calc(var(--_k-radius-panel) - 6px));background:var(--_ku-wash-hi);opacity:0;pointer-events:none;
690
+ transition:transform var(--_ku-ease-ms) var(--_ku-ease),height var(--_ku-ease-ms) var(--_ku-ease),opacity .12s}
691
+ .knobs-palette .knobs-palette-section{padding:10px 10px 4px;color:var(--_k-fg-3);font-size:calc(var(--_k-font-size) - 1px);font-weight:var(--_k-weight-label);user-select:none}
539
692
  .knobs-palette .knobs-palette-section:first-of-type{padding-top:4px}
540
- .knobs-palette .knobs-palette-item{position:relative;display:flex;align-items:center;gap:8px;height:max(32px,var(--ku-row));padding:0 10px;
541
- color:var(--ku-label);cursor:default;user-select:none}
542
- .knobs-palette .knobs-palette-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ku-text)}
693
+ .knobs-palette .knobs-palette-item{position:relative;display:flex;align-items:center;gap:8px;height:max(32px,var(--_k-row));padding:0 10px;
694
+ color:var(--_k-fg-2);cursor:default;user-select:none}
695
+ .knobs-palette .knobs-palette-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--_k-fg)}
543
696
  /* Searching, the label dims and its matched letters light up. */
544
- .knobs-palette[data-query] .knobs-palette-label{color:var(--ku-label)}
545
- .knobs-palette .knobs-palette-label mark{color:var(--ku-accent);font-weight:var(--ku-title-weight)}
546
- .knobs-palette[data-query] .knobs-palette-item[data-active] .knobs-palette-label{color:var(--ku-text)}
547
- .knobs-palette .knobs-palette-hint{flex:none;color:var(--ku-dim)}
697
+ .knobs-palette[data-query] .knobs-palette-label{color:var(--_k-fg-2)}
698
+ .knobs-palette .knobs-palette-label mark{color:var(--_k-accent);font-weight:var(--_k-weight-title)}
699
+ .knobs-palette[data-query] .knobs-palette-item[data-active] .knobs-palette-label{color:var(--_k-fg)}
700
+ .knobs-palette .knobs-palette-hint{flex:none;color:var(--_k-fg-3)}
548
701
  .knobs-palette .knobs-palette-fill{flex:1}
549
- .knobs-palette .knobs-palette-tag{flex:none;color:var(--ku-dim);font-size:calc(var(--ku-font-size) - 1px);white-space:nowrap}
702
+ .knobs-palette .knobs-palette-tag{flex:none;color:var(--_k-fg-3);font-size:calc(var(--_k-font-size) - 1px);white-space:nowrap}
550
703
  .knobs-palette .knobs-palette-item[aria-disabled="true"]{opacity:.4}
551
- .knobs-palette .knobs-palette-empty{padding:18px 10px;color:var(--ku-dim);text-align:center}
704
+ .knobs-palette .knobs-palette-empty{padding:18px 10px;color:var(--_k-fg-3);text-align:center}
552
705
 
553
- .knobs-layers>.knobs-scrim{inset:0;width:100%;height:100%;background:rgba(0,0,0,.3)}
706
+ .knobs-layers>.knobs-scrim{inset:0;width:100%;height:100%;background:var(--_k-scrim)}
554
707
  .knobs-layers>.knobs-confirm{left:50%;top:42%;translate:-50% -50%;width:min(340px,calc(100vw - 32px));padding:18px 18px 14px}
555
- .knobs-confirm .knobs-confirm-title{margin:0 0 6px;font-size:calc(var(--ku-font-size) + 1.5px);font-weight:var(--ku-title-weight);color:var(--ku-text);line-height:1.3}
556
- .knobs-confirm .knobs-confirm-body{margin:0;color:var(--ku-label);line-height:1.45}
708
+ .knobs-confirm .knobs-confirm-title{margin:0 0 6px;font-size:calc(var(--_k-font-size) + 1.5px);font-weight:var(--_k-weight-title);color:var(--_k-fg);line-height:1.3}
709
+ .knobs-confirm .knobs-confirm-body{margin:0;color:var(--_k-fg-2);line-height:1.45}
557
710
  .knobs-confirm .knobs-confirm-buttons{display:flex;justify-content:flex-end;gap:8px;margin-top:18px}
558
- .knobs-confirm .knobs-confirm-btn{height:28px;padding:0 14px;border-radius:min(var(--ku-radius),7px);background:var(--ku-surface-hi);color:var(--ku-text);
559
- font-weight:var(--ku-label-weight);cursor:pointer;transition:background .15s,filter .15s}
560
- .knobs-confirm .knobs-confirm-cancel:is(:hover,:focus-visible){background:color-mix(in srgb,var(--ku-text) 18%,transparent)}
561
- .knobs-confirm .knobs-confirm-ok{background:var(--ku-accent);color:var(--ku-bg)}
562
- .knobs-confirm .knobs-confirm-ok[data-destructive]{background:var(--ku-critical);color:#fff}
711
+ .knobs-confirm .knobs-confirm-btn{height:28px;padding:0 14px;border-radius:min(var(--_k-radius),7px);background:var(--_k-fill-selected);color:var(--_k-fg);
712
+ font-weight:var(--_k-weight-label);cursor:pointer;transition:background .15s,filter .15s}
713
+ .knobs-confirm .knobs-confirm-cancel:is(:hover,:focus-visible){background:color-mix(in srgb,var(--_k-fg) 18%,transparent)}
714
+ .knobs-confirm .knobs-confirm-ok{background:var(--_k-accent);color:var(--_k-bg)}
715
+ .knobs-confirm .knobs-confirm-ok[data-destructive]{background:var(--_k-danger);color:#fff}
563
716
  .knobs-confirm .knobs-confirm-ok:is(:hover,:focus-visible){filter:brightness(1.14)}
564
717
 
565
718
  .knobs-ui.knobs-toast{left:50%;top:auto;bottom:24px;z-index:2147480005;translate:-50% 0;display:inline-flex;align-items:center;gap:10px;
566
- max-width:min(480px,80vw);padding:8px 16px;background:var(--ku-bg);color:var(--ku-text);border-radius:calc(var(--ku-radius) * 999);
567
- box-shadow:0 0 0 .5px var(--ku-line-hi),0 8px 28px rgba(0,0,0,.32)}
719
+ max-width:min(480px,80vw);padding:8px 16px;background:var(--_k-bg);color:var(--_k-fg);border-radius:calc(var(--_k-radius) * 999);
720
+ box-shadow:0 0 0 .5px var(--_k-border-strong),0 8px 28px rgba(0,0,0,calc(.32 * var(--_k-shadow-k,1)))}
568
721
  .knobs-toast .knobs-toast-text{overflow-wrap:anywhere}
569
- .knobs-toast[data-tone="warn"]::before,.knobs-toast[data-tone="error"]::before{content:"";flex:none;width:7px;height:7px;border-radius:50%;background:var(--ku-warn)}
570
- .knobs-toast[data-tone="error"]::before{background:var(--ku-critical)}
571
- .knobs-toast .knobs-toast-action{flex:none;color:var(--ku-accent);font-weight:var(--ku-title-weight);cursor:pointer}
722
+ .knobs-toast[data-tone="warn"]::before,.knobs-toast[data-tone="error"]::before{content:"";flex:none;width:7px;height:7px;border-radius:50%;background:var(--_k-warn)}
723
+ .knobs-toast[data-tone="error"]::before{background:var(--_k-danger)}
724
+ .knobs-toast .knobs-toast-action{flex:none;color:var(--_k-accent);font-weight:var(--_k-weight-title);cursor:pointer}
572
725
  .knobs-toast .knobs-toast-action[hidden]{display:none}
573
726
  `;
574
727
 
575
728
  // src/ui/picker-css.ts
576
729
  var snappy, pickerCss;
577
730
  var init_picker_css = __esm(() => {
578
- snappy = springEasing(2 * Math.PI / 0.25, 1);
731
+ init_motion();
732
+ snappy = springLinear(SPRINGS.snappy);
579
733
  pickerCss = `
580
734
  :where(.knobs-picker,.knobs-picker-option,.knobs-picker-head,.knobs-picker-head *,.knobs-picker-card,.knobs-picker-body){box-sizing:border-box}
581
735
  .knobs-ui.knobs-picker{position:relative;display:flex;flex-direction:column;gap:2px;padding:0;outline:none;
582
- font:var(--ku-font-weight) var(--ku-font-size)/1.35 var(--ku-font);color:var(--ku-text);text-align:left;letter-spacing:normal;-webkit-font-smoothing:antialiased;
583
- --kp-card:var(--k-picker-card,var(--ku-surface));--kp-radius:var(--k-picker-radius,var(--ku-panel-radius));--kp-snappy:${snappy.easing};--kp-snappy-ms:${snappy.ms}ms}
736
+ font:var(--_k-weight) var(--_k-font-size)/1.35 var(--_k-font);color:var(--_k-fg);text-align:left;letter-spacing:normal;-webkit-font-smoothing:antialiased;
737
+ --kp-card:var(--_k-picker-card);--kp-radius:var(--k-picker-radius,var(--_k-radius-panel));--kp-snappy:${snappy.easing};--kp-snappy-ms:${snappy.ms}ms}
584
738
  .knobs-picker [hidden]{display:none!important}
585
739
  /* The selection: one card behind the selected option and its parameters, gliding between them. */
586
- .knobs-picker-card{position:absolute;left:0;right:0;top:0;height:0;border-radius:var(--kp-radius);background:var(--kp-card);box-shadow:inset 0 0 0 1px var(--ku-line);pointer-events:none}
740
+ .knobs-picker-card{position:absolute;left:0;right:0;top:0;height:0;border-radius:var(--kp-radius);background:var(--kp-card);box-shadow:inset 0 0 0 1px var(--_k-border);pointer-events:none}
587
741
  .knobs-picker[data-frame="flat"] .knobs-picker-card{box-shadow:none}
588
742
  .knobs-picker-option{position:relative;flex:none}
589
- :where(.knobs-ui) .knobs-picker-head{all:revert;box-sizing:border-box;position:relative;display:flex;align-items:center;gap:8px;width:100%;height:var(--ku-row);padding:0 calc(var(--ku-inset) - 2px) 0 calc(var(--ku-inset) - 4px);
590
- border:0;margin:0;background:transparent;color:var(--ku-label);font:inherit;letter-spacing:inherit;text-align:left;cursor:default;outline:none;user-select:none;-webkit-user-select:none}
743
+ :where(.knobs-ui) .knobs-picker-head{all:revert;box-sizing:border-box;position:relative;display:flex;align-items:center;gap:8px;width:100%;height:var(--_k-row);padding:0 calc(var(--_k-inset) - 2px) 0 calc(var(--_k-inset) - 4px);
744
+ border:0;margin:0;background:transparent;color:var(--_k-fg-2);font:inherit;letter-spacing:inherit;text-align:left;cursor:default;outline:none;user-select:none;-webkit-user-select:none}
591
745
  /* Hover: in at once, out over 100 ms. Keyboard focus: the same wash, a little firmer. */
592
- .knobs-picker-head::before{content:"";position:absolute;inset:0;border-radius:var(--kp-radius);background:var(--ku-wash);opacity:0;transition:opacity calc(var(--k-hover-out,100) * 1ms) ease-out;pointer-events:none}
593
- .knobs-picker-option:not([data-selected]) .knobs-picker-head:hover::before{opacity:1;transition-duration:calc(var(--k-hover-in,0) * 1ms)}
594
- .knobs-picker-head:focus-visible::before{opacity:1;background:var(--ku-wash-hi);transition-duration:0s}
746
+ .knobs-picker-head::before{content:"";position:absolute;inset:0;border-radius:var(--kp-radius);background:var(--_ku-wash);opacity:0;transition:opacity calc(var(--_k-hover-out,100) * 1ms) ease-out;pointer-events:none}
747
+ .knobs-picker-option:not([data-selected]) .knobs-picker-head:hover::before{opacity:1;transition-duration:calc(var(--_k-hover-in,0) * 1ms)}
748
+ .knobs-picker-head:focus-visible::before{opacity:1;background:var(--_ku-wash-hi);transition-duration:0s}
595
749
  .knobs-picker-head>*{position:relative}
596
- .knobs-picker-option[data-selected] .knobs-picker-head{color:var(--ku-text)}
750
+ .knobs-picker-option[data-selected] .knobs-picker-head{color:var(--_k-fg)}
597
751
  /* Every row is numbered (only 1–9 are keys): tabular digits in a column two digits wide, so the
598
752
  names line up past the ninth. */
599
- .knobs-picker-key{flex:none;display:inline-flex;align-items:center;justify-content:center;width:max(17px,calc(2ch + 6px));height:17px;padding:0;border-radius:5px;background:var(--ku-surface);
600
- color:var(--ku-dim);font:var(--ku-label-weight) calc(var(--ku-font-size) - 1.5px)/1 var(--ku-font);font-variant-numeric:tabular-nums;transition:background .15s,color .15s}
753
+ .knobs-picker-key{flex:none;display:inline-flex;align-items:center;justify-content:center;width:max(17px,calc(2ch + 6px));height:17px;padding:0;border-radius:5px;background:var(--_k-fill);
754
+ color:var(--_k-fg-3);font:var(--_k-weight-label) calc(var(--_k-font-size) - 1.5px)/1 var(--_k-font);font-variant-numeric:tabular-nums;transition:background .15s,color .15s}
601
755
  .knobs-picker-key:empty{visibility:hidden}
602
756
  /* An option's picture: cover-fit, the rows' corner language and a hairline drawn over it. Its
603
757
  space is kept while it loads (nothing drawn), it fades in once loaded, and one that fails
604
758
  gives its space back on the same ease. */
605
- .knobs-picker-thumb{flex:none;display:block;width:var(--k-picker-thumb,min(24px,calc(var(--ku-row) - 10px)));aspect-ratio:1;margin:0;border-radius:max(3px,calc(var(--ku-radius) - 2px));
606
- object-fit:cover;background:none;outline:1px solid var(--ku-line);outline-offset:-1px;opacity:0;
759
+ .knobs-picker-thumb{flex:none;display:block;width:var(--k-picker-thumb,min(24px,calc(var(--_k-row) - 10px)));aspect-ratio:1;margin:0;border-radius:max(3px,calc(var(--_k-radius) - 2px));
760
+ object-fit:cover;background:none;outline:1px solid var(--_k-border);outline-offset:-1px;opacity:0;
607
761
  transition:opacity .2s ease-out,width .18s ease-out,margin .18s ease-out}
608
762
  .knobs-picker-thumb[data-state="loaded"]{opacity:1}
609
763
  .knobs-picker-thumb[data-instant]{transition:none}
610
764
  .knobs-picker-thumb[data-state="failed"]{width:0;margin-right:-8px;outline-color:transparent}
611
- .knobs-picker-option[data-selected] .knobs-picker-key{background:var(--ku-surface-hi);color:var(--ku-text)}
612
- .knobs-picker-name{flex:1;min-width:0;overflow:hidden;white-space:nowrap;font-weight:var(--ku-label-weight)}
613
- .knobs-picker-suggested{flex:none;color:var(--ku-dim);font-size:var(--ku-text-meta)}
614
- .knobs-picker-check{flex:none;display:flex;width:14px;height:14px;color:var(--ku-accent);opacity:0;scale:.6;filter:blur(2px);
765
+ .knobs-picker-option[data-selected] .knobs-picker-key{background:var(--_k-fill-selected);color:var(--_k-fg)}
766
+ .knobs-picker-name{flex:1;min-width:0;overflow:hidden;white-space:nowrap;font-weight:var(--_k-weight-label)}
767
+ .knobs-picker-suggested{flex:none;color:var(--_k-fg-3);font-size:var(--_k-text-meta)}
768
+ .knobs-picker-check{flex:none;display:flex;width:14px;height:14px;color:var(--_k-accent);opacity:0;scale:.6;filter:blur(2px);
615
769
  transition:opacity .11s ease-in,scale .11s ease-in,filter .11s ease-in}
616
770
  .knobs-picker-check svg{display:block;width:14px;height:14px}
617
771
  .knobs-picker-option[data-chosen] .knobs-picker-check{opacity:1;scale:1;filter:none;transition:opacity .15s ease-out,scale var(--kp-snappy-ms) var(--kp-snappy),filter .15s ease-out}
@@ -623,7 +777,7 @@ var init_picker_css = __esm(() => {
623
777
  .knobs-picker-inner{padding:var(--k-picker-pad,0 8px 8px)}
624
778
  .knobs-picker-inner:empty{padding:0}
625
779
  .knobs-picker-inner .knobs-panel.knobs-inline{--k-chrome:0;padding:0}
626
- .knobs-picker-empty{padding:8px var(--ku-inset);color:var(--ku-dim)}
780
+ .knobs-picker-empty{padding:8px var(--_k-inset);color:var(--_k-fg-3)}
627
781
  @media(prefers-reduced-motion:reduce){.knobs-picker :where(*,::before,::after){transition-duration:.15s!important;scale:none!important;filter:none!important}}
628
782
  `;
629
783
  });
@@ -634,25 +788,25 @@ var readoutCss = `
634
788
  :where(.knobs-ui) :is(.knobs-rd-chip,.knobs-rd-copy,.knobs-rd-jump,.knobs-rd-find,.knobs-rd-match){all:revert;box-sizing:border-box;
635
789
  font:inherit;color:inherit;letter-spacing:inherit;background:transparent;border:0;border-radius:0;margin:0;padding:0;min-width:0;box-shadow:none;outline:none}
636
790
  .knobs-ui.knobs-rd,.knobs-rd *{box-sizing:border-box}
637
- .knobs-ui.knobs-rd{display:flex;align-items:center;gap:8px;min-width:0;color:var(--ku-text);letter-spacing:normal}
638
- .knobs-rd .knobs-rd-v{font:var(--ku-font-weight) var(--ku-value-size)/1.25 var(--ku-value-font);font-variant-numeric:tabular-nums;font-feature-settings:"tnum";white-space:nowrap}
639
- .knobs-rd .knobs-rd-mono{font:400 var(--ku-text-meta)/1.25 var(--ku-mono);font-variant-numeric:tabular-nums;white-space:pre}
640
- .knobs-rd .knobs-rd-meta{font:var(--ku-font-weight) var(--ku-text-meta)/1.25 var(--ku-font);white-space:nowrap}
791
+ .knobs-ui.knobs-rd{display:flex;align-items:center;gap:8px;min-width:0;color:var(--_k-fg);letter-spacing:normal}
792
+ .knobs-rd .knobs-rd-v{font:var(--_k-weight) var(--_k-value-size)/1.25 var(--_k-value-font);font-variant-numeric:tabular-nums;font-feature-settings:"tnum";white-space:nowrap}
793
+ .knobs-rd .knobs-rd-mono{font:400 var(--_k-text-meta)/1.25 var(--_k-mono);font-variant-numeric:tabular-nums;white-space:pre}
794
+ .knobs-rd .knobs-rd-meta{font:var(--_k-weight) var(--_k-text-meta)/1.25 var(--_k-font);white-space:nowrap}
641
795
  .knobs-rd .knobs-rd-value{display:inline-flex;justify-content:flex-end;align-items:baseline;flex:none;margin-left:auto;contain:layout paint style}
642
- .knobs-rd .knobs-rd-num{color:var(--ku-text);text-align:right;transition:color .15s}
643
- .knobs-rd .knobs-rd-unit{margin-left:var(--k-unit-gap,.28em);color:var(--ku-dim)}
796
+ .knobs-rd .knobs-rd-num{color:var(--_k-fg);text-align:right;transition:color .15s}
797
+ .knobs-rd .knobs-rd-unit{margin-left:var(--k-unit-gap,.28em);color:var(--_k-fg-3)}
644
798
  .knobs-rd .knobs-rd-unit[hidden]{display:none}
645
799
  .knobs-rd.knobs-rd-watch{flex:1 1 auto;justify-content:flex-end}
646
800
  .knobs-rd.knobs-rd-spark,.knobs-rd.knobs-rd-meter{flex:0 1 64%;margin-left:auto}
647
- .knobs-rd .knobs-rd-plot{display:block;flex:1 1 0;min-width:24px;height:max(12px,calc(var(--ku-control-h) - 2px))}
801
+ .knobs-rd .knobs-rd-plot{display:block;flex:1 1 0;min-width:24px;height:max(12px,calc(var(--_k-control-h) - 2px))}
648
802
  .knobs-rd.knobs-rd-meter>.knobs-rd-plot{height:8px}
649
- .knobs-rd.knobs-rd-spark[data-hover] .knobs-rd-num{color:var(--ku-label)}
650
- .knobs-rd .knobs-rd-cap,.knobs-rd .knobs-rd-head>span:first-child{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ku-label);font-weight:var(--ku-label-weight)}
803
+ .knobs-rd.knobs-rd-spark[data-hover] .knobs-rd-num{color:var(--_k-fg-2)}
804
+ .knobs-rd .knobs-rd-cap,.knobs-rd .knobs-rd-head>span:first-child{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--_k-fg-2);font-weight:var(--_k-weight-label)}
651
805
 
652
806
  /* Blocks: a head line (the label and what goes with it) over a body. In a panel the row grows to fit. */
653
807
  .knobs-panel .knobs-row.knobs-rd-rowblock{display:block;height:auto}
654
808
  .knobs-rd.knobs-rd-block{display:flex;flex-direction:column;align-items:stretch;gap:2px;width:100%}
655
- .knobs-rd .knobs-rd-head{display:flex;align-items:center;gap:0 10px;min-height:var(--ku-row);min-width:0}
809
+ .knobs-rd .knobs-rd-head{display:flex;align-items:center;gap:0 10px;min-height:var(--_k-row);min-width:0}
656
810
  /* The title keeps its words; the legend or tools beside it give way (see fitHead). */
657
811
  .knobs-rd .knobs-rd-head>span:first-child{flex:0 0 auto;max-width:100%}
658
812
  .knobs-rd .knobs-rd-legend{display:flex;align-items:center;gap:12px;margin-left:auto;min-width:0;overflow:hidden}
@@ -660,16 +814,16 @@ var readoutCss = `
660
814
  .knobs-rd .knobs-rd-tools>.knobs-rd-find{flex:1 1 56px;min-width:56px;max-width:84px}
661
815
  .knobs-rd .knobs-rd-head[data-short] .knobs-rd-legend .knobs-rd-unit{display:none}
662
816
  .knobs-rd .knobs-rd-head[data-wrap]{flex-wrap:wrap;padding-bottom:4px}
663
- .knobs-rd .knobs-rd-head[data-wrap]>span:first-child{display:flex;align-items:center;min-height:var(--ku-row)}
817
+ .knobs-rd .knobs-rd-head[data-wrap]>span:first-child{display:flex;align-items:center;min-height:var(--_k-row)}
664
818
  .knobs-rd .knobs-rd-head[data-wrap]>:is(.knobs-rd-legend,.knobs-rd-tools){flex:1 0 100%;margin-left:0}
665
819
  .knobs-rd .knobs-rd-head[data-wrap]>.knobs-rd-tools{flex-wrap:wrap;row-gap:4px}
666
820
  .knobs-rd .knobs-rd-key{display:inline-flex;align-items:center;gap:5px;white-space:nowrap}
667
821
  .knobs-rd .knobs-rd-swatch{flex:none;width:8px;height:2px;border-radius:1px}
668
- .knobs-rd .knobs-rd-name{color:var(--ku-label)}
822
+ .knobs-rd .knobs-rd-name{color:var(--_k-fg-2)}
669
823
  .knobs-rd .knobs-rd-key>.knobs-rd-value{margin-left:2px}
670
824
  .knobs-rd .knobs-rd-plotbox{position:relative;outline:none;margin-bottom:6px}
671
825
  .knobs-rd .knobs-rd-plotbox>.knobs-rd-plot{position:absolute;inset:0;width:100%;height:100%;min-width:0}
672
- .knobs-rd .knobs-rd-tick,.knobs-rd .knobs-rd-mark{position:absolute;color:var(--ku-dim);pointer-events:none;line-height:14px;height:14px}
826
+ .knobs-rd .knobs-rd-tick,.knobs-rd .knobs-rd-mark{position:absolute;color:var(--_k-fg-3);pointer-events:none;line-height:14px;height:14px}
673
827
  .knobs-rd .knobs-rd-tick{left:0}
674
828
  .knobs-rd .knobs-rd-tick[data-at="top"]{top:-2px}
675
829
  .knobs-rd .knobs-rd-tick[data-at="bottom"]{bottom:0}
@@ -678,36 +832,36 @@ var readoutCss = `
678
832
 
679
833
  .knobs-rd .knobs-rd-grid{display:grid;column-gap:14px;align-items:center;outline:none;margin-bottom:4px}
680
834
  .knobs-rd .knobs-rd-tr{display:contents}
681
- .knobs-rd .knobs-rd-tr>*{height:calc(var(--ku-row) * .72);line-height:calc(var(--ku-row) * .72);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
682
- .knobs-rd .knobs-rd-thead>*{height:var(--ku-row);line-height:var(--ku-row)}
683
- .knobs-rd .knobs-rd-th{color:var(--ku-dim);text-align:right}
684
- .knobs-rd .knobs-rd-td{color:var(--ku-text)}
685
- .knobs-rd .knobs-rd-td:first-child{color:var(--ku-label)}
835
+ .knobs-rd .knobs-rd-tr>*{height:calc(var(--_k-row) * .72);line-height:calc(var(--_k-row) * .72);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
836
+ .knobs-rd .knobs-rd-thead>*{height:var(--_k-row);line-height:var(--_k-row)}
837
+ .knobs-rd .knobs-rd-th{color:var(--_k-fg-3);text-align:right}
838
+ .knobs-rd .knobs-rd-td{color:var(--_k-fg)}
839
+ .knobs-rd .knobs-rd-td:first-child{color:var(--_k-fg-2)}
686
840
  .knobs-rd .knobs-rd-td[data-num]{text-align:right}
687
841
 
688
842
  .knobs-rd.knobs-rd-log{--rd-lh:18px}
689
843
  .knobs-rd .knobs-rd-chips{display:inline-flex;align-items:center;gap:2px;margin-right:auto}
690
- .knobs-ui .knobs-rd-chip,.knobs-ui .knobs-rd-copy{height:calc(var(--ku-control-h) - 2px);padding:0 7px;border-radius:min(var(--ku-radius),5px);color:var(--ku-label);cursor:pointer;transition:background .15s,color .15s}
691
- .knobs-ui .knobs-rd-chip:hover,.knobs-ui .knobs-rd-copy:hover{background:var(--ku-wash);color:var(--ku-text)}
692
- .knobs-ui .knobs-rd-chip[aria-checked="true"]{background:var(--ku-wash-hi);color:var(--ku-text)}
693
- .knobs-ui .knobs-rd-find{width:84px;height:calc(var(--ku-control-h) - 2px);padding:0 7px;border-radius:min(var(--ku-radius),5px);
694
- background:color-mix(in srgb,var(--ku-surface-hi) 60%,transparent);color:var(--ku-text);caret-color:var(--ku-accent)}
695
- .knobs-rd .knobs-rd-find::placeholder{color:var(--ku-dim)}
844
+ .knobs-ui .knobs-rd-chip,.knobs-ui .knobs-rd-copy{height:calc(var(--_k-control-h) - 2px);padding:0 7px;border-radius:min(var(--_k-radius),5px);color:var(--_k-fg-2);cursor:pointer;transition:background .15s,color .15s}
845
+ .knobs-ui .knobs-rd-chip:hover,.knobs-ui .knobs-rd-copy:hover{background:var(--_ku-wash);color:var(--_k-fg)}
846
+ .knobs-ui .knobs-rd-chip[aria-checked="true"]{background:var(--_ku-wash-hi);color:var(--_k-fg)}
847
+ .knobs-ui .knobs-rd-find{width:84px;height:calc(var(--_k-control-h) - 2px);padding:0 7px;border-radius:min(var(--_k-radius),5px);
848
+ background:color-mix(in srgb,var(--_k-fill-selected) 60%,transparent);color:var(--_k-fg);caret-color:var(--_k-accent)}
849
+ .knobs-rd .knobs-rd-find::placeholder{color:var(--_k-fg-3)}
696
850
  .knobs-rd .knobs-rd-find::-webkit-search-cancel-button{display:none}
697
851
  .knobs-rd .knobs-rd-logbody{position:relative;margin-bottom:6px}
698
852
  .knobs-rd .knobs-rd-scroll{position:relative;overflow-x:hidden;overflow-y:auto;height:calc(var(--knobs-rd-lines,8) * var(--rd-lh));outline:none;
699
- background:color-mix(in srgb,var(--ku-surface-hi) 45%,transparent);border-radius:min(var(--ku-radius),6px);scrollbar-width:thin;overscroll-behavior:contain}
853
+ background:color-mix(in srgb,var(--_k-fill-selected) 45%,transparent);border-radius:min(var(--_k-radius),6px);scrollbar-width:thin;overscroll-behavior:contain}
700
854
  .knobs-rd .knobs-rd-space{position:relative;width:100%}
701
855
  .knobs-rd .knobs-rd-line{position:absolute;left:0;right:0;top:0;display:flex;gap:10px;height:var(--rd-lh);line-height:var(--rd-lh);padding:0 8px;contain:layout style;will-change:transform}
702
856
  .knobs-rd .knobs-rd-line[hidden]{display:none}
703
- .knobs-rd .knobs-rd-time{flex:none;color:var(--ku-dim)}
704
- .knobs-rd .knobs-rd-text{min-width:0;overflow:hidden;text-overflow:ellipsis;color:var(--ku-text)}
705
- .knobs-rd .knobs-rd-line[data-level="warn"]>.knobs-rd-text{color:var(--ku-warn)}
706
- .knobs-rd .knobs-rd-line[data-level="error"]>.knobs-rd-text{color:var(--ku-critical)}
707
- .knobs-rd .knobs-rd-line[data-level="debug"]>.knobs-rd-text{color:var(--ku-dim)}
708
- .knobs-ui .knobs-rd-match{color:var(--ku-accent)}
709
- .knobs-ui .knobs-rd-jump{position:absolute;left:50%;bottom:6px;height:20px;padding:0 10px;border-radius:calc(var(--ku-radius) * 999);
710
- background:var(--ku-accent);color:var(--ku-bg);opacity:0;transform:translate(-50%,6px);cursor:pointer;white-space:nowrap}
857
+ .knobs-rd .knobs-rd-time{flex:none;color:var(--_k-fg-3)}
858
+ .knobs-rd .knobs-rd-text{min-width:0;overflow:hidden;text-overflow:ellipsis;color:var(--_k-fg)}
859
+ .knobs-rd .knobs-rd-line[data-level="warn"]>.knobs-rd-text{color:var(--_k-warn)}
860
+ .knobs-rd .knobs-rd-line[data-level="error"]>.knobs-rd-text{color:var(--_k-danger)}
861
+ .knobs-rd .knobs-rd-line[data-level="debug"]>.knobs-rd-text{color:var(--_k-fg-3)}
862
+ .knobs-ui .knobs-rd-match{color:var(--_k-accent)}
863
+ .knobs-ui .knobs-rd-jump{position:absolute;left:50%;bottom:6px;height:20px;padding:0 10px;border-radius:calc(var(--_k-radius) * 999);
864
+ background:var(--_k-accent);color:var(--_k-bg);opacity:0;transform:translate(-50%,6px);cursor:pointer;white-space:nowrap}
711
865
 
712
866
  /* Under the GPU overlay the readouts' DOM stays for focus, hit-testing and screen readers; the
713
867
  overlay draws them. Their filter field sits above it. */
@@ -717,6 +871,1515 @@ var readoutCss = `
717
871
  @media(prefers-reduced-motion:reduce){.knobs-rd :where(*){transition:none!important}}
718
872
  `;
719
873
 
874
+ // src/tokens/color.ts
875
+ function linearToOklch([r, g, b, a]) {
876
+ const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);
877
+ const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);
878
+ const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);
879
+ const L = 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s;
880
+ const A = 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s;
881
+ const B = 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s;
882
+ const c = Math.hypot(A, B);
883
+ const h = c < 0.0000001 ? 0 : (Math.atan2(B, A) * 180 / Math.PI + 360) % 360;
884
+ return { l: L, c, h, alpha: a };
885
+ }
886
+ function oklchToLinear({ l: L, c, h, alpha = 1 }) {
887
+ const hr = h * Math.PI / 180;
888
+ const A = c * Math.cos(hr);
889
+ const B = c * Math.sin(hr);
890
+ const l = (L + 0.3963377774 * A + 0.2158037573 * B) ** 3;
891
+ const m = (L - 0.1055613458 * A - 0.0638541728 * B) ** 3;
892
+ const s = (L - 0.0894841775 * A - 1.291485548 * B) ** 3;
893
+ return [
894
+ 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,
895
+ -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,
896
+ -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s,
897
+ alpha
898
+ ];
899
+ }
900
+ function oklchToLinearInGamut(color) {
901
+ let rgb = oklchToLinear(color);
902
+ if (inGamut(rgb))
903
+ return clampRgba(rgb);
904
+ let lo = 0;
905
+ let hi = color.c;
906
+ for (let i = 0;i < 24; i++) {
907
+ const mid = (lo + hi) / 2;
908
+ rgb = oklchToLinear({ ...color, c: mid });
909
+ if (inGamut(rgb))
910
+ lo = mid;
911
+ else
912
+ hi = mid;
913
+ }
914
+ return clampRgba(oklchToLinear({ ...color, c: lo }));
915
+ }
916
+ function parseColor(input) {
917
+ const s = input.trim().toLowerCase();
918
+ if (s === "transparent")
919
+ return [0, 0, 0, 0];
920
+ if (s.startsWith("#")) {
921
+ let hex = s.slice(1);
922
+ if (hex.length === 3 || hex.length === 4)
923
+ hex = [...hex].map((ch) => ch + ch).join("");
924
+ if (!/^[0-9a-f]{6}([0-9a-f]{2})?$/.test(hex))
925
+ throw new Error(`Invalid colour: ${input}`);
926
+ const n = (i) => Number.parseInt(hex.slice(i, i + 2), 16) / 255;
927
+ return [toLinear(n(0)), toLinear(n(2)), toLinear(n(4)), hex.length === 8 ? n(6) : 1];
928
+ }
929
+ const fn = /^(oklch|rgba?)\(([^)]*)\)$/.exec(s);
930
+ if (!fn)
931
+ throw new Error(`Unsupported colour: ${input}`);
932
+ const parts = fn[2].split(/[\s,/]+/).filter(Boolean);
933
+ const num = (p, scale) => p === undefined ? 1 : p.endsWith("%") ? Number.parseFloat(p) / 100 : Number.parseFloat(p) / scale;
934
+ if (fn[1] === "oklch") {
935
+ const l = num(parts[0], 1);
936
+ return oklchToLinearInGamut({
937
+ l,
938
+ c: Number.parseFloat(parts[1]),
939
+ h: Number.parseFloat(parts[2]),
940
+ alpha: num(parts[3], 1)
941
+ });
942
+ }
943
+ return [
944
+ toLinear(num(parts[0], 255)),
945
+ toLinear(num(parts[1], 255)),
946
+ toLinear(num(parts[2], 255)),
947
+ num(parts[3], 1)
948
+ ];
949
+ }
950
+ function formatHex([r, g, b, a]) {
951
+ const rgb = `#${byte(toGamma(r))}${byte(toGamma(g))}${byte(toGamma(b))}`;
952
+ return a >= 0.9995 ? rgb : rgb + byte(a);
953
+ }
954
+ function withAlpha(input, alpha) {
955
+ const [r, g, b, a] = parseColor(input);
956
+ return formatHex([r, g, b, a * alpha]);
957
+ }
958
+ function over(top, bottom) {
959
+ const t = parseColor(top);
960
+ const b = parseColor(bottom);
961
+ const a = t[3];
962
+ const mix = (i) => toLinear(toGamma(t[i]) * a + toGamma(b[i]) * (1 - a));
963
+ return formatHex([mix(0), mix(1), mix(2), 1]);
964
+ }
965
+ function apcaY(input) {
966
+ const [r, g, b] = parseColor(input).map(toGamma);
967
+ return 0.2126729 * r ** 2.4 + 0.7151522 * g ** 2.4 + 0.072175 * b ** 2.4;
968
+ }
969
+ function apca(text, background) {
970
+ const bgOpaque = parseColor(background)[3] < 1 ? over(background, "#000") : background;
971
+ const fg = parseColor(text)[3] < 1 ? over(text, bgOpaque) : text;
972
+ const soft = (y) => y > 0.022 ? y : y + (0.022 - y) ** 1.414;
973
+ const yt = soft(apcaY(fg));
974
+ const yb = soft(apcaY(bgOpaque));
975
+ if (Math.abs(yb - yt) < 0.0005)
976
+ return 0;
977
+ if (yb > yt) {
978
+ const sapc = (yb ** 0.56 - yt ** 0.57) * 1.14;
979
+ return sapc < 0.1 ? 0 : (sapc - 0.027) * 100;
980
+ }
981
+ const sapc = (yb ** 0.65 - yt ** 0.62) * 1.14;
982
+ return sapc > -0.1 ? 0 : -(sapc + 0.027) * 100;
983
+ }
984
+ 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 ** (1 / 2.4) - 0.055, inGamut = ([r, g, b]) => [r, g, b].every((x) => x >= -0.00001 && x <= 1 + 0.00001), clampRgba = ([r, g, b, a]) => [clamp01(r), clamp01(g), clamp01(b), clamp01(a)], toOklch = (input) => linearToOklch(parseColor(input)), byte = (c) => Math.round(clamp01(c) * 255).toString(16).padStart(2, "0"), oklchToHex = (color) => formatHex(oklchToLinearInGamut(color)), normalize = (input) => formatHex(parseColor(input));
985
+
986
+ // src/tokens/schema.ts
987
+ var 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, TOKEN_BY_NAME, cssName = (t) => `${t.tier === "private" ? "--_k-" : "--k-"}${t.name}`, PROPERTY_TO_NAME, tokenForProperty = (property) => PROPERTY_TO_NAME.get(property), DEPRECATED;
988
+ var init_schema = __esm(() => {
989
+ theme = { from: "theme" };
990
+ TOKENS = [
991
+ {
992
+ name: "accent",
993
+ tier: "input",
994
+ type: "color",
995
+ group: "Accent",
996
+ source: theme,
997
+ doc: "The one accent: primary actions, handles, focus. Hover, soft and selection derive from it in CSS.",
998
+ deprecated: ["--ku-accent"]
999
+ },
1000
+ {
1001
+ name: "contrast",
1002
+ tier: "input",
1003
+ type: "number",
1004
+ group: "Inputs",
1005
+ source: theme,
1006
+ doc: "Contrast multiplier for fills and alpha borders (1 = default; the theme's 0–100 dial maps 50 → 1)."
1007
+ },
1008
+ {
1009
+ name: "radius",
1010
+ tier: "input",
1011
+ type: "length",
1012
+ group: "Shape",
1013
+ source: theme,
1014
+ doc: "Control corner radius. 0 squares everything, including capsules. Scales with density.",
1015
+ deprecated: ["--ku-radius"],
1016
+ resolve: "round(calc($ * (1 + (var(--_k-density) - 1) * 1.5)),2px)"
1017
+ },
1018
+ {
1019
+ name: "density",
1020
+ tier: "input",
1021
+ type: "number",
1022
+ group: "Size",
1023
+ source: theme,
1024
+ doc: "Size multiplier: compact .875, default 1, comfortable 1.1875."
1025
+ },
1026
+ {
1027
+ name: "font",
1028
+ tier: "input",
1029
+ type: "font",
1030
+ group: "Type",
1031
+ source: theme,
1032
+ doc: "UI font stack.",
1033
+ deprecated: ["--ku-font"]
1034
+ },
1035
+ {
1036
+ name: "mono",
1037
+ tier: "input",
1038
+ type: "font",
1039
+ group: "Type",
1040
+ source: theme,
1041
+ doc: "Monospace font stack.",
1042
+ deprecated: ["--ku-mono"]
1043
+ },
1044
+ {
1045
+ name: "bg-page",
1046
+ tier: "semantic",
1047
+ type: "color",
1048
+ group: "Surfaces",
1049
+ source: theme,
1050
+ doc: "The page behind panels; workspace backdrops.",
1051
+ deprecated: ["--k-page", "--ku-page"]
1052
+ },
1053
+ {
1054
+ name: "bg-inset",
1055
+ tier: "semantic",
1056
+ type: "color",
1057
+ group: "Surfaces",
1058
+ source: theme,
1059
+ doc: "Wells sunk into a panel: tracks, inputs, segmented backgrounds."
1060
+ },
1061
+ {
1062
+ name: "bg",
1063
+ tier: "semantic",
1064
+ type: "color",
1065
+ group: "Surfaces",
1066
+ source: theme,
1067
+ doc: "The panel surface.",
1068
+ deprecated: ["--ku-bg"]
1069
+ },
1070
+ {
1071
+ name: "bg-raised",
1072
+ tier: "semantic",
1073
+ type: "color",
1074
+ group: "Surfaces",
1075
+ source: theme,
1076
+ doc: "Raised within a panel: the active segment, cards on a panel."
1077
+ },
1078
+ {
1079
+ name: "bg-overlay",
1080
+ tier: "semantic",
1081
+ type: "color",
1082
+ group: "Surfaces",
1083
+ source: theme,
1084
+ doc: "Floating surfaces: menus, popovers, tooltips."
1085
+ },
1086
+ {
1087
+ name: "fill",
1088
+ tier: "semantic",
1089
+ type: "color",
1090
+ group: "Fills",
1091
+ source: css(alpha(5.5)),
1092
+ doc: "Resting fill for controls.",
1093
+ deprecated: ["--k-surface", "--ku-surface"]
1094
+ },
1095
+ {
1096
+ name: "fill-hover",
1097
+ tier: "semantic",
1098
+ type: "color",
1099
+ group: "Fills",
1100
+ source: css(alpha(8)),
1101
+ doc: "Hovered fill."
1102
+ },
1103
+ {
1104
+ name: "fill-selected",
1105
+ tier: "semantic",
1106
+ type: "color",
1107
+ group: "Fills",
1108
+ source: css(alpha(11)),
1109
+ doc: "Pressed or selected fill.",
1110
+ deprecated: ["--k-surface-hi", "--ku-surface-hi"]
1111
+ },
1112
+ {
1113
+ name: "fg",
1114
+ tier: "semantic",
1115
+ type: "color",
1116
+ group: "Foreground",
1117
+ source: theme,
1118
+ doc: "Primary text and icons (≥ Lc 90 on bg).",
1119
+ deprecated: ["--k-text", "--ku-text"]
1120
+ },
1121
+ {
1122
+ name: "fg-2",
1123
+ tier: "semantic",
1124
+ type: "color",
1125
+ group: "Foreground",
1126
+ source: theme,
1127
+ doc: "Secondary text: labels (≥ Lc 75).",
1128
+ deprecated: ["--k-label", "--ku-label"]
1129
+ },
1130
+ {
1131
+ name: "fg-3",
1132
+ tier: "semantic",
1133
+ type: "color",
1134
+ group: "Foreground",
1135
+ source: theme,
1136
+ doc: "Tertiary text: metadata, units, captions (≥ Lc 45).",
1137
+ deprecated: ["--k-dim", "--ku-dim"]
1138
+ },
1139
+ {
1140
+ name: "fg-4",
1141
+ tier: "semantic",
1142
+ type: "color",
1143
+ group: "Foreground",
1144
+ source: theme,
1145
+ doc: "Placeholder and disabled text (≥ Lc 30)."
1146
+ },
1147
+ {
1148
+ name: "border-subtle",
1149
+ tier: "semantic",
1150
+ type: "color",
1151
+ group: "Borders",
1152
+ source: css(alpha(6)),
1153
+ doc: "Hairline edges and dividers (below Lc 15 by design).",
1154
+ deprecated: ["--k-edge"]
1155
+ },
1156
+ {
1157
+ name: "border",
1158
+ tier: "semantic",
1159
+ type: "color",
1160
+ group: "Borders",
1161
+ source: css(alpha(10)),
1162
+ doc: "Default borders.",
1163
+ deprecated: ["--k-line", "--ku-line"]
1164
+ },
1165
+ {
1166
+ name: "border-strong",
1167
+ tier: "semantic",
1168
+ type: "color",
1169
+ group: "Borders",
1170
+ source: theme,
1171
+ doc: "Interactive edges (≥ Lc 15; solid).",
1172
+ deprecated: ["--k-line-hi", "--ku-line-hi"]
1173
+ },
1174
+ {
1175
+ name: "accent-hover",
1176
+ tier: "semantic",
1177
+ type: "color",
1178
+ group: "Accent",
1179
+ source: css("color-mix(in oklch,var(--k-accent) 90%,var(--k-bg))"),
1180
+ doc: "Hovered accent."
1181
+ },
1182
+ {
1183
+ name: "accent-soft",
1184
+ tier: "semantic",
1185
+ type: "color",
1186
+ group: "Accent",
1187
+ source: css("color-mix(in oklch,var(--k-accent) 15%,transparent)"),
1188
+ doc: "Accent tint behind accent content."
1189
+ },
1190
+ {
1191
+ name: "accent-fg",
1192
+ tier: "semantic",
1193
+ type: "color",
1194
+ group: "Accent",
1195
+ source: theme,
1196
+ doc: "Accent as text on bg (≥ Lc 60)."
1197
+ },
1198
+ {
1199
+ name: "on-accent",
1200
+ tier: "semantic",
1201
+ type: "color",
1202
+ group: "Accent",
1203
+ source: theme,
1204
+ doc: "Content placed on a solid accent."
1205
+ },
1206
+ { name: "ok", tier: "semantic", type: "color", group: "Status", source: theme, doc: "Success." },
1207
+ {
1208
+ name: "warn",
1209
+ tier: "semantic",
1210
+ type: "color",
1211
+ group: "Status",
1212
+ source: theme,
1213
+ doc: "Warning.",
1214
+ deprecated: ["--ku-warn"]
1215
+ },
1216
+ {
1217
+ name: "danger",
1218
+ tier: "semantic",
1219
+ type: "color",
1220
+ group: "Status",
1221
+ source: theme,
1222
+ doc: "Error, destructive. Put text on danger-soft rather than bare bg.",
1223
+ deprecated: ["--k-critical", "--ku-critical"]
1224
+ },
1225
+ {
1226
+ name: "info",
1227
+ tier: "semantic",
1228
+ type: "color",
1229
+ group: "Status",
1230
+ source: theme,
1231
+ doc: "Informational."
1232
+ },
1233
+ {
1234
+ name: "ok-soft",
1235
+ tier: "semantic",
1236
+ type: "color",
1237
+ group: "Status",
1238
+ source: css("color-mix(in oklch,var(--k-ok) 15%,transparent)"),
1239
+ doc: "Success tint."
1240
+ },
1241
+ {
1242
+ name: "warn-soft",
1243
+ tier: "semantic",
1244
+ type: "color",
1245
+ group: "Status",
1246
+ source: css("color-mix(in oklch,var(--k-warn) 15%,transparent)"),
1247
+ doc: "Warning tint."
1248
+ },
1249
+ {
1250
+ name: "danger-soft",
1251
+ tier: "semantic",
1252
+ type: "color",
1253
+ group: "Status",
1254
+ source: css("color-mix(in oklch,var(--k-danger) 15%,transparent)"),
1255
+ doc: "Danger tint."
1256
+ },
1257
+ {
1258
+ name: "info-soft",
1259
+ tier: "semantic",
1260
+ type: "color",
1261
+ group: "Status",
1262
+ source: css("color-mix(in oklch,var(--k-info) 15%,transparent)"),
1263
+ doc: "Info tint."
1264
+ },
1265
+ {
1266
+ name: "focus",
1267
+ tier: "semantic",
1268
+ type: "color",
1269
+ group: "Interaction",
1270
+ source: css("var(--k-accent)"),
1271
+ doc: "Focus ring colour (drawn as a 2px bg gap, then 2px of focus)."
1272
+ },
1273
+ {
1274
+ name: "selection",
1275
+ tier: "semantic",
1276
+ type: "color",
1277
+ group: "Interaction",
1278
+ source: css("color-mix(in oklch,var(--k-accent) 24%,transparent)"),
1279
+ doc: "Selected rows and ranges.",
1280
+ deprecated: ["--k-ui-select", "--ku-select"]
1281
+ },
1282
+ {
1283
+ name: "scrim",
1284
+ tier: "semantic",
1285
+ type: "color",
1286
+ group: "Interaction",
1287
+ source: theme,
1288
+ doc: "Dimming behind modal layers."
1289
+ },
1290
+ {
1291
+ name: "diff-add",
1292
+ tier: "semantic",
1293
+ type: "color",
1294
+ group: "Data",
1295
+ source: css("var(--k-ok)"),
1296
+ doc: "Added lines; line and word tints derive privately (12% / 38%)."
1297
+ },
1298
+ {
1299
+ name: "diff-del",
1300
+ tier: "semantic",
1301
+ type: "color",
1302
+ group: "Data",
1303
+ source: css("var(--k-danger)"),
1304
+ doc: "Deleted lines."
1305
+ },
1306
+ {
1307
+ name: "diff-mod",
1308
+ tier: "semantic",
1309
+ type: "color",
1310
+ group: "Data",
1311
+ source: css("var(--k-warn)"),
1312
+ doc: "Modified lines."
1313
+ },
1314
+ {
1315
+ name: "series-1",
1316
+ tier: "semantic",
1317
+ type: "color",
1318
+ group: "Data",
1319
+ source: theme,
1320
+ doc: "Chart series 1."
1321
+ },
1322
+ {
1323
+ name: "series-2",
1324
+ tier: "semantic",
1325
+ type: "color",
1326
+ group: "Data",
1327
+ source: theme,
1328
+ doc: "Chart series 2."
1329
+ },
1330
+ {
1331
+ name: "series-3",
1332
+ tier: "semantic",
1333
+ type: "color",
1334
+ group: "Data",
1335
+ source: theme,
1336
+ doc: "Chart series 3."
1337
+ },
1338
+ {
1339
+ name: "series-4",
1340
+ tier: "semantic",
1341
+ type: "color",
1342
+ group: "Data",
1343
+ source: theme,
1344
+ doc: "Chart series 4."
1345
+ },
1346
+ {
1347
+ name: "series-5",
1348
+ tier: "semantic",
1349
+ type: "color",
1350
+ group: "Data",
1351
+ source: theme,
1352
+ doc: "Chart series 5."
1353
+ },
1354
+ {
1355
+ name: "series-6",
1356
+ tier: "semantic",
1357
+ type: "color",
1358
+ group: "Data",
1359
+ source: theme,
1360
+ doc: "Chart series 6."
1361
+ },
1362
+ {
1363
+ name: "radius-panel",
1364
+ tier: "semantic",
1365
+ type: "length",
1366
+ group: "Shape",
1367
+ source: css("calc(var(--k-radius) + var(--k-unit))"),
1368
+ doc: "Panel and card radius, concentric with controls.",
1369
+ deprecated: ["--k-panel-radius", "--ku-panel-radius"]
1370
+ },
1371
+ {
1372
+ name: "round",
1373
+ tier: "semantic",
1374
+ type: "length",
1375
+ group: "Shape",
1376
+ source: css("calc(var(--k-radius) * 999)"),
1377
+ doc: "Capsule radius that squares when --k-radius is 0. Use instead of 999px."
1378
+ },
1379
+ {
1380
+ name: "unit",
1381
+ tier: "semantic",
1382
+ type: "length",
1383
+ group: "Size",
1384
+ source: value("4px"),
1385
+ doc: "The spacing unit."
1386
+ },
1387
+ {
1388
+ name: "row",
1389
+ tier: "semantic",
1390
+ type: "length",
1391
+ group: "Size",
1392
+ source: css("round(calc(32px * var(--k-density)),2px)"),
1393
+ doc: "Row height.",
1394
+ deprecated: ["--ku-row"]
1395
+ },
1396
+ {
1397
+ name: "width",
1398
+ tier: "semantic",
1399
+ type: "length",
1400
+ group: "Size",
1401
+ source: value("288px"),
1402
+ doc: "Panel width."
1403
+ },
1404
+ {
1405
+ name: "font-size",
1406
+ tier: "semantic",
1407
+ type: "length",
1408
+ group: "Type",
1409
+ source: css("round(calc(12px * (1 + (var(--k-density) - 1) * .5)),1px)"),
1410
+ doc: "Body size; a 5-step scale derives privately.",
1411
+ deprecated: ["--ku-font-size"]
1412
+ },
1413
+ {
1414
+ name: "value-font",
1415
+ tier: "semantic",
1416
+ type: "font",
1417
+ group: "Type",
1418
+ source: css("var(--k-font)"),
1419
+ doc: "Font for readouts and values (labPreset: mono).",
1420
+ deprecated: ["--ku-value-font"]
1421
+ },
1422
+ {
1423
+ name: "shadow-raised",
1424
+ tier: "semantic",
1425
+ type: "shadow",
1426
+ group: "Material",
1427
+ source: theme,
1428
+ doc: "Small lift for raised controls.",
1429
+ deprecated: ["--k-lift-shadow"]
1430
+ },
1431
+ {
1432
+ name: "shadow-overlay",
1433
+ tier: "semantic",
1434
+ type: "shadow",
1435
+ group: "Material",
1436
+ source: theme,
1437
+ doc: "Floating panels, menus, popovers.",
1438
+ deprecated: ["--k-shadow", "--ku-shadow"]
1439
+ },
1440
+ {
1441
+ name: "glass",
1442
+ tier: "semantic",
1443
+ type: "number",
1444
+ group: "Material",
1445
+ source: theme,
1446
+ doc: "Backdrop glass amount (0 = opaque)."
1447
+ },
1448
+ {
1449
+ name: "glow",
1450
+ tier: "semantic",
1451
+ type: "number",
1452
+ group: "Material",
1453
+ source: theme,
1454
+ doc: "Specular glow amount."
1455
+ },
1456
+ {
1457
+ name: "rim",
1458
+ tier: "semantic",
1459
+ type: "color",
1460
+ group: "Material",
1461
+ source: theme,
1462
+ doc: "Top-edge highlight hairline.",
1463
+ deprecated: ["--ku-rim"]
1464
+ },
1465
+ {
1466
+ name: "spring",
1467
+ tier: "semantic",
1468
+ type: "spring",
1469
+ group: "Motion",
1470
+ source: value("0.3 0"),
1471
+ doc: "Default spring as `duration bounce` (the motion module's `default`)."
1472
+ },
1473
+ {
1474
+ name: "hover-in",
1475
+ tier: "semantic",
1476
+ type: "number",
1477
+ group: "Motion",
1478
+ source: value("0"),
1479
+ doc: "Hover wash fade-in, unitless milliseconds.",
1480
+ deprecated: ["--ku-hover-in"]
1481
+ },
1482
+ {
1483
+ name: "hover-out",
1484
+ tier: "semantic",
1485
+ type: "number",
1486
+ group: "Motion",
1487
+ source: value("120"),
1488
+ doc: "Hover wash fade-out, unitless milliseconds.",
1489
+ deprecated: ["--ku-hover-out"]
1490
+ },
1491
+ {
1492
+ name: "z",
1493
+ tier: "semantic",
1494
+ type: "integer",
1495
+ group: "Motion",
1496
+ source: value("2147480000"),
1497
+ doc: "Base of knobs' stacking ladder; layers add small offsets."
1498
+ },
1499
+ {
1500
+ name: "slider-track",
1501
+ tier: "hook",
1502
+ type: "color",
1503
+ group: "Hooks",
1504
+ source: css("var(--k-fill)"),
1505
+ doc: "Slider track."
1506
+ },
1507
+ {
1508
+ name: "slider-fill",
1509
+ tier: "hook",
1510
+ type: "color",
1511
+ group: "Hooks",
1512
+ source: css("color-mix(in oklch,var(--k-accent) 20%,var(--k-fill-selected))"),
1513
+ doc: "Slider value fill.",
1514
+ deprecated: ["--k-fill-rest"]
1515
+ },
1516
+ {
1517
+ name: "slider-handle",
1518
+ tier: "hook",
1519
+ type: "color",
1520
+ group: "Hooks",
1521
+ source: css("var(--k-accent)"),
1522
+ doc: "Slider handle and range thumbs.",
1523
+ deprecated: ["--k-handle"]
1524
+ },
1525
+ {
1526
+ name: "toggle-thumb-off",
1527
+ tier: "hook",
1528
+ type: "color",
1529
+ group: "Hooks",
1530
+ source: css("#ffffff"),
1531
+ doc: "A switch's thumb while off, and the ring around colour and gradient thumbs.",
1532
+ deprecated: ["--k-thumb"]
1533
+ },
1534
+ {
1535
+ name: "toggle-track",
1536
+ tier: "hook",
1537
+ type: "color",
1538
+ group: "Hooks",
1539
+ source: css("var(--k-fill-selected)"),
1540
+ doc: "Toggle track, off."
1541
+ },
1542
+ {
1543
+ name: "toggle-track-on",
1544
+ tier: "hook",
1545
+ type: "color",
1546
+ group: "Hooks",
1547
+ source: css("var(--k-accent)"),
1548
+ doc: "Toggle track, on."
1549
+ },
1550
+ {
1551
+ name: "toggle-thumb",
1552
+ tier: "hook",
1553
+ type: "color",
1554
+ group: "Hooks",
1555
+ source: css("var(--k-on-accent)"),
1556
+ doc: "Toggle thumb."
1557
+ },
1558
+ {
1559
+ name: "segmented-track",
1560
+ tier: "hook",
1561
+ type: "color",
1562
+ group: "Hooks",
1563
+ source: css("var(--k-bg-inset)"),
1564
+ doc: "Segmented control background.",
1565
+ deprecated: ["--k-seg-bg", "--ku-seg-bg"]
1566
+ },
1567
+ {
1568
+ name: "segmented-active",
1569
+ tier: "hook",
1570
+ type: "color",
1571
+ group: "Hooks",
1572
+ source: css("var(--k-bg-raised)"),
1573
+ doc: "Active segment.",
1574
+ deprecated: ["--k-seg-active"]
1575
+ },
1576
+ {
1577
+ name: "timeline-playhead",
1578
+ tier: "hook",
1579
+ type: "color",
1580
+ group: "Hooks",
1581
+ source: css("var(--k-accent)"),
1582
+ doc: "Timeline playhead."
1583
+ },
1584
+ {
1585
+ name: "split-gutter",
1586
+ tier: "hook",
1587
+ type: "color",
1588
+ group: "Hooks",
1589
+ source: css("var(--k-border-subtle)"),
1590
+ doc: "Split pane divider.",
1591
+ deprecated: ["--k-ui-divider", "--ku-divider"]
1592
+ },
1593
+ {
1594
+ name: "compare-divider",
1595
+ tier: "hook",
1596
+ type: "color",
1597
+ group: "Hooks",
1598
+ source: css("var(--k-fg)"),
1599
+ doc: "Before/after divider line.",
1600
+ deprecated: ["--k-compare-line"]
1601
+ },
1602
+ {
1603
+ name: "compare-stage",
1604
+ tier: "hook",
1605
+ type: "color",
1606
+ group: "Hooks",
1607
+ source: css("var(--k-fill)"),
1608
+ doc: "Compare stage background."
1609
+ },
1610
+ {
1611
+ name: "activity-rail",
1612
+ tier: "hook",
1613
+ type: "color",
1614
+ group: "Hooks",
1615
+ source: css("var(--k-border-strong)"),
1616
+ doc: "Activity rail line.",
1617
+ deprecated: ["--k-activity-line"]
1618
+ },
1619
+ {
1620
+ name: "picker-card",
1621
+ tier: "hook",
1622
+ type: "color",
1623
+ group: "Hooks",
1624
+ source: css("var(--k-fill)"),
1625
+ doc: "Picker card."
1626
+ },
1627
+ {
1628
+ name: "pane-bg",
1629
+ tier: "hook",
1630
+ type: "color",
1631
+ group: "Hooks",
1632
+ source: css("var(--k-bg)"),
1633
+ doc: "knobs/ui pane card.",
1634
+ deprecated: ["--k-ui-pane", "--ku-pane-bg"]
1635
+ },
1636
+ {
1637
+ name: "button-bg",
1638
+ tier: "hook",
1639
+ type: "color",
1640
+ group: "Hooks",
1641
+ source: css("var(--k-fill)"),
1642
+ doc: "Button fill."
1643
+ },
1644
+ {
1645
+ name: "button-border",
1646
+ tier: "hook",
1647
+ type: "color",
1648
+ group: "Hooks",
1649
+ source: css("transparent"),
1650
+ doc: "Button border.",
1651
+ deprecated: ["--k-button-line"]
1652
+ },
1653
+ {
1654
+ name: "button-fg",
1655
+ tier: "hook",
1656
+ type: "color",
1657
+ group: "Hooks",
1658
+ source: css("var(--k-fg)"),
1659
+ doc: "Button text.",
1660
+ deprecated: ["--k-button-color"]
1661
+ },
1662
+ {
1663
+ name: "row-hover",
1664
+ tier: "hook",
1665
+ type: "color",
1666
+ group: "Hooks",
1667
+ source: css("color-mix(in oklch,var(--k-fill) 50%,transparent)"),
1668
+ doc: "Row hover wash."
1669
+ },
1670
+ {
1671
+ name: "group-label",
1672
+ tier: "hook",
1673
+ type: "color",
1674
+ group: "Hooks",
1675
+ source: css("var(--k-fg-3)"),
1676
+ doc: "Folder and group headings.",
1677
+ deprecated: ["--k-group-ink", "--k-group-color"]
1678
+ },
1679
+ {
1680
+ name: "modified",
1681
+ tier: "hook",
1682
+ type: "color",
1683
+ group: "Hooks",
1684
+ source: css("var(--k-fg-3)"),
1685
+ doc: "Marker for values changed from their default."
1686
+ },
1687
+ {
1688
+ name: "tray-pad",
1689
+ tier: "private",
1690
+ type: "length",
1691
+ group: "Private",
1692
+ source: css("calc(var(--k-unit) * .5)"),
1693
+ doc: "Padding inside a tray around its controls.",
1694
+ deprecated: ["--k-tray-pad"]
1695
+ },
1696
+ {
1697
+ name: "pad",
1698
+ tier: "private",
1699
+ type: "length",
1700
+ group: "Private",
1701
+ source: css("round(calc(10px * var(--k-density)),2px)"),
1702
+ doc: "Panel padding.",
1703
+ deprecated: ["--k-pad"]
1704
+ },
1705
+ {
1706
+ name: "inset",
1707
+ tier: "private",
1708
+ type: "length",
1709
+ group: "Private",
1710
+ source: css("var(--_k-pad)"),
1711
+ doc: "Row content inset.",
1712
+ deprecated: ["--k-inset", "--ku-inset"]
1713
+ },
1714
+ {
1715
+ name: "gap",
1716
+ tier: "private",
1717
+ type: "length",
1718
+ group: "Private",
1719
+ source: css("round(calc(var(--k-unit) * (1 + (var(--k-density) - 1) * 2.5)),1px)"),
1720
+ doc: "Gap between rows.",
1721
+ deprecated: ["--k-gap"]
1722
+ },
1723
+ {
1724
+ name: "radius-md",
1725
+ tier: "private",
1726
+ type: "length",
1727
+ group: "Private",
1728
+ source: css("max(0px,calc(var(--k-radius) - var(--_k-tray-pad)))"),
1729
+ doc: "Concentric radius one tray in.",
1730
+ deprecated: ["--k-radius-md"]
1731
+ },
1732
+ {
1733
+ name: "radius-sm",
1734
+ tier: "private",
1735
+ type: "length",
1736
+ group: "Private",
1737
+ source: css("max(0px,calc(var(--k-radius) - var(--_k-tray-pad) * 2))"),
1738
+ doc: "Concentric radius two trays in.",
1739
+ deprecated: ["--k-radius-sm"]
1740
+ },
1741
+ {
1742
+ name: "control-h",
1743
+ tier: "private",
1744
+ type: "length",
1745
+ group: "Private",
1746
+ source: css("calc(var(--k-row) - var(--k-unit) * 2)"),
1747
+ doc: "Control height inside a row.",
1748
+ deprecated: ["--k-control-h", "--ku-control-h"]
1749
+ },
1750
+ {
1751
+ name: "value-size",
1752
+ tier: "private",
1753
+ type: "length",
1754
+ group: "Private",
1755
+ source: css("calc(var(--k-font-size) - .5px)"),
1756
+ doc: "Readout size.",
1757
+ deprecated: ["--k-value-size", "--ku-value-size"]
1758
+ },
1759
+ {
1760
+ name: "text-title",
1761
+ tier: "private",
1762
+ type: "length",
1763
+ group: "Private",
1764
+ source: css("calc(var(--k-font-size) + 1px)"),
1765
+ doc: "Type scale: titles.",
1766
+ deprecated: ["--k-text-title"]
1767
+ },
1768
+ {
1769
+ name: "text-body",
1770
+ tier: "private",
1771
+ type: "length",
1772
+ group: "Private",
1773
+ source: css("var(--k-font-size)"),
1774
+ doc: "Type scale: body.",
1775
+ deprecated: ["--k-text-body"]
1776
+ },
1777
+ {
1778
+ name: "text-control",
1779
+ tier: "private",
1780
+ type: "length",
1781
+ group: "Private",
1782
+ source: css("calc(var(--k-font-size) - .5px)"),
1783
+ doc: "Type scale: controls.",
1784
+ deprecated: ["--k-text-control"]
1785
+ },
1786
+ {
1787
+ name: "text-meta",
1788
+ tier: "private",
1789
+ type: "length",
1790
+ group: "Private",
1791
+ source: css("calc(var(--k-font-size) - 1px)"),
1792
+ doc: "Type scale: metadata.",
1793
+ deprecated: ["--k-text-meta", "--ku-text-meta"]
1794
+ },
1795
+ {
1796
+ name: "text-cap",
1797
+ tier: "private",
1798
+ type: "length",
1799
+ group: "Private",
1800
+ source: css("calc(var(--k-font-size) - 2px)"),
1801
+ doc: "Type scale: caps and captions.",
1802
+ deprecated: ["--k-text-cap"]
1803
+ },
1804
+ {
1805
+ name: "weight",
1806
+ tier: "private",
1807
+ type: "number",
1808
+ group: "Private",
1809
+ source: value("400"),
1810
+ doc: "Body weight.",
1811
+ deprecated: ["--k-font-weight", "--ku-font-weight"]
1812
+ },
1813
+ {
1814
+ name: "weight-label",
1815
+ tier: "private",
1816
+ type: "number",
1817
+ group: "Private",
1818
+ source: value("500"),
1819
+ doc: "Label weight.",
1820
+ deprecated: ["--k-label-weight", "--ku-label-weight"]
1821
+ },
1822
+ {
1823
+ name: "weight-title",
1824
+ tier: "private",
1825
+ type: "number",
1826
+ group: "Private",
1827
+ source: value("600"),
1828
+ doc: "Title weight.",
1829
+ deprecated: ["--k-title-weight", "--ku-title-weight"]
1830
+ },
1831
+ {
1832
+ name: "focus-ring",
1833
+ tier: "private",
1834
+ type: "shadow",
1835
+ group: "Private",
1836
+ source: css("0 0 0 2px var(--k-bg),0 0 0 4px var(--k-focus)"),
1837
+ doc: "Two-layer focus ring: a bg gap, then the focus colour."
1838
+ },
1839
+ {
1840
+ name: "diff-add-line",
1841
+ tier: "private",
1842
+ type: "color",
1843
+ group: "Private",
1844
+ source: css("color-mix(in oklch,var(--k-diff-add) 12%,transparent)"),
1845
+ doc: "Added line tint."
1846
+ },
1847
+ {
1848
+ name: "diff-add-word",
1849
+ tier: "private",
1850
+ type: "color",
1851
+ group: "Private",
1852
+ source: css("color-mix(in oklch,var(--k-diff-add) 38%,transparent)"),
1853
+ doc: "Added word tint."
1854
+ },
1855
+ {
1856
+ name: "diff-del-line",
1857
+ tier: "private",
1858
+ type: "color",
1859
+ group: "Private",
1860
+ source: css("color-mix(in oklch,var(--k-diff-del) 12%,transparent)"),
1861
+ doc: "Deleted line tint."
1862
+ },
1863
+ {
1864
+ name: "diff-del-word",
1865
+ tier: "private",
1866
+ type: "color",
1867
+ group: "Private",
1868
+ source: css("color-mix(in oklch,var(--k-diff-del) 38%,transparent)"),
1869
+ doc: "Deleted word tint."
1870
+ },
1871
+ {
1872
+ name: "diff-mod-line",
1873
+ tier: "private",
1874
+ type: "color",
1875
+ group: "Private",
1876
+ source: css("color-mix(in oklch,var(--k-diff-mod) 12%,transparent)"),
1877
+ doc: "Modified line tint."
1878
+ },
1879
+ {
1880
+ name: "diff-mod-word",
1881
+ tier: "private",
1882
+ type: "color",
1883
+ group: "Private",
1884
+ source: css("color-mix(in oklch,var(--k-diff-mod) 38%,transparent)"),
1885
+ doc: "Modified word tint."
1886
+ }
1887
+ ];
1888
+ TOKEN_BY_NAME = new Map(TOKENS.map((t) => [t.name, t]));
1889
+ PROPERTY_TO_NAME = new Map(TOKENS.map((t) => [cssName(t), t.name]));
1890
+ DEPRECATED = new Map(TOKENS.flatMap((t) => (t.deprecated ?? []).map((old) => [old, cssName(t)])));
1891
+ });
1892
+
1893
+ // src/tokens/css.ts
1894
+ function pair(def, dark, light) {
1895
+ if (dark === undefined && light === undefined)
1896
+ return;
1897
+ if (dark === undefined || light === undefined || dark === light || def.type !== "color")
1898
+ return dark ?? light;
1899
+ return `light-dark(${light},${dark})`;
1900
+ }
1901
+ function declaredValue(theme, def) {
1902
+ const name = def.name;
1903
+ const dark = theme.declared.dark[name];
1904
+ const light = theme.declared.light[name];
1905
+ if (def.type === "color" && dark === undefined !== (light === undefined))
1906
+ return pair(def, dark ?? theme.dark[name], light ?? theme.light[name]);
1907
+ return pair(def, dark, light);
1908
+ }
1909
+ function resolver(def) {
1910
+ const reads = [...def.deprecated ?? []];
1911
+ if (def.tier !== "private")
1912
+ reads.push(cssName(def));
1913
+ const source = def.source;
1914
+ const fallback = "css" in source ? privately(source.css) : ("value" in source) && def.tier === "private" ? source.value : undefined;
1915
+ let out = fallback ?? "";
1916
+ for (let i = reads.length - 1;i >= 0; i--)
1917
+ out = out === "" ? `var(${reads[i]})` : `var(${reads[i]},${out})`;
1918
+ return def.resolve ? privately(def.resolve).replaceAll("$", out) : out;
1919
+ }
1920
+ function tokensCss(theme) {
1921
+ const root = [];
1922
+ const resolved = [];
1923
+ for (const def of TOKENS) {
1924
+ const source = def.source;
1925
+ const own = declaredValue(theme, def) ?? ("from" in source ? "" : ("value" in source) && def.tier !== "private" ? source.value : undefined);
1926
+ if (own !== undefined && def.tier !== "private")
1927
+ root.push(`${cssName(def)}:${own}`);
1928
+ resolved.push(`--_k-${def.name}:${resolver(def)}`);
1929
+ }
1930
+ return `@layer knobs.tokens{
1931
+ :where(:root,:host){${root.join(";")}}
1932
+ :where(.knobs-root){${resolved.join(";")}}
1933
+ ${APPEARANCE_CSS}
1934
+ }`;
1935
+ }
1936
+ function themeCss(theme, selector) {
1937
+ const decls = [];
1938
+ for (const def of TOKENS) {
1939
+ const own = declaredValue(theme, def);
1940
+ if (own !== undefined)
1941
+ decls.push(`${cssName(def)}:${own}`);
1942
+ }
1943
+ return `@layer knobs.tokens{${selector}{${decls.join(";")}}}`;
1944
+ }
1945
+ var SCHEMES, APPEARANCE_CSS, privately = (css) => css.replace(/var\(--k-([a-z0-9-]+)/g, (m, name) => tokenForProperty(`--k-${name}`) ? `var(--_k-${name}` : m);
1946
+ var init_css = __esm(() => {
1947
+ init_schema();
1948
+ SCHEMES = [
1949
+ [":where(.knobs-root)", "light dark"],
1950
+ [
1951
+ ':where(.dark,.dark-theme,[data-theme="dark"],[data-appearance="dark"],[data-knobs-theme="dark"]) :where(.knobs-root)',
1952
+ "dark"
1953
+ ],
1954
+ [
1955
+ ':where(.light,.light-theme,[data-theme="light"],[data-appearance="light"],[data-knobs-theme="light"]) :where(.knobs-root)',
1956
+ "light"
1957
+ ],
1958
+ [":where(.knobs-root) :where(.knobs-root:not([data-appearance]))", "inherit"],
1959
+ [':where(.knobs-root[data-appearance="dark"])', "dark"],
1960
+ [':where(.knobs-root[data-appearance="light"])', "light"],
1961
+ [':where(.knobs-root[data-appearance="system"])', "light dark"],
1962
+ [':where(.knobs-root[data-appearance="inherit"])', "inherit"]
1963
+ ];
1964
+ APPEARANCE_CSS = SCHEMES.map(([selector, scheme]) => {
1965
+ const light = scheme === "light" ? "1" : scheme === "inherit" ? "inherit" : "0";
1966
+ const rule = `${selector}{color-scheme:${scheme};--_k-light:${light}}`;
1967
+ return scheme === "light dark" ? `${rule}
1968
+ @media(prefers-color-scheme:light){${selector}{--_k-light:1}}` : rule;
1969
+ }).join(`
1970
+ `);
1971
+ });
1972
+
1973
+ // src/tokens/evaluate.ts
1974
+ function splitTop(s) {
1975
+ const out = [];
1976
+ let depth = 0;
1977
+ let start = 0;
1978
+ for (let i = 0;i < s.length; i++) {
1979
+ const ch = s[i];
1980
+ if (ch === "(")
1981
+ depth++;
1982
+ else if (ch === ")")
1983
+ depth--;
1984
+ else if (ch === "," && depth === 0) {
1985
+ out.push(s.slice(start, i).trim());
1986
+ start = i + 1;
1987
+ }
1988
+ }
1989
+ out.push(s.slice(start).trim());
1990
+ return out;
1991
+ }
1992
+ function evaluate(input, lookup) {
1993
+ const s = input.trim();
1994
+ const v = call(s, "var");
1995
+ if (v !== undefined) {
1996
+ const [name, ...fallback] = splitTop(v);
1997
+ const value = lookup(name);
1998
+ if (value !== undefined)
1999
+ return evaluate(value, lookup);
2000
+ if (fallback.length)
2001
+ return evaluate(fallback.join(","), lookup);
2002
+ throw new Error(`Unresolved ${name}`);
2003
+ }
2004
+ const mix = call(s, "color-mix");
2005
+ if (mix !== undefined)
2006
+ return colorMix(mix, lookup);
2007
+ return normalize(s);
2008
+ }
2009
+ function percent(s, lookup) {
2010
+ const c = call(s, "calc");
2011
+ if (c === undefined)
2012
+ return Number.parseFloat(s) / 100;
2013
+ const [a, b] = c.split("*").map((x) => x.trim());
2014
+ const num = (x) => {
2015
+ const inner = call(x, "var");
2016
+ if (inner !== undefined)
2017
+ return Number.parseFloat(lookup(splitTop(inner)[0]) ?? Number.NaN.toString());
2018
+ return x.endsWith("%") ? Number.parseFloat(x) / 100 : Number.parseFloat(x);
2019
+ };
2020
+ const out = num(a) * num(b);
2021
+ if (!Number.isFinite(out))
2022
+ throw new Error(`Bad percentage: ${s}`);
2023
+ return out;
2024
+ }
2025
+ function stop(s, lookup) {
2026
+ const m = /^(.*?)\s+((?:calc\(.*\))|(?:[\d.]+%))$/.exec(s);
2027
+ if (!m)
2028
+ return { color: evaluate(s, lookup) };
2029
+ return { color: evaluate(m[1], lookup), p: percent(m[2], lookup) };
2030
+ }
2031
+ function colorMix(args, lookup) {
2032
+ const [space, a, b] = splitTop(args);
2033
+ if (space !== "in oklch")
2034
+ throw new Error(`Only color-mix(in oklch, …) is supported, got ${space}`);
2035
+ const x = stop(a, lookup);
2036
+ const y = stop(b, lookup);
2037
+ let p1 = x.p ?? (y.p === undefined ? 0.5 : 1 - y.p);
2038
+ let p2 = y.p ?? 1 - p1;
2039
+ const sum = p1 + p2;
2040
+ const scale = sum < 1 ? sum : 1;
2041
+ p1 /= sum;
2042
+ p2 /= sum;
2043
+ const ca = linearToOklch(parseColor(x.color));
2044
+ const cb = linearToOklch(parseColor(y.color));
2045
+ const a1 = ca.alpha ?? 1;
2046
+ const a2 = cb.alpha ?? 1;
2047
+ const alpha = a1 * p1 + a2 * p2;
2048
+ if (alpha <= 0)
2049
+ return "#00000000";
2050
+ const powerless = (c, alpha) => c.c < 0.0002 || alpha === 0;
2051
+ const h1 = powerless(ca, a1) ? cb.h : ca.h;
2052
+ const h2 = powerless(cb, a2) ? h1 : cb.h;
2053
+ let dh = h2 - h1;
2054
+ if (dh > 180)
2055
+ dh -= 360;
2056
+ if (dh < -180)
2057
+ dh += 360;
2058
+ const pre = (u, v) => (u * a1 * p1 + v * a2 * p2) / alpha;
2059
+ const rgb = oklchToLinear({
2060
+ l: pre(ca.l, cb.l),
2061
+ c: pre(ca.c, cb.c),
2062
+ h: (h1 + dh * p2 + 360) % 360
2063
+ });
2064
+ return formatHex([rgb[0], rgb[1], rgb[2], alpha * scale]);
2065
+ }
2066
+ var call = (s, fn) => s.startsWith(`${fn}(`) && s.endsWith(")") ? s.slice(fn.length + 1, -1) : undefined;
2067
+ var init_evaluate = () => {};
2068
+
2069
+ // src/themes/define.ts
2070
+ function fontStack(family, fallback) {
2071
+ if (family.includes(","))
2072
+ return family;
2073
+ const quoted = /\s/.test(family) && !/^["']/.test(family) ? `"${family}"` : family;
2074
+ return family === fallback ? family : `${quoted},${fallback}`;
2075
+ }
2076
+ function mergeInputs(parent, spec) {
2077
+ return {
2078
+ gray: { ...parent.gray, ...spec.gray },
2079
+ accent: spec.accent ?? parent.accent,
2080
+ contrast: spec.contrast ?? parent.contrast,
2081
+ radius: spec.radius ?? parent.radius,
2082
+ density: spec.density ?? parent.density,
2083
+ material: spec.material ?? parent.material,
2084
+ font: {
2085
+ sans: spec.font?.sans ? fontStack(spec.font.sans, DEFAULT_SANS) : parent.font.sans,
2086
+ mono: spec.font?.mono ? fontStack(spec.font.mono, DEFAULT_MONO) : parent.font.mono
2087
+ },
2088
+ tokens: {
2089
+ dark: { ...parent.tokens.dark, ...spec.tokens?.dark },
2090
+ light: { ...parent.tokens.light, ...spec.tokens?.light }
2091
+ }
2092
+ };
2093
+ }
2094
+ function meet(l, floor, bg, away, make) {
2095
+ let x = l;
2096
+ while (apca(make(x), bg) < floor + 0.5 && x >= 0 && x <= 100)
2097
+ x += away * 0.25;
2098
+ return make(Math.min(100, Math.max(0, x)));
2099
+ }
2100
+ function solve(target, bg, away, make) {
2101
+ let near = toOklch(bg).l * 100;
2102
+ let far = away > 0 ? 100 : 0;
2103
+ if (apca(make(far), bg) <= target)
2104
+ return far;
2105
+ for (let i = 0;i < 30; i++) {
2106
+ const mid = (near + far) / 2;
2107
+ if (apca(make(mid), bg) < target)
2108
+ near = mid;
2109
+ else
2110
+ far = mid;
2111
+ }
2112
+ return far;
2113
+ }
2114
+ function accentPair(inputs) {
2115
+ if (typeof inputs.accent !== "string")
2116
+ return { ...inputs.accent };
2117
+ const dark = inputs.accent;
2118
+ const o = toOklch(dark);
2119
+ const 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 });
2120
+ return { dark, light };
2121
+ }
2122
+ function generate(inputs, appearance, accent) {
2123
+ const m = contrastMultiplier(inputs.contrast);
2124
+ const { hue, chroma } = inputs.gray;
2125
+ const neutral = (l, tint) => oklchToHex({ l: l / 100, c: chroma * tint, h: hue });
2126
+ const user = inputs.tokens[appearance];
2127
+ const out = {};
2128
+ const surfaces = SURFACES[appearance];
2129
+ for (const [role, l] of Object.entries(surfaces)) {
2130
+ const spread = surfaces.bg + (l - surfaces.bg) * m;
2131
+ out[role] = user[role] ?? neutral(Math.min(100, Math.max(0, spread)), TINT.surface[appearance]);
2132
+ }
2133
+ const bg = out.bg;
2134
+ const away = appearance === "dark" ? 1 : -1;
2135
+ const inkSpread = 1 + (m - 1) * 0.4;
2136
+ for (const [role, target] of Object.entries(INKS[appearance])) {
2137
+ const tint = role === "fg" ? TINT.fg : role === "border-strong" ? TINT.border : TINT.ink;
2138
+ const make = (x) => neutral(x, tint);
2139
+ const l = solve(target * inkSpread, bg, away, make);
2140
+ out[role] = meet(l, APCA_BUDGET[role], bg, away, make);
2141
+ }
2142
+ out.accent = accent;
2143
+ const a = toOklch(accent);
2144
+ out["accent-fg"] = meet(a.l * 100, APCA_BUDGET["accent-fg"], bg, away, (x) => oklchToHex({ l: x / 100, c: a.c, h: a.h }));
2145
+ out["on-accent"] = apca("#111111", accent) >= apca("#ffffff", accent) ? "#111111" : "#ffffff";
2146
+ for (const [role, [l, c, h]] of Object.entries(STATUS[appearance]))
2147
+ out[role] = oklchToHex({ l: l / 100, c, h });
2148
+ const s = SERIES[appearance];
2149
+ const start = a.c >= 0.04 ? a.h - SERIES_HUES[0] : 0;
2150
+ SERIES_HUES.forEach((h, i) => {
2151
+ out[`series-${i + 1}`] = oklchToHex({ l: s.l / 100, c: s.c, h: (h + start + 360) % 360 });
2152
+ });
2153
+ out.scrim = appearance === "dark" ? "#00000099" : "#00000040";
2154
+ out.contrast = String(Math.round(m * 1000) / 1000);
2155
+ out.radius = `${inputs.radius}px`;
2156
+ out.density = String(DENSITY[inputs.density]);
2157
+ out.font = inputs.font.sans;
2158
+ out.mono = inputs.font.mono;
2159
+ const material = inputs.material;
2160
+ out.glass = material === "glass" ? "0.6" : "0";
2161
+ out.glow = material === "glass" ? "0.5" : "0";
2162
+ out.rim = material === "flat" ? "transparent" : appearance === "dark" ? "#ffffff1a" : "#ffffff99";
2163
+ if (material === "flat") {
2164
+ out["border-subtle"] = over(withAlpha(out.fg, 0.06 * m), bg);
2165
+ out.border = over(withAlpha(out.fg, 0.1 * m), bg);
2166
+ }
2167
+ return out;
2168
+ }
2169
+ function shadows(material, borderStrong) {
2170
+ if (material === "flat")
2171
+ return {
2172
+ "shadow-raised": "none",
2173
+ "shadow-overlay": `0 0 0 1px light-dark(${borderStrong.light},${borderStrong.dark})`
2174
+ };
2175
+ return {
2176
+ "shadow-raised": "0 1px 2px light-dark(#0000001f,#00000029)",
2177
+ "shadow-overlay": "0 12px 36px light-dark(#00000024,#00000085),0 1px 2px light-dark(#00000014,#0000004d)"
2178
+ };
2179
+ }
2180
+ function resolve(declared) {
2181
+ const raw = (name) => {
2182
+ const def = TOKEN_BY_NAME.get(name);
2183
+ const own = declared[name];
2184
+ if (own !== undefined)
2185
+ return own;
2186
+ const source = def.source;
2187
+ if ("css" in source)
2188
+ return source.css;
2189
+ if ("value" in source)
2190
+ return source.value;
2191
+ throw new Error(`Theme does not supply ${name}`);
2192
+ };
2193
+ const lookup = (property) => {
2194
+ const name = tokenForProperty(property);
2195
+ return name ? raw(name) : undefined;
2196
+ };
2197
+ const out = {};
2198
+ for (const t of TOKENS)
2199
+ out[t.name] = t.type === "color" ? evaluate(raw(t.name), lookup) : raw(t.name);
2200
+ return out;
2201
+ }
2202
+ function gpuOf(resolved) {
2203
+ const out = {};
2204
+ for (const t of TOKENS)
2205
+ if (t.type === "color")
2206
+ out[t.name] = parseColor(resolved[t.name]);
2207
+ return out;
2208
+ }
2209
+ function validate(name, inputs) {
2210
+ if (!/^[\w-]+$/.test(name))
2211
+ throw new Error(`Invalid theme name: ${name}`);
2212
+ if (name === "dark" || name === "light")
2213
+ throw new Error(`Reserved theme name: ${name}`);
2214
+ for (const appearance of ["dark", "light"])
2215
+ for (const key of Object.keys(inputs.tokens[appearance]))
2216
+ if (!TOKEN_BY_NAME.has(key))
2217
+ throw new Error(`Unknown token in theme ${name}: ${key}`);
2218
+ }
2219
+ function defineTheme(spec) {
2220
+ const inputs = mergeInputs(spec.extends?.inputs ?? BASE, spec);
2221
+ validate(spec.name, inputs);
2222
+ const accent = accentPair(inputs);
2223
+ const generated = {
2224
+ dark: generate(inputs, "dark", accent.dark),
2225
+ light: generate(inputs, "light", accent.light)
2226
+ };
2227
+ const material = shadows(inputs.material, {
2228
+ dark: inputs.tokens.dark["border-strong"] ?? generated.dark["border-strong"],
2229
+ light: inputs.tokens.light["border-strong"] ?? generated.light["border-strong"]
2230
+ });
2231
+ const declared = {
2232
+ dark: { ...generated.dark, ...material, ...inputs.tokens.dark },
2233
+ light: { ...generated.light, ...material, ...inputs.tokens.light }
2234
+ };
2235
+ for (const [key, dark] of Object.entries(declared.dark)) {
2236
+ const def = TOKEN_BY_NAME.get(key);
2237
+ const light = declared.light[key];
2238
+ if (def.type !== "color" && light !== undefined && light !== dark)
2239
+ throw new Error(`Theme ${spec.name}: only colours may differ by appearance (${key})`);
2240
+ }
2241
+ const dark = resolve(declared.dark);
2242
+ const light = resolve(declared.light);
2243
+ const theme = {
2244
+ name: spec.name,
2245
+ inputs,
2246
+ dark,
2247
+ light,
2248
+ declared,
2249
+ gpu: { dark: gpuOf(dark), light: gpuOf(light) },
2250
+ css: (options) => options?.selector ? themeCss(theme, options.selector) : tokensCss(theme)
2251
+ };
2252
+ return theme;
2253
+ }
2254
+ var DEFAULT_SANS = 'system-ui,-apple-system,"SF Pro Text",sans-serif', DEFAULT_MONO = '"SF Mono",SFMono-Regular,ui-monospace,Menlo,monospace', BASE, DENSITY, SURFACES, INKS, APCA_BUDGET, TINT, STATUS, SERIES_HUES, SERIES, contrastMultiplier = (contrast) => 0.5 + Math.min(100, Math.max(0, contrast)) / 100;
2255
+ var init_define = __esm(() => {
2256
+ init_css();
2257
+ init_evaluate();
2258
+ init_schema();
2259
+ BASE = {
2260
+ gray: { hue: 0, chroma: 0 },
2261
+ accent: "#ffffff",
2262
+ contrast: 50,
2263
+ radius: 8,
2264
+ density: "default",
2265
+ material: "solid",
2266
+ font: { sans: DEFAULT_SANS, mono: DEFAULT_MONO },
2267
+ tokens: { dark: {}, light: {} }
2268
+ };
2269
+ DENSITY = { compact: 0.875, default: 1, comfortable: 1.1875 };
2270
+ SURFACES = {
2271
+ dark: { "bg-page": 14.5, "bg-inset": 19.6, bg: 22.6, "bg-raised": 25.7, "bg-overlay": 28.1 },
2272
+ light: { "bg-page": 92.6, "bg-inset": 94.6, bg: 97.1, "bg-raised": 100, "bg-overlay": 100 }
2273
+ };
2274
+ INKS = {
2275
+ dark: { fg: 99.7, "fg-2": 76.7, "fg-3": 48.4, "fg-4": 31.9, "border-strong": 15.8 },
2276
+ light: { fg: 98.35, "fg-2": 78, "fg-3": 50, "fg-4": 34, "border-strong": 17 }
2277
+ };
2278
+ APCA_BUDGET = {
2279
+ fg: 90,
2280
+ "fg-2": 75,
2281
+ "fg-3": 45,
2282
+ "fg-4": 30,
2283
+ "accent-fg": 60,
2284
+ "border-strong": 15
2285
+ };
2286
+ TINT = { surface: { dark: 0.5, light: 0.7 }, fg: 1.35, ink: 1.5, border: 1.25 };
2287
+ STATUS = {
2288
+ dark: {
2289
+ ok: [78, 0.15, 155],
2290
+ warn: [83, 0.14, 80],
2291
+ danger: [70, 0.18, 25],
2292
+ info: [75, 0.13, 240]
2293
+ },
2294
+ light: {
2295
+ ok: [52, 0.14, 150],
2296
+ warn: [60, 0.14, 65],
2297
+ danger: [55, 0.2, 27],
2298
+ info: [53, 0.15, 245]
2299
+ }
2300
+ };
2301
+ SERIES_HUES = [250, 155, 75, 25, 305, 195];
2302
+ SERIES = { dark: { l: 74, c: 0.12 }, light: { l: 56, c: 0.14 } };
2303
+ });
2304
+
2305
+ // src/themes/knobs.ts
2306
+ var knobs;
2307
+ var init_knobs = __esm(() => {
2308
+ init_define();
2309
+ knobs = defineTheme({
2310
+ name: "knobs",
2311
+ gray: { hue: 285, chroma: 0.004 },
2312
+ accent: { dark: "#ffffff", light: "#1c1c1e" },
2313
+ contrast: 50,
2314
+ radius: 8,
2315
+ density: "default",
2316
+ material: "glass"
2317
+ });
2318
+ });
2319
+
2320
+ // src/core/glide.ts
2321
+ var COLOR_TOKENS, LENGTH_TOKENS, NUMBER_TOKENS, ANIMATED, TOKEN_TRANSITIONS, 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(`
2322
+ `), GLIDING = ".knobs-panel,.knobs-chip,.knobs-notice,.knobs-ui", DRIVERS, aliased = (css) => css.replace(new RegExp(`var\\(--_k-(${ANIMATED.join("|")})\\)`, "g"), "var(--kv-$1)").replace(/var\(--k-blur\)/g, "var(--kv-blur)");
2323
+ var init_glide = __esm(() => {
2324
+ COLOR_TOKENS = [
2325
+ "bg",
2326
+ "fill",
2327
+ "fill-selected",
2328
+ "border",
2329
+ "border-strong",
2330
+ "fg",
2331
+ "fg-2",
2332
+ "fg-3",
2333
+ "accent",
2334
+ "modified",
2335
+ "segmented-track",
2336
+ "segmented-active",
2337
+ "toggle-track",
2338
+ "toggle-thumb",
2339
+ "toggle-thumb-off",
2340
+ "slider-handle",
2341
+ "rim",
2342
+ "border-subtle",
2343
+ "bg-page"
2344
+ ];
2345
+ LENGTH_TOKENS = ["pad", "inset", "row", "gap", "radius", "radius-panel", "font-size"];
2346
+ NUMBER_TOKENS = ["weight-label", "blur", "glow", "glass", "glass-tone"];
2347
+ ANIMATED = [...COLOR_TOKENS, ...LENGTH_TOKENS, ...NUMBER_TOKENS, "width"];
2348
+ TOKEN_TRANSITIONS = ANIMATED.map((t) => `--kt-${t} var(--k-token-t)`).join(",");
2349
+ DRIVERS = `${register(COLOR_TOKENS, "<color>", "transparent")}
2350
+ ${register(LENGTH_TOKENS, "<length>", "0px")}
2351
+ ${register(NUMBER_TOKENS, "<number>", "0")}
2352
+ ${register(["width"], "<length-percentage>", "288px")}
2353
+ :where(${GLIDING}){${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)}
2354
+ :where(.knobs-ui){transition:${TOKEN_TRANSITIONS}}
2355
+ :root[data-knobs-scrub] :where(.knobs-chip,.knobs-ui){--k-token-t:0s}
2356
+ @media(prefers-reduced-motion:reduce){:where(.knobs-chip,.knobs-ui){--k-token-t:0s}}`;
2357
+ });
2358
+
2359
+ // src/core/root.ts
2360
+ function injectTokens(doc) {
2361
+ if (doc.querySelector("style[data-knobs-tokens]"))
2362
+ return;
2363
+ const style = doc.createElement("style");
2364
+ style.dataset.knobsTokens = "";
2365
+ style.textContent = rootCss;
2366
+ doc.head.append(style);
2367
+ }
2368
+ var ROOT_CLASS = "knobs-root", extras, spring, rootCss;
2369
+ var init_root = __esm(() => {
2370
+ init_knobs();
2371
+ init_css();
2372
+ init_glide();
2373
+ init_motion();
2374
+ 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))}`;
2375
+ spring = `:where(:root,:host){--k-fill-ease:${DEFAULT_LINEAR.easing};--k-fill-ms:${DEFAULT_LINEAR.ms}}`;
2376
+ rootCss = `${tokensCss(knobs)}
2377
+ ${extras}
2378
+ ${spring}
2379
+ ${DRIVERS}
2380
+ ${motionCss}`;
2381
+ });
2382
+
720
2383
  // src/core/keys.ts
721
2384
  function normalizeCombo(combo) {
722
2385
  const trimmed = combo.trim();
@@ -835,36 +2498,18 @@ var init_keys = __esm(() => {
835
2498
 
836
2499
  // src/ui/look.ts
837
2500
  function injectUiStyles(doc) {
2501
+ injectTokens(doc);
838
2502
  if (doc.querySelector("style[data-knobs-ui]"))
839
2503
  return;
840
2504
  const style = doc.createElement("style");
841
2505
  style.dataset.knobsUi = "";
842
- style.textContent = css + readoutCss + overlayCss + bentoCss + activityCss + pickerCss + compareCss + rolling_css_default;
2506
+ style.textContent = uiCss();
843
2507
  doc.head.append(style);
844
2508
  }
845
- function injectUiPreset(doc, preset) {
846
- const content = presetCss({ ...preset, css: undefined }).replaceAll(".knobs-panel", ".knobs-ui");
847
- const existing = doc.querySelector(`style[data-knobs-ui-preset="${preset.name}"]`);
848
- if (existing) {
849
- if (existing.textContent !== content)
850
- existing.textContent = content;
851
- return;
852
- }
853
- const style = doc.createElement("style");
854
- style.dataset.knobsUiPreset = preset.name;
855
- style.textContent = content;
856
- doc.head.append(style);
857
- }
858
- function applyLook(root, look) {
859
- const doc = root.ownerDocument;
860
- injectUiStyles(doc);
861
- root.classList.add("knobs-ui");
862
- if (look.preset) {
863
- injectUiPreset(doc, look.preset);
864
- root.dataset.preset = look.preset.name;
865
- }
866
- if (look.theme)
867
- root.dataset.theme = look.theme;
2509
+ function applyLook2(root, look) {
2510
+ injectUiStyles(root.ownerDocument);
2511
+ root.classList.add("knobs-root", "knobs-ui");
2512
+ applyLook(root, resolveLook(look));
868
2513
  syncFrame(root);
869
2514
  }
870
2515
  function syncFrame(root) {
@@ -906,109 +2551,44 @@ function frameLoop(win, step) {
906
2551
  }
907
2552
  };
908
2553
  }
909
- var ease, TOKENS, LIGHT, lightBlock, css, lookDefaults, reducedMotion = (win) => win?.matchMedia?.("(prefers-reduced-motion: reduce)").matches ?? false, tune = (s, m) => {
910
- s.omega = m.omega;
911
- s.zeta = m.zeta;
912
- return s;
913
- }, svg = (body, box = 16) => `<svg viewBox="0 0 ${box} ${box}" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">${body}</svg>`, ICONS;
914
- var init_look = __esm(() => {
915
- init_theme();
916
- init_activity_css();
917
- init_picker_css();
918
- init_keys();
919
- ease = springEasing(26, 1);
920
- TOKENS = {
921
- bg: "#1c1c1e",
922
- surface: "rgba(255,255,255,.055)",
923
- "surface-hi": "rgba(255,255,255,.11)",
924
- line: "rgba(255,255,255,.1)",
925
- "line-hi": "rgba(255,255,255,.18)",
926
- text: "rgba(255,255,255,.92)",
927
- label: "rgba(255,255,255,.64)",
928
- dim: "rgba(255,255,255,.42)",
929
- accent: "#fff",
930
- font: 'system-ui,-apple-system,"SF Pro Text",sans-serif',
931
- mono: '"SF Mono",SFMono-Regular,ui-monospace,Menlo,monospace',
932
- "font-size": "12px",
933
- "font-weight": "400",
934
- "label-weight": "500",
935
- "title-weight": "600",
936
- row: "32px",
937
- inset: "10px",
938
- radius: "8px",
939
- "hover-in": "150",
940
- "hover-out": "150",
941
- warn: "#ff9f0a",
942
- critical: "#ff453a",
943
- rim: "rgba(255,255,255,.09)",
944
- page: "#101012",
945
- "seg-bg": "rgba(0,0,0,.26)",
946
- shadow: "0 12px 36px rgba(0,0,0,.52),0 1px 2px rgba(0,0,0,.3)"
947
- };
948
- LIGHT = {
949
- bg: "#f5f5f7",
950
- surface: "rgba(0,0,0,.05)",
951
- "surface-hi": "rgba(0,0,0,.095)",
952
- line: "rgba(0,0,0,.1)",
953
- "line-hi": "rgba(0,0,0,.2)",
954
- text: "rgba(0,0,0,.88)",
955
- label: "rgba(60,60,67,.68)",
956
- dim: "rgba(60,60,67,.5)",
957
- accent: "#1c1c1e",
958
- warn: "#c56a00",
959
- critical: "#e0352b",
960
- rim: "rgba(255,255,255,.75)",
961
- page: "#e6e6eb",
962
- "seg-bg": "rgba(0,0,0,.065)",
963
- shadow: "0 10px 32px rgba(0,0,0,.14),0 1px 3px rgba(0,0,0,.08)"
964
- };
965
- lightBlock = `${Object.entries(LIGHT).map(([k, v]) => `--k-${k}:${v}`).join(";")};color-scheme:light`;
966
- css = `
967
- :where(.knobs-ui){${Object.entries(TOKENS).map(([k, v]) => `--ku-${k}:var(--k-${k},${v})`).join(";")};
968
- --ku-control-h:var(--k-control-h,calc(var(--ku-row) - 8px));
969
- --ku-value-font:var(--k-value-font,var(--ku-font));
970
- --ku-value-size:var(--kc-value-size,calc(var(--ku-font-size) - .5px));
971
- --ku-text-meta:var(--k-text-meta,calc(var(--ku-font-size) - 1px));
972
- --ku-hit:var(--k-ui-hit,9px);
973
- --ku-rail:var(--k-ui-rail,var(--ku-row));
974
- --ku-indent:var(--k-ui-indent,14px);
975
- --ku-select:var(--k-ui-select,color-mix(in srgb,var(--ku-accent) 13%,transparent));
976
- --ku-select-focus:var(--k-ui-select-focus,color-mix(in srgb,var(--ku-accent) 19%,transparent));
977
- --ku-wash:var(--k-ui-wash,color-mix(in srgb,var(--ku-surface) 70%,transparent));
978
- --ku-wash-hi:var(--k-ui-wash-hi,var(--ku-surface-hi));
979
- --ku-ease:${ease.easing};--ku-ease-ms:${ease.ms}ms;
2554
+ var css2 = `
2555
+ :where(.knobs-ui){
2556
+ --_ku-hit:var(--k-ui-hit,9px);
2557
+ --_ku-rail:var(--k-ui-rail,var(--_k-row));
2558
+ --_ku-indent:var(--k-ui-indent,14px);
2559
+ --_ku-select:var(--k-ui-select,var(--k-selection,color-mix(in srgb,var(--_k-accent) 13%,transparent)));
2560
+ --_ku-select-focus:var(--k-ui-select-focus,color-mix(in srgb,var(--_k-accent) 19%,transparent));
2561
+ --_ku-wash:var(--k-ui-wash,color-mix(in srgb,var(--_k-fill) 70%,transparent));
2562
+ --_ku-wash-hi:var(--k-ui-wash-hi,var(--_k-fill-selected));
2563
+ --_ku-ease:var(--_k-motion-snappy);--_ku-ease-ms:calc(var(--_k-motion-snappy-ms) * 1ms);
980
2564
  /* The card frame (knobs' own look): every leaf pane a rounded card on the page, half a gap
981
2565
  inside its slot, so panes sit a gap apart with the dividers' grips between them; tree rows
982
2566
  inset as soft rounded washes. --k-frame: flat (labPreset) puts panes edge to edge on
983
2567
  hairlines, square, as a dense editor's columns. */
984
- --ku-panel-radius:var(--k-panel-radius,calc(var(--ku-radius) + 4px));
985
- --ku-gap:var(--k-ui-gap,6px);
986
- --ku-pane-m:calc(var(--ku-gap) / 2);
987
- --ku-pane-bg:var(--k-ui-pane,var(--ku-bg));
988
- --ku-pane-radius:var(--ku-panel-radius);
989
- --ku-pane-ring:inset 0 0 0 1px var(--ku-line),inset 0 1px 0 var(--ku-rim);
990
- --ku-divider:var(--k-ui-divider,transparent);
991
- --ku-row-x:var(--k-ui-row-x,6px);
992
- --ku-row-radius:max(0px,calc(var(--ku-panel-radius) - var(--ku-row-x)));
993
- }
994
- :where(.knobs-ui)[data-frame="flat"]{--ku-gap:var(--k-ui-gap,0px);--ku-pane-bg:var(--k-ui-pane,transparent);--ku-pane-radius:0px;--ku-pane-ring:none;
995
- --ku-divider:var(--k-ui-divider,var(--ku-line));--ku-row-x:var(--k-ui-row-x,0px);--ku-row-radius:0px;
996
- --ku-select:var(--k-ui-select,color-mix(in srgb,var(--ku-accent) 24%,transparent));--ku-select-focus:var(--k-ui-select-focus,color-mix(in srgb,var(--ku-accent) 34%,transparent))}
2568
+ --_ku-gap:var(--k-ui-gap,6px);
2569
+ --_ku-pane-m:calc(var(--_ku-gap) / 2);
2570
+ --_ku-pane-bg:var(--_k-pane-bg);
2571
+ --_ku-pane-radius:var(--_k-radius-panel);
2572
+ --_ku-pane-ring:inset 0 0 0 1px var(--_k-border),inset 0 1px 0 var(--_k-rim);
2573
+ --_ku-divider:var(--k-ui-divider,var(--k-split-gutter,transparent));
2574
+ --_ku-row-x:var(--k-ui-row-x,6px);
2575
+ --_ku-row-radius:max(0px,calc(var(--_ku-pane-radius) - var(--_ku-row-x)));
2576
+ }
2577
+ :where(.knobs-ui)[data-frame="flat"]{--_ku-gap:var(--k-ui-gap,0px);--_ku-pane-bg:var(--k-ui-pane,var(--k-pane-bg,transparent));--_ku-pane-radius:0px;--_ku-pane-ring:none;
2578
+ --_ku-divider:var(--_k-split-gutter);--_ku-row-x:var(--k-ui-row-x,0px);--_ku-row-radius:0px;
2579
+ --_ku-select:var(--_k-selection);--_ku-select-focus:var(--k-ui-select-focus,color-mix(in srgb,var(--_k-accent) 34%,transparent))}
997
2580
  /* One surface per thing: a piece on another surface draws no card of its own. Whatever draws a
998
2581
  card (a walkthrough's step, a host's own) carries .knobs-surface, and a split's pane that's a
999
2582
  card (not only a slot for another split) counts as one; any piece inside it, or one
1000
2583
  marked data-nested, loses its fill and ring and parts its own panes on hairlines as the flat
1001
2584
  frame does, so cards never stack two or three borders deep. Pieces draw their card from
1002
- --ku-pane-bg and --ku-pane-ring so this reaches them. */
1003
- :where(.knobs-surface,.knobs-pane:not([data-nested])>.knobs-pane-clip) .knobs-ui:not(.knobs-surface),.knobs-ui[data-nested]{--ku-gap:var(--k-ui-gap,0px);--ku-pane-bg:transparent;--ku-pane-ring:none;
1004
- --ku-divider:var(--k-ui-divider,var(--ku-line));--k-diff-bg:transparent}
1005
- :where(.knobs-ui)[data-theme="light"],
1006
- :where(:root[data-theme="light"]) :where(.knobs-ui)[data-theme="auto"]{${lightBlock}}
1007
- @media(prefers-color-scheme:light){:where(:root:not([data-theme="dark"])) :where(.knobs-ui)[data-theme="auto"]{${lightBlock}}}
2585
+ --_ku-pane-bg and --_ku-pane-ring so this reaches them. */
2586
+ :where(.knobs-surface,.knobs-pane:not([data-nested])>.knobs-pane-clip) .knobs-ui:not(.knobs-surface),.knobs-ui[data-nested]{--_ku-gap:var(--k-ui-gap,0px);--_ku-pane-bg:transparent;--_ku-pane-ring:none;
2587
+ --_ku-divider:var(--_k-split-gutter);--_kd-bg:transparent}
1008
2588
  /* Only the pieces' own elements take their type and resets: what you put in a pane is yours. */
1009
2589
  .knobs-ui{box-sizing:border-box}
1010
2590
  :where(.knobs-split>*,.knobs-pane-clip,.knobs-pane-inner,.knobs-pane-body,.knobs-pane-head,.knobs-pane-head *,.knobs-pane-rail,.knobs-pane-rail *,.knobs-tree,.knobs-tree *,.knobs-tree-ghost){box-sizing:border-box}
1011
- :is(.knobs-tree,.knobs-pane-head,.knobs-pane-rail,.knobs-tree-ghost){font:var(--ku-font-weight) var(--ku-font-size)/1.35 var(--ku-font);color:var(--ku-text);text-align:left;
2591
+ :is(.knobs-tree,.knobs-pane-head,.knobs-pane-rail,.knobs-tree-ghost){font:var(--_k-weight) var(--_k-font-size)/1.35 var(--_k-font);color:var(--_k-fg);text-align:left;
1012
2592
  letter-spacing:normal;word-spacing:normal;text-transform:none;text-indent:0;text-shadow:none;font-style:normal;-webkit-font-smoothing:antialiased}
1013
2593
  /* A host's element rules (button{padding}, header{margin}, mark{background}) stop at these, as
1014
2594
  they do at panels; (0,1,0), so the pieces' own rules after it win. */
@@ -1046,17 +2626,17 @@ var init_look = __esm(() => {
1046
2626
  :is(.knobs-tree,.knobs-activity)::-webkit-scrollbar{display:none}
1047
2627
  .knobs-scrollbar{position:sticky;top:0;z-index:3;height:0;pointer-events:none}
1048
2628
  .knobs-scrollbar[hidden]{display:none}
1049
- .knobs-scrollbar-thumb{position:absolute;top:0;right:2px;width:5px;border-radius:3px;background:color-mix(in srgb,var(--ku-text) 30%,transparent);opacity:0;
2629
+ .knobs-scrollbar-thumb{position:absolute;top:0;right:2px;width:5px;border-radius:3px;background:color-mix(in srgb,var(--_k-fg) 30%,transparent);opacity:0;
1050
2630
  transition:opacity .3s ease-out,background .15s}
1051
2631
  :hover>.knobs-scrollbar>.knobs-scrollbar-thumb,.knobs-scrollbar:is([data-active],[data-dragging])>.knobs-scrollbar-thumb{opacity:1;pointer-events:auto;transition-duration:.12s,.15s}
1052
- .knobs-scrollbar-thumb:hover,.knobs-scrollbar[data-dragging]>.knobs-scrollbar-thumb{background:color-mix(in srgb,var(--ku-text) 48%,transparent)}
2632
+ .knobs-scrollbar-thumb:hover,.knobs-scrollbar[data-dragging]>.knobs-scrollbar-thumb{background:color-mix(in srgb,var(--_k-fg) 48%,transparent)}
1053
2633
 
1054
2634
  /* Split: panes along a row or column, hairline dividers with a wider grip. */
1055
2635
  .knobs-split{position:relative;display:flex;width:100%;height:100%;min-width:0;min-height:0;overflow:hidden}
1056
2636
  .knobs-split[data-direction="column"]{flex-direction:column}
1057
2637
  .knobs-pane{position:relative;flex:none;min-width:0;min-height:0;overflow:hidden}
1058
- .knobs-pane-clip{position:absolute;inset:0;margin:var(--ku-pane-m);overflow:hidden;border-radius:var(--ku-pane-radius);background:var(--ku-pane-bg)}
1059
- .knobs-pane-clip::after{content:"";position:absolute;inset:0;border-radius:inherit;box-shadow:var(--ku-pane-ring);pointer-events:none}
2638
+ .knobs-pane-clip{position:absolute;inset:0;margin:var(--_ku-pane-m);overflow:hidden;border-radius:var(--_ku-pane-radius);background:var(--_ku-pane-bg)}
2639
+ .knobs-pane-clip::after{content:"";position:absolute;inset:0;border-radius:inherit;box-shadow:var(--_ku-pane-ring);pointer-events:none}
1060
2640
  /* A pane holding another split is only its slot: the split's own panes are the cards. */
1061
2641
  .knobs-pane[data-nested]>.knobs-pane-clip{margin:0;background:transparent}
1062
2642
  .knobs-pane[data-nested]>.knobs-pane-clip::after{content:none}
@@ -1064,36 +2644,36 @@ var init_look = __esm(() => {
1064
2644
  .knobs-pane-body{position:relative;flex:1;min-width:0;min-height:0;overflow:hidden}
1065
2645
  .knobs-pane[data-scroll] .knobs-pane-body{overflow:auto;scrollbar-width:thin}
1066
2646
  .knobs-pane[data-rail][data-collapsed][data-settled]>.knobs-pane-clip>.knobs-pane-inner,.knobs-pane:not([data-rail])[data-collapsed][data-settled]>.knobs-pane-clip>.knobs-pane-inner>.knobs-pane-body{visibility:hidden}
1067
- .knobs-ui .knobs-pane-head{display:flex;align-items:center;gap:6px;flex:none;height:var(--ku-row);padding:0 calc(var(--ku-inset) - 4px) 0 var(--ku-inset);user-select:none;-webkit-user-select:none}
1068
- .knobs-pane-title{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:var(--ku-title-weight);color:var(--ku-text)}
1069
- .knobs-pane-count{flex:none;color:var(--ku-dim);font-variant-numeric:tabular-nums}
2647
+ .knobs-ui .knobs-pane-head{display:flex;align-items:center;gap:6px;flex:none;height:var(--_k-row);padding:0 calc(var(--_k-inset) - 4px) 0 var(--_k-inset);user-select:none;-webkit-user-select:none}
2648
+ .knobs-pane-title{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:var(--_k-weight-title);color:var(--_k-fg)}
2649
+ .knobs-pane-count{flex:none;color:var(--_k-fg-3);font-variant-numeric:tabular-nums}
1070
2650
  .knobs-pane-fill{flex:1}
1071
- .knobs-ui .knobs-pane-btn{flex:none;display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:calc(var(--ku-radius) * 999);color:var(--ku-dim);cursor:pointer;
2651
+ .knobs-ui .knobs-pane-btn{flex:none;display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:calc(var(--_k-radius) * 999);color:var(--_k-fg-3);cursor:pointer;
1072
2652
  transition:background var(--hover-t,.15s),color .15s}
1073
- .knobs-ui .knobs-pane-btn:is(:hover,:focus-visible){background:var(--ku-wash-hi);color:var(--ku-text)}
1074
- .knobs-ui .knobs-pane-btn[aria-pressed="true"]{color:var(--ku-accent)}
2653
+ .knobs-ui .knobs-pane-btn:is(:hover,:focus-visible){background:var(--_ku-wash-hi);color:var(--_k-fg)}
2654
+ .knobs-ui .knobs-pane-btn[aria-pressed="true"]{color:var(--_k-accent)}
1075
2655
  .knobs-pane-btn svg{width:13px;height:13px}
1076
2656
  .knobs-pane-head[data-toggles]{cursor:pointer}
1077
2657
  /* A collapsed pane's rail: its title along the edge; a click opens it. It holds on to the edge the
1078
2658
  pane folds toward, as wide as the rail, over the card (which folds to its size): only its label
1079
2659
  and chevron draw, and a nested split's slot, which has no card, gives it one of its own. */
1080
- .knobs-ui .knobs-pane-rail{position:absolute;margin:var(--ku-pane-m);border-radius:var(--ku-pane-radius);background-color:transparent;display:flex;align-items:center;gap:8px;color:var(--ku-label);cursor:pointer;opacity:0;pointer-events:none;
1081
- font-weight:var(--ku-title-weight);transition:background .15s,color .15s}
1082
- .knobs-ui .knobs-pane[data-nested]>.knobs-pane-rail{background-color:var(--ku-pane-bg);box-shadow:var(--ku-pane-ring)}
1083
- .knobs-split[data-direction="row"]>.knobs-pane>.knobs-pane-rail{top:0;bottom:0;width:var(--ku-rail);writing-mode:vertical-rl;padding:10px 0}
2660
+ .knobs-ui .knobs-pane-rail{position:absolute;margin:var(--_ku-pane-m);border-radius:var(--_ku-pane-radius);background-color:transparent;display:flex;align-items:center;gap:8px;color:var(--_k-fg-2);cursor:pointer;opacity:0;pointer-events:none;
2661
+ font-weight:var(--_k-weight-title);transition:background .15s,color .15s}
2662
+ .knobs-ui .knobs-pane[data-nested]>.knobs-pane-rail{background-color:var(--_ku-pane-bg);box-shadow:var(--_ku-pane-ring)}
2663
+ .knobs-split[data-direction="row"]>.knobs-pane>.knobs-pane-rail{top:0;bottom:0;width:var(--_ku-rail);writing-mode:vertical-rl;padding:10px 0}
1084
2664
  .knobs-split[data-direction="row"]>.knobs-pane[data-edge="start"]>.knobs-pane-rail{right:0}
1085
2665
  .knobs-split[data-direction="row"]>.knobs-pane[data-edge="end"]>.knobs-pane-rail{left:0}
1086
- .knobs-split[data-direction="column"]>.knobs-pane>.knobs-pane-rail{left:0;right:0;height:var(--ku-rail);padding:0 var(--ku-inset)}
2666
+ .knobs-split[data-direction="column"]>.knobs-pane>.knobs-pane-rail{left:0;right:0;height:var(--_ku-rail);padding:0 var(--_k-inset)}
1087
2667
  .knobs-split[data-direction="column"]>.knobs-pane[data-edge="start"]>.knobs-pane-rail{bottom:0}
1088
2668
  .knobs-split[data-direction="column"]>.knobs-pane[data-edge="end"]>.knobs-pane-rail{top:0}
1089
2669
  .knobs-pane[data-collapsed]>.knobs-pane-rail{pointer-events:auto}
1090
2670
  /* Its hover wash fades, rather than going in one frame as a click opens the pane. */
1091
- .knobs-ui .knobs-pane-rail::before{content:"";position:absolute;inset:0;border-radius:inherit;background:var(--ku-wash);opacity:0;transition:opacity .15s;pointer-events:none}
2671
+ .knobs-ui .knobs-pane-rail::before{content:"";position:absolute;inset:0;border-radius:inherit;background:var(--_ku-wash);opacity:0;transition:opacity .15s;pointer-events:none}
1092
2672
  .knobs-pane-rail>*{position:relative}
1093
- .knobs-ui .knobs-pane[data-collapsed]>.knobs-pane-rail:is(:hover,:focus-visible){color:var(--ku-text)}
2673
+ .knobs-ui .knobs-pane[data-collapsed]>.knobs-pane-rail:is(:hover,:focus-visible){color:var(--_k-fg)}
1094
2674
  .knobs-ui .knobs-pane[data-collapsed]>.knobs-pane-rail:is(:hover,:focus-visible)::before{opacity:1}
1095
2675
  .knobs-pane-rail-label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
1096
- .knobs-pane-chevron{display:flex;flex:none;width:11px;height:11px;writing-mode:horizontal-tb;color:var(--ku-dim)}
2676
+ .knobs-pane-chevron{display:flex;flex:none;width:11px;height:11px;writing-mode:horizontal-tb;color:var(--_k-fg-3)}
1097
2677
  .knobs-pane-turn{display:flex;width:100%;height:100%;transform-origin:50% 50%}
1098
2678
  .knobs-pane-rail svg{width:11px;height:11px}
1099
2679
  /* The rail's chevron stands in for the header's collapse icon (it turns into the rail's), so the
@@ -1101,26 +2681,26 @@ var init_look = __esm(() => {
1101
2681
  .knobs-pane[data-morph]>.knobs-pane-clip>.knobs-pane-inner>.knobs-pane-head>.knobs-pane-collapse>svg{visibility:hidden}
1102
2682
  /* So does the rail's label for the title, when it travels (split's fold: { title: "travel" }). */
1103
2683
  .knobs-pane[data-travel]>.knobs-pane-clip>.knobs-pane-inner>.knobs-pane-head>.knobs-pane-title{visibility:hidden}
1104
- .knobs-pane[data-morph]:not([data-collapsed]):has(>.knobs-pane-clip>.knobs-pane-inner>.knobs-pane-head>.knobs-pane-collapse:is(:hover,:focus-visible))>.knobs-pane-rail .knobs-pane-chevron{color:var(--ku-text)}
2684
+ .knobs-pane[data-morph]:not([data-collapsed]):has(>.knobs-pane-clip>.knobs-pane-inner>.knobs-pane-head>.knobs-pane-collapse:is(:hover,:focus-visible))>.knobs-pane-rail .knobs-pane-chevron{color:var(--_k-fg)}
1105
2685
  .knobs-pane[data-morph]:not([data-collapsed])>.knobs-pane-rail .knobs-pane-chevron{transition:color .15s}
1106
2686
 
1107
- .knobs-divider{position:relative;z-index:2;flex:none;width:1px;background:var(--ku-divider);touch-action:none;outline:none}
2687
+ .knobs-divider{position:relative;z-index:2;flex:none;width:1px;background:var(--_ku-divider);touch-action:none;outline:none}
1108
2688
  .knobs-split[data-direction="column"]>.knobs-divider{width:auto;height:1px}
1109
- .knobs-divider::before{content:"";position:absolute;top:0;bottom:0;left:calc(50% - var(--ku-hit) / 2);width:var(--ku-hit);cursor:col-resize}
1110
- .knobs-split[data-direction="column"]>.knobs-divider::before{left:0;right:0;top:calc(50% - var(--ku-hit) / 2);bottom:auto;width:auto;height:var(--ku-hit);cursor:row-resize}
2689
+ .knobs-divider::before{content:"";position:absolute;top:0;bottom:0;left:calc(50% - var(--_ku-hit) / 2);width:var(--_ku-hit);cursor:col-resize}
2690
+ .knobs-split[data-direction="column"]>.knobs-divider::before{left:0;right:0;top:calc(50% - var(--_ku-hit) / 2);bottom:auto;width:auto;height:var(--_ku-hit);cursor:row-resize}
1111
2691
  /* Hover, focus and drags draw the hairline in the accent, with a soft wash beside it. */
1112
- .knobs-divider::after{content:"";position:absolute;inset:0 -1px;background:var(--ku-accent);opacity:0;pointer-events:none;
1113
- box-shadow:0 0 0 2px color-mix(in srgb,var(--ku-accent) 18%,transparent);transition:opacity .16s}
2692
+ .knobs-divider::after{content:"";position:absolute;inset:0 -1px;background:var(--_k-accent);opacity:0;pointer-events:none;
2693
+ box-shadow:0 0 0 2px color-mix(in srgb,var(--_k-accent) 18%,transparent);transition:opacity .16s}
1114
2694
  .knobs-split[data-direction="column"]>.knobs-divider::after{inset:-1px 0}
1115
2695
  .knobs-divider:hover::after{opacity:.7;transition-delay:.12s}
1116
2696
  .knobs-divider:focus-visible::after,.knobs-divider[data-active]::after{opacity:1;transition-delay:0s}
1117
2697
  /* Between cards, the hairline gives way to a grip: a small capsule in the gap that shows on
1118
2698
  hover, and lengthens and takes the accent while dragged or focused. */
1119
- .knobs-split:not([data-frame="flat"])>.knobs-divider::after{inset:auto;left:50%;top:50%;width:4px;height:28px;margin:-14px 0 0 -2px;border-radius:2px;background:var(--ku-line-hi);box-shadow:none;
1120
- transition:opacity .16s,background .16s,scale var(--ku-ease-ms) var(--ku-ease)}
2699
+ .knobs-split:not([data-frame="flat"])>.knobs-divider::after{inset:auto;left:50%;top:50%;width:4px;height:28px;margin:-14px 0 0 -2px;border-radius:2px;background:var(--_k-border-strong);box-shadow:none;
2700
+ transition:opacity .16s,background .16s,scale var(--_ku-ease-ms) var(--_ku-ease)}
1121
2701
  .knobs-split[data-direction="column"]:not([data-frame="flat"])>.knobs-divider::after{inset:auto;left:50%;top:50%;width:28px;height:4px;margin:-2px 0 0 -14px}
1122
2702
  .knobs-split:not([data-frame="flat"])>.knobs-divider:hover::after{opacity:1}
1123
- .knobs-split:not([data-frame="flat"])>.knobs-divider:is(:focus-visible,[data-active])::after{background:var(--ku-accent);opacity:.9;scale:1 1.45}
2703
+ .knobs-split:not([data-frame="flat"])>.knobs-divider:is(:focus-visible,[data-active])::after{background:var(--_k-accent);opacity:.9;scale:1 1.45}
1124
2704
  .knobs-split[data-direction="column"]:not([data-frame="flat"])>.knobs-divider:is(:focus-visible,[data-active])::after{scale:1.45 1}
1125
2705
  :root[data-knobs-resizing],:root[data-knobs-resizing] *{user-select:none!important;-webkit-user-select:none!important}
1126
2706
  :root[data-knobs-resizing="row"] *{cursor:col-resize!important}
@@ -1130,112 +2710,124 @@ var init_look = __esm(() => {
1130
2710
  /* Tree: one scroller, rows placed by transform, only those near the view in the DOM. */
1131
2711
  .knobs-tree{position:relative;overflow:auto;height:100%;outline:none;scrollbar-width:none;overscroll-behavior:contain;user-select:none;-webkit-user-select:none}
1132
2712
  .knobs-tree-space{position:relative;width:100%;pointer-events:none}
1133
- .knobs-tree-row{position:absolute;left:var(--ku-row-x);right:var(--ku-row-x);top:0;display:flex;align-items:center;height:var(--ku-row);padding-right:calc(var(--ku-inset) - 4px);
1134
- color:var(--ku-text);white-space:nowrap;cursor:default;will-change:transform;contain:layout style}
1135
- .knobs-tree-row::before{content:"";position:absolute;inset:0;border-radius:var(--ku-row-radius);background:var(--ku-wash);opacity:0;transition:opacity calc(var(--ku-hover-out) * 1ms),background .12s;pointer-events:none}
1136
- .knobs-tree:not([data-keyboard]):not([data-dragging]) .knobs-tree-row:hover::before{opacity:1;transition-duration:calc(var(--ku-hover-in) * 1ms)}
1137
- .knobs-tree-row[aria-selected="true"]::before{opacity:1;background:var(--ku-select)}
1138
- .knobs-tree:focus-visible .knobs-tree-row[data-active]::before,.knobs-tree[data-keyboard]:focus .knobs-tree-row[data-active]::before{opacity:1;background:var(--ku-wash-hi)}
1139
- .knobs-tree:focus .knobs-tree-row[data-active][aria-selected="true"]::before{background:var(--ku-select-focus)}
1140
- .knobs-tree-row[data-drop="into"]::before{opacity:1;background:color-mix(in srgb,var(--ku-accent) 30%,transparent)}
2713
+ .knobs-tree-row{position:absolute;left:var(--_ku-row-x);right:var(--_ku-row-x);top:0;display:flex;align-items:center;height:var(--_k-row);padding-right:calc(var(--_k-inset) - 4px);
2714
+ color:var(--_k-fg);white-space:nowrap;cursor:default;will-change:transform;contain:layout style}
2715
+ .knobs-tree-row::before{content:"";position:absolute;inset:0;border-radius:var(--_ku-row-radius);background:var(--_ku-wash);opacity:0;transition:opacity calc(var(--_k-hover-out) * 1ms),background .12s;pointer-events:none}
2716
+ .knobs-tree:not([data-keyboard]):not([data-dragging]) .knobs-tree-row:hover::before{opacity:1;transition-duration:calc(var(--_k-hover-in) * 1ms)}
2717
+ .knobs-tree-row[aria-selected="true"]::before{opacity:1;background:var(--_ku-select)}
2718
+ .knobs-tree:focus-visible .knobs-tree-row[data-active]::before,.knobs-tree[data-keyboard]:focus .knobs-tree-row[data-active]::before{opacity:1;background:var(--_ku-wash-hi)}
2719
+ .knobs-tree:focus .knobs-tree-row[data-active][aria-selected="true"]::before{background:var(--_ku-select-focus)}
2720
+ .knobs-tree-row[data-drop="into"]::before{opacity:1;background:color-mix(in srgb,var(--_k-accent) 30%,transparent)}
1141
2721
  .knobs-tree-row[data-dragged]{opacity:.38}
1142
2722
  /* glide: one highlight under the selected row that glides between rows (the row's own stays off). */
1143
- .knobs-tree-cursor{position:absolute;left:var(--ku-row-x);right:var(--ku-row-x);top:0;height:var(--ku-row);border-radius:var(--ku-row-radius);background:var(--ku-select);
2723
+ .knobs-tree-cursor{position:absolute;left:var(--_ku-row-x);right:var(--_ku-row-x);top:0;height:var(--_k-row);border-radius:var(--_ku-row-radius);background:var(--_ku-select);
1144
2724
  opacity:0;pointer-events:none;will-change:transform;transition:opacity .15s ease-out,background .12s}
1145
2725
  .knobs-tree-cursor[data-on]{opacity:1}
1146
- .knobs-tree:focus .knobs-tree-cursor{background:var(--ku-select-focus)}
2726
+ .knobs-tree:focus .knobs-tree-cursor{background:var(--_ku-select-focus)}
1147
2727
  .knobs-tree[data-glide] .knobs-tree-row[aria-selected="true"]::before{opacity:0!important}
1148
2728
  .knobs-tree-row>*{position:relative}
1149
- .knobs-tree-caret{flex:none;display:flex;align-items:center;justify-content:center;width:16px;height:100%;color:var(--ku-dim);transition:transform var(--ku-ease-ms) var(--ku-ease)}
2729
+ .knobs-tree-caret{flex:none;display:flex;align-items:center;justify-content:center;width:16px;height:100%;color:var(--_k-fg-3);transition:transform var(--_ku-ease-ms) var(--_ku-ease)}
1150
2730
  .knobs-tree-caret svg{width:9px;height:9px}
1151
2731
  .knobs-tree-row[aria-expanded="true"]>.knobs-tree-caret{transform:rotate(90deg)}
1152
2732
  .knobs-tree-row:not([aria-expanded])>.knobs-tree-caret{visibility:hidden}
1153
- .knobs-tree-icon{flex:none;display:flex;align-items:center;justify-content:center;width:14px;margin-right:6px;color:var(--ku-dim);font-size:calc(var(--ku-font-size) - 1px)}
1154
- .knobs-tree-label{position:relative;flex:1;min-width:0;overflow:hidden;font-weight:var(--ku-font-weight)}
1155
- .knobs-tree-row[data-ancestor] .knobs-tree-label{color:var(--ku-label)}
1156
- .knobs-tree-label .knobs-tree-mark{color:var(--ku-accent)}
2733
+ .knobs-tree-icon{flex:none;display:flex;align-items:center;justify-content:center;width:14px;margin-right:6px;color:var(--_k-fg-3);font-size:calc(var(--_k-font-size) - 1px)}
2734
+ .knobs-tree-label{position:relative;flex:1;min-width:0;overflow:hidden;font-weight:var(--_k-weight)}
2735
+ .knobs-tree-row[data-ancestor] .knobs-tree-label{color:var(--_k-fg-2)}
2736
+ .knobs-tree-label .knobs-tree-mark{color:var(--_k-accent)}
1157
2737
  .knobs-tree-row[data-off~="visible"] :is(.knobs-tree-label,.knobs-tree-icon){opacity:.45}
1158
- .knobs-tree-row[data-off~="locked"] .knobs-tree-label{color:var(--ku-label)}
1159
- .knobs-tree-detail{flex:none;margin-left:6px;color:var(--ku-dim);font-variant-numeric:tabular-nums}
2738
+ .knobs-tree-row[data-off~="locked"] .knobs-tree-label{color:var(--_k-fg-2)}
2739
+ .knobs-tree-detail{flex:none;margin-left:6px;color:var(--_k-fg-3);font-variant-numeric:tabular-nums}
1160
2740
  .knobs-tree-tools{flex:none;display:flex;align-items:center;gap:1px;margin-left:4px}
1161
- .knobs-ui .knobs-tree-toggle{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:calc(var(--ku-radius) * 999);color:var(--ku-dim);cursor:pointer;opacity:0;transition:opacity .12s,color .12s,background .12s}
2741
+ .knobs-ui .knobs-tree-toggle{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:calc(var(--_k-radius) * 999);color:var(--_k-fg-3);cursor:pointer;opacity:0;transition:opacity .12s,color .12s,background .12s}
1162
2742
  .knobs-ui .knobs-tree-toggle svg{width:12px;height:12px}
1163
2743
  .knobs-tree-row:is(:hover,[data-active],[aria-selected="true"]) .knobs-tree-toggle,.knobs-ui .knobs-tree-toggle[aria-pressed="false"]{opacity:1}
1164
- .knobs-ui .knobs-tree-toggle:hover{background:var(--ku-wash-hi);color:var(--ku-text)}
1165
- .knobs-ui .knobs-tree-toggle[aria-pressed="false"]{color:var(--ku-label)}
2744
+ .knobs-ui .knobs-tree-toggle:hover{background:var(--_ku-wash-hi);color:var(--_k-fg)}
2745
+ .knobs-ui .knobs-tree-toggle[aria-pressed="false"]{color:var(--_k-fg-2)}
1166
2746
  /* Renaming in place, as a number is edited in a panel: no box, just the text and an underline. */
1167
- .knobs-ui .knobs-tree-edit{position:absolute;inset:auto 0 auto 0;top:50%;transform:translateY(-50%);width:100%;height:calc(var(--ku-font-size) * 1.5);padding:0;
1168
- background:transparent;color:var(--ku-text);caret-color:var(--ku-accent);font:inherit;font-weight:var(--ku-font-weight);border-bottom:1px solid var(--ku-text)}
1169
- .knobs-tree-edit::selection{background:color-mix(in srgb,var(--ku-accent) 40%,transparent)}
2747
+ .knobs-ui .knobs-tree-edit{position:absolute;inset:auto 0 auto 0;top:50%;transform:translateY(-50%);width:100%;height:calc(var(--_k-font-size) * 1.5);padding:0;
2748
+ background:transparent;color:var(--_k-fg);caret-color:var(--_k-accent);font:inherit;font-weight:var(--_k-weight);border-bottom:1px solid var(--_k-fg)}
2749
+ .knobs-tree-edit::selection{background:color-mix(in srgb,var(--_k-accent) 40%,transparent)}
1170
2750
  .knobs-tree-row[data-editing] .knobs-tree-text{visibility:hidden}
1171
- .knobs-tree-line{position:absolute;left:0;right:6px;top:0;height:2px;margin-top:-1px;border-radius:1px;background:var(--ku-accent);pointer-events:none;opacity:0;transition:opacity .1s}
1172
- .knobs-tree-line::before{content:"";position:absolute;left:-3px;top:-2px;width:6px;height:6px;border-radius:50%;box-shadow:inset 0 0 0 2px var(--ku-accent)}
2751
+ .knobs-tree-line{position:absolute;left:0;right:6px;top:0;height:2px;margin-top:-1px;border-radius:1px;background:var(--_k-accent);pointer-events:none;opacity:0;transition:opacity .1s}
2752
+ .knobs-tree-line::before{content:"";position:absolute;left:-3px;top:-2px;width:6px;height:6px;border-radius:50%;box-shadow:inset 0 0 0 2px var(--_k-accent)}
1173
2753
  .knobs-tree[data-dragging] .knobs-tree-line[data-shown]{opacity:1}
1174
- .knobs-tree-ghost{position:fixed;left:0;top:0;z-index:2147480004;padding:2px 8px;background:var(--ku-bg);color:var(--ku-text);border-radius:var(--ku-radius);
1175
- box-shadow:0 0 0 1px var(--ku-line-hi),0 6px 18px rgba(0,0,0,.35);pointer-events:none;white-space:nowrap;font:var(--ku-font-weight) var(--ku-font-size)/1.6 var(--ku-font)}
1176
- .knobs-tree-empty{padding:10px var(--ku-inset);color:var(--ku-dim)}
2754
+ .knobs-tree-ghost{position:fixed;left:0;top:0;z-index:2147480004;padding:2px 8px;background:var(--_k-bg);color:var(--_k-fg);border-radius:var(--_k-radius);
2755
+ box-shadow:0 0 0 1px var(--_k-border-strong),0 6px 18px rgba(0,0,0,calc(.35 * var(--_k-shadow-k,1)));pointer-events:none;white-space:nowrap;font:var(--_k-weight) var(--_k-font-size)/1.6 var(--_k-font)}
2756
+ .knobs-tree-empty{padding:10px var(--_k-inset);color:var(--_k-fg-3)}
1177
2757
 
1178
2758
  /* Timeline: a transport (play, the time) beside a track: the ruler's canvas over a lane of
1179
2759
  markers, ranges as soft bands, and the playhead, a hairline in the accent with a cap. */
1180
2760
  :where(.knobs-timeline,.knobs-timeline *){box-sizing:border-box}
1181
- .knobs-ui.knobs-timeline{display:flex;align-items:stretch;gap:10px;width:100%;height:100%;min-height:52px;padding:6px var(--ku-inset) 8px 8px;outline:none;user-select:none;-webkit-user-select:none;
1182
- font:var(--ku-font-weight) var(--ku-font-size)/1.35 var(--ku-font);color:var(--ku-text);letter-spacing:normal;text-align:left}
2761
+ .knobs-ui.knobs-timeline{display:flex;align-items:stretch;gap:10px;width:100%;height:100%;min-height:52px;padding:6px var(--_k-inset) 8px 8px;outline:none;user-select:none;-webkit-user-select:none;
2762
+ font:var(--_k-weight) var(--_k-font-size)/1.35 var(--_k-font);color:var(--_k-fg);letter-spacing:normal;text-align:left}
1183
2763
  :where(.knobs-ui) :is(.knobs-tl-play,.knobs-tl-edit){all:revert;box-sizing:border-box;font:inherit;color:inherit;letter-spacing:inherit;background:transparent;border:0;margin:0;padding:0;outline:none;box-shadow:none}
1184
2764
  .knobs-tl-transport{flex:none;display:flex;align-items:center;gap:8px;min-width:96px}
1185
- .knobs-ui .knobs-tl-play{flex:none;display:inline-flex;align-items:center;justify-content:center;width:var(--ku-control-h);height:var(--ku-control-h);min-width:22px;min-height:22px;border-radius:calc(var(--ku-radius) * 999);
1186
- background:var(--ku-surface-hi);color:var(--ku-text);cursor:pointer;transition:background .15s,transform .15s var(--ku-ease)}
1187
- .knobs-ui .knobs-tl-play:hover{background:color-mix(in srgb,var(--ku-text) 16%,transparent)}
2765
+ .knobs-ui .knobs-tl-play{flex:none;display:inline-flex;align-items:center;justify-content:center;width:var(--_k-control-h);height:var(--_k-control-h);min-width:22px;min-height:22px;border-radius:calc(var(--_k-radius) * 999);
2766
+ background:var(--_k-fill-selected);color:var(--_k-fg);cursor:pointer;transition:background .15s,transform .15s var(--_ku-ease)}
2767
+ .knobs-ui .knobs-tl-play:hover{background:color-mix(in srgb,var(--_k-fg) 16%,transparent)}
1188
2768
  .knobs-ui .knobs-tl-play:active{transform:scale(.94)}
1189
2769
  .knobs-tl-play svg{width:12px;height:12px}
1190
- .knobs-timeline[data-playing] .knobs-tl-play{background:var(--ku-accent);color:var(--ku-bg)}
2770
+ .knobs-timeline[data-playing] .knobs-tl-play{background:var(--_k-accent);color:var(--_k-bg)}
1191
2771
  .knobs-tl-time{display:flex;flex-direction:column;line-height:1.2;font-variant-numeric:tabular-nums;font-feature-settings:"tnum"}
1192
- .knobs-tl-now{font:var(--ku-font-weight) var(--ku-value-size)/1.2 var(--ku-value-font);font-variant-numeric:tabular-nums;font-feature-settings:"tnum";color:var(--ku-text);white-space:nowrap}
1193
- .knobs-tl-sub{font-size:var(--ku-text-meta);color:var(--ku-dim);white-space:nowrap}
1194
- .knobs-tl-track{position:relative;flex:1;min-width:0;overflow:hidden;border-radius:var(--ku-radius);background:var(--ku-surface);cursor:col-resize;touch-action:none;
1195
- transition:background calc(var(--ku-hover-out) * 1ms)}
1196
- .knobs-timeline:focus-visible .knobs-tl-track,.knobs-timeline[data-keyboard]:focus .knobs-tl-track{background:color-mix(in srgb,var(--ku-surface-hi) 80%,transparent)}
2772
+ .knobs-tl-now{font:var(--_k-weight) var(--_k-value-size)/1.2 var(--_k-value-font);font-variant-numeric:tabular-nums;font-feature-settings:"tnum";color:var(--_k-fg);white-space:nowrap}
2773
+ .knobs-tl-sub{font-size:var(--_k-text-meta);color:var(--_k-fg-3);white-space:nowrap}
2774
+ .knobs-tl-track{position:relative;flex:1;min-width:0;overflow:hidden;border-radius:var(--_k-radius);background:var(--_k-fill);cursor:col-resize;touch-action:none;
2775
+ transition:background calc(var(--_k-hover-out) * 1ms)}
2776
+ .knobs-timeline:focus-visible .knobs-tl-track,.knobs-timeline[data-keyboard]:focus .knobs-tl-track{background:color-mix(in srgb,var(--_k-fill-selected) 80%,transparent)}
1197
2777
  .knobs-tl-ruler{position:absolute;left:0;top:0;height:22px;pointer-events:none}
1198
2778
  .knobs-tl-lane{position:absolute;left:0;right:0;top:22px;bottom:0;pointer-events:none}
1199
2779
  /* Ranges: a soft band through the lane, its edges handles; the loop range in the accent. */
1200
- .knobs-tl-range{position:absolute;left:0;top:0;bottom:0;width:0;background:color-mix(in srgb,var(--ku-text) 6%,transparent);will-change:transform}
1201
- .knobs-tl-range[data-loop]{background:color-mix(in srgb,var(--ku-accent) 11%,transparent)}
1202
- .knobs-tl-range[data-selected]{background:color-mix(in srgb,var(--ku-accent) 18%,transparent)}
2780
+ .knobs-tl-range{position:absolute;left:0;top:0;bottom:0;width:0;background:color-mix(in srgb,var(--_k-fg) 6%,transparent);will-change:transform}
2781
+ .knobs-tl-range[data-loop]{background:color-mix(in srgb,var(--_k-accent) 11%,transparent)}
2782
+ .knobs-tl-range[data-selected]{background:color-mix(in srgb,var(--_k-accent) 18%,transparent)}
1203
2783
  .knobs-tl-edge{position:absolute;top:0;bottom:0;width:9px;cursor:ew-resize}
1204
2784
  .knobs-tl-edge[data-edge="start"]{left:-4px}
1205
2785
  .knobs-tl-edge[data-edge="end"]{right:-5px}
1206
- .knobs-tl-edge::after{content:"";position:absolute;top:0;bottom:0;left:4px;width:1px;background:color-mix(in srgb,var(--ku-accent) 55%,transparent);transition:background .15s,box-shadow .15s}
1207
- .knobs-tl-edge:hover::after,.knobs-tl-range[data-selected] .knobs-tl-edge::after{background:var(--ku-accent);box-shadow:0 0 0 1px color-mix(in srgb,var(--ku-accent) 22%,transparent)}
1208
- .knobs-tl-rlabel{position:absolute;left:5px;bottom:3px;padding:0 5px;border-radius:max(0px,calc(var(--ku-radius) - 3px));font-size:var(--ku-text-meta);line-height:16px;color:var(--ku-label);cursor:grab;white-space:nowrap}
2786
+ .knobs-tl-edge::after{content:"";position:absolute;top:0;bottom:0;left:4px;width:1px;background:color-mix(in srgb,var(--_k-accent) 55%,transparent);transition:background .15s,box-shadow .15s}
2787
+ .knobs-tl-edge:hover::after,.knobs-tl-range[data-selected] .knobs-tl-edge::after{background:var(--_k-accent);box-shadow:0 0 0 1px color-mix(in srgb,var(--_k-accent) 22%,transparent)}
2788
+ .knobs-tl-rlabel{position:absolute;left:5px;bottom:3px;padding:0 5px;border-radius:max(0px,calc(var(--_k-radius) - 3px));font-size:var(--_k-text-meta);line-height:16px;color:var(--_k-fg-2);cursor:grab;white-space:nowrap}
1209
2789
  .knobs-tl-rlabel:empty{display:none}
1210
- .knobs-tl-rlabel:hover{background:var(--ku-wash-hi);color:var(--ku-text)}
2790
+ .knobs-tl-rlabel:hover{background:var(--_ku-wash-hi);color:var(--_k-fg)}
1211
2791
  /* Markers: a diamond on the ruler's edge and a label chip below it. */
1212
- .knobs-tl-marker{position:absolute;left:0;top:-22px;bottom:0;width:0;will-change:transform;pointer-events:none;--knobs-tl-c:var(--knobs-tl-color,var(--ku-label))}
2792
+ .knobs-tl-marker{position:absolute;left:0;top:-22px;bottom:0;width:0;will-change:transform;pointer-events:none;--knobs-tl-c:var(--knobs-tl-color,var(--_k-fg-2))}
1213
2793
  .knobs-tl-marker::before{content:"";position:absolute;top:22px;bottom:0;left:-.5px;width:1px;background:color-mix(in srgb,var(--knobs-tl-c) 40%,transparent)}
1214
2794
  .knobs-tl-pin{position:absolute;top:13px;left:-5px;width:10px;height:10px;pointer-events:auto;cursor:grab}
1215
- .knobs-tl-pin::after{content:"";position:absolute;inset:1.5px;border-radius:min(2px,var(--ku-radius));background:var(--knobs-tl-c);rotate:45deg;transition:background .15s,scale .2s var(--ku-ease)}
1216
- .knobs-tl-mlabel{position:absolute;top:26px;left:3px;max-width:140px;padding:0 6px;border-radius:max(0px,calc(var(--ku-radius) - 3px));background:var(--ku-surface-hi);color:var(--ku-text);
1217
- font-size:var(--ku-text-meta);line-height:17px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;pointer-events:auto;cursor:grab;transition:background .15s,color .15s}
1218
- .knobs-tl-marker[data-selected]{--knobs-tl-c:var(--ku-accent)}
1219
- .knobs-tl-marker[data-selected] .knobs-tl-mlabel{background:color-mix(in srgb,var(--ku-accent) 24%,var(--ku-surface-hi))}
2795
+ .knobs-tl-pin::after{content:"";position:absolute;inset:1.5px;border-radius:min(2px,var(--_k-radius));background:var(--knobs-tl-c);rotate:45deg;transition:background .15s,scale .2s var(--_ku-ease)}
2796
+ .knobs-tl-mlabel{position:absolute;top:26px;left:3px;max-width:140px;padding:0 6px;border-radius:max(0px,calc(var(--_k-radius) - 3px));background:var(--_k-fill-selected);color:var(--_k-fg);
2797
+ font-size:var(--_k-text-meta);line-height:17px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;pointer-events:auto;cursor:grab;transition:background .15s,color .15s}
2798
+ .knobs-tl-marker[data-selected]{--knobs-tl-c:var(--_k-accent)}
2799
+ .knobs-tl-marker[data-selected] .knobs-tl-mlabel{background:color-mix(in srgb,var(--_k-accent) 24%,var(--_k-fill-selected))}
1220
2800
  .knobs-tl-marker[data-selected] .knobs-tl-pin::after{scale:1.2}
1221
2801
  .knobs-timeline[data-dragging] .knobs-tl-marker[data-selected] :is(.knobs-tl-pin,.knobs-tl-mlabel){cursor:grabbing}
1222
2802
  .knobs-tl-marker[data-editing] .knobs-tl-mlabel{visibility:hidden}
1223
- .knobs-ui .knobs-tl-edit{position:absolute;top:26px;left:3px;width:120px;height:17px;padding:0 6px;font-size:var(--ku-text-meta);color:var(--ku-text);caret-color:var(--ku-accent);
1224
- background:var(--ku-bg);border-radius:max(0px,calc(var(--ku-radius) - 3px));box-shadow:inset 0 -1px 0 var(--ku-text);pointer-events:auto}
2803
+ .knobs-ui .knobs-tl-edit{position:absolute;top:26px;left:3px;width:120px;height:17px;padding:0 6px;font-size:var(--_k-text-meta);color:var(--_k-fg);caret-color:var(--_k-accent);
2804
+ background:var(--_k-bg);border-radius:max(0px,calc(var(--_k-radius) - 3px));box-shadow:inset 0 -1px 0 var(--_k-fg);pointer-events:auto}
1225
2805
  /* The playhead: an accent hairline with a rounded cap in the ruler; it glows a little while held
1226
2806
  on a marker. */
1227
2807
  .knobs-tl-head{position:absolute;left:0;top:0;bottom:0;width:0;will-change:transform;pointer-events:none}
1228
- .knobs-tl-head::before{content:"";position:absolute;top:4px;bottom:0;left:-.75px;width:1.5px;background:var(--ku-accent)}
1229
- .knobs-tl-head::after{content:"";position:absolute;top:3px;left:-4.5px;width:9px;height:13px;border-radius:min(4.5px,var(--ku-radius)) min(4.5px,var(--ku-radius)) min(4.5px,var(--ku-radius)) min(4.5px,var(--ku-radius));
1230
- background:var(--ku-accent);box-shadow:0 1px 3px rgba(0,0,0,calc(.3 * var(--k-lift,1)));transition:box-shadow .15s,scale .18s var(--ku-ease)}
2808
+ .knobs-tl-head::before{content:"";position:absolute;top:4px;bottom:0;left:-.75px;width:1.5px;background:var(--_k-accent)}
2809
+ .knobs-tl-head::after{content:"";position:absolute;top:3px;left:-4.5px;width:9px;height:13px;border-radius:min(4.5px,var(--_k-radius)) min(4.5px,var(--_k-radius)) min(4.5px,var(--_k-radius)) min(4.5px,var(--_k-radius));
2810
+ background:var(--_k-accent);box-shadow:0 1px 3px rgba(0,0,0,calc(.3 * var(--k-lift,1)));transition:box-shadow .15s,scale .18s var(--_ku-ease)}
1231
2811
  .knobs-timeline[data-scrubbing] .knobs-tl-head::after{scale:1.12}
1232
- .knobs-timeline[data-stuck] .knobs-tl-head::after{box-shadow:0 0 0 3px color-mix(in srgb,var(--ku-accent) 26%,transparent)}
1233
- .knobs-tl-hover{position:absolute;left:0;top:0;bottom:0;width:1px;margin-left:-.5px;background:var(--ku-line-hi);transform:translateX(-100px);pointer-events:none;opacity:0;transition:opacity .15s}
2812
+ .knobs-timeline[data-stuck] .knobs-tl-head::after{box-shadow:0 0 0 3px color-mix(in srgb,var(--_k-accent) 26%,transparent)}
2813
+ .knobs-tl-hover{position:absolute;left:0;top:0;bottom:0;width:1px;margin-left:-.5px;background:var(--_k-border-strong);transform:translateX(-100px);pointer-events:none;opacity:0;transition:opacity .15s}
1234
2814
  .knobs-tl-track:hover .knobs-tl-hover{opacity:1}
1235
2815
  .knobs-timeline[data-scrubbing] .knobs-tl-hover{opacity:0}
1236
2816
  @media(prefers-reduced-motion:reduce){.knobs-timeline :where(*,::before,::after){transition:none!important}}
1237
2817
  @media(prefers-reduced-motion:reduce){:is(.knobs-tree,.knobs-split>.knobs-divider,.knobs-pane-head,.knobs-pane-rail) :where(*,::before,::after){transition:none!important}}
1238
- `;
2818
+ `, uiCss = () => aliased(css2 + readoutCss + overlayCss + bentoCss + activityCss + pickerCss + compareCss) + rolling_css_default, lookDefaults, tune = (s, m) => {
2819
+ s.omega = m.omega;
2820
+ s.zeta = m.zeta;
2821
+ return s;
2822
+ }, svg = (body, box = 16) => `<svg viewBox="0 0 ${box} ${box}" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">${body}</svg>`, ICONS;
2823
+ var init_look = __esm(() => {
2824
+ init_appearance();
2825
+ init_activity_css();
2826
+ init_picker_css();
2827
+ init_root();
2828
+ init_glide();
2829
+ init_motion();
2830
+ init_keys();
1239
2831
  lookDefaults = { current: {} };
1240
2832
  ICONS = {
1241
2833
  caret: svg('<path d="M6 3.5 10.5 8 6 12.5"/>'),
@@ -1339,73 +2931,73 @@ var storageKey = (id, part) => `knobs:${encodeURIComponent(id)}:${part}:v1`;
1339
2931
  // src/ui/diff-css.ts
1340
2932
  var snappy2, diffCss;
1341
2933
  var init_diff_css = __esm(() => {
1342
- snappy2 = springCss({ duration: 0.25, bounce: 0 });
2934
+ init_motion();
2935
+ snappy2 = springCss(SPRINGS.snappy);
1343
2936
  diffCss = `
1344
2937
  @property --kd-ft{syntax:"<length>";inherits:false;initial-value:0px}
1345
2938
  @property --kd-fb{syntax:"<length>";inherits:false;initial-value:0px}
1346
- :where(.knobs-ui){--kd-add:var(--k-diff-add,color-mix(in oklab,#3fb950 70%,var(--ku-text)));--kd-del:var(--k-diff-del,color-mix(in oklab,#f0524a 70%,var(--ku-text)));
1347
- --kd-mod:var(--k-diff-mod,color-mix(in oklab,#d29922 72%,var(--ku-text)));--kd-move:var(--k-diff-move,color-mix(in oklab,#58a6ff 68%,var(--ku-text)))}
2939
+ :where(.knobs-ui){--kd-add:var(--_k-diff-add);--kd-del:var(--_k-diff-del);--kd-mod:var(--_k-diff-mod);--kd-move:var(--k-diff-move,var(--_k-info))}
1348
2940
  :where(.knobs-diff,.knobs-diff *,.knobs-diff-files,.knobs-diff-files *){box-sizing:border-box}
1349
- .knobs-ui.knobs-diff{--kd-bg:var(--k-diff-bg,var(--ku-bg));--kd-solid:var(--kd-fill,var(--kd-bg));--kd-line:calc(var(--ku-font-size) * 1.5);
1350
- --kd-i:var(--k-diff-inset,8px);--kd-x:var(--kd-i);--kd-inner:max(3px,calc(var(--ku-pane-radius) - var(--kd-i)));--kd-ctl:var(--kd-inner);
1351
- --kd-head:calc(var(--ku-control-h) + 2 * var(--kd-i));--kd-fade:var(--k-diff-fade,20px);--kd-stick:0px;position:relative;display:flex;flex-direction:column;width:100%;height:100%;min-width:0;min-height:0;overflow:hidden;
1352
- background:var(--kd-bg);border-radius:var(--ku-pane-radius);font:var(--ku-font-weight) var(--ku-font-size)/1.35 var(--ku-font);color:var(--ku-text);text-align:left;
2941
+ .knobs-ui.knobs-diff{--kd-bg:var(--k-diff-bg,var(--_kd-bg,var(--_k-bg)));--kd-solid:var(--kd-fill,var(--kd-bg));--kd-line:calc(var(--_k-font-size) * 1.5);
2942
+ --kd-i:var(--k-diff-inset,8px);--kd-x:var(--kd-i);--kd-inner:max(3px,calc(var(--_ku-pane-radius) - var(--kd-i)));--kd-ctl:var(--kd-inner);
2943
+ --kd-head:calc(var(--_k-control-h) + 2 * var(--kd-i));--kd-fade:var(--k-diff-fade,20px);--kd-stick:0px;position:relative;display:flex;flex-direction:column;width:100%;height:100%;min-width:0;min-height:0;overflow:hidden;
2944
+ background:var(--kd-bg);border-radius:var(--_ku-pane-radius);font:var(--_k-weight) var(--_k-font-size)/1.35 var(--_k-font);color:var(--_k-fg);text-align:left;
1353
2945
  letter-spacing:normal;word-spacing:normal;text-transform:none;-webkit-font-smoothing:antialiased}
1354
2946
  .knobs-ui.knobs-diff[data-height="auto"]{height:auto}
1355
- .knobs-diff::after{content:"";position:absolute;inset:0;z-index:3;border-radius:inherit;box-shadow:var(--ku-pane-ring);pointer-events:none}
2947
+ .knobs-diff::after{content:"";position:absolute;inset:0;z-index:3;border-radius:inherit;box-shadow:var(--_ku-pane-ring);pointer-events:none}
1356
2948
  .knobs-diff [hidden],.knobs-diff-files [hidden]{display:none!important}
1357
2949
  .knobs-diff svg{display:block;flex:none}
1358
- .knobs-ui.knobs-diff[data-on="surface"]{--kd-x:0px;--kd-head:var(--ku-control-h);--kd-ctl:var(--ku-radius)}
2950
+ .knobs-ui.knobs-diff[data-on="surface"]{--kd-x:0px;--kd-head:var(--_k-control-h);--kd-ctl:var(--_k-radius)}
1359
2951
  /* The header's hairline shows only once the code has scrolled under it. */
1360
2952
  .knobs-diff-head{position:relative;z-index:1;flex:none;display:flex;align-items:center;gap:8px;height:var(--kd-head);padding:0 var(--kd-x);
1361
2953
  box-shadow:inset 0 -1px transparent;transition:box-shadow .15s;user-select:none;-webkit-user-select:none}
1362
- .knobs-diff[data-scrolled]>.knobs-diff-head{box-shadow:inset 0 -1px var(--ku-line)}
2954
+ .knobs-diff[data-scrolled]>.knobs-diff-head{box-shadow:inset 0 -1px var(--_k-border)}
1363
2955
  .knobs-diff-path{flex:0 1 auto;min-width:0;overflow:hidden;white-space:nowrap}
1364
- .knobs-diff-dir,.knobs-diff-from{color:var(--ku-dim)}
1365
- .knobs-diff-base{color:var(--ku-text);font-weight:var(--ku-title-weight)}
2956
+ .knobs-diff-dir,.knobs-diff-from{color:var(--_k-fg-3)}
2957
+ .knobs-diff-base{color:var(--_k-fg);font-weight:var(--_k-weight-title)}
1366
2958
  .knobs-diff-stat,.knobs-diff-counts{flex:none;display:inline-flex;gap:6px;font-variant-numeric:tabular-nums;font-feature-settings:"tnum"}
1367
- .knobs-diff-stat{font-size:var(--ku-text-meta);align-items:center}
2959
+ .knobs-diff-stat{font-size:var(--_k-text-meta);align-items:center}
1368
2960
  /* +/− as five squares, GitHub's way. */
1369
2961
  .knobs-diff-bar{display:inline-flex;gap:1px;margin-left:1px}
1370
- .knobs-diff-bar>i{width:6px;height:6px;border-radius:1.5px;background:color-mix(in srgb,var(--ku-text) 14%,transparent)}
2962
+ .knobs-diff-bar>i{width:6px;height:6px;border-radius:1.5px;background:color-mix(in srgb,var(--_k-fg) 14%,transparent)}
1371
2963
  .knobs-diff-bar>i[data-kind="add"]{background:var(--kd-add)}
1372
2964
  .knobs-diff-bar>i[data-kind="del"]{background:var(--kd-del)}
1373
2965
  .knobs-diff-add{color:var(--kd-add)}
1374
2966
  .knobs-diff-del{color:var(--kd-del)}
1375
2967
  .knobs-diff-counts>:empty{display:none}
1376
- .knobs-diff-status{font:600 calc(var(--ku-font-size) - 2px)/1 var(--ku-mono);color:var(--ku-dim)}
2968
+ .knobs-diff-status{font:600 calc(var(--_k-font-size) - 2px)/1 var(--_k-mono);color:var(--_k-fg-3)}
1377
2969
  .knobs-diff-status[data-change="change"]{color:var(--kd-mod)}
1378
2970
  .knobs-diff-status[data-change="new"]{color:var(--kd-add)}
1379
2971
  .knobs-diff-status[data-change="deleted"]{color:var(--kd-del)}
1380
2972
  .knobs-diff-status[data-change="rename"]{color:var(--kd-move)}
1381
2973
  .knobs-diff-fill{flex:1}
1382
- .knobs-diff-nav{flex:none;display:inline-flex;align-items:center;gap:1px;color:var(--ku-dim);font-size:var(--ku-text-meta);font-variant-numeric:tabular-nums}
2974
+ .knobs-diff-nav{flex:none;display:inline-flex;align-items:center;gap:1px;color:var(--_k-fg-3);font-size:var(--_k-text-meta);font-variant-numeric:tabular-nums}
1383
2975
  .knobs-diff-nav>span{min-width:3.6em;text-align:center}
1384
2976
  :where(.knobs-ui) :is(.knobs-diff-btn,.knobs-diff-seg>button,.knobs-diff-viewed,.knobs-diff-filter>input,.knobs-diff-filter>button){all:revert;box-sizing:border-box;font:inherit;color:inherit;letter-spacing:inherit;background:transparent;border:0;border-radius:0;
1385
2977
  margin:0;padding:0;min-width:0;box-shadow:none;outline:none}
1386
- .knobs-ui .knobs-diff-btn{flex:none;display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:calc(var(--ku-radius) * 999);color:var(--ku-dim);cursor:pointer;
2978
+ .knobs-ui .knobs-diff-btn{flex:none;display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:calc(var(--_k-radius) * 999);color:var(--_k-fg-3);cursor:pointer;
1387
2979
  transition:background .15s,color .15s,opacity .15s}
1388
- .knobs-ui .knobs-diff-btn:is(:hover,:focus-visible){background:var(--ku-wash-hi);color:var(--ku-text)}
1389
- .knobs-ui .knobs-diff-btn[aria-pressed="true"]{color:var(--ku-text);background:var(--ku-wash)}
2980
+ .knobs-ui .knobs-diff-btn:is(:hover,:focus-visible){background:var(--_ku-wash-hi);color:var(--_k-fg)}
2981
+ .knobs-ui .knobs-diff-btn[aria-pressed="true"]{color:var(--_k-fg);background:var(--_ku-wash)}
1390
2982
  .knobs-ui .knobs-diff-btn:disabled{opacity:.35;cursor:default;background:transparent}
1391
2983
  .knobs-diff-btn svg{width:13px;height:13px}
1392
2984
  /* Viewed: a check with its word, as on GitHub; the path dims once it's ticked. */
1393
- .knobs-ui .knobs-diff-viewed{flex:none;display:inline-flex;align-items:center;gap:5px;height:var(--ku-control-h);padding:0 8px 0 6px;border-radius:var(--kd-ctl);color:var(--ku-label);
1394
- font-size:var(--ku-text-meta);font-weight:var(--ku-label-weight);white-space:nowrap;cursor:pointer;transition:background .15s,color .15s}
1395
- .knobs-ui .knobs-diff-viewed:is(:hover,:focus-visible){background:var(--ku-wash-hi);color:var(--ku-text)}
1396
- .knobs-ui .knobs-diff-viewed[aria-pressed="true"]{color:var(--ku-text);background:var(--ku-wash)}
2985
+ .knobs-ui .knobs-diff-viewed{flex:none;display:inline-flex;align-items:center;gap:5px;height:var(--_k-control-h);padding:0 8px 0 6px;border-radius:var(--kd-ctl);color:var(--_k-fg-2);
2986
+ font-size:var(--_k-text-meta);font-weight:var(--_k-weight-label);white-space:nowrap;cursor:pointer;transition:background .15s,color .15s}
2987
+ .knobs-ui .knobs-diff-viewed:is(:hover,:focus-visible){background:var(--_ku-wash-hi);color:var(--_k-fg)}
2988
+ .knobs-ui .knobs-diff-viewed[aria-pressed="true"]{color:var(--_k-fg);background:var(--_ku-wash)}
1397
2989
  .knobs-diff-viewed svg{width:13px;height:13px}
1398
2990
  .knobs-diff-viewed[aria-pressed="true"] svg{color:var(--kd-add)}
1399
2991
  .knobs-diff-path{transition:opacity .2s}
1400
2992
  .knobs-diff[data-viewed]>.knobs-diff-head .knobs-diff-path,.knobs-diff-part[data-viewed] .knobs-diff-path{opacity:.6}
1401
2993
  /* Split | Unified: one pill that glides between the two, raised as a panel's segments are (a
1402
2994
  lighter bg in dark, near white in light). */
1403
- .knobs-diff-seg{position:relative;flex:none;display:grid;grid-template-columns:1fr 1fr;height:var(--ku-control-h);padding:2px;border-radius:var(--kd-ctl);background:var(--ku-seg-bg)}
1404
- .knobs-ui .knobs-diff-seg>button{position:relative;z-index:1;padding:0 9px;border-radius:max(0px,calc(var(--kd-ctl) - 2px));color:var(--ku-label);font-size:var(--ku-text-meta);
1405
- font-weight:var(--ku-label-weight);white-space:nowrap;cursor:pointer;transition:color .15s}
1406
- .knobs-ui .knobs-diff-seg>button:is(:hover,:focus-visible),.knobs-ui .knobs-diff-seg>button[aria-checked="true"]{color:var(--ku-text)}
1407
- .knobs-diff-pill{position:absolute;top:2px;bottom:2px;left:2px;width:calc(50% - 2px);border-radius:max(0px,calc(var(--kd-ctl) - 2px));background:var(--k-pill-bg,color-mix(in oklab,var(--ku-bg) 88%,#fff));
1408
- box-shadow:0 1px 2px rgba(0,0,0,calc(.16 * var(--k-lift,1)));transition:transform var(--ku-ease-ms) var(--ku-ease)}
2995
+ .knobs-diff-seg{position:relative;flex:none;display:grid;grid-template-columns:1fr 1fr;height:var(--_k-control-h);padding:2px;border-radius:var(--kd-ctl);background:var(--_k-segmented-track)}
2996
+ .knobs-ui .knobs-diff-seg>button{position:relative;z-index:1;padding:0 9px;border-radius:max(0px,calc(var(--kd-ctl) - 2px));color:var(--_k-fg-2);font-size:var(--_k-text-meta);
2997
+ font-weight:var(--_k-weight-label);white-space:nowrap;cursor:pointer;transition:color .15s}
2998
+ .knobs-ui .knobs-diff-seg>button:is(:hover,:focus-visible),.knobs-ui .knobs-diff-seg>button[aria-checked="true"]{color:var(--_k-fg)}
2999
+ .knobs-diff-pill{position:absolute;top:2px;bottom:2px;left:2px;width:calc(50% - 2px);border-radius:max(0px,calc(var(--kd-ctl) - 2px));background:color-mix(in srgb,var(--_k-accent) 18%,var(--_k-segmented-active));
3000
+ box-shadow:0 1px 2px rgba(0,0,0,calc(.16 * var(--k-lift,1)));transition:transform var(--_ku-ease-ms) var(--_ku-ease)}
1409
3001
  .knobs-diff-seg[data-value="unified"]>.knobs-diff-pill{transform:translateX(100%)}
1410
3002
  .knobs-diff[data-frame="flat"] .knobs-diff-pill{box-shadow:none}
1411
3003
  /* The diff: one layer per file or layout on show, the old fading under the new. */
@@ -1426,30 +3018,30 @@ var init_diff_css = __esm(() => {
1426
3018
  .knobs-diff-scroll::-webkit-scrollbar{display:none;width:0;height:0}
1427
3019
  .knobs-diff-layer{position:absolute;inset:0;z-index:4;pointer-events:none;overflow:hidden}
1428
3020
  .knobs-diff-hbar{position:absolute;height:5px;pointer-events:none}
1429
- .knobs-diff-hbar>i{position:absolute;left:0;top:0;height:5px;border-radius:3px;background:color-mix(in srgb,var(--ku-text) 30%,transparent);opacity:0;pointer-events:none;
3021
+ .knobs-diff-hbar>i{position:absolute;left:0;top:0;height:5px;border-radius:3px;background:color-mix(in srgb,var(--_k-fg) 30%,transparent);opacity:0;pointer-events:none;
1430
3022
  transition:opacity .3s,background .15s}
1431
3023
  .knobs-diff-body:hover .knobs-diff-hbar>i,.knobs-diff-hbar:is([data-active],[data-dragging])>i{opacity:1;pointer-events:auto;transition-duration:.12s,.15s}
1432
- .knobs-diff-hbar>i:hover,.knobs-diff-hbar[data-dragging]>i{background:color-mix(in srgb,var(--ku-text) 48%,transparent)}
3024
+ .knobs-diff-hbar>i:hover,.knobs-diff-hbar[data-dragging]>i{background:color-mix(in srgb,var(--_k-fg) 48%,transparent)}
1433
3025
  /* stack: every file down one scroller, each header sticking until the next pushes it off. It's
1434
3026
  flush (square, no card around its file), opaque in the code's own colour, with a hairline
1435
3027
  under it only while it's stuck; a gap, not a line, parts one file from the next. */
1436
- .knobs-diff[data-stack]{--kd-stick:var(--ku-row)}
3028
+ .knobs-diff[data-stack]{--kd-stick:var(--_k-row)}
1437
3029
  .knobs-diff-part+.knobs-diff-part{margin-top:var(--kd-i)}
1438
- .knobs-diff-part-head{position:sticky;top:0;z-index:2;border-radius:0;display:flex;align-items:center;gap:8px;height:var(--ku-row);padding:0 var(--kd-x);background:var(--kd-solid);
3030
+ .knobs-diff-part-head{position:sticky;top:0;z-index:2;border-radius:0;display:flex;align-items:center;gap:8px;height:var(--_k-row);padding:0 var(--kd-x);background:var(--kd-solid);
1439
3031
  box-shadow:inset 0 0 transparent;transition:box-shadow .15s;user-select:none;-webkit-user-select:none}
1440
- .knobs-diff-part>.knobs-diff-part-head[data-stuck]{box-shadow:inset 0 -1px var(--ku-line)}
1441
- .knobs-diff-part-head .knobs-diff-counts{font-size:var(--ku-text-meta);align-items:center}
3032
+ .knobs-diff-part>.knobs-diff-part-head[data-stuck]{box-shadow:inset 0 -1px var(--_k-border)}
3033
+ .knobs-diff-part-head .knobs-diff-counts{font-size:var(--_k-text-meta);align-items:center}
1442
3034
  .knobs-diff-part-head .knobs-diff-status{flex:none;width:10px}
1443
- .knobs-diff-part-note{padding:var(--kd-i) var(--kd-x);color:var(--ku-dim)}
3035
+ .knobs-diff-part-note{padding:var(--kd-i) var(--kd-x);color:var(--_k-fg-3)}
1444
3036
  .knobs-diff[data-height="auto"] .knobs-diff-scroll{overscroll-behavior:auto}
1445
3037
  .knobs-diff-slot[data-leaving]{pointer-events:none}
1446
- .knobs-diff-note{position:absolute;inset:0;display:grid;place-items:center;padding:12px;color:var(--ku-dim);text-align:center;pointer-events:none;transition:opacity .2s}
1447
- .knobs-diff[data-height="auto"] .knobs-diff-note{position:static;min-height:calc(var(--ku-row) * 2)}
3038
+ .knobs-diff-note{position:absolute;inset:0;display:grid;place-items:center;padding:12px;color:var(--_k-fg-3);text-align:center;pointer-events:none;transition:opacity .2s}
3039
+ .knobs-diff[data-height="auto"] .knobs-diff-note{position:static;min-height:calc(var(--_k-row) * 2)}
1448
3040
  .knobs-diff diffs-container{
1449
3041
  --diffs-bg:var(--kd-solid);
1450
- --diffs-font-family:var(--ku-mono);
1451
- --diffs-header-font-family:var(--ku-font);
1452
- --diffs-font-size:calc(var(--ku-font-size) - .5px);
3042
+ --diffs-font-family:var(--_k-mono);
3043
+ --diffs-header-font-family:var(--_k-font);
3044
+ --diffs-font-size:calc(var(--_k-font-size) - .5px);
1453
3045
  --diffs-line-height:var(--kd-line);
1454
3046
  --diffs-gap-inline:var(--kd-x);
1455
3047
  --diffs-gap-block:var(--kd-i);
@@ -1464,47 +3056,47 @@ var init_diff_css = __esm(() => {
1464
3056
  --diffs-bg-deletion-number-override:color-mix(in srgb,var(--kd-del) 55%,var(--kd-solid));
1465
3057
  --diffs-bg-addition-emphasis-override:color-mix(in srgb,var(--kd-add) 22%,transparent);
1466
3058
  --diffs-bg-deletion-emphasis-override:color-mix(in srgb,var(--kd-del) 22%,transparent);
1467
- --diffs-bg-separator-override:color-mix(in srgb,var(--ku-text) 4.5%,var(--kd-solid));
1468
- --diffs-bg-context-override:color-mix(in srgb,var(--ku-text) 3%,var(--kd-solid));
1469
- --diffs-bg-buffer-override:color-mix(in srgb,var(--ku-text) 3.5%,var(--kd-solid));
1470
- --diffs-bg-selection-override:var(--ku-accent);
1471
- --diffs-fg-number-override:var(--ku-dim);
3059
+ --diffs-bg-separator-override:color-mix(in srgb,var(--_k-fg) 4.5%,var(--kd-solid));
3060
+ --diffs-bg-context-override:color-mix(in srgb,var(--_k-fg) 3%,var(--kd-solid));
3061
+ --diffs-bg-buffer-override:color-mix(in srgb,var(--_k-fg) 3.5%,var(--kd-solid));
3062
+ --diffs-bg-selection-override:var(--_k-accent);
3063
+ --diffs-fg-number-override:var(--_k-fg-3);
1472
3064
  }
1473
3065
  /* diffReview: one card, the file list a drawer at its left (its width springs; the list inside
1474
3066
  is pinned to its right edge, so it slides out from under the diff), parted from the diff by a
1475
3067
  hairline. The diff in it draws no card of its own. */
1476
- .knobs-ui.knobs-diff-review{position:relative;display:flex;width:100%;height:100%;min-width:0;min-height:0;overflow:hidden;border-radius:var(--ku-pane-radius);background:var(--ku-pane-bg);
1477
- font:var(--ku-font-weight) var(--ku-font-size)/1.35 var(--ku-font);color:var(--ku-text);text-align:left;letter-spacing:normal;-webkit-font-smoothing:antialiased}
1478
- .knobs-diff-review::after{content:"";position:absolute;inset:0;z-index:5;border-radius:inherit;box-shadow:var(--ku-pane-ring);pointer-events:none}
3068
+ .knobs-ui.knobs-diff-review{position:relative;display:flex;width:100%;height:100%;min-width:0;min-height:0;overflow:hidden;border-radius:var(--_ku-pane-radius);background:var(--_ku-pane-bg);
3069
+ font:var(--_k-weight) var(--_k-font-size)/1.35 var(--_k-font);color:var(--_k-fg);text-align:left;letter-spacing:normal;-webkit-font-smoothing:antialiased}
3070
+ .knobs-diff-review::after{content:"";position:absolute;inset:0;z-index:5;border-radius:inherit;box-shadow:var(--_ku-pane-ring);pointer-events:none}
1479
3071
  :where(.knobs-diff-review,.knobs-diff-review *){box-sizing:border-box}
1480
- .knobs-diff-drawer{position:relative;flex:none;width:0;height:100%;overflow:hidden;box-shadow:inset -1px 0 var(--ku-line)}
3072
+ .knobs-diff-drawer{position:relative;flex:none;width:0;height:100%;overflow:hidden;box-shadow:inset -1px 0 var(--_k-border)}
1481
3073
  .knobs-diff-drawer[data-shut]{visibility:hidden}
1482
3074
  .knobs-diff-drawer-in{position:absolute;top:0;bottom:0;right:0;display:flex;flex-direction:column}
1483
- .knobs-diff-drawer-head{flex:none;display:flex;align-items:center;gap:6px;height:calc(var(--ku-control-h) + 2 * var(--k-diff-inset,8px));padding:0 var(--k-diff-inset,8px) 0 calc(var(--ku-row-x) + 8px);
3075
+ .knobs-diff-drawer-head{flex:none;display:flex;align-items:center;gap:6px;height:calc(var(--_k-control-h) + 2 * var(--k-diff-inset,8px));padding:0 var(--k-diff-inset,8px) 0 calc(var(--_ku-row-x) + 8px);
1484
3076
  user-select:none;-webkit-user-select:none}
1485
- .knobs-diff-drawer-title{font-weight:var(--ku-title-weight)}
1486
- .knobs-diff-drawer-count{color:var(--ku-dim);font-size:var(--ku-text-meta);font-variant-numeric:tabular-nums}
3077
+ .knobs-diff-drawer-title{font-weight:var(--_k-weight-title)}
3078
+ .knobs-diff-drawer-count{color:var(--_k-fg-3);font-size:var(--_k-text-meta);font-variant-numeric:tabular-nums}
1487
3079
  .knobs-diff-drawer-in>.knobs-diff-files{flex:1;min-height:0;height:auto}
1488
3080
  .knobs-diff-main{position:relative;flex:1;min-width:0;height:100%}
1489
3081
  /* height: "auto": the card as tall as its diff; the drawer stretches to it. */
1490
3082
  .knobs-ui.knobs-diff-review[data-height="auto"],.knobs-diff-review[data-height="auto"]>:is(.knobs-diff-drawer,.knobs-diff-main){height:auto}
1491
- .knobs-diff-review .knobs-ui.knobs-diff{--k-diff-bg:transparent;--ku-pane-ring:none;border-radius:0}
3083
+ .knobs-diff-review .knobs-ui.knobs-diff{--_kd-bg:transparent;--_ku-pane-ring:none;border-radius:0}
1492
3084
  .knobs-ui .knobs-diff-toggle{margin-left:-4px}
1493
3085
  .knobs-ui .knobs-diff-toggle[aria-pressed]:not(:hover,:focus-visible){background:transparent}
1494
3086
  /* diffReview's file list: a filter over a compact tree, a status letter, the counts and their
1495
3087
  bar on each file; one highlight glides to the file on show. Viewed files dim, with a tick. */
1496
3088
  .knobs-diff-files{--k-row:var(--k-diff-row,28px);display:flex;flex-direction:column;height:100%;min-height:0;padding-top:2px}
1497
- .knobs-diff-filter{position:relative;flex:none;display:flex;align-items:center;gap:6px;height:26px;margin:0 var(--ku-row-x) 4px;padding:0 4px 0 8px;
1498
- border-radius:max(6px,var(--ku-row-radius));background:var(--ku-wash);color:var(--ku-dim);box-shadow:inset 0 0 0 1px transparent;transition:background .15s,box-shadow .15s}
1499
- .knobs-diff-filter:focus-within{background:var(--ku-wash-hi);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--ku-accent) 45%,transparent)}
3089
+ .knobs-diff-filter{position:relative;flex:none;display:flex;align-items:center;gap:6px;height:26px;margin:0 var(--_ku-row-x) 4px;padding:0 4px 0 8px;
3090
+ border-radius:max(6px,var(--_ku-row-radius));background:var(--_ku-wash);color:var(--_k-fg-3);box-shadow:inset 0 0 0 1px transparent;transition:background .15s,box-shadow .15s}
3091
+ .knobs-diff-filter:focus-within{background:var(--_ku-wash-hi);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--_k-accent) 45%,transparent)}
1500
3092
  .knobs-diff-filter svg{width:12px;height:12px;flex:none}
1501
- .knobs-ui .knobs-diff-filter>input{flex:1;min-width:0;height:100%;font:var(--ku-font-weight) var(--ku-font-size)/1 var(--ku-font);color:var(--ku-text);caret-color:var(--ku-accent);background:transparent}
1502
- .knobs-ui .knobs-diff-filter>input::placeholder{color:var(--ku-dim)}
1503
- .knobs-ui .knobs-diff-filter>button{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:999px;color:var(--ku-dim);cursor:pointer;transition:background .12s,color .12s,opacity .12s}
1504
- .knobs-ui .knobs-diff-filter>button:hover{background:var(--ku-wash-hi);color:var(--ku-text)}
3093
+ .knobs-ui .knobs-diff-filter>input{flex:1;min-width:0;height:100%;font:var(--_k-weight) var(--_k-font-size)/1 var(--_k-font);color:var(--_k-fg);caret-color:var(--_k-accent);background:transparent}
3094
+ .knobs-ui .knobs-diff-filter>input::placeholder{color:var(--_k-fg-3)}
3095
+ .knobs-ui .knobs-diff-filter>button{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:999px;color:var(--_k-fg-3);cursor:pointer;transition:background .12s,color .12s,opacity .12s}
3096
+ .knobs-ui .knobs-diff-filter>button:hover{background:var(--_ku-wash-hi);color:var(--_k-fg)}
1505
3097
  .knobs-diff-filter>button svg{width:10px;height:10px}
1506
3098
  .knobs-diff-list{position:relative;flex:1;min-height:0}
1507
- .knobs-diff-files .knobs-diff-counts{font-size:var(--ku-text-meta);align-items:center}
3099
+ .knobs-diff-files .knobs-diff-counts{font-size:var(--_k-text-meta);align-items:center}
1508
3100
  .knobs-diff-files .knobs-diff-counts{gap:5px}
1509
3101
  .knobs-diff-files .knobs-diff-bar{margin-left:0}
1510
3102
  .knobs-diff-files .knobs-diff-bar>i{width:4px;height:4px;border-radius:1px}
@@ -2219,6 +3811,40 @@ function parseCssColor(raw, fallback = [1, 1, 1, 1]) {
2219
3811
  cache.set(s, out);
2220
3812
  return out;
2221
3813
  }
3814
+ function pickScheme(raw, light) {
3815
+ let s = raw;
3816
+ for (let at = s.lastIndexOf("light-dark(");at >= 0; at = s.lastIndexOf("light-dark(")) {
3817
+ let depth = 0;
3818
+ let comma = -1;
3819
+ let end = -1;
3820
+ for (let i = at + 11;i < s.length; i++) {
3821
+ const ch = s[i];
3822
+ if (ch === "(")
3823
+ depth++;
3824
+ else if (ch === ")") {
3825
+ if (depth === 0) {
3826
+ end = i;
3827
+ break;
3828
+ }
3829
+ depth--;
3830
+ } else if (ch === "," && depth === 0 && comma < 0)
3831
+ comma = i;
3832
+ }
3833
+ if (end < 0 || comma < 0)
3834
+ break;
3835
+ const side = light ? s.slice(at + 11, comma) : s.slice(comma + 1, end);
3836
+ s = s.slice(0, at) + side.trim() + s.slice(end + 1);
3837
+ }
3838
+ return s;
3839
+ }
3840
+ function tokenColor(style, name, fallback) {
3841
+ const raw = style.getPropertyValue(name).trim();
3842
+ return raw ? parseCssColor(pickScheme(raw, isLightStyle(style)), fallback) : fallback;
3843
+ }
3844
+ function tokenCss(style, name, fallback) {
3845
+ const raw = style.getPropertyValue(name).trim();
3846
+ return raw ? pickScheme(raw, isLightStyle(style)) : fallback;
3847
+ }
2222
3848
  var cache, probe = null, probeCtx = () => {
2223
3849
  if (probe)
2224
3850
  return probe;
@@ -2230,7 +3856,7 @@ var cache, probe = null, probeCtx = () => {
2230
3856
  probe = c.getContext("2d", { willReadFrequently: true });
2231
3857
  }
2232
3858
  return probe;
2233
- }, rgbaCss = (c) => `rgba(${Math.round(c[0] * 255)},${Math.round(c[1] * 255)},${Math.round(c[2] * 255)},${Math.round(c[3] * 1000) / 1000})`;
3859
+ }, rgbaCss = (c) => `rgba(${Math.round(c[0] * 255)},${Math.round(c[1] * 255)},${Math.round(c[2] * 255)},${Math.round(c[3] * 1000) / 1000})`, isLightStyle = (style) => style.getPropertyValue("--_k-light").trim() === "1";
2234
3860
  var init_rgba = __esm(() => {
2235
3861
  cache = new Map;
2236
3862
  });
@@ -2701,13 +4327,13 @@ function hintTokens(doc, groups) {
2701
4327
  };
2702
4328
  const panel = doc.querySelector(".knobs-panel");
2703
4329
  const piece = groups.find((g) => g.source && !g.source.paint)?.source?.root;
2704
- const pick = (k, fallback) => read(panel, [`--k-${k}`]) || read(piece, [`--ku-${k}`, `--k-${k}`]) || fallback;
4330
+ const pick = (k, fallback) => read(panel, [`--_k-${k}`]) || read(piece, [`--_k-${k}`]) || fallback;
2705
4331
  return {
2706
4332
  "--kh-accent": pick("accent", "#fff"),
2707
4333
  "--kh-bg": pick("bg", "#1c1c1e"),
2708
4334
  "--kh-mono": pick("mono", "ui-monospace,Menlo,monospace"),
2709
- "--kh-radius": read(panel, ["--k-radius-sm"]) || "4px",
2710
- "--kh-size": read(panel, ["--k-text-cap"]) || "10px",
4335
+ "--kh-radius": read(panel, ["--_k-radius-sm"]) || "4px",
4336
+ "--kh-size": read(panel, ["--_k-text-cap"]) || "10px",
2711
4337
  "--kh-typed": read(panel, ["--k-hint-typed-opacity"]) || ".42",
2712
4338
  "--kh-lift": read(panel, ["--k-lift"]) || "1",
2713
4339
  "--kh-ease": read(panel, ["--k-ease"]) || "cubic-bezier(.2,.8,.2,1)"
@@ -3055,7 +4681,7 @@ function tree(container, options) {
3055
4681
  root.setAttribute("aria-multiselectable", "true");
3056
4682
  if (options.label)
3057
4683
  root.setAttribute("aria-label", options.label);
3058
- applyLook(root, options);
4684
+ applyLook2(root, options);
3059
4685
  const space = doc.createElement("div");
3060
4686
  space.className = "knobs-tree-space";
3061
4687
  const line = doc.createElement("div");
@@ -3100,7 +4726,7 @@ function tree(container, options) {
3100
4726
  const measure = () => {
3101
4727
  syncFrame(root);
3102
4728
  const probe = doc.createElement("div");
3103
- probe.style.cssText = "position:absolute;visibility:hidden;height:var(--ku-row);width:var(--ku-indent);padding-left:var(--ku-inset)";
4729
+ probe.style.cssText = "position:absolute;visibility:hidden;height:var(--_k-row);width:var(--_ku-indent);padding-left:var(--_k-inset)";
3104
4730
  root.append(probe);
3105
4731
  const r = probe.getBoundingClientRect();
3106
4732
  h = options.rowHeight ?? (r.height || 26);
@@ -3619,11 +5245,8 @@ function tree(container, options) {
3619
5245
  function beginDrag(id) {
3620
5246
  const ids = topmost(items, access, isSelected(id) ? sel.ids : [id]);
3621
5247
  const ghost = doc.createElement("div");
3622
- ghost.className = "knobs-ui knobs-tree-ghost";
3623
- if (options.preset)
3624
- ghost.dataset.preset = options.preset.name;
3625
- if (options.theme)
3626
- ghost.dataset.theme = options.theme;
5248
+ ghost.className = "knobs-root knobs-ui knobs-tree-ghost";
5249
+ applyLook(ghost, lookAt(root));
3627
5250
  ghost.textContent = ids.length === 1 ? renamed.get(ids[0]) ?? access.label(index.get(ids[0]).item) : `${ids.length} items`;
3628
5251
  doc.body.append(ghost);
3629
5252
  dragging = { ids, ghost, x: press.x, y: press.y, hoverAt: 0, hoverId: null };
@@ -3969,10 +5592,12 @@ function builtinIcon(id, on) {
3969
5592
  }
3970
5593
  var MOVE, EDGE = 28;
3971
5594
  var init_tree = __esm(() => {
5595
+ init_appearance();
5596
+ init_motion();
3972
5597
  init_page_hints();
3973
5598
  init_look();
3974
5599
  init_tree_model();
3975
- MOVE = springMotion({ duration: 0.3, bounce: 0 });
5600
+ MOVE = springMotion(SPRINGS.default);
3976
5601
  });
3977
5602
 
3978
5603
  // src/ui/diff.ts
@@ -3981,7 +5606,7 @@ function injectDiffStyles(doc) {
3981
5606
  return;
3982
5607
  const style = doc.createElement("style");
3983
5608
  style.dataset.knobsUiDiff = "";
3984
- style.textContent = diffCss;
5609
+ style.textContent = aliased(diffCss);
3985
5610
  doc.head.append(style);
3986
5611
  }
3987
5612
  function diffCounts(file, doc = document, options = {}) {
@@ -4037,10 +5662,10 @@ function backdrop(el, view) {
4037
5662
  if (!out)
4038
5663
  return null;
4039
5664
  for (let i = layers.length - 1;i >= 0; i--)
4040
- out = over(layers[i], out);
5665
+ out = over2(layers[i], out);
4041
5666
  return out;
4042
5667
  }
4043
- function over(top, under) {
5668
+ function over2(top, under) {
4044
5669
  const [r, g, b, a] = top;
4045
5670
  const [R, G, B, A] = under;
4046
5671
  const o = a + A * (1 - a);
@@ -4079,7 +5704,7 @@ function codeDiff(container, options) {
4079
5704
  root.dataset.height = auto ? "auto" : "fill";
4080
5705
  if (stack)
4081
5706
  root.dataset.stack = "";
4082
- applyLook(root, options);
5707
+ applyLook2(root, options);
4083
5708
  injectDiffStyles(doc);
4084
5709
  const make = (tag, cls) => {
4085
5710
  const el = doc.createElement(tag);
@@ -4401,7 +6026,7 @@ function codeDiff(container, options) {
4401
6026
  scrolls.set(slot.file, slot.sc.scrollTop);
4402
6027
  slot.leaving = true;
4403
6028
  slot.el.dataset.leaving = "";
4404
- tune(slot.o, reducedMotion(win) ? FADE3 : OUT).set(0);
6029
+ tune(slot.o, reducedMotion(win) ? FADE4 : OUT).set(0);
4405
6030
  };
4406
6031
  const say = (text) => {
4407
6032
  note.textContent = text ?? "";
@@ -4515,7 +6140,7 @@ function codeDiff(container, options) {
4515
6140
  slot.bars.rescan();
4516
6141
  slot.sc.scrollTop = same ? along * (slot.sc.scrollHeight - slot.sc.clientHeight) : scrolls.get(file.name) ?? 0;
4517
6142
  slot.fades.update();
4518
- tune(slot.o, reducedMotion(win) ? FADE3 : IN).snap(0).set(1);
6143
+ tune(slot.o, reducedMotion(win) ? FADE4 : IN).snap(0).set(1);
4519
6144
  style(slot);
4520
6145
  live.push(slot);
4521
6146
  sizes.disconnect();
@@ -4830,7 +6455,7 @@ function codeDiff(container, options) {
4830
6455
  return;
4831
6456
  const behind = backdrop(root.parentElement, win);
4832
6457
  if (behind)
4833
- root.style.setProperty("--kd-fill", rgbaCss(over(own, behind)));
6458
+ root.style.setProperty("--kd-fill", rgbaCss(over2(own, behind)));
4834
6459
  };
4835
6460
  const rescheme = () => {
4836
6461
  syncFrame(root);
@@ -5043,7 +6668,8 @@ function diffReview(container, options) {
5043
6668
  const doc = container.ownerDocument;
5044
6669
  const look = {
5045
6670
  ...options.preset ? { preset: options.preset } : {},
5046
- ...options.theme ? { theme: options.theme } : {}
6671
+ ...options.theme ? { theme: options.theme } : {},
6672
+ ...options.appearance ? { appearance: options.appearance } : {}
5047
6673
  };
5048
6674
  const title = options.title ?? "Files";
5049
6675
  const store = options.storage === undefined ? browserStorage() : options.storage;
@@ -5066,7 +6692,7 @@ function diffReview(container, options) {
5066
6692
  const root = doc.createElement("div");
5067
6693
  root.className = "knobs-diff-review";
5068
6694
  root.dataset.height = options.height ?? "fill";
5069
- applyLook(root, look);
6695
+ applyLook2(root, look);
5070
6696
  injectDiffStyles(doc);
5071
6697
  const drawer = doc.createElement("div");
5072
6698
  drawer.className = "knobs-diff-drawer";
@@ -5370,19 +6996,21 @@ function diffReview(container, options) {
5370
6996
  }
5371
6997
  };
5372
6998
  }
5373
- var lib, load = () => lib ??= import("@pierre/diffs"), SYNTAX, IN, OUT, FADE3, HEIGHT, DRAWER, BLUR = 3, WRAP, PREV, UNVIEWED, VIEWED, SEARCH, CLEAR2, SIDEBAR, SEPARATOR = 32;
6999
+ var lib, load = () => lib ??= import("@pierre/diffs"), SYNTAX, IN, OUT, FADE4, HEIGHT, DRAWER, BLUR = 3, WRAP, PREV, UNVIEWED, VIEWED, SEARCH, CLEAR2, SIDEBAR, SEPARATOR = 32;
5374
7000
  var init_diff = __esm(() => {
7001
+ init_glide();
7002
+ init_motion();
5375
7003
  init_diff_css();
5376
7004
  init_diff_model();
5377
7005
  init_look();
5378
7006
  init_rgba();
5379
7007
  init_tree();
5380
7008
  SYNTAX = { dark: "pierre-dark", light: "pierre-light" };
5381
- IN = springMotion({ duration: 0.3, bounce: 0 });
5382
- OUT = springMotion({ duration: 0.24, bounce: 0 });
5383
- FADE3 = springMotion({ duration: 0.16, bounce: 0 });
5384
- HEIGHT = springMotion({ duration: 0.4, bounce: 0 });
5385
- DRAWER = springMotion({ duration: 0.4, bounce: 0 });
7009
+ IN = springMotion(SPRINGS.default);
7010
+ OUT = springMotion(SPRINGS.snappy);
7011
+ FADE4 = springMotion(FADE);
7012
+ HEIGHT = springMotion(SPRINGS.calm);
7013
+ DRAWER = springMotion(SPRINGS.calm);
5386
7014
  WRAP = svg('<path d="M2.5 4h11"/><path d="M2.5 8h9a2 2 0 0 1 0 4H8.5"/><path d="M10 10.5 8.5 12l1.5 1.5"/><path d="M2.5 12h3"/>');
5387
7015
  PREV = svg('<path d="M10 3.5 5.5 8l4.5 4.5"/>');
5388
7016
  UNVIEWED = svg('<circle cx="8" cy="8" r="5.5"/>');
@@ -5407,7 +7035,7 @@ function layerElement(doc, cls, look) {
5407
7035
  const el = doc.createElement("div");
5408
7036
  el.className = cls;
5409
7037
  layerRoot(doc).append(el);
5410
- applyLook(el, lookOf(look));
7038
+ applyLook2(el, lookOf(look));
5411
7039
  return el;
5412
7040
  }
5413
7041
  function presence(el, o = {}) {
@@ -5446,7 +7074,7 @@ function presence(el, o = {}) {
5446
7074
  });
5447
7075
  const tune = (seconds, zeta) => {
5448
7076
  const reduced = reducedMotion(win);
5449
- spring.omega = 2 * Math.PI / (reduced ? 0.16 : seconds);
7077
+ spring.omega = 2 * Math.PI / (reduced ? FADE.duration : seconds);
5450
7078
  spring.zeta = reduced ? 1 : zeta;
5451
7079
  };
5452
7080
  render();
@@ -5574,6 +7202,7 @@ var lookOf = (look) => ({ ...lookDefaults.current, ...look }), roots, stacks, FO
5574
7202
  h: doc.documentElement.clientHeight
5575
7203
  });
5576
7204
  var init_layer = __esm(() => {
7205
+ init_motion();
5577
7206
  init_look();
5578
7207
  roots = new WeakMap;
5579
7208
  stacks = new WeakMap;
@@ -5668,7 +7297,7 @@ function softClamp(x, min, max, knee = 12) {
5668
7297
  return min + k * Math.exp(-(min + k - x) / k);
5669
7298
  return x;
5670
7299
  }
5671
- function solve(input) {
7300
+ function solve2(input) {
5672
7301
  const { panes, sizes, collapsed, fixed = {} } = input;
5673
7302
  const rail = input.rail ?? (() => 0);
5674
7303
  const room = Math.max(0, input.total - (input.divider ?? 1) * Math.max(0, panes.length - 1));
@@ -5790,15 +7419,15 @@ function foldProgress(size, open, rail) {
5790
7419
  return Math.min(1, Math.max(0, (open - size) / span));
5791
7420
  }
5792
7421
  function face(prev, away) {
5793
- const lo = clamp01(1 - away / FACE_IN);
5794
- const hi = clamp01(1 - away / FACE_OUT);
7422
+ const lo = clamp012(1 - away / FACE_IN);
7423
+ const hi = clamp012(1 - away / FACE_OUT);
5795
7424
  return Math.min(hi, Math.max(lo, prev));
5796
7425
  }
5797
7426
  function foldFaces(prev, p) {
5798
7427
  return { content: face(prev.content, p), rail: face(prev.rail, 1 - p) };
5799
7428
  }
5800
7429
  function chevronTurn(p, edge) {
5801
- return (edge === "start" ? 180 : -180) * (1 - clamp01(p));
7430
+ return (edge === "start" ? 180 : -180) * (1 - clamp012(p));
5802
7431
  }
5803
7432
  function chevronFlip(f, edge) {
5804
7433
  return chevronTurn(f, edge);
@@ -5812,7 +7441,7 @@ function foldStyle(options = {}) {
5812
7441
  };
5813
7442
  }
5814
7443
  function titleTravel(at, open, rail, edge, p) {
5815
- const k = 1 - clamp01(p);
7444
+ const k = 1 - clamp012(p);
5816
7445
  const dx = at.title - at.label - (edge === "start" ? open - rail : 0);
5817
7446
  return { x: dx * k, y: at.dy * k, turn: -90 * k };
5818
7447
  }
@@ -5841,7 +7470,7 @@ function serializeLayout(layout) {
5841
7470
  collapsed[id] = true;
5842
7471
  return JSON.stringify({ sizes, collapsed });
5843
7472
  }
5844
- var DEFAULT_MIN = 48, COLLAPSE_PAST = 40, paneMin = (p) => Math.max(0, p.min ?? DEFAULT_MIN), paneMax = (p) => Math.max(paneMin(p), p.max ?? Number.POSITIVE_INFINITY), FACE_OUT = 0.4, FACE_IN = 0.3, clamp01 = (x) => Math.min(1, Math.max(0, x)), FOLD_STYLE;
7473
+ var DEFAULT_MIN = 48, COLLAPSE_PAST = 40, paneMin = (p) => Math.max(0, p.min ?? DEFAULT_MIN), paneMax = (p) => Math.max(paneMin(p), p.max ?? Number.POSITIVE_INFINITY), FACE_OUT = 0.4, FACE_IN = 0.3, clamp012 = (x) => Math.min(1, Math.max(0, x)), FOLD_STYLE;
5845
7474
  var init_split_model = __esm(() => {
5846
7475
  FOLD_STYLE = { chevron: "flip", title: "travel", duration: 0.25 };
5847
7476
  });
@@ -6419,7 +8048,7 @@ function timeline(container, options) {
6419
8048
  root.setAttribute("aria-roledescription", "timeline");
6420
8049
  root.setAttribute("aria-label", options.label ?? "Timeline");
6421
8050
  root.setAttribute("aria-keyshortcuts", "Space ArrowLeft ArrowRight , . Home End [ ] I O M");
6422
- applyLook(root, options);
8051
+ applyLook2(root, options);
6423
8052
  const transport = el("div", "knobs-tl-transport");
6424
8053
  const playBtn = el("button", "knobs-tl-play");
6425
8054
  playBtn.type = "button";
@@ -6476,11 +8105,11 @@ function timeline(container, options) {
6476
8105
  const readColors = () => {
6477
8106
  const cs = win.getComputedStyle(root);
6478
8107
  colors = {
6479
- tick: cs.getPropertyValue("--ku-line-hi").trim() || "rgba(255,255,255,.18)",
6480
- major: cs.getPropertyValue("--ku-dim").trim() || "rgba(255,255,255,.42)",
6481
- label: cs.getPropertyValue("--ku-label").trim() || "rgba(255,255,255,.64)",
6482
- line: cs.getPropertyValue("--ku-line").trim() || "rgba(255,255,255,.1)",
6483
- font: `${cs.getPropertyValue("--ku-font-weight").trim() || 400} ${cs.getPropertyValue("--ku-text-meta").trim() || "11px"} ${cs.getPropertyValue("--ku-font").trim() || "system-ui"}`
8108
+ tick: tokenCss(cs, "--kv-border-strong", "rgba(255,255,255,.18)"),
8109
+ major: tokenCss(cs, "--kv-fg-3", "rgba(255,255,255,.42)"),
8110
+ label: tokenCss(cs, "--kv-fg-2", "rgba(255,255,255,.64)"),
8111
+ line: tokenCss(cs, "--kv-border", "rgba(255,255,255,.1)"),
8112
+ font: `${cs.getPropertyValue("--_k-weight").trim() || 400} ${(Number.parseFloat(cs.fontSize) || 12) - 1}px ${cs.getPropertyValue("--_k-font").trim() || "system-ui"}`
6484
8113
  };
6485
8114
  drawn = "";
6486
8115
  };
@@ -7347,14 +8976,16 @@ function timeline(container, options) {
7347
8976
  }
7348
8977
  var RULER = 22, INSTANT2, CALM, GLIDE, uid2 = 0, PLAY2 = '<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M5 3.6v8.8c0 .5.5.8.9.5l6.6-4.4c.4-.3.4-.8 0-1L5.9 3.1c-.4-.3-.9 0-.9.5Z" fill="currentColor"/></svg>', PAUSE = '<svg viewBox="0 0 16 16" aria-hidden="true"><rect x="4" y="3.2" width="2.8" height="9.6" rx="1" fill="currentColor"/><rect x="9.2" y="3.2" width="2.8" height="9.6" rx="1" fill="currentColor"/></svg>';
7349
8978
  var init_timeline = __esm(() => {
8979
+ init_rgba();
8980
+ init_motion();
7350
8981
  init_page_hints();
7351
8982
  init_menu();
7352
8983
  init_look();
7353
8984
  init_split_model();
7354
8985
  init_timeline_model();
7355
- INSTANT2 = springMotion({ duration: 0.1, bounce: 0 });
7356
- CALM = springMotion({ duration: 0.4, bounce: 0 });
7357
- GLIDE = springMotion({ duration: 0.22, bounce: 0 });
8986
+ INSTANT2 = springMotion(SPRINGS.instant);
8987
+ CALM = springMotion(SPRINGS.calm);
8988
+ GLIDE = springMotion(SPRINGS.snappy);
7358
8989
  });
7359
8990
 
7360
8991
  // src/ui/compare-model.ts
@@ -8465,7 +10096,7 @@ function compareStrip(container, options) {
8465
10096
  root.className = "knobs-cmp-strip";
8466
10097
  root.setAttribute("role", "img");
8467
10098
  root.setAttribute("aria-label", "Frame strip: Before over After, with how much they differ");
8468
- applyLook(root, options);
10099
+ applyLook2(root, options);
8469
10100
  const canvas = doc.createElement("canvas");
8470
10101
  canvas.setAttribute("aria-hidden", "true");
8471
10102
  root.append(canvas);
@@ -8585,10 +10216,10 @@ function compareStrip(container, options) {
8585
10216
  const readColors = () => {
8586
10217
  const cs = win.getComputedStyle(root);
8587
10218
  colors = {
8588
- surface: rgba(cs.getPropertyValue("--ku-surface"), [1, 1, 1, 0.055]),
8589
- accent: rgba(cs.getPropertyValue("--ku-accent"), [1, 1, 1, 1]),
8590
- diff: rgba(cs.getPropertyValue("--ku-cmp-diff"), [0.49, 0.81, 0.61, 1]),
8591
- wash: rgba(cs.getPropertyValue("--ku-surface-hi"), [1, 1, 1, 0.11])
10219
+ surface: rgba(tokenCss(cs, "--kv-fill", ""), [1, 1, 1, 0.055]),
10220
+ accent: rgba(tokenCss(cs, "--kv-accent", ""), [1, 1, 1, 1]),
10221
+ diff: rgba(tokenCss(cs, "--_ku-cmp-diff", ""), [0.49, 0.81, 0.61, 1]),
10222
+ wash: rgba(tokenCss(cs, "--kv-fill-selected", ""), [1, 1, 1, 0.11])
8592
10223
  };
8593
10224
  };
8594
10225
  let hover = null;
@@ -8832,7 +10463,8 @@ function compare(container, options) {
8832
10463
  const win = doc.defaultView;
8833
10464
  const look = {
8834
10465
  ...options.preset ? { preset: options.preset } : {},
8835
- ...options.theme ? { theme: options.theme } : {}
10466
+ ...options.theme ? { theme: options.theme } : {},
10467
+ ...options.appearance ? { appearance: options.appearance } : {}
8836
10468
  };
8837
10469
  let mode = options.mode ?? "side";
8838
10470
  let wipe = Math.min(1, Math.max(0, options.wipe ?? 0.5));
@@ -8853,7 +10485,7 @@ function compare(container, options) {
8853
10485
  root.setAttribute("aria-roledescription", "compare");
8854
10486
  root.setAttribute("aria-label", options.label ?? "Compare");
8855
10487
  root.setAttribute("aria-keyshortcuts", "Space ArrowLeft ArrowRight Shift+ArrowLeft Shift+ArrowRight , . 1 2 3 4 S W D X Z L 0 = -");
8856
- applyLook(root, options);
10488
+ applyLook2(root, options);
8857
10489
  root.dataset.mode = mode;
8858
10490
  if (auto)
8859
10491
  root.dataset.auto = "";
@@ -8861,7 +10493,7 @@ function compare(container, options) {
8861
10493
  const modes = el("div", "knobs-cmp-modes");
8862
10494
  modes.setAttribute("role", "radiogroup");
8863
10495
  modes.setAttribute("aria-label", "Mode");
8864
- const modeBtns = MODES.map((m, i) => {
10496
+ const modeBtns = MODES2.map((m, i) => {
8865
10497
  const b = el("button", "knobs-cmp-mode");
8866
10498
  b.type = "button";
8867
10499
  b.tabIndex = -1;
@@ -8952,7 +10584,7 @@ function compare(container, options) {
8952
10584
  let pending = false;
8953
10585
  let gpu = null;
8954
10586
  const lay = new Spring(mode === "side" ? 0 : 1, LAYOUT2.omega, LAYOUT2.zeta, 0.0001);
8955
- const fade = new Spring(1, FADE5.omega, FADE5.zeta, 0.001);
10587
+ const fade = new Spring(1, FADE6.omega, FADE6.zeta, 0.001);
8956
10588
  let fromMode = mode;
8957
10589
  let toMode = mode;
8958
10590
  let phase = false;
@@ -9287,7 +10919,7 @@ function compare(container, options) {
9287
10919
  };
9288
10920
  const syncModeUi = () => {
9289
10921
  root.dataset.mode = mode;
9290
- MODES.forEach((m, i) => {
10922
+ MODES2.forEach((m, i) => {
9291
10923
  modeBtns[i].setAttribute("aria-checked", String(m.mode === mode));
9292
10924
  });
9293
10925
  handle.tabIndex = mode === "wipe" ? 0 : -1;
@@ -9297,7 +10929,7 @@ function compare(container, options) {
9297
10929
  return;
9298
10930
  mode = next;
9299
10931
  const reduced = reducedMotion(win);
9300
- tune(fade, reduced ? FADE_REDUCED : FADE5);
10932
+ tune(fade, reduced ? FADE_REDUCED : FADE6);
9301
10933
  if (fade.x >= 0.5) {
9302
10934
  fromMode = toMode;
9303
10935
  fade.snap(0);
@@ -9647,7 +11279,7 @@ function compare(container, options) {
9647
11279
  stageRect = null;
9648
11280
  };
9649
11281
  const readColors = () => {
9650
- const c = parseCssColor(win.getComputedStyle(root).getPropertyValue("--ku-cmp-diff"), [0.49, 0.81, 0.61, 1]);
11282
+ const c = tokenColor(win.getComputedStyle(root), "--_ku-cmp-diff", [0.49, 0.81, 0.61, 1]);
9651
11283
  accent = [c[0], c[1], c[2]];
9652
11284
  labelW = [labels[0].offsetWidth, labels[1].offsetWidth];
9653
11285
  requestDraw();
@@ -9913,7 +11545,7 @@ function compare(container, options) {
9913
11545
  if (e.altKey || e.shiftKey)
9914
11546
  return;
9915
11547
  claim();
9916
- return setMode(MODES[Number(key) - 1].mode);
11548
+ return setMode(MODES2[Number(key) - 1].mode);
9917
11549
  case "x":
9918
11550
  if (e.altKey)
9919
11551
  return;
@@ -10048,7 +11680,7 @@ function compare(container, options) {
10048
11680
  holdLoupe(false);
10049
11681
  });
10050
11682
  const unregisterHints = options.hints === false ? undefined : hints.register(root, () => [
10051
- ...MODES.map((m, i) => ({
11683
+ ...MODES2.map((m, i) => ({
10052
11684
  el: modeBtns[i],
10053
11685
  label: m.label,
10054
11686
  activate: () => setMode(m.mode)
@@ -10203,8 +11835,9 @@ function compare(container, options) {
10203
11835
  wake();
10204
11836
  return api;
10205
11837
  }
10206
- var LAYOUT2, FADE5, FADE_REDUCED, ZOOM, FLICKER_MS = 400, SLOP = 12, INSET = 8, LOUPE, FAST_SEEK_FRAMES = 15, RELEASE_MS = 3000, MODES, KEY_MODE;
11838
+ var LAYOUT2, FADE6, FADE_REDUCED, ZOOM, FLICKER_MS = 400, SLOP = 12, INSET = 8, LOUPE, FAST_SEEK_FRAMES = 15, RELEASE_MS = 3000, MODES2, KEY_MODE;
10207
11839
  var init_compare = __esm(() => {
11840
+ init_motion();
10208
11841
  init_page_hints();
10209
11842
  init_compare_frames();
10210
11843
  init_compare_gpu();
@@ -10214,11 +11847,11 @@ var init_compare = __esm(() => {
10214
11847
  init_rgba();
10215
11848
  init_timeline();
10216
11849
  LAYOUT2 = springMotion({ duration: 0.35, bounce: 0 });
10217
- FADE5 = springMotion({ duration: 0.25, bounce: 0 });
10218
- FADE_REDUCED = springMotion({ duration: 0.15, bounce: 0 });
11850
+ FADE6 = springMotion(SPRINGS.snappy);
11851
+ FADE_REDUCED = springMotion(FADE);
10219
11852
  ZOOM = springMotion({ duration: 0.35, bounce: 0 });
10220
11853
  LOUPE = { r: 88, zoom: 4 };
10221
- MODES = [
11854
+ MODES2 = [
10222
11855
  { mode: "side", label: "Side by side", key: "S" },
10223
11856
  { mode: "wipe", label: "Wipe", key: "W" },
10224
11857
  { mode: "difference", label: "Difference", key: "D" },
@@ -10931,6 +12564,10 @@ function rt(e, t) {
10931
12564
  let n = new oe(e, t, Fe);
10932
12565
  return _.add(e), n;
10933
12566
  }
12567
+
12568
+ // src/ui/activity.ts
12569
+ init_motion();
12570
+
10934
12571
  // src/ui/activity-model.ts
10935
12572
  function flattenActivity(events, expanded) {
10936
12573
  const rows = [];
@@ -11087,12 +12724,12 @@ var ACTIVITY_ICONS = {
11087
12724
  shipped: svg('<circle cx="8" cy="8" r="5.8"/><path d="m5.6 8.2 1.7 1.7 3.2-3.6"/>')
11088
12725
  };
11089
12726
  var PLAY = '<svg viewBox="0 0 8 8" aria-hidden="true"><path d="M1.5 1v6l5.2-3Z" fill="currentColor"/></svg>';
11090
- var REFLOW = springMotion({ duration: 0.3, bounce: 0 });
11091
- var OPEN = springMotion({ duration: 0.22, bounce: 0 });
11092
- var CLOSE = springMotion({ duration: 0.18, bounce: 0 });
11093
- var BLOOM = springMotion({ duration: 0.3, bounce: 0 });
11094
- var EXIT = springMotion({ duration: 0.24, bounce: 0 });
11095
- var FADE = springMotion({ duration: 0.16, bounce: 0 });
12727
+ var REFLOW = springMotion(SPRINGS.default);
12728
+ var OPEN = springMotion(SPRINGS.snappy);
12729
+ var CLOSE2 = springMotion(CLOSE);
12730
+ var BLOOM = springMotion(SPRINGS.default);
12731
+ var EXIT = springMotion(SPRINGS.snappy);
12732
+ var FADE2 = springMotion(FADE);
11096
12733
  var CLEAR = [11, 5];
11097
12734
  var PAD = 6;
11098
12735
  var SLIDE = 8;
@@ -11113,7 +12750,7 @@ function activity(container, options) {
11113
12750
  root.setAttribute("role", "tree");
11114
12751
  if (options.label)
11115
12752
  root.setAttribute("aria-label", options.label);
11116
- applyLook(root, options);
12753
+ applyLook2(root, options);
11117
12754
  const space = doc.createElement("div");
11118
12755
  space.className = "knobs-activity-space";
11119
12756
  const hl = doc.createElement("div");
@@ -11417,7 +13054,7 @@ function activity(container, options) {
11417
13054
  function sync(cause, toggled) {
11418
13055
  const reduced = reducedMotion(win);
11419
13056
  const animate = cause !== "snap";
11420
- const glide = cause === "open" ? OPEN : cause === "close" ? CLOSE : REFLOW;
13057
+ const glide = cause === "open" ? OPEN : cause === "close" ? CLOSE2 : REFLOW;
11421
13058
  const before = [...views.values()].filter((v) => !v.leaving).map((v) => v.id);
11422
13059
  rows = flattenActivity(events, expanded);
11423
13060
  selected = keepSelection(rows, selected, (id) => index.get(id)?.parent);
@@ -11455,7 +13092,7 @@ function activity(container, options) {
11455
13092
  v.p.snap(1);
11456
13093
  } else if (reduced) {
11457
13094
  v.y.snap(goal);
11458
- tune(v.p, FADE).snap(0).set(1);
13095
+ tune(v.p, FADE2).snap(0).set(1);
11459
13096
  } else {
11460
13097
  const parent = row.parent !== null ? views.get(row.parent) : undefined;
11461
13098
  if (parent && !parent.leaving) {
@@ -11487,7 +13124,7 @@ function activity(container, options) {
11487
13124
  v.el.dataset.leaving = "";
11488
13125
  v.el.setAttribute("aria-selected", "false");
11489
13126
  if (reduced) {
11490
- tune(v.p, FADE).set(0);
13127
+ tune(v.p, FADE2).set(0);
11491
13128
  continue;
11492
13129
  }
11493
13130
  const group = index.get(v.id)?.parent ?? null;
@@ -11495,8 +13132,8 @@ function activity(container, options) {
11495
13132
  if (parent && !parent.leaving && v.depth === 1) {
11496
13133
  v.under = group;
11497
13134
  const drawer = cause === "close" && group === toggled;
11498
- tune(v.y, drawer ? CLOSE : glide).set(drawer ? v.y.target - shut : targets.get(group) ?? parent.y.target);
11499
- tune(v.p, drawer ? CLOSE : EXIT).set(0);
13135
+ tune(v.y, drawer ? CLOSE2 : glide).set(drawer ? v.y.target - shut : targets.get(group) ?? parent.y.target);
13136
+ tune(v.p, drawer ? CLOSE2 : EXIT).set(0);
11500
13137
  } else {
11501
13138
  v.from = 0;
11502
13139
  tune(v.p, EXIT).set(0);
@@ -11599,7 +13236,7 @@ function activity(container, options) {
11599
13236
  const to = targets.get(id);
11600
13237
  const far = from !== undefined && to !== undefined && Math.abs(to - from) > 400;
11601
13238
  const reduced = reducedMotion(win);
11602
- moveHighlight(reduced || from === undefined ? null : springMotion({ duration: far ? 0.42 : 0.3, bounce: 0 }));
13239
+ moveHighlight(reduced || from === undefined ? null : springMotion(far ? SPRINGS.calm : SPRINGS.default));
11603
13240
  root.setAttribute("aria-activedescendant", domId(id));
11604
13241
  if (source === "key") {
11605
13242
  scrollHold = null;
@@ -11767,6 +13404,10 @@ function activity(container, options) {
11767
13404
  };
11768
13405
  return handle;
11769
13406
  }
13407
+
13408
+ // src/ui/bento.ts
13409
+ init_motion();
13410
+
11770
13411
  // src/ui/bento-model.ts
11771
13412
  var FIT_MAX = 24;
11772
13413
  var clamp = (x, a, b) => Math.min(b, Math.max(a, x));
@@ -12087,16 +13728,16 @@ function motionBlur(speed, max = 3, per = 1600) {
12087
13728
 
12088
13729
  // src/ui/bento.ts
12089
13730
  init_look();
12090
- var LAYOUT = springMotion({ duration: 0.4, bounce: 0 });
12091
- var ZOOM_IN = springMotion({ duration: 0.45, bounce: 0 });
12092
- var ZOOM_OUT = springMotion({ duration: 0.38, bounce: 0 });
12093
- var SLIDE2 = springMotion({ duration: 0.3, bounce: 0 });
12094
- var SLIDE_OUT = springMotion({ duration: 0.25, bounce: 0 });
12095
- var ENTER = springMotion({ duration: 0.3, bounce: 0 });
12096
- var EXIT2 = springMotion({ duration: 0.25, bounce: 0 });
12097
- var WASH = springMotion({ duration: 0.25, bounce: 0 });
12098
- var FADE2 = springMotion({ duration: 0.18, bounce: 0 });
12099
- var INSTANT = springMotion({ duration: 0.1, bounce: 0 });
13731
+ var LAYOUT = springMotion(SPRINGS.calm);
13732
+ var ZOOM_IN = springMotion(SPRINGS.smooth);
13733
+ var ZOOM_OUT = springMotion(SPRINGS.calm);
13734
+ var SLIDE2 = springMotion(SPRINGS.default);
13735
+ var SLIDE_OUT = springMotion(SPRINGS.snappy);
13736
+ var ENTER = springMotion(SPRINGS.default);
13737
+ var EXIT2 = springMotion(SPRINGS.snappy);
13738
+ var WASH = springMotion(SPRINGS.snappy);
13739
+ var FADE3 = springMotion(FADE);
13740
+ var INSTANT = springMotion(SPRINGS.instant);
12100
13741
  var SLIDE_BY = 0.12;
12101
13742
  var EXIT_BLUR = 3;
12102
13743
  var px = (x) => new Spring(x, LAYOUT.omega, LAYOUT.zeta, 0.05);
@@ -12139,7 +13780,7 @@ function bento(container, options) {
12139
13780
  root.setAttribute("role", "listbox");
12140
13781
  root.setAttribute("aria-multiselectable", "true");
12141
13782
  root.setAttribute("aria-label", options.label ?? "Ideas");
12142
- applyLook(root, options);
13783
+ applyLook2(root, options);
12143
13784
  const space = doc.createElement("div");
12144
13785
  space.className = "knobs-bento-space";
12145
13786
  const scrim = doc.createElement("div");
@@ -12261,7 +13902,7 @@ function bento(container, options) {
12261
13902
  if (enter && !reduced())
12262
13903
  drive(t.life.snap(0), ENTER, 1);
12263
13904
  else if (enter)
12264
- drive(t.life.snap(0), FADE2, 1);
13905
+ drive(t.life.snap(0), FADE3, 1);
12265
13906
  if (reduced() || !from)
12266
13907
  for (const s of [t.x, t.y, t.w, t.h])
12267
13908
  s.snap(s.target);
@@ -12591,7 +14232,7 @@ function bento(container, options) {
12591
14232
  if (r)
12592
14233
  setBox(t, r.w, r.h);
12593
14234
  if (f.out || f.veil)
12594
- drive(t.life.snap(0), reduced() ? FADE2 : ENTER, 1);
14235
+ drive(t.life.snap(0), reduced() ? FADE3 : ENTER, 1);
12595
14236
  t.drawn = "";
12596
14237
  draw(t);
12597
14238
  syncZoomed();
@@ -12624,7 +14265,7 @@ function bento(container, options) {
12624
14265
  f.z.snap(1);
12625
14266
  f.dx.snap(0);
12626
14267
  f.veil = true;
12627
- drive(f.alpha.snap(f.alpha.target === 0 ? f.alpha.x : 0), FADE2, 1);
14268
+ drive(f.alpha.snap(f.alpha.target === 0 ? f.alpha.x : 0), FADE3, 1);
12628
14269
  } else {
12629
14270
  f.veil = false;
12630
14271
  drive(f.z, ZOOM_IN, 1);
@@ -12659,7 +14300,7 @@ function bento(container, options) {
12659
14300
  revealUnder(f.tile.id);
12660
14301
  if (reduced()) {
12661
14302
  f.veil = true;
12662
- drive(f.alpha, FADE2, 0);
14303
+ drive(f.alpha, FADE3, 0);
12663
14304
  } else
12664
14305
  drive(f.z, ZOOM_OUT, 0);
12665
14306
  syncZoomed();
@@ -12680,7 +14321,7 @@ function bento(container, options) {
12680
14321
  cur.out = true;
12681
14322
  cur.veil = false;
12682
14323
  drive(cur.dx, SLIDE_OUT, -dir * by);
12683
- drive(cur.alpha, reduced() ? FADE2 : SLIDE_OUT, 0);
14324
+ drive(cur.alpha, reduced() ? FADE3 : SLIDE_OUT, 0);
12684
14325
  let f = focusOf(t);
12685
14326
  if (!f) {
12686
14327
  f = beginFocus(t);
@@ -12692,7 +14333,7 @@ function bento(container, options) {
12692
14333
  f.veil = false;
12693
14334
  drive(f.z, ZOOM_IN, 1);
12694
14335
  drive(f.dx, SLIDE2, 0);
12695
- drive(f.alpha, reduced() ? FADE2 : SLIDE2, 1);
14336
+ drive(f.alpha, reduced() ? FADE3 : SLIDE2, 1);
12696
14337
  setActive(id);
12697
14338
  syncZoomed();
12698
14339
  loop.wake();
@@ -13016,7 +14657,7 @@ function bento(container, options) {
13016
14657
  if (f)
13017
14658
  endFocus(f);
13018
14659
  t.leaving = true;
13019
- drive(t.life, reduced() ? FADE2 : EXIT2, 0);
14660
+ drive(t.life, reduced() ? FADE3 : EXIT2, 0);
13020
14661
  }
13021
14662
  items = next;
13022
14663
  reindex();
@@ -13114,6 +14755,7 @@ function timelineChanges(now, changed) {
13114
14755
  }
13115
14756
 
13116
14757
  // src/ui/picker.ts
14758
+ init_motion();
13117
14759
  init_look();
13118
14760
 
13119
14761
  // src/ui/picker-model.ts
@@ -13164,10 +14806,10 @@ function settleHeight(previous, now, frames, limit = 6) {
13164
14806
  }
13165
14807
 
13166
14808
  // src/ui/picker.ts
13167
- var OPEN2 = springMotion({ duration: 0.22, bounce: 0 });
13168
- var CLOSE2 = springMotion({ duration: 0.18, bounce: 0 });
13169
- var CARD = springMotion({ duration: 0.3, bounce: 0 });
13170
- var FADE4 = springMotion({ duration: 0.16, bounce: 0 });
14809
+ var OPEN2 = springMotion(SPRINGS.snappy);
14810
+ var CLOSE3 = springMotion(CLOSE);
14811
+ var CARD = springMotion(SPRINGS.default);
14812
+ var FADE5 = springMotion(FADE);
13171
14813
  var DRIFT = 6;
13172
14814
  var CHECK = svg('<path d="m3.5 8.4 3 3 6-6.6"/>');
13173
14815
  function optionPicker(container, options) {
@@ -13189,7 +14831,7 @@ function optionPicker(container, options) {
13189
14831
  root.setAttribute("role", "radiogroup");
13190
14832
  if (options.label)
13191
14833
  root.setAttribute("aria-label", options.label);
13192
- applyLook(root, options);
14834
+ applyLook2(root, options);
13193
14835
  const card = doc.createElement("div");
13194
14836
  card.className = "knobs-picker-card";
13195
14837
  card.setAttribute("aria-hidden", "true");
@@ -13365,10 +15007,10 @@ function optionPicker(container, options) {
13365
15007
  e.body.dataset.moving = "";
13366
15008
  if (reduced) {
13367
15009
  e.h.snap(open ? natural(e) : 0);
13368
- tune(e.o, FADE4).set(open ? 1 : 0);
15010
+ tune(e.o, FADE5).set(open ? 1 : 0);
13369
15011
  } else {
13370
- tune(e.h, open ? OPEN2 : CLOSE2).set(open ? natural(e) : 0);
13371
- tune(e.o, open ? OPEN2 : CLOSE2).set(open ? 1 : 0);
15012
+ tune(e.h, open ? OPEN2 : CLOSE3).set(open ? natural(e) : 0);
15013
+ tune(e.o, open ? OPEN2 : CLOSE3).set(open ? 1 : 0);
13372
15014
  }
13373
15015
  loop.wake();
13374
15016
  };
@@ -13545,7 +15187,7 @@ function optionPicker(container, options) {
13545
15187
  e.head.tabIndex = -1;
13546
15188
  if (e.open)
13547
15189
  setOpen(e, false, true);
13548
- tune(e.presence, reduced ? FADE4 : CLOSE2).set(0);
15190
+ tune(e.presence, reduced ? FADE5 : CLOSE3).set(0);
13549
15191
  }
13550
15192
  let before = card;
13551
15193
  list.forEach((o, i) => {
@@ -13559,7 +15201,7 @@ function optionPicker(container, options) {
13559
15201
  e = make(o);
13560
15202
  ro.observe(e.el);
13561
15203
  if (animate)
13562
- tune(e.presence, reduced ? FADE4 : OPEN2).snap(0).set(1);
15204
+ tune(e.presence, reduced ? FADE5 : OPEN2).snap(0).set(1);
13563
15205
  }
13564
15206
  if (before.nextElementSibling !== e.el)
13565
15207
  before.after(e.el);
@@ -13671,6 +15313,7 @@ function optionPicker(container, options) {
13671
15313
  }
13672
15314
 
13673
15315
  // src/ui/split.ts
15316
+ init_motion();
13674
15317
  init_look();
13675
15318
  init_page_hints();
13676
15319
 
@@ -13854,9 +15497,9 @@ function tooltip(el, content, options = {}) {
13854
15497
 
13855
15498
  // src/ui/split.ts
13856
15499
  init_split_model();
13857
- var FLIP = springMotion({ duration: 0.25, bounce: 0 });
15500
+ var FLIP = springMotion(SPRINGS.snappy);
13858
15501
  var FLIP_DEPTH = 28;
13859
- var SETTLE = springMotion({ duration: 0.3, bounce: 0 });
15502
+ var SETTLE = springMotion(SPRINGS.default);
13860
15503
  var CONTENT_BLUR = 3;
13861
15504
  var LABEL_BLUR = 2;
13862
15505
  var COUNT_CLEAR = 0.12;
@@ -13912,7 +15555,7 @@ function split(container, options) {
13912
15555
  const root = doc.createElement("div");
13913
15556
  root.className = "knobs-split";
13914
15557
  root.dataset.direction = direction;
13915
- applyLook(root, options);
15558
+ applyLook2(root, options);
13916
15559
  const host = container.closest(".knobs-pane");
13917
15560
  host?.setAttribute("data-nested", "");
13918
15561
  const views = new Map;
@@ -14077,7 +15720,7 @@ function split(container, options) {
14077
15720
  const measure = () => {
14078
15721
  syncFrame(root);
14079
15722
  const probe = doc.createElement("div");
14080
- probe.style.cssText = "position:absolute;visibility:hidden;width:var(--ku-rail);height:var(--ku-pane-m)";
15723
+ probe.style.cssText = "position:absolute;visibility:hidden;width:var(--_ku-rail);height:var(--_ku-pane-m)";
14081
15724
  root.append(probe);
14082
15725
  const r = probe.getBoundingClientRect();
14083
15726
  paneM = r.height;
@@ -14131,8 +15774,8 @@ function split(container, options) {
14131
15774
  out[id] = s.x;
14132
15775
  return out;
14133
15776
  };
14134
- const target = () => solve({ panes: specs, sizes, collapsed, total: total(), rail });
14135
- const current = () => solve({ panes: specs, sizes, collapsed, total: total(), rail, fixed: fixed() });
15777
+ const target = () => solve2({ panes: specs, sizes, collapsed, total: total(), rail });
15778
+ const current = () => solve2({ panes: specs, sizes, collapsed, total: total(), rail, fixed: fixed() });
14136
15779
  const SIDES = { row: ["right", "left"], column: ["bottom", "top"] };
14137
15780
  const sides = (v) => {
14138
15781
  const [a, b] = SIDES[direction];
@@ -14183,7 +15826,7 @@ function split(container, options) {
14183
15826
  put(label, "opacity", "");
14184
15827
  put(label, "filter", "");
14185
15828
  put(label, "transform", k === 0 ? "" : `translate(${t.x.toFixed(2)}px,${t.y.toFixed(2)}px) rotate(${t.turn.toFixed(2)}deg)`);
14186
- put(label, "color", k === 0 ? "" : `color-mix(in srgb,var(--ku-text) ${(k * 100).toFixed(1)}%,var(--ku-label))`);
15829
+ put(label, "color", k === 0 ? "" : `color-mix(in srgb,var(--kv-fg) ${(k * 100).toFixed(1)}%,var(--kv-fg-2))`);
14187
15830
  } else {
14188
15831
  put(label, "transform", "");
14189
15832
  put(label, "color", "");
@@ -14473,7 +16116,7 @@ function split(container, options) {
14473
16116
  const first = target();
14474
16117
  for (const spec of specs) {
14475
16118
  const open = { ...collapsed, [spec.id]: false };
14476
- views.get(spec.id).open = collapsed[spec.id] ? solve({ panes: specs, sizes, collapsed: open, total: total(), rail })[spec.id] : first[spec.id];
16119
+ views.get(spec.id).open = collapsed[spec.id] ? solve2({ panes: specs, sizes, collapsed: open, total: total(), rail })[spec.id] : first[spec.id];
14477
16120
  }
14478
16121
  render(first);
14479
16122
  measureChevrons();
@@ -14573,6 +16216,7 @@ init_compare_strip();
14573
16216
  init_tree();
14574
16217
 
14575
16218
  // src/ui/walkthrough.ts
16219
+ init_motion();
14576
16220
  init_page_hints();
14577
16221
 
14578
16222
  // src/ui/confirm.ts
@@ -14656,7 +16300,7 @@ function toast(message, options = {}) {
14656
16300
  const key = options.within ?? doc;
14657
16301
  let r = regions.get(key);
14658
16302
  if (!r || !r.el.isConnected) {
14659
- const el = options.within ? Object.assign(doc.createElement("div"), { className: "knobs-ui knobs-toast" }) : layerElement(doc, "knobs-layer knobs-toast", options.look);
16303
+ const el = options.within ? Object.assign(doc.createElement("div"), { className: "knobs-root knobs-ui knobs-toast" }) : layerElement(doc, "knobs-layer knobs-toast", options.look);
14660
16304
  if (options.within) {
14661
16305
  injectUiStyles(doc);
14662
16306
  options.within.append(el);
@@ -14712,25 +16356,25 @@ function toast(message, options = {}) {
14712
16356
 
14713
16357
  // src/ui/walkthrough-media.ts
14714
16358
  init_compare_model();
16359
+ init_glide();
14715
16360
  init_look();
14716
16361
 
14717
16362
  // src/ui/walkthrough-css.ts
14718
- var snappy3 = springCss({ duration: 0.25, bounce: 0 });
14719
- var calm = springCss({ duration: 0.4, bounce: 0 });
16363
+ init_motion();
16364
+ var snappy3 = springCss(SPRINGS.snappy);
16365
+ var calm = springCss(SPRINGS.calm);
14720
16366
  var walkthroughCss = `
14721
16367
  :where(.knobs-walkthrough,.knobs-walkthrough *,.knobs-wt-slot,.knobs-wt-slot *){box-sizing:border-box}
14722
16368
  .knobs-ui.knobs-walkthrough{--kw-snappy:${snappy3.easing};--kw-snappy-ms:${snappy3.duration}ms;--kw-calm:${calm.easing};--kw-calm-ms:${calm.duration}ms;
14723
- --kw-text:var(--k-walkthrough-text,14px);--kw-measure:var(--k-walkthrough-measure,68ch);--kw-good:var(--k-walkthrough-good,#30d158);--kw-info:var(--k-walkthrough-info,#64d2ff);
14724
- --kw-card:var(--ku-pane-bg);--kw-card-ring:var(--ku-pane-ring);--kw-pad:16px;--kw-ink:var(--k-walkthrough-ink,#ff375f);
14725
- container:knobs-wt / inline-size;display:block;width:100%;color:var(--ku-text);font:var(--ku-font-weight) var(--kw-text)/1.5 var(--ku-font);text-align:left;
16369
+ --kw-text:var(--k-walkthrough-text,14px);--kw-measure:var(--k-walkthrough-measure,68ch);--kw-good:var(--k-walkthrough-good,var(--_k-ok));--kw-info:var(--k-walkthrough-info,var(--_k-info));
16370
+ --kw-card:var(--_ku-pane-bg);--kw-card-ring:var(--_ku-pane-ring);--kw-pad:16px;--kw-ink:var(--k-walkthrough-ink,#ff375f);
16371
+ container:knobs-wt / inline-size;display:block;width:100%;color:var(--_k-fg);font:var(--_k-weight) var(--kw-text)/1.5 var(--_k-font);text-align:left;
14726
16372
  letter-spacing:normal;-webkit-font-smoothing:antialiased}
14727
- .knobs-ui.knobs-walkthrough[data-theme="light"],:where(:root[data-theme="light"]) .knobs-ui.knobs-walkthrough[data-theme="auto"]{--kw-good:var(--k-walkthrough-good,#248a3d);--kw-info:var(--k-walkthrough-info,#0071a4)}
14728
- @media(prefers-color-scheme:light){:where(:root:not([data-theme="dark"])) .knobs-ui.knobs-walkthrough[data-theme="auto"]{--kw-good:var(--k-walkthrough-good,#248a3d);--kw-info:var(--k-walkthrough-info,#0071a4)}}
14729
16373
  .knobs-walkthrough [hidden]{display:none!important}
14730
16374
  .knobs-walkthrough :is(h1,h2,h3,p){margin:0;font:inherit;letter-spacing:inherit}
14731
16375
  .knobs-walkthrough a{color:inherit;text-decoration:underline;text-decoration-color:color-mix(in srgb,currentColor 35%,transparent);text-underline-offset:2px;transition:text-decoration-color .15s}
14732
16376
  .knobs-walkthrough a:hover{text-decoration-color:currentColor}
14733
- .knobs-walkthrough code,.knobs-wt-slot code{font:calc(1em - 1px) var(--ku-mono);padding:1px 5px;border-radius:5px;background:var(--ku-surface)}
16377
+ .knobs-walkthrough code,.knobs-wt-slot code{font:calc(1em - 1px) var(--_k-mono);padding:1px 5px;border-radius:5px;background:var(--_k-fill)}
14734
16378
  :where(.knobs-ui) :is(.knobs-wt-btn,.knobs-wt-pick,.knobs-wt-toc-step){all:revert;box-sizing:border-box;font:inherit;color:inherit;letter-spacing:inherit;
14735
16379
  background:transparent;border:0;border-radius:0;margin:0;padding:0;min-width:0;box-shadow:none;outline:none}
14736
16380
 
@@ -14741,40 +16385,40 @@ var walkthroughCss = `
14741
16385
 
14742
16386
  /* ——— the page's head ——— */
14743
16387
  .knobs-wt-head{display:flex;flex-direction:column;gap:10px}
14744
- .knobs-wt-title{font-size:calc(var(--kw-text) + 10px)!important;font-weight:var(--ku-title-weight)!important;line-height:1.2;letter-spacing:-.01em!important}
14745
- .knobs-wt-summary{max-width:var(--kw-measure);color:var(--ku-label)}
14746
- .knobs-wt-meta{display:flex;flex-wrap:wrap;gap:6px 16px;color:var(--ku-dim);font-size:calc(var(--kw-text) - 2px)}
16388
+ .knobs-wt-title{font-size:calc(var(--kw-text) + 10px)!important;font-weight:var(--_k-weight-title)!important;line-height:1.2;letter-spacing:-.01em!important}
16389
+ .knobs-wt-summary{max-width:var(--kw-measure);color:var(--_k-fg-2)}
16390
+ .knobs-wt-meta{display:flex;flex-wrap:wrap;gap:6px 16px;color:var(--_k-fg-3);font-size:calc(var(--kw-text) - 2px)}
14747
16391
  .knobs-wt-meta>span{display:inline-flex;gap:6px;white-space:nowrap}
14748
- .knobs-wt-meta b{font-weight:var(--ku-font-weight);color:var(--ku-label);font-family:var(--ku-mono);font-size:calc(1em - .5px)}
16392
+ .knobs-wt-meta b{font-weight:var(--_k-weight);color:var(--_k-fg-2);font-family:var(--_k-mono);font-size:calc(1em - .5px)}
14749
16393
 
14750
16394
  /* ——— a section: a PR or topic ——— */
14751
16395
  .knobs-wt-section{display:flex;flex-direction:column;gap:14px;min-width:0}
14752
16396
  .knobs-wt-shead{display:flex;flex-direction:column;gap:6px;scroll-margin-top:16px}
14753
- .knobs-wt-kicker{display:flex;align-items:center;gap:10px;font-size:calc(var(--kw-text) - 2px);color:var(--ku-dim)}
14754
- .knobs-wt-kicker a{font-family:var(--ku-mono);color:var(--ku-label);text-decoration:none}
14755
- .knobs-wt-kicker a:hover{color:var(--ku-text)}
14756
- .knobs-wt-stitle{font-size:calc(var(--kw-text) + 4px)!important;font-weight:var(--ku-title-weight)!important;line-height:1.3}
14757
- .knobs-wt-ssum{max-width:var(--kw-measure);color:var(--ku-label)}
14758
- .knobs-wt-chip{display:inline-flex;align-items:center;gap:6px;height:20px;padding:0 8px;border-radius:999px;font-size:calc(var(--kw-text) - 3px);font-weight:var(--ku-label-weight);white-space:nowrap;
14759
- --kw-tone:var(--ku-label);color:var(--kw-tone);background:color-mix(in srgb,var(--kw-tone) 14%,transparent)}
16397
+ .knobs-wt-kicker{display:flex;align-items:center;gap:10px;font-size:calc(var(--kw-text) - 2px);color:var(--_k-fg-3)}
16398
+ .knobs-wt-kicker a{font-family:var(--_k-mono);color:var(--_k-fg-2);text-decoration:none}
16399
+ .knobs-wt-kicker a:hover{color:var(--_k-fg)}
16400
+ .knobs-wt-stitle{font-size:calc(var(--kw-text) + 4px)!important;font-weight:var(--_k-weight-title)!important;line-height:1.3}
16401
+ .knobs-wt-ssum{max-width:var(--kw-measure);color:var(--_k-fg-2)}
16402
+ .knobs-wt-chip{display:inline-flex;align-items:center;gap:6px;height:20px;padding:0 8px;border-radius:999px;font-size:calc(var(--kw-text) - 3px);font-weight:var(--_k-weight-label);white-space:nowrap;
16403
+ --kw-tone:var(--_k-fg-2);color:var(--kw-tone);background:color-mix(in srgb,var(--kw-tone) 14%,transparent)}
14760
16404
  .knobs-wt-chip::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor}
14761
16405
  :is(.knobs-wt-chip,.knobs-wt-toc-glyph)[data-tone="good"]{--kw-tone:var(--kw-good)}
14762
- :is(.knobs-wt-chip,.knobs-wt-toc-glyph)[data-tone="warn"]{--kw-tone:var(--ku-warn)}
14763
- :is(.knobs-wt-chip,.knobs-wt-toc-glyph)[data-tone="bad"]{--kw-tone:var(--ku-critical)}
16406
+ :is(.knobs-wt-chip,.knobs-wt-toc-glyph)[data-tone="warn"]{--kw-tone:var(--_k-warn)}
16407
+ :is(.knobs-wt-chip,.knobs-wt-toc-glyph)[data-tone="bad"]{--kw-tone:var(--_k-danger)}
14764
16408
  :is(.knobs-wt-chip,.knobs-wt-toc-glyph)[data-tone="info"]{--kw-tone:var(--kw-info)}
14765
- :is(.knobs-wt-chip,.knobs-wt-toc-glyph)[data-tone="dim"]{--kw-tone:var(--ku-label)}
16409
+ :is(.knobs-wt-chip,.knobs-wt-toc-glyph)[data-tone="dim"]{--kw-tone:var(--_k-fg-2)}
14766
16410
 
14767
16411
  /* ——— a step: one card ——— */
14768
- .knobs-wt-step{position:relative;display:flex;flex-direction:column;gap:12px;padding:var(--kw-pad);border-radius:var(--ku-panel-radius);background:var(--kw-card);box-shadow:var(--kw-card-ring);
16412
+ .knobs-wt-step{position:relative;display:flex;flex-direction:column;gap:12px;padding:var(--kw-pad);border-radius:var(--_k-radius-panel);background:var(--kw-card);box-shadow:var(--kw-card-ring);
14769
16413
  scroll-margin-top:16px;outline:none;container:knobs-wt-step / inline-size}
14770
- .knobs-walkthrough[data-frame="flat"] .knobs-wt-step{box-shadow:inset 0 0 0 1px var(--ku-line)}
16414
+ .knobs-walkthrough[data-frame="flat"] .knobs-wt-step{box-shadow:inset 0 0 0 1px var(--_k-border)}
14771
16415
  .knobs-wt-step-head{display:flex;align-items:baseline;gap:10px;min-width:0}
14772
- .knobs-wt-num{flex:none;font:var(--ku-font-weight) calc(var(--kw-text) - 2px)/1 var(--ku-mono);color:var(--ku-dim);font-variant-numeric:tabular-nums}
14773
- .knobs-wt-stepTitle{flex:1;min-width:0;font-weight:var(--ku-title-weight)!important}
14774
- .knobs-wt-caption{max-width:var(--kw-measure);color:var(--ku-label);margin-top:-6px!important}
14775
- .knobs-wt-question{font-weight:var(--ku-label-weight)!important}
16416
+ .knobs-wt-num{flex:none;font:var(--_k-weight) calc(var(--kw-text) - 2px)/1 var(--_k-mono);color:var(--_k-fg-3);font-variant-numeric:tabular-nums}
16417
+ .knobs-wt-stepTitle{flex:1;min-width:0;font-weight:var(--_k-weight-title)!important}
16418
+ .knobs-wt-caption{max-width:var(--kw-measure);color:var(--_k-fg-2);margin-top:-6px!important}
16419
+ .knobs-wt-question{font-weight:var(--_k-weight-label)!important}
14776
16420
  /* The step Kit is on: its number lights, and its choices show their keys. */
14777
- .knobs-wt-step[data-current] .knobs-wt-num{color:var(--ku-text)}
16421
+ .knobs-wt-step[data-current] .knobs-wt-num{color:var(--_k-fg)}
14778
16422
  .knobs-wt-media{display:grid;grid-template-columns:repeat(var(--kw-n,1),minmax(0,1fr));gap:12px;min-width:0}
14779
16423
  @container knobs-wt-step (max-width:640px){.knobs-wt-media{grid-template-columns:minmax(0,1fr)}}
14780
16424
 
@@ -14783,16 +16427,16 @@ var walkthroughCss = `
14783
16427
  .knobs-wt-feed-list{list-style:none;margin:0;padding:0;max-height:260px;overflow:auto;scrollbar-width:none;display:flex;flex-direction:column}
14784
16428
  .knobs-wt-feed-list::-webkit-scrollbar{display:none}
14785
16429
  .knobs-wt-fi{display:grid;grid-template-columns:64px 56px minmax(0,1fr) auto;gap:10px;align-items:baseline;padding:6px 0;font-size:calc(var(--kw-text) - 1px)}
14786
- .knobs-wt-fi+.knobs-wt-fi{box-shadow:inset 0 1px 0 var(--ku-line)}
14787
- .knobs-wt-fi-when{color:var(--ku-dim);font-size:calc(var(--kw-text) - 2.5px);font-variant-numeric:tabular-nums;white-space:nowrap}
14788
- .knobs-wt-fi-kind{color:var(--ku-label);font-size:calc(var(--kw-text) - 2.5px);font-weight:var(--ku-label-weight)}
16430
+ .knobs-wt-fi+.knobs-wt-fi{box-shadow:inset 0 1px 0 var(--_k-border)}
16431
+ .knobs-wt-fi-when{color:var(--_k-fg-3);font-size:calc(var(--kw-text) - 2.5px);font-variant-numeric:tabular-nums;white-space:nowrap}
16432
+ .knobs-wt-fi-kind{color:var(--_k-fg-2);font-size:calc(var(--kw-text) - 2.5px);font-weight:var(--_k-weight-label)}
14789
16433
  .knobs-wt-fi[data-kind="qa"] .knobs-wt-fi-kind{color:var(--kw-info)}
14790
- .knobs-wt-fi-body{max-width:var(--kw-measure);color:var(--ku-text)}
14791
- .knobs-wt-fi-q{color:var(--ku-label)}
14792
- .knobs-wt-fi-q::before{content:"You asked: ";color:var(--ku-dim)}
14793
- :where(.knobs-ui) .knobs-wt-fi-step{all:revert;box-sizing:border-box;font:var(--ku-font-weight) calc(var(--kw-text) - 2.5px)/1 var(--ku-mono);color:var(--ku-label);background:transparent;border:0;
16434
+ .knobs-wt-fi-body{max-width:var(--kw-measure);color:var(--_k-fg)}
16435
+ .knobs-wt-fi-q{color:var(--_k-fg-2)}
16436
+ .knobs-wt-fi-q::before{content:"You asked: ";color:var(--_k-fg-3)}
16437
+ :where(.knobs-ui) .knobs-wt-fi-step{all:revert;box-sizing:border-box;font:var(--_k-weight) calc(var(--kw-text) - 2.5px)/1 var(--_k-mono);color:var(--_k-fg-2);background:transparent;border:0;
14794
16438
  padding:3px 6px;margin:0;border-radius:6px;cursor:pointer;outline:none;transition:background .15s,color .15s}
14795
- .knobs-ui .knobs-wt-fi-step:is(:hover,:focus-visible){background:var(--ku-wash-hi);color:var(--ku-text)}
16439
+ .knobs-ui .knobs-wt-fi-step:is(:hover,:focus-visible){background:var(--_ku-wash-hi);color:var(--_k-fg)}
14796
16440
 
14797
16441
  /* ——— a step's sent notes ——— */
14798
16442
  .knobs-wt-notes{display:flex;flex-direction:column}
@@ -14801,47 +16445,47 @@ var walkthroughCss = `
14801
16445
  transition:height var(--kw-snappy-ms) var(--kw-snappy),opacity var(--kw-snappy-ms) var(--kw-snappy),filter var(--kw-snappy-ms) var(--kw-snappy)}
14802
16446
  .knobs-wt-n[data-entering]{opacity:0;filter:blur(3px)}
14803
16447
  .knobs-wt-n[data-leaving]{opacity:0;filter:blur(3px);padding-block:0}
14804
- .knobs-wt-n+.knobs-wt-n{box-shadow:inset 0 1px 0 var(--ku-line)}
14805
- .knobs-wt-n-meta{flex:none;min-width:44px;padding-top:2px;color:var(--ku-dim);font:var(--ku-font-weight) calc(var(--kw-text) - 2.5px)/1.4 var(--ku-mono);font-variant-numeric:tabular-nums}
16448
+ .knobs-wt-n+.knobs-wt-n{box-shadow:inset 0 1px 0 var(--_k-border)}
16449
+ .knobs-wt-n-meta{flex:none;min-width:44px;padding-top:2px;color:var(--_k-fg-3);font:var(--_k-weight) calc(var(--kw-text) - 2.5px)/1.4 var(--_k-mono);font-variant-numeric:tabular-nums}
14806
16450
  .knobs-wt-n-meta[data-seek]{cursor:pointer}
14807
- .knobs-wt-n-meta[data-seek]:hover{color:var(--ku-text)}
16451
+ .knobs-wt-n-meta[data-seek]:hover{color:var(--_k-fg)}
14808
16452
  .knobs-wt-n-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:6px;font-size:calc(var(--kw-text) - 1px)}
14809
16453
  .knobs-wt-n-voice{height:30px;max-width:320px}
14810
- .knobs-wt-n-ink{display:block;width:120px;max-height:80px;border-radius:6px;background:var(--ku-surface)}
16454
+ .knobs-wt-n-ink{display:block;width:120px;max-height:80px;border-radius:6px;background:var(--_k-fill)}
14811
16455
  .knobs-wt-n-ink path{fill:none;stroke:var(--kw-ink);stroke-width:2px;vector-effect:non-scaling-stroke;stroke-linecap:round;stroke-linejoin:round}
14812
16456
 
14813
16457
  /* ——— the note bar, docked at the bottom of the column ——— */
14814
16458
  .knobs-wt-dock{position:sticky;bottom:12px;z-index:40;margin-top:-24px}
14815
- .knobs-wt-notebar{display:flex;flex-direction:column;gap:2px;padding:6px 6px 6px 14px;border-radius:calc(var(--ku-panel-radius) + 2px);background:var(--ku-bg);
14816
- box-shadow:var(--ku-pane-ring),var(--ku-shadow)}
14817
- .knobs-wt-on{padding-top:3px;color:var(--ku-dim);font-size:calc(var(--kw-text) - 2.5px);white-space:nowrap;overflow:hidden;
16459
+ .knobs-wt-notebar{display:flex;flex-direction:column;gap:2px;padding:6px 6px 6px 14px;border-radius:calc(var(--_k-radius-panel) + 2px);background:var(--_k-bg);
16460
+ box-shadow:var(--_ku-pane-ring),var(--_k-shadow-overlay)}
16461
+ .knobs-wt-on{padding-top:3px;color:var(--_k-fg-3);font-size:calc(var(--kw-text) - 2.5px);white-space:nowrap;overflow:hidden;
14818
16462
  -webkit-mask-image:linear-gradient(to right,#000 calc(100% - 1.5em),transparent);mask-image:linear-gradient(to right,#000 calc(100% - 1.5em),transparent)}
14819
16463
  .knobs-wt-row{display:flex;align-items:flex-end;gap:4px}
14820
16464
  :where(.knobs-ui) :is(.knobs-wt-input,.knobs-wt-tool,.knobs-wt-x,.knobs-wt-back){all:revert;box-sizing:border-box;font:inherit;color:inherit;letter-spacing:inherit;background:transparent;border:0;
14821
16465
  border-radius:0;margin:0;padding:0;min-width:0;box-shadow:none;outline:none}
14822
- .knobs-ui .knobs-wt-input{flex:1;min-width:0;height:32px;max-height:140px;padding:6px 0;resize:none;color:var(--ku-text);caret-color:var(--ku-accent);line-height:20px;font-size:var(--kw-text)}
14823
- .knobs-ui .knobs-wt-input::placeholder{color:var(--ku-dim)}
16466
+ .knobs-ui .knobs-wt-input{flex:1;min-width:0;height:32px;max-height:140px;padding:6px 0;resize:none;color:var(--_k-fg);caret-color:var(--_k-accent);line-height:20px;font-size:var(--kw-text)}
16467
+ .knobs-ui .knobs-wt-input::placeholder{color:var(--_k-fg-3)}
14824
16468
  .knobs-wt-attach{display:flex;gap:4px;align-items:center;align-self:center}
14825
16469
  .knobs-wt-attach:empty{display:none}
14826
- .knobs-wt-chip-a{display:inline-flex;align-items:center;gap:2px;height:24px;padding:0 2px 0 9px;border-radius:999px;background:var(--ku-surface-hi);font-size:calc(var(--kw-text) - 2.5px);white-space:nowrap}
14827
- .knobs-ui .knobs-wt-x{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:50%;color:var(--ku-dim);cursor:pointer;transition:background .15s,color .15s}
14828
- .knobs-ui .knobs-wt-x:is(:hover,:focus-visible){background:var(--ku-wash-hi);color:var(--ku-text)}
16470
+ .knobs-wt-chip-a{display:inline-flex;align-items:center;gap:2px;height:24px;padding:0 2px 0 9px;border-radius:999px;background:var(--_k-fill-selected);font-size:calc(var(--kw-text) - 2.5px);white-space:nowrap}
16471
+ .knobs-ui .knobs-wt-x{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:50%;color:var(--_k-fg-3);cursor:pointer;transition:background .15s,color .15s}
16472
+ .knobs-ui .knobs-wt-x:is(:hover,:focus-visible){background:var(--_ku-wash-hi);color:var(--_k-fg)}
14829
16473
  .knobs-wt-x svg{width:10px;height:10px}
14830
- .knobs-ui .knobs-wt-tool{flex:none;display:inline-flex;align-items:center;justify-content:center;gap:5px;min-width:32px;height:32px;padding:0 8px;border-radius:calc(var(--ku-radius) + 2px);
14831
- color:var(--ku-label);cursor:pointer;transition:background .15s,color .15s}
14832
- .knobs-ui .knobs-wt-tool:is(:hover,:focus-visible){background:var(--ku-wash-hi);color:var(--ku-text)}
14833
- .knobs-ui .knobs-wt-tool[aria-pressed="true"]{background:var(--ku-surface-hi);color:var(--ku-text)}
16474
+ .knobs-ui .knobs-wt-tool{flex:none;display:inline-flex;align-items:center;justify-content:center;gap:5px;min-width:32px;height:32px;padding:0 8px;border-radius:calc(var(--_k-radius) + 2px);
16475
+ color:var(--_k-fg-2);cursor:pointer;transition:background .15s,color .15s}
16476
+ .knobs-ui .knobs-wt-tool:is(:hover,:focus-visible){background:var(--_ku-wash-hi);color:var(--_k-fg)}
16477
+ .knobs-ui .knobs-wt-tool[aria-pressed="true"]{background:var(--_k-fill-selected);color:var(--_k-fg)}
14834
16478
  .knobs-wt-tool svg{width:15px;height:15px}
14835
16479
  .knobs-wt-rec{font-size:calc(var(--kw-text) - 2.5px);font-variant-numeric:tabular-nums}
14836
16480
  .knobs-wt-rec:empty{display:none}
14837
- .knobs-ui .knobs-wt-tool[data-send]{color:var(--ku-dim)}
14838
- .knobs-ui .knobs-wt-tool[data-send][data-ready]{background:var(--ku-accent);color:var(--ku-bg)}
16481
+ .knobs-ui .knobs-wt-tool[data-send]{color:var(--_k-fg-3)}
16482
+ .knobs-ui .knobs-wt-tool[data-send][data-ready]{background:var(--_k-accent);color:var(--_k-bg)}
14839
16483
  /* Back: in place over the bar for a few seconds after a note moves the page on. */
14840
- .knobs-ui .knobs-wt-back{position:absolute;left:8px;bottom:calc(100% + 8px);height:28px;padding:0 12px;border-radius:999px;background:var(--ku-bg);color:var(--ku-text);
14841
- box-shadow:var(--ku-pane-ring),var(--ku-shadow);font-size:calc(var(--kw-text) - 1.5px);font-weight:var(--ku-label-weight);cursor:pointer;
16484
+ .knobs-ui .knobs-wt-back{position:absolute;left:8px;bottom:calc(100% + 8px);height:28px;padding:0 12px;border-radius:999px;background:var(--_k-bg);color:var(--_k-fg);
16485
+ box-shadow:var(--_ku-pane-ring),var(--_k-shadow-overlay);font-size:calc(var(--kw-text) - 1.5px);font-weight:var(--_k-weight-label);cursor:pointer;
14842
16486
  opacity:0;scale:.96;filter:blur(3px);pointer-events:none;transition:opacity .11s cubic-bezier(.4,0,1,1),scale .11s cubic-bezier(.4,0,1,1),filter .11s cubic-bezier(.4,0,1,1)}
14843
16487
  .knobs-ui .knobs-wt-back[data-on]{opacity:1;scale:1;filter:none;pointer-events:auto;transition:opacity .15s cubic-bezier(.2,.8,.2,1),scale .15s cubic-bezier(.2,.8,.2,1),filter .15s cubic-bezier(.2,.8,.2,1)}
14844
- .knobs-ui .knobs-wt-back:hover{background:var(--ku-surface-hi)}
16488
+ .knobs-ui .knobs-wt-back:hover{background:var(--_k-fill-selected)}
14845
16489
 
14846
16490
  /* ——— ink over a step's media ——— */
14847
16491
  .knobs-wt-media,.knobs-wt-options{position:relative}
@@ -14850,10 +16494,10 @@ var walkthroughCss = `
14850
16494
  .knobs-wt-ink path{fill:none;stroke:var(--kw-ink);stroke-width:3px;vector-effect:non-scaling-stroke;stroke-linecap:round;stroke-linejoin:round}
14851
16495
 
14852
16496
  /* ——— full-window: the step over the page, its media filling it; its place held in the page ——— */
14853
- .knobs-wt-scrim{position:fixed;inset:0;z-index:30;background:color-mix(in srgb,var(--ku-page) 82%,transparent);opacity:0;pointer-events:none}
16497
+ .knobs-wt-scrim{position:fixed;inset:0;z-index:30;background:color-mix(in srgb,var(--_k-bg-page) 82%,transparent);opacity:0;pointer-events:none}
14854
16498
  .knobs-wt-scrim[data-on]{pointer-events:auto}
14855
16499
  .knobs-wt-hold-card{flex:none}
14856
- .knobs-wt-step[data-full]{position:fixed;z-index:35;margin:0;overflow:hidden;overscroll-behavior:contain;padding-bottom:84px;box-shadow:var(--kw-card-ring),var(--ku-shadow);background:var(--ku-bg)}
16500
+ .knobs-wt-step[data-full]{position:fixed;z-index:35;margin:0;overflow:hidden;overscroll-behavior:contain;padding-bottom:84px;box-shadow:var(--kw-card-ring),var(--_k-shadow-overlay);background:var(--_k-bg)}
14857
16501
  .knobs-wt-step[data-full]>:not(.knobs-wt-media){flex:none}
14858
16502
  .knobs-wt-step[data-full] .knobs-wt-notes{display:none}
14859
16503
  .knobs-wt-step[data-full]>.knobs-wt-media{flex:1;min-height:0;grid-auto-rows:minmax(0,1fr)}
@@ -14865,71 +16509,71 @@ var walkthroughCss = `
14865
16509
  /* ——— a taste test: the options side by side, Kit's pick lit and the rest stepping back ——— */
14866
16510
  .knobs-wt-options{display:grid;grid-template-columns:repeat(var(--kw-n,2),minmax(0,1fr));gap:10px}
14867
16511
  @container knobs-wt-step (max-width:640px){.knobs-wt-options{grid-template-columns:minmax(0,1fr)}}
14868
- .knobs-wt-option{position:relative;display:flex;flex-direction:column;gap:8px;min-width:0;padding:8px;border-radius:calc(var(--ku-panel-radius) - 4px);background:var(--ku-wash);
16512
+ .knobs-wt-option{position:relative;display:flex;flex-direction:column;gap:8px;min-width:0;padding:8px;border-radius:calc(var(--_k-radius-panel) - 4px);background:var(--_ku-wash);
14869
16513
  transition:background var(--kw-snappy-ms) var(--kw-snappy)}
14870
- .knobs-wt-option[data-picked]{background:color-mix(in srgb,var(--ku-accent) 12%,var(--ku-wash))}
16514
+ .knobs-wt-option[data-picked]{background:color-mix(in srgb,var(--_k-accent) 12%,var(--_ku-wash))}
14871
16515
  .knobs-wt-option>:not(.knobs-wt-pick){transition:opacity var(--kw-snappy-ms) var(--kw-snappy)}
14872
16516
  .knobs-wt-options[data-has-pick] .knobs-wt-option:not([data-picked])>:not(.knobs-wt-pick){opacity:.55}
14873
- .knobs-ui .knobs-wt-pick{display:flex;align-items:center;gap:8px;width:100%;min-height:28px;padding:0 4px;border-radius:calc(var(--ku-radius) - 2px);cursor:pointer;color:var(--ku-label);text-align:left}
14874
- .knobs-ui .knobs-wt-pick:is(:hover,:focus-visible){color:var(--ku-text)}
14875
- .knobs-wt-letter{flex:none;font:var(--ku-title-weight) calc(var(--kw-text) - 1px)/1 var(--ku-font);color:var(--ku-text)}
14876
- .knobs-wt-olabel{flex:1;min-width:0;font-weight:var(--ku-label-weight);color:var(--ku-text)}
14877
- .knobs-wt-suggested{flex:none;font-size:calc(var(--kw-text) - 3px);color:var(--ku-dim)}
14878
- .knobs-wt-check{flex:none;display:flex;width:18px;height:18px;align-items:center;justify-content:center;border-radius:50%;background:var(--ku-surface);color:transparent;
16517
+ .knobs-ui .knobs-wt-pick{display:flex;align-items:center;gap:8px;width:100%;min-height:28px;padding:0 4px;border-radius:calc(var(--_k-radius) - 2px);cursor:pointer;color:var(--_k-fg-2);text-align:left}
16518
+ .knobs-ui .knobs-wt-pick:is(:hover,:focus-visible){color:var(--_k-fg)}
16519
+ .knobs-wt-letter{flex:none;font:var(--_k-weight-title) calc(var(--kw-text) - 1px)/1 var(--_k-font);color:var(--_k-fg)}
16520
+ .knobs-wt-olabel{flex:1;min-width:0;font-weight:var(--_k-weight-label);color:var(--_k-fg)}
16521
+ .knobs-wt-suggested{flex:none;font-size:calc(var(--kw-text) - 3px);color:var(--_k-fg-3)}
16522
+ .knobs-wt-check{flex:none;display:flex;width:18px;height:18px;align-items:center;justify-content:center;border-radius:50%;background:var(--_k-fill);color:transparent;
14879
16523
  transition:background var(--kw-snappy-ms) var(--kw-snappy),color var(--kw-snappy-ms) var(--kw-snappy)}
14880
16524
  .knobs-wt-check svg{width:12px;height:12px}
14881
- .knobs-wt-option[data-picked] .knobs-wt-check{background:var(--ku-accent);color:var(--ku-bg)}
14882
- .knobs-wt-key{display:inline-flex;align-items:center;justify-content:center;min-width:15px;height:15px;padding:0 3px;border-radius:4px;background:var(--ku-surface);color:var(--ku-dim);
14883
- font:var(--ku-label-weight) calc(var(--kw-text) - 4px)/1 var(--ku-font);font-variant-numeric:tabular-nums;opacity:.5;transition:opacity .15s}
16525
+ .knobs-wt-option[data-picked] .knobs-wt-check{background:var(--_k-accent);color:var(--_k-bg)}
16526
+ .knobs-wt-key{display:inline-flex;align-items:center;justify-content:center;min-width:15px;height:15px;padding:0 3px;border-radius:4px;background:var(--_k-fill);color:var(--_k-fg-3);
16527
+ font:var(--_k-weight-label) calc(var(--kw-text) - 4px)/1 var(--_k-font);font-variant-numeric:tabular-nums;opacity:.5;transition:opacity .15s}
14884
16528
  .knobs-wt-step[data-current] .knobs-wt-key{opacity:1}
14885
- .knobs-wt-ocap{color:var(--ku-label);font-size:calc(var(--kw-text) - 1px);padding:0 4px}
16529
+ .knobs-wt-ocap{color:var(--_k-fg-2);font-size:calc(var(--kw-text) - 1px);padding:0 4px}
14886
16530
 
14887
16531
  /* ——— the rail: progress, contents, export ——— */
14888
16532
  .knobs-wt-rail{position:sticky;top:16px;display:flex;flex-direction:column;gap:14px;max-height:calc(100vh - 32px);min-height:0;font-size:calc(var(--kw-text) - 1.5px)}
14889
16533
  .knobs-wt-progress{display:flex;flex-direction:column;gap:7px}
14890
- .knobs-wt-count{display:flex;align-items:baseline;justify-content:space-between;color:var(--ku-label);font-variant-numeric:tabular-nums}
14891
- .knobs-wt-count b{color:var(--ku-text);font-weight:var(--ku-label-weight)}
14892
- .knobs-wt-bar{position:relative;height:4px;border-radius:2px;overflow:hidden;background:var(--ku-surface)}
14893
- .knobs-wt-fill{position:absolute;inset:0;border-radius:inherit;background:var(--ku-accent);transform-origin:0 50%;transform:scaleX(var(--kw-done,0))}
16534
+ .knobs-wt-count{display:flex;align-items:baseline;justify-content:space-between;color:var(--_k-fg-2);font-variant-numeric:tabular-nums}
16535
+ .knobs-wt-count b{color:var(--_k-fg);font-weight:var(--_k-weight-label)}
16536
+ .knobs-wt-bar{position:relative;height:4px;border-radius:2px;overflow:hidden;background:var(--_k-fill)}
16537
+ .knobs-wt-fill{position:absolute;inset:0;border-radius:inherit;background:var(--_k-accent);transform-origin:0 50%;transform:scaleX(var(--kw-done,0))}
14894
16538
  .knobs-walkthrough[data-settled] .knobs-wt-fill{transition:transform var(--kw-calm-ms) var(--kw-calm)}
14895
16539
  /* The contents: no box, one text spine for sections and steps (the steps' dots hang in the
14896
16540
  gutter left of it), and one pill behind the current step that springs between rows. */
14897
16541
  .knobs-wt-toc{position:relative;flex:1 1 auto;min-height:0;overflow:auto;scrollbar-width:none;margin:0 -8px;padding:0 0 8px}
14898
16542
  .knobs-wt-toc::-webkit-scrollbar{display:none}
14899
- .knobs-wt-toc-section{display:block;padding:12px 8px 4px 26px;color:var(--ku-dim);font-size:calc(var(--kw-text) - 3px);font-weight:var(--ku-label-weight);white-space:nowrap;overflow:hidden;
16543
+ .knobs-wt-toc-section{display:block;padding:12px 8px 4px 26px;color:var(--_k-fg-3);font-size:calc(var(--kw-text) - 3px);font-weight:var(--_k-weight-label);white-space:nowrap;overflow:hidden;
14900
16544
  -webkit-mask-image:linear-gradient(to right,#000 calc(100% - 1.5em),transparent);mask-image:linear-gradient(to right,#000 calc(100% - 1.5em),transparent)}
14901
16545
  .knobs-wt-toc-section:first-of-type{padding-top:2px}
14902
- .knobs-wt-toc-mark{position:absolute;left:0;right:0;top:0;height:0;border-radius:calc(var(--ku-radius) - 1px);background:var(--ku-wash-hi);pointer-events:none;opacity:0;will-change:transform}
16546
+ .knobs-wt-toc-mark{position:absolute;left:0;right:0;top:0;height:0;border-radius:calc(var(--_k-radius) - 1px);background:var(--_ku-wash-hi);pointer-events:none;opacity:0;will-change:transform}
14903
16547
  .knobs-wt-toc-mark[data-on]{opacity:1}
14904
16548
  .knobs-walkthrough[data-settled] .knobs-wt-toc-mark{transition:opacity .15s}
14905
- .knobs-ui .knobs-wt-toc-step{position:relative;display:flex;align-items:center;width:100%;text-align:left;height:26px;padding:0 8px 0 26px;color:var(--ku-label);cursor:pointer;white-space:nowrap}
14906
- .knobs-ui .knobs-wt-toc-step:is(:hover,:focus-visible){color:var(--ku-text)}
14907
- .knobs-wt-toc-step[aria-current="step"]{color:var(--ku-text)}
16549
+ .knobs-ui .knobs-wt-toc-step{position:relative;display:flex;align-items:center;width:100%;text-align:left;height:26px;padding:0 8px 0 26px;color:var(--_k-fg-2);cursor:pointer;white-space:nowrap}
16550
+ .knobs-ui .knobs-wt-toc-step:is(:hover,:focus-visible){color:var(--_k-fg)}
16551
+ .knobs-wt-toc-step[aria-current="step"]{color:var(--_k-fg)}
14908
16552
  .knobs-wt-toc-label{flex:1;min-width:0;overflow:hidden;-webkit-mask-image:linear-gradient(to right,#000 calc(100% - 1.5em),transparent);mask-image:linear-gradient(to right,#000 calc(100% - 1.5em),transparent)}
14909
16553
  /* A step's state: an open ring, a filled dot once answered, nothing to answer a faint ring. */
14910
- .knobs-wt-toc-glyph{--kw-tone:var(--ku-dim);position:absolute;left:11px;top:50%;width:7px;height:7px;margin-top:-3.5px;border-radius:50%;box-shadow:inset 0 0 0 1.5px var(--kw-tone);
16554
+ .knobs-wt-toc-glyph{--kw-tone:var(--_k-fg-3);position:absolute;left:11px;top:50%;width:7px;height:7px;margin-top:-3.5px;border-radius:50%;box-shadow:inset 0 0 0 1.5px var(--kw-tone);
14911
16555
  transition:background var(--kw-snappy-ms) var(--kw-snappy),box-shadow var(--kw-snappy-ms) var(--kw-snappy)}
14912
- .knobs-wt-toc-glyph[data-tone="accent"]{--kw-tone:var(--ku-accent)}
16556
+ .knobs-wt-toc-glyph[data-tone="accent"]{--kw-tone:var(--_k-accent)}
14913
16557
  .knobs-wt-toc-glyph[data-done]{background:var(--kw-tone)}
14914
- .knobs-wt-toc-glyph[data-tone="none"]{box-shadow:inset 0 0 0 1px var(--ku-line)}
16558
+ .knobs-wt-toc-glyph[data-tone="none"]{box-shadow:inset 0 0 0 1px var(--_k-border)}
14915
16559
  .knobs-wt-actions{display:flex;flex-wrap:wrap;gap:4px}
14916
- .knobs-ui .knobs-wt-btn{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 9px;border-radius:var(--ku-radius);color:var(--ku-label);cursor:pointer;white-space:nowrap;
16560
+ .knobs-ui .knobs-wt-btn{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 9px;border-radius:var(--_k-radius);color:var(--_k-fg-2);cursor:pointer;white-space:nowrap;
14917
16561
  transition:background .15s,color .15s}
14918
- .knobs-ui .knobs-wt-btn:is(:hover,:focus-visible){background:var(--ku-wash-hi);color:var(--ku-text)}
14919
- .knobs-ui .knobs-wt-btn[data-primary]{background:var(--ku-surface-hi);color:var(--ku-text)}
14920
- .knobs-ui .knobs-wt-btn[data-primary]:is(:hover,:focus-visible){background:color-mix(in srgb,var(--ku-text) 16%,transparent)}
14921
- .knobs-wt-keys{color:var(--ku-dim);font-size:calc(var(--kw-text) - 3px);line-height:1.6}
14922
- .knobs-wt-keys kbd{font:inherit;color:var(--ku-label)}
16562
+ .knobs-ui .knobs-wt-btn:is(:hover,:focus-visible){background:var(--_ku-wash-hi);color:var(--_k-fg)}
16563
+ .knobs-ui .knobs-wt-btn[data-primary]{background:var(--_k-fill-selected);color:var(--_k-fg)}
16564
+ .knobs-ui .knobs-wt-btn[data-primary]:is(:hover,:focus-visible){background:color-mix(in srgb,var(--_k-fg) 16%,transparent)}
16565
+ .knobs-wt-keys{color:var(--_k-fg-3);font-size:calc(var(--kw-text) - 3px);line-height:1.6}
16566
+ .knobs-wt-keys kbd{font:inherit;color:var(--_k-fg-2)}
14923
16567
  /* Narrow: the rail becomes a bar along the top, with the progress and the export only. */
14924
16568
  @container knobs-wt (max-width:880px){
14925
- .knobs-wt-rail{z-index:4;flex-direction:row;align-items:center;gap:12px;max-height:none;margin:0 calc(var(--kw-pad) * -1) 20px;padding:8px var(--kw-pad);top:0;background:var(--ku-page)}
16569
+ .knobs-wt-rail{z-index:4;flex-direction:row;align-items:center;gap:12px;max-height:none;margin:0 calc(var(--kw-pad) * -1) 20px;padding:8px var(--kw-pad);top:0;background:var(--_k-bg-page)}
14926
16570
  .knobs-wt-progress{flex:1}.knobs-wt-toc,.knobs-wt-keys{display:none}
14927
16571
  .knobs-wt-step,.knobs-wt-shead{scroll-margin-top:60px}
14928
16572
  }
14929
16573
 
14930
16574
  /* ——— media slots ——— */
14931
- .knobs-ui.knobs-wt-slot{position:relative;min-width:0;container:knobs-wt-slot / inline-size;color:var(--ku-text);font:var(--ku-font-weight) var(--k-walkthrough-text,14px)/1.5 var(--ku-font)}
14932
- .knobs-wt-slot-label{display:block;margin:0 0 6px 2px;font:var(--ku-label-weight) calc(var(--k-walkthrough-text,14px) - 3px)/1.3 var(--ku-font);color:var(--ku-label);letter-spacing:.04em;text-transform:uppercase}
16575
+ .knobs-ui.knobs-wt-slot{position:relative;min-width:0;container:knobs-wt-slot / inline-size;color:var(--_k-fg);font:var(--_k-weight) var(--k-walkthrough-text,14px)/1.5 var(--_k-font)}
16576
+ .knobs-wt-slot-label{display:block;margin:0 0 6px 2px;font:var(--_k-weight-label) calc(var(--k-walkthrough-text,14px) - 3px)/1.3 var(--_k-font);color:var(--_k-fg-2);letter-spacing:.04em;text-transform:uppercase}
14933
16577
  /* A compare is exactly as tall as its pictures at this width, so there's no letterbox: the two
14934
16578
  sides edge to edge (side) or one (overlaid), plus its mode bar, the timeline and their two gaps
14935
16579
  (92 px), and the frame strip with its gap (158 px). */
@@ -14937,37 +16581,37 @@ var walkthroughCss = `
14937
16581
  .knobs-wt-fit[data-overlay]{height:calc(100cqw / var(--kw-aspect,1.7778) + var(--kw-chrome,92px))}
14938
16582
  .knobs-wt-fit[data-strip]{--kw-chrome:158px}
14939
16583
  .knobs-wt-fit[data-settled]{transition:height var(--k-wt-calm-ms,${calm.duration}ms) ${calm.easing}}
14940
- .knobs-wt-frame{position:relative;width:100%;overflow:hidden;border-radius:calc(var(--ku-panel-radius) - 4px);background:var(--ku-surface);aspect-ratio:var(--kw-aspect,16/9)}
16584
+ .knobs-wt-frame{position:relative;width:100%;overflow:hidden;border-radius:calc(var(--_k-radius-panel) - 4px);background:var(--_k-fill);aspect-ratio:var(--kw-aspect,16/9)}
14941
16585
  .knobs-wt-frame>:is(video,img){position:absolute;inset:0;display:block;width:100%;height:100%;object-fit:contain;margin:0;border:0}
14942
16586
  .knobs-wt-frame[data-natural]{aspect-ratio:auto}
14943
16587
  .knobs-wt-frame[data-natural]>img{position:static;height:auto}
14944
- .knobs-wt-code{margin:0;padding:12px 14px;max-height:420px;overflow:auto;border-radius:calc(var(--ku-panel-radius) - 4px);background:var(--ku-surface);color:var(--ku-text);
14945
- font:calc(var(--k-walkthrough-text,14px) - 2px)/1.55 var(--ku-mono);white-space:pre;tab-size:2;scrollbar-width:thin}
16588
+ .knobs-wt-code{margin:0;padding:12px 14px;max-height:420px;overflow:auto;border-radius:calc(var(--_k-radius-panel) - 4px);background:var(--_k-fill);color:var(--_k-fg);
16589
+ font:calc(var(--k-walkthrough-text,14px) - 2px)/1.55 var(--_k-mono);white-space:pre;tab-size:2;scrollbar-width:thin}
14946
16590
  .knobs-wt-code[data-terminal]{white-space:pre-wrap;overflow-wrap:anywhere}
14947
- .knobs-wt-prompt{color:var(--ku-dim);user-select:none;-webkit-user-select:none}
14948
- .knobs-wt-cmd{color:var(--ku-text);font-weight:var(--ku-label-weight)}
14949
- .knobs-wt-out{color:var(--ku-label)}
14950
- .knobs-wt-metric{display:flex;flex-direction:column;gap:8px;padding:12px 14px;border-radius:calc(var(--ku-panel-radius) - 4px);background:var(--ku-surface)}
14951
- .knobs-wt-mlabel{color:var(--ku-label);font-size:calc(var(--k-walkthrough-text,14px) - 2px)}
16591
+ .knobs-wt-prompt{color:var(--_k-fg-3);user-select:none;-webkit-user-select:none}
16592
+ .knobs-wt-cmd{color:var(--_k-fg);font-weight:var(--_k-weight-label)}
16593
+ .knobs-wt-out{color:var(--_k-fg-2)}
16594
+ .knobs-wt-metric{display:flex;flex-direction:column;gap:8px;padding:12px 14px;border-radius:calc(var(--_k-radius-panel) - 4px);background:var(--_k-fill)}
16595
+ .knobs-wt-mlabel{color:var(--_k-fg-2);font-size:calc(var(--k-walkthrough-text,14px) - 2px)}
14952
16596
  .knobs-wt-mvalue{display:flex;align-items:baseline;flex-wrap:wrap;gap:8px;font-variant-numeric:tabular-nums;font-feature-settings:"tnum"}
14953
- .knobs-wt-mfrom{color:var(--ku-dim);font-size:calc(var(--k-walkthrough-text,14px) + 2px)}
14954
- .knobs-wt-mto{font-size:calc(var(--k-walkthrough-text,14px) + 12px);font-weight:var(--ku-title-weight);line-height:1}
14955
- .knobs-wt-mof{color:var(--ku-dim)}
14956
- .knobs-wt-mdelta{--kw-tone:var(--ku-label);padding:1px 7px;border-radius:999px;font-size:calc(var(--k-walkthrough-text,14px) - 3px);font-weight:var(--ku-label-weight);color:var(--kw-tone);background:color-mix(in srgb,var(--kw-tone) 14%,transparent)}
14957
- .knobs-wt-mdelta[data-tone="good"]{--kw-tone:var(--k-walkthrough-good,#30d158)}
14958
- .knobs-wt-mdelta[data-tone="bad"]{--kw-tone:var(--ku-critical)}
14959
- .knobs-wt-mtrack{position:relative;height:4px;border-radius:2px;background:color-mix(in srgb,var(--ku-text) 8%,transparent)}
16597
+ .knobs-wt-mfrom{color:var(--_k-fg-3);font-size:calc(var(--k-walkthrough-text,14px) + 2px)}
16598
+ .knobs-wt-mto{font-size:calc(var(--k-walkthrough-text,14px) + 12px);font-weight:var(--_k-weight-title);line-height:1}
16599
+ .knobs-wt-mof{color:var(--_k-fg-3)}
16600
+ .knobs-wt-mdelta{--kw-tone:var(--_k-fg-2);padding:1px 7px;border-radius:999px;font-size:calc(var(--k-walkthrough-text,14px) - 3px);font-weight:var(--_k-weight-label);color:var(--kw-tone);background:color-mix(in srgb,var(--kw-tone) 14%,transparent)}
16601
+ .knobs-wt-mdelta[data-tone="good"]{--kw-tone:var(--kw-good)}
16602
+ .knobs-wt-mdelta[data-tone="bad"]{--kw-tone:var(--_k-danger)}
16603
+ .knobs-wt-mtrack{position:relative;height:4px;border-radius:2px;background:color-mix(in srgb,var(--_k-fg) 8%,transparent)}
14960
16604
  .knobs-wt-mtrack>span{position:absolute;top:0;bottom:0;left:0;border-radius:inherit}
14961
- .knobs-wt-mtrack>.knobs-wt-mafter{background:var(--ku-accent)}
14962
- .knobs-wt-mtrack>.knobs-wt-mbefore{background:color-mix(in srgb,var(--ku-text) 30%,transparent)}
14963
- .knobs-wt-callout{--kw-tone:var(--k-walkthrough-info,#64d2ff);display:flex;gap:10px;padding:10px 14px;border-radius:calc(var(--ku-panel-radius) - 4px);background:color-mix(in srgb,var(--kw-tone) 11%,transparent);color:var(--ku-text)}
16605
+ .knobs-wt-mtrack>.knobs-wt-mafter{background:var(--_k-accent)}
16606
+ .knobs-wt-mtrack>.knobs-wt-mbefore{background:color-mix(in srgb,var(--_k-fg) 30%,transparent)}
16607
+ .knobs-wt-callout{--kw-tone:var(--kw-info);display:flex;gap:10px;padding:10px 14px;border-radius:calc(var(--_k-radius-panel) - 4px);background:color-mix(in srgb,var(--kw-tone) 11%,transparent);color:var(--_k-fg)}
14964
16608
  .knobs-wt-callout::before{content:"";flex:none;width:6px;height:6px;margin-top:.62em;border-radius:50%;background:var(--kw-tone)}
14965
- .knobs-wt-callout[data-tone="good"]{--kw-tone:var(--k-walkthrough-good,#30d158)}
14966
- .knobs-wt-callout[data-tone="warn"]{--kw-tone:var(--ku-warn)}
14967
- .knobs-wt-callout[data-tone="bad"]{--kw-tone:var(--ku-critical)}
14968
- .knobs-wt-text{max-width:var(--k-walkthrough-measure,68ch);color:var(--ku-label)}
14969
- .knobs-wt-hold{border-radius:calc(var(--ku-panel-radius) - 4px);background:var(--ku-surface)}
14970
- .knobs-wt-failed{display:flex;align-items:center;justify-content:center;min-height:80px;color:var(--ku-dim);font-size:calc(var(--k-walkthrough-text,14px) - 2px)}
16609
+ .knobs-wt-callout[data-tone="good"]{--kw-tone:var(--kw-good)}
16610
+ .knobs-wt-callout[data-tone="warn"]{--kw-tone:var(--_k-warn)}
16611
+ .knobs-wt-callout[data-tone="bad"]{--kw-tone:var(--_k-danger)}
16612
+ .knobs-wt-text{max-width:var(--k-walkthrough-measure,68ch);color:var(--_k-fg-2)}
16613
+ .knobs-wt-hold{border-radius:calc(var(--_k-radius-panel) - 4px);background:var(--_k-fill)}
16614
+ .knobs-wt-failed{display:flex;align-items:center;justify-content:center;min-height:80px;color:var(--_k-fg-3);font-size:calc(var(--k-walkthrough-text,14px) - 2px)}
14971
16615
  @media(prefers-reduced-motion:reduce){:is(.knobs-walkthrough,.knobs-wt-slot) :where(*,::before,::after){transition-duration:.15s!important;transition-property:opacity,background,color!important}}
14972
16616
  `;
14973
16617
 
@@ -15004,7 +16648,7 @@ function parseAspect(aspect) {
15004
16648
  const h = m[2] === undefined ? 1 : Number(m[2]);
15005
16649
  return w > 0 && h > 0 ? w / h : undefined;
15006
16650
  }
15007
- function source(s, base) {
16651
+ function source2(s, base) {
15008
16652
  const v = typeof s === "string" ? { src: s } : s;
15009
16653
  return { ...v, src: resolveSrc(v.src, base) };
15010
16654
  }
@@ -15013,7 +16657,7 @@ function fillMedia(m, base) {
15013
16657
  return mediaOf(resolveSrc(m, base));
15014
16658
  switch (m.kind) {
15015
16659
  case "compare":
15016
- return { ...m, before: source(m.before, base), after: source(m.after, base) };
16660
+ return { ...m, before: source2(m.before, base), after: source2(m.after, base) };
15017
16661
  case "video":
15018
16662
  return {
15019
16663
  ...m,
@@ -15414,7 +17058,7 @@ function injectWalkthroughStyles(doc) {
15414
17058
  return;
15415
17059
  const style = doc.createElement("style");
15416
17060
  style.dataset.knobsUiWalkthrough = "";
15417
- style.textContent = walkthroughCss;
17061
+ style.textContent = aliased(walkthroughCss);
15418
17062
  doc.head.append(style);
15419
17063
  }
15420
17064
  var watchers = new WeakMap;
@@ -15769,7 +17413,7 @@ function mediaSlot(container, options) {
15769
17413
  const m = fillMedia(options.media);
15770
17414
  const root = div(doc, "knobs-wt-slot");
15771
17415
  root.dataset.kind = m.kind;
15772
- applyLook(root, options);
17416
+ applyLook2(root, options);
15773
17417
  const label = labelOf2(m);
15774
17418
  if (label && (m.kind === "video" || m.kind === "image" || m.kind === "code" || m.kind === "terminal")) {
15775
17419
  const l = doc.createElement("span");
@@ -15915,8 +17559,8 @@ var ICON = {
15915
17559
  send: svg('<path d="M8 13V3.5M4 7.5 8 3.5l4 4"/>'),
15916
17560
  close: svg('<path d="M4.5 4.5l7 7M11.5 4.5l-7 7"/>')
15917
17561
  };
15918
- var CALM2 = springMotion({ duration: 0.4, bounce: 0 });
15919
- var SMOOTH = springMotion({ duration: 0.45, bounce: 0 });
17562
+ var CALM2 = springMotion(SPRINGS.calm);
17563
+ var SMOOTH = springMotion(SPRINGS.smooth);
15920
17564
  var BACK_MS = 4500;
15921
17565
  function tasteTest(container, options) {
15922
17566
  const doc = container.ownerDocument;
@@ -15936,7 +17580,7 @@ function tasteTest(container, options) {
15936
17580
  root.setAttribute("aria-label", "Options");
15937
17581
  root.style.setProperty("--kw-n", String(Math.min(list.length, 3)));
15938
17582
  if (!container.closest(".knobs-ui"))
15939
- applyLook(root, options);
17583
+ applyLook2(root, options);
15940
17584
  const slots = [];
15941
17585
  const tiles = list.map((o, i) => {
15942
17586
  const tile = el(doc, "div", "knobs-wt-option");
@@ -16025,7 +17669,7 @@ function walkthrough(container, options) {
16025
17669
  const look = lookOf2(options);
16026
17670
  const storage = options.storage === undefined ? browserStorage() : options.storage;
16027
17671
  const root = el(doc, "div", "knobs-walkthrough");
16028
- applyLook(root, options);
17672
+ applyLook2(root, options);
16029
17673
  container.append(root);
16030
17674
  let page = normalizeWalkthrough(options.doc);
16031
17675
  const keyOf = () => storageKey(page.id, "walkthrough");
@@ -16290,13 +17934,13 @@ function walkthrough(container, options) {
16290
17934
  placeFull(full);
16291
17935
  win.addEventListener("resize", onFullResize);
16292
17936
  }
16293
- tune(full.p, reduced() ? springMotion({ duration: 0.2, bounce: 0 }) : SMOOTH);
17937
+ tune(full.p, reduced() ? springMotion(FADE) : SMOOTH);
16294
17938
  full.p.set(1);
16295
17939
  record({ what: "full", step: v.step.key, detail: "on" });
16296
17940
  } else {
16297
17941
  if (!full)
16298
17942
  return;
16299
- tune(full.p, reduced() ? springMotion({ duration: 0.16, bounce: 0 }) : SMOOTH);
17943
+ tune(full.p, reduced() ? springMotion(FADE) : SMOOTH);
16300
17944
  full.p.set(0);
16301
17945
  record({ what: "full", step: full.v.step.key, detail: "off" });
16302
17946
  }