twiddle-panel 0.9.0 → 0.9.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.
package/dist/twiddle.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  const Ct = /* @__PURE__ */ new Set();
2
- let E = ya(), oe = [], Ee = [], Ze = null, gn = 0;
2
+ let M = ya(), oe = [], Ee = [], Ze = null, gn = 0;
3
3
  function ya() {
4
4
  const e = new URLSearchParams(location.search).get("twd");
5
5
  if (!e) return {};
@@ -11,15 +11,15 @@ function ya() {
11
11
  }
12
12
  function ka() {
13
13
  const e = new URL(location.href);
14
- Object.keys(E).length ? e.searchParams.set("twd", JSON.stringify(E)) : e.searchParams.delete("twd"), history.replaceState(history.state, "", e);
14
+ Object.keys(M).length ? e.searchParams.set("twd", JSON.stringify(M)) : e.searchParams.delete("twd"), history.replaceState(history.state, "", e);
15
15
  }
16
16
  function Rt() {
17
- ka(), Ct.forEach((e) => e(E));
17
+ ka(), Ct.forEach((e) => e(M));
18
18
  }
19
19
  function re(e, t) {
20
- if (JSON.stringify(e) === JSON.stringify(E)) return;
20
+ if (JSON.stringify(e) === JSON.stringify(M)) return;
21
21
  const n = Date.now();
22
- t && t === Ze && n - gn < 400 || (oe.push(E), oe.length > 100 && oe.shift()), Ee = [], Ze = t, gn = n, E = e, Rt();
22
+ t && t === Ze && n - gn < 400 || (oe.push(M), oe.length > 100 && oe.shift()), Ee = [], Ze = t, gn = n, M = e, Rt();
23
23
  }
24
24
  function Te(e, t) {
25
25
  const n = { ...e, ...t };
@@ -32,51 +32,51 @@ function I(e, t, n) {
32
32
  return n == null ? delete a[t] : a[t] = n, a;
33
33
  }
34
34
  function Mt() {
35
- return JSON.parse(JSON.stringify(E));
35
+ return JSON.parse(JSON.stringify(M));
36
36
  }
37
37
  function Sa(e, t) {
38
- re(I(E, e, Te(E[e], t)), `${e}:${Object.keys(t)}`);
38
+ re(I(M, e, Te(M[e], t)), `${e}:${Object.keys(t)}`);
39
39
  }
40
40
  function $a(e, t = `multi:${Object.keys(e)}`) {
41
- const n = Object.entries(e).reduce((a, [o, r]) => I(a, o, Te(a[o], r)), E);
41
+ const n = Object.entries(e).reduce((a, [o, r]) => I(a, o, Te(a[o], r)), M);
42
42
  re(n, t);
43
43
  }
44
- function Dn(e, t, n) {
45
- const a = I(E.scopes?.[e], t, Te(E.scopes?.[e]?.[t], n)), o = I(E.scopes, e, Object.keys(a).length ? a : null);
46
- re(I(E, "scopes", Object.keys(o).length ? o : null), `${e}|${t}:${Object.keys(n)}`);
44
+ function In(e, t, n) {
45
+ const a = I(M.scopes?.[e], t, Te(M.scopes?.[e]?.[t], n)), o = I(M.scopes, e, Object.keys(a).length ? a : null);
46
+ re(I(M, "scopes", Object.keys(o).length ? o : null), `${e}|${t}:${Object.keys(n)}`);
47
47
  }
48
48
  function Ea(e, t, n = `multi:${Object.keys(t)}`) {
49
- const a = Object.entries(t).reduce((r, [s, i]) => I(r, s, Te(r?.[s], i)), E.scopes?.[e]), o = I(E.scopes, e, Object.keys(a).length ? a : null);
50
- re(I(E, "scopes", Object.keys(o).length ? o : null), `${e}|${n}`);
49
+ const a = Object.entries(t).reduce((r, [s, i]) => I(r, s, Te(r?.[s], i)), M.scopes?.[e]), o = I(M.scopes, e, Object.keys(a).length ? a : null);
50
+ re(I(M, "scopes", Object.keys(o).length ? o : null), `${e}|${n}`);
51
51
  }
52
52
  function Ca(e, t) {
53
- if (t) return Dn(e, t, Object.fromEntries(
54
- Object.keys(E.scopes?.[e]?.[t] || {}).map((a) => [a, null])
53
+ if (t) return In(e, t, Object.fromEntries(
54
+ Object.keys(M.scopes?.[e]?.[t] || {}).map((a) => [a, null])
55
55
  ));
56
- const n = I(E.scopes, e, null);
57
- re(I(E, "scopes", Object.keys(n).length ? n : null));
56
+ const n = I(M.scopes, e, null);
57
+ re(I(M, "scopes", Object.keys(n).length ? n : null));
58
58
  }
59
59
  function Ma(e, t) {
60
- const n = E.scopes?.[e];
60
+ const n = M.scopes?.[e];
61
61
  if (!n || e === t) return;
62
- let a = { ...E.scopes[t] };
62
+ let a = { ...M.scopes[t] };
63
63
  Object.entries(n).forEach(([r, s]) => {
64
64
  a = I(a, r, Te(a[r], s));
65
65
  });
66
- const o = I(I(E.scopes, e, null), t, a);
67
- re(I(E, "scopes", o));
66
+ const o = I(I(M.scopes, e, null), t, a);
67
+ re(I(M, "scopes", o));
68
68
  }
69
- function Bn() {
69
+ function Dn() {
70
70
  re({});
71
71
  }
72
- function Un() {
73
- oe.length && (Ee.push(E), E = oe.pop(), Ze = null, Rt());
72
+ function Bn() {
73
+ oe.length && (Ee.push(M), M = oe.pop(), Ze = null, Rt());
74
74
  }
75
- function Vn() {
76
- Ee.length && (oe.push(E), E = Ee.pop(), Ze = null, Rt());
75
+ function Un() {
76
+ Ee.length && (oe.push(M), M = Ee.pop(), Ze = null, Rt());
77
77
  }
78
78
  const Ta = () => oe.length > 0, La = () => Ee.length > 0;
79
- function qn(e) {
79
+ function Vn(e) {
80
80
  return Ct.add(e), () => Ct.delete(e);
81
81
  }
82
82
  const Aa = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
@@ -85,21 +85,21 @@ const Aa = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
85
85
  canUndo: Ta,
86
86
  getState: Mt,
87
87
  moveScope: Ma,
88
- onChange: qn,
89
- redo: Vn,
88
+ onChange: Vn,
89
+ redo: Un,
90
90
  removeScope: Ca,
91
- resetState: Bn,
92
- setScope: Dn,
91
+ resetState: Dn,
92
+ setScope: In,
93
93
  setScopeSections: Ea,
94
94
  setSection: Sa,
95
95
  setSections: $a,
96
- undo: Un
97
- }, Symbol.toStringTag, { value: "Module" })), Hn = ':root{--twd-font-heading: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;--twd-font-body: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;--twd-text-xs: .694rem;--twd-text-sm: .833rem;--twd-text-base: 1rem;--twd-text-lg: 1.2rem;--twd-text-xl: 1.44rem;--twd-text-2xl: 1.728rem;--twd-text-3xl: 2.074rem;--twd-leading-tight: 1.2;--twd-leading-normal: 1.5;--twd-weight-heading: 600;--twd-weight-strong: 600;--twd-bg: #fafafa;--twd-surface: #ffffff;--twd-surface-raised: #ffffff;--twd-text: #18181b;--twd-text-muted: #71717a;--twd-border: #e4e4e7;--twd-primary: #4f46e5;--twd-primary-hover: #4338ca;--twd-on-primary: #ffffff;--twd-focus: #6366f1;--twd-success: #16a34a;--twd-warning: #d97706;--twd-danger: #dc2626;--twd-radius-control: 8px;--twd-radius-container: 12px;--twd-space-1: 4px;--twd-space-2: 8px;--twd-space-3: 12px;--twd-space-4: 16px;--twd-space-5: 24px;--twd-space-6: 32px;--twd-space-7: 48px;--twd-space-8: 64px;--twd-control-height: 40px;--twd-control-pad-x: 16px;--twd-page-pad: var(--twd-space-5);--twd-section-gap: var(--twd-space-6);--twd-card-pad: var(--twd-space-5);--twd-card-gap: var(--twd-space-2);--twd-control-gap: var(--twd-space-3);--twd-border-width: 1px;--twd-border-width-container: var(--twd-border-width);--twd-shadow-sm: 0 1px 2px rgb(0 0 0 / .06);--twd-shadow-md: 0 4px 12px rgb(0 0 0 / .08);--twd-shadow-lg: 0 12px 32px rgb(0 0 0 / .12);--twd-button-bg: var(--twd-primary);--twd-button-fg: var(--twd-on-primary);--twd-button-border: transparent;--twd-button-hover: var(--twd-primary-hover);--twd-card-bg: var(--twd-surface);--twd-card-border: var(--twd-border);--twd-card-shadow: var(--twd-shadow-sm)}', Oa = [...Hn.matchAll(/(--twd-[\w-]+):\s*([^;]*var\(--twd-[^;]*);/g)].map((e) => [e[1], e[2].trim()]);
98
- function Pa(e) {
96
+ undo: Bn
97
+ }, Symbol.toStringTag, { value: "Module" })), qn = ':root{--twd-font-heading: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;--twd-font-body: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;--twd-text-xs: .694rem;--twd-text-sm: .833rem;--twd-text-base: 1rem;--twd-text-lg: 1.2rem;--twd-text-xl: 1.44rem;--twd-text-2xl: 1.728rem;--twd-text-3xl: 2.074rem;--twd-leading-tight: 1.2;--twd-leading-normal: 1.5;--twd-weight-heading: 600;--twd-weight-strong: 600;--twd-bg: #fafafa;--twd-surface: #ffffff;--twd-surface-raised: #ffffff;--twd-text: #18181b;--twd-text-muted: #71717a;--twd-border: #e4e4e7;--twd-primary: #4f46e5;--twd-primary-hover: #4338ca;--twd-on-primary: #ffffff;--twd-focus: #6366f1;--twd-success: #16a34a;--twd-warning: #d97706;--twd-danger: #dc2626;--twd-radius-control: 8px;--twd-radius-container: 12px;--twd-space-1: 4px;--twd-space-2: 8px;--twd-space-3: 12px;--twd-space-4: 16px;--twd-space-5: 24px;--twd-space-6: 32px;--twd-space-7: 48px;--twd-space-8: 64px;--twd-control-height: 40px;--twd-control-pad-x: 16px;--twd-page-pad: var(--twd-space-5);--twd-section-gap: var(--twd-space-6);--twd-card-pad: var(--twd-space-5);--twd-card-gap: var(--twd-space-2);--twd-control-gap: var(--twd-space-3);--twd-border-width: 1px;--twd-border-width-container: var(--twd-border-width);--twd-shadow-sm: 0 1px 2px rgb(0 0 0 / .06);--twd-shadow-md: 0 4px 12px rgb(0 0 0 / .08);--twd-shadow-lg: 0 12px 32px rgb(0 0 0 / .12);--twd-button-bg: var(--twd-primary);--twd-button-fg: var(--twd-on-primary);--twd-button-border: transparent;--twd-button-hover: var(--twd-primary-hover);--twd-card-bg: var(--twd-surface);--twd-card-border: var(--twd-border);--twd-card-shadow: var(--twd-shadow-sm)}', Pa = [...qn.matchAll(/(--twd-[\w-]+):\s*([^;]*var\(--twd-[^;]*);/g)].map((e) => [e[1], e[2].trim()]);
98
+ function Oa(e) {
99
99
  const t = document.documentElement, n = document.createElement("div");
100
100
  n.hidden = !0, t.appendChild(n);
101
101
  const a = getComputedStyle(t), o = getComputedStyle(n), r = [];
102
- return Oa.forEach(([s, i]) => {
102
+ return Pa.forEach(([s, i]) => {
103
103
  const l = e[s];
104
104
  if (l != null) {
105
105
  String(l).includes("var(") && r.push([s, l]);
@@ -108,12 +108,12 @@ function Pa(e) {
108
108
  n.style.setProperty("--twd-probe", i), o.getPropertyValue("--twd-probe").trim() === a.getPropertyValue(s).trim() && r.push([s, i]);
109
109
  }), n.remove(), r;
110
110
  }
111
- const _n = [];
112
- let Tt = [], zt = {}, R = null, fe = !1, Kn = {};
113
- function Fa(e) {
114
- typeof e == "function" && _n.push(e);
111
+ const Hn = [];
112
+ let Tt = [], zt = {}, R = null, fe = !1, _n = {};
113
+ function ja(e) {
114
+ typeof e == "function" && Hn.push(e);
115
115
  }
116
- const bn = (e) => Object.assign({}, ..._n.map((t) => t(e) || {})), Lt = (e) => /^(\.[\w-]+|\[data-twd="[^"]+"\])$/.test(e), ja = (e) => {
116
+ const mn = (e) => Object.assign({}, ...Hn.map((t) => t(e) || {})), Lt = (e) => /^(\.[\w-]+|\[data-twd="[^"]+"\])$/.test(e), Fa = (e) => {
117
117
  try {
118
118
  return document.querySelector(e), !0;
119
119
  } catch {
@@ -123,15 +123,15 @@ const bn = (e) => Object.assign({}, ..._n.map((t) => t(e) || {})), Lt = (e) => /
123
123
  function Na() {
124
124
  return (!R || !R.isConnected) && (R = document.createElement("style"), R.id = "twiddle-scoped", document.head.appendChild(R)), R;
125
125
  }
126
- function Wn() {
126
+ function Kn() {
127
127
  const e = document.documentElement;
128
128
  Tt.forEach((t) => e.style.removeProperty(t)), Tt = [], zt = {};
129
129
  }
130
130
  function At(e) {
131
- if (Kn = e, fe) return;
131
+ if (_n = e, fe) return;
132
132
  const t = document.documentElement;
133
- Wn();
134
- const n = bn(e), a = e.scopes ? Pa(n) : [], o = Object.entries(e.scopes || {}).filter(([s]) => ja(s)).sort(([s], [i]) => Lt(i) - Lt(s)).map(([s, i]) => [s, bn(i)]);
133
+ Kn();
134
+ const n = mn(e), a = e.scopes ? Oa(n) : [], o = Object.entries(e.scopes || {}).filter(([s]) => Fa(s)).sort(([s], [i]) => Lt(i) - Lt(s)).map(([s, i]) => [s, mn(i)]);
135
135
  Object.entries(n).forEach(([s, i]) => t.style.setProperty(s, i)), Tt = Object.keys(n), zt = n;
136
136
  const r = o.filter(([, s]) => Object.keys(s).length).map(([s, i]) => `${s} {
137
137
  ${[
@@ -144,7 +144,7 @@ ${[
144
144
  `);
145
145
  (r || R) && (Na().textContent = r);
146
146
  }
147
- function Gn(e) {
147
+ function Wn(e) {
148
148
  const t = document.documentElement, n = fe, a = { ...zt };
149
149
  Object.keys(a).forEach((o) => t.style.removeProperty(o)), R && (R.disabled = !0);
150
150
  try {
@@ -154,16 +154,16 @@ function Gn(e) {
154
154
  }
155
155
  }
156
156
  function Ra(e, t = document.documentElement) {
157
- return Gn(() => {
157
+ return Wn(() => {
158
158
  const n = getComputedStyle(t);
159
159
  return Object.fromEntries(e.map((a) => [a, n.getPropertyValue(a).trim()]));
160
160
  });
161
161
  }
162
162
  function za() {
163
- fe || (Wn(), R && (R.disabled = !0), fe = !0);
163
+ fe || (Kn(), R && (R.disabled = !0), fe = !0);
164
164
  }
165
165
  function Ia() {
166
- fe && (fe = !1, R && (R.disabled = !1), At(Kn));
166
+ fe && (fe = !1, R && (R.disabled = !1), At(_n));
167
167
  }
168
168
  const Da = `
169
169
  :host { all: initial; } /* block fonts/colours inherited from the page */
@@ -909,32 +909,35 @@ const Da = `
909
909
  .sketch i { height: 9px; border-radius: 2px; background: var(--p-line); }
910
910
  .sketch i:first-child { background: var(--p-muted); }
911
911
  .shape { display: block; }
912
- .shape-button { width: 52px; height: 24px; background: #4f46e5; }
913
- .shape-button.size-small { width: 38px; height: 16px; border-radius: 4px; }
914
- .shape-button.size-medium { width: 52px; height: 22px; border-radius: 5px; }
915
- .shape-button.size-large { width: 66px; height: 28px; border-radius: 6px; }
912
+ /* Live previews: --pv-* come from the page (panel.js syncPreviews); fallbacks = defaults. */
913
+ .shape-button { width: 52px; height: 24px; background: var(--pv-primary, #4f46e5); }
914
+ .shape-button.size-small { width: 38px; height: 16px; border-radius: min(var(--pv-radius-control, 8px), 8px); }
915
+ .shape-button.size-medium { width: 52px; height: 22px; border-radius: min(var(--pv-radius-control, 8px), 11px); }
916
+ .shape-button.size-large { width: 66px; height: 28px; border-radius: min(var(--pv-radius-control, 8px), 14px); }
916
917
  .shape-card { width: 52px; height: 38px; background: var(--p-bg); border: 1px solid var(--p-muted); }
917
- .shape-card.border-none { border-color: transparent; background: var(--p-hover); border-radius: 6px; }
918
- .shape-card.border-thin { border-radius: 6px; }
919
- .shape-card.border-thick { border-width: 2px; border-radius: 6px; }
920
- /* Style tiles (v0.4): Figma "Shape — with styles" 257:711 */
921
- .shape-button[class*="style-"] { width: 52px; height: 22px; border-radius: 5px; display: grid; place-items: center; border: 1.5px solid transparent; }
922
- .shape-button[class*="style-"]::after { content: ""; width: 22px; height: 3px; border-radius: 2px; background: #a5b4fc; }
923
- .shape-button.style-solid::after { background: #fff; }
924
- .shape-button.style-soft { background: rgb(79 70 229 / 0.32); }
925
- .shape-button.style-outline { background: transparent; border-color: #818cf8; }
918
+ .shape-card[class*="border-"] { border-radius: min(calc(var(--pv-radius-container, 12px) / 2), 10px); }
919
+ .shape-card.border-none { border-color: transparent; background: var(--p-hover); }
920
+ .shape-card.border-thick { border-width: 2px; }
921
+ /* Button style tiles (Figma 281:1158) */
922
+ .shape-button[class*="style-"] { width: 52px; height: 22px; border-radius: min(var(--pv-radius-control, 8px), 11px); display: grid; place-items: center; border: 1.5px solid transparent; }
923
+ .shape-button[class*="style-"]::after { content: ""; width: 22px; height: 3px; border-radius: 2px; background: color-mix(in srgb, var(--pv-primary, #4f46e5) 55%, white); }
924
+ .shape-button.style-solid::after { background: var(--pv-on-primary, #fff); }
925
+ .shape-button.style-soft { background: color-mix(in srgb, var(--pv-primary, #4f46e5) 32%, transparent); }
926
+ .shape-button.style-outline { background: transparent; border-color: color-mix(in srgb, var(--pv-primary, #4f46e5) 70%, white); }
926
927
  .shape-button.style-ghost { background: transparent; }
927
- .shape-card[class*="style-"] { border-radius: 6px; }
928
- .shape-card.style-filled { background: var(--p-hover); border-color: var(--p-line); }
929
- .shape-card.style-outlined { background: transparent; border-color: var(--p-muted); }
930
- .shape-card.style-elevated { background: color-mix(in oklch, var(--p-hover) 88%, white); border-color: transparent; box-shadow: 0 5px 12px rgb(0 0 0 / 0.55); }
931
- /* Cards › Fill tiles */
932
- .shape-card[class*="fill-"] { border-radius: 6px; border-color: var(--p-muted); }
933
- .shape-card.fill-none { background: transparent; border-style: dashed; }
934
- .shape-card.fill-surface { background: var(--p-hover); }
935
- .shape-card.fill-raised { background: color-mix(in oklch, var(--p-hover) 80%, white); }
936
- .shape-card.fill-tinted { background: rgb(79 70 229 / 0.28); }
937
- .shape-card.style-tinted { background: rgb(79 70 229 / 0.2); border-color: rgb(129 140 248 / 0.5); }
928
+ /* Card style tiles: a mini card with content lines on a page backdrop (Figma 281:1421) */
929
+ .mini { display: grid; place-items: center; width: 60px; height: 42px; border-radius: 6px; background: var(--p-hover); }
930
+ .mini-card {
931
+ width: 44px; height: 28px; padding: 0 7px; box-sizing: border-box;
932
+ display: grid; align-content: center; gap: 4px;
933
+ border: 1px solid transparent; border-radius: min(calc(var(--pv-radius-container, 12px) / 2), 10px);
934
+ }
935
+ .mini-card i { display: block; width: 22px; height: 3px; border-radius: 2px; background: #a1a1aa; }
936
+ .mini-card i + i { width: 30px; background: #71717a; }
937
+ .mini-card.style-filled { background: #3f3f46; border-color: #52525b; }
938
+ .mini-card.style-outlined { background: transparent; border-color: #a1a1aa; }
939
+ .mini-card.style-elevated { background: #52525b; box-shadow: 0 4px 8px rgb(0 0 0 / 0.7); }
940
+ .mini-card.style-tinted { background: color-mix(in srgb, var(--pv-primary, #6366f1) 30%, transparent); border-color: color-mix(in srgb, var(--pv-primary, #6366f1) 70%, white); }
938
941
  .shape-card[class*="shadow-"] { width: 44px; height: 32px; border-radius: 6px; border-color: var(--p-line); margin: 4px 0 6px; }
939
942
  .shape-card.shadow-bold { border-color: var(--p-fg); }
940
943
 
@@ -985,91 +988,91 @@ const Da = `
985
988
  .summary-swatch { width: 14px; height: 14px; border-radius: 4px; flex: none; }
986
989
  .summary-swatch[hidden] { display: none; }
987
990
  .summary-row .chev { display: grid; color: var(--p-muted); }
988
- `, L = (e, t, n) => `<svg width="${e}" height="${e}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="${t}" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${n}</svg>`, A = {
989
- dial: L(20, 1.8, '<circle cx="12" cy="12" r="8"/><path d="M12 12l4-4"/><path d="M12 2v2M12 20v2M2 12h2M20 12h2"/>'),
990
- link: L(15, 2, '<path d="M10 13a5 5 0 0 0 7.07 0l3-3a5 5 0 0 0-7.07-7.07l-1 1"/><path d="M14 11a5 5 0 0 0-7.07 0l-3 3a5 5 0 0 0 7.07 7.07l1-1"/>'),
991
- reset: L(15, 2, '<path d="M3 12a9 9 0 1 0 3-6.7"/><path d="M3 3v6h6"/>'),
992
- close: L(15, 2, '<path d="M18 6L6 18M6 6l12 12"/>'),
993
- chevron: L(12, 2.4, '<path d="M9 6l6 6-6 6"/>'),
991
+ `, A = (e, t, n) => `<svg width="${e}" height="${e}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="${t}" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${n}</svg>`, P = {
992
+ dial: A(20, 1.8, '<circle cx="12" cy="12" r="8"/><path d="M12 12l4-4"/><path d="M12 2v2M12 20v2M2 12h2M20 12h2"/>'),
993
+ link: A(15, 2, '<path d="M10 13a5 5 0 0 0 7.07 0l3-3a5 5 0 0 0-7.07-7.07l-1 1"/><path d="M14 11a5 5 0 0 0-7.07 0l-3 3a5 5 0 0 0 7.07 7.07l1-1"/>'),
994
+ reset: A(15, 2, '<path d="M3 12a9 9 0 1 0 3-6.7"/><path d="M3 3v6h6"/>'),
995
+ close: A(15, 2, '<path d="M18 6L6 18M6 6l12 12"/>'),
996
+ chevron: A(12, 2.4, '<path d="M9 6l6 6-6 6"/>'),
994
997
  // Proposals: not yet in the Figma Icon/* set.
995
998
  // Figma: Icon/Cursor (39:313), the header's Pick button.
996
- pick: L(15, 2, '<path d="M17.202 10.5576C17.6738 10.3035 17.9098 10.1765 17.9694 10.0236C18.0212 9.89097 18.0066 9.74158 17.9301 9.6215C17.8419 9.48312 17.5858 9.40424 17.0737 9.24647L7.05204 6.15943C6.63366 6.03055 6.42447 5.96611 6.28318 6.01796C6.16011 6.06312 6.06312 6.16011 6.01796 6.28317C5.96611 6.42446 6.03055 6.63365 6.15943 7.05204L9.24645 17.0737C9.40422 17.5858 9.4831 17.8419 9.62147 17.9301C9.74156 18.0066 9.89095 18.0212 10.0236 17.9694C10.1764 17.9098 10.3035 17.6738 10.5576 17.202L12.7816 13.0717C12.8193 13.0016 12.8382 12.9666 12.8625 12.9359C12.884 12.9086 12.9086 12.884 12.9359 12.8624C12.9666 12.8382 13.0016 12.8193 13.0717 12.7816L17.202 10.5576Z"/>'),
997
- compare: L(15, 2, '<circle cx="12" cy="12" r="9"/><path d="M12 3v18" /><path d="M12 3a9 9 0 0 0 0 18z" fill="currentColor" stroke="none"/>'),
998
- undo: L(15, 2, '<path d="M9 14L4 9l5-5"/><path d="M4 9h11a5 5 0 0 1 0 10h-3"/>'),
999
- redo: L(15, 2, '<path d="M15 14l5-5-5-5"/><path d="M20 9H9a5 5 0 0 0 0 10h3"/>'),
1000
- back: L(15, 2, '<path d="M15 18l-6-6 6-6"/>'),
1001
- down: L(12, 2.4, '<path d="M6 9l6 6 6-6"/>'),
1002
- minimise: L(15, 2, '<path d="M6 9l6 6 6-6"/>'),
999
+ pick: A(15, 2, '<path d="M17.202 10.5576C17.6738 10.3035 17.9098 10.1765 17.9694 10.0236C18.0212 9.89097 18.0066 9.74158 17.9301 9.6215C17.8419 9.48312 17.5858 9.40424 17.0737 9.24647L7.05204 6.15943C6.63366 6.03055 6.42447 5.96611 6.28318 6.01796C6.16011 6.06312 6.06312 6.16011 6.01796 6.28317C5.96611 6.42446 6.03055 6.63365 6.15943 7.05204L9.24645 17.0737C9.40422 17.5858 9.4831 17.8419 9.62147 17.9301C9.74156 18.0066 9.89095 18.0212 10.0236 17.9694C10.1764 17.9098 10.3035 17.6738 10.5576 17.202L12.7816 13.0717C12.8193 13.0016 12.8382 12.9666 12.8625 12.9359C12.884 12.9086 12.9086 12.884 12.9359 12.8624C12.9666 12.8382 13.0016 12.8193 13.0717 12.7816L17.202 10.5576Z"/>'),
1000
+ compare: A(15, 2, '<circle cx="12" cy="12" r="9"/><path d="M12 3v18" /><path d="M12 3a9 9 0 0 0 0 18z" fill="currentColor" stroke="none"/>'),
1001
+ undo: A(15, 2, '<path d="M9 14L4 9l5-5"/><path d="M4 9h11a5 5 0 0 1 0 10h-3"/>'),
1002
+ redo: A(15, 2, '<path d="M15 14l5-5-5-5"/><path d="M20 9H9a5 5 0 0 0 0 10h3"/>'),
1003
+ back: A(15, 2, '<path d="M15 18l-6-6 6-6"/>'),
1004
+ down: A(12, 2.4, '<path d="M6 9l6 6 6-6"/>'),
1005
+ minimise: A(15, 2, '<path d="M6 9l6 6 6-6"/>'),
1003
1006
  // chevron at the end of the tab bar; flips to ˄ when minimised (Ravi, 2026-10-16)
1004
- changes: L(15, 2, '<path d="M9 6h11M9 12h11M9 18h11"/><path d="M4.5 6h.01M4.5 12h.01M4.5 18h.01"/>'),
1005
- copy: L(13, 2, '<rect x="9" y="9" width="11" height="11" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/>'),
1006
- warn: L(13, 2, '<path d="M12 3l9.5 17h-19z"/><path d="M12 10v4M12 17.5v.01"/>'),
1007
+ changes: A(15, 2, '<path d="M9 6h11M9 12h11M9 18h11"/><path d="M4.5 6h.01M4.5 12h.01M4.5 18h.01"/>'),
1008
+ copy: A(13, 2, '<rect x="9" y="9" width="11" height="11" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/>'),
1009
+ warn: A(13, 2, '<path d="M12 3l9.5 17h-19z"/><path d="M12 10v4M12 17.5v.01"/>'),
1007
1010
  // Launcher: the Panel product mark (Twiddle brand; Figma Logo page › Panel mark; also site/favicon.svg).
1008
1011
  // A switch knocked out of a disc; knob + two-dot trail. Classes let the Toggle animation move them.
1009
1012
  panelMark: '<svg class="mark" width="44" height="44" viewBox="0 0 120 120" aria-hidden="true"><path class="mark-disc" fill-rule="evenodd" clip-rule="evenodd" d="M60 120C93.1371 120 120 93.1371 120 60C120 26.8629 93.1371 0 60 0C26.8629 0 0 26.8629 0 60C0 93.1371 26.8629 120 60 120ZM86 76C86 90.3594 74.3594 102 60 102C45.6406 102 34 90.3594 34 76V44C34 29.6406 45.6406 18 60 18C74.3594 18 86 29.6406 86 44V76ZM60 22C72.1503 22 82 31.8497 82 44V76C82 88.1503 72.1503 98 60 98C47.8497 98 38 88.1503 38 76V44C38 31.8497 47.8497 22 60 22Z"/><circle class="mark-t2" cx="60" cy="80.46" r="4.28"/><circle class="mark-t1" cx="60" cy="66.04" r="7.14"/><circle class="mark-knob" cx="60" cy="44" r="11.9"/></svg>',
1010
1013
  // Tab bar (Figma: Panel — tabbed layout (proposal), Icon/Tab * components)
1011
- tabOverview: L(18, 1.8, '<circle cx="12" cy="12" r="8"/><path d="M12 12l4-4"/><path d="M12 2v2M12 20v2M2 12h2M20 12h2"/>'),
1012
- tabColour: L(18, 2, '<path d="M12 3c-3.5 4.5-6 7.8-6 11a6 6 0 0 0 12 0c0-3.2-2.5-6.5-6-11z"/>'),
1013
- tabType: L(18, 2, '<path d="M5 7V5h14v2"/><path d="M12 5v14"/><path d="M9 19h6"/>'),
1014
- tabSpacing: L(18, 2, '<path d="M4 5v14M20 5v14"/><path d="M8 12h8"/><path d="M10 9l-3 3 3 3M14 9l3 3-3 3"/>'),
1015
- tabShape: L(18, 2, '<path d="M20 4h-9a7 7 0 0 0-7 7v9"/><path d="M20 10h-5a5 5 0 0 0-5 5v5"/>'),
1016
- tabShadows: L(18, 2, '<rect x="4" y="4" width="12" height="12" rx="2"/><path d="M20 8v10a2 2 0 0 1-2 2H8"/>'),
1017
- sliders: L(15, 2, '<path d="M4 7h10M18 7h2M4 17h4M12 17h8"/><circle cx="16" cy="7" r="2"/><circle cx="10" cy="17" r="2"/>')
1014
+ tabOverview: A(18, 1.8, '<circle cx="12" cy="12" r="8"/><path d="M12 12l4-4"/><path d="M12 2v2M12 20v2M2 12h2M20 12h2"/>'),
1015
+ tabColour: A(18, 2, '<path d="M12 3c-3.5 4.5-6 7.8-6 11a6 6 0 0 0 12 0c0-3.2-2.5-6.5-6-11z"/>'),
1016
+ tabType: A(18, 2, '<path d="M5 7V5h14v2"/><path d="M12 5v14"/><path d="M9 19h6"/>'),
1017
+ tabSpacing: A(18, 2, '<path d="M4 5v14M20 5v14"/><path d="M8 12h8"/><path d="M10 9l-3 3 3 3M14 9l3 3-3 3"/>'),
1018
+ tabShape: A(18, 2, '<path d="M20 4h-9a7 7 0 0 0-7 7v9"/><path d="M20 10h-5a5 5 0 0 0-5 5v5"/>'),
1019
+ tabShadows: A(18, 2, '<rect x="4" y="4" width="12" height="12" rx="2"/><path d="M20 8v10a2 2 0 0 1-2 2H8"/>'),
1020
+ sliders: A(15, 2, '<path d="M4 7h10M18 7h2M4 17h4M12 17h8"/><circle cx="16" cy="7" r="2"/><circle cx="10" cy="17" r="2"/>')
1018
1021
  // Figma: Icon/Sliders (proposal)
1019
- }, Yn = "twiddle:";
1022
+ }, Gn = "twiddle:";
1020
1023
  function ne(e) {
1021
1024
  try {
1022
- return localStorage.getItem(Yn + e);
1025
+ return localStorage.getItem(Gn + e);
1023
1026
  } catch {
1024
1027
  return null;
1025
1028
  }
1026
1029
  }
1027
1030
  function ce(e, t) {
1028
1031
  try {
1029
- localStorage.setItem(Yn + e, t);
1032
+ localStorage.setItem(Gn + e, t);
1030
1033
  } catch {
1031
1034
  }
1032
1035
  }
1033
- const pe = 44, de = 8, Ba = 4, Xn = { corner: "br", x: 16, y: 16 };
1036
+ const pe = 44, de = 8, Ba = 4, Yn = { corner: "br", x: 16, y: 16 };
1034
1037
  function Ua() {
1035
1038
  try {
1036
1039
  const e = JSON.parse(ne("position"));
1037
1040
  if (e && /^[tb][lr]$/.test(e.corner) && isFinite(e.x) && isFinite(e.y)) return e;
1038
1041
  } catch {
1039
1042
  }
1040
- return { ...Xn };
1043
+ return { ...Yn };
1041
1044
  }
1042
- function mn(e) {
1045
+ function bn(e) {
1043
1046
  const t = Math.max(de, innerWidth - pe - de), n = Math.max(de, innerHeight - pe - de);
1044
1047
  return { corner: e.corner, x: Math.round(Math.min(Math.max(e.x, de), t)), y: Math.round(Math.min(Math.max(e.y, de), n)) };
1045
1048
  }
1046
1049
  function Va({ wrapEl: e, launcherEl: t }) {
1047
1050
  let n = Ua();
1048
1051
  function a() {
1049
- const d = mn(n), h = d.corner[1] === "l", u = d.corner[0] === "t";
1052
+ const d = bn(n), p = d.corner[1] === "l", f = d.corner[0] === "t";
1050
1053
  Object.assign(e.style, {
1051
- left: h ? `${d.x}px` : "auto",
1052
- right: h ? "auto" : `${d.x}px`,
1053
- top: u ? `${d.y}px` : "auto",
1054
- bottom: u ? "auto" : `${d.y}px`
1055
- }), e.style.setProperty("--off-x", `${d.x}px`), e.style.setProperty("--off-y", `${d.y}px`), e.classList.toggle("at-left", h), e.classList.toggle("at-top", u);
1054
+ left: p ? `${d.x}px` : "auto",
1055
+ right: p ? "auto" : `${d.x}px`,
1056
+ top: f ? `${d.y}px` : "auto",
1057
+ bottom: f ? "auto" : `${d.y}px`
1058
+ }), e.style.setProperty("--off-x", `${d.x}px`), e.style.setProperty("--off-y", `${d.y}px`), e.classList.toggle("at-left", p), e.classList.toggle("at-top", f);
1056
1059
  }
1057
- function o(d, h = !0) {
1058
- n = mn(d), a(), h && ce("position", JSON.stringify(n));
1060
+ function o(d, p = !0) {
1061
+ n = bn(d), a(), p && ce("position", JSON.stringify(n));
1059
1062
  }
1060
- function r(d, h) {
1061
- const u = d + pe / 2 < innerWidth / 2, w = h + pe / 2 < innerHeight / 2, p = !w && e.classList.contains("is-open") ? 10 : 0;
1063
+ function r(d, p) {
1064
+ const f = d + pe / 2 < innerWidth / 2, v = p + pe / 2 < innerHeight / 2, u = !v && e.classList.contains("is-open") ? 10 : 0;
1062
1065
  return {
1063
- corner: (w ? "t" : "b") + (u ? "l" : "r"),
1064
- x: u ? d : innerWidth - d - pe,
1065
- y: w ? h : innerHeight - h - pe - p
1066
+ corner: (v ? "t" : "b") + (f ? "l" : "r"),
1067
+ x: f ? d : innerWidth - d - pe,
1068
+ y: v ? p : innerHeight - p - pe - u
1066
1069
  };
1067
1070
  }
1068
1071
  let s = null, i = !1;
1069
1072
  t.addEventListener("pointerdown", (d) => {
1070
1073
  if (d.button !== 0) return;
1071
- const h = t.getBoundingClientRect();
1072
- s = { id: d.pointerId, sx: d.clientX, sy: d.clientY, dx: d.clientX - h.left, dy: d.clientY - h.top, moving: !1 };
1074
+ const p = t.getBoundingClientRect();
1075
+ s = { id: d.pointerId, sx: d.clientX, sy: d.clientY, dx: d.clientX - p.left, dy: d.clientY - p.top, moving: !1 };
1073
1076
  }), t.addEventListener("pointermove", (d) => {
1074
1077
  if (!(!s || d.pointerId !== s.id)) {
1075
1078
  if (!s.moving) {
@@ -1083,11 +1086,11 @@ function Va({ wrapEl: e, launcherEl: t }) {
1083
1086
  !s || d.pointerId !== s.id || (s.moving && (i = !0, e.classList.remove("dragging"), o(n)), s = null);
1084
1087
  };
1085
1088
  return t.addEventListener("pointerup", l), t.addEventListener("pointercancel", l), t.addEventListener("keydown", (d) => {
1086
- const h = { ArrowLeft: [-1, 0], ArrowRight: [1, 0], ArrowUp: [0, -1], ArrowDown: [0, 1] }[d.key];
1087
- if (!h || d.altKey || d.metaKey || d.ctrlKey) return;
1089
+ const p = { ArrowLeft: [-1, 0], ArrowRight: [1, 0], ArrowUp: [0, -1], ArrowDown: [0, 1] }[d.key];
1090
+ if (!p || d.altKey || d.metaKey || d.ctrlKey) return;
1088
1091
  d.preventDefault();
1089
- const u = d.shiftKey ? 10 : 1, w = n.corner[1] === "l" ? 1 : -1, p = n.corner[0] === "t" ? 1 : -1;
1090
- o({ corner: n.corner, x: n.x + h[0] * u * w, y: n.y + h[1] * u * p });
1092
+ const f = d.shiftKey ? 10 : 1, v = n.corner[1] === "l" ? 1 : -1, u = n.corner[0] === "t" ? 1 : -1;
1093
+ o({ corner: n.corner, x: n.x + p[0] * f * v, y: n.y + p[1] * f * u });
1091
1094
  }), window.addEventListener("resize", a), a(), {
1092
1095
  /** Call from the launcher's click handler: true = ignore this click (it ended a drag). */
1093
1096
  consumeClick() {
@@ -1095,7 +1098,7 @@ function Va({ wrapEl: e, launcherEl: t }) {
1095
1098
  return i = !1, d;
1096
1099
  },
1097
1100
  reset() {
1098
- o({ ...Xn });
1101
+ o({ ...Yn });
1099
1102
  }
1100
1103
  };
1101
1104
  }
@@ -1109,28 +1112,28 @@ function ge({ label: e, options: t, onSelect: n }) {
1109
1112
  a.append(...o);
1110
1113
  let r = null;
1111
1114
  function s(l) {
1112
- r = l, o.forEach((h) => h.setAttribute("aria-checked", String(h.dataset.value === l)));
1113
- const d = Math.max(0, o.findIndex((h) => h.dataset.value === l));
1114
- o.forEach((h, u) => {
1115
- h.tabIndex = u === d ? 0 : -1;
1115
+ r = l, o.forEach((p) => p.setAttribute("aria-checked", String(p.dataset.value === l)));
1116
+ const d = Math.max(0, o.findIndex((p) => p.dataset.value === l));
1117
+ o.forEach((p, f) => {
1118
+ p.tabIndex = f === d ? 0 : -1;
1116
1119
  });
1117
1120
  }
1118
1121
  function i(l, d) {
1119
- l !== r && (s(l), n(l)), d && o.find((h) => h.dataset.value === l).focus();
1122
+ l !== r && (s(l), n(l)), d && o.find((p) => p.dataset.value === l).focus();
1120
1123
  }
1121
1124
  return a.addEventListener("keydown", (l) => {
1122
1125
  const d = o.indexOf(l.target);
1123
1126
  if (d < 0) return;
1124
- const h = { ArrowRight: 1, ArrowDown: 1, ArrowLeft: -1, ArrowUp: -1 }[l.key];
1125
- let u;
1126
- if (h) u = (d + h + o.length) % o.length;
1127
- else if (l.key === "Home") u = 0;
1128
- else if (l.key === "End") u = o.length - 1;
1127
+ const p = { ArrowRight: 1, ArrowDown: 1, ArrowLeft: -1, ArrowUp: -1 }[l.key];
1128
+ let f;
1129
+ if (p) f = (d + p + o.length) % o.length;
1130
+ else if (l.key === "Home") f = 0;
1131
+ else if (l.key === "End") f = o.length - 1;
1129
1132
  else return;
1130
- l.preventDefault(), i(o[u].dataset.value, !0);
1133
+ l.preventDefault(), i(o[f].dataset.value, !0);
1131
1134
  }), s(null), { el: a, setValue: s };
1132
1135
  }
1133
- const Zn = /var\(\s*(--twd-[\w-]+)/g, qa = /::?[\w-]+(\([^)]*\))?/g;
1136
+ const Xn = /var\(\s*(--twd-[\w-]+)/g, qa = /::?[\w-]+(\([^)]*\))?/g;
1134
1137
  function* Qe(e) {
1135
1138
  for (const t of e)
1136
1139
  t.selectorText != null && (yield t), t.cssRules && (yield* Qe(t.cssRules));
@@ -1146,7 +1149,7 @@ function Ha() {
1146
1149
  continue;
1147
1150
  }
1148
1151
  for (const a of Qe(n)) {
1149
- const o = [...a.style.cssText.matchAll(Zn)].map((r) => r[1]);
1152
+ const o = [...a.style.cssText.matchAll(Xn)].map((r) => r[1]);
1150
1153
  o.length && e.push({ selectors: a.selectorText.split(","), vars: o });
1151
1154
  }
1152
1155
  }
@@ -1160,33 +1163,33 @@ function _a(e, t) {
1160
1163
  return !1;
1161
1164
  }
1162
1165
  }
1163
- function Jn(e) {
1166
+ function Zn(e) {
1164
1167
  const t = /* @__PURE__ */ new Set(), n = [];
1165
1168
  return Ha().forEach(({ selectors: a, vars: o }) => {
1166
1169
  const r = a.find((s) => _a(e, s));
1167
1170
  r && (o.forEach((s) => t.add(s)), n.push(r.trim()));
1168
- }), [...(e.getAttribute("style") || "").matchAll(Zn)].forEach((a) => t.add(a[1])), { names: t, selectors: n };
1171
+ }), [...(e.getAttribute("style") || "").matchAll(Xn)].forEach((a) => t.add(a[1])), { names: t, selectors: n };
1169
1172
  }
1170
- const Ot = (e) => window.CSS && CSS.escape ? CSS.escape(e) : e;
1173
+ const Pt = (e) => window.CSS && CSS.escape ? CSS.escape(e) : e;
1171
1174
  function Ka(e) {
1172
1175
  const t = [];
1173
1176
  let n = e;
1174
1177
  for (; n && n.nodeType === 1 && n !== document.body && n !== document.documentElement; ) {
1175
- if (n.id && document.querySelectorAll(`#${Ot(n.id)}`).length === 1)
1176
- return t.unshift(`#${Ot(n.id)}`), t.join(" > ");
1178
+ if (n.id && document.querySelectorAll(`#${Pt(n.id)}`).length === 1)
1179
+ return t.unshift(`#${Pt(n.id)}`), t.join(" > ");
1177
1180
  const a = n.localName, o = [...n.parentElement.children].filter((r) => r.localName === a);
1178
1181
  t.unshift(o.length > 1 ? `${a}:nth-of-type(${o.indexOf(n) + 1})` : a), n = n.parentElement;
1179
1182
  }
1180
1183
  return ["body", ...t].join(" > ");
1181
1184
  }
1182
- function Wa(e, t = Jn(e).selectors) {
1185
+ function Wa(e, t = Zn(e).selectors) {
1183
1186
  const n = e.getAttribute("data-twd");
1184
1187
  if (n) return `[data-twd="${n.replace(/"/g, "")}"]`;
1185
1188
  const a = [...e.classList], r = a.find((s) => t.some((i) => new RegExp(`\\.${s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![\\w-])`).test(i))) || a[0];
1186
- return r ? `.${Ot(r)}` : null;
1189
+ return r ? `.${Pt(r)}` : null;
1187
1190
  }
1188
1191
  function Ga(e) {
1189
- const t = Jn(e), n = Wa(e, t.selectors), a = (e.getAttribute("aria-label") || e.placeholder || e.textContent || "").trim().replace(/\s+/g, " ");
1192
+ const t = Zn(e), n = Wa(e, t.selectors), a = (e.getAttribute("aria-label") || e.placeholder || e.textContent || "").trim().replace(/\s+/g, " ");
1190
1193
  return {
1191
1194
  el: e,
1192
1195
  tag: e.localName,
@@ -1198,9 +1201,9 @@ function Ga(e) {
1198
1201
  classCount: n ? document.querySelectorAll(n).length : 0
1199
1202
  };
1200
1203
  }
1201
- const Pt = (e) => e.localName + [...e.classList].map((t) => `.${t}`).join(""), Ya = { radius: "px", intensity: "%", base: "px" }, Qn = (e) => e.charAt(0).toUpperCase() + e.slice(1), Xa = (e, t) => typeof t == "number" || /^\d+$/.test(t) ? `${t}${Ya[e] || ""}` : Qn(String(t));
1204
+ const Ot = (e) => e.localName + [...e.classList].map((t) => `.${t}`).join(""), Ya = { radius: "px", intensity: "%", base: "px" }, Jn = (e) => e.charAt(0).toUpperCase() + e.slice(1), Xa = (e, t) => typeof t == "number" || /^\d+$/.test(t) ? `${t}${Ya[e] || ""}` : Jn(String(t));
1202
1205
  function xn(e, t, n) {
1203
- const a = Gn(() => e.tokens({ [e.id]: t }) || {}), o = Object.keys(a);
1206
+ const a = Wn(() => e.tokens({ [e.id]: t }) || {}), o = Object.keys(a);
1204
1207
  let r = {};
1205
1208
  if (o.length) {
1206
1209
  const s = n.selector ? document.querySelector(n.selector) : void 0;
@@ -1210,7 +1213,7 @@ function xn(e, t, n) {
1210
1213
  ...n,
1211
1214
  sectionId: e.id,
1212
1215
  title: e.title,
1213
- settings: Object.entries(t).map(([s, i]) => ({ key: s, label: Qn(s), value: Xa(s, i), ...e.describe?.(s, i) || {} })),
1216
+ settings: Object.entries(t).map(([s, i]) => ({ key: s, label: Jn(s), value: Xa(s, i), ...e.describe?.(s, i) || {} })),
1214
1217
  tokens: o.map((s) => ({ name: s, from: r[s] || "", to: a[s] }))
1215
1218
  };
1216
1219
  }
@@ -1229,7 +1232,7 @@ function Za(e) {
1229
1232
  const t = (o) => Object.values(o || {}).reduce((r, s) => r + Object.keys(s || {}).length, 0), { scopes: n, ...a } = e;
1230
1233
  return t(a) + Object.values(n || {}).reduce((o, r) => o + t(r), 0);
1231
1234
  }
1232
- const ue = (e) => `\`${e}\``, dt = (e) => e.map((t) => ` - ${ue(t.name)}: ${t.from ? `${ue(t.from)} → ` : ""}${ue(t.to)}`), ct = (e) => `${e.title} › ${e.settings.map((t) => `${t.label}: ${t.value}`).join(", ")}`;
1235
+ const ue = (e) => `\`${e}\``, ct = (e) => e.map((t) => ` - ${ue(t.name)}: ${t.from ? `${ue(t.from)} → ` : ""}${ue(t.to)}`), pt = (e) => `${e.title} › ${e.settings.map((t) => `${t.label}: ${t.value}`).join(", ")}`;
1233
1236
  function Ja(e) {
1234
1237
  let t = null;
1235
1238
  try {
@@ -1238,7 +1241,7 @@ function Ja(e) {
1238
1241
  }
1239
1242
  if (!t) return "not found on the current page";
1240
1243
  const n = (t.getAttribute("aria-label") || t.placeholder || t.textContent || "").trim().replace(/\s+/g, " ").slice(0, 60);
1241
- return `${ue(Pt(t))}${n ? ` with text “${n}”` : ""}`;
1244
+ return `${ue(Ot(t))}${n ? ` with text “${n}”` : ""}`;
1242
1245
  }
1243
1246
  function vn(e, t) {
1244
1247
  const n = /* @__PURE__ */ new Map();
@@ -1262,14 +1265,14 @@ function Qa(e, { link: t = location.href, warnings: n = [] } = {}) {
1262
1265
  "",
1263
1266
  "Update the default value of each token where it is defined (usually a `:root` rule or a `tokens.css` / `twiddle-tokens.css` file). Change the definition, not the places that use it.",
1264
1267
  ""
1265
- ), a.forEach((i) => s.push(`- **${ct(i)}**`, ...dt(i.tokens)))), o.length && (s.push(
1268
+ ), a.forEach((i) => s.push(`- **${pt(i)}**`, ...ct(i.tokens)))), o.length && (s.push(
1266
1269
  "",
1267
1270
  `## ${a.length ? 2 : 1}. Component-wide changes`,
1268
1271
  "",
1269
1272
  "These apply to every element matching the selector. In the CSS rule for that component, redeclare the token, e.g. `.input { --twd-radius-control: 999px; }`. Don't replace the `var(--twd-…)` usages with fixed values.",
1270
1273
  ""
1271
1274
  ), vn(o, "selector").forEach(([i, l]) => {
1272
- s.push(`- ${ue(i)} (${document.querySelectorAll(i).length} on this page)`), l.forEach((d) => s.push(` - **${ct(d)}**`, ...dt(d.tokens).map((h) => ` ${h}`)));
1275
+ s.push(`- ${ue(i)} (${document.querySelectorAll(i).length} on this page)`), l.forEach((d) => s.push(` - **${pt(d)}**`, ...ct(d.tokens).map((p) => ` ${p}`)));
1273
1276
  })), r.length) {
1274
1277
  const i = 1 + (a.length ? 1 : 0) + (o.length ? 1 : 0);
1275
1278
  s.push(
@@ -1279,7 +1282,7 @@ function Qa(e, { link: t = location.href, warnings: n = [] } = {}) {
1279
1282
  "These apply to one element only. Add a modifier class to that element (e.g. `input--pill`) and redeclare the token in a rule for that class. The selectors below are runtime paths to help you find the element; don't copy them into the stylesheet.",
1280
1283
  ""
1281
1284
  ), vn(r, "selector").forEach(([l, d]) => {
1282
- s.push(`- ${Ja(l)}, found at ${ue(l)}`), d.forEach((h) => s.push(` - **${ct(h)}**`, ...dt(h.tokens).map((u) => ` ${u}`)));
1285
+ s.push(`- ${Ja(l)}, found at ${ue(l)}`), d.forEach((p) => s.push(` - **${pt(p)}**`, ...ct(p.tokens).map((f) => ` ${f}`)));
1283
1286
  });
1284
1287
  }
1285
1288
  return n.length && s.push(
@@ -1322,19 +1325,19 @@ function yn(e) {
1322
1325
  const kn = ([e, t, n]) => {
1323
1326
  const a = (o) => (o /= 255, o <= 0.03928 ? o / 12.92 : ((o + 0.055) / 1.055) ** 2.4);
1324
1327
  return 0.2126 * a(e) + 0.7152 * a(t) + 0.0722 * a(n);
1325
- }, ea = (e, t) => e.slice(0, 3).map((n, a) => n * e[3] + t[a] * (1 - e[3])).concat(1);
1326
- function ta(e, t) {
1327
- const n = kn(e[3] < 1 ? ea(e, t) : e), a = kn(t);
1328
+ }, Qn = (e, t) => e.slice(0, 3).map((n, a) => n * e[3] + t[a] * (1 - e[3])).concat(1);
1329
+ function ea(e, t) {
1330
+ const n = kn(e[3] < 1 ? Qn(e, t) : e), a = kn(t);
1328
1331
  return (Math.max(n, a) + 0.05) / (Math.min(n, a) + 0.05);
1329
1332
  }
1330
- const na = (e) => `${e.toFixed(1)}:1`;
1331
- function pt() {
1333
+ const ta = (e) => `${e.toFixed(1)}:1`;
1334
+ function ut() {
1332
1335
  const e = [];
1333
1336
  return to.forEach(([t, n, a]) => {
1334
1337
  const o = yn(t), r = yn(n);
1335
1338
  if (!o || !r || r[3] === 0) return;
1336
- const s = ta(o, r);
1337
- s < Ye && e.push({ label: a, ratio: s, needed: Ye, text: `${a}: ${na(s)} · AA needs ${Ye}` });
1339
+ const s = ea(o, r);
1340
+ s < Ye && e.push({ label: a, ratio: s, needed: Ye, text: `${a}: ${ta(s)} · AA needs ${Ye}` });
1338
1341
  }), e;
1339
1342
  }
1340
1343
  function no(e) {
@@ -1344,16 +1347,16 @@ function no(e) {
1344
1347
  if (a && a[3] > 0 && (t.push(a), a[3] >= 1))
1345
1348
  break;
1346
1349
  }
1347
- return t.reduceRight((n, a) => ea(a, n), [255, 255, 255, 1]);
1350
+ return t.reduceRight((n, a) => Qn(a, n), [255, 255, 255, 1]);
1348
1351
  }
1349
1352
  function ao(e) {
1350
1353
  if (!e.textContent.trim() && !e.placeholder) return null;
1351
1354
  const t = getComputedStyle(e), n = It(t.color);
1352
1355
  if (!n) return null;
1353
- const a = parseFloat(t.fontSize), r = a >= 24 || a >= 18.66 && parseInt(t.fontWeight, 10) >= 700 ? eo : Ye, s = ta(n, no(e));
1354
- return s < r ? { label: "This element", ratio: s, needed: r, text: `This element’s text: ${na(s)} · AA needs ${r}` } : null;
1356
+ const a = parseFloat(t.fontSize), r = a >= 24 || a >= 18.66 && parseInt(t.fontWeight, 10) >= 700 ? eo : Ye, s = ea(n, no(e));
1357
+ return s < r ? { label: "This element", ratio: s, needed: r, text: `This element’s text: ${ta(s)} · AA needs ${r}` } : null;
1355
1358
  }
1356
- const Sn = "twiddle-panel", oo = "0.9.0", $n = "https://panel.twiddle.in", ro = "--twd-radius-control", so = /var\(\s*--twd-/;
1359
+ const Sn = "twiddle-panel", oo = "0.9.1", $n = "https://panel.twiddle.in", ro = "--twd-radius-control", so = /var\(\s*--twd-/;
1357
1360
  function io(e) {
1358
1361
  return e.style.cssText.split(";").some((t) => {
1359
1362
  const n = t.slice(0, t.indexOf(":")).trim();
@@ -1439,107 +1442,106 @@ function D(e) {
1439
1442
  function uo({ label: e, ends: t, cols: n = 9, rows: a = 5, onInput: o }) {
1440
1443
  const r = document.createElement("div");
1441
1444
  r.className = "pad", r.tabIndex = 0, r.setAttribute("role", "group"), r.setAttribute("aria-roledescription", "2D slider");
1442
- const s = (m, f) => {
1443
- const v = document.createElement("span");
1444
- return v.className = `pad-edge ${m}`, v.textContent = f, v.setAttribute("aria-hidden", "true"), v;
1445
+ const s = (b, h) => {
1446
+ const w = document.createElement("span");
1447
+ return w.className = `pad-edge ${b}`, w.textContent = h, w.setAttribute("aria-hidden", "true"), w;
1445
1448
  };
1446
1449
  r.append(s("top", t.top), s("bottom", t.bottom), s("left", t.left), s("right", t.right));
1447
1450
  const i = document.createElement("div");
1448
1451
  i.className = "pad-area";
1449
- for (let m = 0; m < a; m++)
1450
- for (let f = 0; f < n; f++) {
1451
- const v = document.createElement("i");
1452
- v.className = "pad-dot", v.style.left = `${f / (n - 1) * 100}%`, v.style.top = `${m / (a - 1) * 100}%`, i.append(v);
1452
+ for (let b = 0; b < a; b++)
1453
+ for (let h = 0; h < n; h++) {
1454
+ const w = document.createElement("i");
1455
+ w.className = "pad-dot", w.style.left = `${h / (n - 1) * 100}%`, w.style.top = `${b / (a - 1) * 100}%`, i.append(w);
1453
1456
  }
1454
1457
  const l = document.createElement("span");
1455
1458
  l.className = "pad-knob", i.append(l), r.append(i);
1456
- let d = 0.5, h = 0.5;
1457
- const u = (m, f) => Math.round(Math.min(1, Math.max(0, m)) * (f - 1)) / (f - 1);
1458
- function w() {
1459
- l.style.left = `${d * 100}%`, l.style.top = `${h * 100}%`;
1459
+ let d = 0.5, p = 0.5;
1460
+ const f = (b, h) => Math.round(Math.min(1, Math.max(0, b)) * (h - 1)) / (h - 1);
1461
+ function v() {
1462
+ l.style.left = `${d * 100}%`, l.style.top = `${p * 100}%`;
1460
1463
  }
1461
- function p(m, f, v) {
1462
- m = v === "x" ? d : u(m, n), f = v === "y" ? h : u(f, a), !(m === d && f === h) && (d = m, h = f, w(), o(d, h));
1464
+ function u(b, h, w) {
1465
+ b = w === "x" ? d : f(b, n), h = w === "y" ? p : f(h, a), !(b === d && h === p) && (d = b, p = h, v(), o(d, p));
1463
1466
  }
1464
- const g = (m) => {
1465
- const f = i.getBoundingClientRect();
1466
- p((m.clientX - f.left) / f.width, (m.clientY - f.top) / f.height);
1467
+ const m = (b) => {
1468
+ const h = i.getBoundingClientRect();
1469
+ u((b.clientX - h.left) / h.width, (b.clientY - h.top) / h.height);
1467
1470
  };
1468
- r.addEventListener("pointerdown", (m) => {
1469
- r.setPointerCapture(m.pointerId), r.classList.add("dragging"), g(m);
1470
- }), r.addEventListener("pointermove", (m) => {
1471
- r.hasPointerCapture(m.pointerId) && g(m);
1471
+ r.addEventListener("pointerdown", (b) => {
1472
+ r.setPointerCapture(b.pointerId), r.classList.add("dragging"), m(b);
1473
+ }), r.addEventListener("pointermove", (b) => {
1474
+ r.hasPointerCapture(b.pointerId) && m(b);
1472
1475
  });
1473
- const x = (m) => {
1474
- r.hasPointerCapture(m.pointerId) && r.releasePointerCapture(m.pointerId), r.classList.remove("dragging");
1476
+ const x = (b) => {
1477
+ r.hasPointerCapture(b.pointerId) && r.releasePointerCapture(b.pointerId), r.classList.remove("dragging");
1475
1478
  };
1476
- return r.addEventListener("pointerup", x), r.addEventListener("pointercancel", x), r.addEventListener("keydown", (m) => {
1477
- const f = { ArrowLeft: [-1, 0], ArrowRight: [1, 0], ArrowUp: [0, -1], ArrowDown: [0, 1] }[m.key];
1478
- f && (m.preventDefault(), f[0] ? p(u(d, n) + f[0] / (n - 1), h, "y") : p(d, u(h, a) + f[1] / (a - 1), "x"));
1479
+ return r.addEventListener("pointerup", x), r.addEventListener("pointercancel", x), r.addEventListener("keydown", (b) => {
1480
+ const h = { ArrowLeft: [-1, 0], ArrowRight: [1, 0], ArrowUp: [0, -1], ArrowDown: [0, 1] }[b.key];
1481
+ h && (b.preventDefault(), h[0] ? u(f(d, n) + h[0] / (n - 1), p, "y") : u(d, f(p, a) + h[1] / (a - 1), "x"));
1479
1482
  }), {
1480
1483
  el: r,
1481
1484
  /** Show a position without telling anyone (used to sync). Off-grid values are shown as they are. */
1482
- setValue(m, f, v) {
1483
- d = Math.min(1, Math.max(0, m)), h = Math.min(1, Math.max(0, f)), w(), r.setAttribute("aria-label", v ? `${e}: ${v}` : e);
1485
+ setValue(b, h, w) {
1486
+ d = Math.min(1, Math.max(0, b)), p = Math.min(1, Math.max(0, h)), v(), r.setAttribute("aria-label", w ? `${e}: ${w}` : e);
1484
1487
  }
1485
1488
  };
1486
1489
  }
1487
- function aa({ label: e, min: t, max: n, step: a = 1, format: o = String, onInput: r }) {
1490
+ function na({ label: e, min: t, max: n, step: a = 1, format: o = String, onInput: r }) {
1488
1491
  const s = document.createElement("div");
1489
1492
  s.className = "slider";
1490
1493
  const i = document.createElement("input");
1491
1494
  i.type = "range", i.min = String(t), i.max = String(n), i.step = String(a), i.setAttribute("aria-label", e);
1492
1495
  const l = document.createElement("span");
1493
1496
  l.className = "slider-value", l.setAttribute("aria-hidden", "true"), s.append(i, l);
1494
- const d = (h) => {
1495
- const u = (Number(i.value) - t) / (n - t) * 100;
1496
- i.style.setProperty("--fill", `${u}%`), l.textContent = h ?? o(Number(i.value)), i.setAttribute("aria-valuetext", l.textContent);
1497
+ const d = (p) => {
1498
+ const f = (Number(i.value) - t) / (n - t) * 100;
1499
+ i.style.setProperty("--fill", `${f}%`), l.textContent = p ?? o(Number(i.value)), i.setAttribute("aria-valuetext", l.textContent);
1497
1500
  };
1498
1501
  return i.addEventListener("input", () => {
1499
1502
  d(), r(Number(i.value));
1500
1503
  }), {
1501
1504
  el: s,
1502
1505
  /** Show a value without reporting it (sync after reset / URL load). */
1503
- setValue(h, u) {
1504
- i.value = String(h), d(u);
1506
+ setValue(p, f) {
1507
+ i.value = String(p), d(f);
1505
1508
  }
1506
1509
  };
1507
1510
  }
1508
1511
  function ho({ label: e, options: t, columns: n = 3, className: a = "", onSelect: o }) {
1509
1512
  const r = document.createElement("div");
1510
1513
  r.className = `tiles ${a}`.trim(), r.style.setProperty("--cols", n), r.setAttribute("role", "radiogroup"), r.setAttribute("aria-label", e);
1511
- const s = t.map((u) => {
1512
- const w = document.createElement("button");
1513
- return w.type = "button", w.className = "tile", u.wide && w.classList.add("wide"), w.setAttribute("role", "radio"), w.dataset.value = u.value, u.title && (w.title = u.title), w.innerHTML = `${u.preview ? `<span class="tile-preview" aria-hidden="true">${u.preview}</span>` : ""}<span class="tile-text"><span class="tile-label"></span>${u.sub ? '<span class="tile-sub"></span>' : ""}</span>`, w.querySelector(".tile-label").textContent = u.label, u.sub && (w.querySelector(".tile-sub").textContent = u.sub), w.addEventListener("click", () => d(u.value)), w;
1514
+ const s = t.map((p) => {
1515
+ const f = document.createElement("button");
1516
+ return f.type = "button", f.className = "tile", p.wide && f.classList.add("wide"), f.setAttribute("role", "radio"), f.dataset.value = p.value, p.title && (f.title = p.title), f.innerHTML = `${p.preview ? `<span class="tile-preview" aria-hidden="true">${p.preview}</span>` : ""}<span class="tile-text"><span class="tile-label"></span>${p.sub ? '<span class="tile-sub"></span>' : ""}</span>`, f.querySelector(".tile-label").textContent = p.label, p.sub && (f.querySelector(".tile-sub").textContent = p.sub), f.addEventListener("click", () => l(p.value)), f;
1514
1517
  });
1515
1518
  r.append(...s);
1516
- let i = null;
1517
- function l(u) {
1518
- i = u, s.forEach((p) => p.setAttribute("aria-checked", String(p.dataset.value === u)));
1519
- const w = Math.max(0, s.findIndex((p) => p.dataset.value === u));
1520
- s.forEach((p, g) => {
1521
- p.tabIndex = g === w ? 0 : -1;
1519
+ function i(p) {
1520
+ s.forEach((v) => v.setAttribute("aria-checked", String(v.dataset.value === p)));
1521
+ const f = Math.max(0, s.findIndex((v) => v.dataset.value === p));
1522
+ s.forEach((v, u) => {
1523
+ v.tabIndex = u === f ? 0 : -1;
1522
1524
  });
1523
1525
  }
1524
- function d(u, w) {
1525
- u !== i && (l(u), o(u)), w && s.find((p) => p.dataset.value === u).focus();
1526
+ function l(p, f) {
1527
+ i(p), o(p), f && s.find((v) => v.dataset.value === p).focus();
1526
1528
  }
1527
- function h(u = []) {
1528
- s.forEach((w) => w.classList.toggle("near", u.includes(w.dataset.value)));
1529
+ function d(p = []) {
1530
+ s.forEach((f) => f.classList.toggle("near", p.includes(f.dataset.value)));
1529
1531
  }
1530
- return r.addEventListener("keydown", (u) => {
1531
- const w = s.indexOf(u.target.closest(".tile"));
1532
- if (w < 0) return;
1533
- const p = { ArrowRight: 1, ArrowDown: 1, ArrowLeft: -1, ArrowUp: -1 }[u.key];
1534
- let g;
1535
- if (p) g = (w + p + s.length) % s.length;
1536
- else if (u.key === "Home") g = 0;
1537
- else if (u.key === "End") g = s.length - 1;
1532
+ return r.addEventListener("keydown", (p) => {
1533
+ const f = s.indexOf(p.target.closest(".tile"));
1534
+ if (f < 0) return;
1535
+ const v = { ArrowRight: 1, ArrowDown: 1, ArrowLeft: -1, ArrowUp: -1 }[p.key];
1536
+ let u;
1537
+ if (v) u = (f + v + s.length) % s.length;
1538
+ else if (p.key === "Home") u = 0;
1539
+ else if (p.key === "End") u = s.length - 1;
1538
1540
  else return;
1539
- u.preventDefault(), d(s[g].dataset.value, !0);
1540
- }), l(null), { el: r, setValue: l, setNear: h };
1541
+ p.preventDefault(), l(s[u].dataset.value, !0);
1542
+ }), i(null), { el: r, setValue: i, setNear: d };
1541
1543
  }
1542
- const O = (e) => getComputedStyle(document.documentElement).getPropertyValue(e).trim();
1544
+ const L = (e) => getComputedStyle(document.documentElement).getPropertyValue(e).trim();
1543
1545
  function Ce(e, t) {
1544
1546
  const n = /^(-?\d*\.?\d+)([a-z%]*)$/i.exec(String(e).trim());
1545
1547
  if (!n) return null;
@@ -1547,12 +1549,12 @@ function Ce(e, t) {
1547
1549
  return o === "px" ? `${Math.round(a)}px` : `${+a.toFixed(3)}${o}`;
1548
1550
  }
1549
1551
  const fo = 999;
1550
- function oa({ id: e, title: t, hint: n, token: a, uses: o = [], presets: r, max: s, extra: i = [], extraTokens: l = () => ({}), shape: d = "card" }) {
1551
- const h = (p) => r.find((g) => g.value === p), u = (p) => p >= fo ? "full" : `${p}px`, w = (p) => {
1552
- if (typeof p.radius == "number" && isFinite(p.radius))
1553
- return { [a]: `${Math.min(Math.max(p.radius, 0), s)}px` };
1554
- const g = h(p.corners);
1555
- return g ? { [a]: `${g.radius}px` } : {};
1552
+ function aa({ id: e, title: t, hint: n, token: a, uses: o = [], presets: r, max: s, extra: i = [], extraTokens: l = () => ({}), shape: d = "card" }) {
1553
+ const p = (u) => r.find((m) => m.value === u), f = (u) => u >= fo ? "full" : `${u}px`, v = (u) => {
1554
+ if (typeof u.radius == "number" && isFinite(u.radius))
1555
+ return { [a]: `${Math.min(Math.max(u.radius, 0), s)}px` };
1556
+ const m = p(u.corners);
1557
+ return m ? { [a]: `${m.radius}px` } : {};
1556
1558
  };
1557
1559
  return {
1558
1560
  id: e,
@@ -1560,86 +1562,86 @@ function oa({ id: e, title: t, hint: n, token: a, uses: o = [], presets: r, max:
1560
1562
  hint: n,
1561
1563
  presets: r,
1562
1564
  uses: [a, ...o],
1563
- tokens(p) {
1564
- const g = p[e] || {};
1565
- return { ...w(g), ...l(g) };
1565
+ tokens(u) {
1566
+ const m = u[e] || {};
1567
+ return { ...v(m), ...l(m) };
1566
1568
  },
1567
1569
  // One render function per knob, so a layout can place them separately.
1568
1570
  // Each takes an optional label (e.g. "Buttons" on the Corners page).
1569
1571
  parts: {
1570
- corners(p, g, { label: x = "Corners" } = {}) {
1571
- const m = D(x), f = ge({
1572
+ corners(u, m, { label: x = "Corners" } = {}) {
1573
+ const b = D(x), h = ge({
1572
1574
  label: `${t} corners`,
1573
- options: r.map(($) => ({ value: $.value, label: $.label, title: u($.radius) })),
1574
- onSelect: ($) => g.setSection(e, { corners: $, radius: null })
1575
- }), v = aa({
1575
+ options: r.map(($) => ({ value: $.value, label: $.label, title: f($.radius) })),
1576
+ onSelect: ($) => m.setSection(e, { corners: $, radius: null })
1577
+ }), w = na({
1576
1578
  label: `${t} corner radius`,
1577
1579
  min: 0,
1578
1580
  max: s,
1579
- format: u,
1580
- onInput: ($) => g.setSection(e, { radius: $, corners: null })
1581
+ format: f,
1582
+ onInput: ($) => m.setSection(e, { radius: $, corners: null })
1581
1583
  });
1582
- m.append(f.el, v.el), p.append(m.el);
1584
+ b.append(h.el, w.el), u.append(b.el);
1583
1585
  const S = () => {
1584
- const $ = parseFloat((g.readToken || O)(a)), K = g.getState()[e] || {}, Z = h(K.corners) || r.find((Le) => Le.radius === $);
1585
- if (f.setValue(Z ? Z.value : null), isNaN($)) {
1586
- v.setValue(0, "—"), m.setValue("");
1586
+ const $ = parseFloat((m.readToken || L)(a)), K = m.getState()[e] || {}, Z = p(K.corners) || r.find((Le) => Le.radius === $);
1587
+ if (h.setValue(Z ? Z.value : null), isNaN($)) {
1588
+ w.setValue(0, "—"), b.setValue("");
1587
1589
  return;
1588
1590
  }
1589
- v.setValue(Math.min($, s), u($)), m.setValue(u($));
1591
+ w.setValue(Math.min($, s), f($)), b.setValue(f($));
1590
1592
  };
1591
- S(), g.onChange(S);
1593
+ S(), m.onChange(S);
1592
1594
  },
1593
- ...Object.fromEntries(i.map((p) => [p.key, (g, x, { label: m } = {}) => g.append(Me(x, { section: e, ...p, label: m || p.label }))])),
1595
+ ...Object.fromEntries(i.map((u) => [u.key, (m, x, { label: b } = {}) => m.append(Me(x, { section: e, ...u, label: b || u.label }))])),
1594
1596
  // Tabbed layout: presets as tiles showing the real rounding.
1595
- cornerTiles(p, g, { label: x = "Corners" } = {}) {
1596
- const m = (f) => `<span class="shape shape-${d}" style="border-radius:${Math.min(f, d === "button" ? 12 : 16)}px"></span>`;
1597
- p.append(_(g, {
1597
+ cornerTiles(u, m, { label: x = "Corners" } = {}) {
1598
+ const b = (h) => `<span class="shape shape-${d}" style="border-radius:${Math.min(h, d === "button" ? 12 : 16)}px"></span>`;
1599
+ u.append(_(m, {
1598
1600
  section: e,
1599
1601
  key: "corners",
1600
1602
  label: x,
1601
1603
  columns: r.length,
1602
- options: r.map((f) => ({ value: f.value, label: f.label, title: u(f.radius), preview: m(f.radius) })),
1603
- current: (f) => {
1604
- const v = f[e] || {};
1605
- if (v.radius != null) return null;
1606
- if (h(v.corners)) return v.corners;
1607
- if (he(f, a)) return null;
1608
- const S = parseFloat((g.readToken || O)(a));
1604
+ options: r.map((h) => ({ value: h.value, label: h.label, title: f(h.radius), preview: b(h.radius) })),
1605
+ current: (h) => {
1606
+ const w = h[e] || {};
1607
+ if (w.radius != null) return null;
1608
+ if (p(w.corners)) return w.corners;
1609
+ if (he(h, a)) return null;
1610
+ const S = parseFloat((m.readToken || L)(a));
1609
1611
  return r.find(($) => $.radius === S)?.value || null;
1610
1612
  },
1611
- select: (f) => g.setSection(e, { corners: f, radius: null }),
1612
- valueText: (f, v) => {
1613
- const S = parseFloat((g.readToken || O)(a));
1613
+ select: (h) => m.setSection(e, { corners: h, radius: null }),
1614
+ valueText: (h, w) => {
1615
+ const S = parseFloat((m.readToken || L)(a));
1614
1616
  if (isNaN(S)) return "";
1615
- const $ = v[e] || {};
1616
- return u(S) + Cn(v, a, $.radius != null ? "custom" : h($.corners)?.label);
1617
+ const $ = w[e] || {};
1618
+ return f(S) + Cn(w, a, $.radius != null ? "custom" : p($.corners)?.label);
1617
1619
  }
1618
1620
  }));
1619
1621
  },
1620
- ...Object.fromEntries(i.filter((p) => p.preview).map((p) => [`${p.key}Tiles`, (g, x, { label: m } = {}) => g.append(_(x, {
1622
+ ...Object.fromEntries(i.filter((u) => u.preview).map((u) => [`${u.key}Tiles`, (m, x, { label: b } = {}) => m.append(_(x, {
1621
1623
  section: e,
1622
- key: p.key,
1623
- label: m || p.label,
1624
- fallback: p.fallback,
1625
- columns: p.columns || p.options.length,
1626
- options: p.options.map((f) => ({ ...f, preview: p.preview(f.value) })),
1627
- ...p.token && {
1628
- current: (f) => (f[e] || {})[p.key] || (he(f, p.token) ? null : p.fallback || null),
1629
- valueText: (f, v) => {
1630
- if (!he(v, p.token)) return "";
1631
- const S = p.options.find(($) => $.value === (v[e] || {})[p.key]);
1632
- return `${(x.readToken || O)(p.token)}${Cn(v, p.token, S && S.label)}`;
1624
+ key: u.key,
1625
+ label: b || u.label,
1626
+ fallback: u.fallback,
1627
+ columns: u.columns || u.options.length,
1628
+ options: u.options.map((h) => ({ ...h, preview: u.preview(h.value) })),
1629
+ ...u.token && {
1630
+ current: (h) => (h[e] || {})[u.key] || (he(h, u.token) ? null : u.fallback || null),
1631
+ valueText: (h, w) => {
1632
+ if (!he(w, u.token)) return "";
1633
+ const S = u.options.find(($) => $.value === (w[e] || {})[u.key]);
1634
+ return `${(x.readToken || L)(u.token)}${Cn(w, u.token, S && S.label)}`;
1633
1635
  }
1634
1636
  },
1635
1637
  // A knob can bring its own rules (e.g. Cards › Fill reads "from Style").
1636
- ...p.current && { current: (f) => p.current(f[e] || {}) },
1637
- ...p.valueText && { valueText: (f, v) => p.valueText(v[e] || {}) },
1638
- ...p.select && { select: (f) => x.setSection(e, p.select(f)) }
1638
+ ...u.current && { current: (h) => u.current(h[e] || {}) },
1639
+ ...u.valueText && { valueText: (h, w) => u.valueText(w[e] || {}, x.readToken || L) },
1640
+ ...u.select && { select: (h) => x.setSection(e, u.select(h)) }
1639
1641
  }))]))
1640
1642
  },
1641
- render(p, g) {
1642
- Object.entries(this.parts).filter(([x]) => !x.endsWith("Tiles")).forEach(([, x]) => x(p, g));
1643
+ render(u, m) {
1644
+ Object.entries(this.parts).filter(([x]) => !x.endsWith("Tiles")).forEach(([, x]) => x(u, m));
1643
1645
  }
1644
1646
  };
1645
1647
  }
@@ -1647,44 +1649,44 @@ function Me(e, { section: t, key: n, label: a, options: o, fallback: r, valueTex
1647
1649
  const i = D(a), l = ge({
1648
1650
  label: a,
1649
1651
  options: o,
1650
- onSelect: (h) => e.setSection(t, { [n]: h })
1652
+ onSelect: (p) => e.setSection(t, { [n]: p })
1651
1653
  });
1652
1654
  i.append(l.el);
1653
1655
  const d = () => {
1654
- const h = (e.getState()[t] || {})[n] || r;
1655
- l.setValue(h), i.setValue(s ? s(h) : "");
1656
+ const p = (e.getState()[t] || {})[n] || r;
1657
+ l.setValue(p), i.setValue(s ? s(p) : "");
1656
1658
  };
1657
1659
  return d(), e.onChange(d), i.el;
1658
1660
  }
1659
1661
  function go(e, { section: t, key: n, label: a, min: o, max: r, fallback: s, format: i, note: l, value: d }) {
1660
- const h = D(a), u = aa({ label: a, min: o, max: r, format: i, onInput: (p) => e.setSection(t, { [n]: p }) });
1661
- h.append(u.el);
1662
- const w = () => {
1663
- const p = e.getState(), g = d ? d(p) : (p[t] || {})[n];
1664
- u.setValue(typeof g == "number" ? g : s), l && (h.el.querySelector(".field-label").textContent = `${a}${l(p) ? ` · ${l(p)}` : ""}`);
1662
+ const p = D(a), f = na({ label: a, min: o, max: r, format: i, onInput: (u) => e.setSection(t, { [n]: u }) });
1663
+ p.append(f.el);
1664
+ const v = () => {
1665
+ const u = e.getState(), m = d ? d(u) : (u[t] || {})[n];
1666
+ f.setValue(typeof m == "number" ? m : s), l && (p.el.querySelector(".field-label").textContent = `${a}${l(u) ? ` · ${l(u)}` : ""}`);
1665
1667
  };
1666
- return w(), e.onChange(w), h.el;
1667
- }
1668
- let ra = () => ({});
1669
- const bo = (e) => {
1670
- ra = e;
1671
- }, he = (e, t) => Object.prototype.hasOwnProperty.call(ra(e), t), Cn = (e, t, n) => he(e, t) ? n ? ` · ${n}, adjusted by Character` : " · from Character" : "";
1672
- function _(e, { section: t, key: n, label: a, options: o, columns: r = 3, className: s = "", fallback: i, valueText: l, current: d, select: h, near: u }) {
1673
- const w = D(a), p = ho({
1668
+ return v(), e.onChange(v), p.el;
1669
+ }
1670
+ let oa = () => ({});
1671
+ const mo = (e) => {
1672
+ oa = e;
1673
+ }, he = (e, t) => Object.prototype.hasOwnProperty.call(oa(e), t), Cn = (e, t, n) => he(e, t) ? n ? ` · ${n}, adjusted by Character` : " · from Character" : "";
1674
+ function _(e, { section: t, key: n, label: a, options: o, columns: r = 3, className: s = "", fallback: i, valueText: l, current: d, select: p, near: f }) {
1675
+ const v = D(a), u = ho({
1674
1676
  label: a,
1675
1677
  options: o,
1676
1678
  columns: r,
1677
1679
  className: s,
1678
- onSelect: (x) => h ? h(x) : e.setSection(t, { [n]: x })
1680
+ onSelect: (x) => p ? p(x) : e.setSection(t, { [n]: x })
1679
1681
  });
1680
- w.append(p.el);
1681
- const g = () => {
1682
- const x = e.getState(), m = d ? d(x) : (x[t] || {})[n] || i || null;
1683
- p.setValue(m), p.setNear(u ? u(x) : []), w.setValue(l ? l(m, x) : "");
1682
+ v.append(u.el);
1683
+ const m = () => {
1684
+ const x = e.getState(), b = d ? d(x) : (x[t] || {})[n] || i || null;
1685
+ u.setValue(b), u.setNear(f ? f(x) : []), v.setValue(l ? l(b, x) : "");
1684
1686
  };
1685
- return g(), e.onChange(g), w.el;
1687
+ return m(), e.onChange(m), v.el;
1686
1688
  }
1687
- const Mn = (e, t) => t.map((n) => `${e}${n}`), sa = {
1689
+ const Mn = (e, t) => t.map((n) => `${e}${n}`), ra = {
1688
1690
  fonts: { label: "Tokens", tokens: ["font-heading", "font-body"], kind: "text" },
1689
1691
  type: { label: "Tokens", tokens: Mn("text-", ["xs", "sm", "base", "lg", "xl", "2xl", "3xl"]), kind: "length" },
1690
1692
  leading: { label: "Line height", tokens: ["leading-tight", "leading-normal"], kind: "number" },
@@ -1698,8 +1700,8 @@ const Mn = (e, t) => t.map((n) => `${e}${n}`), sa = {
1698
1700
  buttonStyle: { label: "Button", tokens: ["button-bg", "button-fg", "button-border", "button-hover"], kind: "colour" },
1699
1701
  cardStyle: { label: "Card", tokens: ["card-bg", "card-border"], kind: "colour" },
1700
1702
  cardShadow: { label: "Card shadow", tokens: ["card-shadow"], kind: "text" }
1701
- }, Y = (e) => `--twd-${e}`, ut = (e, t) => Object.prototype.hasOwnProperty.call(e.getState().custom || {}, t), $e = (e, t) => sa[t].tokens.some((n) => (e.custom || {})[n] != null);
1702
- function mo(e, t) {
1703
+ }, Y = (e) => `--twd-${e}`, ht = (e, t) => Object.prototype.hasOwnProperty.call(e.getState().custom || {}, t), $e = (e, t) => ra[t].tokens.some((n) => (e.custom || {})[n] != null);
1704
+ function bo(e, t) {
1703
1705
  const n = /^(-?\d*\.?\d+)(px|rem)?$/.exec(String(e).trim());
1704
1706
  return !n || t === "text" || t === "colour" ? null : n[2] === "rem" ? { n: +(parseFloat(n[1]) * 16).toFixed(1), unit: "px" } : { n: +parseFloat(n[1]).toFixed(3), unit: n[2] || (t === "length" ? "px" : "") };
1705
1707
  }
@@ -1718,29 +1720,29 @@ function wo(e, t, n, a) {
1718
1720
  <input type="text" spellcheck="false" aria-label="${Y(t)}" ${n === "length" || n === "number" ? 'inputmode="decimal"' : ""}>
1719
1721
  <span class="token-unit"></span>
1720
1722
  </label>
1721
- <button class="icon-btn token-reset" title="Back to the page’s value" aria-label="Reset ${Y(t)}" hidden>${A.reset}</button>
1723
+ <button class="icon-btn token-reset" title="Back to the page’s value" aria-label="Reset ${Y(t)}" hidden>${P.reset}</button>
1722
1724
  `;
1723
- const r = o.querySelector("input"), s = o.querySelector(".token-unit"), i = o.querySelector(".token-bar span"), l = o.querySelector(".token-swatch"), d = o.querySelector(".custom-tag"), h = o.querySelector(".token-reset");
1724
- let u = "";
1725
- const w = () => {
1726
- let g = r.value;
1727
- u && /^-?\d*\.?\d+$/.test(g.trim()) && (g = `${g.trim()}${u}`);
1728
- const x = xo(g, n), m = O(Y(t));
1725
+ const r = o.querySelector("input"), s = o.querySelector(".token-unit"), i = o.querySelector(".token-bar span"), l = o.querySelector(".token-swatch"), d = o.querySelector(".custom-tag"), p = o.querySelector(".token-reset");
1726
+ let f = "";
1727
+ const v = () => {
1728
+ let m = r.value;
1729
+ f && /^-?\d*\.?\d+$/.test(m.trim()) && (m = `${m.trim()}${f}`);
1730
+ const x = xo(m, n), b = L(Y(t));
1729
1731
  if (x === null) {
1730
- ut(e, t) ? e.setSection("custom", { [t]: null }) : p();
1732
+ ht(e, t) ? e.setSection("custom", { [t]: null }) : u();
1731
1733
  return;
1732
1734
  }
1733
- if (x === m && !ut(e, t)) return p();
1735
+ if (x === b && !ht(e, t)) return u();
1734
1736
  e.setSection("custom", { [t]: x });
1735
1737
  };
1736
- r.addEventListener("change", w), r.addEventListener("blur", () => p()), r.addEventListener("keydown", (g) => {
1737
- g.key === "Enter" && (g.preventDefault(), r.blur()), g.key === "Escape" && (g.stopPropagation(), p(), r.blur());
1738
- }), h.addEventListener("click", () => e.setSection("custom", { [t]: null }));
1739
- function p() {
1740
- const g = O(Y(t)), x = ut(e, t), m = mo(g, n);
1741
- u = m ? m.unit : "", document.activeElement !== r && o.getRootNode().activeElement !== r && (r.value = m ? String(m.n) : g), r.title = g, s.textContent = u, s.hidden = !u, i && (i.style.width = `${Math.max(2, Math.min(100, (m ? m.n : 0) / a * 100))}%`), l && (l.style.background = g), o.classList.toggle("edited", x), d.hidden = !x, h.hidden = !x;
1738
+ r.addEventListener("change", v), r.addEventListener("blur", () => u()), r.addEventListener("keydown", (m) => {
1739
+ m.key === "Enter" && (m.preventDefault(), r.blur()), m.key === "Escape" && (m.stopPropagation(), u(), r.blur());
1740
+ }), p.addEventListener("click", () => e.setSection("custom", { [t]: null }));
1741
+ function u() {
1742
+ const m = L(Y(t)), x = ht(e, t), b = bo(m, n);
1743
+ f = b ? b.unit : "", document.activeElement !== r && o.getRootNode().activeElement !== r && (r.value = b ? String(b.n) : m), r.title = m, s.textContent = f, s.hidden = !f, i && (i.style.width = `${Math.max(2, Math.min(100, (b ? b.n : 0) / a * 100))}%`), l && (l.style.background = m), o.classList.toggle("edited", x), d.hidden = !x, p.hidden = !x;
1742
1744
  }
1743
- return p(), e.onChange(p), o;
1745
+ return u(), e.onChange(u), o;
1744
1746
  }
1745
1747
  const vo = {
1746
1748
  id: "custom",
@@ -1753,7 +1755,7 @@ const vo = {
1753
1755
  },
1754
1756
  describe: (e, t) => ({ label: Y(e), value: String(t) }),
1755
1757
  // One part per Edit page group, e.g. parts.spacing → rows for --twd-space-1 … 8.
1756
- parts: Object.fromEntries(Object.entries(sa).map(([e, t]) => [e, (n, a, { label: o = t.label } = {}) => {
1758
+ parts: Object.fromEntries(Object.entries(ra).map(([e, t]) => [e, (n, a, { label: o = t.label } = {}) => {
1757
1759
  const r = D(o);
1758
1760
  r.el.classList.add("token-field");
1759
1761
  const s = t.tokens[0], i = t.tokens[t.tokens.length - 1];
@@ -1761,24 +1763,24 @@ const vo = {
1761
1763
  const l = document.createElement("div");
1762
1764
  l.className = "token-rows", t.tokens.forEach((d) => l.append(wo(a, d, t.kind, t.bar))), r.append(l), n.append(r.el);
1763
1765
  }]))
1764
- }, X = { compact: 0.75, regular: 1, comfy: 1.25 }, Ft = [0.75, 1.25], Tn = [1, 2, 3, 4, 5, 6, 7, 8].map((e) => `--twd-space-${e}`);
1765
- function ia(e) {
1766
+ }, X = { compact: 0.75, regular: 1, comfy: 1.25 }, jt = [0.75, 1.25], Tn = [1, 2, 3, 4, 5, 6, 7, 8].map((e) => `--twd-space-${e}`);
1767
+ function sa(e) {
1766
1768
  const t = Object.entries(X).sort((a, o) => a[1] - o[1]);
1767
1769
  if (t.some(([, a]) => a === e)) return [];
1768
1770
  const n = t.findIndex(([, a]) => a > e);
1769
1771
  return n > 0 ? [t[n - 1][0], t[n][0]] : [];
1770
1772
  }
1771
- const ht = (e) => e[0].toUpperCase() + e.slice(1);
1773
+ const ft = (e) => e[0].toUpperCase() + e.slice(1);
1772
1774
  function Dt(e) {
1773
1775
  const t = Object.keys(X).find((a) => X[a] === e);
1774
- if (t) return ht(t);
1775
- const n = ia(e);
1776
- return n.length ? `Between ${ht(n[0])} and ${ht(n[1])}` : e > 1 ? "Comfy" : "Compact";
1776
+ if (t) return ft(t);
1777
+ const n = sa(e);
1778
+ return n.length ? `Between ${ft(n[0])} and ${ft(n[1])}` : e > 1 ? "Comfy" : "Compact";
1777
1779
  }
1778
1780
  function H(e = {}) {
1779
- return typeof e.factor == "number" && isFinite(e.factor) ? Math.min(Ft[1], Math.max(Ft[0], e.factor)) : X[e.spacing] || 1;
1781
+ return typeof e.factor == "number" && isFinite(e.factor) ? Math.min(jt[1], Math.max(jt[0], e.factor)) : X[e.spacing] || 1;
1780
1782
  }
1781
- const ft = (e) => `${Math.round(e * 100)}%`, yo = {
1783
+ const gt = (e) => `${Math.round(e * 100)}%`, yo = {
1782
1784
  id: "density",
1783
1785
  title: "Density",
1784
1786
  hint: "Compact · regular · comfortable",
@@ -1788,12 +1790,12 @@ const ft = (e) => `${Math.round(e * 100)}%`, yo = {
1788
1790
  if (t === 1) return {};
1789
1791
  const n = {};
1790
1792
  return Tn.forEach((a) => {
1791
- const o = Ce(O(a), t);
1793
+ const o = Ce(L(a), t);
1792
1794
  o && (n[a] = o);
1793
1795
  }), n;
1794
1796
  },
1795
1797
  /** How the Changes list and prompt describe a setting. */
1796
- describe: (e, t) => e === "factor" ? { label: "Spacing", value: ft(t) } : null,
1798
+ describe: (e, t) => e === "factor" ? { label: "Spacing", value: gt(t) } : null,
1797
1799
  parts: {
1798
1800
  // Tabbed layout: presets as tiles with a tiny layout sketch.
1799
1801
  spacingTiles(e, t, { label: n = "Density" } = {}) {
@@ -1808,8 +1810,8 @@ const ft = (e) => `${Math.round(e * 100)}%`, yo = {
1808
1810
  return Object.keys(X).find((s) => X[s] === r) || null;
1809
1811
  },
1810
1812
  select: (o) => t.setSection("density", { spacing: o, factor: null }),
1811
- near: (o) => $e(o, "spacing") ? [] : ia(H(o.density)),
1812
- valueText: (o, r) => $e(r, "spacing") ? "Custom" : o ? "" : `${Dt(H(r.density))} · ${ft(H(r.density))}`
1813
+ near: (o) => $e(o, "spacing") ? [] : sa(H(o.density)),
1814
+ valueText: (o, r) => $e(r, "spacing") ? "Custom" : o ? "" : `${Dt(H(r.density))} · ${gt(H(r.density))}`
1813
1815
  }));
1814
1816
  },
1815
1817
  spacing(e, t, { label: n = "Spacing" } = {}) {
@@ -1821,7 +1823,7 @@ const ft = (e) => `${Math.round(e * 100)}%`, yo = {
1821
1823
  a.append(o.el);
1822
1824
  const r = () => {
1823
1825
  const s = t.getState().density || {}, i = H(s), l = Object.keys(X).find((d) => X[d] === i);
1824
- o.setValue(l || null), a.setValue($e(t.getState(), "spacing") ? "Custom" : l ? "" : ft(i));
1826
+ o.setValue(l || null), a.setValue($e(t.getState(), "spacing") ? "Custom" : l ? "" : gt(i));
1825
1827
  };
1826
1828
  r(), t.onChange(r), e.append(a.el);
1827
1829
  }
@@ -1841,7 +1843,7 @@ const ft = (e) => `${Math.round(e * 100)}%`, yo = {
1841
1843
  [800, "black", 58],
1842
1844
  [900, "black", 45],
1843
1845
  [950, "black", 30]
1844
- ], gt = (e) => {
1846
+ ], mt = (e) => {
1845
1847
  let t = String(e).trim().replace(/^#/, "");
1846
1848
  return /^[0-9a-f]{3}$/i.test(t) && (t = t.split("").map((n) => n + n).join("")), /^[0-9a-f]{6}$/i.test(t) ? `#${t.toUpperCase()}` : null;
1847
1849
  };
@@ -1859,15 +1861,15 @@ function $o({ label: e, onInput: t }) {
1859
1861
  const i = document.createElement("button");
1860
1862
  i.type = "button", i.className = "colour-pipette", i.innerHTML = ko, i.title = "Pick a colour from the screen", i.setAttribute("aria-label", "Pick a colour from the screen"), a.append(o, r, s, i);
1861
1863
  const l = document.createElement("div");
1862
- l.className = "ramp", l.setAttribute("aria-hidden", "true"), l.innerHTML = So.map(([p, g, x]) => {
1863
- const m = g ? `color-mix(in oklch, var(--brand) ${x}%, ${g})` : "var(--brand)";
1864
- return `<span title="${p}" style="background:${m}"></span>`;
1864
+ l.className = "ramp", l.setAttribute("aria-hidden", "true"), l.innerHTML = So.map(([u, m, x]) => {
1865
+ const b = m ? `color-mix(in oklch, var(--brand) ${x}%, ${m})` : "var(--brand)";
1866
+ return `<span title="${u}" style="background:${b}"></span>`;
1865
1867
  }).join(""), n.append(a, l);
1866
1868
  let d = "#000000";
1867
- const h = (p) => {
1868
- d = p, o.value = p.toLowerCase(), r.style.background = p, n.getRootNode().activeElement !== s && (s.value = p), n.style.setProperty("--brand", p);
1869
- }, u = (p) => {
1870
- p !== d && (h(p), t(p));
1869
+ const p = (u) => {
1870
+ d = u, o.value = u.toLowerCase(), r.style.background = u, n.getRootNode().activeElement !== s && (s.value = u), n.style.setProperty("--brand", u);
1871
+ }, f = (u) => {
1872
+ u !== d && (p(u), t(u));
1871
1873
  };
1872
1874
  r.addEventListener("click", () => {
1873
1875
  if (o.showPicker)
@@ -1877,25 +1879,25 @@ function $o({ label: e, onInput: t }) {
1877
1879
  } catch {
1878
1880
  }
1879
1881
  o.click();
1880
- }), o.addEventListener("input", () => u(o.value.toUpperCase())), s.addEventListener("input", () => {
1881
- const p = gt(s.value);
1882
- p && u(p);
1882
+ }), o.addEventListener("input", () => f(o.value.toUpperCase())), s.addEventListener("input", () => {
1883
+ const u = mt(s.value);
1884
+ u && f(u);
1883
1885
  });
1884
- const w = () => {
1886
+ const v = () => {
1885
1887
  s.value = d;
1886
1888
  };
1887
- return s.addEventListener("blur", w), s.addEventListener("keydown", (p) => {
1888
- p.key === "Enter" && (w(), s.select());
1889
+ return s.addEventListener("blur", v), s.addEventListener("keydown", (u) => {
1890
+ u.key === "Enter" && (v(), s.select());
1889
1891
  }), i.addEventListener("click", async () => {
1890
1892
  if ("EyeDropper" in window)
1891
1893
  try {
1892
- const { sRGBHex: p } = await new window.EyeDropper().open(), g = gt(p);
1893
- g && u(g);
1894
+ const { sRGBHex: u } = await new window.EyeDropper().open(), m = mt(u);
1895
+ m && f(m);
1894
1896
  } catch {
1895
1897
  }
1896
1898
  else
1897
1899
  r.click();
1898
- }), { el: n, setValue: (p) => h(gt(p) || d) };
1900
+ }), { el: n, setValue: (u) => p(mt(u) || d) };
1899
1901
  }
1900
1902
  function Eo({ label: e, options: t, onSelect: n }) {
1901
1903
  const a = document.createElement("div");
@@ -1907,25 +1909,25 @@ function Eo({ label: e, options: t, onSelect: n }) {
1907
1909
  a.append(...o);
1908
1910
  let r = null;
1909
1911
  function s(l) {
1910
- r = l, o.forEach((h) => h.setAttribute("aria-checked", String(h.dataset.value === l)));
1911
- const d = Math.max(0, o.findIndex((h) => h.dataset.value === l));
1912
- o.forEach((h, u) => {
1913
- h.tabIndex = u === d ? 0 : -1;
1912
+ r = l, o.forEach((p) => p.setAttribute("aria-checked", String(p.dataset.value === l)));
1913
+ const d = Math.max(0, o.findIndex((p) => p.dataset.value === l));
1914
+ o.forEach((p, f) => {
1915
+ p.tabIndex = f === d ? 0 : -1;
1914
1916
  });
1915
1917
  }
1916
1918
  function i(l, d) {
1917
- l !== r && (s(l), n(l)), d && o.find((h) => h.dataset.value === l).focus();
1919
+ l !== r && (s(l), n(l)), d && o.find((p) => p.dataset.value === l).focus();
1918
1920
  }
1919
1921
  return a.addEventListener("keydown", (l) => {
1920
1922
  const d = o.indexOf(l.target.closest(".swatch"));
1921
1923
  if (d < 0) return;
1922
- const h = { ArrowRight: 1, ArrowDown: 1, ArrowLeft: -1, ArrowUp: -1 }[l.key];
1923
- let u;
1924
- if (h) u = (d + h + o.length) % o.length;
1925
- else if (l.key === "Home") u = 0;
1926
- else if (l.key === "End") u = o.length - 1;
1924
+ const p = { ArrowRight: 1, ArrowDown: 1, ArrowLeft: -1, ArrowUp: -1 }[l.key];
1925
+ let f;
1926
+ if (p) f = (d + p + o.length) % o.length;
1927
+ else if (l.key === "Home") f = 0;
1928
+ else if (l.key === "End") f = o.length - 1;
1927
1929
  else return;
1928
- l.preventDefault(), i(o[u].dataset.value, !0);
1930
+ l.preventDefault(), i(o[f].dataset.value, !0);
1929
1931
  }), s(null), { el: a, setValue: s };
1930
1932
  }
1931
1933
  const Co = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950], ke = (e) => Object.fromEntries(e.split(" ").map((t, n) => [Co[n], `#${t}`])), bt = {
@@ -1934,7 +1936,7 @@ const Co = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950], ke = (e) => O
1934
1936
  zinc: ke("fafafa f4f4f5 e4e4e7 d4d4d8 a1a1aa 71717a 52525b 3f3f46 27272a 18181b 09090b"),
1935
1937
  neutral: ke("fafafa f5f5f5 e5e5e5 d4d4d4 a3a3a3 737373 525252 404040 262626 171717 0a0a0a"),
1936
1938
  stone: ke("fafaf9 f5f5f4 e7e5e4 d6d3d1 a8a29e 78716c 57534e 44403c 292524 1c1917 0c0a09")
1937
- }, N = (e) => Object.fromEntries(e.split(" ").map((t, n) => [400 + 100 * n, `#${t}`])), mt = {
1939
+ }, N = (e) => Object.fromEntries(e.split(" ").map((t, n) => [400 + 100 * n, `#${t}`])), xt = {
1938
1940
  red: N("f87171 ef4444 dc2626 b91c1c 991b1b"),
1939
1941
  orange: N("fb923c f97316 ea580c c2410c 9a3412"),
1940
1942
  amber: N("fbbf24 f59e0b d97706 b45309 92400e"),
@@ -1970,8 +1972,8 @@ const Co = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950], ke = (e) => O
1970
1972
  text: "#F4F4F5",
1971
1973
  "text-muted": "#A1A1AA",
1972
1974
  border: "#2E2E33"
1973
- }, Ao = { bg: 4, surface: 2, "surface-raised": 2, text: 5, "text-muted": 12, border: 10 }, ee = (e) => /^#[0-9a-f]{6}$/i.test(e || ""), xt = (e) => [500, 600, 700].includes(Number(e.shade)) ? Number(e.shade) : 600, wt = (e) => e[0].toUpperCase() + e.slice(1);
1974
- function On(e) {
1975
+ }, Ao = { bg: 4, surface: 2, "surface-raised": 2, text: 5, "text-muted": 12, border: 10 }, ee = (e) => /^#[0-9a-f]{6}$/i.test(e || ""), wt = (e) => [500, 600, 700].includes(Number(e.shade)) ? Number(e.shade) : 600, vt = (e) => e[0].toUpperCase() + e.slice(1);
1976
+ function Pn(e) {
1975
1977
  const t = (l) => (l /= 255, l <= 0.03928 ? l / 12.92 : ((l + 0.055) / 1.055) ** 2.4), [n, a, o] = [1, 3, 5].map((l) => t(parseInt(e.slice(l, l + 2), 16))), r = 0.2126 * n + 0.7152 * a + 0.0722 * o, s = 1.05 / (r + 0.05), i = (r + 0.05) / (98e-4 + 0.05);
1976
1978
  return s >= i ? "#FFFFFF" : "#18181B";
1977
1979
  }
@@ -1981,20 +1983,20 @@ const Je = {
1981
1983
  hint: "Brand colour · neutral tint · mode",
1982
1984
  uses: ["--twd-primary", "--twd-primary-hover", "--twd-on-primary", "--twd-focus", ...An.map((e) => `--twd-${e}`)],
1983
1985
  tokens(e) {
1984
- const t = e.colour || {}, n = {}, a = t.mode === "dark", o = mt[t.primary];
1986
+ const t = e.colour || {}, n = {}, a = t.mode === "dark", o = xt[t.primary];
1985
1987
  if (!ee(t.brand) && o) {
1986
- const i = xt(t);
1987
- n["--twd-primary"] = o[i], n["--twd-primary-hover"] = o[a ? i - 100 : i + 100], n["--twd-on-primary"] = On(o[i]), n["--twd-focus"] = o[500];
1988
+ const i = wt(t);
1989
+ n["--twd-primary"] = o[i], n["--twd-primary-hover"] = o[a ? i - 100 : i + 100], n["--twd-on-primary"] = Pn(o[i]), n["--twd-focus"] = o[500];
1988
1990
  }
1989
- ee(t.brand) && (n["--twd-primary"] = t.brand, n["--twd-primary-hover"] = a ? `color-mix(in oklch, ${t.brand} 85%, white)` : `color-mix(in oklch, ${t.brand} 86%, black)`, n["--twd-on-primary"] = On(t.brand), n["--twd-focus"] = t.brand);
1990
- const r = t.tint === "subtle" ? ee(t.brand) ? t.brand : O("--twd-primary") || Ln : t.tint === "warm" ? Mo : null, s = bt[t.neutral];
1991
+ ee(t.brand) && (n["--twd-primary"] = t.brand, n["--twd-primary-hover"] = a ? `color-mix(in oklch, ${t.brand} 85%, white)` : `color-mix(in oklch, ${t.brand} 86%, black)`, n["--twd-on-primary"] = Pn(t.brand), n["--twd-focus"] = t.brand);
1992
+ const r = t.tint === "subtle" ? ee(t.brand) ? t.brand : L("--twd-primary") || Ln : t.tint === "warm" ? Mo : null, s = bt[t.neutral];
1991
1993
  if (s) {
1992
1994
  const i = a ? { bg: s[950], surface: s[900], "surface-raised": s[800], text: s[100], "text-muted": s[400], border: s[800] } : { bg: s[50], surface: "#ffffff", "surface-raised": "#ffffff", text: s[900], "text-muted": s[500], border: s[200] };
1993
1995
  Object.entries(i).forEach(([l, d]) => {
1994
1996
  n[`--twd-${l}`] = d;
1995
1997
  });
1996
1998
  } else (a || r) && An.forEach((i) => {
1997
- const l = a ? Lo[i] : O(`--twd-${i}`);
1999
+ const l = a ? Lo[i] : L(`--twd-${i}`);
1998
2000
  l && (n[`--twd-${i}`] = r ? `color-mix(in oklch, ${l} ${100 - Ao[i]}%, ${r})` : l);
1999
2001
  });
2000
2002
  return n;
@@ -2003,7 +2005,7 @@ const Je = {
2003
2005
  // ---- Tabbed layout (Colour tab): themes, then Tailwind fine-tuning ----
2004
2006
  themeTiles(e, t, { label: n = "Theme" } = {}) {
2005
2007
  const a = (o) => {
2006
- const r = bt[o.neutral], s = mt[o.primary];
2008
+ const r = bt[o.neutral], s = xt[o.primary];
2007
2009
  return `<span class="theme" style="--bg:${r[50]};--line:${r[200]};--ink:${r[900]};--soft:${r[500]};--pri:${s[600]}"><i><b></b><s></s><u></u></i></span><span class="palette">${[s[400], s[500], s[600], s[700], s[800], r[200], r[500], r[900]].map((i) => `<i style="background:${i}"></i>`).join("")}</span>`;
2008
2010
  };
2009
2011
  e.append(_(t, {
@@ -2034,7 +2036,7 @@ const Je = {
2034
2036
  label: `${n} colour family`,
2035
2037
  columns: 9,
2036
2038
  className: "tiles-swatches",
2037
- options: Object.entries(mt).map(([i, l]) => ({ value: i, label: wt(i), title: wt(i), preview: `<span class="dot" style="background:${l[500]}"></span>` })),
2039
+ options: Object.entries(xt).map(([i, l]) => ({ value: i, label: vt(i), title: vt(i), preview: `<span class="dot" style="background:${l[500]}"></span>` })),
2038
2040
  current: (i) => {
2039
2041
  const l = i.colour || {};
2040
2042
  return ee(l.brand) ? null : l.primary || null;
@@ -2046,7 +2048,7 @@ const Je = {
2046
2048
  a.append(o, r.el);
2047
2049
  const s = () => {
2048
2050
  const i = t.getState().colour || {};
2049
- r.setValue(String(xt(i))), a.setValue(ee(i.brand) ? i.brand.toLowerCase() : i.primary ? `${i.primary}-${xt(i)}` : "");
2051
+ r.setValue(String(wt(i))), a.setValue(ee(i.brand) ? i.brand.toLowerCase() : i.primary ? `${i.primary}-${wt(i)}` : "");
2050
2052
  };
2051
2053
  s(), t.onChange(s), e.append(a.el);
2052
2054
  },
@@ -2057,7 +2059,7 @@ const Je = {
2057
2059
  label: n,
2058
2060
  columns: 5,
2059
2061
  className: "tiles-greys",
2060
- options: Object.entries(bt).map(([a, o]) => ({ value: a, label: wt(a), preview: `<span class="greys">${[o[50], o[200], o[500], o[900]].map((r) => `<i style="background:${r}"></i>`).join("")}</span>` })),
2062
+ options: Object.entries(bt).map(([a, o]) => ({ value: a, label: vt(a), preview: `<span class="greys">${[o[50], o[200], o[500], o[900]].map((r) => `<i style="background:${r}"></i>`).join("")}</span>` })),
2061
2063
  select: (a) => t.setSection("colour", { neutral: a, tint: null }),
2062
2064
  valueText: (a) => a || ""
2063
2065
  }));
@@ -2071,7 +2073,7 @@ const Je = {
2071
2073
  brand(e, t, { label: n = "Brand" } = {}) {
2072
2074
  const a = D(n), o = $o({ label: "Brand colour", onInput: (s) => t.setSection("colour", { brand: s }) });
2073
2075
  a.append(o.el);
2074
- const r = () => o.setValue((t.getState().colour || {}).brand || (t.readToken || O)("--twd-primary") || Ln);
2076
+ const r = () => o.setValue((t.getState().colour || {}).brand || (t.readToken || L)("--twd-primary") || Ln);
2075
2077
  r(), t.onChange(r), e.append(a.el);
2076
2078
  },
2077
2079
  neutral(e, t, { label: n = "Neutral" } = {}) {
@@ -2093,12 +2095,12 @@ const Je = {
2093
2095
  render(e, t) {
2094
2096
  ["brand", "neutral", "mode"].forEach((n) => this.parts[n](e, t));
2095
2097
  }
2096
- }, Ve = (e, t = "var(--twd-surface)") => `color-mix(in oklch, var(--twd-primary) ${e}%, ${t})`, Oo = {
2098
+ }, Ve = (e, t = "var(--twd-surface)") => `color-mix(in oklch, var(--twd-primary) ${e}%, ${t})`, Po = {
2097
2099
  // proposal recipes; Solid leaves tokens.css defaults
2098
2100
  soft: { bg: Ve(14), fg: "var(--twd-primary)", border: "transparent", hover: Ve(22) },
2099
2101
  outline: { bg: "transparent", fg: "var(--twd-primary)", border: "var(--twd-primary)", hover: Ve(8, "transparent") },
2100
2102
  ghost: { bg: "transparent", fg: "var(--twd-primary)", border: "transparent", hover: Ve(10, "transparent") }
2101
- }, Po = { small: { height: 0.8, pad: 0.75 }, large: { height: 1.2, pad: 1.25 } }, la = oa({
2103
+ }, Oo = { small: { height: 0.8, pad: 0.75 }, large: { height: 1.2, pad: 1.25 } }, ia = aa({
2102
2104
  id: "buttons",
2103
2105
  title: "Buttons",
2104
2106
  hint: "Style · corners · size",
@@ -2118,13 +2120,13 @@ const Je = {
2118
2120
  { value: "pill", label: "Pill", radius: 999 }
2119
2121
  ],
2120
2122
  extraTokens(e) {
2121
- const t = {}, n = Oo[e.style];
2123
+ const t = {}, n = Po[e.style];
2122
2124
  n && Object.entries(n).forEach(([s, i]) => {
2123
2125
  t[`--twd-button-${s}`] = i;
2124
2126
  });
2125
- const a = Po[e.size];
2127
+ const a = Oo[e.size];
2126
2128
  if (!a) return t;
2127
- const o = Ce(O("--twd-control-height"), a.height), r = Ce(O("--twd-control-pad-x"), a.pad);
2129
+ const o = Ce(L("--twd-control-height"), a.height), r = Ce(L("--twd-control-pad-x"), a.pad);
2128
2130
  return o && (t["--twd-control-height"] = o), r && (t["--twd-control-pad-x"] = r), t;
2129
2131
  },
2130
2132
  extra: [
@@ -2140,25 +2142,21 @@ const Je = {
2140
2142
  key: "size",
2141
2143
  label: "Size",
2142
2144
  fallback: "medium",
2145
+ valueText: (e, t) => t("--twd-control-height"),
2146
+ // the height in effect (Shape pass)
2143
2147
  preview: (e) => `<span class="shape shape-button size-${e}"></span>`,
2144
2148
  options: [{ value: "small", label: "Small" }, { value: "medium", label: "Medium" }, { value: "large", label: "Large" }]
2145
2149
  }
2146
2150
  ]
2147
- }), vt = {
2151
+ }), jo = {
2148
2152
  // proposal recipes; Filled leaves tokens.css defaults
2149
2153
  outlined: { bg: "transparent", border: "color-mix(in oklch, var(--twd-border) 60%, var(--twd-text))", shadow: "none" },
2150
2154
  elevated: { bg: "var(--twd-surface-raised)", border: "transparent", shadow: "var(--twd-shadow-md)" },
2151
2155
  tinted: { bg: "color-mix(in oklch, var(--twd-primary) 8%, var(--twd-surface))", border: "color-mix(in oklch, var(--twd-primary) 25%, var(--twd-surface))", shadow: "none" }
2152
- }, Pn = {
2153
- // proposal
2154
- none: "transparent",
2155
- surface: "var(--twd-surface)",
2156
- raised: "var(--twd-surface-raised)",
2157
- tinted: "color-mix(in oklch, var(--twd-primary) 8%, var(--twd-surface))"
2158
- }, Fo = { outlined: "Outlined", elevated: "Elevated", tinted: "Tinted" }, jt = oa({
2156
+ }, Ft = aa({
2159
2157
  id: "cards",
2160
2158
  title: "Cards",
2161
- hint: "Style · corners · fill · border",
2159
+ hint: "Style · corners · border",
2162
2160
  token: "--twd-radius-container",
2163
2161
  shape: "card",
2164
2162
  // tile previews: an outlined card
@@ -2175,11 +2173,11 @@ const Je = {
2175
2173
  // proposal (cards don't go fully pill)
2176
2174
  ],
2177
2175
  extraTokens(e) {
2178
- const t = {}, n = vt[e.style];
2176
+ const t = {}, n = jo[e.style];
2179
2177
  if (n && Object.entries(n).forEach(([a, o]) => {
2180
2178
  t[`--twd-card-${a}`] = o;
2181
- }), Pn[e.fill] && (t["--twd-card-bg"] = Pn[e.fill]), e.border === "none" && (t["--twd-border-width-container"] = "0px"), e.border === "thick") {
2182
- const a = Ce(O("--twd-border-width-container"), 2);
2179
+ }), e.border === "none" && (t["--twd-border-width-container"] = "0px"), e.border === "thick") {
2180
+ const a = Ce(L("--twd-border-width-container"), 2);
2183
2181
  a && (t["--twd-border-width-container"] = a);
2184
2182
  }
2185
2183
  return t;
@@ -2190,19 +2188,9 @@ const Je = {
2190
2188
  label: "Style",
2191
2189
  fallback: "filled",
2192
2190
  columns: 4,
2193
- preview: (e) => `<span class="shape shape-card style-${e}"></span>`,
2194
- options: [{ value: "filled", label: "Filled" }, { value: "outlined", label: "Outlined" }, { value: "elevated", label: "Elevated" }, { value: "tinted", label: "Tinted" }],
2195
- select: (e) => ({ style: e, fill: null })
2196
- },
2197
- // a style is a whole recipe, its fill included
2198
- {
2199
- key: "fill",
2200
- label: "Fill",
2201
- columns: 4,
2202
- preview: (e) => `<span class="shape shape-card fill-${e}"></span>`,
2203
- options: [{ value: "none", label: "None" }, { value: "surface", label: "Surface" }, { value: "raised", label: "Raised" }, { value: "tinted", label: "Tinted" }],
2204
- current: (e) => e.fill || (vt[e.style] ? null : "surface"),
2205
- valueText: (e) => !e.fill && vt[e.style] ? `${Fo[e.style]} · from Style` : ""
2191
+ // A mini card with two content lines on a page backdrop (Figma 281:1421)
2192
+ preview: (e) => `<span class="mini"><span class="mini-card style-${e}"><i></i><i></i></span></span>`,
2193
+ options: [{ value: "filled", label: "Filled" }, { value: "outlined", label: "Outlined" }, { value: "elevated", label: "Elevated" }, { value: "tinted", label: "Tinted" }]
2206
2194
  },
2207
2195
  {
2208
2196
  key: "border",
@@ -2214,7 +2202,7 @@ const Je = {
2214
2202
  options: [{ value: "none", label: "None" }, { value: "thin", label: "Thin" }, { value: "thick", label: "Thick" }]
2215
2203
  }
2216
2204
  ]
2217
- }), qe = (e) => !(e.depth || {}).style && he(e, "--twd-shadow-md"), jo = (e) => ((e.character || {}).bold || 0.5) > 0.5, G = 60, yt = {
2205
+ }), qe = (e) => !(e.depth || {}).style && he(e, "--twd-shadow-md"), Fo = (e) => ((e.character || {}).bold || 0.5) > 0.5, G = 60, yt = {
2218
2206
  soft: { sm: [0, 1, 2, 0, 0.06], md: [0, 4, 12, 0, 0.08], lg: [0, 12, 32, 0, 0.12] },
2219
2207
  // = tokens.css
2220
2208
  crisp: { sm: [0, 1, 1, 0, 0.12], md: [0, 2, 4, 0, 0.14], lg: [0, 4, 8, 0, 0.16] },
@@ -2253,7 +2241,7 @@ const Je = {
2253
2241
  columns: 4,
2254
2242
  options: ["flat", "soft", "crisp", "bold"].map((o) => ({ value: o, label: o[0].toUpperCase() + o.slice(1), preview: a(o) })),
2255
2243
  current: (o) => (o.depth || {}).style || (qe(o) ? null : "soft"),
2256
- valueText: (o, r) => qe(r) ? `${jo(r) ? "Bold recipe" : "Soft, faded"} · from Character` : ""
2244
+ valueText: (o, r) => qe(r) ? `${Fo(r) ? "Bold recipe" : "Soft, faded"} · from Character` : ""
2257
2245
  }));
2258
2246
  },
2259
2247
  style(e, t, { label: n = "Style" } = {}) {
@@ -2287,11 +2275,11 @@ const Je = {
2287
2275
  render(e, t) {
2288
2276
  Object.entries(this.parts).filter(([n]) => !n.endsWith("Tiles")).forEach(([, n]) => n(e, t));
2289
2277
  }
2290
- }, No = (e) => Math.min(1, Math.max(0, e)), Fn = (e) => Math.round(e / 50) * 50, kt = (e) => `${+e.toFixed(1)}%`;
2278
+ }, No = (e) => Math.min(1, Math.max(0, e)), On = (e) => Math.round(e / 50) * 50, kt = (e) => `${+e.toFixed(1)}%`;
2291
2279
  function Bt(e = {}) {
2292
2280
  return typeof e.bold == "number" && isFinite(e.bold) && e.bold !== 0.5 ? No(e.bold) : null;
2293
2281
  }
2294
- const _e = (e, t, n) => (e.tokens(t) || {})[n] || O(n), da = {
2282
+ const _e = (e, t, n) => (e.tokens(t) || {})[n] || L(n), la = {
2295
2283
  id: "character",
2296
2284
  title: "Character",
2297
2285
  hint: "Subtle ↔ Bold",
@@ -2301,17 +2289,17 @@ const _e = (e, t, n) => (e.tokens(t) || {})[n] || O(n), da = {
2301
2289
  const t = Bt(e.character);
2302
2290
  if (t === null) return {};
2303
2291
  const n = {}, a = 2 * t - 1, o = Math.max(0, a), r = Math.max(0, -a);
2304
- n["--twd-weight-heading"] = String(Fn(600 + 200 * a)), n["--twd-weight-strong"] = String(Fn(600 + 100 * a));
2292
+ n["--twd-weight-heading"] = String(On(600 + 200 * a)), n["--twd-weight-strong"] = String(On(600 + 100 * a));
2305
2293
  const s = _e(Je, e, "--twd-border");
2306
2294
  if (r && (n["--twd-border"] = `color-mix(in oklch, ${s} ${kt(100 - 50 * r)}, var(--twd-bg))`), o) {
2307
2295
  n["--twd-border"] = `color-mix(in oklch, ${s} ${kt(100 - 90 * o)}, var(--twd-text))`;
2308
2296
  const l = _e(Je, e, "--twd-text-muted");
2309
2297
  n["--twd-text-muted"] = `color-mix(in oklch, ${l} ${kt(100 - 35 * o)}, var(--twd-text))`, ["--twd-border-width", "--twd-border-width-container"].forEach((d) => {
2310
- const h = d === "--twd-border-width-container" ? _e(jt, e, d) : O(d), u = parseFloat(h);
2311
- u > 0 && (n[d] = `${Math.round(u * (1 + o))}px`);
2312
- }), [[la, "--twd-radius-control"], [jt, "--twd-radius-container"]].forEach(([d, h]) => {
2313
- const u = parseFloat(_e(d, e, h));
2314
- u > 0 && u < 999 && (n[h] = Ce(`${u}px`, 1 - 0.5 * o));
2298
+ const p = d === "--twd-border-width-container" ? _e(Ft, e, d) : L(d), f = parseFloat(p);
2299
+ f > 0 && (n[d] = `${Math.round(f * (1 + o))}px`);
2300
+ }), [[ia, "--twd-radius-control"], [Ft, "--twd-radius-container"]].forEach(([d, p]) => {
2301
+ const f = parseFloat(_e(d, e, p));
2302
+ f > 0 && f < 999 && (n[p] = Ce(`${f}px`, 1 - 0.5 * o));
2315
2303
  });
2316
2304
  }
2317
2305
  const i = e.depth || {};
@@ -2323,7 +2311,7 @@ const _e = (e, t, n) => (e.tokens(t) || {})[n] || O(n), da = {
2323
2311
  },
2324
2312
  describe: (e, t) => e === "bold" ? { label: "Subtle ↔ Bold", value: `${Math.round(t * 100)}%` } : null
2325
2313
  };
2326
- bo((e) => da.tokens(e));
2314
+ mo((e) => la.tokens(e));
2327
2315
  const Ro = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 9l6 6 6-6"/></svg>', zo = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7.5"/></svg>';
2328
2316
  let Io = 0;
2329
2317
  function Do({ label: e, options: t, onSelect: n, placeholder: a, onOpen: o }) {
@@ -2337,56 +2325,56 @@ function Do({ label: e, options: t, onSelect: n, placeholder: a, onOpen: o }) {
2337
2325
  <span class="font-chevron">${Ro}</span>`;
2338
2326
  const l = document.createElement("div");
2339
2327
  l.className = "font-menu", l.id = r, l.setAttribute("role", "listbox"), l.setAttribute("aria-label", e), l.hidden = !0;
2340
- const d = t.map((f) => {
2341
- const v = document.createElement("div");
2342
- return v.className = "font-option", v.setAttribute("role", "option"), v.tabIndex = -1, v.dataset.value = f.value, v.innerHTML = `
2343
- <span class="font-aa" style="font-family:${f.preview}" aria-hidden="true">Aa</span>
2344
- <span class="font-text"><span class="font-name">${f.name}</span><span class="font-fonts">${f.fonts}</span></span>
2345
- <span class="font-check">${zo}</span>`, v.addEventListener("click", () => m(f.value)), v;
2328
+ const d = t.map((h) => {
2329
+ const w = document.createElement("div");
2330
+ return w.className = "font-option", w.setAttribute("role", "option"), w.tabIndex = -1, w.dataset.value = h.value, w.innerHTML = `
2331
+ <span class="font-aa" style="font-family:${h.preview}" aria-hidden="true">Aa</span>
2332
+ <span class="font-text"><span class="font-name">${h.name}</span><span class="font-fonts">${h.fonts}</span></span>
2333
+ <span class="font-check">${zo}</span>`, w.addEventListener("click", () => b(h.value)), w;
2346
2334
  });
2347
2335
  l.append(...d), s.append(i, l);
2348
- let h = null;
2349
- function u(f) {
2350
- const v = t.find(($) => $.value === f), S = v || a || t[0];
2351
- h = v ? v.value : a ? null : t[0].value, i.querySelector(".font-name").textContent = S.name, i.querySelector(".font-fonts").textContent = S.fonts, i.querySelector(".font-aa").style.fontFamily = S.preview, i.setAttribute("aria-label", `${e}: ${S.name}, ${S.fonts}`), d.forEach(($) => $.setAttribute("aria-selected", String($.dataset.value === h)));
2336
+ let p = null;
2337
+ function f(h) {
2338
+ const w = t.find(($) => $.value === h), S = w || a || t[0];
2339
+ p = w ? w.value : a ? null : t[0].value, i.querySelector(".font-name").textContent = S.name, i.querySelector(".font-fonts").textContent = S.fonts, i.querySelector(".font-aa").style.fontFamily = S.preview, i.setAttribute("aria-label", `${e}: ${S.name}, ${S.fonts}`), d.forEach(($) => $.setAttribute("aria-selected", String($.dataset.value === p)));
2352
2340
  }
2353
- function w() {
2354
- const f = i.getBoundingClientRect(), v = l.offsetHeight, $ = window.innerHeight - f.bottom - 8 >= v ? f.bottom + 4 : Math.max(8, f.top - 4 - v);
2355
- l.style.top = `${$}px`, l.style.left = `${f.left}px`, l.style.width = `${f.width}px`;
2341
+ function v() {
2342
+ const h = i.getBoundingClientRect(), w = l.offsetHeight, $ = window.innerHeight - h.bottom - 8 >= w ? h.bottom + 4 : Math.max(8, h.top - 4 - w);
2343
+ l.style.top = `${$}px`, l.style.left = `${h.left}px`, l.style.width = `${h.width}px`;
2356
2344
  }
2357
- function p() {
2358
- l.hidden && (l.hidden = !1, i.setAttribute("aria-expanded", "true"), o && o(), w(), (d.find((f) => f.dataset.value === h) || d[0]).focus(), setTimeout(() => document.addEventListener("pointerdown", x, !0)), window.addEventListener("resize", g), s.closest(".body")?.addEventListener("scroll", g, { once: !0 }));
2345
+ function u() {
2346
+ l.hidden && (l.hidden = !1, i.setAttribute("aria-expanded", "true"), o && o(), v(), (d.find((h) => h.dataset.value === p) || d[0]).focus(), setTimeout(() => document.addEventListener("pointerdown", x, !0)), window.addEventListener("resize", m), s.closest(".body")?.addEventListener("scroll", m, { once: !0 }));
2359
2347
  }
2360
- function g(f) {
2361
- l.hidden || (l.hidden = !0, i.setAttribute("aria-expanded", "false"), document.removeEventListener("pointerdown", x, !0), window.removeEventListener("resize", g), f === !0 && i.focus());
2348
+ function m(h) {
2349
+ l.hidden || (l.hidden = !0, i.setAttribute("aria-expanded", "false"), document.removeEventListener("pointerdown", x, !0), window.removeEventListener("resize", m), h === !0 && i.focus());
2362
2350
  }
2363
- function x(f) {
2364
- f.composedPath().includes(s) || g();
2351
+ function x(h) {
2352
+ h.composedPath().includes(s) || m();
2365
2353
  }
2366
- function m(f) {
2367
- f !== h && (u(f), n(f)), g(!0);
2354
+ function b(h) {
2355
+ h !== p && (f(h), n(h)), m(!0);
2368
2356
  }
2369
- return i.addEventListener("click", () => l.hidden ? p() : g(!0)), i.addEventListener("keydown", (f) => {
2370
- (f.key === "ArrowDown" || f.key === "ArrowUp") && (f.preventDefault(), p());
2371
- }), l.addEventListener("keydown", (f) => {
2372
- const v = d.indexOf(f.target);
2357
+ return i.addEventListener("click", () => l.hidden ? u() : m(!0)), i.addEventListener("keydown", (h) => {
2358
+ (h.key === "ArrowDown" || h.key === "ArrowUp") && (h.preventDefault(), u());
2359
+ }), l.addEventListener("keydown", (h) => {
2360
+ const w = d.indexOf(h.target);
2373
2361
  let S = null;
2374
- if (f.key === "ArrowDown") S = Math.min(d.length - 1, v + 1);
2375
- else if (f.key === "ArrowUp") S = Math.max(0, v - 1);
2376
- else if (f.key === "Home") S = 0;
2377
- else if (f.key === "End") S = d.length - 1;
2378
- else if (f.key === "Enter" || f.key === " ") {
2379
- f.preventDefault(), m(f.target.dataset.value);
2362
+ if (h.key === "ArrowDown") S = Math.min(d.length - 1, w + 1);
2363
+ else if (h.key === "ArrowUp") S = Math.max(0, w - 1);
2364
+ else if (h.key === "Home") S = 0;
2365
+ else if (h.key === "End") S = d.length - 1;
2366
+ else if (h.key === "Enter" || h.key === " ") {
2367
+ h.preventDefault(), b(h.target.dataset.value);
2380
2368
  return;
2381
- } else if (f.key === "Escape") {
2382
- f.preventDefault(), f.stopPropagation(), g(!0);
2369
+ } else if (h.key === "Escape") {
2370
+ h.preventDefault(), h.stopPropagation(), m(!0);
2383
2371
  return;
2384
- } else if (f.key === "Tab") {
2385
- g();
2372
+ } else if (h.key === "Tab") {
2373
+ m();
2386
2374
  return;
2387
2375
  }
2388
- S !== null && (f.preventDefault(), d[S].focus());
2389
- }), u(a ? null : t[0].value), { el: s, setValue: u };
2376
+ S !== null && (h.preventDefault(), d[S].focus());
2377
+ }), f(a ? null : t[0].value), { el: s, setValue: f };
2390
2378
  }
2391
2379
  const z = 'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif', Ke = 'Georgia, "Times New Roman", serif', ae = [
2392
2380
  { value: "neutral", name: "Neutral", fonts: "Inter · Inter", heading: `"Inter", ${z}`, body: `"Inter", ${z}`, load: ["Inter:wght@400;500;600;700"] },
@@ -2397,11 +2385,11 @@ const z = 'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-ser
2397
2385
  { value: "plex", name: "Plex", fonts: "Plex Serif · Plex Sans", heading: `"IBM Plex Serif", ${Ke}`, body: `"IBM Plex Sans", ${z}`, load: ["IBM+Plex+Serif:wght@500;600;700", "IBM+Plex+Sans:wght@400;500;600"] },
2398
2386
  { value: "elegant", name: "Elegant", fonts: "Instrument Serif · Inter", heading: `"Instrument Serif", ${Ke}`, body: `"Inter", ${z}`, load: ["Instrument+Serif", "Inter:wght@400;500;600;700"] },
2399
2387
  { value: "friendly", name: "Friendly", fonts: "Manrope · Manrope", heading: `"Manrope", ${z}`, body: `"Manrope", ${z}`, load: ["Manrope:wght@400;500;600;700"] }
2400
- ], Se = { compact: 1.125, balanced: 1.2, expressive: 1.333 }, jn = { xs: -2, sm: -1, base: 0, lg: 1, xl: 2, "2xl": 3, "3xl": 4 }, Nn = /* @__PURE__ */ new Set();
2388
+ ], Se = { compact: 1.125, balanced: 1.2, expressive: 1.333 }, jn = { xs: -2, sm: -1, base: 0, lg: 1, xl: 2, "2xl": 3, "3xl": 4 }, Fn = /* @__PURE__ */ new Set();
2401
2389
  function St(e) {
2402
- const t = e.filter((a) => !Nn.has(a));
2390
+ const t = e.filter((a) => !Fn.has(a));
2403
2391
  if (!t.length) return;
2404
- t.forEach((a) => Nn.add(a));
2392
+ t.forEach((a) => Fn.add(a));
2405
2393
  const n = document.createElement("link");
2406
2394
  n.rel = "stylesheet", n.href = `https://fonts.googleapis.com/css2?${t.map((a) => `family=${a}`).join("&")}&display=swap`, n.dataset.twiddle = "fonts", document.head.appendChild(n);
2407
2395
  }
@@ -2468,7 +2456,7 @@ const Bo = {
2468
2456
  // The weights in effect; Subtle ↔ Bold on the Character pad moves them (linked settings, rule 2).
2469
2457
  weights(e, t, { label: n = "Weights" } = {}) {
2470
2458
  const a = D(n), o = () => {
2471
- const r = t.getState(), s = O("--twd-weight-heading"), i = O("--twd-weight-strong");
2459
+ const r = t.getState(), s = L("--twd-weight-heading"), i = L("--twd-weight-strong");
2472
2460
  a.setValue(s || i ? `Headings ${s || "—"} · strong ${i || "—"}${he(r, "--twd-weight-heading") ? " · from Character" : ""}` : "");
2473
2461
  };
2474
2462
  o(), t.onChange(o), e.append(a.el);
@@ -2498,17 +2486,17 @@ const Bo = {
2498
2486
  render(e, t) {
2499
2487
  Object.entries(this.parts).filter(([n]) => !n.endsWith("Tiles")).forEach(([, n]) => n(e, t));
2500
2488
  }
2501
- }, [Rn, We] = Ft;
2489
+ }, [Nn, We] = jt;
2502
2490
  function Uo(e) {
2503
2491
  return e > 0.56 ? "Bold" : e < 0.44 ? "Subtle" : "Balanced";
2504
2492
  }
2505
2493
  function Vo(e) {
2506
2494
  return $e(e, "spacing") ? "Custom spacing" : Dt(H(e.density));
2507
2495
  }
2508
- const Ge = (e) => e && e[0].toUpperCase() + e.slice(1), zn = [
2496
+ const Ge = (e) => e && e[0].toUpperCase() + e.slice(1), Rn = [
2509
2497
  ["colour", "Colour", (e) => {
2510
2498
  const t = e.colour || {}, n = Xe.find((o) => o.primary === t.primary && o.neutral === t.neutral);
2511
- return { text: `${t.brand ? t.brand.toUpperCase() : n && !t.shade ? n.label : t.primary ? `${Ge(t.primary)}${t.neutral ? ` · ${Ge(t.neutral)}` : ""}` : "Prototype colours"}${t.mode === "dark" ? " · Dark" : ""}`, swatch: O("--twd-primary") };
2499
+ return { text: `${t.brand ? t.brand.toUpperCase() : n && !t.shade ? n.label : t.primary ? `${Ge(t.primary)}${t.neutral ? ` · ${Ge(t.neutral)}` : ""}` : "Prototype colours"}${t.mode === "dark" ? " · Dark" : ""}`, swatch: L("--twd-primary") };
2512
2500
  }],
2513
2501
  ["type", "Type", (e) => {
2514
2502
  const t = e.typography || {};
@@ -2520,17 +2508,17 @@ const Ge = (e) => e && e[0].toUpperCase() + e.slice(1), zn = [
2520
2508
  ], qo = {
2521
2509
  summary(e, t, { label: n = "Current look", goTab: a } = {}) {
2522
2510
  const o = D(n), r = document.createElement("div");
2523
- r.className = "summary", zn.forEach(([i, l]) => {
2511
+ r.className = "summary", Rn.forEach(([i, l]) => {
2524
2512
  const d = document.createElement("button");
2525
- d.type = "button", d.className = "summary-row", d.dataset.summary = i, d.innerHTML = `<span class="summary-name"></span><span class="summary-swatch" hidden></span><span class="summary-value"></span><span class="chev" aria-hidden="true">${A.chevron}</span>`, d.querySelector(".summary-name").textContent = l, d.addEventListener("click", () => a && a(i)), r.append(d);
2513
+ d.type = "button", d.className = "summary-row", d.dataset.summary = i, d.innerHTML = `<span class="summary-name"></span><span class="summary-swatch" hidden></span><span class="summary-value"></span><span class="chev" aria-hidden="true">${P.chevron}</span>`, d.querySelector(".summary-name").textContent = l, d.addEventListener("click", () => a && a(i)), r.append(d);
2526
2514
  }), o.append(r);
2527
2515
  const s = () => {
2528
2516
  const i = t.getState();
2529
- zn.forEach(([l, , d]) => {
2530
- const h = r.querySelector(`[data-summary="${l}"]`), u = d(i);
2531
- h.querySelector(".summary-value").textContent = u.text;
2532
- const w = h.querySelector(".summary-swatch");
2533
- w.hidden = !u.swatch, u.swatch && (w.style.background = u.swatch);
2517
+ Rn.forEach(([l, , d]) => {
2518
+ const p = r.querySelector(`[data-summary="${l}"]`), f = d(i);
2519
+ p.querySelector(".summary-value").textContent = f.text;
2520
+ const v = p.querySelector(".summary-swatch");
2521
+ v.hidden = !f.swatch, f.swatch && (v.style.background = f.swatch);
2534
2522
  });
2535
2523
  };
2536
2524
  s(), t.onChange(s), e.append(o.el);
@@ -2540,7 +2528,7 @@ const Ge = (e) => e && e[0].toUpperCase() + e.slice(1), zn = [
2540
2528
  label: n,
2541
2529
  ends: { top: "Spacious", bottom: "Compact", left: "Subtle", right: "Bold" },
2542
2530
  onInput: (s, i) => {
2543
- const l = +(We - i * (We - Rn)).toFixed(3), d = +s.toFixed(3);
2531
+ const l = +(We - i * (We - Nn)).toFixed(3), d = +s.toFixed(3);
2544
2532
  t.setSections({
2545
2533
  density: { factor: l === 1 ? null : l, spacing: null },
2546
2534
  character: { bold: d === 0.5 ? null : d }
@@ -2549,8 +2537,8 @@ const Ge = (e) => e && e[0].toUpperCase() + e.slice(1), zn = [
2549
2537
  });
2550
2538
  a.append(o.el);
2551
2539
  const r = () => {
2552
- const s = t.getState(), i = H(s.density), l = Bt(s.character), d = l === null ? 0.5 : l, h = `${Vo(s)} · ${Uo(d)}`;
2553
- o.setValue(d, (We - i) / (We - Rn), h), a.setValue(h);
2540
+ const s = t.getState(), i = H(s.density), l = Bt(s.character), d = l === null ? 0.5 : l, p = `${Vo(s)} · ${Uo(d)}`;
2541
+ o.setValue(d, (We - i) / (We - Nn), p), a.setValue(p);
2554
2542
  };
2555
2543
  r(), t.onChange(r), e.append(a.el);
2556
2544
  }
@@ -2572,43 +2560,43 @@ function Ko(e, t, n) {
2572
2560
  <label class="token-value role-fixed" hidden><input type="text" inputmode="decimal" spellcheck="false" aria-label="${t.label}, fixed value"><span class="token-unit">px</span></label>
2573
2561
  <span class="step-select">
2574
2562
  <select aria-label="${t.label}"></select>
2575
- <span class="step-chevron" aria-hidden="true">${A.down}</span>
2563
+ <span class="step-chevron" aria-hidden="true">${P.down}</span>
2576
2564
  </span>
2577
- <button class="icon-btn token-reset" title="Back to the default" aria-label="Reset ${t.label}" hidden>${A.reset}</button>
2565
+ <button class="icon-btn token-reset" title="Back to the default" aria-label="Reset ${t.label}" hidden>${P.reset}</button>
2578
2566
  `;
2579
- const r = o.querySelector("select"), s = o.querySelector(".role-fixed"), i = s.querySelector("input"), l = o.querySelector(".token-reset"), d = () => (e.getState().custom || {})[t.key], h = () => {
2567
+ const r = o.querySelector("select"), s = o.querySelector(".role-fixed"), i = s.querySelector("input"), l = o.querySelector(".token-reset"), d = () => (e.getState().custom || {})[t.key], p = () => {
2580
2568
  const x = d();
2581
- if (x == null) return t.step ? { step: t.step } : { fixed: O(a) };
2582
- const m = _o.exec(x);
2583
- return m ? { step: +m[1] } : { fixed: x };
2584
- }, u = (x) => e.setSection("custom", { [t.key]: x }), w = (x) => t.step ? x === `var(--twd-space-${t.step})` : !1;
2569
+ if (x == null) return t.step ? { step: t.step } : { fixed: L(a) };
2570
+ const b = _o.exec(x);
2571
+ return b ? { step: +b[1] } : { fixed: x };
2572
+ }, f = (x) => e.setSection("custom", { [t.key]: x }), v = (x) => t.step ? x === `var(--twd-space-${t.step})` : !1;
2585
2573
  r.addEventListener("change", () => {
2586
2574
  if (r.value === "fixed") {
2587
- const m = Et(O(a));
2588
- u(m != null ? `${m}px` : O(a)), i.focus(), i.select();
2575
+ const b = Et(L(a));
2576
+ f(b != null ? `${b}px` : L(a)), i.focus(), i.select();
2589
2577
  return;
2590
2578
  }
2591
2579
  const x = `var(--twd-space-${r.value})`;
2592
- u(w(x) ? null : x);
2580
+ f(v(x) ? null : x);
2593
2581
  });
2594
- const p = () => {
2582
+ const u = () => {
2595
2583
  const x = i.value.trim();
2596
- if (!x) return u(null);
2597
- u(/^-?\d*\.?\d+$/.test(x) ? `${x}px` : x);
2584
+ if (!x) return f(null);
2585
+ f(/^-?\d*\.?\d+$/.test(x) ? `${x}px` : x);
2598
2586
  };
2599
- i.addEventListener("change", p), i.addEventListener("blur", () => g()), i.addEventListener("keydown", (x) => {
2600
- x.key === "Enter" && (x.preventDefault(), i.blur()), x.key === "Escape" && (x.stopPropagation(), g(), i.blur());
2601
- }), l.addEventListener("click", () => u(null));
2602
- function g() {
2603
- const x = h();
2604
- if (r.innerHTML = Ho.map((f) => `<option value="${f}">space-${f} · ${Et(O(`--twd-space-${f}`)) ?? "?"}</option>`).join("") + '<option value="fixed">Fixed</option>', r.value = x.step ? String(x.step) : "fixed", s.hidden = !x.fixed, o.classList.toggle("is-fixed", !!x.fixed), x.fixed && o.getRootNode().activeElement !== i) {
2605
- const f = Et(x.fixed);
2606
- i.value = f != null ? String(f) : x.fixed;
2587
+ i.addEventListener("change", u), i.addEventListener("blur", () => m()), i.addEventListener("keydown", (x) => {
2588
+ x.key === "Enter" && (x.preventDefault(), i.blur()), x.key === "Escape" && (x.stopPropagation(), m(), i.blur());
2589
+ }), l.addEventListener("click", () => f(null));
2590
+ function m() {
2591
+ const x = p();
2592
+ if (r.innerHTML = Ho.map((h) => `<option value="${h}">space-${h} · ${Et(L(`--twd-space-${h}`)) ?? "?"}</option>`).join("") + '<option value="fixed">Fixed</option>', r.value = x.step ? String(x.step) : "fixed", s.hidden = !x.fixed, o.classList.toggle("is-fixed", !!x.fixed), x.fixed && o.getRootNode().activeElement !== i) {
2593
+ const h = Et(x.fixed);
2594
+ i.value = h != null ? String(h) : x.fixed;
2607
2595
  }
2608
- const m = d() != null;
2609
- o.classList.toggle("edited", m), l.hidden = !m;
2596
+ const b = d() != null;
2597
+ o.classList.toggle("edited", b), l.hidden = !b;
2610
2598
  }
2611
- return g(), e.onChange(g), o;
2599
+ return m(), e.onChange(m), o;
2612
2600
  }
2613
2601
  const Wo = {
2614
2602
  spacing(e, t, { label: n = "Roles" } = {}) {
@@ -2646,17 +2634,21 @@ const Wo = {
2646
2634
  { more: "Spacing tokens", parts: [["custom", "spacing"]] }
2647
2635
  ] },
2648
2636
  { id: "shape", title: "Shape", icon: "tabShape", parts: [
2649
- // Figma: "Shape — with styles" (257:711), agreed 2026-10-15
2650
- { heading: "Buttons" },
2651
- ["buttons", "styleTiles", { label: "Style" }],
2652
- ["buttons", "cornerTiles", { label: "Corners" }],
2653
- ["buttons", "sizeTiles", { label: "Size" }],
2654
- { heading: "Cards" },
2655
- ["cards", "styleTiles", { label: "Style" }],
2656
- ["cards", "cornerTiles", { label: "Corners" }],
2657
- ["cards", "fillTiles", { label: "Fill" }],
2658
- // Ravi, 2026-10-16
2659
- ["cards", "borderTiles", { label: "Borders" }],
2637
+ // Shape pass (Ravi, 2026-10-16; Figma 281:1158 / 281:1421): one group at a
2638
+ // time, so the tab fits without scrolling. Buttons & Inputs: corners and size
2639
+ // also change inputs and chips (shared control tokens).
2640
+ { tabs: [
2641
+ { label: "Buttons & Inputs", parts: [
2642
+ ["buttons", "styleTiles", { label: "Style" }],
2643
+ ["buttons", "cornerTiles", { label: "Corners" }],
2644
+ ["buttons", "sizeTiles", { label: "Size" }]
2645
+ ] },
2646
+ { label: "Cards", parts: [
2647
+ ["cards", "styleTiles", { label: "Style" }],
2648
+ ["cards", "cornerTiles", { label: "Corners" }],
2649
+ ["cards", "borderTiles", { label: "Borders" }]
2650
+ ] }
2651
+ ] },
2660
2652
  { more: "Shape tokens", parts: [["custom", "buttonStyle"], ["custom", "cardStyle"], ["custom", "cardShadow"], ["custom", "corners"], ["custom", "controls"], ["custom", "borders"]] }
2661
2653
  ] },
2662
2654
  { id: "shadows", title: "Shadows", icon: "tabShadows", parts: [
@@ -2664,7 +2656,7 @@ const Wo = {
2664
2656
  ["depth", "intensity"],
2665
2657
  { more: "Shadow tokens", parts: [["custom", "shadows"]] }
2666
2658
  ] }
2667
- ], j = (e) => String(e).replace(/[&<>"]/g, (t) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;" })[t]);
2659
+ ], F = (e) => String(e).replace(/[&<>"]/g, (t) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;" })[t]);
2668
2660
  function Go({ sections: e, store: t, view: n }) {
2669
2661
  const a = document.createElement("div");
2670
2662
  a.id = "twiddle-root", document.body.appendChild(a);
@@ -2675,13 +2667,13 @@ function Go({ sections: e, store: t, view: n }) {
2675
2667
  <div class="wrap">
2676
2668
  <div class="toast" role="status"></div>
2677
2669
  <section class="side" aria-label="Changes" hidden>
2678
- <div class="side-head"><span>Changes</span><button class="icon-btn" data-action="changes-close" title="Close Changes" aria-label="Close Changes">${A.close}</button></div>
2670
+ <div class="side-head"><span>Changes</span><button class="icon-btn" data-action="changes-close" title="Close Changes" aria-label="Close Changes">${P.close}</button></div>
2679
2671
  <div class="body" data-view="changes"></div>
2680
2672
  </section>
2681
2673
  <div class="panel" role="dialog" aria-label="Panel" hidden>
2682
2674
  <nav class="tabbar" aria-label="Areas">
2683
- ${te.map((c) => `<button class="tab" data-tab="${c.id}" title="${c.title}" aria-pressed="false">${A[c.icon]}<span>${c.title}</span></button>`).join("")}
2684
- <button class="icon-btn tab-min" data-action="minimise" title="Minimise to the tabs" aria-label="Minimise to the tabs">${A.minimise}</button>
2675
+ ${te.map((c) => `<button class="tab" data-tab="${c.id}" title="${c.title}" aria-pressed="false">${P[c.icon]}<span>${c.title}</span></button>`).join("")}
2676
+ <button class="icon-btn tab-min" data-action="minimise" title="Minimise to the tabs" aria-label="Minimise to the tabs">${P.minimise}</button>
2685
2677
  </nav>
2686
2678
  <div class="original-pill" hidden>Showing original</div>
2687
2679
  <div class="body" data-view="global"><div class="setup-hint" role="status" hidden></div>
@@ -2690,19 +2682,19 @@ function Go({ sections: e, store: t, view: n }) {
2690
2682
  <div class="body" data-view="local" hidden></div>
2691
2683
  <!-- One footer row with every action (Ravi, 2026-10-16); the launcher closes the panel. -->
2692
2684
  <div class="actions">
2693
- <button class="icon-btn" data-action="undo" title="Undo (⌘Z)" aria-label="Undo">${A.undo}</button>
2694
- <button class="icon-btn" data-action="redo" title="Redo (⇧⌘Z)" aria-label="Redo">${A.redo}</button>
2685
+ <button class="icon-btn" data-action="undo" title="Undo (⌘Z)" aria-label="Undo">${P.undo}</button>
2686
+ <button class="icon-btn" data-action="redo" title="Redo (⇧⌘Z)" aria-label="Redo">${P.redo}</button>
2695
2687
  <span class="sep" aria-hidden="true"></span>
2696
- <button class="icon-btn" data-action="pick" title="Pick an element to tweak on its own" aria-label="Pick an element" aria-pressed="false">${A.pick}</button>
2697
- <button class="icon-btn" data-action="compare" title="Hold to see the original (Alt+C toggles)" aria-label="Compare with original" aria-pressed="false">${A.compare}</button>
2698
- <button class="icon-btn" data-action="copy" title="Copy link to this version" aria-label="Copy link">${A.link}</button>
2699
- <button class="icon-btn" data-action="reset" title="Reset to defaults" aria-label="Reset">${A.reset}</button>
2688
+ <button class="icon-btn" data-action="pick" title="Pick an element to tweak on its own" aria-label="Pick an element" aria-pressed="false">${P.pick}</button>
2689
+ <button class="icon-btn" data-action="compare" title="Hold to see the original (Alt+C toggles)" aria-label="Compare with original" aria-pressed="false">${P.compare}</button>
2690
+ <button class="icon-btn" data-action="copy" title="Copy link to this version" aria-label="Copy link">${P.link}</button>
2691
+ <button class="icon-btn" data-action="reset" title="Reset to defaults" aria-label="Reset">${P.reset}</button>
2700
2692
  <span class="sep" aria-hidden="true"></span>
2701
2693
  <button class="changes-btn" data-action="changes" title="Changes" aria-label="Changes" aria-pressed="false"><span class="badge">0</span></button>
2702
2694
  <span class="spacer"></span>
2703
2695
  <div class="apply">
2704
2696
  <button class="apply-btn" data-action="apply" title="Copy these tweaks as a prompt for your coding agent">Copy<span class="wide"> prompt</span></button>
2705
- <button class="apply-menu-btn" data-action="apply-menu" aria-label="Copy prompt options" aria-haspopup="true" aria-expanded="false">${A.down}</button>
2697
+ <button class="apply-menu-btn" data-action="apply-menu" aria-label="Copy prompt options" aria-haspopup="true" aria-expanded="false">${P.down}</button>
2706
2698
  <div class="menu apply-menu" role="menu" hidden>
2707
2699
  <button role="menuitemradio" data-apply-mode="preview">Preview before copying</button>
2708
2700
  <button role="menuitemradio" data-apply-mode="copy">Copy without preview</button>
@@ -2710,13 +2702,13 @@ function Go({ sections: e, store: t, view: n }) {
2710
2702
  </div>
2711
2703
  </div>
2712
2704
  </div>
2713
- <button class="launcher" aria-label="Open Panel" aria-expanded="false" title="Panel · drag to move, double-click to reset">${A.panelMark}</button>
2705
+ <button class="launcher" aria-label="Open Panel" aria-expanded="false" title="Panel · drag to move, double-click to reset">${P.panelMark}</button>
2714
2706
  </div>
2715
2707
  <div class="dialog-backdrop" hidden>
2716
2708
  <div class="dialog" role="dialog" aria-modal="true" aria-labelledby="twd-dialog-title">
2717
2709
  <div class="dialog-head">
2718
2710
  <span id="twd-dialog-title">Prompt for your agent</span>
2719
- <button class="icon-btn" data-action="dialog-close" aria-label="Close">${A.close}</button>
2711
+ <button class="icon-btn" data-action="dialog-close" aria-label="Close">${P.close}</button>
2720
2712
  </div>
2721
2713
  <textarea class="prompt-text" readonly spellcheck="false" aria-label="Generated prompt"></textarea>
2722
2714
  <div class="dialog-foot">
@@ -2726,142 +2718,142 @@ function Go({ sections: e, store: t, view: n }) {
2726
2718
  </div>
2727
2719
  </div>
2728
2720
  `;
2729
- const r = (c) => o.querySelector(c), s = r(".panel"), i = r(".launcher"), l = r(".toast"), d = { global: r('[data-view="global"]'), local: r('[data-view="local"]'), changes: r('[data-view="changes"]') }, h = r(".pick-box"), u = r(".pick-tag"), w = { getState: t.getState, setSection: t.setSection, setSections: t.setSections, onChange: t.onChange }, p = Object.fromEntries(e.map((c) => [c.id, c]));
2730
- function g(c, b, y = w) {
2731
- const M = y !== w;
2732
- b.forEach((k) => {
2721
+ const r = (c) => o.querySelector(c), s = r(".panel"), i = r(".launcher"), l = r(".toast"), d = { global: r('[data-view="global"]'), local: r('[data-view="local"]'), changes: r('[data-view="changes"]') }, p = r(".pick-box"), f = r(".pick-tag"), v = { getState: t.getState, setSection: t.setSection, setSections: t.setSections, onChange: t.onChange }, u = Object.fromEntries(e.map((c) => [c.id, c]));
2722
+ function m(c, g, y = v) {
2723
+ const C = y !== v;
2724
+ g.forEach((k) => {
2733
2725
  if (k === "warnings") {
2734
- if (M) return;
2735
- const F = document.createElement("div");
2736
- F.className = "warnings page-warnings", c.append(F);
2726
+ if (C) return;
2727
+ const j = document.createElement("div");
2728
+ j.className = "warnings page-warnings", c.append(j);
2737
2729
  return;
2738
2730
  }
2739
2731
  if (k.heading) {
2740
- const F = document.createElement("div");
2741
- F.className = "page-heading", F.innerHTML = `<span></span>${k.note ? '<span class="muted"></span>' : ""}`, F.firstChild.textContent = k.heading, k.note && (F.lastChild.textContent = k.note), c.append(F);
2732
+ const j = document.createElement("div");
2733
+ j.className = "page-heading", j.innerHTML = `<span></span>${k.note ? '<span class="muted"></span>' : ""}`, j.firstChild.textContent = k.heading, k.note && (j.lastChild.textContent = k.note), c.append(j);
2742
2734
  return;
2743
2735
  }
2744
2736
  if (k.more) {
2745
- const F = document.createElement("details");
2746
- F.className = "more", F.innerHTML = `<summary><span class="chev" aria-hidden="true">${A.chevron}</span><span></span></summary><div class="more-body"></div>`, F.querySelector("summary span:last-child").textContent = k.more, g(F.querySelector(".more-body"), k.parts, y), c.append(F);
2737
+ const j = document.createElement("details");
2738
+ j.className = "more", j.innerHTML = `<summary><span class="chev" aria-hidden="true">${P.chevron}</span><span></span></summary><div class="more-body"></div>`, j.querySelector("summary span:last-child").textContent = k.more, m(j.querySelector(".more-body"), k.parts, y), c.append(j);
2747
2739
  return;
2748
2740
  }
2749
2741
  if (k.tabs) {
2750
- const F = k.tabs.map((W) => {
2742
+ const j = k.tabs.map((W) => {
2751
2743
  const q = document.createElement("div");
2752
- return q.className = "tab-pane", g(q, W.parts, y), q;
2753
- }), lt = ge({
2744
+ return q.className = "tab-pane", m(q, W.parts, y), q;
2745
+ }), dt = ge({
2754
2746
  label: "View",
2755
2747
  options: k.tabs.map((W, q) => ({ value: String(q), label: W.label })),
2756
2748
  onSelect: (W) => {
2757
- lt.setValue(W), F.forEach((q, va) => {
2749
+ dt.setValue(W), j.forEach((q, va) => {
2758
2750
  q.hidden = String(va) !== W;
2759
2751
  });
2760
2752
  }
2761
2753
  });
2762
- lt.setValue("0"), F.forEach((W, q) => {
2754
+ dt.setValue("0"), j.forEach((W, q) => {
2763
2755
  W.hidden = q !== 0;
2764
- }), c.append(lt.el, ...F);
2756
+ }), c.append(dt.el, ...j);
2765
2757
  return;
2766
2758
  }
2767
- const [T, U, P = {}] = k, ye = T === "simple" ? qo[U] : T === "roles" ? Wo[U] : p[T]?.parts?.[U];
2768
- ye && ye(c, y, { ...P, buttons: p.buttons, cards: p.cards, goTab: (F) => {
2769
- Ae(Ut()), v(F);
2759
+ const [T, U, O = {}] = k, ye = T === "simple" ? qo[U] : T === "roles" ? Wo[U] : u[T]?.parts?.[U];
2760
+ ye && ye(c, y, { ...O, buttons: u.buttons, cards: u.cards, goTab: (j) => {
2761
+ Ae(Ut()), w(j);
2770
2762
  } });
2771
2763
  });
2772
2764
  }
2773
- te.forEach((c) => g(d.global.querySelector(`[data-page="${c.id}"]`), c.parts));
2765
+ te.forEach((c) => m(d.global.querySelector(`[data-page="${c.id}"]`), c.parts));
2774
2766
  const x = [...o.querySelectorAll(".tab")];
2775
- let m = te.some((c) => c.id === ne("tab")) ? ne("tab") : te[0].id;
2776
- function f() {
2777
- x.forEach((c) => c.setAttribute("aria-pressed", String(c.dataset.tab === m)));
2767
+ let b = te.some((c) => c.id === ne("tab")) ? ne("tab") : te[0].id;
2768
+ function h() {
2769
+ x.forEach((c) => c.setAttribute("aria-pressed", String(c.dataset.tab === b)));
2778
2770
  }
2779
- function v(c) {
2780
- m = c, ce("tab", c), [d.global, d.local].forEach((b) => {
2781
- b.querySelectorAll(".page").forEach((y) => {
2771
+ function w(c) {
2772
+ b = c, ce("tab", c), [d.global, d.local].forEach((g) => {
2773
+ g.querySelectorAll(".page").forEach((y) => {
2782
2774
  y.hidden = y.dataset.page !== c;
2783
- }), b.scrollTop = 0;
2784
- }), f();
2775
+ }), g.scrollTop = 0;
2776
+ }), h();
2785
2777
  }
2786
- const S = (c) => c.map((b) => `<div class="warning">${A.warn}<span>${j(b.text)}</span></div>`).join(""), $ = r(".side");
2778
+ const S = (c) => c.map((g) => `<div class="warning">${P.warn}<span>${F(g.text)}</span></div>`).join(""), $ = r(".side");
2787
2779
  let K = !1;
2788
2780
  function Z(c) {
2789
2781
  K = c && !s.hidden, $.hidden = !K, r('[data-action="changes"]').setAttribute("aria-pressed", String(K)), K && rn();
2790
2782
  }
2791
2783
  let Le = "global";
2792
- const Ut = () => C ? "local" : "global";
2784
+ const Ut = () => E ? "local" : "global";
2793
2785
  function Ae(c) {
2794
- Le = c, Object.entries(d).forEach(([b, y]) => {
2795
- y.hidden = b !== c;
2796
- }), f();
2786
+ Le = c, Object.entries(d).forEach(([g, y]) => {
2787
+ y.hidden = g !== c;
2788
+ }), h();
2797
2789
  }
2798
- v(m);
2799
- const et = "cubic-bezier(0.3, 0.7, 0.2, 1)", tt = "cubic-bezier(0.2, 0.8, 0.2, 1)", Oe = 640, be = 100, nt = 50, ca = () => i.querySelector(".mark-knob"), pa = () => [i.querySelector(".mark-t1"), i.querySelector(".mark-t2")];
2790
+ w(b);
2791
+ const et = "cubic-bezier(0.3, 0.7, 0.2, 1)", tt = "cubic-bezier(0.2, 0.8, 0.2, 1)", Pe = 640, me = 100, nt = 50, da = () => i.querySelector(".mark-knob"), ca = () => [i.querySelector(".mark-t1"), i.querySelector(".mark-t2")];
2800
2792
  function Vt(c) {
2801
2793
  if (matchMedia("(prefers-reduced-motion: reduce)").matches || !i.animate) return;
2802
- const b = ca(), [y, M] = pa(), k = (T) => `translateY(${T}px)`;
2794
+ const g = da(), [y, C] = ca(), k = (T) => `translateY(${T}px)`;
2803
2795
  if (c) {
2804
- b.animate([{ transform: k(32) }, { transform: k(-6), offset: 0.78 }, { transform: k(0) }], { duration: Oe, easing: et });
2796
+ g.animate([{ transform: k(32) }, { transform: k(-6), offset: 0.78 }, { transform: k(0) }], { duration: Pe, easing: et });
2805
2797
  const T = [{ transform: "scale(0.4)", opacity: 0 }, { transform: "scale(1)", opacity: 1 }];
2806
- M.animate(T, { duration: be * 2, delay: Oe * 0.12, easing: et, fill: "backwards" }), y.animate(T, { duration: be * 2, delay: Oe * 0.32 + nt, easing: et, fill: "backwards" });
2798
+ C.animate(T, { duration: me * 2, delay: Pe * 0.12, easing: et, fill: "backwards" }), y.animate(T, { duration: me * 2, delay: Pe * 0.32 + nt, easing: et, fill: "backwards" });
2807
2799
  } else {
2808
2800
  const T = [{ opacity: 1 }, { opacity: 0 }];
2809
- y.animate(T, { duration: be, easing: tt }), M.animate(T, { duration: be, delay: nt / 2, easing: tt, fill: "backwards" }), b.animate([{ transform: k(0) }, { transform: k(34), offset: 0.8 }, { transform: k(32) }], { duration: Oe * 0.7, delay: be + nt / 2, easing: tt, fill: "backwards" });
2801
+ y.animate(T, { duration: me, easing: tt }), C.animate(T, { duration: me, delay: nt / 2, easing: tt, fill: "backwards" }), g.animate([{ transform: k(0) }, { transform: k(34), offset: 0.8 }, { transform: k(32) }], { duration: Pe * 0.7, delay: me + nt / 2, easing: tt, fill: "backwards" });
2810
2802
  }
2811
2803
  }
2812
- const Pe = r(".wrap"), qt = Va({ wrapEl: Pe, launcherEl: i });
2804
+ const Oe = r(".wrap"), qt = Va({ wrapEl: Oe, launcherEl: i });
2813
2805
  let at = !1;
2814
- function me(c) {
2815
- at = c, s.classList.toggle("minimised", c), c && Z(!1), Pe.classList.toggle("is-min", c);
2816
- const b = r('[data-action="minimise"]');
2817
- b.title = c ? "Expand the panel" : "Minimise to the tabs", b.setAttribute("aria-label", b.title), s.hidden || ce("panel", c ? "tabs" : "open");
2806
+ function be(c) {
2807
+ at = c, s.classList.toggle("minimised", c), c && Z(!1), Oe.classList.toggle("is-min", c);
2808
+ const g = r('[data-action="minimise"]');
2809
+ g.title = c ? "Expand the panel" : "Minimise to the tabs", g.setAttribute("aria-label", g.title), s.hidden || ce("panel", c ? "tabs" : "open");
2818
2810
  }
2819
2811
  function J({ animate: c = !0 } = {}) {
2820
- s.hidden && c && Vt(!0), s.hidden = !1, Pe.classList.add("is-open"), i.setAttribute("aria-expanded", "true"), i.setAttribute("aria-label", "Close Panel"), me(!1);
2812
+ s.hidden && c && Vt(!0), s.hidden = !1, Oe.classList.add("is-open"), i.setAttribute("aria-expanded", "true"), i.setAttribute("aria-label", "Close Panel"), be(!1);
2821
2813
  }
2822
- function ua() {
2823
- s.hidden && J(), me(!0);
2814
+ function pa() {
2815
+ s.hidden && J(), be(!0);
2824
2816
  }
2825
2817
  function ot() {
2826
- s.hidden || Vt(!1), s.hidden = !0, Pe.classList.remove("is-open", "is-min"), Z(!1), i.setAttribute("aria-expanded", "false"), i.setAttribute("aria-label", "Open Panel"), ce("panel", "closed"), Re();
2818
+ s.hidden || Vt(!1), s.hidden = !0, Oe.classList.remove("is-open", "is-min"), Z(!1), i.setAttribute("aria-expanded", "false"), i.setAttribute("aria-label", "Open Panel"), ce("panel", "closed"), Re();
2827
2819
  }
2828
- function Fe() {
2820
+ function je() {
2829
2821
  s.hidden ? J() : ot();
2830
2822
  }
2831
2823
  let Ht;
2832
2824
  function V(c) {
2833
2825
  l.textContent = c, l.classList.add("show"), clearTimeout(Ht), Ht = setTimeout(() => l.classList.remove("show"), 1600);
2834
2826
  }
2835
- function xe(c, b) {
2836
- navigator.clipboard.writeText(c).then(() => V(b)).catch(() => V("Couldn’t copy — select the text and copy it instead"));
2827
+ function xe(c, g) {
2828
+ navigator.clipboard.writeText(c).then(() => V(g)).catch(() => V("Couldn’t copy — select the text and copy it instead"));
2837
2829
  }
2838
2830
  let rt = null;
2839
- function se(c, b) {
2831
+ function se(c, g) {
2840
2832
  if (rt = c, !c) {
2841
- h.hidden = !0;
2833
+ p.hidden = !0;
2842
2834
  return;
2843
2835
  }
2844
2836
  const y = c.getBoundingClientRect();
2845
- Object.assign(h.style, { top: `${y.top}px`, left: `${y.left}px`, width: `${y.width}px`, height: `${y.height}px` }), u.textContent = b || Pt(c), h.hidden = !1;
2837
+ Object.assign(p.style, { top: `${y.top}px`, left: `${y.left}px`, width: `${y.width}px`, height: `${y.height}px` }), f.textContent = g || Ot(c), p.hidden = !1;
2846
2838
  }
2847
2839
  const _t = () => {
2848
- rt && !h.hidden && se(rt, u.textContent);
2840
+ rt && !p.hidden && se(rt, f.textContent);
2849
2841
  };
2850
2842
  window.addEventListener("scroll", _t, !0), window.addEventListener("resize", _t);
2851
2843
  let ie = !1;
2852
- const je = r('[data-action="pick"]'), Kt = (c) => c.composedPath().includes(a);
2844
+ const Fe = r('[data-action="pick"]'), Kt = (c) => c.composedPath().includes(a);
2853
2845
  function Wt(c) {
2854
2846
  if (Kt(c)) return;
2855
- const b = c.target;
2856
- b && b.nodeType === 1 && b !== document.documentElement && b !== document.body && se(b);
2847
+ const g = c.target;
2848
+ g && g.nodeType === 1 && g !== document.documentElement && g !== document.body && se(g);
2857
2849
  }
2858
2850
  function Gt(c) {
2859
2851
  if (Kt(c) || (c.preventDefault(), c.stopPropagation(), c.type !== "click")) return;
2860
- const b = c.target;
2861
- !b || b === document.documentElement || b === document.body || (Re(), Jt(b));
2852
+ const g = c.target;
2853
+ !g || g === document.documentElement || g === document.body || (Re(), Jt(g));
2862
2854
  }
2863
2855
  function Yt(c) {
2864
- c.key === "Escape" && (c.preventDefault(), Re(), C && se(C.el), Ne());
2856
+ c.key === "Escape" && (c.preventDefault(), Re(), E && se(E.el), Ne());
2865
2857
  }
2866
2858
  const Xt = ["pointerdown", "mousedown", "mouseup", "click"];
2867
2859
  function Zt() {
@@ -2870,87 +2862,87 @@ function Go({ sections: e, store: t, view: n }) {
2870
2862
  const c = document.createElement("style");
2871
2863
  c.id = "twiddle-picking", c.textContent = "html.twd-picking, html.twd-picking * { cursor: crosshair !important; }", document.head.appendChild(c);
2872
2864
  }
2873
- J(), je.setAttribute("aria-pressed", "true"), document.documentElement.classList.add("twd-picking"), document.addEventListener("pointermove", Wt, !0), Xt.forEach((c) => document.addEventListener(c, Gt, !0)), document.addEventListener("keydown", Yt, !0), V("Click an element · Esc to cancel");
2865
+ J(), Fe.setAttribute("aria-pressed", "true"), document.documentElement.classList.add("twd-picking"), document.addEventListener("pointermove", Wt, !0), Xt.forEach((c) => document.addEventListener(c, Gt, !0)), document.addEventListener("keydown", Yt, !0), V("Click an element · Esc to cancel");
2874
2866
  }
2875
2867
  }
2876
2868
  function Ne() {
2877
- const c = ie || !!C;
2878
- je.setAttribute("aria-pressed", String(c));
2879
- const b = c ? "Leave selection mode" : "Pick an element to tweak on its own";
2880
- je.title = b, je.setAttribute("aria-label", c ? "Leave selection mode" : "Pick an element");
2869
+ const c = ie || !!E;
2870
+ Fe.setAttribute("aria-pressed", String(c));
2871
+ const g = c ? "Leave selection mode" : "Pick an element to tweak on its own";
2872
+ Fe.title = g, Fe.setAttribute("aria-label", c ? "Leave selection mode" : "Pick an element");
2881
2873
  }
2882
2874
  function Re() {
2883
- ie && (ie = !1, Ne(), document.documentElement.classList.remove("twd-picking"), document.removeEventListener("pointermove", Wt, !0), Xt.forEach((c) => document.removeEventListener(c, Gt, !0)), document.removeEventListener("keydown", Yt, !0), se(C ? C.el : null));
2875
+ ie && (ie = !1, Ne(), document.documentElement.classList.remove("twd-picking"), document.removeEventListener("pointermove", Wt, !0), Xt.forEach((c) => document.removeEventListener(c, Gt, !0)), document.removeEventListener("keydown", Yt, !0), se(E ? E.el : null));
2884
2876
  }
2885
- let C = null;
2886
- function ha(c, b) {
2877
+ let E = null;
2878
+ function ua(c, g) {
2887
2879
  const y = [];
2888
2880
  return {
2889
2881
  ctx: {
2890
2882
  getState: () => (t.getState().scopes || {})[c] || {},
2891
- setSection: (M, k) => t.setScope(c, M, k),
2892
- setSections: (M, k) => t.setScopeSections(c, M, k),
2893
- onChange: (M) => {
2894
- const k = t.onChange(M);
2883
+ setSection: (C, k) => t.setScope(c, C, k),
2884
+ setSections: (C, k) => t.setScopeSections(c, C, k),
2885
+ onChange: (C) => {
2886
+ const k = t.onChange(C);
2895
2887
  return y.push(k), k;
2896
2888
  },
2897
- readToken: (M) => getComputedStyle(b).getPropertyValue(M).trim()
2889
+ readToken: (C) => getComputedStyle(g).getPropertyValue(C).trim()
2898
2890
  },
2899
- dispose: () => y.forEach((M) => M())
2891
+ dispose: () => y.forEach((C) => C())
2900
2892
  };
2901
2893
  }
2902
- function Jt(c, b) {
2903
- const y = Ga(c), M = t.getState().scopes || {};
2904
- b || (b = !M[y.elementSelector] && y.classSelector && M[y.classSelector] ? "class" : "element"), C && C.dispose(), C = { el: c, info: y, target: b, dispose: () => {
2905
- } }, st(), Ae("local"), J(), se(c), Ne();
2894
+ function Jt(c, g) {
2895
+ const y = Ga(c), C = t.getState().scopes || {};
2896
+ g || (g = !C[y.elementSelector] && y.classSelector && C[y.classSelector] ? "class" : "element"), E && E.dispose(), E = { el: c, info: y, target: g, dispose: () => {
2897
+ } }, st(), Ae("local"), J(), se(c), Ne(), lt();
2906
2898
  }
2907
- const Qt = () => C.target === "class" ? C.info.classSelector : C.info.elementSelector;
2899
+ const Qt = () => E.target === "class" ? E.info.classSelector : E.info.elementSelector;
2908
2900
  function st() {
2909
- C.dispose();
2910
- const { info: c } = C, b = d.local;
2911
- if (b.innerHTML = `
2901
+ E.dispose();
2902
+ const { info: c } = E, g = d.local;
2903
+ if (g.innerHTML = `
2912
2904
  <div class="scope-bar">
2913
2905
  <div class="scope-head">
2914
- <button class="icon-btn" data-action="back" title="Leave selection mode" aria-label="Leave selection mode">${A.back}</button>
2906
+ <button class="icon-btn" data-action="back" title="Leave selection mode" aria-label="Leave selection mode">${P.back}</button>
2915
2907
  <div class="scope-name">
2916
- <code>${j(Pt(c.el))}</code>
2917
- ${c.text ? `<span class="muted">“${j(c.text)}”</span>` : ""}
2908
+ <code>${F(Ot(c.el))}</code>
2909
+ ${c.text ? `<span class="muted">“${F(c.text)}”</span>` : ""}
2918
2910
  </div>
2919
2911
  </div>
2920
2912
  <div class="scope-target"></div>
2921
2913
  ${c.tokens.size ? "" : '<div class="scope-note">This element doesn’t use Panel tokens yet, so changes here won’t show. Style it with <code>var(--twd-…)</code> to make it tweakable.</div>'}
2922
2914
  <div class="warnings"></div>
2923
2915
  </div>
2924
- ${te.map((P) => `<div class="page page-fields" data-page="${P.id}"${P.id === m ? "" : " hidden"}></div>`).join("")}
2916
+ ${te.map((O) => `<div class="page page-fields" data-page="${O.id}"${O.id === b ? "" : " hidden"}></div>`).join("")}
2925
2917
  `, c.classSelector) {
2926
- const P = ge({
2918
+ const O = ge({
2927
2919
  label: "Apply to",
2928
2920
  options: [
2929
2921
  { value: "element", label: "This element" },
2930
2922
  { value: "class", label: `All ${c.classSelector} (${c.classCount})`, title: `Every element matching ${c.classSelector}` }
2931
2923
  ],
2932
2924
  onSelect: (ye) => {
2933
- ye === "class" && t.moveScope(c.elementSelector, c.classSelector), C.target = ye, st();
2925
+ ye === "class" && t.moveScope(c.elementSelector, c.classSelector), E.target = ye, st();
2934
2926
  }
2935
2927
  });
2936
- P.setValue(C.target), b.querySelector(".scope-target").append(P.el);
2928
+ O.setValue(E.target), g.querySelector(".scope-target").append(O.el);
2937
2929
  }
2938
- const { ctx: y, dispose: M } = ha(Qt(), c.el);
2939
- te.forEach((P) => g(b.querySelector(`[data-page="${P.id}"]`), P.parts, y));
2940
- const k = b.querySelector(".warnings"), T = () => {
2941
- const P = c.tokens.size ? ao(c.el) : null;
2942
- k.innerHTML = P ? S([P]) : "";
2930
+ const { ctx: y, dispose: C } = ua(Qt(), c.el);
2931
+ te.forEach((O) => m(g.querySelector(`[data-page="${O.id}"]`), O.parts, y));
2932
+ const k = g.querySelector(".warnings"), T = () => {
2933
+ const O = c.tokens.size ? ao(c.el) : null;
2934
+ k.innerHTML = O ? S([O]) : "";
2943
2935
  };
2944
2936
  T();
2945
2937
  const U = t.onChange(T);
2946
- C.dispose = () => {
2947
- M(), U();
2938
+ E.dispose = () => {
2939
+ C(), U();
2948
2940
  };
2949
2941
  }
2950
2942
  function en() {
2951
- if (!C || !C.info.classSelector) return;
2952
- const c = t.getState().scopes || {}, b = C.target === "class" ? "element" : "class", y = b === "class" ? C.info.classSelector : C.info.elementSelector;
2953
- !c[Qt()] && c[y] && (C.target = b, st());
2943
+ if (!E || !E.info.classSelector) return;
2944
+ const c = t.getState().scopes || {}, g = E.target === "class" ? "element" : "class", y = g === "class" ? E.info.classSelector : E.info.elementSelector;
2945
+ !c[Qt()] && c[y] && (E.target = g, st());
2954
2946
  }
2955
2947
  const tn = () => {
2956
2948
  t.undo(), en();
@@ -2958,51 +2950,51 @@ function Go({ sections: e, store: t, view: n }) {
2958
2950
  t.redo(), en();
2959
2951
  };
2960
2952
  function an() {
2961
- C && (C.dispose(), C = null, d.local.innerHTML = "", se(null), Ne(), Le === "local" && Ae("global"));
2953
+ E && (E.dispose(), E = null, d.local.innerHTML = "", se(null), Ne(), Le === "local" && Ae("global"));
2962
2954
  }
2963
2955
  const on = (c) => c.kind === "global" ? "Whole page" : c.kind === "class" ? `All ${c.selector}` : "One element";
2964
2956
  function rn() {
2965
- const c = wn(t.getState(), e), b = pt(), y = d.changes;
2957
+ const c = wn(t.getState(), e), g = ut(), y = d.changes;
2966
2958
  if (!c.length) {
2967
- y.innerHTML = `<div class="empty">No changes yet. Tweak a section, or pick an element to change it on its own.</div>${S(b)}`;
2959
+ y.innerHTML = `<div class="empty">No changes yet. Tweak a section, or pick an element to change it on its own.</div>${S(g)}`;
2968
2960
  return;
2969
2961
  }
2970
- const M = /* @__PURE__ */ new Map();
2962
+ const C = /* @__PURE__ */ new Map();
2971
2963
  c.forEach((k) => {
2972
2964
  const T = k.selector || "";
2973
- M.has(T) || M.set(T, []), M.get(T).push(k);
2974
- }), y.innerHTML = (b.length ? `<div class="warnings">${S(b)}</div>` : "") + [...M].map(([k, T]) => `
2965
+ C.has(T) || C.set(T, []), C.get(T).push(k);
2966
+ }), y.innerHTML = (g.length ? `<div class="warnings">${S(g)}</div>` : "") + [...C].map(([k, T]) => `
2975
2967
  <div class="change-group">
2976
2968
  <div class="change-scope">
2977
- ${k ? `<button class="link-btn" data-select="${j(k)}" title="Select it on the page">${j(on(T[0]))}</button><code>${j(k)}</code>` : `<span>${on(T[0])}</span>`}
2969
+ ${k ? `<button class="link-btn" data-select="${F(k)}" title="Select it on the page">${F(on(T[0]))}</button><code>${F(k)}</code>` : `<span>${on(T[0])}</span>`}
2978
2970
  </div>
2979
2971
  ${T.map((U) => `
2980
2972
  <div class="change-row">
2981
2973
  <div class="change-main">
2982
- <div class="change-title">${j(U.title)} <span class="muted">›</span> ${U.settings.map((P) => `${j(P.label)}: <b>${j(P.value)}</b>`).join(", ")}</div>
2983
- ${U.tokens.map((P) => `<div class="change-token"><code>${j(P.name)}</code> ${P.from ? `${j(P.from)} → ` : ""}${j(P.to)}</div>`).join("")}
2974
+ <div class="change-title">${F(U.title)} <span class="muted">›</span> ${U.settings.map((O) => `${F(O.label)}: <b>${F(O.value)}</b>`).join(", ")}</div>
2975
+ ${U.tokens.map((O) => `<div class="change-token"><code>${F(O.name)}</code> ${O.from ? `${F(O.from)} → ` : ""}${F(O.to)}</div>`).join("")}
2984
2976
  </div>
2985
- <button class="icon-btn" data-remove="${j(U.sectionId)}" data-remove-scope="${j(k)}" aria-label="Remove ${j(U.title)} change">${A.close}</button>
2977
+ <button class="icon-btn" data-remove="${F(U.sectionId)}" data-remove-scope="${F(k)}" aria-label="Remove ${F(U.title)} change">${P.close}</button>
2986
2978
  </div>`).join("")}
2987
2979
  </div>`).join("");
2988
2980
  }
2989
- function fa(c, b) {
2990
- if (b) return t.removeScope(b, c);
2981
+ function ha(c, g) {
2982
+ if (g) return t.removeScope(g, c);
2991
2983
  const y = t.getState()[c] || {};
2992
- t.setSection(c, Object.fromEntries(Object.keys(y).map((M) => [M, null])));
2984
+ t.setSection(c, Object.fromEntries(Object.keys(y).map((C) => [C, null])));
2993
2985
  }
2994
2986
  const we = r(".apply-menu"), sn = r('[data-action="apply-menu"]'), ln = () => ne("apply-mode") === "copy" ? "copy" : "preview";
2995
- function ga() {
2987
+ function fa() {
2996
2988
  we.querySelectorAll("[data-apply-mode]").forEach((c) => c.setAttribute("aria-checked", String(c.dataset.applyMode === ln())));
2997
2989
  }
2998
2990
  function ze(c) {
2999
- we.hidden = !c, sn.setAttribute("aria-expanded", String(c)), c && ga();
2991
+ we.hidden = !c, sn.setAttribute("aria-expanded", String(c)), c && fa();
3000
2992
  }
3001
2993
  function dn() {
3002
- return Qa(wn(t.getState(), e), { warnings: pt() });
2994
+ return Qa(wn(t.getState(), e), { warnings: ut() });
3003
2995
  }
3004
2996
  const Ie = r(".dialog-backdrop"), cn = r(".prompt-text");
3005
- function ba() {
2997
+ function ga() {
3006
2998
  const c = dn();
3007
2999
  if (!c) return V("No changes to copy yet");
3008
3000
  if (ln() === "copy") return xe(c, "Prompt copied · paste it into your agent");
@@ -3025,7 +3017,7 @@ function Go({ sections: e, store: t, view: n }) {
3025
3017
  clearTimeout(pn), ve && (De(!1), ve = !1);
3026
3018
  };
3027
3019
  le.addEventListener("pointerup", un), le.addEventListener("pointerleave", un);
3028
- const Be = r(".setup-hint"), hn = `setup-hint-dismissed:${location.pathname}`, xa = {
3020
+ const Be = r(".setup-hint"), hn = `setup-hint-dismissed:${location.pathname}`, ba = {
3029
3021
  "no-tokens": {
3030
3022
  title: "The Panel tokens aren’t loaded",
3031
3023
  text: "The knobs change the --twd-* variables, but this page doesn’t load them. Add the token stylesheet before your own CSS:",
@@ -3044,60 +3036,72 @@ function Go({ sections: e, store: t, view: n }) {
3044
3036
  let B = null;
3045
3037
  function Ue() {
3046
3038
  const c = lo();
3047
- B = ne(hn) === c ? null : xa[c] || null, i.toggleAttribute("data-hint", !!B), Be.hidden = !B, B && (Be.innerHTML = `
3048
- <div class="setup-head">${A.warn}<b>${j(B.title)}</b>
3049
- <button class="icon-btn" data-action="setup-dismiss" title="Hide this message" aria-label="Hide this message">${A.close}</button>
3039
+ B = ne(hn) === c ? null : ba[c] || null, i.toggleAttribute("data-hint", !!B), Be.hidden = !B, B && (Be.innerHTML = `
3040
+ <div class="setup-head">${P.warn}<b>${F(B.title)}</b>
3041
+ <button class="icon-btn" data-action="setup-dismiss" title="Hide this message" aria-label="Hide this message">${P.close}</button>
3050
3042
  </div>
3051
- <p>${j(B.text)}</p>
3052
- ${(B.snippets || []).map((b, y) => `
3043
+ <p>${F(B.text)}</p>
3044
+ ${(B.snippets || []).map((g, y) => `
3053
3045
  <div class="setup-snippet">
3054
- <span>${j(b.label)}</span>
3055
- <div class="setup-code"><code>${j(b.code)}</code><button class="text-btn" data-setup-snippet="${y}">Copy</button></div>
3046
+ <span>${F(g.label)}</span>
3047
+ <div class="setup-code"><code>${F(g.code)}</code><button class="text-btn" data-setup-snippet="${y}">Copy</button></div>
3056
3048
  </div>`).join("")}
3057
3049
  <div class="setup-actions">
3058
- ${B.copy ? `<button class="apply-btn" data-action="setup-copy">${j(B.copy)}</button>` : ""}
3050
+ ${B.copy ? `<button class="apply-btn" data-action="setup-copy">${F(B.copy)}</button>` : ""}
3059
3051
  <a href="${B.link}" target="_blank" rel="noopener">Setup guide</a>
3060
3052
  </div>`, Be.dataset.status = c);
3061
3053
  }
3062
3054
  Ue(), document.readyState !== "complete" && window.addEventListener("load", Ue, { once: !0 }), setTimeout(Ue, 1500);
3055
+ const xa = { "--pv-primary": "--twd-primary", "--pv-on-primary": "--twd-on-primary", "--pv-radius-control": "--twd-radius-control", "--pv-radius-container": "--twd-radius-container" };
3056
+ function lt() {
3057
+ [[d.global, document.documentElement], [d.local, E && E.info.el]].forEach(([c, g]) => {
3058
+ if (!g) return;
3059
+ const y = getComputedStyle(g);
3060
+ Object.entries(xa).forEach(([C, k]) => {
3061
+ const T = y.getPropertyValue(k).trim();
3062
+ T ? c.style.setProperty(C, T) : c.style.removeProperty(C);
3063
+ });
3064
+ });
3065
+ }
3066
+ t.onChange(() => requestAnimationFrame(lt)), lt();
3063
3067
  const wa = r(".badge");
3064
3068
  function fn() {
3065
3069
  r('[data-action="undo"]').disabled = !t.canUndo(), r('[data-action="redo"]').disabled = !t.canRedo();
3066
3070
  const c = Za(t.getState());
3067
3071
  wa.textContent = c, r('[data-action="changes"]').classList.toggle("has-changes", c > 0), r('[data-action="changes"]').setAttribute("aria-label", `Changes (${c})`);
3068
- const b = S(pt());
3072
+ const g = S(ut());
3069
3073
  d.global.querySelectorAll(".page-warnings").forEach((y) => {
3070
- y.innerHTML = b;
3074
+ y.innerHTML = g;
3071
3075
  }), K && rn();
3072
3076
  }
3073
3077
  return t.onChange(fn), fn(), o.addEventListener("click", (c) => {
3074
3078
  if (c.target === Ie) return it();
3075
- const b = c.target.closest("button");
3076
- if (b) {
3077
- if (b !== sn && !we.contains(b) && ze(!1), b === i)
3078
- return qt.consumeClick() ? void 0 : c.detail === 2 ? (Fe(), qt.reset(), V("Panel moved back to the corner")) : Fe();
3079
- if (b.dataset.select) {
3080
- const y = document.querySelector(b.dataset.select);
3079
+ const g = c.target.closest("button");
3080
+ if (g) {
3081
+ if (g !== sn && !we.contains(g) && ze(!1), g === i)
3082
+ return qt.consumeClick() ? void 0 : c.detail === 2 ? (je(), qt.reset(), V("Panel moved back to the corner")) : je();
3083
+ if (g.dataset.select) {
3084
+ const y = document.querySelector(g.dataset.select);
3081
3085
  return y ? Jt(y) : V("That element isn’t on this page");
3082
3086
  }
3083
- if (b.dataset.setupSnippet) return xe(En[b.dataset.setupSnippet].code, "Copied");
3084
- if (b.dataset.tab)
3085
- return Ae(Ut()), at && me(!1), v(b.dataset.tab);
3086
- if (b.dataset.remove) return fa(b.dataset.remove, b.dataset.removeScope);
3087
- if (b.dataset.applyMode)
3088
- return ce("apply-mode", b.dataset.applyMode), ze(!1), V(b.dataset.applyMode === "copy" ? "Copy prompt copies straight away" : "Copy prompt shows a preview first");
3089
- switch (b.dataset.action) {
3087
+ if (g.dataset.setupSnippet) return xe(En[g.dataset.setupSnippet].code, "Copied");
3088
+ if (g.dataset.tab)
3089
+ return Ae(Ut()), at && be(!1), w(g.dataset.tab);
3090
+ if (g.dataset.remove) return ha(g.dataset.remove, g.dataset.removeScope);
3091
+ if (g.dataset.applyMode)
3092
+ return ce("apply-mode", g.dataset.applyMode), ze(!1), V(g.dataset.applyMode === "copy" ? "Copy prompt copies straight away" : "Copy prompt shows a preview first");
3093
+ switch (g.dataset.action) {
3090
3094
  case "close":
3091
3095
  return ot();
3092
3096
  case "minimise":
3093
- return at ? me(!1) : (ua(), (o.querySelector('.tab[aria-pressed="true"]') || x[0]).focus());
3097
+ return at ? be(!1) : (pa(), (o.querySelector('.tab[aria-pressed="true"]') || x[0]).focus());
3094
3098
  case "reset":
3095
3099
  return t.resetState(), V("Reset to defaults · ⌘Z to undo");
3096
3100
  case "copy":
3097
3101
  return xe(location.href, "Link copied");
3098
3102
  // Pressed again (picking, or an element selected): out of selection mode.
3099
3103
  case "pick":
3100
- return ie || C ? (Re(), an()) : Zt();
3104
+ return ie || E ? (Re(), an()) : Zt();
3101
3105
  case "compare":
3102
3106
  ve || De(le.getAttribute("aria-pressed") !== "true");
3103
3107
  return;
@@ -3112,7 +3116,7 @@ function Go({ sections: e, store: t, view: n }) {
3112
3116
  case "changes-close":
3113
3117
  return Z(!1);
3114
3118
  case "apply":
3115
- return ba();
3119
+ return ga();
3116
3120
  case "apply-menu":
3117
3121
  return ze(we.hidden);
3118
3122
  case "dialog-close":
@@ -3132,28 +3136,28 @@ function Go({ sections: e, store: t, view: n }) {
3132
3136
  }
3133
3137
  !(c.metaKey || c.ctrlKey) || c.key.toLowerCase() !== "z" || c.target.matches?.('input[type="text"], textarea') || (c.preventDefault(), c.shiftKey ? nn() : tn());
3134
3138
  }), document.addEventListener("keydown", (c) => {
3135
- c.altKey && (c.code === "KeyT" && (c.preventDefault(), Fe()), c.code === "KeyC" && (c.preventDefault(), De(le.getAttribute("aria-pressed") !== "true")));
3136
- }), ne("panel") === "open" ? J({ animate: !1 }) : ne("panel") === "tabs" && (J({ animate: !1 }), me(!0)), { open: J, close: ot, toggle: Fe, toast: V, pick: Zt, prompt: dn };
3139
+ c.altKey && (c.code === "KeyT" && (c.preventDefault(), je()), c.code === "KeyC" && (c.preventDefault(), De(le.getAttribute("aria-pressed") !== "true")));
3140
+ }), ne("panel") === "open" ? J({ animate: !1 }) : ne("panel") === "tabs" && (J({ animate: !1 }), be(!0)), { open: J, close: ot, toggle: je, toast: V, pick: Zt, prompt: dn };
3137
3141
  }
3138
- const In = [Bo, Je, la, jt, yo, Nt, da, vo];
3142
+ const zn = [Bo, Je, ia, Ft, yo, Nt, la, vo];
3139
3143
  function Yo() {
3140
3144
  if (getComputedStyle(document.documentElement).getPropertyValue("--twd-radius-control").trim() || document.getElementById("twiddle-tokens")) return;
3141
3145
  const t = document.createElement("style");
3142
- t.id = "twiddle-tokens", t.textContent = Hn, document.head.prepend(t);
3146
+ t.id = "twiddle-tokens", t.textContent = qn, document.head.prepend(t);
3143
3147
  }
3144
3148
  if (!window.Twiddle) {
3145
- Yo(), In.forEach((n) => Fa(n.tokens)), qn(At);
3149
+ Yo(), zn.forEach((n) => ja(n.tokens)), Vn(At);
3146
3150
  let e;
3147
3151
  const t = () => {
3148
- At(Mt()), e = Go({ sections: In, store: Aa, view: { suspend: za, resume: Ia } });
3152
+ At(Mt()), e = Go({ sections: zn, store: Aa, view: { suspend: za, resume: Ia } });
3149
3153
  };
3150
3154
  document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", t) : t(), window.Twiddle = {
3151
3155
  open: () => e && e.open(),
3152
3156
  close: () => e && e.close(),
3153
3157
  toggle: () => e && e.toggle(),
3154
- reset: () => Bn(),
3155
- undo: () => Un(),
3156
- redo: () => Vn(),
3158
+ reset: () => Dn(),
3159
+ undo: () => Bn(),
3160
+ redo: () => Un(),
3157
3161
  pick: () => e && e.pick(),
3158
3162
  prompt: () => e ? e.prompt() : "",
3159
3163
  getState: Mt