twiddle-panel 0.7.0 → 0.7.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,6 +1,6 @@
1
- const pt = /* @__PURE__ */ new Set();
2
- let T = Xn(), X = [], ve = [], Ie = null, Xt = 0;
3
- function Xn() {
1
+ const ut = /* @__PURE__ */ new Set();
2
+ let M = ta(), J = [], ve = [], De = null, en = 0;
3
+ function ta() {
4
4
  const t = new URLSearchParams(location.search).get("twd");
5
5
  if (!t) return {};
6
6
  try {
@@ -9,19 +9,19 @@ function Xn() {
9
9
  return {};
10
10
  }
11
11
  }
12
- function Jn() {
12
+ function na() {
13
13
  const t = new URL(location.href);
14
- Object.keys(T).length ? t.searchParams.set("twd", JSON.stringify(T)) : t.searchParams.delete("twd"), history.replaceState(history.state, "", t);
14
+ Object.keys(M).length ? t.searchParams.set("twd", JSON.stringify(M)) : t.searchParams.delete("twd"), history.replaceState(history.state, "", t);
15
15
  }
16
- function yt() {
17
- Jn(), pt.forEach((t) => t(T));
16
+ function kt() {
17
+ na(), ut.forEach((t) => t(M));
18
18
  }
19
- function se(t, e) {
20
- if (JSON.stringify(t) === JSON.stringify(T)) return;
19
+ function le(t, e) {
20
+ if (JSON.stringify(t) === JSON.stringify(M)) return;
21
21
  const n = Date.now();
22
- e && e === Ie && n - Xt < 400 || (X.push(T), X.length > 100 && X.shift()), ve = [], Ie = e, Xt = n, T = t, yt();
22
+ e && e === De && n - en < 400 || (J.push(M), J.length > 100 && J.shift()), ve = [], De = e, en = n, M = t, kt();
23
23
  }
24
- function Be(t, e) {
24
+ function Ue(t, e) {
25
25
  const n = { ...t, ...e };
26
26
  return Object.keys(n).forEach((a) => {
27
27
  n[a] == null && delete n[a];
@@ -31,118 +31,118 @@ function U(t, e, n) {
31
31
  const a = { ...t };
32
32
  return n == null ? delete a[e] : a[e] = n, a;
33
33
  }
34
- function ut() {
35
- return JSON.parse(JSON.stringify(T));
34
+ function ht() {
35
+ return JSON.parse(JSON.stringify(M));
36
36
  }
37
- function Qn(t, e) {
38
- se(U(T, t, Be(T[t], e)), `${t}:${Object.keys(e)}`);
37
+ function aa(t, e) {
38
+ le(U(M, t, Ue(M[t], e)), `${t}:${Object.keys(e)}`);
39
39
  }
40
- function ea(t, e = `multi:${Object.keys(t)}`) {
41
- const n = Object.entries(t).reduce((a, [o, r]) => U(a, o, Be(a[o], r)), T);
42
- se(n, e);
40
+ function oa(t, e = `multi:${Object.keys(t)}`) {
41
+ const n = Object.entries(t).reduce((a, [o, s]) => U(a, o, Ue(a[o], s)), M);
42
+ le(n, e);
43
43
  }
44
- function vn(t, e, n) {
45
- const a = U(T.scopes?.[t], e, Be(T.scopes?.[t]?.[e], n)), o = U(T.scopes, t, Object.keys(a).length ? a : null);
46
- se(U(T, "scopes", Object.keys(o).length ? o : null), `${t}|${e}:${Object.keys(n)}`);
44
+ function Sn(t, e, n) {
45
+ const a = U(M.scopes?.[t], e, Ue(M.scopes?.[t]?.[e], n)), o = U(M.scopes, t, Object.keys(a).length ? a : null);
46
+ le(U(M, "scopes", Object.keys(o).length ? o : null), `${t}|${e}:${Object.keys(n)}`);
47
47
  }
48
- function ta(t, e) {
49
- if (e) return vn(t, e, Object.fromEntries(
50
- Object.keys(T.scopes?.[t]?.[e] || {}).map((a) => [a, null])
48
+ function ra(t, e) {
49
+ if (e) return Sn(t, e, Object.fromEntries(
50
+ Object.keys(M.scopes?.[t]?.[e] || {}).map((a) => [a, null])
51
51
  ));
52
- const n = U(T.scopes, t, null);
53
- se(U(T, "scopes", Object.keys(n).length ? n : null));
52
+ const n = U(M.scopes, t, null);
53
+ le(U(M, "scopes", Object.keys(n).length ? n : null));
54
54
  }
55
- function na(t, e) {
56
- const n = T.scopes?.[t];
55
+ function sa(t, e) {
56
+ const n = M.scopes?.[t];
57
57
  if (!n || t === e) return;
58
- let a = { ...T.scopes[e] };
59
- Object.entries(n).forEach(([r, s]) => {
60
- a = U(a, r, Be(a[r], s));
58
+ let a = { ...M.scopes[e] };
59
+ Object.entries(n).forEach(([s, r]) => {
60
+ a = U(a, s, Ue(a[s], r));
61
61
  });
62
- const o = U(U(T.scopes, t, null), e, a);
63
- se(U(T, "scopes", o));
62
+ const o = U(U(M.scopes, t, null), e, a);
63
+ le(U(M, "scopes", o));
64
64
  }
65
- function yn() {
66
- se({});
65
+ function $n() {
66
+ le({});
67
67
  }
68
- function kn() {
69
- X.length && (ve.push(T), T = X.pop(), Ie = null, yt());
68
+ function En() {
69
+ J.length && (ve.push(M), M = J.pop(), De = null, kt());
70
70
  }
71
- function Sn() {
72
- ve.length && (X.push(T), T = ve.pop(), Ie = null, yt());
71
+ function Cn() {
72
+ ve.length && (J.push(M), M = ve.pop(), De = null, kt());
73
73
  }
74
- const aa = () => X.length > 0, oa = () => ve.length > 0;
75
- function $n(t) {
76
- return pt.add(t), () => pt.delete(t);
74
+ const ia = () => J.length > 0, la = () => ve.length > 0;
75
+ function Mn(t) {
76
+ return ut.add(t), () => ut.delete(t);
77
77
  }
78
- const ra = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
78
+ const da = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
79
79
  __proto__: null,
80
- canRedo: oa,
81
- canUndo: aa,
82
- getState: ut,
83
- moveScope: na,
84
- onChange: $n,
85
- redo: Sn,
86
- removeScope: ta,
87
- resetState: yn,
88
- setScope: vn,
89
- setSection: Qn,
90
- setSections: ea,
91
- undo: kn
92
- }, Symbol.toStringTag, { value: "Module" })), En = [];
93
- let ht = [], kt = {}, R = null, oe = !1, Cn = {};
94
- function sa(t) {
95
- typeof t == "function" && En.push(t);
96
- }
97
- const Jt = (t) => Object.assign({}, ...En.map((e) => e(t) || {})), ft = (t) => /^(\.[\w-]+|\[data-twd="[^"]+"\])$/.test(t), ia = (t) => {
80
+ canRedo: la,
81
+ canUndo: ia,
82
+ getState: ht,
83
+ moveScope: sa,
84
+ onChange: Mn,
85
+ redo: Cn,
86
+ removeScope: ra,
87
+ resetState: $n,
88
+ setScope: Sn,
89
+ setSection: aa,
90
+ setSections: oa,
91
+ undo: En
92
+ }, Symbol.toStringTag, { value: "Module" })), Tn = [];
93
+ let ft = [], St = {}, R = null, se = !1, An = {};
94
+ function ca(t) {
95
+ typeof t == "function" && Tn.push(t);
96
+ }
97
+ const tn = (t) => Object.assign({}, ...Tn.map((e) => e(t) || {})), gt = (t) => /^(\.[\w-]+|\[data-twd="[^"]+"\])$/.test(t), pa = (t) => {
98
98
  try {
99
99
  return document.querySelector(t), !0;
100
100
  } catch {
101
101
  return !1;
102
102
  }
103
103
  };
104
- function la() {
104
+ function ua() {
105
105
  return (!R || !R.isConnected) && (R = document.createElement("style"), R.id = "twiddle-scoped", document.head.appendChild(R)), R;
106
106
  }
107
- function Tn() {
107
+ function Ln() {
108
108
  const t = document.documentElement;
109
- ht.forEach((e) => t.style.removeProperty(e)), ht = [], kt = {};
109
+ ft.forEach((e) => t.style.removeProperty(e)), ft = [], St = {};
110
110
  }
111
- function gt(t) {
112
- if (Cn = t, oe) return;
111
+ function mt(t) {
112
+ if (An = t, se) return;
113
113
  const e = document.documentElement;
114
- Tn();
115
- const n = Jt(t), a = Object.entries(t.scopes || {}).filter(([r]) => ia(r)).sort(([r], [s]) => ft(s) - ft(r)).map(([r, s]) => [r, Jt(s)]);
116
- Object.entries(n).forEach(([r, s]) => e.style.setProperty(r, s)), ht = Object.keys(n), kt = n;
117
- const o = a.filter(([, r]) => Object.keys(r).length).map(([r, s]) => `${r} {
118
- ${Object.entries(s).map(([i, l]) => ` ${i}: ${l} !important;`).join(`
114
+ Ln();
115
+ const n = tn(t), a = Object.entries(t.scopes || {}).filter(([s]) => pa(s)).sort(([s], [r]) => gt(r) - gt(s)).map(([s, r]) => [s, tn(r)]);
116
+ Object.entries(n).forEach(([s, r]) => e.style.setProperty(s, r)), ft = Object.keys(n), St = n;
117
+ const o = a.filter(([, s]) => Object.keys(s).length).map(([s, r]) => `${s} {
118
+ ${Object.entries(r).map(([i, l]) => ` ${i}: ${l} !important;`).join(`
119
119
  `)}
120
120
  }`).join(`
121
121
  `);
122
- (o || R) && (la().textContent = o);
122
+ (o || R) && (ua().textContent = o);
123
123
  }
124
- function Mn(t) {
125
- const e = document.documentElement, n = oe, a = { ...kt };
124
+ function On(t) {
125
+ const e = document.documentElement, n = se, a = { ...St };
126
126
  Object.keys(a).forEach((o) => e.style.removeProperty(o)), R && (R.disabled = !0);
127
127
  try {
128
128
  return t();
129
129
  } finally {
130
- n || (Object.entries(a).forEach(([o, r]) => e.style.setProperty(o, r)), R && (R.disabled = !1));
130
+ n || (Object.entries(a).forEach(([o, s]) => e.style.setProperty(o, s)), R && (R.disabled = !1));
131
131
  }
132
132
  }
133
- function da(t, e = document.documentElement) {
134
- return Mn(() => {
133
+ function ha(t, e = document.documentElement) {
134
+ return On(() => {
135
135
  const n = getComputedStyle(e);
136
136
  return Object.fromEntries(t.map((a) => [a, n.getPropertyValue(a).trim()]));
137
137
  });
138
138
  }
139
- function ca() {
140
- oe || (Tn(), R && (R.disabled = !0), oe = !0);
139
+ function fa() {
140
+ se || (Ln(), R && (R.disabled = !0), se = !0);
141
141
  }
142
- function pa() {
143
- oe && (oe = !1, R && (R.disabled = !1), gt(Cn));
142
+ function ga() {
143
+ se && (se = !1, R && (R.disabled = !1), mt(An));
144
144
  }
145
- const ua = `
145
+ const ma = `
146
146
  :host { all: initial; } /* block fonts/colours inherited from the page */
147
147
  * { box-sizing: border-box; }
148
148
 
@@ -163,8 +163,10 @@ const ua = `
163
163
  z-index: 2147483647;
164
164
  font: 13px/1.4 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
165
165
  color: var(--p-fg);
166
+ /* The panel opens to the left of the launcher, bottoms aligned,
167
+ so it can use the full window height. */
166
168
  display: flex;
167
- flex-direction: column;
169
+ flex-direction: row;
168
170
  align-items: flex-end;
169
171
  gap: 10px;
170
172
  }
@@ -196,6 +198,11 @@ const ua = `
196
198
  cursor: pointer;
197
199
  padding: 0;
198
200
  }
201
+ /* Open or minimised: centred on the tabs. 10px = panel border 1 + tab bar
202
+ padding 6 + half a tab (~49px) − half the launcher (22). */
203
+ .launcher { transition: margin-bottom .2s cubic-bezier(0.2, 0.8, 0.2, 1); }
204
+ .wrap.is-open .launcher { margin-bottom: 10px; }
205
+ @media (prefers-reduced-motion: reduce) { .launcher { transition: none; } }
199
206
  .mark { display: block; overflow: visible; }
200
207
  .mark-disc { fill: #16161a; }
201
208
  .mark-knob { fill: #4f46e5; }
@@ -212,11 +219,12 @@ const ua = `
212
219
  /* Panel */
213
220
  .panel {
214
221
  width: 360px; /* tabbed layout (Figma 254:323); was 300 */
215
- max-width: calc(100vw - 32px);
222
+ /* 86px = 16 + 16 margins + 44 launcher + 10 gap */
223
+ max-width: calc(100vw - 86px);
216
224
  /* As tall as its content; scrolls only when the window is shorter.
217
- 90px = 16 margin + 44 launcher + 10 gap + 20 room at the top. */
218
- max-height: calc(100vh - 90px);
219
- max-height: calc(100dvh - 90px);
225
+ 32px = 16 margin below + 16 room at the top. */
226
+ max-height: calc(100vh - 32px);
227
+ max-height: calc(100dvh - 32px);
220
228
  background: var(--p-bg);
221
229
  border: 1px solid var(--p-line);
222
230
  border-radius: 14px;
@@ -443,8 +451,9 @@ const ua = `
443
451
  padding: 1px 4px;
444
452
  }
445
453
 
446
- /* Beside the launcher (left of it, centred on it). The panel always sits
447
- above the launcher, so a toast here never covers the footer's Copy prompt. */
454
+ /* Closed: beside the launcher (left of it, centred on it). Open or minimised:
455
+ the panel takes that spot, so the toast floats just above the tab bar
456
+ (63px tall), inside the panel's right edge. */
448
457
  .toast {
449
458
  position: absolute; bottom: 22px; right: 54px; transform: translateY(50%);
450
459
  background: var(--p-accent); color: var(--p-on-accent);
@@ -453,6 +462,7 @@ const ua = `
453
462
  opacity: 0; transition: opacity .15s ease; pointer-events: none;
454
463
  }
455
464
  .toast.show { opacity: 1; }
465
+ .wrap.is-open .toast { bottom: 72px; right: 62px; transform: none; z-index: 3; }
456
466
 
457
467
  /* ---------- Proposals below: not yet designed in Figma ---------- */
458
468
 
@@ -763,6 +773,11 @@ const ua = `
763
773
  .tab:hover { background: var(--p-hover); color: var(--p-fg); }
764
774
  .tab[aria-pressed="true"] { background: var(--p-hover); color: var(--p-fg); font-weight: 600; }
765
775
  .tab span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
776
+
777
+ /* Minimised (proposal, not yet in Figma): only the tab bar (and the Compare
778
+ strip while it shows); clicking a tab opens the panel on that tab. */
779
+ .panel.minimised > :not(.tabbar):not(.original-pill) { display: none; }
780
+ .panel.minimised .tabbar { border-top: 0; }
766
781
  .page-fields { gap: 16px; }
767
782
  .page-heading { display: flex; align-items: baseline; justify-content: space-between; font-size: 13px; font-weight: 500; color: var(--p-fg); margin-bottom: -6px; }
768
783
  .page-heading .muted { font-size: 12px; font-weight: 400; }
@@ -871,48 +886,49 @@ const ua = `
871
886
  .summary-swatch { width: 14px; height: 14px; border-radius: 4px; flex: none; }
872
887
  .summary-swatch[hidden] { display: none; }
873
888
  .summary-row .chev { display: grid; color: var(--p-muted); }
874
- `, P = (t, e, n) => `<svg width="${t}" height="${t}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="${e}" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${n}</svg>`, A = {
875
- dial: P(20, 1.8, '<circle cx="12" cy="12" r="8"/><path d="M12 12l4-4"/><path d="M12 2v2M12 20v2M2 12h2M20 12h2"/>'),
876
- link: P(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"/>'),
877
- reset: P(15, 2, '<path d="M3 12a9 9 0 1 0 3-6.7"/><path d="M3 3v6h6"/>'),
878
- close: P(15, 2, '<path d="M18 6L6 18M6 6l12 12"/>'),
879
- chevron: P(12, 2.4, '<path d="M9 6l6 6-6 6"/>'),
889
+ `, O = (t, e, n) => `<svg width="${t}" height="${t}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="${e}" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${n}</svg>`, A = {
890
+ dial: O(20, 1.8, '<circle cx="12" cy="12" r="8"/><path d="M12 12l4-4"/><path d="M12 2v2M12 20v2M2 12h2M20 12h2"/>'),
891
+ link: O(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"/>'),
892
+ reset: O(15, 2, '<path d="M3 12a9 9 0 1 0 3-6.7"/><path d="M3 3v6h6"/>'),
893
+ close: O(15, 2, '<path d="M18 6L6 18M6 6l12 12"/>'),
894
+ chevron: O(12, 2.4, '<path d="M9 6l6 6-6 6"/>'),
880
895
  // Proposals: not yet in the Figma Icon/* set.
881
- pick: P(15, 2, '<circle cx="12" cy="12" r="7"/><path d="M12 2v4M12 18v4M2 12h4M18 12h4"/>'),
882
- compare: P(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"/>'),
883
- undo: P(15, 2, '<path d="M9 14L4 9l5-5"/><path d="M4 9h11a5 5 0 0 1 0 10h-3"/>'),
884
- redo: P(15, 2, '<path d="M15 14l5-5-5-5"/><path d="M20 9H9a5 5 0 0 0 0 10h3"/>'),
885
- back: P(15, 2, '<path d="M15 18l-6-6 6-6"/>'),
886
- down: P(12, 2.4, '<path d="M6 9l6 6 6-6"/>'),
887
- copy: P(13, 2, '<rect x="9" y="9" width="11" height="11" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/>'),
888
- warn: P(13, 2, '<path d="M12 3l9.5 17h-19z"/><path d="M12 10v4M12 17.5v.01"/>'),
896
+ pick: O(15, 2, '<circle cx="12" cy="12" r="7"/><path d="M12 2v4M12 18v4M2 12h4M18 12h4"/>'),
897
+ compare: O(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"/>'),
898
+ undo: O(15, 2, '<path d="M9 14L4 9l5-5"/><path d="M4 9h11a5 5 0 0 1 0 10h-3"/>'),
899
+ redo: O(15, 2, '<path d="M15 14l5-5-5-5"/><path d="M20 9H9a5 5 0 0 0 0 10h3"/>'),
900
+ back: O(15, 2, '<path d="M15 18l-6-6 6-6"/>'),
901
+ down: O(12, 2.4, '<path d="M6 9l6 6 6-6"/>'),
902
+ minimise: O(15, 2, '<path d="M5 12h14"/>'),
903
+ copy: O(13, 2, '<rect x="9" y="9" width="11" height="11" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/>'),
904
+ warn: O(13, 2, '<path d="M12 3l9.5 17h-19z"/><path d="M12 10v4M12 17.5v.01"/>'),
889
905
  // Launcher: the Panel product mark (Twiddle brand; Figma Logo page › Panel mark; also site/favicon.svg).
890
906
  // A switch knocked out of a disc; knob + two-dot trail. Classes let the Toggle animation move them.
891
907
  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>',
892
908
  // Tab bar (Figma: Panel — tabbed layout (proposal), Icon/Tab * components)
893
- tabOverview: P(18, 1.8, '<circle cx="12" cy="12" r="8"/><path d="M12 12l4-4"/><path d="M12 2v2M12 20v2M2 12h2M20 12h2"/>'),
894
- tabColour: P(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"/>'),
895
- tabType: P(18, 2, '<path d="M5 7V5h14v2"/><path d="M12 5v14"/><path d="M9 19h6"/>'),
896
- tabSpacing: P(18, 2, '<path d="M4 5v14M20 5v14"/><path d="M8 12h8"/><path d="M10 9l-3 3 3 3M14 9l3 3-3 3"/>'),
897
- tabShape: P(18, 2, '<path d="M20 4h-9a7 7 0 0 0-7 7v9"/><path d="M20 10h-5a5 5 0 0 0-5 5v5"/>'),
898
- tabShadows: P(18, 2, '<rect x="4" y="4" width="12" height="12" rx="2"/><path d="M20 8v10a2 2 0 0 1-2 2H8"/>'),
899
- sliders: P(15, 2, '<path d="M4 7h10M18 7h2M4 17h4M12 17h8"/><circle cx="16" cy="7" r="2"/><circle cx="10" cy="17" r="2"/>')
909
+ tabOverview: O(18, 1.8, '<circle cx="12" cy="12" r="8"/><path d="M12 12l4-4"/><path d="M12 2v2M12 20v2M2 12h2M20 12h2"/>'),
910
+ tabColour: O(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"/>'),
911
+ tabType: O(18, 2, '<path d="M5 7V5h14v2"/><path d="M12 5v14"/><path d="M9 19h6"/>'),
912
+ tabSpacing: O(18, 2, '<path d="M4 5v14M20 5v14"/><path d="M8 12h8"/><path d="M10 9l-3 3 3 3M14 9l3 3-3 3"/>'),
913
+ tabShape: O(18, 2, '<path d="M20 4h-9a7 7 0 0 0-7 7v9"/><path d="M20 10h-5a5 5 0 0 0-5 5v5"/>'),
914
+ tabShadows: O(18, 2, '<rect x="4" y="4" width="12" height="12" rx="2"/><path d="M20 8v10a2 2 0 0 1-2 2H8"/>'),
915
+ sliders: O(15, 2, '<path d="M4 7h10M18 7h2M4 17h4M12 17h8"/><circle cx="16" cy="7" r="2"/><circle cx="10" cy="17" r="2"/>')
900
916
  // Figma: Icon/Sliders (proposal)
901
- }, An = "twiddle:";
902
- function fe(t) {
917
+ }, Pn = "twiddle:";
918
+ function ne(t) {
903
919
  try {
904
- return localStorage.getItem(An + t);
920
+ return localStorage.getItem(Pn + t);
905
921
  } catch {
906
922
  return null;
907
923
  }
908
924
  }
909
925
  function ge(t, e) {
910
926
  try {
911
- localStorage.setItem(An + t, e);
927
+ localStorage.setItem(Pn + t, e);
912
928
  } catch {
913
929
  }
914
930
  }
915
- function re({ label: t, options: e, onSelect: n }) {
931
+ function ie({ label: t, options: e, onSelect: n }) {
916
932
  const a = document.createElement("div");
917
933
  a.className = "seg", a.setAttribute("role", "radiogroup"), a.setAttribute("aria-label", t);
918
934
  const o = e.map((l) => {
@@ -920,16 +936,16 @@ function re({ label: t, options: e, onSelect: n }) {
920
936
  return p.type = "button", p.setAttribute("role", "radio"), p.dataset.value = l.value, p.textContent = l.label, l.title && (p.title = l.title), p.addEventListener("click", () => i(l.value)), p;
921
937
  });
922
938
  a.append(...o);
923
- let r = null;
924
- function s(l) {
925
- r = l, o.forEach((c) => c.setAttribute("aria-checked", String(c.dataset.value === l)));
939
+ let s = null;
940
+ function r(l) {
941
+ s = l, o.forEach((c) => c.setAttribute("aria-checked", String(c.dataset.value === l)));
926
942
  const p = Math.max(0, o.findIndex((c) => c.dataset.value === l));
927
943
  o.forEach((c, h) => {
928
944
  c.tabIndex = h === p ? 0 : -1;
929
945
  });
930
946
  }
931
947
  function i(l, p) {
932
- l !== r && (s(l), n(l)), p && o.find((c) => c.dataset.value === l).focus();
948
+ l !== s && (r(l), n(l)), p && o.find((c) => c.dataset.value === l).focus();
933
949
  }
934
950
  return a.addEventListener("keydown", (l) => {
935
951
  const p = o.indexOf(l.target);
@@ -941,14 +957,14 @@ function re({ label: t, options: e, onSelect: n }) {
941
957
  else if (l.key === "End") h = o.length - 1;
942
958
  else return;
943
959
  l.preventDefault(), i(o[h].dataset.value, !0);
944
- }), s(null), { el: a, setValue: s };
960
+ }), r(null), { el: a, setValue: r };
945
961
  }
946
- const Ln = /var\(\s*(--twd-[\w-]+)/g, ha = /::?[\w-]+(\([^)]*\))?/g;
947
- function* Ue(t) {
962
+ const Fn = /var\(\s*(--twd-[\w-]+)/g, ba = /::?[\w-]+(\([^)]*\))?/g;
963
+ function* qe(t) {
948
964
  for (const e of t)
949
- e.selectorText != null && (yield e), e.cssRules && (yield* Ue(e.cssRules));
965
+ e.selectorText != null && (yield e), e.cssRules && (yield* qe(e.cssRules));
950
966
  }
951
- function fa() {
967
+ function xa() {
952
968
  const t = [];
953
969
  for (const e of document.styleSheets) {
954
970
  if (e.ownerNode?.id === "twiddle-scoped") continue;
@@ -958,92 +974,92 @@ function fa() {
958
974
  } catch {
959
975
  continue;
960
976
  }
961
- for (const a of Ue(n)) {
962
- const o = [...a.style.cssText.matchAll(Ln)].map((r) => r[1]);
977
+ for (const a of qe(n)) {
978
+ const o = [...a.style.cssText.matchAll(Fn)].map((s) => s[1]);
963
979
  o.length && t.push({ selectors: a.selectorText.split(","), vars: o });
964
980
  }
965
981
  }
966
982
  return t;
967
983
  }
968
- function ga(t, e) {
969
- const n = e.replace(ha, "").trim() || "*";
984
+ function wa(t, e) {
985
+ const n = e.replace(ba, "").trim() || "*";
970
986
  try {
971
987
  return t.matches(n);
972
988
  } catch {
973
989
  return !1;
974
990
  }
975
991
  }
976
- function Pn(t) {
992
+ function Nn(t) {
977
993
  const e = /* @__PURE__ */ new Set(), n = [];
978
- return fa().forEach(({ selectors: a, vars: o }) => {
979
- const r = a.find((s) => ga(t, s));
980
- r && (o.forEach((s) => e.add(s)), n.push(r.trim()));
981
- }), [...(t.getAttribute("style") || "").matchAll(Ln)].forEach((a) => e.add(a[1])), { names: e, selectors: n };
994
+ return xa().forEach(({ selectors: a, vars: o }) => {
995
+ const s = a.find((r) => wa(t, r));
996
+ s && (o.forEach((r) => e.add(r)), n.push(s.trim()));
997
+ }), [...(t.getAttribute("style") || "").matchAll(Fn)].forEach((a) => e.add(a[1])), { names: e, selectors: n };
982
998
  }
983
- const mt = (t) => window.CSS && CSS.escape ? CSS.escape(t) : t;
984
- function ma(t) {
999
+ const bt = (t) => window.CSS && CSS.escape ? CSS.escape(t) : t;
1000
+ function va(t) {
985
1001
  const e = [];
986
1002
  let n = t;
987
1003
  for (; n && n.nodeType === 1 && n !== document.body && n !== document.documentElement; ) {
988
- if (n.id && document.querySelectorAll(`#${mt(n.id)}`).length === 1)
989
- return e.unshift(`#${mt(n.id)}`), e.join(" > ");
990
- const a = n.localName, o = [...n.parentElement.children].filter((r) => r.localName === a);
1004
+ if (n.id && document.querySelectorAll(`#${bt(n.id)}`).length === 1)
1005
+ return e.unshift(`#${bt(n.id)}`), e.join(" > ");
1006
+ const a = n.localName, o = [...n.parentElement.children].filter((s) => s.localName === a);
991
1007
  e.unshift(o.length > 1 ? `${a}:nth-of-type(${o.indexOf(n) + 1})` : a), n = n.parentElement;
992
1008
  }
993
1009
  return ["body", ...e].join(" > ");
994
1010
  }
995
- function ba(t, e = Pn(t).selectors) {
1011
+ function ya(t, e = Nn(t).selectors) {
996
1012
  const n = t.getAttribute("data-twd");
997
1013
  if (n) return `[data-twd="${n.replace(/"/g, "")}"]`;
998
- const a = [...t.classList], r = a.find((s) => e.some((i) => new RegExp(`\\.${s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![\\w-])`).test(i))) || a[0];
999
- return r ? `.${mt(r)}` : null;
1014
+ const a = [...t.classList], s = a.find((r) => e.some((i) => new RegExp(`\\.${r.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![\\w-])`).test(i))) || a[0];
1015
+ return s ? `.${bt(s)}` : null;
1000
1016
  }
1001
- function xa(t) {
1002
- const e = Pn(t), n = ba(t, e.selectors), a = (t.getAttribute("aria-label") || t.placeholder || t.textContent || "").trim().replace(/\s+/g, " ");
1017
+ function ka(t) {
1018
+ const e = Nn(t), n = ya(t, e.selectors), a = (t.getAttribute("aria-label") || t.placeholder || t.textContent || "").trim().replace(/\s+/g, " ");
1003
1019
  return {
1004
1020
  el: t,
1005
1021
  tag: t.localName,
1006
1022
  classes: [...t.classList],
1007
1023
  text: a.length > 40 ? `${a.slice(0, 40)}…` : a,
1008
1024
  tokens: e.names,
1009
- elementSelector: ma(t),
1025
+ elementSelector: va(t),
1010
1026
  classSelector: n,
1011
1027
  classCount: n ? document.querySelectorAll(n).length : 0
1012
1028
  };
1013
1029
  }
1014
- const bt = (t) => t.localName + [...t.classList].map((e) => `.${e}`).join(""), wa = { radius: "px", intensity: "%", base: "px" }, On = (t) => t.charAt(0).toUpperCase() + t.slice(1), va = (t, e) => typeof e == "number" || /^\d+$/.test(e) ? `${e}${wa[t] || ""}` : On(String(e));
1015
- function Qt(t, e, n) {
1016
- const a = Mn(() => t.tokens({ [t.id]: e }) || {}), o = Object.keys(a);
1017
- let r = {};
1030
+ const xt = (t) => t.localName + [...t.classList].map((e) => `.${e}`).join(""), Sa = { radius: "px", intensity: "%", base: "px" }, jn = (t) => t.charAt(0).toUpperCase() + t.slice(1), $a = (t, e) => typeof e == "number" || /^\d+$/.test(e) ? `${e}${Sa[t] || ""}` : jn(String(e));
1031
+ function nn(t, e, n) {
1032
+ const a = On(() => t.tokens({ [t.id]: e }) || {}), o = Object.keys(a);
1033
+ let s = {};
1018
1034
  if (o.length) {
1019
- const s = n.selector ? document.querySelector(n.selector) : void 0;
1020
- r = da(o, s || void 0);
1035
+ const r = n.selector ? document.querySelector(n.selector) : void 0;
1036
+ s = ha(o, r || void 0);
1021
1037
  }
1022
1038
  return {
1023
1039
  ...n,
1024
1040
  sectionId: t.id,
1025
1041
  title: t.title,
1026
- settings: Object.entries(e).map(([s, i]) => ({ key: s, label: On(s), value: va(s, i), ...t.describe?.(s, i) || {} })),
1027
- tokens: o.map((s) => ({ name: s, from: r[s] || "", to: a[s] }))
1042
+ settings: Object.entries(e).map(([r, i]) => ({ key: r, label: jn(r), value: $a(r, i), ...t.describe?.(r, i) || {} })),
1043
+ tokens: o.map((r) => ({ name: r, from: s[r] || "", to: a[r] }))
1028
1044
  };
1029
1045
  }
1030
- function en(t, e) {
1046
+ function an(t, e) {
1031
1047
  const n = [];
1032
1048
  return e.forEach((a) => {
1033
- t[a.id] && n.push(Qt(a, t[a.id], { kind: "global", selector: null }));
1049
+ t[a.id] && n.push(nn(a, t[a.id], { kind: "global", selector: null }));
1034
1050
  }), Object.entries(t.scopes || {}).forEach(([a, o]) => {
1035
- const r = ft(a) ? "class" : "element";
1036
- e.forEach((s) => {
1037
- o[s.id] && n.push(Qt(s, o[s.id], { kind: r, selector: a }));
1051
+ const s = gt(a) ? "class" : "element";
1052
+ e.forEach((r) => {
1053
+ o[r.id] && n.push(nn(r, o[r.id], { kind: s, selector: a }));
1038
1054
  });
1039
1055
  }), n;
1040
1056
  }
1041
- function ya(t) {
1042
- const e = (o) => Object.values(o || {}).reduce((r, s) => r + Object.keys(s || {}).length, 0), { scopes: n, ...a } = t;
1043
- return e(a) + Object.values(n || {}).reduce((o, r) => o + e(r), 0);
1057
+ function Ea(t) {
1058
+ const e = (o) => Object.values(o || {}).reduce((s, r) => s + Object.keys(r || {}).length, 0), { scopes: n, ...a } = t;
1059
+ return e(a) + Object.values(n || {}).reduce((o, s) => o + e(s), 0);
1044
1060
  }
1045
- const ae = (t) => `\`${t}\``, Ze = (t) => t.map((e) => ` - ${ae(e.name)}: ${e.from ? `${ae(e.from)} → ` : ""}${ae(e.to)}`), Xe = (t) => `${t.title} › ${t.settings.map((e) => `${e.label}: ${e.value}`).join(", ")}`;
1046
- function ka(t) {
1061
+ const re = (t) => `\`${t}\``, Xe = (t) => t.map((e) => ` - ${re(e.name)}: ${e.from ? `${re(e.from)} → ` : ""}${re(e.to)}`), Je = (t) => `${t.title} › ${t.settings.map((e) => `${e.label}: ${e.value}`).join(", ")}`;
1062
+ function Ca(t) {
1047
1063
  let e = null;
1048
1064
  try {
1049
1065
  e = document.querySelector(t);
@@ -1051,58 +1067,58 @@ function ka(t) {
1051
1067
  }
1052
1068
  if (!e) return "not found on the current page";
1053
1069
  const n = (e.getAttribute("aria-label") || e.placeholder || e.textContent || "").trim().replace(/\s+/g, " ").slice(0, 60);
1054
- return `${ae(bt(e))}${n ? ` with text “${n}”` : ""}`;
1070
+ return `${re(xt(e))}${n ? ` with text “${n}”` : ""}`;
1055
1071
  }
1056
- function tn(t, e) {
1072
+ function on(t, e) {
1057
1073
  const n = /* @__PURE__ */ new Map();
1058
1074
  return t.forEach((a) => {
1059
1075
  const o = a[e];
1060
1076
  n.has(o) || n.set(o, []), n.get(o).push(a);
1061
1077
  }), [...n];
1062
1078
  }
1063
- function Sa(t, { link: e = location.href, warnings: n = [] } = {}) {
1079
+ function Ma(t, { link: e = location.href, warnings: n = [] } = {}) {
1064
1080
  if (!t.length) return "";
1065
- const a = t.filter((i) => i.kind === "global"), o = t.filter((i) => i.kind === "class"), r = t.filter((i) => i.kind === "element"), s = [];
1066
- if (s.push(
1081
+ const a = t.filter((i) => i.kind === "global"), o = t.filter((i) => i.kind === "class"), s = t.filter((i) => i.kind === "element"), r = [];
1082
+ if (r.push(
1067
1083
  "# Apply design tweaks from Panel",
1068
1084
  "",
1069
1085
  "I explored design changes to this prototype with Panel (by Twiddle), a tweak panel that overrides the prototype's `--twd-*` CSS custom properties (design tokens) at runtime. Make these changes permanent in the source code.",
1070
1086
  "",
1071
1087
  `Preview of the tweaked version: ${e}`
1072
- ), a.length && (s.push(
1088
+ ), a.length && (r.push(
1073
1089
  "",
1074
1090
  "## 1. Global token changes",
1075
1091
  "",
1076
1092
  "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.",
1077
1093
  ""
1078
- ), a.forEach((i) => s.push(`- **${Xe(i)}**`, ...Ze(i.tokens)))), o.length && (s.push(
1094
+ ), a.forEach((i) => r.push(`- **${Je(i)}**`, ...Xe(i.tokens)))), o.length && (r.push(
1079
1095
  "",
1080
1096
  `## ${a.length ? 2 : 1}. Component-wide changes`,
1081
1097
  "",
1082
1098
  "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.",
1083
1099
  ""
1084
- ), tn(o, "selector").forEach(([i, l]) => {
1085
- s.push(`- ${ae(i)} (${document.querySelectorAll(i).length} on this page)`), l.forEach((p) => s.push(` - **${Xe(p)}**`, ...Ze(p.tokens).map((c) => ` ${c}`)));
1086
- })), r.length) {
1100
+ ), on(o, "selector").forEach(([i, l]) => {
1101
+ r.push(`- ${re(i)} (${document.querySelectorAll(i).length} on this page)`), l.forEach((p) => r.push(` - **${Je(p)}**`, ...Xe(p.tokens).map((c) => ` ${c}`)));
1102
+ })), s.length) {
1087
1103
  const i = 1 + (a.length ? 1 : 0) + (o.length ? 1 : 0);
1088
- s.push(
1104
+ r.push(
1089
1105
  "",
1090
1106
  `## ${i}. Single-element changes`,
1091
1107
  "",
1092
1108
  "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.",
1093
1109
  ""
1094
- ), tn(r, "selector").forEach(([l, p]) => {
1095
- s.push(`- ${ka(l)}, found at ${ae(l)}`), p.forEach((c) => s.push(` - **${Xe(c)}**`, ...Ze(c.tokens).map((h) => ` ${h}`)));
1110
+ ), on(s, "selector").forEach(([l, p]) => {
1111
+ r.push(`- ${Ca(l)}, found at ${re(l)}`), p.forEach((c) => r.push(` - **${Je(c)}**`, ...Xe(c.tokens).map((h) => ` ${h}`)));
1096
1112
  });
1097
1113
  }
1098
- return n.length && s.push(
1114
+ return n.length && r.push(
1099
1115
  "",
1100
1116
  "## Contrast to check",
1101
1117
  "",
1102
1118
  "Panel flagged these colour pairs as below WCAG AA with the new values:",
1103
1119
  "",
1104
1120
  ...n.map((i) => `- ${i.text}`)
1105
- ), s.push(
1121
+ ), r.push(
1106
1122
  "",
1107
1123
  "## Constraints",
1108
1124
  "",
@@ -1110,71 +1126,71 @@ function Sa(t, { link: e = location.href, warnings: n = [] } = {}) {
1110
1126
  "- Change only what is listed above.",
1111
1127
  "- If a value uses `color-mix()` and the project targets older browsers, ask before converting it.",
1112
1128
  "- When done, list the files you changed."
1113
- ), s.join(`
1129
+ ), r.join(`
1114
1130
  `);
1115
1131
  }
1116
- const Re = 4.5, $a = 3, Ea = [
1132
+ const ze = 4.5, Ta = 3, Aa = [
1117
1133
  ["--twd-text", "--twd-bg", "Text on background"],
1118
1134
  ["--twd-text", "--twd-surface", "Text on surface"],
1119
1135
  ["--twd-text-muted", "--twd-surface", "Muted text on surface"],
1120
1136
  ["--twd-on-primary", "--twd-primary", "Text on brand"]
1121
1137
  ];
1122
- let W;
1123
- function St(t) {
1124
- if (!t || (W ||= Object.assign(document.createElement("canvas"), { width: 1, height: 1 }).getContext("2d", { willReadFrequently: !0 }), !W)) return null;
1125
- W.clearRect(0, 0, 1, 1), W.fillStyle = "#000", W.fillStyle = t, W.fillRect(0, 0, 1, 1);
1126
- const [e, n, a, o] = W.getImageData(0, 0, 1, 1).data;
1138
+ let Y;
1139
+ function $t(t) {
1140
+ if (!t || (Y ||= Object.assign(document.createElement("canvas"), { width: 1, height: 1 }).getContext("2d", { willReadFrequently: !0 }), !Y)) return null;
1141
+ Y.clearRect(0, 0, 1, 1), Y.fillStyle = "#000", Y.fillStyle = t, Y.fillRect(0, 0, 1, 1);
1142
+ const [e, n, a, o] = Y.getImageData(0, 0, 1, 1).data;
1127
1143
  return [e, n, a, o / 255];
1128
1144
  }
1129
- function nn(t) {
1145
+ function rn(t) {
1130
1146
  const e = document.createElement("i");
1131
1147
  e.style.cssText = `position:absolute;visibility:hidden;color:var(${t})`, document.documentElement.appendChild(e);
1132
1148
  const n = getComputedStyle(e).color;
1133
- return e.remove(), St(n);
1149
+ return e.remove(), $t(n);
1134
1150
  }
1135
- const an = ([t, e, n]) => {
1151
+ const sn = ([t, e, n]) => {
1136
1152
  const a = (o) => (o /= 255, o <= 0.03928 ? o / 12.92 : ((o + 0.055) / 1.055) ** 2.4);
1137
1153
  return 0.2126 * a(t) + 0.7152 * a(e) + 0.0722 * a(n);
1138
- }, Fn = (t, e) => t.slice(0, 3).map((n, a) => n * t[3] + e[a] * (1 - t[3])).concat(1);
1139
- function Nn(t, e) {
1140
- const n = an(t[3] < 1 ? Fn(t, e) : t), a = an(e);
1154
+ }, Rn = (t, e) => t.slice(0, 3).map((n, a) => n * t[3] + e[a] * (1 - t[3])).concat(1);
1155
+ function zn(t, e) {
1156
+ const n = sn(t[3] < 1 ? Rn(t, e) : t), a = sn(e);
1141
1157
  return (Math.max(n, a) + 0.05) / (Math.min(n, a) + 0.05);
1142
1158
  }
1143
- const jn = (t) => `${t.toFixed(1)}:1`;
1144
- function Je() {
1159
+ const In = (t) => `${t.toFixed(1)}:1`;
1160
+ function Qe() {
1145
1161
  const t = [];
1146
- return Ea.forEach(([e, n, a]) => {
1147
- const o = nn(e), r = nn(n);
1148
- if (!o || !r || r[3] === 0) return;
1149
- const s = Nn(o, r);
1150
- s < Re && t.push({ label: a, ratio: s, needed: Re, text: `${a}: ${jn(s)} · AA needs ${Re}` });
1162
+ return Aa.forEach(([e, n, a]) => {
1163
+ const o = rn(e), s = rn(n);
1164
+ if (!o || !s || s[3] === 0) return;
1165
+ const r = zn(o, s);
1166
+ r < ze && t.push({ label: a, ratio: r, needed: ze, text: `${a}: ${In(r)} · AA needs ${ze}` });
1151
1167
  }), t;
1152
1168
  }
1153
- function Ca(t) {
1169
+ function La(t) {
1154
1170
  const e = [];
1155
1171
  for (let n = t; n && n.nodeType === 1; n = n.parentElement) {
1156
- const a = St(getComputedStyle(n).backgroundColor);
1172
+ const a = $t(getComputedStyle(n).backgroundColor);
1157
1173
  if (a && a[3] > 0 && (e.push(a), a[3] >= 1))
1158
1174
  break;
1159
1175
  }
1160
- return e.reduceRight((n, a) => Fn(a, n), [255, 255, 255, 1]);
1176
+ return e.reduceRight((n, a) => Rn(a, n), [255, 255, 255, 1]);
1161
1177
  }
1162
- function Ta(t) {
1178
+ function Oa(t) {
1163
1179
  if (!t.textContent.trim() && !t.placeholder) return null;
1164
- const e = getComputedStyle(t), n = St(e.color);
1180
+ const e = getComputedStyle(t), n = $t(e.color);
1165
1181
  if (!n) return null;
1166
- const a = parseFloat(e.fontSize), r = a >= 24 || a >= 18.66 && parseInt(e.fontWeight, 10) >= 700 ? $a : Re, s = Nn(n, Ca(t));
1167
- return s < r ? { label: "This element", ratio: s, needed: r, text: `This element’s text: ${jn(s)} · AA needs ${r}` } : null;
1182
+ const a = parseFloat(e.fontSize), s = a >= 24 || a >= 18.66 && parseInt(e.fontWeight, 10) >= 700 ? Ta : ze, r = zn(n, La(t));
1183
+ return r < s ? { label: "This element", ratio: r, needed: s, text: `This element’s text: ${In(r)} · AA needs ${s}` } : null;
1168
1184
  }
1169
- const on = "twiddle-panel", Ma = "0.7.0", rn = "https://panel.twiddle.in", Aa = "--twd-radius-control", La = /var\(\s*--twd-/;
1170
- function Pa(t) {
1185
+ const ln = "twiddle-panel", Pa = "0.7.1", dn = "https://panel.twiddle.in", Fa = "--twd-radius-control", Na = /var\(\s*--twd-/;
1186
+ function ja(t) {
1171
1187
  return t.style.cssText.split(";").some((e) => {
1172
1188
  const n = e.slice(0, e.indexOf(":")).trim();
1173
- return n && !n.startsWith("--") && La.test(e);
1189
+ return n && !n.startsWith("--") && Na.test(e);
1174
1190
  });
1175
1191
  }
1176
- function Oa() {
1177
- if (!getComputedStyle(document.documentElement).getPropertyValue(Aa).trim()) return "no-tokens";
1192
+ function Ra() {
1193
+ if (!getComputedStyle(document.documentElement).getPropertyValue(Fa).trim()) return "no-tokens";
1178
1194
  let t = !1;
1179
1195
  for (const e of document.styleSheets) {
1180
1196
  if (e.ownerNode?.id === "twiddle-scoped") continue;
@@ -1185,11 +1201,11 @@ function Oa() {
1185
1201
  t = !0;
1186
1202
  continue;
1187
1203
  }
1188
- for (const a of Ue(n)) if (Pa(a)) return "ok";
1204
+ for (const a of qe(n)) if (ja(a)) return "ok";
1189
1205
  }
1190
1206
  return document.querySelector('[style*="var(--twd-"]') ? "ok" : t ? "unknown" : "unused";
1191
1207
  }
1192
- function Fa() {
1208
+ function za() {
1193
1209
  const t = /* @__PURE__ */ new Set(), e = (n) => {
1194
1210
  for (const a of n.matchAll(/var\(\s*(--twd-[\w-]+)/g)) t.add(a[1]);
1195
1211
  };
@@ -1201,19 +1217,19 @@ function Fa() {
1201
1217
  } catch {
1202
1218
  continue;
1203
1219
  }
1204
- for (const o of Ue(a))
1205
- o.style.cssText.split(";").forEach((r) => {
1206
- const s = r.slice(0, r.indexOf(":")).trim();
1207
- s && !s.startsWith("--") && e(r);
1220
+ for (const o of qe(a))
1221
+ o.style.cssText.split(";").forEach((s) => {
1222
+ const r = s.slice(0, s.indexOf(":")).trim();
1223
+ r && !r.startsWith("--") && e(s);
1208
1224
  });
1209
1225
  }
1210
1226
  return document.querySelectorAll('[style*="var(--twd-"]').forEach((n) => e(n.getAttribute("style"))), t;
1211
1227
  }
1212
- const sn = [
1213
- { label: "With a build tool, in your entry file", code: `import '${on}/tokens.css';` },
1228
+ const cn = [
1229
+ { label: "With a build tool, in your entry file", code: `import '${ln}/tokens.css';` },
1214
1230
  // Pinned to this build's version: unversioned jsDelivr links can lag a release by days, and unpkg once failed for a fresh one.
1215
- { label: "Plain HTML, in <head>", code: `<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/${on}@${Ma}/dist/twiddle-tokens.css">` }
1216
- ], Na = `Convert this prototype's styles to use the Panel design tokens (the --twd-* CSS custom properties from twiddle-panel), so the panel can tweak them live.
1231
+ { label: "Plain HTML, in <head>", code: `<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/${ln}@${Pa}/dist/twiddle-tokens.css">` }
1232
+ ], Ia = `Convert this prototype's styles to use the Panel design tokens (the --twd-* CSS custom properties from twiddle-panel), so the panel can tweak them live.
1217
1233
 
1218
1234
  1. Keep the current look. In a :root rule loaded after twiddle-tokens.css, set each token below to the value this project already uses (for example, if buttons use #0f766e, set --twd-primary: #0f766e). Only set the tokens the project actually needs.
1219
1235
  2. Replace fixed values in component styles with var(--twd-…). Map each value to the closest token by role:
@@ -1241,22 +1257,22 @@ function B(t) {
1241
1257
  const o = document.createElement("span");
1242
1258
  return o.className = "field-value", o.hidden = !0, n.append(a, o), e.append(n), {
1243
1259
  el: e,
1244
- setValue(r) {
1245
- o.textContent = r || "", o.hidden = !r;
1260
+ setValue(s) {
1261
+ o.textContent = s || "", o.hidden = !s;
1246
1262
  },
1247
- append(...r) {
1248
- e.append(...r);
1263
+ append(...s) {
1264
+ e.append(...s);
1249
1265
  }
1250
1266
  };
1251
1267
  }
1252
- function ja({ label: t, ends: e, cols: n = 9, rows: a = 5, onInput: o }) {
1253
- const r = document.createElement("div");
1254
- r.className = "pad", r.tabIndex = 0, r.setAttribute("role", "group"), r.setAttribute("aria-roledescription", "2D slider");
1255
- const s = (b, u) => {
1268
+ function Da({ label: t, ends: e, cols: n = 9, rows: a = 5, onInput: o }) {
1269
+ const s = document.createElement("div");
1270
+ s.className = "pad", s.tabIndex = 0, s.setAttribute("role", "group"), s.setAttribute("aria-roledescription", "2D slider");
1271
+ const r = (b, u) => {
1256
1272
  const v = document.createElement("span");
1257
1273
  return v.className = `pad-edge ${b}`, v.textContent = u, v.setAttribute("aria-hidden", "true"), v;
1258
1274
  };
1259
- r.append(s("top", e.top), s("bottom", e.bottom), s("left", e.left), s("right", e.right));
1275
+ s.append(r("top", e.top), r("bottom", e.bottom), r("left", e.left), r("right", e.right));
1260
1276
  const i = document.createElement("div");
1261
1277
  i.className = "pad-area";
1262
1278
  for (let b = 0; b < a; b++)
@@ -1265,7 +1281,7 @@ function ja({ label: t, ends: e, cols: n = 9, rows: a = 5, onInput: o }) {
1265
1281
  v.className = "pad-dot", v.style.left = `${u / (n - 1) * 100}%`, v.style.top = `${b / (a - 1) * 100}%`, i.append(v);
1266
1282
  }
1267
1283
  const l = document.createElement("span");
1268
- l.className = "pad-knob", i.append(l), r.append(i);
1284
+ l.className = "pad-knob", i.append(l), s.append(i);
1269
1285
  let p = 0.5, c = 0.5;
1270
1286
  const h = (b, u) => Math.round(Math.min(1, Math.max(0, b)) * (u - 1)) / (u - 1);
1271
1287
  function y() {
@@ -1278,76 +1294,76 @@ function ja({ label: t, ends: e, cols: n = 9, rows: a = 5, onInput: o }) {
1278
1294
  const u = i.getBoundingClientRect();
1279
1295
  f((b.clientX - u.left) / u.width, (b.clientY - u.top) / u.height);
1280
1296
  };
1281
- r.addEventListener("pointerdown", (b) => {
1282
- r.setPointerCapture(b.pointerId), r.classList.add("dragging"), m(b);
1283
- }), r.addEventListener("pointermove", (b) => {
1284
- r.hasPointerCapture(b.pointerId) && m(b);
1297
+ s.addEventListener("pointerdown", (b) => {
1298
+ s.setPointerCapture(b.pointerId), s.classList.add("dragging"), m(b);
1299
+ }), s.addEventListener("pointermove", (b) => {
1300
+ s.hasPointerCapture(b.pointerId) && m(b);
1285
1301
  });
1286
1302
  const x = (b) => {
1287
- r.hasPointerCapture(b.pointerId) && r.releasePointerCapture(b.pointerId), r.classList.remove("dragging");
1303
+ s.hasPointerCapture(b.pointerId) && s.releasePointerCapture(b.pointerId), s.classList.remove("dragging");
1288
1304
  };
1289
- return r.addEventListener("pointerup", x), r.addEventListener("pointercancel", x), r.addEventListener("keydown", (b) => {
1305
+ return s.addEventListener("pointerup", x), s.addEventListener("pointercancel", x), s.addEventListener("keydown", (b) => {
1290
1306
  const u = { ArrowLeft: [-1, 0], ArrowRight: [1, 0], ArrowUp: [0, -1], ArrowDown: [0, 1] }[b.key];
1291
1307
  u && (b.preventDefault(), u[0] ? f(h(p, n) + u[0] / (n - 1), c, "y") : f(p, h(c, a) + u[1] / (a - 1), "x"));
1292
1308
  }), {
1293
- el: r,
1309
+ el: s,
1294
1310
  /** Show a position without telling anyone (used to sync). Off-grid values are shown as they are. */
1295
1311
  setValue(b, u, v) {
1296
- p = Math.min(1, Math.max(0, b)), c = Math.min(1, Math.max(0, u)), y(), r.setAttribute("aria-label", v ? `${t}: ${v}` : t);
1312
+ p = Math.min(1, Math.max(0, b)), c = Math.min(1, Math.max(0, u)), y(), s.setAttribute("aria-label", v ? `${t}: ${v}` : t);
1297
1313
  }
1298
1314
  };
1299
1315
  }
1300
- function Rn({ label: t, min: e, max: n, step: a = 1, format: o = String, onInput: r }) {
1301
- const s = document.createElement("div");
1302
- s.className = "slider";
1316
+ function Dn({ label: t, min: e, max: n, step: a = 1, format: o = String, onInput: s }) {
1317
+ const r = document.createElement("div");
1318
+ r.className = "slider";
1303
1319
  const i = document.createElement("input");
1304
1320
  i.type = "range", i.min = String(e), i.max = String(n), i.step = String(a), i.setAttribute("aria-label", t);
1305
1321
  const l = document.createElement("span");
1306
- l.className = "slider-value", l.setAttribute("aria-hidden", "true"), s.append(i, l);
1322
+ l.className = "slider-value", l.setAttribute("aria-hidden", "true"), r.append(i, l);
1307
1323
  const p = (c) => {
1308
1324
  const h = (Number(i.value) - e) / (n - e) * 100;
1309
1325
  i.style.setProperty("--fill", `${h}%`), l.textContent = c ?? o(Number(i.value)), i.setAttribute("aria-valuetext", l.textContent);
1310
1326
  };
1311
1327
  return i.addEventListener("input", () => {
1312
- p(), r(Number(i.value));
1328
+ p(), s(Number(i.value));
1313
1329
  }), {
1314
- el: s,
1330
+ el: r,
1315
1331
  /** Show a value without reporting it (sync after reset / URL load). */
1316
1332
  setValue(c, h) {
1317
1333
  i.value = String(c), p(h);
1318
1334
  }
1319
1335
  };
1320
1336
  }
1321
- function Ra({ label: t, options: e, columns: n = 3, className: a = "", onSelect: o }) {
1322
- const r = document.createElement("div");
1323
- r.className = `tiles ${a}`.trim(), r.style.setProperty("--cols", n), r.setAttribute("role", "radiogroup"), r.setAttribute("aria-label", t);
1324
- const s = e.map((c) => {
1337
+ function Ba({ label: t, options: e, columns: n = 3, className: a = "", onSelect: o }) {
1338
+ const s = document.createElement("div");
1339
+ s.className = `tiles ${a}`.trim(), s.style.setProperty("--cols", n), s.setAttribute("role", "radiogroup"), s.setAttribute("aria-label", t);
1340
+ const r = e.map((c) => {
1325
1341
  const h = document.createElement("button");
1326
1342
  return h.type = "button", h.className = "tile", c.wide && h.classList.add("wide"), h.setAttribute("role", "radio"), h.dataset.value = c.value, c.title && (h.title = c.title), h.innerHTML = `${c.preview ? `<span class="tile-preview" aria-hidden="true">${c.preview}</span>` : ""}<span class="tile-text"><span class="tile-label"></span>${c.sub ? '<span class="tile-sub"></span>' : ""}</span>`, h.querySelector(".tile-label").textContent = c.label, c.sub && (h.querySelector(".tile-sub").textContent = c.sub), h.addEventListener("click", () => p(c.value)), h;
1327
1343
  });
1328
- r.append(...s);
1344
+ s.append(...r);
1329
1345
  let i = null;
1330
1346
  function l(c) {
1331
- i = c, s.forEach((y) => y.setAttribute("aria-checked", String(y.dataset.value === c)));
1332
- const h = Math.max(0, s.findIndex((y) => y.dataset.value === c));
1333
- s.forEach((y, f) => {
1347
+ i = c, r.forEach((y) => y.setAttribute("aria-checked", String(y.dataset.value === c)));
1348
+ const h = Math.max(0, r.findIndex((y) => y.dataset.value === c));
1349
+ r.forEach((y, f) => {
1334
1350
  y.tabIndex = f === h ? 0 : -1;
1335
1351
  });
1336
1352
  }
1337
1353
  function p(c, h) {
1338
- c !== i && (l(c), o(c)), h && s.find((y) => y.dataset.value === c).focus();
1354
+ c !== i && (l(c), o(c)), h && r.find((y) => y.dataset.value === c).focus();
1339
1355
  }
1340
- return r.addEventListener("keydown", (c) => {
1341
- const h = s.indexOf(c.target.closest(".tile"));
1356
+ return s.addEventListener("keydown", (c) => {
1357
+ const h = r.indexOf(c.target.closest(".tile"));
1342
1358
  if (h < 0) return;
1343
1359
  const y = { ArrowRight: 1, ArrowDown: 1, ArrowLeft: -1, ArrowUp: -1 }[c.key];
1344
1360
  let f;
1345
- if (y) f = (h + y + s.length) % s.length;
1361
+ if (y) f = (h + y + r.length) % r.length;
1346
1362
  else if (c.key === "Home") f = 0;
1347
- else if (c.key === "End") f = s.length - 1;
1363
+ else if (c.key === "End") f = r.length - 1;
1348
1364
  else return;
1349
- c.preventDefault(), p(s[f].dataset.value, !0);
1350
- }), l(null), { el: r, setValue: l };
1365
+ c.preventDefault(), p(r[f].dataset.value, !0);
1366
+ }), l(null), { el: s, setValue: l };
1351
1367
  }
1352
1368
  const F = (t) => getComputedStyle(document.documentElement).getPropertyValue(t).trim();
1353
1369
  function ye(t, e) {
@@ -1356,11 +1372,11 @@ function ye(t, e) {
1356
1372
  const a = parseFloat(n[1]) * e, o = n[2] || "px";
1357
1373
  return o === "px" ? `${Math.round(a)}px` : `${+a.toFixed(3)}${o}`;
1358
1374
  }
1359
- const za = 999;
1360
- function zn({ id: t, title: e, hint: n, token: a, uses: o = [], presets: r, max: s, extra: i = [], extraTokens: l = () => ({}), shape: p = "card" }) {
1361
- const c = (f) => r.find((m) => m.value === f), h = (f) => f >= za ? "full" : `${f}px`, y = (f) => {
1375
+ const Ua = 999;
1376
+ function Bn({ id: t, title: e, hint: n, token: a, uses: o = [], presets: s, max: r, extra: i = [], extraTokens: l = () => ({}), shape: p = "card" }) {
1377
+ const c = (f) => s.find((m) => m.value === f), h = (f) => f >= Ua ? "full" : `${f}px`, y = (f) => {
1362
1378
  if (typeof f.radius == "number" && isFinite(f.radius))
1363
- return { [a]: `${Math.min(Math.max(f.radius, 0), s)}px` };
1379
+ return { [a]: `${Math.min(Math.max(f.radius, 0), r)}px` };
1364
1380
  const m = c(f.corners);
1365
1381
  return m ? { [a]: `${m.radius}px` } : {};
1366
1382
  };
@@ -1368,7 +1384,7 @@ function zn({ id: t, title: e, hint: n, token: a, uses: o = [], presets: r, max:
1368
1384
  id: t,
1369
1385
  title: e,
1370
1386
  hint: n,
1371
- presets: r,
1387
+ presets: s,
1372
1388
  uses: [a, ...o],
1373
1389
  tokens(f) {
1374
1390
  const m = f[t] || {};
@@ -1378,25 +1394,25 @@ function zn({ id: t, title: e, hint: n, token: a, uses: o = [], presets: r, max:
1378
1394
  // Each takes an optional label (e.g. "Buttons" on the Corners page).
1379
1395
  parts: {
1380
1396
  corners(f, m, { label: x = "Corners" } = {}) {
1381
- const b = B(x), u = re({
1397
+ const b = B(x), u = ie({
1382
1398
  label: `${e} corners`,
1383
- options: r.map((E) => ({ value: E.value, label: E.label, title: h(E.radius) })),
1399
+ options: s.map((E) => ({ value: E.value, label: E.label, title: h(E.radius) })),
1384
1400
  onSelect: (E) => m.setSection(t, { corners: E, radius: null })
1385
- }), v = Rn({
1401
+ }), v = Dn({
1386
1402
  label: `${e} corner radius`,
1387
1403
  min: 0,
1388
- max: s,
1404
+ max: r,
1389
1405
  format: h,
1390
1406
  onInput: (E) => m.setSection(t, { radius: E, corners: null })
1391
1407
  });
1392
1408
  b.append(u.el, v.el), f.append(b.el);
1393
1409
  const L = () => {
1394
- const E = parseFloat((m.readToken || F)(a)), J = m.getState()[t] || {}, K = c(J.corners) || r.find((G) => G.radius === E);
1410
+ const E = parseFloat((m.readToken || F)(a)), Q = m.getState()[t] || {}, K = c(Q.corners) || s.find((G) => G.radius === E);
1395
1411
  if (u.setValue(K ? K.value : null), isNaN(E)) {
1396
1412
  v.setValue(0, "—"), b.setValue("");
1397
1413
  return;
1398
1414
  }
1399
- v.setValue(Math.min(E, s), h(E)), b.setValue(h(E));
1415
+ v.setValue(Math.min(E, r), h(E)), b.setValue(h(E));
1400
1416
  };
1401
1417
  L(), m.onChange(L);
1402
1418
  },
@@ -1408,13 +1424,13 @@ function zn({ id: t, title: e, hint: n, token: a, uses: o = [], presets: r, max:
1408
1424
  section: t,
1409
1425
  key: "corners",
1410
1426
  label: x,
1411
- columns: r.length,
1412
- options: r.map((u) => ({ value: u.value, label: u.label, title: h(u.radius), preview: b(u.radius) })),
1427
+ columns: s.length,
1428
+ options: s.map((u) => ({ value: u.value, label: u.label, title: h(u.radius), preview: b(u.radius) })),
1413
1429
  current: (u) => {
1414
1430
  const v = u[t] || {};
1415
1431
  if (v.radius != null) return null;
1416
1432
  const L = parseFloat((m.readToken || F)(a));
1417
- return (c(v.corners) || r.find((E) => E.radius === L))?.value || null;
1433
+ return (c(v.corners) || s.find((E) => E.radius === L))?.value || null;
1418
1434
  },
1419
1435
  select: (u) => m.setSection(t, { corners: u, radius: null }),
1420
1436
  valueText: () => {
@@ -1437,34 +1453,34 @@ function zn({ id: t, title: e, hint: n, token: a, uses: o = [], presets: r, max:
1437
1453
  }
1438
1454
  };
1439
1455
  }
1440
- function ke(t, { section: e, key: n, label: a, options: o, fallback: r, valueText: s }) {
1441
- const i = B(a), l = re({
1456
+ function ke(t, { section: e, key: n, label: a, options: o, fallback: s, valueText: r }) {
1457
+ const i = B(a), l = ie({
1442
1458
  label: a,
1443
1459
  options: o,
1444
1460
  onSelect: (c) => t.setSection(e, { [n]: c })
1445
1461
  });
1446
1462
  i.append(l.el);
1447
1463
  const p = () => {
1448
- const c = (t.getState()[e] || {})[n] || r;
1449
- l.setValue(c), i.setValue(s ? s(c) : "");
1464
+ const c = (t.getState()[e] || {})[n] || s;
1465
+ l.setValue(c), i.setValue(r ? r(c) : "");
1450
1466
  };
1451
1467
  return p(), t.onChange(p), i.el;
1452
1468
  }
1453
- function Ia(t, { section: e, key: n, label: a, min: o, max: r, fallback: s, format: i }) {
1454
- const l = B(a), p = Rn({ label: a, min: o, max: r, format: i, onInput: (h) => t.setSection(e, { [n]: h }) });
1469
+ function qa(t, { section: e, key: n, label: a, min: o, max: s, fallback: r, format: i }) {
1470
+ const l = B(a), p = Dn({ label: a, min: o, max: s, format: i, onInput: (h) => t.setSection(e, { [n]: h }) });
1455
1471
  l.append(p.el);
1456
1472
  const c = () => {
1457
1473
  const h = (t.getState()[e] || {})[n];
1458
- p.setValue(typeof h == "number" ? h : s);
1474
+ p.setValue(typeof h == "number" ? h : r);
1459
1475
  };
1460
1476
  return c(), t.onChange(c), l.el;
1461
1477
  }
1462
- function V(t, { section: e, key: n, label: a, options: o, columns: r = 3, className: s = "", fallback: i, valueText: l, current: p, select: c }) {
1463
- const h = B(a), y = Ra({
1478
+ function V(t, { section: e, key: n, label: a, options: o, columns: s = 3, className: r = "", fallback: i, valueText: l, current: p, select: c }) {
1479
+ const h = B(a), y = Ba({
1464
1480
  label: a,
1465
1481
  options: o,
1466
- columns: r,
1467
- className: s,
1482
+ columns: s,
1483
+ className: r,
1468
1484
  onSelect: (m) => c ? c(m) : t.setSection(e, { [n]: m })
1469
1485
  });
1470
1486
  h.append(y.el);
@@ -1474,13 +1490,13 @@ function V(t, { section: e, key: n, label: a, options: o, columns: r = 3, classN
1474
1490
  };
1475
1491
  return f(), t.onChange(f), h.el;
1476
1492
  }
1477
- const ln = (t, e) => e.map((n) => `${t}${n}`), In = {
1493
+ const pn = (t, e) => e.map((n) => `${t}${n}`), Un = {
1478
1494
  fonts: { label: "Tokens", tokens: ["font-heading", "font-body"], kind: "text" },
1479
- type: { label: "Tokens", tokens: ln("text-", ["xs", "sm", "base", "lg", "xl", "2xl", "3xl"]), kind: "length" },
1495
+ type: { label: "Tokens", tokens: pn("text-", ["xs", "sm", "base", "lg", "xl", "2xl", "3xl"]), kind: "length" },
1480
1496
  leading: { label: "Line height", tokens: ["leading-tight", "leading-normal"], kind: "number" },
1481
1497
  weights: { label: "Weights", tokens: ["weight-heading", "weight-strong"], kind: "number" },
1482
1498
  colours: { label: "Tokens", tokens: ["bg", "surface", "surface-raised", "text", "text-muted", "border", "primary", "primary-hover", "on-primary", "focus", "success", "warning", "danger"], kind: "colour" },
1483
- spacing: { label: "Steps", tokens: ln("space-", [1, 2, 3, 4, 5, 6, 7, 8]), kind: "length", bar: 64 },
1499
+ spacing: { label: "Steps", tokens: pn("space-", [1, 2, 3, 4, 5, 6, 7, 8]), kind: "length", bar: 64 },
1484
1500
  controls: { label: "Controls", tokens: ["control-height", "control-pad-x"], kind: "length" },
1485
1501
  corners: { label: "Tokens", tokens: ["radius-control", "radius-container"], kind: "length" },
1486
1502
  borders: { label: "Tokens", tokens: ["border-width", "border-width-container"], kind: "length" },
@@ -1488,16 +1504,16 @@ const ln = (t, e) => e.map((n) => `${t}${n}`), In = {
1488
1504
  buttonStyle: { label: "Button", tokens: ["button-bg", "button-fg", "button-border", "button-hover"], kind: "colour" },
1489
1505
  cardStyle: { label: "Card", tokens: ["card-bg", "card-border"], kind: "colour" },
1490
1506
  cardShadow: { label: "Card shadow", tokens: ["card-shadow"], kind: "text" }
1491
- }, _ = (t) => `--twd-${t}`, Qe = (t, e) => Object.prototype.hasOwnProperty.call(t.getState().custom || {}, e), dn = (t, e) => In[e].tokens.some((n) => (t.custom || {})[n] != null);
1492
- function Da(t, e) {
1507
+ }, _ = (t) => `--twd-${t}`, et = (t, e) => Object.prototype.hasOwnProperty.call(t.getState().custom || {}, e), un = (t, e) => Un[e].tokens.some((n) => (t.custom || {})[n] != null);
1508
+ function Va(t, e) {
1493
1509
  const n = /^(-?\d*\.?\d+)(px|rem)?$/.exec(String(t).trim());
1494
1510
  return !n || e === "text" || e === "colour" ? null : n[2] === "rem" ? { n: +(parseFloat(n[1]) * 16).toFixed(1), unit: "px" } : { n: +parseFloat(n[1]).toFixed(3), unit: n[2] || (e === "length" ? "px" : "") };
1495
1511
  }
1496
- function Ba(t, e) {
1512
+ function Ha(t, e) {
1497
1513
  const n = t.trim();
1498
1514
  return n ? e === "length" && /^-?\d*\.?\d+$/.test(n) ? `${n}px` : n : null;
1499
1515
  }
1500
- function Ua(t, e, n, a) {
1516
+ function _a(t, e, n, a) {
1501
1517
  const o = document.createElement("div");
1502
1518
  o.className = `token-row kind-${n}`, o.innerHTML = `
1503
1519
  <code class="token-name" title="${_(e)}">${e}</code>
@@ -1510,29 +1526,29 @@ function Ua(t, e, n, a) {
1510
1526
  </label>
1511
1527
  <button class="icon-btn token-reset" title="Back to the page’s value" aria-label="Reset ${_(e)}" hidden>${A.reset}</button>
1512
1528
  `;
1513
- const r = o.querySelector("input"), s = o.querySelector(".token-unit"), i = o.querySelector(".token-bar span"), l = o.querySelector(".token-swatch"), p = o.querySelector(".custom-tag"), c = o.querySelector(".token-reset");
1529
+ const s = o.querySelector("input"), r = o.querySelector(".token-unit"), i = o.querySelector(".token-bar span"), l = o.querySelector(".token-swatch"), p = o.querySelector(".custom-tag"), c = o.querySelector(".token-reset");
1514
1530
  let h = "";
1515
1531
  const y = () => {
1516
- let m = r.value;
1532
+ let m = s.value;
1517
1533
  h && /^-?\d*\.?\d+$/.test(m.trim()) && (m = `${m.trim()}${h}`);
1518
- const x = Ba(m, n), b = F(_(e));
1534
+ const x = Ha(m, n), b = F(_(e));
1519
1535
  if (x === null) {
1520
- Qe(t, e) ? t.setSection("custom", { [e]: null }) : f();
1536
+ et(t, e) ? t.setSection("custom", { [e]: null }) : f();
1521
1537
  return;
1522
1538
  }
1523
- if (x === b && !Qe(t, e)) return f();
1539
+ if (x === b && !et(t, e)) return f();
1524
1540
  t.setSection("custom", { [e]: x });
1525
1541
  };
1526
- r.addEventListener("change", y), r.addEventListener("blur", () => f()), r.addEventListener("keydown", (m) => {
1527
- m.key === "Enter" && (m.preventDefault(), r.blur()), m.key === "Escape" && (m.stopPropagation(), f(), r.blur());
1542
+ s.addEventListener("change", y), s.addEventListener("blur", () => f()), s.addEventListener("keydown", (m) => {
1543
+ m.key === "Enter" && (m.preventDefault(), s.blur()), m.key === "Escape" && (m.stopPropagation(), f(), s.blur());
1528
1544
  }), c.addEventListener("click", () => t.setSection("custom", { [e]: null }));
1529
1545
  function f() {
1530
- const m = F(_(e)), x = Qe(t, e), b = Da(m, n);
1531
- h = b ? b.unit : "", document.activeElement !== r && o.getRootNode().activeElement !== r && (r.value = b ? String(b.n) : m), r.title = m, s.textContent = h, s.hidden = !h, 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), p.hidden = !x, c.hidden = !x;
1546
+ const m = F(_(e)), x = et(t, e), b = Va(m, n);
1547
+ h = b ? b.unit : "", document.activeElement !== s && o.getRootNode().activeElement !== s && (s.value = b ? String(b.n) : m), s.title = m, r.textContent = h, r.hidden = !h, 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), p.hidden = !x, c.hidden = !x;
1532
1548
  }
1533
1549
  return f(), t.onChange(f), o;
1534
1550
  }
1535
- const qa = {
1551
+ const Ka = {
1536
1552
  id: "custom",
1537
1553
  title: "Custom tokens",
1538
1554
  hint: "Any token, set to a fixed value",
@@ -1543,69 +1559,69 @@ const qa = {
1543
1559
  },
1544
1560
  describe: (t, e) => ({ label: _(t), value: String(e) }),
1545
1561
  // One part per Edit page group, e.g. parts.spacing → rows for --twd-space-1 … 8.
1546
- parts: Object.fromEntries(Object.entries(In).map(([t, e]) => [t, (n, a, { label: o = e.label } = {}) => {
1547
- const r = B(o);
1548
- r.el.classList.add("token-field");
1549
- const s = e.tokens[0], i = e.tokens[e.tokens.length - 1];
1550
- r.setValue(e.tokens.length > 2 && /-\w+$/.test(s) ? `${_(s)} … ${i.split("-").pop()}` : "");
1562
+ parts: Object.fromEntries(Object.entries(Un).map(([t, e]) => [t, (n, a, { label: o = e.label } = {}) => {
1563
+ const s = B(o);
1564
+ s.el.classList.add("token-field");
1565
+ const r = e.tokens[0], i = e.tokens[e.tokens.length - 1];
1566
+ s.setValue(e.tokens.length > 2 && /-\w+$/.test(r) ? `${_(r)} … ${i.split("-").pop()}` : "");
1551
1567
  const l = document.createElement("div");
1552
- l.className = "token-rows", e.tokens.forEach((p) => l.append(Ua(a, p, e.kind, e.bar))), r.append(l), n.append(r.el);
1568
+ l.className = "token-rows", e.tokens.forEach((p) => l.append(_a(a, p, e.kind, e.bar))), s.append(l), n.append(s.el);
1553
1569
  }]))
1554
- }, we = { compact: 0.75, regular: 1, comfy: 1.25 }, xt = [0.75, 1.25], cn = [1, 2, 3, 4, 5, 6, 7, 8].map((t) => `--twd-space-${t}`);
1555
- function te(t = {}) {
1556
- return typeof t.factor == "number" && isFinite(t.factor) ? Math.min(xt[1], Math.max(xt[0], t.factor)) : we[t.spacing] || 1;
1570
+ }, we = { compact: 0.75, regular: 1, comfy: 1.25 }, wt = [0.75, 1.25], hn = [1, 2, 3, 4, 5, 6, 7, 8].map((t) => `--twd-space-${t}`);
1571
+ function ae(t = {}) {
1572
+ return typeof t.factor == "number" && isFinite(t.factor) ? Math.min(wt[1], Math.max(wt[0], t.factor)) : we[t.spacing] || 1;
1557
1573
  }
1558
- const et = (t) => `${Math.round(t * 100)}%`, Va = {
1574
+ const tt = (t) => `${Math.round(t * 100)}%`, Ga = {
1559
1575
  id: "density",
1560
1576
  title: "Density",
1561
1577
  hint: "Compact · regular · comfortable",
1562
- uses: cn,
1578
+ uses: hn,
1563
1579
  tokens(t) {
1564
- const e = te(t.density);
1580
+ const e = ae(t.density);
1565
1581
  if (e === 1) return {};
1566
1582
  const n = {};
1567
- return cn.forEach((a) => {
1583
+ return hn.forEach((a) => {
1568
1584
  const o = ye(F(a), e);
1569
1585
  o && (n[a] = o);
1570
1586
  }), n;
1571
1587
  },
1572
1588
  /** How the Changes list and prompt describe a setting. */
1573
- describe: (t, e) => t === "factor" ? { label: "Spacing", value: et(e) } : null,
1589
+ describe: (t, e) => t === "factor" ? { label: "Spacing", value: tt(e) } : null,
1574
1590
  parts: {
1575
1591
  // Tabbed layout: presets as tiles with a tiny layout sketch.
1576
1592
  spacingTiles(t, e, { label: n = "Density" } = {}) {
1577
- const a = (o, r) => `<span class="sketch" style="padding:${r}px;gap:${o}px"><i></i><i></i><i></i></span>`;
1593
+ const a = (o, s) => `<span class="sketch" style="padding:${s}px;gap:${o}px"><i></i><i></i><i></i></span>`;
1578
1594
  t.append(V(e, {
1579
1595
  section: "density",
1580
1596
  key: "spacing",
1581
1597
  label: n,
1582
1598
  options: [{ value: "compact", label: "Compact", preview: a(2, 5) }, { value: "regular", label: "Regular", preview: a(4, 8) }, { value: "comfy", label: "Comfy", preview: a(6, 11) }],
1583
1599
  current: (o) => {
1584
- const r = te(o.density);
1585
- return Object.keys(we).find((s) => we[s] === r) || null;
1600
+ const s = ae(o.density);
1601
+ return Object.keys(we).find((r) => we[r] === s) || null;
1586
1602
  },
1587
1603
  select: (o) => e.setSection("density", { spacing: o, factor: null }),
1588
- valueText: (o, r) => dn(r, "spacing") ? "Custom" : o ? "" : et(te(r.density))
1604
+ valueText: (o, s) => un(s, "spacing") ? "Custom" : o ? "" : tt(ae(s.density))
1589
1605
  }));
1590
1606
  },
1591
1607
  spacing(t, e, { label: n = "Spacing" } = {}) {
1592
- const a = B(n), o = re({
1608
+ const a = B(n), o = ie({
1593
1609
  label: n,
1594
1610
  options: [{ value: "compact", label: "Compact" }, { value: "regular", label: "Regular" }, { value: "comfy", label: "Comfy" }],
1595
- onSelect: (s) => e.setSection("density", { spacing: s, factor: null })
1611
+ onSelect: (r) => e.setSection("density", { spacing: r, factor: null })
1596
1612
  });
1597
1613
  a.append(o.el);
1598
- const r = () => {
1599
- const s = e.getState().density || {}, i = te(s), l = Object.keys(we).find((p) => we[p] === i);
1600
- o.setValue(l || null), a.setValue(dn(e.getState(), "spacing") ? "Custom" : l ? "" : et(i));
1614
+ const s = () => {
1615
+ const r = e.getState().density || {}, i = ae(r), l = Object.keys(we).find((p) => we[p] === i);
1616
+ o.setValue(l || null), a.setValue(un(e.getState(), "spacing") ? "Custom" : l ? "" : tt(i));
1601
1617
  };
1602
- r(), e.onChange(r), t.append(a.el);
1618
+ s(), e.onChange(s), t.append(a.el);
1603
1619
  }
1604
1620
  },
1605
1621
  render(t, e) {
1606
1622
  Object.entries(this.parts).filter(([n]) => !n.endsWith("Tiles")).forEach(([, n]) => n(t, e));
1607
1623
  }
1608
- }, Ha = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14 6l4 4M4 20l1-4 9.5-9.5a2.1 2.1 0 013 3L8 19l-4 1z"/></svg>', _a = [
1624
+ }, Wa = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14 6l4 4M4 20l1-4 9.5-9.5a2.1 2.1 0 013 3L8 19l-4 1z"/></svg>', Ya = [
1609
1625
  [50, "white", 10],
1610
1626
  [100, "white", 20],
1611
1627
  [200, "white", 36],
@@ -1617,35 +1633,35 @@ const et = (t) => `${Math.round(t * 100)}%`, Va = {
1617
1633
  [800, "black", 58],
1618
1634
  [900, "black", 45],
1619
1635
  [950, "black", 30]
1620
- ], tt = (t) => {
1636
+ ], nt = (t) => {
1621
1637
  let e = String(t).trim().replace(/^#/, "");
1622
1638
  return /^[0-9a-f]{3}$/i.test(e) && (e = e.split("").map((n) => n + n).join("")), /^[0-9a-f]{6}$/i.test(e) ? `#${e.toUpperCase()}` : null;
1623
1639
  };
1624
- function Ka({ label: t, onInput: e }) {
1640
+ function Za({ label: t, onInput: e }) {
1625
1641
  const n = document.createElement("div");
1626
1642
  n.className = "colour";
1627
1643
  const a = document.createElement("div");
1628
1644
  a.className = "colour-field";
1629
1645
  const o = document.createElement("input");
1630
1646
  o.type = "color", o.className = "colour-picker", o.tabIndex = -1, o.setAttribute("aria-hidden", "true");
1631
- const r = document.createElement("button");
1632
- r.type = "button", r.className = "colour-swatch", r.setAttribute("aria-label", `${t}: open colour picker`);
1633
- const s = document.createElement("input");
1634
- s.type = "text", s.className = "colour-hex", s.spellcheck = !1, s.maxLength = 7, s.setAttribute("aria-label", `${t} hex value`);
1647
+ const s = document.createElement("button");
1648
+ s.type = "button", s.className = "colour-swatch", s.setAttribute("aria-label", `${t}: open colour picker`);
1649
+ const r = document.createElement("input");
1650
+ r.type = "text", r.className = "colour-hex", r.spellcheck = !1, r.maxLength = 7, r.setAttribute("aria-label", `${t} hex value`);
1635
1651
  const i = document.createElement("button");
1636
- i.type = "button", i.className = "colour-pipette", i.innerHTML = Ha, i.title = "Pick a colour from the screen", i.setAttribute("aria-label", "Pick a colour from the screen"), a.append(o, r, s, i);
1652
+ i.type = "button", i.className = "colour-pipette", i.innerHTML = Wa, i.title = "Pick a colour from the screen", i.setAttribute("aria-label", "Pick a colour from the screen"), a.append(o, s, r, i);
1637
1653
  const l = document.createElement("div");
1638
- l.className = "ramp", l.setAttribute("aria-hidden", "true"), l.innerHTML = _a.map(([f, m, x]) => {
1654
+ l.className = "ramp", l.setAttribute("aria-hidden", "true"), l.innerHTML = Ya.map(([f, m, x]) => {
1639
1655
  const b = m ? `color-mix(in oklch, var(--brand) ${x}%, ${m})` : "var(--brand)";
1640
1656
  return `<span title="${f}" style="background:${b}"></span>`;
1641
1657
  }).join(""), n.append(a, l);
1642
1658
  let p = "#000000";
1643
1659
  const c = (f) => {
1644
- p = f, o.value = f.toLowerCase(), r.style.background = f, n.getRootNode().activeElement !== s && (s.value = f), n.style.setProperty("--brand", f);
1660
+ p = f, o.value = f.toLowerCase(), s.style.background = f, n.getRootNode().activeElement !== r && (r.value = f), n.style.setProperty("--brand", f);
1645
1661
  }, h = (f) => {
1646
1662
  f !== p && (c(f), e(f));
1647
1663
  };
1648
- r.addEventListener("click", () => {
1664
+ s.addEventListener("click", () => {
1649
1665
  if (o.showPicker)
1650
1666
  try {
1651
1667
  o.showPicker();
@@ -1653,27 +1669,27 @@ function Ka({ label: t, onInput: e }) {
1653
1669
  } catch {
1654
1670
  }
1655
1671
  o.click();
1656
- }), o.addEventListener("input", () => h(o.value.toUpperCase())), s.addEventListener("input", () => {
1657
- const f = tt(s.value);
1672
+ }), o.addEventListener("input", () => h(o.value.toUpperCase())), r.addEventListener("input", () => {
1673
+ const f = nt(r.value);
1658
1674
  f && h(f);
1659
1675
  });
1660
1676
  const y = () => {
1661
- s.value = p;
1677
+ r.value = p;
1662
1678
  };
1663
- return s.addEventListener("blur", y), s.addEventListener("keydown", (f) => {
1664
- f.key === "Enter" && (y(), s.select());
1679
+ return r.addEventListener("blur", y), r.addEventListener("keydown", (f) => {
1680
+ f.key === "Enter" && (y(), r.select());
1665
1681
  }), i.addEventListener("click", async () => {
1666
1682
  if ("EyeDropper" in window)
1667
1683
  try {
1668
- const { sRGBHex: f } = await new window.EyeDropper().open(), m = tt(f);
1684
+ const { sRGBHex: f } = await new window.EyeDropper().open(), m = nt(f);
1669
1685
  m && h(m);
1670
1686
  } catch {
1671
1687
  }
1672
1688
  else
1673
- r.click();
1674
- }), { el: n, setValue: (f) => c(tt(f) || p) };
1689
+ s.click();
1690
+ }), { el: n, setValue: (f) => c(nt(f) || p) };
1675
1691
  }
1676
- function Ga({ label: t, options: e, onSelect: n }) {
1692
+ function Xa({ label: t, options: e, onSelect: n }) {
1677
1693
  const a = document.createElement("div");
1678
1694
  a.className = "swatches", a.setAttribute("role", "radiogroup"), a.setAttribute("aria-label", t);
1679
1695
  const o = e.map((l) => {
@@ -1681,16 +1697,16 @@ function Ga({ label: t, options: e, onSelect: n }) {
1681
1697
  return p.type = "button", p.className = "swatch", p.setAttribute("role", "radio"), p.dataset.value = l.value, p.innerHTML = `<span class="swatch-ring"><span class="swatch-dot" style="background:${l.colour}"></span></span><span class="swatch-label">${l.label}</span>`, p.addEventListener("click", () => i(l.value)), p;
1682
1698
  });
1683
1699
  a.append(...o);
1684
- let r = null;
1685
- function s(l) {
1686
- r = l, o.forEach((c) => c.setAttribute("aria-checked", String(c.dataset.value === l)));
1700
+ let s = null;
1701
+ function r(l) {
1702
+ s = l, o.forEach((c) => c.setAttribute("aria-checked", String(c.dataset.value === l)));
1687
1703
  const p = Math.max(0, o.findIndex((c) => c.dataset.value === l));
1688
1704
  o.forEach((c, h) => {
1689
1705
  c.tabIndex = h === p ? 0 : -1;
1690
1706
  });
1691
1707
  }
1692
1708
  function i(l, p) {
1693
- l !== r && (s(l), n(l)), p && o.find((c) => c.dataset.value === l).focus();
1709
+ l !== s && (r(l), n(l)), p && o.find((c) => c.dataset.value === l).focus();
1694
1710
  }
1695
1711
  return a.addEventListener("keydown", (l) => {
1696
1712
  const p = o.indexOf(l.target.closest(".swatch"));
@@ -1702,15 +1718,15 @@ function Ga({ label: t, options: e, onSelect: n }) {
1702
1718
  else if (l.key === "End") h = o.length - 1;
1703
1719
  else return;
1704
1720
  l.preventDefault(), i(o[h].dataset.value, !0);
1705
- }), s(null), { el: a, setValue: s };
1721
+ }), r(null), { el: a, setValue: r };
1706
1722
  }
1707
- const Wa = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950], me = (t) => Object.fromEntries(t.split(" ").map((e, n) => [Wa[n], `#${e}`])), nt = {
1723
+ const Ja = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950], me = (t) => Object.fromEntries(t.split(" ").map((e, n) => [Ja[n], `#${e}`])), at = {
1708
1724
  slate: me("f8fafc f1f5f9 e2e8f0 cbd5e1 94a3b8 64748b 475569 334155 1e293b 0f172a 020617"),
1709
1725
  gray: me("f9fafb f3f4f6 e5e7eb d1d5db 9ca3af 6b7280 4b5563 374151 1f2937 111827 030712"),
1710
1726
  zinc: me("fafafa f4f4f5 e4e4e7 d4d4d8 a1a1aa 71717a 52525b 3f3f46 27272a 18181b 09090b"),
1711
1727
  neutral: me("fafafa f5f5f5 e5e5e5 d4d4d4 a3a3a3 737373 525252 404040 262626 171717 0a0a0a"),
1712
1728
  stone: me("fafaf9 f5f5f4 e7e5e4 d6d3d1 a8a29e 78716c 57534e 44403c 292524 1c1917 0c0a09")
1713
- }, N = (t) => Object.fromEntries(t.split(" ").map((e, n) => [400 + 100 * n, `#${e}`])), at = {
1729
+ }, N = (t) => Object.fromEntries(t.split(" ").map((e, n) => [400 + 100 * n, `#${e}`])), ot = {
1714
1730
  red: N("f87171 ef4444 dc2626 b91c1c 991b1b"),
1715
1731
  orange: N("fb923c f97316 ea580c c2410c 9a3412"),
1716
1732
  amber: N("fbbf24 f59e0b d97706 b45309 92400e"),
@@ -1728,17 +1744,17 @@ const Wa = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950], me = (t) => O
1728
1744
  fuchsia: N("e879f9 d946ef c026d3 a21caf 86198f"),
1729
1745
  pink: N("f472b6 ec4899 db2777 be185d 9d174d"),
1730
1746
  rose: N("fb7185 f43f5e e11d48 be123c 9f1239")
1731
- }, ze = [
1747
+ }, Ie = [
1732
1748
  { value: "indigo-zinc", label: "Indigo · Zinc", primary: "indigo", neutral: "zinc" },
1733
1749
  { value: "emerald-stone", label: "Emerald · Stone", primary: "emerald", neutral: "stone" },
1734
1750
  { value: "rose-slate", label: "Rose · Slate", primary: "rose", neutral: "slate" },
1735
1751
  { value: "amber-neutral", label: "Amber · Neutral", primary: "amber", neutral: "neutral" }
1736
- ], pn = "#4F46E5", Ya = "#A0743C", Za = [
1752
+ ], fn = "#4F46E5", Qa = "#A0743C", eo = [
1737
1753
  // Figma Swatch row sample colours
1738
1754
  { value: "pure", label: "Pure", colour: "#8E8E93" },
1739
1755
  { value: "subtle", label: "Subtle", colour: "#8A89A6" },
1740
1756
  { value: "warm", label: "Warm", colour: "#9C9389" }
1741
- ], un = ["bg", "surface", "surface-raised", "text", "text-muted", "border"], Xa = {
1757
+ ], gn = ["bg", "surface", "surface-raised", "text", "text-muted", "border"], to = {
1742
1758
  // proposal
1743
1759
  bg: "#0F0F11",
1744
1760
  surface: "#18181B",
@@ -1746,32 +1762,32 @@ const Wa = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950], me = (t) => O
1746
1762
  text: "#F4F4F5",
1747
1763
  "text-muted": "#A1A1AA",
1748
1764
  border: "#2E2E33"
1749
- }, Ja = { bg: 4, surface: 2, "surface-raised": 2, text: 5, "text-muted": 12, border: 10 }, Y = (t) => /^#[0-9a-f]{6}$/i.test(t || ""), ot = (t) => [500, 600, 700].includes(Number(t.shade)) ? Number(t.shade) : 600, rt = (t) => t[0].toUpperCase() + t.slice(1);
1750
- function hn(t) {
1751
- const e = (l) => (l /= 255, l <= 0.03928 ? l / 12.92 : ((l + 0.055) / 1.055) ** 2.4), [n, a, o] = [1, 3, 5].map((l) => e(parseInt(t.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);
1752
- return s >= i ? "#FFFFFF" : "#18181B";
1765
+ }, no = { bg: 4, surface: 2, "surface-raised": 2, text: 5, "text-muted": 12, border: 10 }, Z = (t) => /^#[0-9a-f]{6}$/i.test(t || ""), rt = (t) => [500, 600, 700].includes(Number(t.shade)) ? Number(t.shade) : 600, st = (t) => t[0].toUpperCase() + t.slice(1);
1766
+ function mn(t) {
1767
+ const e = (l) => (l /= 255, l <= 0.03928 ? l / 12.92 : ((l + 0.055) / 1.055) ** 2.4), [n, a, o] = [1, 3, 5].map((l) => e(parseInt(t.slice(l, l + 2), 16))), s = 0.2126 * n + 0.7152 * a + 0.0722 * o, r = 1.05 / (s + 0.05), i = (s + 0.05) / (98e-4 + 0.05);
1768
+ return r >= i ? "#FFFFFF" : "#18181B";
1753
1769
  }
1754
- const De = {
1770
+ const Be = {
1755
1771
  id: "colour",
1756
1772
  title: "Colour",
1757
1773
  hint: "Brand colour · neutral tint · mode",
1758
- uses: ["--twd-primary", "--twd-primary-hover", "--twd-on-primary", "--twd-focus", ...un.map((t) => `--twd-${t}`)],
1774
+ uses: ["--twd-primary", "--twd-primary-hover", "--twd-on-primary", "--twd-focus", ...gn.map((t) => `--twd-${t}`)],
1759
1775
  tokens(t) {
1760
- const e = t.colour || {}, n = {}, a = e.mode === "dark", o = at[e.primary];
1761
- if (!Y(e.brand) && o) {
1762
- const i = ot(e);
1763
- n["--twd-primary"] = o[i], n["--twd-primary-hover"] = o[a ? i - 100 : i + 100], n["--twd-on-primary"] = hn(o[i]), n["--twd-focus"] = o[500];
1776
+ const e = t.colour || {}, n = {}, a = e.mode === "dark", o = ot[e.primary];
1777
+ if (!Z(e.brand) && o) {
1778
+ const i = rt(e);
1779
+ n["--twd-primary"] = o[i], n["--twd-primary-hover"] = o[a ? i - 100 : i + 100], n["--twd-on-primary"] = mn(o[i]), n["--twd-focus"] = o[500];
1764
1780
  }
1765
- Y(e.brand) && (n["--twd-primary"] = e.brand, n["--twd-primary-hover"] = a ? `color-mix(in oklch, ${e.brand} 85%, white)` : `color-mix(in oklch, ${e.brand} 86%, black)`, n["--twd-on-primary"] = hn(e.brand), n["--twd-focus"] = e.brand);
1766
- const r = e.tint === "subtle" ? Y(e.brand) ? e.brand : F("--twd-primary") || pn : e.tint === "warm" ? Ya : null, s = nt[e.neutral];
1767
- if (s) {
1768
- 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] };
1781
+ Z(e.brand) && (n["--twd-primary"] = e.brand, n["--twd-primary-hover"] = a ? `color-mix(in oklch, ${e.brand} 85%, white)` : `color-mix(in oklch, ${e.brand} 86%, black)`, n["--twd-on-primary"] = mn(e.brand), n["--twd-focus"] = e.brand);
1782
+ const s = e.tint === "subtle" ? Z(e.brand) ? e.brand : F("--twd-primary") || fn : e.tint === "warm" ? Qa : null, r = at[e.neutral];
1783
+ if (r) {
1784
+ const i = a ? { bg: r[950], surface: r[900], "surface-raised": r[800], text: r[100], "text-muted": r[400], border: r[800] } : { bg: r[50], surface: "#ffffff", "surface-raised": "#ffffff", text: r[900], "text-muted": r[500], border: r[200] };
1769
1785
  Object.entries(i).forEach(([l, p]) => {
1770
1786
  n[`--twd-${l}`] = p;
1771
1787
  });
1772
- } else (a || r) && un.forEach((i) => {
1773
- const l = a ? Xa[i] : F(`--twd-${i}`);
1774
- l && (n[`--twd-${i}`] = r ? `color-mix(in oklch, ${l} ${100 - Ja[i]}%, ${r})` : l);
1788
+ } else (a || s) && gn.forEach((i) => {
1789
+ const l = a ? to[i] : F(`--twd-${i}`);
1790
+ l && (n[`--twd-${i}`] = s ? `color-mix(in oklch, ${l} ${100 - no[i]}%, ${s})` : l);
1775
1791
  });
1776
1792
  return n;
1777
1793
  },
@@ -1779,8 +1795,8 @@ const De = {
1779
1795
  // ---- Tabbed layout (Colour tab): themes, then Tailwind fine-tuning ----
1780
1796
  themeTiles(t, e, { label: n = "Theme" } = {}) {
1781
1797
  const a = (o) => {
1782
- const r = nt[o.neutral], s = at[o.primary];
1783
- 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>`;
1798
+ const s = at[o.neutral], r = ot[o.primary];
1799
+ return `<span class="theme" style="--bg:${s[50]};--line:${s[200]};--ink:${s[900]};--soft:${s[500]};--pri:${r[600]}"><i><b></b><s></s><u></u></i></span><span class="palette">${[r[400], r[500], r[600], r[700], r[800], s[200], s[500], s[900]].map((i) => `<i style="background:${i}"></i>`).join("")}</span>`;
1784
1800
  };
1785
1801
  t.append(V(e, {
1786
1802
  section: "colour",
@@ -1788,18 +1804,18 @@ const De = {
1788
1804
  label: n,
1789
1805
  columns: 2,
1790
1806
  className: "tiles-themes",
1791
- options: ze.map((o) => ({ value: o.value, label: o.label, preview: a(o) })),
1807
+ options: Ie.map((o) => ({ value: o.value, label: o.label, preview: a(o) })),
1792
1808
  current: (o) => {
1793
- const r = o.colour || {};
1794
- return Y(r.brand) ? null : ze.find((s) => s.primary === r.primary && s.neutral === r.neutral)?.value || null;
1809
+ const s = o.colour || {};
1810
+ return Z(s.brand) ? null : Ie.find((r) => r.primary === s.primary && r.neutral === s.neutral)?.value || null;
1795
1811
  },
1796
1812
  select: (o) => {
1797
- const r = ze.find((s) => s.value === o);
1798
- e.setSection("colour", { primary: r.primary, neutral: r.neutral, shade: null, brand: null, tint: null });
1813
+ const s = Ie.find((r) => r.value === o);
1814
+ e.setSection("colour", { primary: s.primary, neutral: s.neutral, shade: null, brand: null, tint: null });
1799
1815
  },
1800
- valueText: (o, r) => {
1801
- const s = r.colour || {};
1802
- return o ? "" : s.primary || s.neutral || s.brand ? "Custom" : "Prototype colours";
1816
+ valueText: (o, s) => {
1817
+ const r = s.colour || {};
1818
+ return o ? "" : r.primary || r.neutral || r.brand ? "Custom" : "Prototype colours";
1803
1819
  }
1804
1820
  }));
1805
1821
  },
@@ -1810,21 +1826,21 @@ const De = {
1810
1826
  label: `${n} colour family`,
1811
1827
  columns: 9,
1812
1828
  className: "tiles-swatches",
1813
- options: Object.entries(at).map(([i, l]) => ({ value: i, label: rt(i), title: rt(i), preview: `<span class="dot" style="background:${l[500]}"></span>` })),
1829
+ options: Object.entries(ot).map(([i, l]) => ({ value: i, label: st(i), title: st(i), preview: `<span class="dot" style="background:${l[500]}"></span>` })),
1814
1830
  current: (i) => {
1815
1831
  const l = i.colour || {};
1816
- return Y(l.brand) ? null : l.primary || null;
1832
+ return Z(l.brand) ? null : l.primary || null;
1817
1833
  },
1818
1834
  select: (i) => e.setSection("colour", { primary: i, brand: null })
1819
1835
  });
1820
1836
  o.querySelector(".field-head").remove();
1821
- const r = re({ label: "Shade", options: [500, 600, 700].map((i) => ({ value: String(i), label: String(i) })), onSelect: (i) => e.setSection("colour", { shade: Number(i) }) });
1822
- a.append(o, r.el);
1823
- const s = () => {
1837
+ const s = ie({ label: "Shade", options: [500, 600, 700].map((i) => ({ value: String(i), label: String(i) })), onSelect: (i) => e.setSection("colour", { shade: Number(i) }) });
1838
+ a.append(o, s.el);
1839
+ const r = () => {
1824
1840
  const i = e.getState().colour || {};
1825
- r.setValue(String(ot(i))), a.setValue(Y(i.brand) ? i.brand.toLowerCase() : i.primary ? `${i.primary}-${ot(i)}` : "");
1841
+ s.setValue(String(rt(i))), a.setValue(Z(i.brand) ? i.brand.toLowerCase() : i.primary ? `${i.primary}-${rt(i)}` : "");
1826
1842
  };
1827
- s(), e.onChange(s), t.append(a.el);
1843
+ r(), e.onChange(r), t.append(a.el);
1828
1844
  },
1829
1845
  neutralTiles(t, e, { label: n = "Neutral" } = {}) {
1830
1846
  t.append(V(e, {
@@ -1833,7 +1849,7 @@ const De = {
1833
1849
  label: n,
1834
1850
  columns: 5,
1835
1851
  className: "tiles-greys",
1836
- options: Object.entries(nt).map(([a, o]) => ({ value: a, label: rt(a), preview: `<span class="greys">${[o[50], o[200], o[500], o[900]].map((r) => `<i style="background:${r}"></i>`).join("")}</span>` })),
1852
+ options: Object.entries(at).map(([a, o]) => ({ value: a, label: st(a), preview: `<span class="greys">${[o[50], o[200], o[500], o[900]].map((s) => `<i style="background:${s}"></i>`).join("")}</span>` })),
1837
1853
  select: (a) => e.setSection("colour", { neutral: a, tint: null }),
1838
1854
  valueText: (a) => a || ""
1839
1855
  }));
@@ -1842,19 +1858,19 @@ const De = {
1842
1858
  const n = document.createElement("details");
1843
1859
  n.className = "more more-custom", n.innerHTML = '<summary><span class="rainbow" aria-hidden="true"></span><span>Custom colour…</span><span class="muted">any hex</span></summary>';
1844
1860
  const a = document.createElement("div");
1845
- a.className = "more-body", n.append(a), De.parts.brand(a, e, { label: "Brand" }), Y((e.getState().colour || {}).brand) && (n.open = !0), t.append(n);
1861
+ a.className = "more-body", n.append(a), Be.parts.brand(a, e, { label: "Brand" }), Z((e.getState().colour || {}).brand) && (n.open = !0), t.append(n);
1846
1862
  },
1847
1863
  brand(t, e, { label: n = "Brand" } = {}) {
1848
- const a = B(n), o = Ka({ label: "Brand colour", onInput: (s) => e.setSection("colour", { brand: s }) });
1864
+ const a = B(n), o = Za({ label: "Brand colour", onInput: (r) => e.setSection("colour", { brand: r }) });
1849
1865
  a.append(o.el);
1850
- const r = () => o.setValue((e.getState().colour || {}).brand || (e.readToken || F)("--twd-primary") || pn);
1851
- r(), e.onChange(r), t.append(a.el);
1866
+ const s = () => o.setValue((e.getState().colour || {}).brand || (e.readToken || F)("--twd-primary") || fn);
1867
+ s(), e.onChange(s), t.append(a.el);
1852
1868
  },
1853
1869
  neutral(t, e, { label: n = "Neutral" } = {}) {
1854
- const a = B(n), o = Ga({ label: "Neutral tint", options: Za, onSelect: (s) => e.setSection("colour", { tint: s }) });
1870
+ const a = B(n), o = Xa({ label: "Neutral tint", options: eo, onSelect: (r) => e.setSection("colour", { tint: r }) });
1855
1871
  a.append(o.el);
1856
- const r = () => o.setValue((e.getState().colour || {}).tint || "pure");
1857
- r(), e.onChange(r), t.append(a.el);
1872
+ const s = () => o.setValue((e.getState().colour || {}).tint || "pure");
1873
+ s(), e.onChange(s), t.append(a.el);
1858
1874
  },
1859
1875
  mode(t, e, { label: n = "Mode" } = {}) {
1860
1876
  t.append(ke(e, {
@@ -1869,12 +1885,12 @@ const De = {
1869
1885
  render(t, e) {
1870
1886
  ["brand", "neutral", "mode"].forEach((n) => this.parts[n](t, e));
1871
1887
  }
1872
- }, Le = (t, e = "var(--twd-surface)") => `color-mix(in oklch, var(--twd-primary) ${t}%, ${e})`, Qa = {
1888
+ }, Oe = (t, e = "var(--twd-surface)") => `color-mix(in oklch, var(--twd-primary) ${t}%, ${e})`, ao = {
1873
1889
  // proposal recipes; Solid leaves tokens.css defaults
1874
- soft: { bg: Le(14), fg: "var(--twd-primary)", border: "transparent", hover: Le(22) },
1875
- outline: { bg: "transparent", fg: "var(--twd-primary)", border: "var(--twd-primary)", hover: Le(8, "transparent") },
1876
- ghost: { bg: "transparent", fg: "var(--twd-primary)", border: "transparent", hover: Le(10, "transparent") }
1877
- }, eo = { small: { height: 0.8, pad: 0.75 }, large: { height: 1.2, pad: 1.25 } }, Dn = zn({
1890
+ soft: { bg: Oe(14), fg: "var(--twd-primary)", border: "transparent", hover: Oe(22) },
1891
+ outline: { bg: "transparent", fg: "var(--twd-primary)", border: "var(--twd-primary)", hover: Oe(8, "transparent") },
1892
+ ghost: { bg: "transparent", fg: "var(--twd-primary)", border: "transparent", hover: Oe(10, "transparent") }
1893
+ }, oo = { small: { height: 0.8, pad: 0.75 }, large: { height: 1.2, pad: 1.25 } }, qn = Bn({
1878
1894
  id: "buttons",
1879
1895
  title: "Buttons",
1880
1896
  hint: "Style · corners · size",
@@ -1894,14 +1910,14 @@ const De = {
1894
1910
  { value: "pill", label: "Pill", radius: 999 }
1895
1911
  ],
1896
1912
  extraTokens(t) {
1897
- const e = {}, n = Qa[t.style];
1898
- n && Object.entries(n).forEach(([s, i]) => {
1899
- e[`--twd-button-${s}`] = i;
1913
+ const e = {}, n = ao[t.style];
1914
+ n && Object.entries(n).forEach(([r, i]) => {
1915
+ e[`--twd-button-${r}`] = i;
1900
1916
  });
1901
- const a = eo[t.size];
1917
+ const a = oo[t.size];
1902
1918
  if (!a) return e;
1903
- const o = ye(F("--twd-control-height"), a.height), r = ye(F("--twd-control-pad-x"), a.pad);
1904
- return o && (e["--twd-control-height"] = o), r && (e["--twd-control-pad-x"] = r), e;
1919
+ const o = ye(F("--twd-control-height"), a.height), s = ye(F("--twd-control-pad-x"), a.pad);
1920
+ return o && (e["--twd-control-height"] = o), s && (e["--twd-control-pad-x"] = s), e;
1905
1921
  },
1906
1922
  extra: [
1907
1923
  {
@@ -1920,12 +1936,12 @@ const De = {
1920
1936
  options: [{ value: "small", label: "Small" }, { value: "medium", label: "Medium" }, { value: "large", label: "Large" }]
1921
1937
  }
1922
1938
  ]
1923
- }), to = {
1939
+ }), ro = {
1924
1940
  // proposal recipes; Filled leaves tokens.css defaults
1925
1941
  outlined: { bg: "transparent", border: "color-mix(in oklch, var(--twd-border) 60%, var(--twd-text))", shadow: "none" },
1926
1942
  elevated: { bg: "var(--twd-surface-raised)", border: "transparent", shadow: "var(--twd-shadow-md)" },
1927
1943
  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" }
1928
- }, wt = zn({
1944
+ }, vt = Bn({
1929
1945
  id: "cards",
1930
1946
  title: "Cards",
1931
1947
  hint: "Style · corners · border",
@@ -1945,7 +1961,7 @@ const De = {
1945
1961
  // proposal (cards don't go fully pill)
1946
1962
  ],
1947
1963
  extraTokens(t) {
1948
- const e = {}, n = to[t.style];
1964
+ const e = {}, n = ro[t.style];
1949
1965
  if (n && Object.entries(n).forEach(([a, o]) => {
1950
1966
  e[`--twd-card-${a}`] = o;
1951
1967
  }), t.border === "none" && (e["--twd-border-width-container"] = "0px"), t.border === "thick") {
@@ -1971,37 +1987,37 @@ const De = {
1971
1987
  options: [{ value: "none", label: "None" }, { value: "thin", label: "Thin" }, { value: "thick", label: "Thick" }]
1972
1988
  }
1973
1989
  ]
1974
- }), ne = 60, st = {
1990
+ }), oe = 60, it = {
1975
1991
  soft: { sm: [0, 1, 2, 0, 0.06], md: [0, 4, 12, 0, 0.08], lg: [0, 12, 32, 0, 0.12] },
1976
1992
  // = tokens.css
1977
1993
  crisp: { sm: [0, 1, 1, 0, 0.12], md: [0, 2, 4, 0, 0.14], lg: [0, 4, 8, 0, 0.16] },
1978
1994
  bold: { sm: [2, 2, 0, 0, 0.85], md: [3, 3, 0, 0, 0.85], lg: [5, 5, 0, 0, 0.85] }
1979
- }, Pe = ([t, e, n, a, o], r) => {
1980
- const s = Math.min(1, +(o * r).toFixed(3));
1981
- return s <= 0 ? "none" : `${t}px ${e}px ${n}px ${a}px rgb(0 0 0 / ${s})`;
1982
- }, vt = {
1995
+ }, Pe = ([t, e, n, a, o], s) => {
1996
+ const r = Math.min(1, +(o * s).toFixed(3));
1997
+ return r <= 0 ? "none" : `${t}px ${e}px ${n}px ${a}px rgb(0 0 0 / ${r})`;
1998
+ }, yt = {
1983
1999
  id: "depth",
1984
2000
  title: "Depth",
1985
2001
  hint: "Flat · soft · crisp · bold",
1986
2002
  uses: ["--twd-shadow-sm", "--twd-shadow-md", "--twd-shadow-lg"],
1987
2003
  tokens(t) {
1988
- const e = t.depth || {}, n = e.style || "soft", a = typeof e.intensity == "number" ? Math.min(100, Math.max(0, e.intensity)) : ne;
2004
+ const e = t.depth || {}, n = e.style || "soft", a = typeof e.intensity == "number" ? Math.min(100, Math.max(0, e.intensity)) : oe;
1989
2005
  if (n === "flat")
1990
2006
  return { "--twd-shadow-sm": "none", "--twd-shadow-md": "none", "--twd-shadow-lg": "none" };
1991
- const o = st[n];
2007
+ const o = it[n];
1992
2008
  if (!o) return {};
1993
- if (n === "soft" && a === ne) return {};
1994
- const r = a / ne;
2009
+ if (n === "soft" && a === oe) return {};
2010
+ const s = a / oe;
1995
2011
  return {
1996
- "--twd-shadow-sm": Pe(o.sm, r),
1997
- "--twd-shadow-md": Pe(o.md, r),
1998
- "--twd-shadow-lg": Pe(o.lg, r)
2012
+ "--twd-shadow-sm": Pe(o.sm, s),
2013
+ "--twd-shadow-md": Pe(o.md, s),
2014
+ "--twd-shadow-lg": Pe(o.lg, s)
1999
2015
  };
2000
2016
  },
2001
2017
  parts: {
2002
2018
  // Tabbed layout: each style as a small card wearing that shadow.
2003
2019
  styleTiles(t, e, { label: n = "Style" } = {}) {
2004
- const a = (o) => `<span class="shape shape-card shadow-${o}" style="box-shadow:${st[o] ? Pe(st[o].md, 1) : "none"}"></span>`;
2020
+ const a = (o) => `<span class="shape shape-card shadow-${o}" style="box-shadow:${it[o] ? Pe(it[o].md, 1) : "none"}"></span>`;
2005
2021
  t.append(V(e, {
2006
2022
  section: "depth",
2007
2023
  key: "style",
@@ -2021,68 +2037,68 @@ const De = {
2021
2037
  }));
2022
2038
  },
2023
2039
  intensity(t, e, { label: n = "Intensity" } = {}) {
2024
- t.append(Ia(e, { section: "depth", key: "intensity", label: n, min: 0, max: 100, fallback: ne, format: (a) => `${a}%` }));
2040
+ t.append(qa(e, { section: "depth", key: "intensity", label: n, min: 0, max: 100, fallback: oe, format: (a) => `${a}%` }));
2025
2041
  }
2026
2042
  },
2027
2043
  render(t, e) {
2028
2044
  Object.entries(this.parts).filter(([n]) => !n.endsWith("Tiles")).forEach(([, n]) => n(t, e));
2029
2045
  }
2030
- }, no = (t) => Math.min(1, Math.max(0, t)), fn = (t) => Math.round(t / 50) * 50, it = (t) => `${+t.toFixed(1)}%`;
2031
- function $t(t = {}) {
2032
- return typeof t.bold == "number" && isFinite(t.bold) && t.bold !== 0.5 ? no(t.bold) : null;
2046
+ }, so = (t) => Math.min(1, Math.max(0, t)), bn = (t) => Math.round(t / 50) * 50, lt = (t) => `${+t.toFixed(1)}%`;
2047
+ function Et(t = {}) {
2048
+ return typeof t.bold == "number" && isFinite(t.bold) && t.bold !== 0.5 ? so(t.bold) : null;
2033
2049
  }
2034
- const Oe = (t, e, n) => (t.tokens(e) || {})[n] || F(n), ao = {
2050
+ const Fe = (t, e, n) => (t.tokens(e) || {})[n] || F(n), io = {
2035
2051
  id: "character",
2036
2052
  title: "Character",
2037
2053
  hint: "Subtle ↔ Bold",
2038
2054
  uses: [],
2039
2055
  // set from the Simple page only
2040
2056
  tokens(t) {
2041
- const e = $t(t.character);
2057
+ const e = Et(t.character);
2042
2058
  if (e === null) return {};
2043
- const n = {}, a = 2 * e - 1, o = Math.max(0, a), r = Math.max(0, -a);
2044
- n["--twd-weight-heading"] = String(fn(600 + 200 * a)), n["--twd-weight-strong"] = String(fn(600 + 100 * a));
2045
- const s = Oe(De, t, "--twd-border");
2046
- if (r && (n["--twd-border"] = `color-mix(in oklch, ${s} ${it(100 - 50 * r)}, var(--twd-bg))`), o) {
2047
- n["--twd-border"] = `color-mix(in oklch, ${s} ${it(100 - 90 * o)}, var(--twd-text))`;
2048
- const l = Oe(De, t, "--twd-text-muted");
2049
- n["--twd-text-muted"] = `color-mix(in oklch, ${l} ${it(100 - 35 * o)}, var(--twd-text))`, ["--twd-border-width", "--twd-border-width-container"].forEach((p) => {
2050
- const c = p === "--twd-border-width-container" ? Oe(wt, t, p) : F(p), h = parseFloat(c);
2059
+ const n = {}, a = 2 * e - 1, o = Math.max(0, a), s = Math.max(0, -a);
2060
+ n["--twd-weight-heading"] = String(bn(600 + 200 * a)), n["--twd-weight-strong"] = String(bn(600 + 100 * a));
2061
+ const r = Fe(Be, t, "--twd-border");
2062
+ if (s && (n["--twd-border"] = `color-mix(in oklch, ${r} ${lt(100 - 50 * s)}, var(--twd-bg))`), o) {
2063
+ n["--twd-border"] = `color-mix(in oklch, ${r} ${lt(100 - 90 * o)}, var(--twd-text))`;
2064
+ const l = Fe(Be, t, "--twd-text-muted");
2065
+ n["--twd-text-muted"] = `color-mix(in oklch, ${l} ${lt(100 - 35 * o)}, var(--twd-text))`, ["--twd-border-width", "--twd-border-width-container"].forEach((p) => {
2066
+ const c = p === "--twd-border-width-container" ? Fe(vt, t, p) : F(p), h = parseFloat(c);
2051
2067
  isNaN(h) || (n[p] = `${Math.round(h * (1 + o))}px`);
2052
- }), [[Dn, "--twd-radius-control"], [wt, "--twd-radius-container"]].forEach(([p, c]) => {
2053
- const h = parseFloat(Oe(p, t, c));
2068
+ }), [[qn, "--twd-radius-control"], [vt, "--twd-radius-container"]].forEach(([p, c]) => {
2069
+ const h = parseFloat(Fe(p, t, c));
2054
2070
  !isNaN(h) && h < 999 && (n[c] = ye(`${h}px`, 1 - 0.5 * o));
2055
2071
  });
2056
2072
  }
2057
2073
  const i = t.depth || {};
2058
2074
  if (!i.style) {
2059
- const l = typeof i.intensity == "number" ? i.intensity : ne, p = r ? vt.tokens({ depth: { style: "soft", intensity: l * (1 - r) } }) : vt.tokens({ depth: { style: "bold", intensity: ne * o } });
2075
+ const l = typeof i.intensity == "number" ? i.intensity : oe, p = s ? yt.tokens({ depth: { style: "soft", intensity: l * (1 - s) } }) : yt.tokens({ depth: { style: "bold", intensity: oe * o } });
2060
2076
  Object.assign(n, p);
2061
2077
  }
2062
2078
  return n;
2063
2079
  },
2064
2080
  describe: (t, e) => t === "bold" ? { label: "Subtle ↔ Bold", value: `${Math.round(e * 100)}%` } : null
2065
- }, oo = '<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>', ro = '<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>';
2066
- let so = 0;
2067
- function io({ label: t, options: e, onSelect: n, placeholder: a, onOpen: o }) {
2068
- const r = `twd-fonts-${++so}`, s = document.createElement("div");
2069
- s.className = "font-select";
2081
+ }, lo = '<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>', co = '<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>';
2082
+ let po = 0;
2083
+ function uo({ label: t, options: e, onSelect: n, placeholder: a, onOpen: o }) {
2084
+ const s = `twd-fonts-${++po}`, r = document.createElement("div");
2085
+ r.className = "font-select";
2070
2086
  const i = document.createElement("button");
2071
- i.type = "button", i.className = "font-trigger", i.setAttribute("aria-haspopup", "listbox"), i.setAttribute("aria-expanded", "false"), i.setAttribute("aria-controls", r), i.innerHTML = `
2087
+ i.type = "button", i.className = "font-trigger", i.setAttribute("aria-haspopup", "listbox"), i.setAttribute("aria-expanded", "false"), i.setAttribute("aria-controls", s), i.innerHTML = `
2072
2088
  <span class="font-aa" aria-hidden="true">Aa</span>
2073
2089
  <span class="font-name"></span>
2074
2090
  <span class="font-fonts"></span>
2075
- <span class="font-chevron">${oo}</span>`;
2091
+ <span class="font-chevron">${lo}</span>`;
2076
2092
  const l = document.createElement("div");
2077
- l.className = "font-menu", l.id = r, l.setAttribute("role", "listbox"), l.setAttribute("aria-label", t), l.hidden = !0;
2093
+ l.className = "font-menu", l.id = s, l.setAttribute("role", "listbox"), l.setAttribute("aria-label", t), l.hidden = !0;
2078
2094
  const p = e.map((u) => {
2079
2095
  const v = document.createElement("div");
2080
2096
  return v.className = "font-option", v.setAttribute("role", "option"), v.tabIndex = -1, v.dataset.value = u.value, v.innerHTML = `
2081
2097
  <span class="font-aa" style="font-family:${u.preview}" aria-hidden="true">Aa</span>
2082
2098
  <span class="font-text"><span class="font-name">${u.name}</span><span class="font-fonts">${u.fonts}</span></span>
2083
- <span class="font-check">${ro}</span>`, v.addEventListener("click", () => b(u.value)), v;
2099
+ <span class="font-check">${co}</span>`, v.addEventListener("click", () => b(u.value)), v;
2084
2100
  });
2085
- l.append(...p), s.append(i, l);
2101
+ l.append(...p), r.append(i, l);
2086
2102
  let c = null;
2087
2103
  function h(u) {
2088
2104
  const v = e.find((E) => E.value === u), L = v || a || e[0];
@@ -2093,13 +2109,13 @@ function io({ label: t, options: e, onSelect: n, placeholder: a, onOpen: o }) {
2093
2109
  l.style.top = `${E}px`, l.style.left = `${u.left}px`, l.style.width = `${u.width}px`;
2094
2110
  }
2095
2111
  function f() {
2096
- l.hidden && (l.hidden = !1, i.setAttribute("aria-expanded", "true"), o && o(), y(), (p.find((u) => u.dataset.value === c) || p[0]).focus(), setTimeout(() => document.addEventListener("pointerdown", x, !0)), window.addEventListener("resize", m), s.closest(".body")?.addEventListener("scroll", m, { once: !0 }));
2112
+ l.hidden && (l.hidden = !1, i.setAttribute("aria-expanded", "true"), o && o(), y(), (p.find((u) => u.dataset.value === c) || p[0]).focus(), setTimeout(() => document.addEventListener("pointerdown", x, !0)), window.addEventListener("resize", m), r.closest(".body")?.addEventListener("scroll", m, { once: !0 }));
2097
2113
  }
2098
2114
  function m(u) {
2099
2115
  l.hidden || (l.hidden = !0, i.setAttribute("aria-expanded", "false"), document.removeEventListener("pointerdown", x, !0), window.removeEventListener("resize", m), u === !0 && i.focus());
2100
2116
  }
2101
2117
  function x(u) {
2102
- u.composedPath().includes(s) || m();
2118
+ u.composedPath().includes(r) || m();
2103
2119
  }
2104
2120
  function b(u) {
2105
2121
  u !== c && (h(u), n(u)), m(!0);
@@ -2124,53 +2140,53 @@ function io({ label: t, options: e, onSelect: n, placeholder: a, onOpen: o }) {
2124
2140
  return;
2125
2141
  }
2126
2142
  L !== null && (u.preventDefault(), p[L].focus());
2127
- }), h(a ? null : e[0].value), { el: s, setValue: h };
2143
+ }), h(a ? null : e[0].value), { el: r, setValue: h };
2128
2144
  }
2129
- const I = 'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif', Fe = 'Georgia, "Times New Roman", serif', Z = [
2145
+ const I = 'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif', Ne = 'Georgia, "Times New Roman", serif', X = [
2130
2146
  { value: "neutral", name: "Neutral", fonts: "Inter · Inter", heading: `"Inter", ${I}`, body: `"Inter", ${I}`, load: ["Inter:wght@400;500;600;700"] },
2131
2147
  { value: "modern", name: "Modern", fonts: "Geist · Geist", heading: `"Geist", ${I}`, body: `"Geist", ${I}`, load: ["Geist:wght@400;500;600;700"] },
2132
- { value: "editorial", name: "Editorial", fonts: "Fraunces · Inter", heading: `"Fraunces", ${Fe}`, body: `"Inter", ${I}`, load: ["Fraunces:wght@400;600;700", "Inter:wght@400;500;600;700"] },
2148
+ { value: "editorial", name: "Editorial", fonts: "Fraunces · Inter", heading: `"Fraunces", ${Ne}`, body: `"Inter", ${I}`, load: ["Fraunces:wght@400;600;700", "Inter:wght@400;500;600;700"] },
2133
2149
  { value: "technical", name: "Technical", fonts: "Space Grotesk · DM Sans", heading: `"Space Grotesk", ${I}`, body: `"DM Sans", ${I}`, load: ["Space+Grotesk:wght@500;600;700", "DM+Sans:wght@400;500;600;700"] },
2134
- { value: "classic", name: "Classic", fonts: "Playfair · DM Sans", heading: `"Playfair Display", ${Fe}`, body: `"DM Sans", ${I}`, load: ["Playfair+Display:wght@600;700", "DM+Sans:wght@400;500;600;700"] },
2135
- { value: "plex", name: "Plex", fonts: "Plex Serif · Plex Sans", heading: `"IBM Plex Serif", ${Fe}`, body: `"IBM Plex Sans", ${I}`, load: ["IBM+Plex+Serif:wght@500;600;700", "IBM+Plex+Sans:wght@400;500;600"] },
2136
- { value: "elegant", name: "Elegant", fonts: "Instrument Serif · Inter", heading: `"Instrument Serif", ${Fe}`, body: `"Inter", ${I}`, load: ["Instrument+Serif", "Inter:wght@400;500;600;700"] },
2150
+ { value: "classic", name: "Classic", fonts: "Playfair · DM Sans", heading: `"Playfair Display", ${Ne}`, body: `"DM Sans", ${I}`, load: ["Playfair+Display:wght@600;700", "DM+Sans:wght@400;500;600;700"] },
2151
+ { value: "plex", name: "Plex", fonts: "Plex Serif · Plex Sans", heading: `"IBM Plex Serif", ${Ne}`, body: `"IBM Plex Sans", ${I}`, load: ["IBM+Plex+Serif:wght@500;600;700", "IBM+Plex+Sans:wght@400;500;600"] },
2152
+ { value: "elegant", name: "Elegant", fonts: "Instrument Serif · Inter", heading: `"Instrument Serif", ${Ne}`, body: `"Inter", ${I}`, load: ["Instrument+Serif", "Inter:wght@400;500;600;700"] },
2137
2153
  { value: "friendly", name: "Friendly", fonts: "Manrope · Manrope", heading: `"Manrope", ${I}`, body: `"Manrope", ${I}`, load: ["Manrope:wght@400;500;600;700"] }
2138
- ], be = { compact: 1.125, balanced: 1.2, expressive: 1.333 }, gn = { xs: -2, sm: -1, base: 0, lg: 1, xl: 2, "2xl": 3, "3xl": 4 }, mn = /* @__PURE__ */ new Set();
2139
- function lt(t) {
2140
- const e = t.filter((a) => !mn.has(a));
2154
+ ], be = { compact: 1.125, balanced: 1.2, expressive: 1.333 }, xn = { xs: -2, sm: -1, base: 0, lg: 1, xl: 2, "2xl": 3, "3xl": 4 }, wn = /* @__PURE__ */ new Set();
2155
+ function dt(t) {
2156
+ const e = t.filter((a) => !wn.has(a));
2141
2157
  if (!e.length) return;
2142
- e.forEach((a) => mn.add(a));
2158
+ e.forEach((a) => wn.add(a));
2143
2159
  const n = document.createElement("link");
2144
2160
  n.rel = "stylesheet", n.href = `https://fonts.googleapis.com/css2?${e.map((a) => `family=${a}`).join("&")}&display=swap`, n.dataset.twiddle = "fonts", document.head.appendChild(n);
2145
2161
  }
2146
- const lo = {
2162
+ const ho = {
2147
2163
  id: "typography",
2148
2164
  title: "Typography",
2149
2165
  hint: "Font pairing · base size · scale",
2150
- uses: ["--twd-font-heading", "--twd-font-body", ...Object.keys(gn).map((t) => `--twd-text-${t}`)],
2166
+ uses: ["--twd-font-heading", "--twd-font-body", ...Object.keys(xn).map((t) => `--twd-text-${t}`)],
2151
2167
  tokens(t) {
2152
- const e = t.typography || {}, n = {}, a = Z.find((o) => o.value === e.font);
2153
- if (a && (lt(a.load), n["--twd-font-heading"] = a.heading, n["--twd-font-body"] = a.body), e.base || e.scale) {
2154
- const o = Number(e.base) || 16, r = be[e.scale] || be.balanced;
2155
- Object.entries(gn).forEach(([s, i]) => {
2156
- n[`--twd-text-${s}`] = `${+(o * r ** i / 16).toFixed(3)}rem`;
2168
+ const e = t.typography || {}, n = {}, a = X.find((o) => o.value === e.font);
2169
+ if (a && (dt(a.load), n["--twd-font-heading"] = a.heading, n["--twd-font-body"] = a.body), e.base || e.scale) {
2170
+ const o = Number(e.base) || 16, s = be[e.scale] || be.balanced;
2171
+ Object.entries(xn).forEach(([r, i]) => {
2172
+ n[`--twd-text-${r}`] = `${+(o * s ** i / 16).toFixed(3)}rem`;
2157
2173
  });
2158
2174
  }
2159
2175
  return n;
2160
2176
  },
2161
2177
  parts: {
2162
2178
  fonts(t, e, { label: n = "Fonts" } = {}) {
2163
- const a = B(n), o = io({
2179
+ const a = B(n), o = uo({
2164
2180
  label: "Font pairing",
2165
- options: Z.map((s) => ({ value: s.value, name: s.name, fonts: s.fonts, preview: s.heading })),
2181
+ options: X.map((r) => ({ value: r.value, name: r.name, fonts: r.fonts, preview: r.heading })),
2166
2182
  placeholder: { name: "Default", fonts: "Prototype fonts", preview: I },
2167
2183
  // Load every pairing's fonts when the list opens, so the "Aa" previews are real.
2168
- onOpen: () => lt([...new Set(Z.flatMap((s) => s.load))]),
2169
- onSelect: (s) => e.setSection("typography", { font: s })
2184
+ onOpen: () => dt([...new Set(X.flatMap((r) => r.load))]),
2185
+ onSelect: (r) => e.setSection("typography", { font: r })
2170
2186
  });
2171
2187
  a.append(o.el);
2172
- const r = () => o.setValue((e.getState().typography || {}).font || null);
2173
- r(), e.onChange(r), t.append(a.el);
2188
+ const s = () => o.setValue((e.getState().typography || {}).font || null);
2189
+ s(), e.onChange(s), t.append(a.el);
2174
2190
  },
2175
2191
  base(t, e, { label: n = "Base size" } = {}) {
2176
2192
  t.append(ke(e, {
@@ -2185,7 +2201,7 @@ const lo = {
2185
2201
  // Tabbed layout: pairings as tiles, each "Aa" in its own heading font.
2186
2202
  // The fonts load (from Google Fonts) only once the tiles are on screen.
2187
2203
  fontTiles(t, e, { label: n = "Fonts" } = {}) {
2188
- const a = (i) => i.replace(/"/g, "&quot;"), o = (i) => `<span class="tile-aa" style="font-family:${a(i)}">Aa</span>`, r = V(e, {
2204
+ const a = (i) => i.replace(/"/g, "&quot;"), o = (i) => `<span class="tile-aa" style="font-family:${a(i)}">Aa</span>`, s = V(e, {
2189
2205
  section: "typography",
2190
2206
  key: "font",
2191
2207
  label: n,
@@ -2193,24 +2209,24 @@ const lo = {
2193
2209
  className: "tiles-fonts",
2194
2210
  options: [
2195
2211
  { value: "default", label: "Prototype fonts", sub: "Default", preview: o(I), wide: !0 },
2196
- ...Z.map((i) => ({ value: i.value, label: i.name, sub: i.fonts, preview: o(i.heading) }))
2212
+ ...X.map((i) => ({ value: i.value, label: i.name, sub: i.fonts, preview: o(i.heading) }))
2197
2213
  ],
2198
2214
  current: (i) => (i.typography || {}).font || "default",
2199
2215
  select: (i) => e.setSection("typography", { font: i === "default" ? null : i }),
2200
- valueText: (i) => i === "default" ? "Default" : Z.find((l) => l.value === i)?.name || ""
2201
- }), s = new IntersectionObserver((i) => {
2202
- i.some((l) => l.isIntersecting) && (lt([...new Set(Z.flatMap((l) => l.load))]), s.disconnect());
2216
+ valueText: (i) => i === "default" ? "Default" : X.find((l) => l.value === i)?.name || ""
2217
+ }), r = new IntersectionObserver((i) => {
2218
+ i.some((l) => l.isIntersecting) && (dt([...new Set(X.flatMap((l) => l.load))]), r.disconnect());
2203
2219
  });
2204
- s.observe(r), t.append(r);
2220
+ r.observe(s), t.append(s);
2205
2221
  },
2206
2222
  scaleTiles(t, e, { label: n = "Scale" } = {}) {
2207
- const a = (o) => `<span class="ladder">${[-1, 0, 1, 2].map((r) => `<b style="font-size:${Math.round(13 * o ** r)}px">A</b>`).join("")}</span>`;
2223
+ const a = (o) => `<span class="ladder">${[-1, 0, 1, 2].map((s) => `<b style="font-size:${Math.round(13 * o ** s)}px">A</b>`).join("")}</span>`;
2208
2224
  t.append(V(e, {
2209
2225
  section: "typography",
2210
2226
  key: "scale",
2211
2227
  label: n,
2212
2228
  fallback: "balanced",
2213
- options: Object.entries(be).map(([o, r]) => ({ value: o, label: o[0].toUpperCase() + o.slice(1), preview: a(r) })),
2229
+ options: Object.entries(be).map(([o, s]) => ({ value: o, label: o[0].toUpperCase() + o.slice(1), preview: a(s) })),
2214
2230
  valueText: (o) => String(be[o])
2215
2231
  }));
2216
2232
  },
@@ -2228,49 +2244,49 @@ const lo = {
2228
2244
  render(t, e) {
2229
2245
  Object.entries(this.parts).filter(([n]) => !n.endsWith("Tiles")).forEach(([, n]) => n(t, e));
2230
2246
  }
2231
- }, [bn, Ne] = xt;
2232
- function co(t) {
2247
+ }, [vn, je] = wt;
2248
+ function fo(t) {
2233
2249
  return t > 0.56 ? "Bold" : t < 0.44 ? "Subtle" : "Balanced";
2234
2250
  }
2235
- function Bn(t) {
2251
+ function Vn(t) {
2236
2252
  return t > 1.06 ? "Comfy" : t < 0.94 ? "Compact" : "Regular";
2237
2253
  }
2238
- const je = (t) => t && t[0].toUpperCase() + t.slice(1), xn = [
2254
+ const Re = (t) => t && t[0].toUpperCase() + t.slice(1), yn = [
2239
2255
  ["colour", "Colour", (t) => {
2240
- const e = t.colour || {}, n = ze.find((o) => o.primary === e.primary && o.neutral === e.neutral);
2241
- return { text: `${e.brand ? e.brand.toUpperCase() : n && !e.shade ? n.label : e.primary ? `${je(e.primary)}${e.neutral ? ` · ${je(e.neutral)}` : ""}` : "Prototype colours"}${e.mode === "dark" ? " · Dark" : ""}`, swatch: F("--twd-primary") };
2256
+ const e = t.colour || {}, n = Ie.find((o) => o.primary === e.primary && o.neutral === e.neutral);
2257
+ return { text: `${e.brand ? e.brand.toUpperCase() : n && !e.shade ? n.label : e.primary ? `${Re(e.primary)}${e.neutral ? ` · ${Re(e.neutral)}` : ""}` : "Prototype colours"}${e.mode === "dark" ? " · Dark" : ""}`, swatch: F("--twd-primary") };
2242
2258
  }],
2243
2259
  ["type", "Type", (t) => {
2244
2260
  const e = t.typography || {};
2245
- return { text: `${Z.find((n) => n.value === e.font)?.name || "Prototype fonts"} · ${e.base || 16}px` };
2261
+ return { text: `${X.find((n) => n.value === e.font)?.name || "Prototype fonts"} · ${e.base || 16}px` };
2246
2262
  }],
2247
- ["spacing", "Spacing", (t) => ({ text: Bn(te(t.density)) })],
2248
- ["shape", "Shape", (t) => ({ text: `${je((t.buttons || {}).corners) || "Default"} corners` })],
2249
- ["shadows", "Shadows", (t) => ({ text: je((t.depth || {}).style) || ($t(t.character) !== null ? "From the pad" : "Default") })]
2250
- ], po = {
2263
+ ["spacing", "Spacing", (t) => ({ text: Vn(ae(t.density)) })],
2264
+ ["shape", "Shape", (t) => ({ text: `${Re((t.buttons || {}).corners) || "Default"} corners` })],
2265
+ ["shadows", "Shadows", (t) => ({ text: Re((t.depth || {}).style) || (Et(t.character) !== null ? "From the pad" : "Default") })]
2266
+ ], go = {
2251
2267
  summary(t, e, { label: n = "Current look", goTab: a } = {}) {
2252
- const o = B(n), r = document.createElement("div");
2253
- r.className = "summary", xn.forEach(([i, l]) => {
2268
+ const o = B(n), s = document.createElement("div");
2269
+ s.className = "summary", yn.forEach(([i, l]) => {
2254
2270
  const p = document.createElement("button");
2255
- p.type = "button", p.className = "summary-row", p.dataset.summary = i, p.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>`, p.querySelector(".summary-name").textContent = l, p.addEventListener("click", () => a && a(i)), r.append(p);
2256
- }), o.append(r);
2257
- const s = () => {
2271
+ p.type = "button", p.className = "summary-row", p.dataset.summary = i, p.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>`, p.querySelector(".summary-name").textContent = l, p.addEventListener("click", () => a && a(i)), s.append(p);
2272
+ }), o.append(s);
2273
+ const r = () => {
2258
2274
  const i = e.getState();
2259
- xn.forEach(([l, , p]) => {
2260
- const c = r.querySelector(`[data-summary="${l}"]`), h = p(i);
2275
+ yn.forEach(([l, , p]) => {
2276
+ const c = s.querySelector(`[data-summary="${l}"]`), h = p(i);
2261
2277
  c.querySelector(".summary-value").textContent = h.text;
2262
2278
  const y = c.querySelector(".summary-swatch");
2263
2279
  y.hidden = !h.swatch, h.swatch && (y.style.background = h.swatch);
2264
2280
  });
2265
2281
  };
2266
- s(), e.onChange(s), t.append(o.el);
2282
+ r(), e.onChange(r), t.append(o.el);
2267
2283
  },
2268
2284
  character(t, e, { label: n = "Character" } = {}) {
2269
- const a = B(n), o = ja({
2285
+ const a = B(n), o = Da({
2270
2286
  label: n,
2271
2287
  ends: { top: "Spacious", bottom: "Compact", left: "Subtle", right: "Bold" },
2272
- onInput: (s, i) => {
2273
- const l = +(Ne - i * (Ne - bn)).toFixed(3), p = +s.toFixed(3);
2288
+ onInput: (r, i) => {
2289
+ const l = +(je - i * (je - vn)).toFixed(3), p = +r.toFixed(3);
2274
2290
  e.setSections({
2275
2291
  density: { factor: l === 1 ? null : l, spacing: null },
2276
2292
  character: { bold: p === 0.5 ? null : p }
@@ -2278,24 +2294,24 @@ const je = (t) => t && t[0].toUpperCase() + t.slice(1), xn = [
2278
2294
  }
2279
2295
  });
2280
2296
  a.append(o.el);
2281
- const r = () => {
2282
- const s = e.getState(), i = te(s.density), l = $t(s.character), p = l === null ? 0.5 : l, c = `${Bn(i)} · ${co(p)}`;
2283
- o.setValue(p, (Ne - i) / (Ne - bn), c), a.setValue(c);
2297
+ const s = () => {
2298
+ const r = e.getState(), i = ae(r.density), l = Et(r.character), p = l === null ? 0.5 : l, c = `${Vn(i)} · ${fo(p)}`;
2299
+ o.setValue(p, (je - i) / (je - vn), c), a.setValue(c);
2284
2300
  };
2285
- r(), e.onChange(r), t.append(a.el);
2301
+ s(), e.onChange(s), t.append(a.el);
2286
2302
  }
2287
- }, dt = [
2303
+ }, ct = [
2288
2304
  { key: "page-pad", label: "Page padding", step: 5 },
2289
2305
  { key: "section-gap", label: "Section gap", step: 6 },
2290
2306
  { key: "card-pad", label: "Card padding", step: 5 },
2291
2307
  { key: "card-gap", label: "Card gap", step: 2 },
2292
2308
  { key: "control-gap", label: "Control gap", step: 3 },
2293
2309
  { key: "control-pad-x", label: "Control padding", step: null }
2294
- ], uo = [1, 2, 3, 4, 5, 6, 7, 8], ho = /^var\(\s*--twd-space-(\d)\s*\)$/, ct = (t) => {
2310
+ ], mo = [1, 2, 3, 4, 5, 6, 7, 8], bo = /^var\(\s*--twd-space-(\d)\s*\)$/, pt = (t) => {
2295
2311
  const e = /^(-?\d*\.?\d+)(px|rem)?$/.exec(String(t).trim());
2296
2312
  return e ? +(parseFloat(e[1]) * (e[2] === "rem" ? 16 : 1)).toFixed(1) : null;
2297
2313
  };
2298
- function fo(t, e, n) {
2314
+ function xo(t, e, n) {
2299
2315
  const a = `--twd-${e.key}`, o = document.createElement("div");
2300
2316
  o.className = "role-row", n || o.classList.add("unused"), o.innerHTML = `
2301
2317
  <span class="role-label" title="${a}${n ? "" : " (not used on this page)"}">${e.label}</span>
@@ -2306,19 +2322,19 @@ function fo(t, e, n) {
2306
2322
  </span>
2307
2323
  <button class="icon-btn token-reset" title="Back to the default" aria-label="Reset ${e.label}" hidden>${A.reset}</button>
2308
2324
  `;
2309
- const r = o.querySelector("select"), s = o.querySelector(".role-fixed"), i = s.querySelector("input"), l = o.querySelector(".token-reset"), p = () => (t.getState().custom || {})[e.key], c = () => {
2325
+ const s = o.querySelector("select"), r = o.querySelector(".role-fixed"), i = r.querySelector("input"), l = o.querySelector(".token-reset"), p = () => (t.getState().custom || {})[e.key], c = () => {
2310
2326
  const x = p();
2311
2327
  if (x == null) return e.step ? { step: e.step } : { fixed: F(a) };
2312
- const b = ho.exec(x);
2328
+ const b = bo.exec(x);
2313
2329
  return b ? { step: +b[1] } : { fixed: x };
2314
2330
  }, h = (x) => t.setSection("custom", { [e.key]: x }), y = (x) => e.step ? x === `var(--twd-space-${e.step})` : !1;
2315
- r.addEventListener("change", () => {
2316
- if (r.value === "fixed") {
2317
- const b = ct(F(a));
2331
+ s.addEventListener("change", () => {
2332
+ if (s.value === "fixed") {
2333
+ const b = pt(F(a));
2318
2334
  h(b != null ? `${b}px` : F(a)), i.focus(), i.select();
2319
2335
  return;
2320
2336
  }
2321
- const x = `var(--twd-space-${r.value})`;
2337
+ const x = `var(--twd-space-${s.value})`;
2322
2338
  h(y(x) ? null : x);
2323
2339
  });
2324
2340
  const f = () => {
@@ -2331,8 +2347,8 @@ function fo(t, e, n) {
2331
2347
  }), l.addEventListener("click", () => h(null));
2332
2348
  function m() {
2333
2349
  const x = c();
2334
- if (r.innerHTML = uo.map((u) => `<option value="${u}">space-${u} · ${ct(F(`--twd-space-${u}`)) ?? "?"}</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) {
2335
- const u = ct(x.fixed);
2350
+ if (s.innerHTML = mo.map((u) => `<option value="${u}">space-${u} · ${pt(F(`--twd-space-${u}`)) ?? "?"}</option>`).join("") + '<option value="fixed">Fixed</option>', s.value = x.step ? String(x.step) : "fixed", r.hidden = !x.fixed, o.classList.toggle("is-fixed", !!x.fixed), x.fixed && o.getRootNode().activeElement !== i) {
2351
+ const u = pt(x.fixed);
2336
2352
  i.value = u != null ? String(u) : x.fixed;
2337
2353
  }
2338
2354
  const b = p() != null;
@@ -2340,16 +2356,16 @@ function fo(t, e, n) {
2340
2356
  }
2341
2357
  return m(), t.onChange(m), o;
2342
2358
  }
2343
- const go = {
2359
+ const wo = {
2344
2360
  spacing(t, e, { label: n = "Roles" } = {}) {
2345
- const a = Fa(), o = B(n);
2361
+ const a = za(), o = B(n);
2346
2362
  o.el.classList.add("token-field");
2347
- const r = dt.filter((l) => !a.has(`--twd-${l.key}`));
2348
- o.setValue(r.length === dt.length ? "not used on this page" : "");
2349
- const s = document.createElement("div");
2350
- s.className = "token-rows", dt.forEach((l) => s.append(fo(e, l, a.has(`--twd-${l.key}`)))), o.append(s), t.append(o.el);
2363
+ const s = ct.filter((l) => !a.has(`--twd-${l.key}`));
2364
+ o.setValue(s.length === ct.length ? "not used on this page" : "");
2365
+ const r = document.createElement("div");
2366
+ r.className = "token-rows", ct.forEach((l) => r.append(xo(e, l, a.has(`--twd-${l.key}`)))), o.append(r), t.append(o.el);
2351
2367
  const i = document.createElement("p");
2352
- i.className = "role-note", i.textContent = r.length ? `Only elements styled with these tokens change. Not used on this page: ${r.map((l) => l.label).join(", ")}.` : "Each role points at a spacing step, so Density still scales it. Pick another step, or a fixed value.", t.append(i);
2368
+ i.className = "role-note", i.textContent = s.length ? `Only elements styled with these tokens change. Not used on this page: ${s.map((l) => l.label).join(", ")}.` : "Each role points at a spacing step, so Density still scales it. Pick another step, or a fixed value.", t.append(i);
2353
2369
  }
2354
2370
  }, xe = [
2355
2371
  { id: "overview", title: "Overview", icon: "tabOverview", parts: [["simple", "character"], ["simple", "summary"]] },
@@ -2391,18 +2407,18 @@ const go = {
2391
2407
  ["depth", "intensity"],
2392
2408
  { more: "Shadow tokens", parts: [["custom", "shadows"]] }
2393
2409
  ] }
2394
- ], O = (t) => String(t).replace(/[&<>"]/g, (e) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;" })[e]);
2395
- function mo({ sections: t, store: e, view: n }) {
2410
+ ], P = (t) => String(t).replace(/[&<>"]/g, (e) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;" })[e]);
2411
+ function vo({ sections: t, store: e, view: n }) {
2396
2412
  const a = document.createElement("div");
2397
2413
  a.id = "twiddle-root", document.body.appendChild(a);
2398
- const o = a.attachShadow({ mode: "open" }), r = (d) => d.map((g) => `
2414
+ const o = a.attachShadow({ mode: "open" }), s = (d) => d.map((g) => `
2399
2415
  <details data-section="${g.id}">
2400
2416
  <summary>${g.title}<span class="chev">${A.chevron}</span></summary>
2401
2417
  <div class="section-body"><div class="placeholder">${g.hint}</div></div>
2402
2418
  </details>
2403
2419
  `).join("");
2404
2420
  o.innerHTML = `
2405
- <style>${ua}</style>
2421
+ <style>${ma}</style>
2406
2422
  <div class="pick-box" hidden><span class="pick-tag"></span></div>
2407
2423
  <div class="wrap">
2408
2424
  <div class="toast" role="status"></div>
@@ -2413,6 +2429,7 @@ function mo({ sections: t, store: e, view: n }) {
2413
2429
  <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>
2414
2430
  <button class="icon-btn" data-action="copy" title="Copy link to this version" aria-label="Copy link">${A.link}</button>
2415
2431
  <button class="icon-btn" data-action="reset" title="Reset to defaults" aria-label="Reset">${A.reset}</button>
2432
+ <button class="icon-btn" data-action="minimise" title="Minimise to the tabs" aria-label="Minimise to the tabs">${A.minimise}</button>
2416
2433
  <button class="icon-btn" data-action="close" title="Close (Alt+T)" aria-label="Close">${A.close}</button>
2417
2434
  </div>
2418
2435
  <div class="actions">
@@ -2455,7 +2472,7 @@ function mo({ sections: t, store: e, view: n }) {
2455
2472
  </div>
2456
2473
  </div>
2457
2474
  `;
2458
- const s = (d) => o.querySelector(d), i = s(".panel"), l = s(".launcher"), p = s(".toast"), c = { global: s('[data-view="global"]'), local: s('[data-view="local"]'), changes: s('[data-view="changes"]') }, h = s(".pick-box"), y = s(".pick-tag"), f = { getState: e.getState, setSection: e.setSection, setSections: e.setSections, onChange: e.onChange };
2475
+ const r = (d) => o.querySelector(d), i = r(".panel"), l = r(".launcher"), p = r(".toast"), c = { global: r('[data-view="global"]'), local: r('[data-view="local"]'), changes: r('[data-view="changes"]') }, h = r(".pick-box"), y = r(".pick-tag"), f = { getState: e.getState, setSection: e.setSection, setSections: e.setSections, onChange: e.onChange };
2459
2476
  function m(d, g, w) {
2460
2477
  g.forEach((k) => {
2461
2478
  if (typeof k.render != "function") return;
@@ -2491,21 +2508,21 @@ function mo({ sections: t, store: e, view: n }) {
2491
2508
  const S = w.tabs.map((j) => {
2492
2509
  const z = document.createElement("div");
2493
2510
  return z.className = "tab-pane", b(z, j.parts), z;
2494
- }), he = re({
2511
+ }), fe = ie({
2495
2512
  label: "View",
2496
2513
  options: w.tabs.map((j, z) => ({ value: String(z), label: j.label })),
2497
2514
  onSelect: (j) => {
2498
- he.setValue(j), S.forEach((z, Zn) => {
2499
- z.hidden = String(Zn) !== j;
2515
+ fe.setValue(j), S.forEach((z, ea) => {
2516
+ z.hidden = String(ea) !== j;
2500
2517
  });
2501
2518
  }
2502
2519
  });
2503
- he.setValue("0"), S.forEach((j, z) => {
2520
+ fe.setValue("0"), S.forEach((j, z) => {
2504
2521
  j.hidden = z !== 0;
2505
- }), d.append(he.el, ...S);
2522
+ }), d.append(fe.el, ...S);
2506
2523
  return;
2507
2524
  }
2508
- const [$, k, C = {}] = w, q = $ === "simple" ? po[k] : $ === "roles" ? go[k] : x[$]?.parts?.[k];
2525
+ const [$, k, C = {}] = w, q = $ === "simple" ? go[k] : $ === "roles" ? wo[k] : x[$]?.parts?.[k];
2509
2526
  q && q(d, f, { ...C, buttons: x.buttons, cards: x.cards, goTab: (S) => {
2510
2527
  G("global"), E(S);
2511
2528
  } });
@@ -2513,7 +2530,7 @@ function mo({ sections: t, store: e, view: n }) {
2513
2530
  }
2514
2531
  xe.forEach((d) => b(c.global.querySelector(`[data-page="${d.id}"]`), d.parts));
2515
2532
  const u = [...o.querySelectorAll(".tab")];
2516
- let v = xe.some((d) => d.id === fe("tab")) ? fe("tab") : xe[0].id;
2533
+ let v = xe.some((d) => d.id === ne("tab")) ? ne("tab") : xe[0].id;
2517
2534
  function L() {
2518
2535
  u.forEach((d) => d.setAttribute("aria-pressed", String(K === "global" && d.dataset.tab === v)));
2519
2536
  }
@@ -2522,86 +2539,94 @@ function mo({ sections: t, store: e, view: n }) {
2522
2539
  g.hidden = g.dataset.page !== d;
2523
2540
  }), c.global.scrollTop = 0, L();
2524
2541
  }
2525
- const J = (d) => d.map((g) => `<div class="warning">${A.warn}<span>${O(g.text)}</span></div>`).join("");
2542
+ const Q = (d) => d.map((g) => `<div class="warning">${A.warn}<span>${P(g.text)}</span></div>`).join("");
2526
2543
  let K = "global";
2527
2544
  function G(d) {
2528
2545
  K = d, Object.entries(c).forEach(([g, w]) => {
2529
2546
  w.hidden = g !== d;
2530
- }), s('[data-action="changes"]').setAttribute("aria-pressed", String(d === "changes")), d !== "local" && Hn(), d === "changes" && Ut(), L();
2547
+ }), r('[data-action="changes"]').setAttribute("aria-pressed", String(d === "changes")), d !== "local" && Wn(), d === "changes" && Ht(), L();
2531
2548
  }
2532
2549
  E(v);
2533
- const qe = "cubic-bezier(0.3, 0.7, 0.2, 1)", Ve = "cubic-bezier(0.2, 0.8, 0.2, 1)", Se = 640, ie = 100, He = 50, Un = () => l.querySelector(".mark-knob"), qn = () => [l.querySelector(".mark-t1"), l.querySelector(".mark-t2")];
2534
- function Et(d) {
2550
+ const Ve = "cubic-bezier(0.3, 0.7, 0.2, 1)", He = "cubic-bezier(0.2, 0.8, 0.2, 1)", Se = 640, de = 100, _e = 50, Hn = () => l.querySelector(".mark-knob"), _n = () => [l.querySelector(".mark-t1"), l.querySelector(".mark-t2")];
2551
+ function Ct(d) {
2535
2552
  if (matchMedia("(prefers-reduced-motion: reduce)").matches || !l.animate) return;
2536
- const g = Un(), [w, $] = qn(), k = (C) => `translateY(${C}px)`;
2553
+ const g = Hn(), [w, $] = _n(), k = (C) => `translateY(${C}px)`;
2537
2554
  if (d) {
2538
- g.animate([{ transform: k(32) }, { transform: k(-6), offset: 0.78 }, { transform: k(0) }], { duration: Se, easing: qe });
2555
+ g.animate([{ transform: k(32) }, { transform: k(-6), offset: 0.78 }, { transform: k(0) }], { duration: Se, easing: Ve });
2539
2556
  const C = [{ transform: "scale(0.4)", opacity: 0 }, { transform: "scale(1)", opacity: 1 }];
2540
- $.animate(C, { duration: ie * 2, delay: Se * 0.12, easing: qe, fill: "backwards" }), w.animate(C, { duration: ie * 2, delay: Se * 0.32 + He, easing: qe, fill: "backwards" });
2557
+ $.animate(C, { duration: de * 2, delay: Se * 0.12, easing: Ve, fill: "backwards" }), w.animate(C, { duration: de * 2, delay: Se * 0.32 + _e, easing: Ve, fill: "backwards" });
2541
2558
  } else {
2542
2559
  const C = [{ opacity: 1 }, { opacity: 0 }];
2543
- w.animate(C, { duration: ie, easing: Ve }), $.animate(C, { duration: ie, delay: He / 2, easing: Ve, fill: "backwards" }), g.animate([{ transform: k(0) }, { transform: k(34), offset: 0.8 }, { transform: k(32) }], { duration: Se * 0.7, delay: ie + He / 2, easing: Ve, fill: "backwards" });
2560
+ w.animate(C, { duration: de, easing: He }), $.animate(C, { duration: de, delay: _e / 2, easing: He, fill: "backwards" }), g.animate([{ transform: k(0) }, { transform: k(34), offset: 0.8 }, { transform: k(32) }], { duration: Se * 0.7, delay: de + _e / 2, easing: He, fill: "backwards" });
2544
2561
  }
2545
2562
  }
2546
- function le({ animate: d = !0 } = {}) {
2547
- i.hidden && d && Et(!0), i.hidden = !1, l.setAttribute("aria-expanded", "true"), l.setAttribute("aria-label", "Close Panel"), ge("panel", "open");
2563
+ const Mt = r(".wrap");
2564
+ let Tt = !1;
2565
+ function $e(d) {
2566
+ Tt = d, i.classList.toggle("minimised", d), i.hidden || ge("panel", d ? "tabs" : "open");
2567
+ }
2568
+ function W({ animate: d = !0 } = {}) {
2569
+ i.hidden && d && Ct(!0), i.hidden = !1, Mt.classList.add("is-open"), l.setAttribute("aria-expanded", "true"), l.setAttribute("aria-label", "Close Panel"), $e(!1);
2548
2570
  }
2549
- function _e() {
2550
- i.hidden || Et(!1), i.hidden = !0, l.setAttribute("aria-expanded", "false"), l.setAttribute("aria-label", "Open Panel"), ge("panel", "closed"), $e();
2571
+ function Kn() {
2572
+ i.hidden && W(), $e(!0);
2551
2573
  }
2552
2574
  function Ke() {
2553
- i.hidden ? le() : _e();
2575
+ i.hidden || Ct(!1), i.hidden = !0, Mt.classList.remove("is-open"), l.setAttribute("aria-expanded", "false"), l.setAttribute("aria-label", "Open Panel"), ge("panel", "closed"), Ee();
2554
2576
  }
2555
- let Ct;
2577
+ function Ge() {
2578
+ i.hidden ? W() : Ke();
2579
+ }
2580
+ let At;
2556
2581
  function H(d) {
2557
- p.textContent = d, p.classList.add("show"), clearTimeout(Ct), Ct = setTimeout(() => p.classList.remove("show"), 1600);
2582
+ p.textContent = d, p.classList.add("show"), clearTimeout(At), At = setTimeout(() => p.classList.remove("show"), 1600);
2558
2583
  }
2559
- function de(d, g) {
2584
+ function ce(d, g) {
2560
2585
  navigator.clipboard.writeText(d).then(() => H(g)).catch(() => H("Couldn’t copy — select the text and copy it instead"));
2561
2586
  }
2562
- let Ge = null;
2563
- function Q(d, g) {
2564
- if (Ge = d, !d) {
2587
+ let We = null;
2588
+ function ee(d, g) {
2589
+ if (We = d, !d) {
2565
2590
  h.hidden = !0;
2566
2591
  return;
2567
2592
  }
2568
2593
  const w = d.getBoundingClientRect();
2569
- Object.assign(h.style, { top: `${w.top}px`, left: `${w.left}px`, width: `${w.width}px`, height: `${w.height}px` }), y.textContent = g || bt(d), h.hidden = !1;
2594
+ Object.assign(h.style, { top: `${w.top}px`, left: `${w.left}px`, width: `${w.width}px`, height: `${w.height}px` }), y.textContent = g || xt(d), h.hidden = !1;
2570
2595
  }
2571
- const Tt = () => {
2572
- Ge && !h.hidden && Q(Ge, y.textContent);
2596
+ const Lt = () => {
2597
+ We && !h.hidden && ee(We, y.textContent);
2573
2598
  };
2574
- window.addEventListener("scroll", Tt, !0), window.addEventListener("resize", Tt);
2575
- let ce = !1;
2576
- const Mt = s('[data-action="pick"]'), At = (d) => d.composedPath().includes(a);
2577
- function Lt(d) {
2578
- if (At(d)) return;
2599
+ window.addEventListener("scroll", Lt, !0), window.addEventListener("resize", Lt);
2600
+ let pe = !1;
2601
+ const Ot = r('[data-action="pick"]'), Pt = (d) => d.composedPath().includes(a);
2602
+ function Ft(d) {
2603
+ if (Pt(d)) return;
2579
2604
  const g = d.target;
2580
- g && g.nodeType === 1 && g !== document.documentElement && g !== document.body && Q(g);
2605
+ g && g.nodeType === 1 && g !== document.documentElement && g !== document.body && ee(g);
2581
2606
  }
2582
- function Pt(d) {
2583
- if (At(d) || (d.preventDefault(), d.stopPropagation(), d.type !== "click")) return;
2607
+ function Nt(d) {
2608
+ if (Pt(d) || (d.preventDefault(), d.stopPropagation(), d.type !== "click")) return;
2584
2609
  const g = d.target;
2585
- !g || g === document.documentElement || g === document.body || ($e(), jt(g));
2610
+ !g || g === document.documentElement || g === document.body || (Ee(), It(g));
2586
2611
  }
2587
- function Ot(d) {
2588
- d.key === "Escape" && (d.preventDefault(), $e(), M && Q(M.el));
2612
+ function jt(d) {
2613
+ d.key === "Escape" && (d.preventDefault(), Ee(), T && ee(T.el));
2589
2614
  }
2590
- const Ft = ["pointerdown", "mousedown", "mouseup", "click"];
2591
- function Nt() {
2592
- if (!ce) {
2593
- if (ce = !0, !document.getElementById("twiddle-picking")) {
2615
+ const Rt = ["pointerdown", "mousedown", "mouseup", "click"];
2616
+ function zt() {
2617
+ if (!pe) {
2618
+ if (pe = !0, !document.getElementById("twiddle-picking")) {
2594
2619
  const d = document.createElement("style");
2595
2620
  d.id = "twiddle-picking", d.textContent = "html.twd-picking, html.twd-picking * { cursor: crosshair !important; }", document.head.appendChild(d);
2596
2621
  }
2597
- le(), Mt.setAttribute("aria-pressed", "true"), document.documentElement.classList.add("twd-picking"), document.addEventListener("pointermove", Lt, !0), Ft.forEach((d) => document.addEventListener(d, Pt, !0)), document.addEventListener("keydown", Ot, !0), H("Click an element · Esc to cancel");
2622
+ W(), Ot.setAttribute("aria-pressed", "true"), document.documentElement.classList.add("twd-picking"), document.addEventListener("pointermove", Ft, !0), Rt.forEach((d) => document.addEventListener(d, Nt, !0)), document.addEventListener("keydown", jt, !0), H("Click an element · Esc to cancel");
2598
2623
  }
2599
2624
  }
2600
- function $e() {
2601
- ce && (ce = !1, Mt.setAttribute("aria-pressed", "false"), document.documentElement.classList.remove("twd-picking"), document.removeEventListener("pointermove", Lt, !0), Ft.forEach((d) => document.removeEventListener(d, Pt, !0)), document.removeEventListener("keydown", Ot, !0), Q(M ? M.el : null));
2625
+ function Ee() {
2626
+ pe && (pe = !1, Ot.setAttribute("aria-pressed", "false"), document.documentElement.classList.remove("twd-picking"), document.removeEventListener("pointermove", Ft, !0), Rt.forEach((d) => document.removeEventListener(d, Nt, !0)), document.removeEventListener("keydown", jt, !0), ee(T ? T.el : null));
2602
2627
  }
2603
- let M = null;
2604
- function Vn(d, g) {
2628
+ let T = null;
2629
+ function Gn(d, g) {
2605
2630
  const w = [];
2606
2631
  return {
2607
2632
  ctx: {
@@ -2616,260 +2641,262 @@ function mo({ sections: t, store: e, view: n }) {
2616
2641
  dispose: () => w.forEach(($) => $())
2617
2642
  };
2618
2643
  }
2619
- function jt(d, g) {
2620
- const w = xa(d), $ = e.getState().scopes || {};
2621
- g || (g = !$[w.elementSelector] && w.classSelector && $[w.classSelector] ? "class" : "element"), M && M.dispose(), M = { el: d, info: w, target: g, dispose: () => {
2622
- } }, We(), G("local"), le(), Q(d);
2644
+ function It(d, g) {
2645
+ const w = ka(d), $ = e.getState().scopes || {};
2646
+ g || (g = !$[w.elementSelector] && w.classSelector && $[w.classSelector] ? "class" : "element"), T && T.dispose(), T = { el: d, info: w, target: g, dispose: () => {
2647
+ } }, Ye(), G("local"), W(), ee(d);
2623
2648
  }
2624
- const Rt = () => M.target === "class" ? M.info.classSelector : M.info.elementSelector;
2625
- function We() {
2626
- M.dispose();
2627
- const { info: d } = M, g = t.filter((j) => (j.uses || []).some((z) => d.tokens.has(z))), w = c.local;
2649
+ const Dt = () => T.target === "class" ? T.info.classSelector : T.info.elementSelector;
2650
+ function Ye() {
2651
+ T.dispose();
2652
+ const { info: d } = T, g = t.filter((j) => (j.uses || []).some((z) => d.tokens.has(z))), w = c.local;
2628
2653
  if (w.innerHTML = `
2629
2654
  <div class="scope-bar">
2630
2655
  <div class="scope-head">
2631
2656
  <button class="icon-btn" data-action="back" title="Back to the whole page" aria-label="Back to the whole page">${A.back}</button>
2632
2657
  <div class="scope-name">
2633
- <code>${O(bt(d.el))}</code>
2634
- ${d.text ? `<span class="muted">“${O(d.text)}”</span>` : ""}
2658
+ <code>${P(xt(d.el))}</code>
2659
+ ${d.text ? `<span class="muted">“${P(d.text)}”</span>` : ""}
2635
2660
  </div>
2636
2661
  </div>
2637
2662
  <div class="scope-target"></div>
2638
2663
  <div class="warnings"></div>
2639
2664
  </div>
2640
- ${g.length ? r(g) : '<div class="empty">This element doesn’t use Panel tokens yet, so there’s nothing to tweak here. Style it with <code>var(--twd-…)</code> to make it tweakable.</div>'}
2665
+ ${g.length ? s(g) : '<div class="empty">This element doesn’t use Panel tokens yet, so there’s nothing to tweak here. Style it with <code>var(--twd-…)</code> to make it tweakable.</div>'}
2641
2666
  `, d.classSelector) {
2642
- const j = re({
2667
+ const j = ie({
2643
2668
  label: "Apply to",
2644
2669
  options: [
2645
2670
  { value: "element", label: "This element" },
2646
2671
  { value: "class", label: `All ${d.classSelector} (${d.classCount})`, title: `Every element matching ${d.classSelector}` }
2647
2672
  ],
2648
2673
  onSelect: (z) => {
2649
- z === "class" && e.moveScope(d.elementSelector, d.classSelector), M.target = z, We();
2674
+ z === "class" && e.moveScope(d.elementSelector, d.classSelector), T.target = z, Ye();
2650
2675
  }
2651
2676
  });
2652
- j.setValue(M.target), w.querySelector(".scope-target").append(j.el);
2677
+ j.setValue(T.target), w.querySelector(".scope-target").append(j.el);
2653
2678
  }
2654
- const { ctx: $, dispose: k } = Vn(Rt(), d.el), C = m(w, g, $);
2679
+ const { ctx: $, dispose: k } = Gn(Dt(), d.el), C = m(w, g, $);
2655
2680
  C[0] && (C[0].open = !0);
2656
2681
  const q = w.querySelector(".warnings"), S = () => {
2657
- const j = d.tokens.size ? Ta(d.el) : null;
2658
- q.innerHTML = j ? J([j]) : "";
2682
+ const j = d.tokens.size ? Oa(d.el) : null;
2683
+ q.innerHTML = j ? Q([j]) : "";
2659
2684
  };
2660
2685
  S();
2661
- const he = e.onChange(S);
2662
- M.dispose = () => {
2663
- k(), he();
2686
+ const fe = e.onChange(S);
2687
+ T.dispose = () => {
2688
+ k(), fe();
2664
2689
  };
2665
2690
  }
2666
- function zt() {
2667
- if (!M || !M.info.classSelector) return;
2668
- const d = e.getState().scopes || {}, g = M.target === "class" ? "element" : "class", w = g === "class" ? M.info.classSelector : M.info.elementSelector;
2669
- !d[Rt()] && d[w] && (M.target = g, We());
2670
- }
2671
- const It = () => {
2672
- e.undo(), zt();
2673
- }, Dt = () => {
2674
- e.redo(), zt();
2691
+ function Bt() {
2692
+ if (!T || !T.info.classSelector) return;
2693
+ const d = e.getState().scopes || {}, g = T.target === "class" ? "element" : "class", w = g === "class" ? T.info.classSelector : T.info.elementSelector;
2694
+ !d[Dt()] && d[w] && (T.target = g, Ye());
2695
+ }
2696
+ const Ut = () => {
2697
+ e.undo(), Bt();
2698
+ }, qt = () => {
2699
+ e.redo(), Bt();
2675
2700
  };
2676
- function Hn() {
2677
- M && (M.dispose(), M = null, c.local.innerHTML = "", Q(null));
2701
+ function Wn() {
2702
+ T && (T.dispose(), T = null, c.local.innerHTML = "", ee(null));
2678
2703
  }
2679
- const Bt = (d) => d.kind === "global" ? "Whole page" : d.kind === "class" ? `All ${d.selector}` : "One element";
2680
- function Ut() {
2681
- const d = en(e.getState(), t), g = Je(), w = c.changes;
2704
+ const Vt = (d) => d.kind === "global" ? "Whole page" : d.kind === "class" ? `All ${d.selector}` : "One element";
2705
+ function Ht() {
2706
+ const d = an(e.getState(), t), g = Qe(), w = c.changes;
2682
2707
  if (!d.length) {
2683
- w.innerHTML = `<div class="empty">No changes yet. Tweak a section, or pick an element to change it on its own.</div>${J(g)}`;
2708
+ w.innerHTML = `<div class="empty">No changes yet. Tweak a section, or pick an element to change it on its own.</div>${Q(g)}`;
2684
2709
  return;
2685
2710
  }
2686
2711
  const $ = /* @__PURE__ */ new Map();
2687
2712
  d.forEach((k) => {
2688
2713
  const C = k.selector || "";
2689
2714
  $.has(C) || $.set(C, []), $.get(C).push(k);
2690
- }), w.innerHTML = (g.length ? `<div class="warnings">${J(g)}</div>` : "") + [...$].map(([k, C]) => `
2715
+ }), w.innerHTML = (g.length ? `<div class="warnings">${Q(g)}</div>` : "") + [...$].map(([k, C]) => `
2691
2716
  <div class="change-group">
2692
2717
  <div class="change-scope">
2693
- ${k ? `<button class="link-btn" data-select="${O(k)}" title="Select it on the page">${O(Bt(C[0]))}</button><code>${O(k)}</code>` : `<span>${Bt(C[0])}</span>`}
2718
+ ${k ? `<button class="link-btn" data-select="${P(k)}" title="Select it on the page">${P(Vt(C[0]))}</button><code>${P(k)}</code>` : `<span>${Vt(C[0])}</span>`}
2694
2719
  </div>
2695
2720
  ${C.map((q) => `
2696
2721
  <div class="change-row">
2697
2722
  <div class="change-main">
2698
- <div class="change-title">${O(q.title)} <span class="muted">›</span> ${q.settings.map((S) => `${O(S.label)}: <b>${O(S.value)}</b>`).join(", ")}</div>
2699
- ${q.tokens.map((S) => `<div class="change-token"><code>${O(S.name)}</code> ${S.from ? `${O(S.from)} → ` : ""}${O(S.to)}</div>`).join("")}
2723
+ <div class="change-title">${P(q.title)} <span class="muted">›</span> ${q.settings.map((S) => `${P(S.label)}: <b>${P(S.value)}</b>`).join(", ")}</div>
2724
+ ${q.tokens.map((S) => `<div class="change-token"><code>${P(S.name)}</code> ${S.from ? `${P(S.from)} → ` : ""}${P(S.to)}</div>`).join("")}
2700
2725
  </div>
2701
- <button class="icon-btn" data-remove="${O(q.sectionId)}" data-remove-scope="${O(k)}" aria-label="Remove ${O(q.title)} change">${A.close}</button>
2726
+ <button class="icon-btn" data-remove="${P(q.sectionId)}" data-remove-scope="${P(k)}" aria-label="Remove ${P(q.title)} change">${A.close}</button>
2702
2727
  </div>`).join("")}
2703
2728
  </div>`).join("");
2704
2729
  }
2705
- function _n(d, g) {
2730
+ function Yn(d, g) {
2706
2731
  if (g) return e.removeScope(g, d);
2707
2732
  const w = e.getState()[d] || {};
2708
2733
  e.setSection(d, Object.fromEntries(Object.keys(w).map(($) => [$, null])));
2709
2734
  }
2710
- const pe = s(".apply-menu"), qt = s('[data-action="apply-menu"]'), Vt = () => fe("apply-mode") === "copy" ? "copy" : "preview";
2711
- function Kn() {
2712
- pe.querySelectorAll("[data-apply-mode]").forEach((d) => d.setAttribute("aria-checked", String(d.dataset.applyMode === Vt())));
2735
+ const ue = r(".apply-menu"), _t = r('[data-action="apply-menu"]'), Kt = () => ne("apply-mode") === "copy" ? "copy" : "preview";
2736
+ function Zn() {
2737
+ ue.querySelectorAll("[data-apply-mode]").forEach((d) => d.setAttribute("aria-checked", String(d.dataset.applyMode === Kt())));
2713
2738
  }
2714
- function Ee(d) {
2715
- pe.hidden = !d, qt.setAttribute("aria-expanded", String(d)), d && Kn();
2739
+ function Ce(d) {
2740
+ ue.hidden = !d, _t.setAttribute("aria-expanded", String(d)), d && Zn();
2716
2741
  }
2717
- function Ht() {
2718
- return Sa(en(e.getState(), t), { warnings: Je() });
2742
+ function Gt() {
2743
+ return Ma(an(e.getState(), t), { warnings: Qe() });
2719
2744
  }
2720
- const Ce = s(".dialog-backdrop"), _t = s(".prompt-text");
2721
- function Gn() {
2722
- const d = Ht();
2745
+ const Me = r(".dialog-backdrop"), Wt = r(".prompt-text");
2746
+ function Xn() {
2747
+ const d = Gt();
2723
2748
  if (!d) return H("No changes to copy yet");
2724
- if (Vt() === "copy") return de(d, "Prompt copied · paste it into your agent");
2725
- _t.value = d, Ce.hidden = !1, s('[data-action="dialog-copy"]').focus();
2749
+ if (Kt() === "copy") return ce(d, "Prompt copied · paste it into your agent");
2750
+ Wt.value = d, Me.hidden = !1, r('[data-action="dialog-copy"]').focus();
2726
2751
  }
2727
- function Ye() {
2728
- Ce.hidden = !0, s('[data-action="apply"]').focus();
2752
+ function Ze() {
2753
+ Me.hidden = !0, r('[data-action="apply"]').focus();
2729
2754
  }
2730
- const ee = s('[data-action="compare"]'), Wn = s(".original-pill");
2755
+ const te = r('[data-action="compare"]'), Jn = r(".original-pill");
2731
2756
  function Te(d) {
2732
- d ? n.suspend() : n.resume(), ee.setAttribute("aria-pressed", String(d)), Wn.hidden = !d;
2757
+ d ? n.suspend() : n.resume(), te.setAttribute("aria-pressed", String(d)), Jn.hidden = !d;
2733
2758
  }
2734
- let Kt = null, ue = !1;
2735
- ee.addEventListener("pointerdown", () => {
2736
- ue = !1, Kt = setTimeout(() => {
2737
- ue = !0, Te(!0);
2759
+ let Yt = null, he = !1;
2760
+ te.addEventListener("pointerdown", () => {
2761
+ he = !1, Yt = setTimeout(() => {
2762
+ he = !0, Te(!0);
2738
2763
  }, 180);
2739
2764
  });
2740
- const Gt = () => {
2741
- clearTimeout(Kt), ue && (Te(!1), ue = !1);
2765
+ const Zt = () => {
2766
+ clearTimeout(Yt), he && (Te(!1), he = !1);
2742
2767
  };
2743
- ee.addEventListener("pointerup", Gt), ee.addEventListener("pointerleave", Gt);
2744
- const Me = s(".setup-hint"), Wt = `setup-hint-dismissed:${location.pathname}`, Yn = {
2768
+ te.addEventListener("pointerup", Zt), te.addEventListener("pointerleave", Zt);
2769
+ const Ae = r(".setup-hint"), Xt = `setup-hint-dismissed:${location.pathname}`, Qn = {
2745
2770
  "no-tokens": {
2746
2771
  title: "The Panel tokens aren’t loaded",
2747
2772
  text: "The knobs change the --twd-* variables, but this page doesn’t load them. Add the token stylesheet before your own CSS:",
2748
- snippets: sn,
2749
- link: `${rn}/#install`
2773
+ snippets: cn,
2774
+ link: `${dn}/#install`
2750
2775
  },
2751
2776
  unused: {
2752
2777
  title: "Nothing here uses the Panel tokens yet",
2753
2778
  text: "The tokens are loaded, but no style on this page uses var(--twd-…), so the knobs won’t change anything. Ask your coding agent to convert the styles:",
2754
2779
  copy: "Copy prompt for your agent",
2755
2780
  copied: "Prompt copied",
2756
- text2copy: Na,
2757
- link: `${rn}/#tokens`
2781
+ text2copy: Ia,
2782
+ link: `${dn}/#tokens`
2758
2783
  }
2759
2784
  };
2760
2785
  let D = null;
2761
- function Ae() {
2762
- const d = Oa();
2763
- D = fe(Wt) === d ? null : Yn[d] || null, l.toggleAttribute("data-hint", !!D), Me.hidden = !D, D && (Me.innerHTML = `
2764
- <div class="setup-head">${A.warn}<b>${O(D.title)}</b>
2786
+ function Le() {
2787
+ const d = Ra();
2788
+ D = ne(Xt) === d ? null : Qn[d] || null, l.toggleAttribute("data-hint", !!D), Ae.hidden = !D, D && (Ae.innerHTML = `
2789
+ <div class="setup-head">${A.warn}<b>${P(D.title)}</b>
2765
2790
  <button class="icon-btn" data-action="setup-dismiss" title="Hide this message" aria-label="Hide this message">${A.close}</button>
2766
2791
  </div>
2767
- <p>${O(D.text)}</p>
2792
+ <p>${P(D.text)}</p>
2768
2793
  ${(D.snippets || []).map((g, w) => `
2769
2794
  <div class="setup-snippet">
2770
- <span>${O(g.label)}</span>
2771
- <div class="setup-code"><code>${O(g.code)}</code><button class="text-btn" data-setup-snippet="${w}">Copy</button></div>
2795
+ <span>${P(g.label)}</span>
2796
+ <div class="setup-code"><code>${P(g.code)}</code><button class="text-btn" data-setup-snippet="${w}">Copy</button></div>
2772
2797
  </div>`).join("")}
2773
2798
  <div class="setup-actions">
2774
- ${D.copy ? `<button class="apply-btn" data-action="setup-copy">${O(D.copy)}</button>` : ""}
2799
+ ${D.copy ? `<button class="apply-btn" data-action="setup-copy">${P(D.copy)}</button>` : ""}
2775
2800
  <a href="${D.link}" target="_blank" rel="noopener">Setup guide</a>
2776
- </div>`, Me.dataset.status = d);
2777
- }
2778
- Ae(), document.readyState !== "complete" && window.addEventListener("load", Ae, { once: !0 }), setTimeout(Ae, 1500);
2779
- const Yt = s(".badge");
2780
- function Zt() {
2781
- s('[data-action="undo"]').disabled = !e.canUndo(), s('[data-action="redo"]').disabled = !e.canRedo();
2782
- const d = ya(e.getState());
2783
- Yt.textContent = d, Yt.hidden = !d;
2784
- const g = J(Je());
2801
+ </div>`, Ae.dataset.status = d);
2802
+ }
2803
+ Le(), document.readyState !== "complete" && window.addEventListener("load", Le, { once: !0 }), setTimeout(Le, 1500);
2804
+ const Jt = r(".badge");
2805
+ function Qt() {
2806
+ r('[data-action="undo"]').disabled = !e.canUndo(), r('[data-action="redo"]').disabled = !e.canRedo();
2807
+ const d = Ea(e.getState());
2808
+ Jt.textContent = d, Jt.hidden = !d;
2809
+ const g = Q(Qe());
2785
2810
  c.global.querySelectorAll(".page-warnings").forEach((w) => {
2786
2811
  w.innerHTML = g;
2787
- }), K === "changes" && Ut();
2812
+ }), K === "changes" && Ht();
2788
2813
  }
2789
- return e.onChange(Zt), Zt(), o.addEventListener("click", (d) => {
2790
- if (d.target === Ce) return Ye();
2814
+ return e.onChange(Qt), Qt(), o.addEventListener("click", (d) => {
2815
+ if (d.target === Me) return Ze();
2791
2816
  const g = d.target.closest("button");
2792
2817
  if (g) {
2793
- if (g !== qt && !pe.contains(g) && Ee(!1), g === l) return Ke();
2818
+ if (g !== _t && !ue.contains(g) && Ce(!1), g === l) return Ge();
2794
2819
  if (g.dataset.select) {
2795
2820
  const w = document.querySelector(g.dataset.select);
2796
- return w ? jt(w) : H("That element isn’t on this page");
2821
+ return w ? It(w) : H("That element isn’t on this page");
2797
2822
  }
2798
- if (g.dataset.setupSnippet) return de(sn[g.dataset.setupSnippet].code, "Copied");
2823
+ if (g.dataset.setupSnippet) return ce(cn[g.dataset.setupSnippet].code, "Copied");
2799
2824
  if (g.dataset.tab)
2800
- return G("global"), E(g.dataset.tab);
2801
- if (g.dataset.remove) return _n(g.dataset.remove, g.dataset.removeScope);
2825
+ return G("global"), Tt && $e(!1), E(g.dataset.tab);
2826
+ if (g.dataset.remove) return Yn(g.dataset.remove, g.dataset.removeScope);
2802
2827
  if (g.dataset.applyMode)
2803
- return ge("apply-mode", g.dataset.applyMode), Ee(!1), H(g.dataset.applyMode === "copy" ? "Copy prompt copies straight away" : "Copy prompt shows a preview first");
2828
+ return ge("apply-mode", g.dataset.applyMode), Ce(!1), H(g.dataset.applyMode === "copy" ? "Copy prompt copies straight away" : "Copy prompt shows a preview first");
2804
2829
  switch (g.dataset.action) {
2805
2830
  case "close":
2806
- return _e();
2831
+ return Ke();
2832
+ case "minimise":
2833
+ return Kn(), (o.querySelector('.tab[aria-pressed="true"]') || u[0]).focus();
2807
2834
  case "reset":
2808
2835
  return e.resetState(), H("Reset to defaults · ⌘Z to undo");
2809
2836
  case "copy":
2810
- return de(location.href, "Link copied");
2837
+ return ce(location.href, "Link copied");
2811
2838
  case "pick":
2812
- return ce ? $e() : Nt();
2839
+ return pe ? Ee() : zt();
2813
2840
  case "compare":
2814
- ue || Te(ee.getAttribute("aria-pressed") !== "true");
2841
+ he || Te(te.getAttribute("aria-pressed") !== "true");
2815
2842
  return;
2816
2843
  case "undo":
2817
- return It();
2844
+ return Ut();
2818
2845
  case "redo":
2819
- return Dt();
2846
+ return qt();
2820
2847
  case "back":
2821
2848
  return G("global");
2822
2849
  case "changes":
2823
2850
  return G(K === "changes" ? "global" : "changes");
2824
2851
  case "apply":
2825
- return Gn();
2852
+ return Xn();
2826
2853
  case "apply-menu":
2827
- return Ee(pe.hidden);
2854
+ return Ce(ue.hidden);
2828
2855
  case "dialog-close":
2829
- return Ye();
2856
+ return Ze();
2830
2857
  case "dialog-copy":
2831
- return de(_t.value, "Prompt copied · paste it into your agent");
2858
+ return ce(Wt.value, "Prompt copied · paste it into your agent");
2832
2859
  case "setup-copy":
2833
- return D && de(D.text2copy, D.copied);
2860
+ return D && ce(D.text2copy, D.copied);
2834
2861
  case "setup-dismiss":
2835
- return ge(Wt, Me.dataset.status), Ae();
2862
+ return ge(Xt, Ae.dataset.status), Le();
2836
2863
  }
2837
2864
  }
2838
2865
  }), o.addEventListener("keydown", (d) => {
2839
2866
  if (d.key === "Escape") {
2840
- if (!Ce.hidden) return Ye();
2841
- if (!pe.hidden) return Ee(!1);
2867
+ if (!Me.hidden) return Ze();
2868
+ if (!ue.hidden) return Ce(!1);
2842
2869
  }
2843
- !(d.metaKey || d.ctrlKey) || d.key.toLowerCase() !== "z" || d.target.matches?.('input[type="text"], textarea') || (d.preventDefault(), d.shiftKey ? Dt() : It());
2870
+ !(d.metaKey || d.ctrlKey) || d.key.toLowerCase() !== "z" || d.target.matches?.('input[type="text"], textarea') || (d.preventDefault(), d.shiftKey ? qt() : Ut());
2844
2871
  }), document.addEventListener("keydown", (d) => {
2845
- d.altKey && (d.code === "KeyT" && (d.preventDefault(), Ke()), d.code === "KeyC" && (d.preventDefault(), Te(ee.getAttribute("aria-pressed") !== "true")));
2846
- }), fe("panel") === "open" && le({ animate: !1 }), { open: le, close: _e, toggle: Ke, toast: H, pick: Nt, prompt: Ht };
2872
+ d.altKey && (d.code === "KeyT" && (d.preventDefault(), Ge()), d.code === "KeyC" && (d.preventDefault(), Te(te.getAttribute("aria-pressed") !== "true")));
2873
+ }), ne("panel") === "open" ? W({ animate: !1 }) : ne("panel") === "tabs" && (W({ animate: !1 }), $e(!0)), { open: W, close: Ke, toggle: Ge, toast: H, pick: zt, prompt: Gt };
2847
2874
  }
2848
- const wn = [lo, De, Dn, wt, Va, vt, ao, qa], bo = ':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)}';
2849
- function xo() {
2875
+ const kn = [ho, Be, qn, vt, Ga, yt, io, Ka], yo = ':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)}';
2876
+ function ko() {
2850
2877
  if (getComputedStyle(document.documentElement).getPropertyValue("--twd-radius-control").trim() || document.getElementById("twiddle-tokens")) return;
2851
2878
  const e = document.createElement("style");
2852
- e.id = "twiddle-tokens", e.textContent = bo, document.head.prepend(e);
2879
+ e.id = "twiddle-tokens", e.textContent = yo, document.head.prepend(e);
2853
2880
  }
2854
2881
  if (!window.Twiddle) {
2855
- xo(), wn.forEach((n) => sa(n.tokens)), $n(gt);
2882
+ ko(), kn.forEach((n) => ca(n.tokens)), Mn(mt);
2856
2883
  let t;
2857
2884
  const e = () => {
2858
- gt(ut()), t = mo({ sections: wn, store: ra, view: { suspend: ca, resume: pa } });
2885
+ mt(ht()), t = vo({ sections: kn, store: da, view: { suspend: fa, resume: ga } });
2859
2886
  };
2860
2887
  document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", e) : e(), window.Twiddle = {
2861
2888
  open: () => t && t.open(),
2862
2889
  close: () => t && t.close(),
2863
2890
  toggle: () => t && t.toggle(),
2864
- reset: () => yn(),
2865
- undo: () => kn(),
2866
- redo: () => Sn(),
2891
+ reset: () => $n(),
2892
+ undo: () => En(),
2893
+ redo: () => Cn(),
2867
2894
  pick: () => t && t.pick(),
2868
2895
  prompt: () => t ? t.prompt() : "",
2869
- getState: ut
2896
+ getState: ht
2870
2897
  };
2871
2898
  }
2872
- const wo = window.Twiddle;
2899
+ const So = window.Twiddle;
2873
2900
  export {
2874
- wo as Twiddle
2901
+ So as Twiddle
2875
2902
  };