@monoes/monomindcli 2.14.1 → 2.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. package/.claude/helpers/control-start.cjs +10 -13
  2. package/.claude/skills/monodesign/scripts/context.mjs +4 -4
  3. package/.claude/skills/monodesign/scripts/critique-storage.mjs +1 -1
  4. package/.claude/skills/monodesign/scripts/detect-csp.mjs +1 -6
  5. package/.claude/skills/monodesign/scripts/detector/browser/injected/index.mjs +16 -18
  6. package/.claude/skills/monodesign/scripts/detector/cli/main.mjs +3 -3
  7. package/.claude/skills/monodesign/scripts/detector/detect-antipatterns-browser.js +67 -47
  8. package/.claude/skills/monodesign/scripts/detector/engines/regex/detect-text.mjs +6 -6
  9. package/.claude/skills/monodesign/scripts/detector/engines/static-html/css-cascade.mjs +6 -5
  10. package/.claude/skills/monodesign/scripts/detector/engines/static-html/detect-html.mjs +6 -6
  11. package/.claude/skills/monodesign/scripts/detector/fix/index.mjs +3 -3
  12. package/.claude/skills/monodesign/scripts/detector/node/file-system.mjs +1 -1
  13. package/.claude/skills/monodesign/scripts/detector/registry/antipatterns.mjs +1 -1
  14. package/.claude/skills/monodesign/scripts/detector/rules/checks.mjs +24 -25
  15. package/.claude/skills/monodesign/scripts/detector/shared/color.mjs +2 -2
  16. package/.claude/skills/monodesign/scripts/detector/shared/constants.mjs +1 -1
  17. package/.claude/skills/monodesign/scripts/detector/shared/inline-ignores.mjs +2 -2
  18. package/.claude/skills/monodesign/scripts/hook-admin.mjs +6 -6
  19. package/.claude/skills/monodesign/scripts/hook-before-edit.mjs +4 -4
  20. package/.claude/skills/monodesign/scripts/hook-lib.mjs +20 -11
  21. package/.claude/skills/monodesign/scripts/hook.mjs +1 -1
  22. package/.claude/skills/monodesign/scripts/lib/design-parser.mjs +9 -42
  23. package/.claude/skills/monodesign/scripts/lib/is-generated.mjs +1 -1
  24. package/.claude/skills/monodesign/scripts/lib/monodesign-config.mjs +5 -5
  25. package/.claude/skills/monodesign/scripts/lib/monodesign-paths.mjs +1 -1
  26. package/.claude/skills/monodesign/scripts/live/event-validation.mjs +13 -13
  27. package/.claude/skills/monodesign/scripts/live/manual-apply.mjs +4 -4
  28. package/.claude/skills/monodesign/scripts/live/manual-edits-buffer.mjs +1 -1
  29. package/.claude/skills/monodesign/scripts/live/session-store.mjs +5 -5
  30. package/.claude/skills/monodesign/scripts/live/svelte-component.mjs +13 -13
  31. package/.claude/skills/monodesign/scripts/live/sveltekit-adapter.mjs +4 -4
  32. package/.claude/skills/monodesign/scripts/live/ui-core.mjs +1 -1
  33. package/.claude/skills/monodesign/scripts/live-accept.mjs +24 -24
  34. package/.claude/skills/monodesign/scripts/live-browser-dom.js +8 -7
  35. package/.claude/skills/monodesign/scripts/live-browser-session.js +8 -7
  36. package/.claude/skills/monodesign/scripts/live-browser.js +405 -432
  37. package/.claude/skills/monodesign/scripts/live-commit-manual-edits.mjs +6 -6
  38. package/.claude/skills/monodesign/scripts/live-copy-edit-agent.mjs +2 -2
  39. package/.claude/skills/monodesign/scripts/live-discard-manual-edits.mjs +1 -1
  40. package/.claude/skills/monodesign/scripts/live-inject.mjs +7 -7
  41. package/.claude/skills/monodesign/scripts/live-insert.mjs +11 -11
  42. package/.claude/skills/monodesign/scripts/live-manual-edit-evidence.mjs +4 -4
  43. package/.claude/skills/monodesign/scripts/live-poll.mjs +5 -5
  44. package/.claude/skills/monodesign/scripts/live-server.mjs +10 -10
  45. package/.claude/skills/monodesign/scripts/live-wrap.mjs +31 -41
  46. package/.claude/skills/monodesign/scripts/live.mjs +5 -5
  47. package/.claude/skills/monodesign/scripts/palette.mjs +3 -1
  48. package/.claude/skills/monodesign/scripts/pin.mjs +1 -1
  49. package/dist/src/commands/doc-filters.d.ts.map +1 -1
  50. package/dist/src/commands/doc-filters.js +6 -0
  51. package/dist/src/commands/doc-filters.js.map +1 -1
  52. package/dist/src/commands/doc-library.d.ts +2 -1
  53. package/dist/src/commands/doc-library.d.ts.map +1 -1
  54. package/dist/src/commands/doc-library.js +66 -2
  55. package/dist/src/commands/doc-library.js.map +1 -1
  56. package/dist/src/commands/doc.d.ts.map +1 -1
  57. package/dist/src/commands/doc.js +2 -0
  58. package/dist/src/commands/doc.js.map +1 -1
  59. package/dist/src/commands/org.d.ts.map +1 -1
  60. package/dist/src/commands/org.js +42 -4
  61. package/dist/src/commands/org.js.map +1 -1
  62. package/dist/src/commands/ui.d.ts.map +1 -1
  63. package/dist/src/commands/ui.js +60 -0
  64. package/dist/src/commands/ui.js.map +1 -1
  65. package/dist/src/knowledge/capture-envelope.d.ts +5 -0
  66. package/dist/src/knowledge/capture-envelope.d.ts.map +1 -1
  67. package/dist/src/knowledge/capture-envelope.js +2 -0
  68. package/dist/src/knowledge/capture-envelope.js.map +1 -1
  69. package/dist/src/knowledge/document-chunking.d.ts +42 -0
  70. package/dist/src/knowledge/document-chunking.d.ts.map +1 -0
  71. package/dist/src/knowledge/document-chunking.js +288 -0
  72. package/dist/src/knowledge/document-chunking.js.map +1 -0
  73. package/dist/src/knowledge/document-index.d.ts +124 -0
  74. package/dist/src/knowledge/document-index.d.ts.map +1 -0
  75. package/dist/src/knowledge/document-index.js +314 -0
  76. package/dist/src/knowledge/document-index.js.map +1 -0
  77. package/dist/src/knowledge/document-ingest.d.ts +23 -0
  78. package/dist/src/knowledge/document-ingest.d.ts.map +1 -0
  79. package/dist/src/knowledge/document-ingest.js +368 -0
  80. package/dist/src/knowledge/document-ingest.js.map +1 -0
  81. package/dist/src/knowledge/document-pipeline.d.ts +26 -208
  82. package/dist/src/knowledge/document-pipeline.d.ts.map +1 -1
  83. package/dist/src/knowledge/document-pipeline.js +25 -1104
  84. package/dist/src/knowledge/document-pipeline.js.map +1 -1
  85. package/dist/src/knowledge/document-search.d.ts +27 -0
  86. package/dist/src/knowledge/document-search.d.ts.map +1 -0
  87. package/dist/src/knowledge/document-search.js +138 -0
  88. package/dist/src/knowledge/document-search.js.map +1 -0
  89. package/dist/src/knowledge/document-store.d.ts +28 -0
  90. package/dist/src/knowledge/document-store.d.ts.map +1 -0
  91. package/dist/src/knowledge/document-store.js +61 -0
  92. package/dist/src/knowledge/document-store.js.map +1 -0
  93. package/dist/src/knowledge/document-types.d.ts +103 -0
  94. package/dist/src/knowledge/document-types.d.ts.map +1 -0
  95. package/dist/src/knowledge/document-types.js +12 -0
  96. package/dist/src/knowledge/document-types.js.map +1 -0
  97. package/dist/src/knowledge/highlights.d.ts +168 -0
  98. package/dist/src/knowledge/highlights.d.ts.map +1 -0
  99. package/dist/src/knowledge/highlights.js +311 -0
  100. package/dist/src/knowledge/highlights.js.map +1 -0
  101. package/dist/src/knowledge/lookup.d.ts +80 -0
  102. package/dist/src/knowledge/lookup.d.ts.map +1 -0
  103. package/dist/src/knowledge/lookup.js +156 -0
  104. package/dist/src/knowledge/lookup.js.map +1 -0
  105. package/dist/src/knowledge/okf-bundle.d.ts +19 -0
  106. package/dist/src/knowledge/okf-bundle.d.ts.map +1 -0
  107. package/dist/src/knowledge/okf-bundle.js +106 -0
  108. package/dist/src/knowledge/okf-bundle.js.map +1 -0
  109. package/dist/src/knowledge/profile-store.d.ts +134 -0
  110. package/dist/src/knowledge/profile-store.d.ts.map +1 -0
  111. package/dist/src/knowledge/profile-store.js +237 -0
  112. package/dist/src/knowledge/profile-store.js.map +1 -0
  113. package/dist/src/orgrt/agent-runner.d.ts +4 -0
  114. package/dist/src/orgrt/agent-runner.d.ts.map +1 -1
  115. package/dist/src/orgrt/agent-runner.js +22 -0
  116. package/dist/src/orgrt/agent-runner.js.map +1 -1
  117. package/dist/src/orgrt/antigravity-runner.d.ts.map +1 -1
  118. package/dist/src/orgrt/antigravity-runner.js +2 -1
  119. package/dist/src/orgrt/antigravity-runner.js.map +1 -1
  120. package/dist/src/orgrt/authority-mask.d.ts +32 -0
  121. package/dist/src/orgrt/authority-mask.d.ts.map +1 -0
  122. package/dist/src/orgrt/authority-mask.js +135 -0
  123. package/dist/src/orgrt/authority-mask.js.map +1 -0
  124. package/dist/src/orgrt/codex-runner.d.ts.map +1 -1
  125. package/dist/src/orgrt/codex-runner.js +2 -1
  126. package/dist/src/orgrt/codex-runner.js.map +1 -1
  127. package/dist/src/orgrt/copilot-runner.d.ts.map +1 -1
  128. package/dist/src/orgrt/copilot-runner.js +2 -1
  129. package/dist/src/orgrt/copilot-runner.js.map +1 -1
  130. package/dist/src/orgrt/crush-runner.d.ts.map +1 -1
  131. package/dist/src/orgrt/crush-runner.js +6 -1
  132. package/dist/src/orgrt/crush-runner.js.map +1 -1
  133. package/dist/src/orgrt/daemon.d.ts +4 -0
  134. package/dist/src/orgrt/daemon.d.ts.map +1 -1
  135. package/dist/src/orgrt/daemon.js +13 -2
  136. package/dist/src/orgrt/daemon.js.map +1 -1
  137. package/dist/src/orgrt/decisions.d.ts +9 -0
  138. package/dist/src/orgrt/decisions.d.ts.map +1 -1
  139. package/dist/src/orgrt/decisions.js +32 -5
  140. package/dist/src/orgrt/decisions.js.map +1 -1
  141. package/dist/src/orgrt/file-roots.d.ts +2 -1
  142. package/dist/src/orgrt/file-roots.d.ts.map +1 -1
  143. package/dist/src/orgrt/file-roots.js +7 -3
  144. package/dist/src/orgrt/file-roots.js.map +1 -1
  145. package/dist/src/orgrt/grok-runner.d.ts.map +1 -1
  146. package/dist/src/orgrt/grok-runner.js +2 -1
  147. package/dist/src/orgrt/grok-runner.js.map +1 -1
  148. package/dist/src/orgrt/hermes-runner.d.ts.map +1 -1
  149. package/dist/src/orgrt/hermes-runner.js +2 -1
  150. package/dist/src/orgrt/hermes-runner.js.map +1 -1
  151. package/dist/src/orgrt/inbox.d.ts.map +1 -1
  152. package/dist/src/orgrt/inbox.js +70 -4
  153. package/dist/src/orgrt/inbox.js.map +1 -1
  154. package/dist/src/orgrt/kimicode-runner.d.ts.map +1 -1
  155. package/dist/src/orgrt/kimicode-runner.js +2 -1
  156. package/dist/src/orgrt/kimicode-runner.js.map +1 -1
  157. package/dist/src/orgrt/opencode-runner.d.ts.map +1 -1
  158. package/dist/src/orgrt/opencode-runner.js +3 -2
  159. package/dist/src/orgrt/opencode-runner.js.map +1 -1
  160. package/dist/src/orgrt/pi-rpc-runner.d.ts.map +1 -1
  161. package/dist/src/orgrt/pi-rpc-runner.js +3 -2
  162. package/dist/src/orgrt/pi-rpc-runner.js.map +1 -1
  163. package/dist/src/orgrt/pi-runner.d.ts.map +1 -1
  164. package/dist/src/orgrt/pi-runner.js +2 -1
  165. package/dist/src/orgrt/pi-runner.js.map +1 -1
  166. package/dist/src/orgrt/policy.d.ts.map +1 -1
  167. package/dist/src/orgrt/policy.js +3 -0
  168. package/dist/src/orgrt/policy.js.map +1 -1
  169. package/dist/src/orgrt/qwen-rpc-runner.d.ts.map +1 -1
  170. package/dist/src/orgrt/qwen-rpc-runner.js +3 -2
  171. package/dist/src/orgrt/qwen-rpc-runner.js.map +1 -1
  172. package/dist/src/orgrt/qwen-runner.d.ts.map +1 -1
  173. package/dist/src/orgrt/qwen-runner.js +2 -1
  174. package/dist/src/orgrt/qwen-runner.js.map +1 -1
  175. package/dist/src/orgrt/role-sandbox.d.ts +21 -0
  176. package/dist/src/orgrt/role-sandbox.d.ts.map +1 -1
  177. package/dist/src/orgrt/role-sandbox.js +31 -6
  178. package/dist/src/orgrt/role-sandbox.js.map +1 -1
  179. package/dist/src/orgrt/session.d.ts.map +1 -1
  180. package/dist/src/orgrt/session.js +21 -2
  181. package/dist/src/orgrt/session.js.map +1 -1
  182. package/dist/src/orgrt/task-dag.d.ts +3 -0
  183. package/dist/src/orgrt/task-dag.d.ts.map +1 -1
  184. package/dist/src/orgrt/task-dag.js +1 -0
  185. package/dist/src/orgrt/task-dag.js.map +1 -1
  186. package/dist/src/orgrt/types.d.ts +5 -0
  187. package/dist/src/orgrt/types.d.ts.map +1 -1
  188. package/dist/src/orgrt/types.js +23 -1
  189. package/dist/src/orgrt/types.js.map +1 -1
  190. package/dist/src/ui/dashboard.html +28 -848
  191. package/dist/src/ui/human-auth.mjs +103 -0
  192. package/dist/src/ui/org-hil.mjs +86 -37
  193. package/dist/src/ui/org-runtime.mjs +21 -13
  194. package/dist/src/ui/routes-org.mjs +49 -445
  195. package/dist/src/ui/server.mjs +103 -4
  196. package/dist/tsconfig.tsbuildinfo +1 -1
  197. package/package.json +6 -6
@@ -9,7 +9,8 @@
9
9
  * configure (pick action + go), generating (progressive dots), and cycling
10
10
  * (prev/next + accept/discard). Feels like Spotlight, not a modal.
11
11
  */
12
- (function () {
12
+ (() => {
13
+ // biome-ignore lint/suspicious/noRedundantUseStrict: served to the page as a classic <script> (not an ES module despite package type=module), so this directive is what enables strict mode
13
14
  'use strict';
14
15
  if (typeof window === 'undefined') return;
15
16
 
@@ -57,7 +58,8 @@
57
58
  const Z = { highlight: 100001, bar: 100005, picker: 100007, toast: 100010 };
58
59
  const EASE = 'cubic-bezier(0.22, 1, 0.36, 1)'; // ease-out-quint
59
60
  const PREFIX = 'monodesign-live';
60
- const MONODESIGN_COMMAND = (window.__MONODESIGN_COMMAND_PREFIX__ || '/') + 'monodesign';
61
+ const MONODESIGN_COMMAND = `${window.__MONODESIGN_COMMAND_PREFIX__ || '/'}monodesign`;
62
+ // biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-regression.test.mjs:663
61
63
  const PICK_CURSOR_STYLE_ID = PREFIX + '-pick-cursor-style';
62
64
  const MANUAL_APPLY_STATE_TTL_MS = 15 * 60 * 1000;
63
65
  const sessionState = window.__MONODESIGN_LIVE_SESSION__?.createLiveBrowserSessionState({
@@ -77,7 +79,7 @@
77
79
  ', height 140ms ' + EASE +
78
80
  ', opacity 150ms ease';
79
81
  const TOOLTIP_TRANSITION =
80
- 'top 140ms ' + EASE + ', left 140ms ' + EASE + ', opacity 150ms ease';
82
+ `top 140ms ${EASE}, left 140ms ${EASE}, opacity 150ms ease`;
81
83
 
82
84
  const SKIP_TAGS = new Set([
83
85
  'html', 'head', 'body', 'script', 'style', 'link', 'meta', 'noscript', 'br', 'wbr',
@@ -98,20 +100,20 @@
98
100
 
99
101
  const LIVE_CHROME_MOUNT_CONTRACT = ['root', 'transport', 'state', 'actions'];
100
102
  const LIVE_UI_SURFACES = [
101
- { key: 'global-bottom-bar', ids: [PREFIX + '-global-bar', PREFIX + '-global-bar-brand', PREFIX + '-pick-toggle', PREFIX + '-insert-toggle', PREFIX + '-detect-toggle', PREFIX + '-detect-badge', PREFIX + '-design-toggle', PREFIX + '-page-chat', PREFIX + '-page-chat-input', PREFIX + '-page-chat-voice'] },
102
- { key: 'pending-copy-edit-dock', ids: [PREFIX + '-pending-dock'] },
103
- { key: 'element-selection-chrome', ids: [PREFIX + '-highlight', PREFIX + '-tooltip', PREFIX + '-bar', PREFIX + '-selection-pill', PREFIX + '-input', PREFIX + '-configure-voice', PREFIX + '-configure-bar-tooltip'] },
104
- { key: 'action-picker', ids: [PREFIX + '-picker'] },
105
- { key: 'edit-chrome', ids: [PREFIX + '-edit-badge'] },
106
- { key: 'generating-row', ids: [PREFIX + '-bar', PREFIX + '-shader'] },
107
- { key: 'variant-cycling-row', ids: [PREFIX + '-bar', PREFIX + '-params-panel'] },
108
- { key: 'variant-params-panel', ids: [PREFIX + '-params-panel'] },
109
- { key: 'saving-confirmed-rows', ids: [PREFIX + '-bar'] },
110
- { key: 'insert-mode-chrome', ids: [PREFIX + '-insert-line', PREFIX + '-insert-placeholder', PREFIX + '-placeholder-resize', PREFIX + '-insert-input', PREFIX + '-insert-voice', PREFIX + '-insert-create', PREFIX + '-insert-create-tooltip'] },
111
- { key: 'annotation-chrome', ids: [PREFIX + '-annot', PREFIX + '-annot-svg', PREFIX + '-annot-pins', PREFIX + '-annot-clear'] },
112
- { key: 'design-system-panel', ids: [PREFIX + '-design-host'] },
113
- { key: 'toasts-and-errors', ids: [PREFIX + '-toast'] },
114
- { key: 'css-isolation-boundary', ids: [PREFIX + '-root'] },
103
+ { key: 'global-bottom-bar', ids: [`${PREFIX}-global-bar`, `${PREFIX}-global-bar-brand`, `${PREFIX}-pick-toggle`, `${PREFIX}-insert-toggle`, `${PREFIX}-detect-toggle`, `${PREFIX}-detect-badge`, `${PREFIX}-design-toggle`, `${PREFIX}-page-chat`, `${PREFIX}-page-chat-input`, `${PREFIX}-page-chat-voice`] },
104
+ { key: 'pending-copy-edit-dock', ids: [`${PREFIX}-pending-dock`] },
105
+ { key: 'element-selection-chrome', ids: [`${PREFIX}-highlight`, `${PREFIX}-tooltip`, `${PREFIX}-bar`, `${PREFIX}-selection-pill`, `${PREFIX}-input`, `${PREFIX}-configure-voice`, `${PREFIX}-configure-bar-tooltip`] },
106
+ { key: 'action-picker', ids: [`${PREFIX}-picker`] },
107
+ { key: 'edit-chrome', ids: [`${PREFIX}-edit-badge`] },
108
+ { key: 'generating-row', ids: [`${PREFIX}-bar`, `${PREFIX}-shader`] },
109
+ { key: 'variant-cycling-row', ids: [`${PREFIX}-bar`, `${PREFIX}-params-panel`] },
110
+ { key: 'variant-params-panel', ids: [`${PREFIX}-params-panel`] },
111
+ { key: 'saving-confirmed-rows', ids: [`${PREFIX}-bar`] },
112
+ { key: 'insert-mode-chrome', ids: [`${PREFIX}-insert-line`, `${PREFIX}-insert-placeholder`, `${PREFIX}-placeholder-resize`, `${PREFIX}-insert-input`, `${PREFIX}-insert-voice`, `${PREFIX}-insert-create`, `${PREFIX}-insert-create-tooltip`] },
113
+ { key: 'annotation-chrome', ids: [`${PREFIX}-annot`, `${PREFIX}-annot-svg`, `${PREFIX}-annot-pins`, `${PREFIX}-annot-clear`] },
114
+ { key: 'design-system-panel', ids: [`${PREFIX}-design-host`] },
115
+ { key: 'toasts-and-errors', ids: [`${PREFIX}-toast`] },
116
+ { key: 'css-isolation-boundary', ids: [`${PREFIX}-root`] },
115
117
  ];
116
118
  const LIVE_UI_COMPONENT_IDS = [...new Set(LIVE_UI_SURFACES.flatMap((surface) => surface.ids))];
117
119
 
@@ -218,7 +220,6 @@
218
220
  rectIsUsableAnchor,
219
221
  makeFrozenAnchor,
220
222
  id8,
221
- cssId,
222
223
  liveUiRoot,
223
224
  uiAppend,
224
225
  uiAppendStyle,
@@ -264,10 +265,10 @@
264
265
 
265
266
  function initHighlight() {
266
267
  highlightEl = document.createElement('div');
267
- highlightEl.id = PREFIX + '-highlight';
268
+ highlightEl.id = `${PREFIX}-highlight`;
268
269
  Object.assign(highlightEl.style, {
269
270
  position: 'fixed', top: '0', left: '0', width: '0', height: '0',
270
- border: '2px solid ' + C.brand, borderRadius: '3px',
271
+ border: `2px solid ${C.brand}`, borderRadius: '3px',
271
272
  pointerEvents: 'none', zIndex: Z.highlight, boxSizing: 'border-box',
272
273
  transition: HIGHLIGHT_TRANSITION,
273
274
  display: 'none', opacity: '0',
@@ -275,7 +276,7 @@
275
276
  uiAppend(highlightEl);
276
277
 
277
278
  tooltipEl = document.createElement('div');
278
- tooltipEl.id = PREFIX + '-tooltip';
279
+ tooltipEl.id = `${PREFIX}-tooltip`;
279
280
  Object.assign(tooltipEl.style, {
280
281
  position: 'fixed',
281
282
  background: C.ink, color: C.white,
@@ -304,8 +305,8 @@
304
305
  if (!el || !highlightEl) return;
305
306
  if (el.hasAttribute?.('data-monodesign-insert-placeholder')) return;
306
307
  const r = el.getBoundingClientRect();
307
- const top = (r.top - 2) + 'px', left = (r.left - 2) + 'px';
308
- const width = (r.width + 4) + 'px', height = (r.height + 4) + 'px';
308
+ const top = `${r.top - 2}px`, left = `${r.left - 2}px`;
309
+ const width = `${r.width + 4}px`, height = `${r.height + 4}px`;
309
310
  const showTagTooltip = shouldShowHighlightTagTooltip();
310
311
 
311
312
  const hiWasHidden = highlightEl.style.display === 'none' || highlightEl.style.opacity === '0';
@@ -326,8 +327,8 @@
326
327
  }
327
328
 
328
329
  const tipTop = r.top - 20;
329
- const tipY = (tipTop < 4 ? r.bottom + 4 : tipTop) + 'px';
330
- const tipX = Math.max(4, r.left) + 'px';
330
+ const tipY = `${tipTop < 4 ? r.bottom + 4 : tipTop}px`;
331
+ const tipX = `${Math.max(4, r.left)}px`;
331
332
  tooltipEl.textContent = desc(el);
332
333
  if (hiWasHidden) {
333
334
  tooltipEl.style.transition = 'none';
@@ -361,7 +362,7 @@
361
362
  let annotSvgEl = null;
362
363
  let annotPinsEl = null;
363
364
  let annotClearChipEl = null;
364
- let annotState = { comments: [], strokes: [] };
365
+ const annotState = { comments: [], strokes: [] };
365
366
  let annotActive = false;
366
367
  // `annotPointer` is either:
367
368
  // { kind: 'new', x0, y0, moved, strokeEl, strokePoints } creating a stroke/pin
@@ -374,7 +375,7 @@
374
375
 
375
376
  function initAnnotOverlay() {
376
377
  annotOverlayEl = document.createElement('div');
377
- annotOverlayEl.id = PREFIX + '-annot';
378
+ annotOverlayEl.id = `${PREFIX}-annot`;
378
379
  Object.assign(annotOverlayEl.style, {
379
380
  position: 'fixed', top: '0', left: '0', width: '0', height: '0',
380
381
  pointerEvents: 'auto', zIndex: Z.highlight + 2,
@@ -383,7 +384,7 @@
383
384
  });
384
385
 
385
386
  annotSvgEl = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
386
- annotSvgEl.id = PREFIX + '-annot-svg';
387
+ annotSvgEl.id = `${PREFIX}-annot-svg`;
387
388
  Object.assign(annotSvgEl.style, {
388
389
  position: 'absolute', top: '0', left: '0',
389
390
  width: '100%', height: '100%',
@@ -394,7 +395,7 @@
394
395
  annotOverlayEl.appendChild(annotSvgEl);
395
396
 
396
397
  annotPinsEl = document.createElement('div');
397
- annotPinsEl.id = PREFIX + '-annot-pins';
398
+ annotPinsEl.id = `${PREFIX}-annot-pins`;
398
399
  Object.assign(annotPinsEl.style, {
399
400
  position: 'absolute', inset: '0',
400
401
  pointerEvents: 'none',
@@ -402,7 +403,7 @@
402
403
  annotOverlayEl.appendChild(annotPinsEl);
403
404
 
404
405
  annotClearChipEl = document.createElement('div');
405
- annotClearChipEl.id = PREFIX + '-annot-clear';
406
+ annotClearChipEl.id = `${PREFIX}-annot-clear`;
406
407
  annotClearChipEl.dataset.annotClear = 'true';
407
408
  annotClearChipEl.textContent = 'Clear';
408
409
  Object.assign(annotClearChipEl.style, {
@@ -418,7 +419,7 @@
418
419
  annotOverlayEl.appendChild(annotClearChipEl);
419
420
 
420
421
  placeholderResizeLayerEl = document.createElement('div');
421
- placeholderResizeLayerEl.id = PREFIX + '-placeholder-resize';
422
+ placeholderResizeLayerEl.id = `${PREFIX}-placeholder-resize`;
422
423
  Object.assign(placeholderResizeLayerEl.style, {
423
424
  position: 'absolute',
424
425
  inset: '0',
@@ -468,10 +469,10 @@
468
469
  if (!annotOverlayEl || !el) return;
469
470
  const r = el.getBoundingClientRect();
470
471
  Object.assign(annotOverlayEl.style, {
471
- top: r.top + 'px', left: r.left + 'px',
472
- width: r.width + 'px', height: r.height + 'px',
472
+ top: `${r.top}px`, left: `${r.left}px`,
473
+ width: `${r.width}px`, height: `${r.height}px`,
473
474
  });
474
- annotSvgEl.setAttribute('viewBox', '0 0 ' + r.width + ' ' + r.height);
475
+ annotSvgEl.setAttribute('viewBox', `0 0 ${r.width} ${r.height}`);
475
476
  syncPlaceholderResizeHandles();
476
477
  }
477
478
 
@@ -658,9 +659,9 @@
658
659
 
659
660
  function pointsToPath(points) {
660
661
  if (!points || points.length === 0) return '';
661
- let d = 'M' + points[0][0].toFixed(1) + ' ' + points[0][1].toFixed(1);
662
+ let d = `M${points[0][0].toFixed(1)} ${points[0][1].toFixed(1)}`;
662
663
  for (let i = 1; i < points.length; i++) {
663
- d += ' L' + points[i][0].toFixed(1) + ' ' + points[i][1].toFixed(1);
664
+ d += ` L${points[i][0].toFixed(1)} ${points[i][1].toFixed(1)}`;
664
665
  }
665
666
  return d;
666
667
  }
@@ -722,7 +723,7 @@
722
723
  if (interactive) wrap.dataset.annotPin = String(idx);
723
724
  Object.assign(wrap.style, {
724
725
  position: 'absolute',
725
- left: (comment.x - 7) + 'px', top: (comment.y - 7) + 'px',
726
+ left: `${comment.x - 7}px`, top: `${comment.y - 7}px`,
726
727
  pointerEvents: interactive ? 'auto' : 'none',
727
728
  display: 'flex', alignItems: 'flex-start', gap: '6px',
728
729
  cursor: interactive ? 'grab' : 'default',
@@ -731,7 +732,7 @@
731
732
  const dot = document.createElement('div');
732
733
  Object.assign(dot.style, {
733
734
  width: '14px', height: '14px', borderRadius: '50%',
734
- background: C.brand, border: '2px solid ' + C.white,
735
+ background: C.brand, border: `2px solid ${C.white}`,
735
736
  boxShadow: '0 1px 3px rgba(0,0,0,0.25)',
736
737
  flexShrink: '0',
737
738
  });
@@ -754,7 +755,7 @@
754
755
  }
755
756
 
756
757
  function beginEditPin(idx) {
757
- const wrapEl = annotPinsEl.querySelector('[data-annot-pin="' + idx + '"]');
758
+ const wrapEl = annotPinsEl.querySelector(`[data-annot-pin="${idx}"]`);
758
759
  if (!wrapEl) return;
759
760
  // Strip any existing bubble (but keep the dot)
760
761
  wrapEl.querySelectorAll('div:not(:first-child)').forEach(n => n.remove());
@@ -765,7 +766,7 @@
765
766
  background: C.ink, color: C.white,
766
767
  fontFamily: FONT, fontSize: '12px', lineHeight: '1.4',
767
768
  padding: '4px 8px', borderRadius: '3px',
768
- border: '1px solid ' + C.brand,
769
+ border: `1px solid ${C.brand}`,
769
770
  outline: 'none', marginTop: '-2px',
770
771
  width: '220px', pointerEvents: 'auto',
771
772
  });
@@ -834,12 +835,12 @@
834
835
  const wrap = document.createElement('div');
835
836
  Object.assign(wrap.style, {
836
837
  position: 'absolute', top: '0', left: '0',
837
- width: rect.width + 'px', height: rect.height + 'px',
838
+ width: `${rect.width}px`, height: `${rect.height}px`,
838
839
  pointerEvents: 'none', overflow: 'visible',
839
840
  });
840
841
  if (strokes.length > 0) {
841
842
  const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
842
- svg.setAttribute('viewBox', '0 0 ' + rect.width + ' ' + rect.height);
843
+ svg.setAttribute('viewBox', `0 0 ${rect.width} ${rect.height}`);
843
844
  Object.assign(svg.style, {
844
845
  position: 'absolute', top: '0', left: '0',
845
846
  width: '100%', height: '100%', overflow: 'visible',
@@ -868,7 +869,7 @@
868
869
  //
869
870
 
870
871
  function stripManualEditRuntimeState(root) {
871
- if (!root || root.nodeType !== 1) return;
872
+ if (root?.nodeType !== 1) return;
872
873
  unwrapMixedContentTextNodes(root);
873
874
  const nodes = [root, ...root.querySelectorAll('[data-monodesign-editable], [data-monodesign-original-text], [data-monodesign-text-wrap]')];
874
875
  for (const node of nodes) {
@@ -891,7 +892,7 @@
891
892
  }
892
893
 
893
894
  function sanitizedContextOuterHTML(el, maxLength) {
894
- if (!el || !el.cloneNode) return '';
895
+ if (!el?.cloneNode) return '';
895
896
  const clone = el.cloneNode(true);
896
897
  stripManualEditRuntimeState(clone);
897
898
  return clone.outerHTML ? clone.outerHTML.slice(0, maxLength) : '';
@@ -932,8 +933,8 @@
932
933
  cssCustomProperties: props,
933
934
  parentContext: el.parentElement
934
935
  ? '<' + el.parentElement.tagName.toLowerCase()
935
- + (el.parentElement.id ? ' id="' + el.parentElement.id + '"' : '')
936
- + (el.parentElement.className ? ' class="' + el.parentElement.className + '"' : '')
936
+ + (el.parentElement.id ? ` id="${el.parentElement.id}"` : '')
937
+ + (el.parentElement.className ? ` class="${el.parentElement.className}"` : '')
937
938
  + '>'
938
939
  : null,
939
940
  boundingRect: { width: Math.round(r.width), height: Math.round(r.height) },
@@ -967,7 +968,7 @@
967
968
  }
968
969
 
969
970
  function isUsefulManualEditContext(candidate, leafEl, editedTexts) {
970
- if (!candidate || !candidate.contains(leafEl)) return false;
971
+ if (!candidate?.contains(leafEl)) return false;
971
972
  if (!candidate.id && candidate.classList.length === 0 && candidate.children.length < 2) return false;
972
973
  return collectManualContextPieces(candidate, editedTexts).length > 0;
973
974
  }
@@ -1026,16 +1027,16 @@
1026
1027
  function initBar() {
1027
1028
  BP = barPaletteForTheme(detectPageTheme());
1028
1029
  barEl = document.createElement('div');
1029
- barEl.id = PREFIX + '-bar';
1030
+ barEl.id = `${PREFIX}-bar`;
1030
1031
  Object.assign(barEl.style, {
1031
1032
  position: 'fixed', zIndex: Z.bar,
1032
1033
  display: 'none', opacity: '0',
1033
1034
  transform: 'translateY(6px)',
1034
1035
  background: BP.surface,
1035
- border: '1px solid ' + BP.border,
1036
+ border: `1px solid ${BP.border}`,
1036
1037
  borderRadius: '8px',
1037
1038
  boxShadow: BP.shadow,
1038
- transition: 'box-shadow 0.2s ease, opacity 0.25s ' + EASE + ', transform 0.3s ' + EASE,
1039
+ transition: `box-shadow 0.2s ease, opacity 0.25s ${EASE}, transform 0.3s ${EASE}`,
1039
1040
  fontFamily: FONT, fontSize: '13px', color: BP.text,
1040
1041
  padding: '5px',
1041
1042
  maxWidth: '560px', minWidth: '340px',
@@ -1061,7 +1062,7 @@
1061
1062
  : GLOBAL_BAR_RESERVE;
1062
1063
  const top = window.innerHeight - barH - reserve;
1063
1064
  const left = Math.max(GAP, (window.innerWidth - barW) / 2);
1064
- Object.assign(barEl.style, { top: top + 'px', left: left + 'px' });
1065
+ Object.assign(barEl.style, { top: `${top}px`, left: `${left}px` });
1065
1066
  return;
1066
1067
  }
1067
1068
 
@@ -1086,7 +1087,7 @@
1086
1087
  let left = r.left + (r.width - barW) / 2;
1087
1088
  if (left < GAP) left = GAP;
1088
1089
  if (left + barW > window.innerWidth - GAP) left = window.innerWidth - barW - GAP;
1089
- Object.assign(barEl.style, { top: top + 'px', left: left + 'px' });
1090
+ Object.assign(barEl.style, { top: `${top}px`, left: `${left}px` });
1090
1091
  }
1091
1092
 
1092
1093
  function showBar(mode) {
@@ -1183,13 +1184,13 @@
1183
1184
  barEl.style.padding = '5px';
1184
1185
  barEl.style.background = BP.surface;
1185
1186
  barEl.style.overflow = '';
1186
- barEl.style.border = '1px solid ' + BP.border;
1187
+ barEl.style.border = `1px solid ${BP.border}`;
1187
1188
  barEl.style.borderColor = BP.border;
1188
1189
  barEl.style.boxShadow = BP.shadow;
1189
1190
  }
1190
1191
 
1191
1192
  function syncConfigureInputChrome() {
1192
- const input = uiGetById(PREFIX + '-input') || uiGetById(PREFIX + '-insert-input');
1193
+ const input = uiGetById(`${PREFIX}-input`) || uiGetById(`${PREFIX}-insert-input`);
1193
1194
  const surface = barEl?.dataset.configureSurface === 'true' ? barEl : null;
1194
1195
  if (!surface || !input) return;
1195
1196
  const focused = activeElementDeep() === input;
@@ -1231,6 +1232,7 @@
1231
1232
  };
1232
1233
  }
1233
1234
 
1235
+ // biome-ignore-start lint/style/useTemplate: padding source pinned by tests/live-browser-regression.test.mjs:778 (a comment inside the body would overflow its {0,120} window)
1234
1236
  function configureInputShellStyle() {
1235
1237
  return {
1236
1238
  display: 'flex', alignItems: 'center', gap: '6px',
@@ -1238,6 +1240,7 @@
1238
1240
  padding: '0 6px 0 ' + CONFIGURE_BAR_INSET,
1239
1241
  };
1240
1242
  }
1243
+ // biome-ignore-end lint/style/useTemplate: see above
1241
1244
 
1242
1245
  function configureSelectionPillStyle(extra = {}) {
1243
1246
  const P = configureBarPalette();
@@ -1260,12 +1263,13 @@
1260
1263
  };
1261
1264
  }
1262
1265
 
1266
+ // biome-ignore lint/correctness/noUnusedVariables: kept as the configure-row chip style contract pinned by tests/live-browser-regression.test.mjs
1263
1267
  function configureModifierPillStyle(extra = {}) {
1264
1268
  const P = configureBarPalette();
1265
1269
  return {
1266
1270
  display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
1267
1271
  gap: '2px', height: 'auto', minHeight: CONFIGURE_ROW_TRACK_H,
1268
- padding: CONFIGURE_PILL_PAD_Y + ' 8px', flexShrink: '0',
1272
+ padding: `${CONFIGURE_PILL_PAD_Y} 8px`, flexShrink: '0',
1269
1273
  boxSizing: 'border-box',
1270
1274
  border: '1px solid transparent',
1271
1275
  borderRadius: CONFIGURE_PILL_RADIUS,
@@ -1307,21 +1311,6 @@
1307
1311
  });
1308
1312
  }
1309
1313
 
1310
- function bindConfigureModifierPillHover(btn, controlsLocked) {
1311
- btn.addEventListener('mouseenter', () => {
1312
- if (controlsLocked) return;
1313
- const P = configureBarPalette();
1314
- btn.style.color = P.text;
1315
- btn.style.background = P.toggleActive;
1316
- });
1317
- btn.addEventListener('mouseleave', () => {
1318
- if (controlsLocked) return;
1319
- const P = configureBarPalette();
1320
- btn.style.color = P.textDim;
1321
- btn.style.background = 'transparent';
1322
- });
1323
- }
1324
-
1325
1314
  let configureBarTooltipEl = null;
1326
1315
 
1327
1316
  function ensureConfigureBarTooltip() {
@@ -1336,7 +1325,7 @@
1336
1325
  padding: '6px 9px',
1337
1326
  borderRadius: '7px',
1338
1327
  background: P.chatSurface,
1339
- border: '1px solid ' + P.hairline,
1328
+ border: `1px solid ${P.hairline}`,
1340
1329
  boxShadow: P.shadow,
1341
1330
  color: P.text,
1342
1331
  fontFamily: FONT,
@@ -1347,7 +1336,7 @@
1347
1336
  whiteSpace: 'normal',
1348
1337
  wordBreak: 'break-word',
1349
1338
  });
1350
- configureBarTooltipEl.id = PREFIX + '-configure-bar-tooltip';
1339
+ configureBarTooltipEl.id = `${PREFIX}-configure-bar-tooltip`;
1351
1340
  uiAppend(configureBarTooltipEl);
1352
1341
  return configureBarTooltipEl;
1353
1342
  }
@@ -1364,8 +1353,8 @@
1364
1353
  const tipH = tip.offsetHeight;
1365
1354
  const left = Math.max(8, Math.min(window.innerWidth - tipW - 8, r.left + r.width / 2 - tipW / 2));
1366
1355
  const top = Math.max(8, r.top - tipH - 8);
1367
- tip.style.left = left + 'px';
1368
- tip.style.top = top + 'px';
1356
+ tip.style.left = `${left}px`;
1357
+ tip.style.top = `${top}px`;
1369
1358
  }
1370
1359
 
1371
1360
  function hideConfigureBarTooltip() {
@@ -1386,8 +1375,8 @@
1386
1375
  let node = el;
1387
1376
  while (node && node.nodeType === 1 && node !== document.body) {
1388
1377
  let part = node.tagName.toLowerCase();
1389
- if (node.id) part += '#' + node.id;
1390
- else if (node.classList?.length) part += '.' + [...node.classList].slice(0, 2).join('.');
1378
+ if (node.id) part += `#${node.id}`;
1379
+ else if (node.classList?.length) part += `.${[...node.classList].slice(0, 2).join('.')}`;
1391
1380
  parts.unshift(part);
1392
1381
  node = node.parentElement;
1393
1382
  if (parts.length >= maxDepth) break;
@@ -1398,7 +1387,7 @@
1398
1387
  function variantCountTooltipText(count) {
1399
1388
  const n = Number(count) || selectedCount;
1400
1389
  const word = n === 1 ? 'variant' : 'variants';
1401
- return 'Click to change \u00b7 ' + n + ' ' + word;
1390
+ return `Click to change \u00b7 ${n} ${word}`;
1402
1391
  }
1403
1392
 
1404
1393
  function removeConfigureSelection() {
@@ -1416,9 +1405,9 @@
1416
1405
  const path = elementPath(targetEl);
1417
1406
  const P = configureBarPalette();
1418
1407
  const pill = el('button', configureSelectionPillStyle({ minWidth: '32px' }));
1419
- pill.id = PREFIX + '-selection-pill';
1408
+ pill.id = `${PREFIX}-selection-pill`;
1420
1409
  pill.type = 'button';
1421
- pill.setAttribute('aria-label', 'Selected element: ' + tag);
1410
+ pill.setAttribute('aria-label', `Selected element: ${tag}`);
1422
1411
  pill.disabled = controlsLocked;
1423
1412
  pill.style.cursor = controlsLocked ? 'not-allowed' : 'pointer';
1424
1413
  pill.style.opacity = controlsLocked ? '0.58' : '1';
@@ -1451,7 +1440,7 @@
1451
1440
  clearFace.style.opacity = armed ? '1' : '0';
1452
1441
  pill.style.background = armed ? P.toggleActive : 'transparent';
1453
1442
  pill.style.border = CONFIGURE_SELECTION_PILL_BORDER;
1454
- pill.setAttribute('aria-label', armed ? 'Clear selection' : 'Selected element: ' + tag);
1443
+ pill.setAttribute('aria-label', armed ? 'Clear selection' : `Selected element: ${tag}`);
1455
1444
  };
1456
1445
  const arm = () => {
1457
1446
  if (controlsLocked) {
@@ -1523,7 +1512,7 @@
1523
1512
  const count = el('button', configureInlineControlStyle({
1524
1513
  fontFamily: MONO, fontWeight: '600', letterSpacing: '0',
1525
1514
  }));
1526
- count.textContent = '\u00D7' + selectedCount;
1515
+ count.textContent = `\u00D7${selectedCount}`;
1527
1516
  count.disabled = controlsLocked;
1528
1517
  count.style.cursor = controlsLocked ? 'not-allowed' : 'pointer';
1529
1518
  count.style.opacity = controlsLocked ? '0.58' : '1';
@@ -1539,7 +1528,7 @@
1539
1528
  boxSizing: 'border-box',
1540
1529
  width: CONFIGURE_BAR_H, height: '100%', flexShrink: '0',
1541
1530
  padding: '0', margin: '0',
1542
- border: 'none', borderRight: '1px solid ' + BP.hairline,
1531
+ border: 'none', borderRight: `1px solid ${BP.hairline}`,
1543
1532
  borderRadius: '0', background: 'transparent',
1544
1533
  color: BP.textDim, cursor: 'pointer',
1545
1534
  transition: 'color 0.12s ease, background 0.12s ease',
@@ -1559,7 +1548,7 @@
1559
1548
  function buildConfigureTrailingCluster(controls, voiceBtn, submitBtn) {
1560
1549
  const cluster = el('div', {
1561
1550
  display: 'inline-flex', alignItems: 'stretch', flexShrink: '0',
1562
- height: '100%', borderLeft: '1px solid ' + BP.hairline,
1551
+ height: '100%', borderLeft: `1px solid ${BP.hairline}`,
1563
1552
  });
1564
1553
  if (controls.length) {
1565
1554
  const controlsWrap = el('div', {
@@ -1569,7 +1558,7 @@
1569
1558
  controls.forEach((control) => controlsWrap.appendChild(control));
1570
1559
  cluster.appendChild(controlsWrap);
1571
1560
  }
1572
- voiceBtn.style.borderLeft = '1px solid ' + BP.hairline;
1561
+ voiceBtn.style.borderLeft = `1px solid ${BP.hairline}`;
1573
1562
  cluster.appendChild(voiceBtn);
1574
1563
  cluster.appendChild(submitBtn);
1575
1564
  return cluster;
@@ -1580,7 +1569,7 @@
1580
1569
  display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
1581
1570
  boxSizing: 'border-box', width: CONFIGURE_BAR_H, height: CONFIGURE_BAR_H,
1582
1571
  padding: '0', flexShrink: '0',
1583
- border: 'none', borderLeft: '1px solid ' + BP.hairline,
1572
+ border: 'none', borderLeft: `1px solid ${BP.hairline}`,
1584
1573
  borderRadius: '0',
1585
1574
  background: BP.accent, color: C.ink,
1586
1575
  cursor: controlsLocked ? 'not-allowed' : 'pointer',
@@ -1622,7 +1611,7 @@
1622
1611
  }
1623
1612
 
1624
1613
  function detectInsertAxis(parent) {
1625
- if (!parent || parent.nodeType !== 1) return 'column';
1614
+ if (parent?.nodeType !== 1) return 'column';
1626
1615
  const st = getComputedStyle(parent);
1627
1616
  return detectInsertAxisFromStyle({
1628
1617
  display: st.display,
@@ -1784,12 +1773,12 @@
1784
1773
  placeholder.style.width = '';
1785
1774
  if (sizing.kind === 'flex') {
1786
1775
  placeholder.style.flex = sizing.flex;
1787
- placeholder.style.minWidth = sizing.minWidth + 'px';
1776
+ placeholder.style.minWidth = `${sizing.minWidth}px`;
1788
1777
  } else if (sizing.kind === 'percent') {
1789
1778
  placeholder.style.width = '100%';
1790
1779
  placeholder.style.maxWidth = '100%';
1791
1780
  } else if (sizing.kind === 'explicit') {
1792
- placeholder.style.width = sizing.width + 'px';
1781
+ placeholder.style.width = `${sizing.width}px`;
1793
1782
  }
1794
1783
  }
1795
1784
 
@@ -1801,7 +1790,7 @@
1801
1790
  placeholder.style.flex = '';
1802
1791
  placeholder.style.minWidth = '';
1803
1792
  placeholder.style.maxWidth = '';
1804
- placeholder.style.width = w + 'px';
1793
+ placeholder.style.width = `${w}px`;
1805
1794
  placeholder.dataset.monodesignPlaceholderWidth = 'explicit';
1806
1795
  }
1807
1796
 
@@ -1863,12 +1852,12 @@
1863
1852
  function ensureInsertLine() {
1864
1853
  if (insertLineEl) return insertLineEl;
1865
1854
  insertLineEl = document.createElement('div');
1866
- insertLineEl.id = PREFIX + '-insert-line';
1855
+ insertLineEl.id = `${PREFIX}-insert-line`;
1867
1856
  Object.assign(insertLineEl.style, {
1868
1857
  position: 'fixed',
1869
1858
  zIndex: String(Z.highlight),
1870
1859
  height: '0',
1871
- borderTop: '2px dotted ' + C.brand,
1860
+ borderTop: `2px dotted ${C.brand}`,
1872
1861
  pointerEvents: 'none',
1873
1862
  display: 'none',
1874
1863
  opacity: '0.9',
@@ -1885,22 +1874,22 @@
1885
1874
  if (coords.axis === 'row') {
1886
1875
  Object.assign(line.style, {
1887
1876
  display: 'block',
1888
- top: coords.top + 'px',
1889
- left: coords.left + 'px',
1877
+ top: `${coords.top}px`,
1878
+ left: `${coords.left}px`,
1890
1879
  width: '0',
1891
- height: coords.height + 'px',
1880
+ height: `${coords.height}px`,
1892
1881
  borderTop: 'none',
1893
- borderLeft: '2px dotted ' + C.brand,
1882
+ borderLeft: `2px dotted ${C.brand}`,
1894
1883
  });
1895
1884
  } else {
1896
1885
  Object.assign(line.style, {
1897
1886
  display: 'block',
1898
- top: coords.top + 'px',
1899
- left: coords.left + 'px',
1900
- width: coords.width + 'px',
1887
+ top: `${coords.top}px`,
1888
+ left: `${coords.left}px`,
1889
+ width: `${coords.width}px`,
1901
1890
  height: '0',
1902
1891
  borderLeft: 'none',
1903
- borderTop: '2px dotted ' + C.brand,
1892
+ borderTop: `2px dotted ${C.brand}`,
1904
1893
  });
1905
1894
  }
1906
1895
  insertHoverAnchor = resolved.anchor;
@@ -1975,7 +1964,7 @@
1975
1964
  if (anchor) return anchor;
1976
1965
  }
1977
1966
  if (currentSessionId && (state === 'GENERATING' || state === 'CYCLING')) {
1978
- const wrapper = document.querySelector('[data-monodesign-variants="' + currentSessionId + '"]');
1967
+ const wrapper = document.querySelector(`[data-monodesign-variants="${currentSessionId}"]`);
1979
1968
  if (wrapper) {
1980
1969
  const variantCount = wrapper.querySelectorAll('[data-monodesign-variant]:not([data-monodesign-variant="original"])').length;
1981
1970
  if (variantCount > 0 && visibleVariant > 0) {
@@ -2034,7 +2023,7 @@
2034
2023
  const tag = (snap.anchorTag || 'div').toLowerCase();
2035
2024
  const cls = (snap.anchorClasses || '').split(/\s+/).filter(Boolean)[0];
2036
2025
  const needle = snap.anchorText || '';
2037
- const sel = cls ? tag + '.' + cls : tag;
2026
+ const sel = cls ? `${tag}.${cls}` : tag;
2038
2027
  const candidates = document.querySelectorAll(sel);
2039
2028
  for (const candidate of candidates) {
2040
2029
  if (own(candidate)) continue;
@@ -2046,14 +2035,14 @@
2046
2035
 
2047
2036
  function isInsertGeneratingSession() {
2048
2037
  if (state !== 'GENERATING' || !currentSessionId) return false;
2049
- const wrapper = document.querySelector('[data-monodesign-variants="' + currentSessionId + '"]');
2038
+ const wrapper = document.querySelector(`[data-monodesign-variants="${currentSessionId}"]`);
2050
2039
  return !!wrapper && wrapper.dataset.monodesignMode === 'insert';
2051
2040
  }
2052
2041
 
2053
2042
  /** Recreate the dotted placeholder if Astro/Vite HMR removed it mid-generation. */
2054
2043
  function ensureInsertPlaceholder() {
2055
2044
  if (!isInsertGeneratingSession()) return placeholderElement;
2056
- const wrapper = document.querySelector('[data-monodesign-variants="' + currentSessionId + '"]');
2045
+ const wrapper = document.querySelector(`[data-monodesign-variants="${currentSessionId}"]`);
2057
2046
  const variantCount = wrapper.querySelectorAll('[data-monodesign-variant]:not([data-monodesign-variant="original"])').length;
2058
2047
  if (variantCount > 0) return placeholderElement;
2059
2048
  if (placeholderElement && document.body.contains(placeholderElement)) return placeholderElement;
@@ -2083,10 +2072,10 @@
2083
2072
  const ph = placeholderElement;
2084
2073
  if (!ph) return;
2085
2074
  materializePlaceholderWidth(ph);
2086
- ph.style.width = width + 'px';
2087
- ph.style.height = height + 'px';
2088
- ph.style.marginLeft = marginLeft ? marginLeft + 'px' : '';
2089
- ph.style.marginTop = marginTop ? marginTop + 'px' : '';
2075
+ ph.style.width = `${width}px`;
2076
+ ph.style.height = `${height}px`;
2077
+ ph.style.marginLeft = marginLeft ? `${marginLeft}px` : '';
2078
+ ph.style.marginTop = marginTop ? `${marginTop}px` : '';
2090
2079
  positionAnnotOverlay(ph);
2091
2080
  positionBar();
2092
2081
  }
@@ -2113,12 +2102,12 @@
2113
2102
  pointerEvents: 'auto',
2114
2103
  cursor: cursorForPlaceholderEdge(spec.edge),
2115
2104
  });
2116
- if (spec.top != null) handle.style.top = spec.top + 'px';
2117
- if (spec.bottom != null) handle.style.bottom = spec.bottom + 'px';
2118
- if (spec.left != null) handle.style.left = spec.left + 'px';
2119
- if (spec.right != null) handle.style.right = spec.right + 'px';
2120
- if (spec.width != null) handle.style.width = spec.width + 'px';
2121
- if (spec.height != null) handle.style.height = spec.height + 'px';
2105
+ if (spec.top != null) handle.style.top = `${spec.top}px`;
2106
+ if (spec.bottom != null) handle.style.bottom = `${spec.bottom}px`;
2107
+ if (spec.left != null) handle.style.left = `${spec.left}px`;
2108
+ if (spec.right != null) handle.style.right = `${spec.right}px`;
2109
+ if (spec.width != null) handle.style.width = `${spec.width}px`;
2110
+ if (spec.height != null) handle.style.height = `${spec.height}px`;
2122
2111
  handle.dataset.monodesignPlaceholderResize = spec.edge;
2123
2112
  handle.setAttribute('aria-label', 'Resize placeholder');
2124
2113
  handle.title = 'Drag to resize';
@@ -2173,13 +2162,14 @@
2173
2162
  anchorFlex: ast.flex,
2174
2163
  });
2175
2164
  const placeholder = document.createElement('div');
2176
- placeholder.id = PREFIX + '-insert-placeholder';
2165
+ placeholder.id = `${PREFIX}-insert-placeholder`;
2177
2166
  placeholder.setAttribute('data-monodesign-insert-placeholder', 'true');
2178
2167
  placeholder.setAttribute('aria-hidden', 'true');
2179
2168
  Object.assign(placeholder.style, {
2180
2169
  boxSizing: 'border-box',
2181
- height: PLACEHOLDER_DEFAULT_HEIGHT + 'px',
2182
- minHeight: PLACEHOLDER_MIN_HEIGHT + 'px',
2170
+ height: `${PLACEHOLDER_DEFAULT_HEIGHT}px`,
2171
+ minHeight: `${PLACEHOLDER_MIN_HEIGHT}px`,
2172
+ // biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-regression.test.mjs:643
2183
2173
  border: '2px dotted ' + BP.accent,
2184
2174
  borderRadius: '0',
2185
2175
  background: 'transparent',
@@ -2204,7 +2194,7 @@
2204
2194
  }
2205
2195
 
2206
2196
  function isInsertCreateEnabled(btn) {
2207
- btn = btn || uiGetById(PREFIX + '-insert-create');
2197
+ btn = btn || uiGetById(`${PREFIX}-insert-create`);
2208
2198
  return !!btn && btn.getAttribute('aria-disabled') !== 'true';
2209
2199
  }
2210
2200
 
@@ -2221,7 +2211,7 @@
2221
2211
  padding: '6px 9px',
2222
2212
  borderRadius: '7px',
2223
2213
  background: BP.chatSurface,
2224
- border: '1px solid ' + BP.hairline,
2214
+ border: `1px solid ${BP.hairline}`,
2225
2215
  boxShadow: BP.shadow,
2226
2216
  color: BP.text,
2227
2217
  fontFamily: FONT,
@@ -2229,7 +2219,7 @@
2229
2219
  fontWeight: '500',
2230
2220
  lineHeight: '1.35',
2231
2221
  });
2232
- insertCreateTooltipEl.id = PREFIX + '-insert-create-tooltip';
2222
+ insertCreateTooltipEl.id = `${PREFIX}-insert-create-tooltip`;
2233
2223
  uiAppend(insertCreateTooltipEl);
2234
2224
  return insertCreateTooltipEl;
2235
2225
  }
@@ -2244,8 +2234,8 @@
2244
2234
  const tipH = tip.offsetHeight;
2245
2235
  const left = Math.max(8, Math.min(window.innerWidth - tipW - 8, r.left + r.width / 2 - tipW / 2));
2246
2236
  const top = Math.max(8, r.top - tipH - 8);
2247
- tip.style.left = left + 'px';
2248
- tip.style.top = top + 'px';
2237
+ tip.style.left = `${left}px`;
2238
+ tip.style.top = `${top}px`;
2249
2239
  }
2250
2240
 
2251
2241
  function hideInsertCreateTooltip() {
@@ -2262,8 +2252,8 @@
2262
2252
  }
2263
2253
 
2264
2254
  function syncInsertCreateButton(btn, input) {
2265
- btn = btn || uiGetById(PREFIX + '-insert-create');
2266
- input = input || uiGetById(PREFIX + '-insert-input');
2255
+ btn = btn || uiGetById(`${PREFIX}-insert-create`);
2256
+ input = input || uiGetById(`${PREFIX}-insert-input`);
2267
2257
  if (!btn || !input) return;
2268
2258
  const gate = insertCreateGateState(input);
2269
2259
  const ok = canCreateInsert(gate);
@@ -2280,7 +2270,7 @@
2280
2270
  } else {
2281
2271
  btn.style.background = 'transparent';
2282
2272
  btn.style.color = BP.textDim;
2283
- btn.style.border = '1px solid ' + BP.hairline;
2273
+ btn.style.border = `1px solid ${BP.hairline}`;
2284
2274
  btn.style.opacity = '0.72';
2285
2275
  btn.style.cursor = 'not-allowed';
2286
2276
  }
@@ -2288,9 +2278,9 @@
2288
2278
 
2289
2279
  /** Stylesheet shared by the replace and insert configure rows. */
2290
2280
  function ensureConfigureInputStyle() {
2291
- if (uiGetById(PREFIX + '-configure-input-style')) return;
2281
+ if (uiGetById(`${PREFIX}-configure-input-style`)) return;
2292
2282
  const s = document.createElement('style');
2293
- s.id = PREFIX + '-configure-input-style';
2283
+ s.id = `${PREFIX}-configure-input-style`;
2294
2284
  s.textContent =
2295
2285
  '@keyframes monodesign-configure-voice-pulse { 0%, 100% { opacity: 0.55; } 50% { opacity: 1; } }' +
2296
2286
  '#' + PREFIX + '-input, #' + PREFIX + '-insert-input { box-sizing: border-box; height: ' + CONFIGURE_ROW_TRACK_H + '; line-height: ' + CONFIGURE_ROW_TRACK_H + '; padding: 0; margin: 0; caret-color: ' + CONFIGURE_PILL_TEXT + '; }' +
@@ -2310,7 +2300,7 @@
2310
2300
  const inputShell = el('div', configureInputShellStyle());
2311
2301
 
2312
2302
  const input = document.createElement('input');
2313
- input.id = PREFIX + '-input';
2303
+ input.id = `${PREFIX}-input`;
2314
2304
  input.type = 'text';
2315
2305
  input.placeholder = '';
2316
2306
  input.setAttribute('aria-label', 'Describe the change');
@@ -2336,7 +2326,7 @@
2336
2326
  onClick: (e) => {
2337
2327
  e.stopPropagation();
2338
2328
  if (controlsLocked) { showManualApplyBusyToast(); return; }
2339
- count.textContent = '\u00D7' + cycleSelectedCount();
2329
+ count.textContent = `\u00D7${cycleSelectedCount()}`;
2340
2330
  if (count.matches(':hover')) {
2341
2331
  showConfigureBarTooltip(count, variantCountTooltipText(selectedCount));
2342
2332
  }
@@ -2364,7 +2354,7 @@
2364
2354
  });
2365
2355
 
2366
2356
  const voiceBtn = buildConfigureVoiceButton({
2367
- id: PREFIX + '-configure-voice',
2357
+ id: `${PREFIX}-configure-voice`,
2368
2358
  controlsLocked,
2369
2359
  onClick: (e) => {
2370
2360
  e.stopPropagation();
@@ -2400,7 +2390,7 @@
2400
2390
  const inputShell = el('div', configureInputShellStyle());
2401
2391
 
2402
2392
  const input = document.createElement('input');
2403
- input.id = PREFIX + '-insert-input';
2393
+ input.id = `${PREFIX}-insert-input`;
2404
2394
  input.type = 'text';
2405
2395
  input.placeholder = '';
2406
2396
  input.setAttribute('aria-label', 'Describe the new element');
@@ -2417,7 +2407,7 @@
2417
2407
  onClick: (e) => {
2418
2408
  e.stopPropagation();
2419
2409
  if (controlsLocked) { showManualApplyBusyToast(); return; }
2420
- count.textContent = '\u00D7' + cycleSelectedCount();
2410
+ count.textContent = `\u00D7${cycleSelectedCount()}`;
2421
2411
  if (count.matches(':hover')) {
2422
2412
  showConfigureBarTooltip(count, variantCountTooltipText(selectedCount));
2423
2413
  }
@@ -2453,7 +2443,7 @@
2453
2443
  input.addEventListener('blur', () => syncConfigureInputChrome());
2454
2444
 
2455
2445
  const voiceBtn = buildConfigureVoiceButton({
2456
- id: PREFIX + '-insert-voice',
2446
+ id: `${PREFIX}-insert-voice`,
2457
2447
  controlsLocked,
2458
2448
  onClick: (e) => {
2459
2449
  e.stopPropagation();
@@ -2473,6 +2463,7 @@
2473
2463
  handleInsertCreate();
2474
2464
  },
2475
2465
  });
2466
+ // biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-regression.test.mjs:688
2476
2467
  create.id = PREFIX + '-insert-create';
2477
2468
  create.addEventListener('mouseenter', () => {
2478
2469
  if (controlsLocked) return;
@@ -2520,7 +2511,7 @@
2520
2511
  status.textContent = recoveryWaitingForAnchor
2521
2512
  ? 'Variants ready. Reveal the selected element to resume.'
2522
2513
  : (arrivedVariants < expectedVariants
2523
- ? 'Generating ' + expectedVariants + ' variants...'
2514
+ ? `Generating ${expectedVariants} variants...`
2524
2515
  : 'Done');
2525
2516
  row.appendChild(status);
2526
2517
 
@@ -2542,7 +2533,7 @@
2542
2533
 
2543
2534
  // Prev
2544
2535
  const prev = navBtn('\u2190');
2545
- prev.id = PREFIX + '-variant-prev';
2536
+ prev.id = `${PREFIX}-variant-prev`;
2546
2537
  prev.addEventListener('click', (e) => { e.stopPropagation(); cycleVariant(-1); });
2547
2538
  if (visibleVariant <= 1) prev.style.opacity = '0.3';
2548
2539
  row.appendChild(prev);
@@ -2555,13 +2546,13 @@
2555
2546
  fontFamily: MONO, fontSize: '11px', fontWeight: '500',
2556
2547
  color: BP.textDim, minWidth: '24px', textAlign: 'center',
2557
2548
  });
2558
- counter.id = PREFIX + '-variant-counter';
2559
- counter.textContent = visibleVariant + '/' + arrivedVariants;
2549
+ counter.id = `${PREFIX}-variant-counter`;
2550
+ counter.textContent = `${visibleVariant}/${arrivedVariants}`;
2560
2551
  row.appendChild(counter);
2561
2552
 
2562
2553
  // Next
2563
2554
  const next = navBtn('\u2192');
2564
- next.id = PREFIX + '-variant-next';
2555
+ next.id = `${PREFIX}-variant-next`;
2565
2556
  next.addEventListener('click', (e) => { e.stopPropagation(); cycleVariant(1); });
2566
2557
  if (visibleVariant >= arrivedVariants) next.style.opacity = '0.3';
2567
2558
  row.appendChild(next);
@@ -2598,7 +2589,7 @@
2598
2589
  });
2599
2590
  tuneBadge.textContent = String(visParams.length);
2600
2591
  tune.appendChild(tuneBadge);
2601
- tune.title = 'Tune this variant (' + visParams.length + ' knob' + (visParams.length === 1 ? '' : 's') + ')';
2592
+ tune.title = `Tune this variant (${visParams.length} knob${visParams.length === 1 ? '' : 's'})`;
2602
2593
  tune.addEventListener('mouseenter', () => {
2603
2594
  if (!tuneOpen) tune.style.background = BP.accentSoft;
2604
2595
  });
@@ -2633,7 +2624,7 @@
2633
2624
  // Discard
2634
2625
  const discard = el('button', {
2635
2626
  padding: '4px 6px', borderRadius: '5px',
2636
- border: '1px solid ' + BP.hairline, background: 'transparent',
2627
+ border: `1px solid ${BP.hairline}`, background: 'transparent',
2637
2628
  fontFamily: FONT, fontSize: '11px', color: BP.textDim,
2638
2629
  cursor: 'pointer', transition: 'color 0.12s ease, border-color 0.12s ease',
2639
2630
  });
@@ -2658,7 +2649,7 @@
2658
2649
  });
2659
2650
  const spinner = el('div', {
2660
2651
  width: '14px', height: '14px', borderRadius: '50%',
2661
- border: '2px solid ' + BP.hairline,
2652
+ border: `2px solid ${BP.hairline}`,
2662
2653
  borderTopColor: BP.accent,
2663
2654
  animation: 'monodesign-spin 0.6s linear infinite',
2664
2655
  flexShrink: '0',
@@ -2712,7 +2703,7 @@
2712
2703
  const dotBg = active ? C.brand
2713
2704
  : arrived ? BP.textDim
2714
2705
  : 'transparent';
2715
- const dotBorder = arrived ? 'none' : '1.5px solid ' + BP.hairline;
2706
+ const dotBorder = arrived ? 'none' : `1.5px solid ${BP.hairline}`;
2716
2707
  const dot = el('div', {
2717
2708
  width: active ? '8px' : '6px',
2718
2709
  height: active ? '8px' : '6px',
@@ -2720,7 +2711,7 @@
2720
2711
  background: dotBg,
2721
2712
  border: dotBorder,
2722
2713
  boxSizing: 'border-box',
2723
- transition: 'all 0.2s ' + EASE,
2714
+ transition: `all 0.2s ${EASE}`,
2724
2715
  cursor: (clickable && arrived) ? 'pointer' : 'default',
2725
2716
  transform: arrived ? 'scale(1)' : 'scale(0.85)',
2726
2717
  opacity: arrived ? (active ? '1' : '0.6') : '0.4',
@@ -2740,7 +2731,7 @@
2740
2731
  function navBtn(text) {
2741
2732
  const b = el('button', {
2742
2733
  width: '26px', height: '26px', borderRadius: '5px',
2743
- border: '1px solid ' + BP.hairline, background: 'transparent',
2734
+ border: `1px solid ${BP.hairline}`, background: 'transparent',
2744
2735
  color: BP.text, fontFamily: FONT, fontSize: '13px',
2745
2736
  cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center',
2746
2737
  transition: 'border-color 0.12s ease, background 0.12s ease',
@@ -2771,15 +2762,15 @@
2771
2762
  function initActionPicker() {
2772
2763
  const P = barPaletteForTheme(detectPageTheme());
2773
2764
  pickerEl = document.createElement('div');
2774
- pickerEl.id = PREFIX + '-picker';
2765
+ pickerEl.id = `${PREFIX}-picker`;
2775
2766
  Object.assign(pickerEl.style, {
2776
2767
  position: 'fixed', zIndex: Z.picker,
2777
2768
  display: 'none', opacity: '0',
2778
2769
  transform: 'scale(0.96) translateY(4px)',
2779
2770
  transformOrigin: 'bottom right',
2780
- transition: 'opacity 0.18s ' + EASE + ', transform 0.2s ' + EASE,
2771
+ transition: `opacity 0.18s ${EASE}, transform 0.2s ${EASE}`,
2781
2772
  background: P.surface,
2782
- border: '1px solid ' + P.border,
2773
+ border: `1px solid ${P.border}`,
2783
2774
  borderRadius: '8px',
2784
2775
  boxShadow: P.shadow,
2785
2776
  padding: '6px',
@@ -2823,11 +2814,11 @@
2823
2814
  chip.addEventListener('click', (e) => {
2824
2815
  e.preventDefault();
2825
2816
  e.stopPropagation();
2826
- const prompt = uiGetById(PREFIX + '-input')?.value || '';
2817
+ const prompt = uiGetById(`${PREFIX}-input`)?.value || '';
2827
2818
  selectedAction = action.value;
2828
2819
  hideActionPicker();
2829
2820
  updateBarContent('configure');
2830
- const input = uiGetById(PREFIX + '-input');
2821
+ const input = uiGetById(`${PREFIX}-input`);
2831
2822
  if (input && prompt) input.value = prompt;
2832
2823
  });
2833
2824
  grid.appendChild(chip);
@@ -2862,8 +2853,8 @@
2862
2853
  let left = barRect.right - pickerW;
2863
2854
  left = Math.max(8, Math.min(left, window.innerWidth - pickerW - 8));
2864
2855
  Object.assign(pickerEl.style, {
2865
- top: top + 'px',
2866
- left: left + 'px',
2856
+ top: `${top}px`,
2857
+ left: `${left}px`,
2867
2858
  });
2868
2859
  requestAnimationFrame(() => {
2869
2860
  pickerEl.style.opacity = '1';
@@ -2926,7 +2917,6 @@
2926
2917
  //
2927
2918
 
2928
2919
  let paramsPanelEl = null; // outer wrapper (overflow:hidden, clips the slide)
2929
- let paramsPanelInner = null; // translating content (carries bg, padding, knobs)
2930
2920
  let paramsPanelBody = null; // grid holding the knob cells
2931
2921
  let paramsCurrentValues = {}; // {paramId: value} - mirror of the visible variant's live values
2932
2922
  let tuneOpen = false; // whether the Tune popover is open right now
@@ -2948,7 +2938,7 @@
2948
2938
  // hides everything initially; as it grows, content is revealed from
2949
2939
  // the bar edge outward.
2950
2940
  paramsPanelEl = document.createElement('div');
2951
- paramsPanelEl.id = PREFIX + '-params-panel';
2941
+ paramsPanelEl.id = `${PREFIX}-params-panel`;
2952
2942
  Object.assign(paramsPanelEl.style, {
2953
2943
  position: 'fixed', zIndex: String(Z.bar - 1),
2954
2944
  background: P.surfaceDeep,
@@ -2963,7 +2953,7 @@
2963
2953
  // transition support across engines. Closed state clips from the far
2964
2954
  // edge; open = inset(0) shows everything.
2965
2955
  clipPath: 'inset(0 0 100% 0)',
2966
- transition: 'clip-path 0.44s ' + EASE,
2956
+ transition: `clip-path 0.44s ${EASE}`,
2967
2957
 
2968
2958
  // Park off-screen until positionParamsPanel places it. These are NOT
2969
2959
  // in the transition list, so they snap instantly - no fly-in from the
@@ -2983,7 +2973,6 @@
2983
2973
  // click-through) and 'auto' (open) on its own. Just silence the host's
2984
2974
  // outside-interaction listeners while the panel is open.
2985
2975
  defangOutsideHandlers(paramsPanelEl, { setPointerEvents: false });
2986
- paramsPanelInner = paramsPanelEl; // compatibility alias for the rest of the code
2987
2976
  }
2988
2977
 
2989
2978
 
@@ -3006,9 +2995,9 @@
3006
2995
  || svelteComponentSession.wrapperEl
3007
2996
  || null;
3008
2997
  }
3009
- const wrapper = document.querySelector('[data-monodesign-variants="' + currentSessionId + '"]');
2998
+ const wrapper = document.querySelector(`[data-monodesign-variants="${currentSessionId}"]`);
3010
2999
  if (!wrapper) return null;
3011
- return wrapper.querySelector('[data-monodesign-variant="' + visibleVariant + '"]');
3000
+ return wrapper.querySelector(`[data-monodesign-variant="${visibleVariant}"]`);
3012
3001
  }
3013
3002
 
3014
3003
  function parseVariantParams(variantEl) {
@@ -3035,7 +3024,7 @@
3035
3024
 
3036
3025
  function applyParamValue(variantEl, param, value) {
3037
3026
  if (!variantEl) return;
3038
- const attr = 'data-p-' + param.id;
3027
+ const attr = `data-p-${param.id}`;
3039
3028
  if (param.kind === 'toggle') {
3040
3029
  const on = !!value;
3041
3030
  if (on) variantEl.setAttribute(attr, 'on');
@@ -3049,8 +3038,9 @@
3049
3038
  // so there is no React hydration to mismatch. Drive range/toggle --p-* inline
3050
3039
  // on the mounted element so scoped preview CSS resolves them.
3051
3040
  if (svelteComponentSession?.sessionId === currentSessionId) {
3041
+ // biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-regression.test.mjs:335
3052
3042
  if (param.kind === 'range') variantEl.style.setProperty('--p-' + param.id, String(value));
3053
- else if (param.kind === 'toggle') variantEl.style.setProperty('--p-' + param.id, value ? '1' : '0');
3043
+ else if (param.kind === 'toggle') variantEl.style.setProperty(`--p-${param.id}`, value ? '1' : '0');
3054
3044
  return;
3055
3045
  }
3056
3046
  // range/toggle --p-* custom properties are driven through the injected
@@ -3069,7 +3059,7 @@
3069
3059
  function formatRangeValue(input) {
3070
3060
  const max = parseFloat(input.max), min = parseFloat(input.min);
3071
3061
  const v = parseFloat(input.value);
3072
- if (!isFinite(v)) return input.value;
3062
+ if (!Number.isFinite(v)) return input.value;
3073
3063
  return (max - min) <= 2 ? v.toFixed(2) : String(Math.round(v));
3074
3064
  }
3075
3065
 
@@ -3131,7 +3121,7 @@
3131
3121
  left: initial ? '18px' : '2px',
3132
3122
  width: '16px', height: '16px', borderRadius: '50%',
3133
3123
  background: 'oklch(98% 0 0)',
3134
- transition: 'left 0.18s ' + EASE,
3124
+ transition: `left 0.18s ${EASE}`,
3135
3125
  boxShadow: '0 1px 2px oklch(0% 0 0 / 0.2)',
3136
3126
  });
3137
3127
  track.appendChild(knob);
@@ -3154,7 +3144,7 @@
3154
3144
  readout.textContent = activeOpt ? activeOpt.label : String(p.default);
3155
3145
  const segRow = el('div', {
3156
3146
  display: 'grid',
3157
- gridTemplateColumns: 'repeat(' + opts.length + ', 1fr)',
3147
+ gridTemplateColumns: `repeat(${opts.length}, 1fr)`,
3158
3148
  gap: '1px', padding: '2px',
3159
3149
  background: P.hairline, borderRadius: '5px',
3160
3150
  });
@@ -3209,15 +3199,15 @@
3209
3199
  const MIXED_WRAP_SKIP = { script: 1, style: 1, template: 1, noscript: 1, svg: 1, code: 1, pre: 1 };
3210
3200
 
3211
3201
  function collectEditableTextRows(rootEl, opts) {
3212
- if (!rootEl || rootEl.nodeType !== 1) return [];
3213
- const isOwn = (opts && opts.isOwn) || (() => false);
3202
+ if (rootEl?.nodeType !== 1) return [];
3203
+ const isOwn = opts?.isOwn || (() => false);
3214
3204
  const rows = [];
3215
3205
 
3216
3206
  function visit(el) {
3217
- if (!el || el.nodeType !== 1) return;
3207
+ if (el?.nodeType !== 1) return;
3218
3208
  const tag = el.tagName.toLowerCase();
3219
3209
  if (MIXED_WRAP_SKIP[tag]) return;
3220
- if (el.hasAttribute && el.hasAttribute('contenteditable')) return;
3210
+ if (el.hasAttribute?.('contenteditable')) return;
3221
3211
  if (el !== rootEl && isOwn(el)) return;
3222
3212
 
3223
3213
  const children = Array.from(el.childNodes);
@@ -3251,7 +3241,7 @@
3251
3241
  }
3252
3242
 
3253
3243
  function wrapMixedContentTextNodes(rootEl) {
3254
- if (!rootEl || rootEl.nodeType !== 1) return;
3244
+ if (rootEl?.nodeType !== 1) return;
3255
3245
  const tag = rootEl.tagName.toLowerCase();
3256
3246
  if (MIXED_WRAP_SKIP[tag]) return;
3257
3247
  if (rootEl.hasAttribute('contenteditable')) return;
@@ -3270,13 +3260,13 @@
3270
3260
  }
3271
3261
  }
3272
3262
  for (const child of Array.from(rootEl.children)) {
3273
- if (!child.dataset || !child.dataset.monodesignTextWrap) {
3263
+ if (!child.dataset?.monodesignTextWrap) {
3274
3264
  wrapMixedContentTextNodes(child);
3275
3265
  }
3276
3266
  }
3277
3267
  }
3278
3268
  function unwrapMixedContentTextNodes(rootEl) {
3279
- if (!rootEl || rootEl.nodeType !== 1) return;
3269
+ if (rootEl?.nodeType !== 1) return;
3280
3270
  const wraps = rootEl.querySelectorAll('[data-monodesign-text-wrap="true"]');
3281
3271
  for (const wrap of wraps) {
3282
3272
  const parent = wrap.parentNode;
@@ -3339,7 +3329,7 @@
3339
3329
  // (mixed-content paragraphs included). Mirrors what the wrap+walk path
3340
3330
  // will produce in enableInlineEdit.
3341
3331
  function check(node) {
3342
- if (!node || node.nodeType !== 1) return false;
3332
+ if (node?.nodeType !== 1) return false;
3343
3333
  const tag = node.tagName.toLowerCase();
3344
3334
  if (MIXED_WRAP_SKIP[tag]) return false;
3345
3335
  if (node !== el && own(node)) return false;
@@ -3363,9 +3353,11 @@
3363
3353
  enableInlineEdit(selectedElement);
3364
3354
  // Focus first editable element and position cursor at end
3365
3355
  if (inlineEditRows.length > 0) {
3356
+ // biome-ignore lint/complexity/useOptionalChain: exact text pinned by tests/live-browser-regression.test.mjs
3366
3357
  const firstEditable = inlineEditRows[0] && inlineEditRows[0].el;
3367
3358
  setTimeout(() => {
3368
3359
  const el = firstEditable;
3360
+ // biome-ignore lint/complexity/useOptionalChain: test-pinned
3369
3361
  if (!el || !el.isConnected || state !== 'EDITING') return;
3370
3362
  el.focus();
3371
3363
  const range = document.createRange();
@@ -3460,7 +3452,7 @@
3460
3452
  }
3461
3453
 
3462
3454
  function sourceHintForElement(el) {
3463
- if (!el || !el.getAttribute) return null;
3455
+ if (!el?.getAttribute) return null;
3464
3456
  const file = el.getAttribute('data-astro-source-file');
3465
3457
  const loc = el.getAttribute('data-astro-source-loc');
3466
3458
  if (file || loc) {
@@ -3479,12 +3471,12 @@
3479
3471
  const match = String(loc || '').match(/^(\d+)(?::(\d+))?/);
3480
3472
  return {
3481
3473
  line: match ? Number(match[1]) : null,
3482
- column: match && match[2] ? Number(match[2]) : null,
3474
+ column: match?.[2] ? Number(match[2]) : null,
3483
3475
  };
3484
3476
  }
3485
3477
 
3486
3478
  function documentRefForElement(el) {
3487
- if (!el || el.nodeType !== 1) return null;
3479
+ if (el?.nodeType !== 1) return null;
3488
3480
  const parts = [];
3489
3481
  let cur = el;
3490
3482
  while (cur && cur.nodeType === 1) {
@@ -3502,11 +3494,11 @@
3502
3494
 
3503
3495
  function documentRefSegment(el) {
3504
3496
  const tag = el.tagName.toLowerCase();
3505
- return tag + documentRefIdSuffix(el) + documentRefClassSuffix(el) + ':nth-of-type(' + indexAmongSameTag(el) + ')';
3497
+ return `${tag + documentRefIdSuffix(el) + documentRefClassSuffix(el)}:nth-of-type(${indexAmongSameTag(el)})`;
3506
3498
  }
3507
3499
 
3508
3500
  function documentRefIdSuffix(el) {
3509
- return el.id ? '#' + normalizeDocumentRefToken(el.id) : '';
3501
+ return el.id ? `#${normalizeDocumentRefToken(el.id)}` : '';
3510
3502
  }
3511
3503
 
3512
3504
  function documentRefClassSuffix(el) {
@@ -3517,7 +3509,7 @@
3517
3509
  classes.push(normalizeDocumentRefToken(cls));
3518
3510
  if (classes.length === 2) break;
3519
3511
  }
3520
- return classes.length ? '.' + classes.join('.') : '';
3512
+ return classes.length ? `.${classes.join('.')}` : '';
3521
3513
  }
3522
3514
 
3523
3515
  function normalizeDocumentRefToken(value) {
@@ -3604,7 +3596,7 @@
3604
3596
  }
3605
3597
  const forbidden = forbiddenManualTextChars(newText);
3606
3598
  if (forbidden.length > 0) {
3607
- showToast('Save rejected: newText cannot contain ' + forbidden.join(' ') + ' (plain text only; ask the AI to insert markup)', 5500);
3599
+ showToast(`Save rejected: newText cannot contain ${forbidden.join(' ')} (plain text only; ask the AI to insert markup)`, 5500);
3608
3600
  return;
3609
3601
  }
3610
3602
  const locator = buildLocatorForLeaf(row.el, selectedElement);
@@ -3632,6 +3624,7 @@
3632
3624
  const container = copyEditContainerContext(contextElement);
3633
3625
  if (container) for (const op of ops) op.container = container;
3634
3626
  try {
3627
+ // biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-source.test.mjs:18
3635
3628
  const res = await fetch('http://localhost:' + PORT + '/manual-edit-stash', {
3636
3629
  method: 'POST',
3637
3630
  headers: { 'Content-Type': 'application/json' },
@@ -3645,7 +3638,7 @@
3645
3638
  });
3646
3639
  if (!res.ok) {
3647
3640
  const errBody = await res.json().catch(() => ({}));
3648
- throw new Error(errBody.error || ('HTTP ' + res.status));
3641
+ throw new Error(errBody.error || (`HTTP ${res.status}`));
3649
3642
  }
3650
3643
  const stashResult = await res.json();
3651
3644
  updatePendingCounter(stashResult.pendingCount || 0);
@@ -3659,7 +3652,7 @@
3659
3652
  console.error('[monodesign] manual edit stash failed:', err);
3660
3653
  const detail = String(err?.message || '');
3661
3654
  if (detail.includes('newText cannot contain') || detail.includes('newText cannot be empty')) {
3662
- showToast('Save rejected: ' + detail.replace(/^manual_edits:\s*/, ''), 5500);
3655
+ showToast(`Save rejected: ${detail.replace(/^manual_edits:\s*/, '')}`, 5500);
3663
3656
  } else {
3664
3657
  showToast('Save failed - retry or cancel', 4000);
3665
3658
  }
@@ -3676,13 +3669,14 @@
3676
3669
  const width = globalBarEl.offsetWidth;
3677
3670
  const height = globalBarEl.offsetHeight;
3678
3671
  if (!width || !height) return;
3679
- pendingDockEl.style.left = Math.round((window.innerWidth / 2) - (width / 2) - 18) + 'px';
3672
+ pendingDockEl.style.left = `${Math.round((window.innerWidth / 2) - (width / 2) - 18)}px`;
3680
3673
  pendingDockEl.style.top = 'auto';
3674
+ // biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-source.test.mjs:204
3681
3675
  pendingDockEl.style.bottom = Math.round(14 + (height / 2)) + 'px';
3682
3676
  }
3683
3677
 
3684
3678
  function playPendingIntroAnimation() {
3685
- if (!pendingPillEl || !pendingPillEl.animate || (matchMedia?.('(prefers-reduced-motion: reduce)').matches)) return;
3679
+ if (!pendingPillEl?.animate || (matchMedia?.('(prefers-reduced-motion: reduce)').matches)) return;
3686
3680
  if (pendingIntroAnimation) pendingIntroAnimation.cancel();
3687
3681
  pendingIntroAnimation = pendingPillEl.animate([
3688
3682
  {
@@ -3709,9 +3703,9 @@
3709
3703
  }
3710
3704
 
3711
3705
  function ensureSpinKeyframes() {
3712
- if (uiGetById(PREFIX + '-keyframes')) return;
3706
+ if (uiGetById(`${PREFIX}-keyframes`)) return;
3713
3707
  const style = document.createElement('style');
3714
- style.id = PREFIX + '-keyframes';
3708
+ style.id = `${PREFIX}-keyframes`;
3715
3709
  style.textContent = '@keyframes monodesign-spin { to { transform: rotate(360deg); } }';
3716
3710
  uiAppendStyle(style);
3717
3711
  }
@@ -3725,7 +3719,7 @@
3725
3719
  }
3726
3720
 
3727
3721
  function manualApplyStateKey() {
3728
- return PREFIX + ':manual-apply:' + PORT + ':' + TOKEN + ':' + location.pathname;
3722
+ return `${PREFIX}:manual-apply:${PORT}:${TOKEN}:${location.pathname}`;
3729
3723
  }
3730
3724
 
3731
3725
  function readStoredManualApplyState() {
@@ -3790,13 +3784,14 @@
3790
3784
  if (stored?.phase === 'repairing') {
3791
3785
  const attempt = Number(stored.repairAttempt) || 1;
3792
3786
  const max = Number(stored.repairMaxAttempts) || 3;
3793
- return 'Fixing apply issue, attempt ' + attempt + '/' + max;
3787
+ return `Fixing apply issue, attempt ${attempt}/${max}`;
3794
3788
  }
3795
3789
  if (stored?.phase === 'verifying') return 'Verifying copy edits';
3796
3790
  const remaining = Number.isFinite(Number(stored?.remainingCount))
3797
3791
  ? Number(stored.remainingCount)
3798
3792
  : Number(fallbackCount) || 0;
3799
3793
  return remaining > 0
3794
+ // biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-source.test.mjs:151
3800
3795
  ? 'Applying ' + remaining + ' copy edit' + (remaining === 1 ? '' : 's')
3801
3796
  : 'Verifying copy edits';
3802
3797
  }
@@ -3846,10 +3841,10 @@
3846
3841
  closeTunePopover();
3847
3842
  }
3848
3843
  if (barEl && barEl.style.display !== 'none' && state === 'CONFIGURING') {
3849
- const input = uiGetById(PREFIX + '-input');
3844
+ const input = uiGetById(`${PREFIX}-input`);
3850
3845
  const prompt = input ? input.value : '';
3851
3846
  updateBarContent('configure');
3852
- const nextInput = uiGetById(PREFIX + '-input');
3847
+ const nextInput = uiGetById(`${PREFIX}-input`);
3853
3848
  if (nextInput) nextInput.value = prompt;
3854
3849
  }
3855
3850
  if (editBadgeEl && editBadgeEl.style.display !== 'none') {
@@ -3928,7 +3923,7 @@
3928
3923
  }
3929
3924
  pendingPillLabelEl.textContent = pendingApplyLabel(currentPageCount);
3930
3925
  pendingPillCountEl.textContent = String(currentPageCount);
3931
- pendingPillEl.setAttribute('aria-label', 'Apply ' + currentPageCount + ' copy edit' + (currentPageCount === 1 ? '' : 's') + ' to source');
3926
+ pendingPillEl.setAttribute('aria-label', `Apply ${currentPageCount} copy edit${currentPageCount === 1 ? '' : 's'} to source`);
3932
3927
  pendingPillEl.style.display = 'inline-flex';
3933
3928
  pendingTrashBtn.style.display = 'inline-flex';
3934
3929
  pendingDockEl.style.display = 'inline-flex';
@@ -3947,7 +3942,7 @@
3947
3942
  async function fetchPendingCount() {
3948
3943
  try {
3949
3944
  const res = await fetch(
3950
- 'http://localhost:' + PORT + '/manual-edit-stash?token=' + encodeURIComponent(TOKEN) + '&pageUrl=' + encodeURIComponent(location.pathname),
3945
+ `http://localhost:${PORT}/manual-edit-stash?token=${encodeURIComponent(TOKEN)}&pageUrl=${encodeURIComponent(location.pathname)}`,
3951
3946
  );
3952
3947
  if (!res.ok) return;
3953
3948
  const data = await res.json();
@@ -3960,19 +3955,19 @@
3960
3955
  async function onPendingPillClick() {
3961
3956
  const count = parseInt(pendingPillEl?.dataset.count || '0', 10);
3962
3957
  if (count <= 0 || pendingApplyInFlight) return;
3963
- const ok = confirm('Apply ' + count + ' copy edit' + (count === 1 ? '' : 's') + ' to source?');
3958
+ const ok = confirm(`Apply ${count} copy edit${count === 1 ? '' : 's'} to source?`);
3964
3959
  if (!ok) return;
3965
3960
  let waitForSseCompletion = false;
3966
3961
  resetManualApplyProgress(count);
3967
3962
  setPendingApplyLoading(true, count);
3968
3963
  try {
3969
3964
  const res = await fetch(
3970
- 'http://localhost:' + PORT + '/manual-edit-commit?token=' + encodeURIComponent(TOKEN) + '&pageUrl=' + encodeURIComponent(location.pathname) + '&async=1',
3965
+ `http://localhost:${PORT}/manual-edit-commit?token=${encodeURIComponent(TOKEN)}&pageUrl=${encodeURIComponent(location.pathname)}&async=1`,
3971
3966
  { method: 'POST', keepalive: true },
3972
3967
  );
3973
3968
  if (!res.ok) {
3974
3969
  const errBody = await res.json().catch(() => ({}));
3975
- throw new Error(errBody.error || ('HTTP ' + res.status));
3970
+ throw new Error(errBody.error || (`HTTP ${res.status}`));
3976
3971
  }
3977
3972
  const result = await res.json();
3978
3973
  if (res.status === 202 || result.status === 'started') {
@@ -3983,11 +3978,11 @@
3983
3978
  updatePendingCounter(remaining);
3984
3979
  if (result.failed && result.failed.length > 0) {
3985
3980
  console.warn('[monodesign] some copy edits failed:', result.failed);
3986
- showToast('Applied ' + (result.applied?.length || 0) + ', ' + result.failed.length + ' failed - see console', 5000);
3981
+ showToast(`Applied ${result.applied?.length || 0}, ${result.failed.length} failed - see console`, 5000);
3987
3982
  } else {
3988
3983
  const n = Array.isArray(result.applied) ? result.applied.length : (result.cleared || 0);
3989
3984
  if (n > 0) {
3990
- showToast('Applied ' + n + ' edit' + (n === 1 ? '' : 's'), 2500);
3985
+ showToast(`Applied ${n} edit${n === 1 ? '' : 's'}`, 2500);
3991
3986
  } else {
3992
3987
  console.warn('[monodesign] apply returned no verified edits:', result);
3993
3988
  showToast('No edits applied - see console', 4000);
@@ -4008,21 +4003,21 @@
4008
4003
  async function onPendingTrashClick() {
4009
4004
  const count = parseInt(pendingPillEl?.dataset.count || '0', 10);
4010
4005
  if (count <= 0 || pendingApplyInFlight) return;
4011
- const ok = confirm('Discard ' + count + ' copy edit' + (count === 1 ? '' : 's') + ' on this page?');
4006
+ const ok = confirm(`Discard ${count} copy edit${count === 1 ? '' : 's'} on this page?`);
4012
4007
  if (!ok) return;
4013
4008
  try {
4014
4009
  const res = await fetch(
4015
- 'http://localhost:' + PORT + '/manual-edit-discard?token=' + encodeURIComponent(TOKEN) + '&pageUrl=' + encodeURIComponent(location.pathname),
4010
+ `http://localhost:${PORT}/manual-edit-discard?token=${encodeURIComponent(TOKEN)}&pageUrl=${encodeURIComponent(location.pathname)}`,
4016
4011
  { method: 'POST' },
4017
4012
  );
4018
- if (!res.ok) throw new Error('HTTP ' + res.status);
4013
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
4019
4014
  const result = await res.json().catch(() => ({}));
4020
4015
  const restoreFailures = restoreDiscardedManualEdits(result.entries || []);
4021
4016
  updatePendingCounter(0);
4022
4017
  if (restoreFailures > 0) {
4023
- showToast('Discarded ' + count + ' copy edit' + (count === 1 ? '' : 's') + ' - refresh to reset ' + restoreFailures, 4000);
4018
+ showToast(`Discarded ${count} copy edit${count === 1 ? '' : 's'} - refresh to reset ${restoreFailures}`, 4000);
4024
4019
  } else {
4025
- showToast('Discarded ' + count + ' copy edit' + (count === 1 ? '' : 's'), 2500);
4020
+ showToast(`Discarded ${count} copy edit${count === 1 ? '' : 's'}`, 2500);
4026
4021
  }
4027
4022
  } catch (err) {
4028
4023
  console.error('[monodesign] discard failed:', err);
@@ -4061,10 +4056,10 @@
4061
4056
  updateManualApplyRepairState({ attempt: 1, maxAttempts: 3 }, 'repairing');
4062
4057
  try {
4063
4058
  const res = await fetch(
4064
- 'http://localhost:' + PORT + '/manual-edit-commit?token=' + encodeURIComponent(TOKEN) + '&pageUrl=' + encodeURIComponent(location.pathname) + '&async=1&repair=1',
4059
+ `http://localhost:${PORT}/manual-edit-commit?token=${encodeURIComponent(TOKEN)}&pageUrl=${encodeURIComponent(location.pathname)}&async=1&repair=1`,
4065
4060
  { method: 'POST', keepalive: true },
4066
4061
  );
4067
- if (!res.ok) throw new Error('HTTP ' + res.status);
4062
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
4068
4063
  if (pendingKeepFixingBtn) pendingKeepFixingBtn.style.display = 'none';
4069
4064
  if (pendingRollbackBtn) pendingRollbackBtn.style.display = 'none';
4070
4065
  if (pendingTrashBtn) pendingTrashBtn.style.display = 'inline-flex';
@@ -4080,14 +4075,14 @@
4080
4075
  if (!ok) return;
4081
4076
  try {
4082
4077
  const res = await fetch(
4083
- 'http://localhost:' + PORT + '/manual-edit-repair-decision?token=' + encodeURIComponent(TOKEN) + '&pageUrl=' + encodeURIComponent(location.pathname),
4078
+ `http://localhost:${PORT}/manual-edit-repair-decision?token=${encodeURIComponent(TOKEN)}&pageUrl=${encodeURIComponent(location.pathname)}`,
4084
4079
  {
4085
4080
  method: 'POST',
4086
4081
  headers: { 'Content-Type': 'application/json' },
4087
4082
  body: JSON.stringify({ token: TOKEN, pageUrl: location.pathname, action: 'rollback' }),
4088
4083
  },
4089
4084
  );
4090
- if (!res.ok) throw new Error('HTTP ' + res.status);
4085
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
4091
4086
  const result = await res.json().catch(() => ({}));
4092
4087
  clearStoredManualApplyState();
4093
4088
  updatePendingCounter(numberOrNull(result.remainingCount) || 0);
@@ -4174,9 +4169,9 @@
4174
4169
  const failedCount = numberOrNull(msg.failedCount) || 0;
4175
4170
  const appliedCount = numberOrNull(msg.appliedCount) || numberOrNull(msg.cleared) || 0;
4176
4171
  if (failedCount > 0) {
4177
- showToast('Applied ' + appliedCount + ', ' + failedCount + ' failed - see console', 5000);
4172
+ showToast(`Applied ${appliedCount}, ${failedCount} failed - see console`, 5000);
4178
4173
  } else if (appliedCount > 0) {
4179
- showToast('Applied ' + appliedCount + ' edit' + (appliedCount === 1 ? '' : 's'), 2500);
4174
+ showToast(`Applied ${appliedCount} edit${appliedCount === 1 ? '' : 's'}`, 2500);
4180
4175
  }
4181
4176
  }
4182
4177
  return;
@@ -4219,7 +4214,7 @@
4219
4214
  }
4220
4215
 
4221
4216
  function mixedTextWrapRestoreHint(el) {
4222
- if (!el || !el.dataset || el.dataset.monodesignTextWrap !== 'true' || !el.parentElement) return null;
4217
+ if (el?.dataset?.monodesignTextWrap !== 'true' || !el.parentElement) return null;
4223
4218
  const siblings = directMixedTextRestoreNodes(el.parentElement);
4224
4219
  const textIndex = siblings.indexOf(el);
4225
4220
  return {
@@ -4231,7 +4226,7 @@
4231
4226
 
4232
4227
  function restoreMixedTextNodeManualEdit(op) {
4233
4228
  const restore = op?.restore;
4234
- if (!restore || restore.kind !== 'mixedTextNode' || typeof op?.originalText !== 'string') return false;
4229
+ if (restore?.kind !== 'mixedTextNode' || typeof op?.originalText !== 'string') return false;
4235
4230
  const parent = queryManualEditRef(restore.parentRef);
4236
4231
  if (!parent) return false;
4237
4232
  const textNodes = directMixedTextRestoreNodes(parent).filter((node) => node.nodeType === 3);
@@ -4264,7 +4259,7 @@
4264
4259
  }
4265
4260
  const tag = op?.tag || op?.leaf?.tagName || '*';
4266
4261
  const classes = Array.isArray(op?.classes) ? op.classes : (Array.isArray(op?.leaf?.classes) ? op.leaf.classes : []);
4267
- const selector = (tag === '*' ? '' : tag) + classes.map((cls) => '.' + cssIdent(cls)).join('') || '*';
4262
+ const selector = (tag === '*' ? '' : tag) + classes.map((cls) => `.${cssIdent(cls)}`).join('') || '*';
4268
4263
  let matches = [];
4269
4264
  try {
4270
4265
  matches = Array.from(document.querySelectorAll(selector));
@@ -4317,7 +4312,7 @@
4317
4312
  if (el.tagName.toLowerCase() !== segment.tag) return false;
4318
4313
  if (segment.id && el.id !== segment.id) return false;
4319
4314
  for (const cls of segment.classes) {
4320
- if (!el.classList || !el.classList.contains(cls)) return false;
4315
+ if (!el.classList?.contains(cls)) return false;
4321
4316
  }
4322
4317
  if (segment.nth && indexAmongSameTag(el) !== segment.nth) return false;
4323
4318
  return true;
@@ -4340,7 +4335,7 @@
4340
4335
 
4341
4336
  function usesShadowChromeRoot() {
4342
4337
  const root = liveUiRoot();
4343
- return root && root !== document.body && root.host && root.host.id === PREFIX + '-root';
4338
+ return root && root !== document.body && root.host && root.host.id === `${PREFIX}-root`;
4344
4339
  }
4345
4340
 
4346
4341
  function setImportantStyle(el, name, value) {
@@ -4350,7 +4345,7 @@
4350
4345
  function initEditBadgeHitProxies() {
4351
4346
  if (!usesShadowChromeRoot() || editBadgeProxyRoot) return;
4352
4347
  editBadgeProxyRoot = document.createElement('div');
4353
- editBadgeProxyRoot.id = PREFIX + '-edit-badge-hit-proxies';
4348
+ editBadgeProxyRoot.id = `${PREFIX}-edit-badge-hit-proxies`;
4354
4349
  editBadgeProxyRoot.setAttribute('aria-hidden', 'true');
4355
4350
  const styles = {
4356
4351
  all: 'initial',
@@ -4364,7 +4359,7 @@
4364
4359
  overflow: 'visible',
4365
4360
  };
4366
4361
  for (const [name, value] of Object.entries(styles)) {
4367
- setImportantStyle(editBadgeProxyRoot, name.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase()), value);
4362
+ setImportantStyle(editBadgeProxyRoot, name.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`), value);
4368
4363
  }
4369
4364
  document.body.appendChild(editBadgeProxyRoot);
4370
4365
  }
@@ -4375,10 +4370,10 @@
4375
4370
  const styles = {
4376
4371
  all: 'initial',
4377
4372
  position: 'fixed',
4378
- left: rect.left + 'px',
4379
- top: rect.top + 'px',
4380
- width: rect.width + 'px',
4381
- height: rect.height + 'px',
4373
+ left: `${rect.left}px`,
4374
+ top: `${rect.top}px`,
4375
+ width: `${rect.width}px`,
4376
+ height: `${rect.height}px`,
4382
4377
  margin: '0',
4383
4378
  padding: '0',
4384
4379
  border: '0',
@@ -4391,7 +4386,7 @@
4391
4386
  zIndex: String(Z.toast + 2),
4392
4387
  };
4393
4388
  for (const [name, value] of Object.entries(styles)) {
4394
- setImportantStyle(proxy, name.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase()), value);
4389
+ setImportantStyle(proxy, name.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`), value);
4395
4390
  }
4396
4391
  }
4397
4392
 
@@ -4495,7 +4490,7 @@
4495
4490
 
4496
4491
  function initEditBadge() {
4497
4492
  editBadgeEl = document.createElement('div');
4498
- editBadgeEl.id = PREFIX + '-edit-badge';
4493
+ editBadgeEl.id = `${PREFIX}-edit-badge`;
4499
4494
  Object.assign(editBadgeEl.style, {
4500
4495
  position: 'fixed',
4501
4496
  zIndex: String(Z.highlight + 1),
@@ -4507,9 +4502,9 @@
4507
4502
  initEditBadgeHitProxies();
4508
4503
 
4509
4504
  // Remove focus rings on edit badge buttons + contenteditable elements
4510
- if (!uiGetById(PREFIX + '-edit-badge-focus-style')) {
4505
+ if (!uiGetById(`${PREFIX}-edit-badge-focus-style`)) {
4511
4506
  const s = document.createElement('style');
4512
- s.id = PREFIX + '-edit-badge-focus-style';
4507
+ s.id = `${PREFIX}-edit-badge-focus-style`;
4513
4508
  s.textContent =
4514
4509
  '#' + PREFIX + '-edit-badge button { outline: none !important; box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; }' +
4515
4510
  '#' + PREFIX + '-edit-badge button:focus { outline: none !important; }' +
@@ -4530,8 +4525,8 @@
4530
4525
  const bw = editBadgeEl.offsetWidth;
4531
4526
  // Match showHighlight's 2px outset so the badge right edge lines up with the outline.
4532
4527
  const outlineRight = r.right + 2;
4533
- editBadgeEl.style.top = Math.max(4, r.top - 28) + 'px';
4534
- editBadgeEl.style.left = Math.min(window.innerWidth - bw - 4, outlineRight - bw) + 'px';
4528
+ editBadgeEl.style.top = `${Math.max(4, r.top - 28)}px`;
4529
+ editBadgeEl.style.left = `${Math.min(window.innerWidth - bw - 4, outlineRight - bw)}px`;
4535
4530
  syncEditBadgeHitProxies();
4536
4531
  }
4537
4532
 
@@ -4560,7 +4555,7 @@
4560
4555
  color: color,
4561
4556
  background: SURFACE,
4562
4557
  padding: '2px 8px',
4563
- border: '1px solid ' + (borderColor || color),
4558
+ border: `1px solid ${borderColor || color}`,
4564
4559
  borderRadius: '6px',
4565
4560
  boxSizing: 'border-box',
4566
4561
  minHeight: '22px',
@@ -4599,7 +4594,7 @@
4599
4594
  btn.style.cursor = 'not-allowed';
4600
4595
  btn.style.opacity = '0.55';
4601
4596
  btn.disabled = true;
4602
- const disabledTip = EDIT_COPY_LABEL + ' is disabled while the current copy edit is applying';
4597
+ const disabledTip = `${EDIT_COPY_LABEL} is disabled while the current copy edit is applying`;
4603
4598
  btn.addEventListener('mouseenter', () => showConfigureBarTooltip(btn, disabledTip));
4604
4599
  btn.addEventListener('mouseleave', hideConfigureBarTooltip);
4605
4600
  } else {
@@ -4668,20 +4663,20 @@
4668
4663
  const prevDirection = paramsPanelEl.dataset.tuneDirection;
4669
4664
 
4670
4665
  // top/left/width are NOT in the transition list, so they snap instantly.
4671
- paramsPanelEl.style.left = br.left + 'px';
4672
- paramsPanelEl.style.width = br.width + 'px';
4666
+ paramsPanelEl.style.left = `${br.left}px`;
4667
+ paramsPanelEl.style.width = `${br.width}px`;
4673
4668
 
4674
4669
  if (direction === 'below') {
4675
- paramsPanelEl.style.top = (br.bottom - TUNE_OVERLAP) + 'px';
4670
+ paramsPanelEl.style.top = `${br.bottom - TUNE_OVERLAP}px`;
4676
4671
  paramsPanelEl.style.borderRadius = '0 0 10px 10px';
4677
- paramsPanelEl.style.paddingTop = (14 + TUNE_OVERLAP) + 'px';
4672
+ paramsPanelEl.style.paddingTop = `${14 + TUNE_OVERLAP}px`;
4678
4673
  paramsPanelEl.style.paddingBottom = '14px';
4679
4674
  } else {
4680
4675
  const ih = paramsPanelEl.offsetHeight || 80;
4681
- paramsPanelEl.style.top = (br.top - ih + TUNE_OVERLAP) + 'px';
4676
+ paramsPanelEl.style.top = `${br.top - ih + TUNE_OVERLAP}px`;
4682
4677
  paramsPanelEl.style.borderRadius = '10px 10px 0 0';
4683
4678
  paramsPanelEl.style.paddingTop = '14px';
4684
- paramsPanelEl.style.paddingBottom = (14 + TUNE_OVERLAP) + 'px';
4679
+ paramsPanelEl.style.paddingBottom = `${14 + TUNE_OVERLAP}px`;
4685
4680
  }
4686
4681
  paramsPanelEl.dataset.tuneDirection = direction;
4687
4682
 
@@ -4802,10 +4797,10 @@
4802
4797
  const shown = svelteComponentSession?.sessionId === currentSessionId && svelteComponentSession.mountedVariant > 0
4803
4798
  ? svelteComponentSession.mountedVariant
4804
4799
  : visibleVariant;
4805
- const counter = uiGetById(PREFIX + '-variant-counter');
4806
- if (counter && arrivedVariants > 0) counter.textContent = shown + '/' + arrivedVariants;
4807
- const prev = uiGetById(PREFIX + '-variant-prev');
4808
- const next = uiGetById(PREFIX + '-variant-next');
4800
+ const counter = uiGetById(`${PREFIX}-variant-counter`);
4801
+ if (counter && arrivedVariants > 0) counter.textContent = `${shown}/${arrivedVariants}`;
4802
+ const prev = uiGetById(`${PREFIX}-variant-prev`);
4803
+ const next = uiGetById(`${PREFIX}-variant-next`);
4809
4804
  if (prev) prev.style.opacity = shown <= 1 ? '0.3' : '1';
4810
4805
  if (next) next.style.opacity = shown >= arrivedVariants ? '0.3' : '1';
4811
4806
  if (currentSessionId && state === 'CYCLING') saveSession();
@@ -4821,7 +4816,7 @@
4821
4816
  scheduleCyclingBarSync(sessionId, num);
4822
4817
  return true;
4823
4818
  }
4824
- const wrapper = document.querySelector('[data-monodesign-variants="' + sessionId + '"]');
4819
+ const wrapper = document.querySelector(`[data-monodesign-variants="${sessionId}"]`);
4825
4820
  if (!wrapper) return false;
4826
4821
  updateVariantStateStylesheet(sessionId, num);
4827
4822
  // Unconditional refresh - covers first-reveal (no-op if state isn't
@@ -4837,7 +4832,7 @@
4837
4832
 
4838
4833
  function parseOriginalMarkupElement(originalMarkup) {
4839
4834
  const parser = new DOMParser();
4840
- const doc = parser.parseFromString('<div id="monodesign-anchor">' + originalMarkup + '</div>', 'text/html');
4835
+ const doc = parser.parseFromString(`<div id="monodesign-anchor">${originalMarkup}</div>`, 'text/html');
4841
4836
  return doc.getElementById('monodesign-anchor')?.firstElementChild || null;
4842
4837
  }
4843
4838
 
@@ -4854,7 +4849,7 @@
4854
4849
  }
4855
4850
 
4856
4851
  function buildPickedAnchorSnapshot(el) {
4857
- if (!el || el.nodeType !== 1) return null;
4852
+ if (el?.nodeType !== 1) return null;
4858
4853
  return {
4859
4854
  tag: el.tagName,
4860
4855
  id: el.id || '',
@@ -5002,7 +4997,7 @@
5002
4997
  // A wrapper can land incomplete ("wrap HMR landed, variant insert did
5003
4998
  // not"); injectVariantsFromSource owns both cases - it replaces an
5004
4999
  // existing wrapper from source and clears recoveryWaitingForAnchor.
5005
- const wrapperLanded = !!document.querySelector('[data-monodesign-variants="' + sessionId + '"]');
5000
+ const wrapperLanded = !!document.querySelector(`[data-monodesign-variants="${sessionId}"]`);
5006
5001
  if (!wrapperLanded) {
5007
5002
  const liveEl = resolveLiveInjectionAnchor(originalMarkup);
5008
5003
  if (!liveEl?.parentElement) return;
@@ -5045,8 +5040,8 @@
5045
5040
  async function loadSvelteComponentParams(manifest) {
5046
5041
  const dir = String(manifest?.componentDir || '').replace(/^\/+/, '');
5047
5042
  if (!dir) return {};
5048
- const paramsPath = dir + '/params.json';
5049
- const url = 'http://localhost:' + PORT + '/source?token=' + TOKEN + '&path=' + encodeURIComponent(paramsPath);
5043
+ const paramsPath = `${dir}/params.json`;
5044
+ const url = `http://localhost:${PORT}/source?token=${TOKEN}&path=${encodeURIComponent(paramsPath)}`;
5050
5045
  try {
5051
5046
  const res = await fetch(url);
5052
5047
  if (!res.ok) return {};
@@ -5065,8 +5060,8 @@
5065
5060
  async function loadSvelteComponentVariantSource(manifest, variantNum) {
5066
5061
  const dir = String(manifest?.componentDir || '').replace(/^\/+/, '');
5067
5062
  if (!dir || !variantNum) return '';
5068
- const sourcePath = dir + '/v' + variantNum + '.svelte';
5069
- const url = 'http://localhost:' + PORT + '/source?token=' + TOKEN + '&path=' + encodeURIComponent(sourcePath);
5063
+ const sourcePath = `${dir}/v${variantNum}.svelte`;
5064
+ const url = `http://localhost:${PORT}/source?token=${TOKEN}&path=${encodeURIComponent(sourcePath)}`;
5070
5065
  try {
5071
5066
  const res = await fetch(url);
5072
5067
  if (!res.ok) return '';
@@ -5105,7 +5100,7 @@
5105
5100
  }
5106
5101
 
5107
5102
  function scopeCssToSveltePreview(css, sessionId) {
5108
- const prefix = '[data-monodesign-variants="' + String(sessionId).replace(/"/g, '\\"') + '"] ';
5103
+ const prefix = `[data-monodesign-variants="${String(sessionId).replace(/"/g, '\\"')}"] `;
5109
5104
  return scopeCssBlock(String(css || ''), prefix).trim();
5110
5105
  }
5111
5106
 
@@ -5132,11 +5127,11 @@
5132
5127
  }
5133
5128
  const body = css.slice(open + 1, close);
5134
5129
  if (shouldScopeNestedCssAtRule(prelude)) {
5135
- out += prelude + ' {\n' + scopeCssBlock(body, prefix) + '\n}';
5130
+ out += `${prelude} {\n${scopeCssBlock(body, prefix)}\n}`;
5136
5131
  } else if (prelude.startsWith('@')) {
5137
- out += prelude + ' {' + body + '}';
5132
+ out += `${prelude} {${body}}`;
5138
5133
  } else {
5139
- out += prefixCssSelectors(prelude, prefix) + ' {' + body + '}';
5134
+ out += `${prefixCssSelectors(prelude, prefix)} {${body}}`;
5140
5135
  }
5141
5136
  i = close + 1;
5142
5137
  }
@@ -5221,7 +5216,7 @@
5221
5216
  if (!sourceOriginal) return values;
5222
5217
  const map = buildSvelteExpressionTextMap(sourceOriginal, liveEl);
5223
5218
  for (const entry of contract) {
5224
- const token = '{' + entry.expr + '}';
5219
+ const token = `{${entry.expr}}`;
5225
5220
  values[entry.prop] = map.get(token) || '';
5226
5221
  }
5227
5222
  return values;
@@ -5234,8 +5229,8 @@
5234
5229
  const previousAnchor = getMountedSvelteComponentAnchor(svelteComponentSession) || selectedElement;
5235
5230
  svelteComponentSession.swapAnchor = makeFrozenAnchor(previousAnchor) || svelteComponentSession.swapAnchor || null;
5236
5231
  const runtime = await loadSvelteRuntime(manifest.runtimeModule);
5237
- const modulePath = '/' + String(manifest.componentDir || '').replace(/^\/+/, '') + '/v' + variantNum + '.svelte';
5238
- const moduleUrl = new URL(modulePath, location.origin).href + '?t=' + Date.now();
5232
+ const modulePath = `/${String(manifest.componentDir || '').replace(/^\/+/, '')}/v${variantNum}.svelte`;
5233
+ const moduleUrl = `${new URL(modulePath, location.origin).href}?t=${Date.now()}`;
5239
5234
  const mod = await import(/* @vite-ignore */ moduleUrl);
5240
5235
  const Component = mod.default;
5241
5236
  if (svelteComponentSession.mountedInstance && runtime.unmount) {
@@ -5275,7 +5270,7 @@
5275
5270
  if (svelteComponentSession?.sessionId === sessionId) {
5276
5271
  svelteComponentSession.swapAnchor = null;
5277
5272
  }
5278
- console.error('[monodesign] Failed to mount Svelte variant ' + variantNum + ' for ' + sessionId + ':', err);
5273
+ console.error(`[monodesign] Failed to mount Svelte variant ${variantNum} for ${sessionId}:`, err);
5279
5274
  return false;
5280
5275
  }
5281
5276
  }
@@ -5332,7 +5327,7 @@
5332
5327
  }
5333
5328
 
5334
5329
  async function injectSvelteComponentsFromManifest(manifestPath, sessionId) {
5335
- const url = 'http://localhost:' + PORT + '/source?token=' + TOKEN + '&path=' + encodeURIComponent(manifestPath);
5330
+ const url = `http://localhost:${PORT}/source?token=${TOKEN}&path=${encodeURIComponent(manifestPath)}`;
5336
5331
  try {
5337
5332
  const res = await fetch(url);
5338
5333
  if (!res.ok) throw new Error(String(res.status));
@@ -5349,7 +5344,7 @@
5349
5344
  });
5350
5345
  if (state !== 'CYCLING') setLiveState('GENERATING');
5351
5346
 
5352
- const existingWrapper = document.querySelector('[data-monodesign-variants="' + sessionId + '"]');
5347
+ const existingWrapper = document.querySelector(`[data-monodesign-variants="${sessionId}"]`);
5353
5348
  if (existingWrapper && svelteComponentSession?.sessionId === sessionId) {
5354
5349
  recoveryWaitingForAnchor = false;
5355
5350
  svelteComponentSession.paramsByVariant = paramsByVariant;
@@ -5445,7 +5440,7 @@
5445
5440
  refreshParamsPanel();
5446
5441
  positionBar();
5447
5442
  saveSession();
5448
- console.log('[monodesign] Mounted ' + arrivedVariants + ' Svelte component variants.');
5443
+ console.log(`[monodesign] Mounted ${arrivedVariants} Svelte component variants.`);
5449
5444
  } catch (err) {
5450
5445
  console.error('[monodesign] Failed to mount Svelte component variants:', err);
5451
5446
  abortSvelteComponentInjection(sessionId, 'Could not load variants. Fix the error and re-run.');
@@ -5477,7 +5472,7 @@
5477
5472
  if (svelteComponentSession?.sessionId === sessionId) {
5478
5473
  teardownSvelteComponentSession(true);
5479
5474
  } else {
5480
- const orphan = document.querySelector('[data-monodesign-variants="' + sessionId + '"]');
5475
+ const orphan = document.querySelector(`[data-monodesign-variants="${sessionId}"]`);
5481
5476
  if (orphan) orphan.remove();
5482
5477
  }
5483
5478
  } catch (err) {
@@ -5513,7 +5508,7 @@
5513
5508
  return;
5514
5509
  }
5515
5510
  rememberSessionFileMeta({ file: filePath });
5516
- const url = 'http://localhost:' + PORT + '/source?token=' + TOKEN + '&path=' + encodeURIComponent(filePath);
5511
+ const url = `http://localhost:${PORT}/source?token=${TOKEN}&path=${encodeURIComponent(filePath)}`;
5517
5512
  fetch(url)
5518
5513
  .then(r => { if (!r.ok) throw new Error(r.status); return r.text(); })
5519
5514
  .then(html => {
@@ -5521,15 +5516,15 @@
5521
5516
  let srcWrapper = null;
5522
5517
 
5523
5518
  // Full-file parse works for HTML/JSX; Astro/Vue sources need marker extraction.
5524
- const startMark = '<!-- monodesign-variants-start ' + sessionId + ' -->';
5525
- const endMark = '<!-- monodesign-variants-end ' + sessionId + ' -->';
5519
+ const startMark = `<!-- monodesign-variants-start ${sessionId} -->`;
5520
+ const endMark = `<!-- monodesign-variants-end ${sessionId} -->`;
5526
5521
  const startIdx = html.indexOf(startMark);
5527
5522
  const endIdx = html.indexOf(endMark);
5528
5523
  const block = startIdx !== -1 && endIdx !== -1 && endIdx > startIdx
5529
5524
  ? html.slice(startIdx + startMark.length, endIdx).trim()
5530
5525
  : html;
5531
5526
  const doc = parser.parseFromString(normalizeSourceFallbackBlock(block, filePath), 'text/html');
5532
- srcWrapper = doc.querySelector('[data-monodesign-variants="' + sessionId + '"]');
5527
+ srcWrapper = doc.querySelector(`[data-monodesign-variants="${sessionId}"]`);
5533
5528
  if (!srcWrapper) {
5534
5529
  console.warn('[monodesign] Variant wrapper not found in source file.');
5535
5530
  return;
@@ -5539,7 +5534,7 @@
5539
5534
  const wrapper = srcWrapper.cloneNode(true);
5540
5535
 
5541
5536
  // Wrapper already in DOM (wrap HMR landed, variant insert did not).
5542
- const existingWrapper = document.querySelector('[data-monodesign-variants="' + sessionId + '"]');
5537
+ const existingWrapper = document.querySelector(`[data-monodesign-variants="${sessionId}"]`);
5543
5538
  if (existingWrapper) {
5544
5539
  existingWrapper.parentElement.replaceChild(wrapper, existingWrapper);
5545
5540
  } else {
@@ -5571,6 +5566,7 @@
5571
5566
  // when a late HMR/source reinjection lands after they have cycled.
5572
5567
  const variants = wrapper.querySelectorAll('[data-monodesign-variant]:not([data-monodesign-variant="original"])');
5573
5568
  arrivedVariants = variants.length;
5569
+ // biome-ignore lint/correctness/useParseIntRadix: data-monodesign-variant-count can be hand-written in page source (reference/live.md), so a 0x value is not provably excluded
5574
5570
  expectedVariants = parseInt(wrapper.dataset.monodesignVariantCount || arrivedVariants);
5575
5571
  if (arrivedVariants <= 0) {
5576
5572
  recoverEmptyCycling('source-fallback-empty');
@@ -5594,7 +5590,7 @@
5594
5590
  refreshParamsPanel();
5595
5591
  positionBar();
5596
5592
  saveSession();
5597
- console.log('[monodesign] Injected ' + arrivedVariants + ' variants from source file.');
5593
+ console.log(`[monodesign] Injected ${arrivedVariants} variants from source file.`);
5598
5594
  })
5599
5595
  .catch(err => {
5600
5596
  console.error('[monodesign] Failed to fetch source:', err);
@@ -5607,16 +5603,16 @@
5607
5603
  return String(block)
5608
5604
  .replace(
5609
5605
  /<style\b([^>]*)>\s*\{\s*`([\s\S]*?)`\s*\}\s*<\/style>/g,
5610
- (_match, attrs, css) => '<style' + attrs + '>' + css + '</style>',
5606
+ (_match, attrs, css) => `<style${attrs}>${css}</style>`,
5611
5607
  )
5612
5608
  .replace(/\bclassName\s*=\s*\{\s*`([^`]*?)`\s*\}/g, (_match, value) => {
5613
5609
  const literalClasses = value.replace(/\$\{[^}]*\}/g, ' ').replace(/\s+/g, ' ').trim();
5614
- return literalClasses ? 'class="' + escapeHtml(literalClasses) + '"' : '';
5610
+ return literalClasses ? `class="${escapeHtml(literalClasses)}"` : '';
5615
5611
  })
5616
5612
  .replace(/\bclassName\s*=/g, 'class=')
5617
5613
  .replace(/\sstyle=\{\{([\s\S]*?)\}\}/g, (_match, body) => {
5618
5614
  const css = jsxStyleObjectToCss(body);
5619
- return css ? ' style="' + escapeHtml(css) + '"' : '';
5615
+ return css ? ` style="${escapeHtml(css)}"` : '';
5620
5616
  });
5621
5617
  }
5622
5618
 
@@ -5628,16 +5624,16 @@
5628
5624
  const prop = jsxStylePropToCss(match[1]);
5629
5625
  const value = match[2] ?? match[3] ?? match[4] ?? '';
5630
5626
  if (!prop || value === '') continue;
5631
- declarations.push(prop + ': ' + value);
5627
+ declarations.push(`${prop}: ${value}`);
5632
5628
  }
5633
5629
  return declarations.join('; ');
5634
5630
  }
5635
5631
 
5636
5632
  function jsxStylePropToCss(prop) {
5637
- let out = String(prop || '').trim().replace(/^["']|["']$/g, '');
5633
+ const out = String(prop || '').trim().replace(/^["']|["']$/g, '');
5638
5634
  if (!out) return '';
5639
5635
  if (out.startsWith('--')) return out;
5640
- return out.replace(/[A-Z]/g, (ch) => '-' + ch.toLowerCase()).replace(/^-ms-/, '-ms-');
5636
+ return out.replace(/[A-Z]/g, (ch) => `-${ch.toLowerCase()}`).replace(/^-ms-/, '-ms-');
5641
5637
  }
5642
5638
 
5643
5639
  function buildSvelteExpressionTextMap(sourceOriginal, liveOriginal) {
@@ -5668,7 +5664,7 @@
5668
5664
  }
5669
5665
 
5670
5666
  const match = liveText.match(expressionTextMatcher(sourceText, [token]));
5671
- if (match && match[1]) map.set(token, match[1].trim());
5667
+ if (match?.[1]) map.set(token, match[1].trim());
5672
5668
  continue;
5673
5669
  }
5674
5670
 
@@ -5693,7 +5689,7 @@
5693
5689
  pattern += '(.*?)';
5694
5690
  cursor = index + token.length;
5695
5691
  }
5696
- pattern += escapeRegExp(sourceText.slice(cursor)).replace(/\s+/g, '\\s*') + '$';
5692
+ pattern += `${escapeRegExp(sourceText.slice(cursor)).replace(/\s+/g, '\\s*')}$`;
5697
5693
  return new RegExp(pattern);
5698
5694
  }
5699
5695
 
@@ -5763,7 +5759,7 @@
5763
5759
  if (anchor && !anchor.__monodesignFrozenAnchor) selectedElement = anchor;
5764
5760
  return;
5765
5761
  }
5766
- const wrapper = document.querySelector('[data-monodesign-variants="' + currentSessionId + '"]');
5762
+ const wrapper = document.querySelector(`[data-monodesign-variants="${currentSessionId}"]`);
5767
5763
  if (!wrapper) return;
5768
5764
  const visEl = pickVariantContent(wrapper, visibleVariant);
5769
5765
  if (visEl) selectedElement = visEl;
@@ -5773,7 +5769,7 @@
5773
5769
  if (svelteComponentSession?.sessionId === sessionId && svelteComponentSession.mountedVariant > 0) {
5774
5770
  return svelteComponentSession.mountedVariant;
5775
5771
  }
5776
- const wrapper = document.querySelector('[data-monodesign-variants="' + sessionId + '"]');
5772
+ const wrapper = document.querySelector(`[data-monodesign-variants="${sessionId}"]`);
5777
5773
  if (!wrapper) return 0;
5778
5774
  const variants = wrapper.querySelectorAll('[data-monodesign-variant]:not([data-monodesign-variant="original"])');
5779
5775
  for (const variant of variants) {
@@ -5792,7 +5788,7 @@
5792
5788
  // (it wraps all of them and gets correct bounds).
5793
5789
  function pickVariantContent(wrapper, index) {
5794
5790
  if (!wrapper) return null;
5795
- const variantDiv = wrapper.querySelector('[data-monodesign-variant="' + index + '"]');
5791
+ const variantDiv = wrapper.querySelector(`[data-monodesign-variant="${index}"]`);
5796
5792
  if (!variantDiv) return null;
5797
5793
  const NON_VISUAL = new Set(['STYLE', 'SCRIPT', 'LINK', 'META', 'TEMPLATE']);
5798
5794
  const visual = [];
@@ -5819,11 +5815,11 @@
5819
5815
  // single variant (`… > [data-monodesign-variant="N"]`); without it, targets
5820
5816
  // every variant via the bare `[data-monodesign-variant]` attribute.
5821
5817
  function variantStateSelector(sessionId, num) {
5822
- const wrapper = '[data-monodesign-variants="' + sessionId + '"]';
5818
+ const wrapper = `[data-monodesign-variants="${sessionId}"]`;
5823
5819
  const variant = num == null
5824
5820
  ? '[data-monodesign-variant]'
5825
- : '[data-monodesign-variant="' + num + '"]';
5826
- return wrapper + ' > ' + variant;
5821
+ : `[data-monodesign-variant="${num}"]`;
5822
+ return `${wrapper} > ${variant}`;
5827
5823
  }
5828
5824
 
5829
5825
  // Serialize the visible variant's knob values into `--p-<id>` custom-property
@@ -5832,8 +5828,8 @@
5832
5828
  function variantParamDecls(values) {
5833
5829
  return Object.entries(values || {})
5834
5830
  .map(([id, val]) => {
5835
- if (typeof val === 'number') return ' --p-' + id + ': ' + val + ';';
5836
- if (typeof val === 'boolean') return ' --p-' + id + ': ' + (val ? '1' : '0') + ';';
5831
+ if (typeof val === 'number') return ` --p-${id}: ${val};`;
5832
+ if (typeof val === 'boolean') return ` --p-${id}: ${val ? '1' : '0'};`;
5837
5833
  return '';
5838
5834
  })
5839
5835
  .join('');
@@ -5858,7 +5854,7 @@
5858
5854
  const showVisible = variantStateSelector(sessionId, num)
5859
5855
  + ' { ' + VARIANT_SHOW_DECL + variantParamDecls(paramsCurrentValues) + ' }';
5860
5856
 
5861
- styleEl.textContent = hideOthers + '\n' + showVisible + '\n';
5857
+ styleEl.textContent = `${hideOthers}\n${showVisible}\n`;
5862
5858
  }
5863
5859
 
5864
5860
  function removeVariantStateStylesheet() {
@@ -5869,7 +5865,7 @@
5869
5865
  // session's wrapper (HMR patches, variant inserts, cycle swaps).
5870
5866
  function startScrollLock(sessionId, initialTargetY) {
5871
5867
  stopScrollLock();
5872
- scrollLockTargetY = typeof initialTargetY === 'number' && isFinite(initialTargetY)
5868
+ scrollLockTargetY = typeof initialTargetY === 'number' && Number.isFinite(initialTargetY)
5873
5869
  ? initialTargetY
5874
5870
  : window.scrollY;
5875
5871
 
@@ -5892,7 +5888,7 @@
5892
5888
  (document.head || document.documentElement).appendChild(anchorLockStyle);
5893
5889
  }
5894
5890
 
5895
- const correct = (why) => {
5891
+ const correct = (_why) => {
5896
5892
  scrollLockRaf = null;
5897
5893
  if (scrollLockTargetY == null) return;
5898
5894
  const before = window.scrollY;
@@ -5909,12 +5905,12 @@
5909
5905
 
5910
5906
  scrollLockObserver = new MutationObserver((mutations) => {
5911
5907
  for (const m of mutations) {
5912
- if (m.target?.closest?.('[data-monodesign-variants="' + sessionId + '"]')) {
5908
+ if (m.target?.closest?.(`[data-monodesign-variants="${sessionId}"]`)) {
5913
5909
  schedule('mutation-in-wrapper');
5914
5910
  return;
5915
5911
  }
5916
5912
  for (const n of m.addedNodes) {
5917
- if (n.nodeType === 1 && (n.matches?.('[data-monodesign-variants="' + sessionId + '"]') || n.querySelector?.('[data-monodesign-variants="' + sessionId + '"]'))) {
5913
+ if (n.nodeType === 1 && (n.matches?.(`[data-monodesign-variants="${sessionId}"]`) || n.querySelector?.(`[data-monodesign-variants="${sessionId}"]`))) {
5918
5914
  schedule('wrapper-added');
5919
5915
  return;
5920
5916
  }
@@ -5935,9 +5931,8 @@
5935
5931
  let userGestureAt = 0;
5936
5932
  const USER_GESTURE_WINDOW_MS = 250;
5937
5933
 
5938
- const reanchor = (why) => {
5934
+ const reanchor = (_why) => {
5939
5935
  if (scrollLockRaf != null) { cancelAnimationFrame(scrollLockRaf); scrollLockRaf = null; }
5940
- const prevTarget = scrollLockTargetY;
5941
5936
  scrollLockTargetY = window.scrollY;
5942
5937
  writeScrollY(scrollLockTargetY);
5943
5938
  };
@@ -5949,7 +5944,7 @@
5949
5944
  window.addEventListener('touchstart', () => markGesture('touchstart'), { passive: true, ...sig });
5950
5945
  window.addEventListener('touchmove', () => markGesture('touchmove'), { passive: true, ...sig });
5951
5946
  window.addEventListener('keydown', (e) => {
5952
- if (['PageDown', 'PageUp', ' ', 'End', 'Home', 'ArrowDown', 'ArrowUp'].includes(e.key)) markGesture('key:' + e.key);
5947
+ if (['PageDown', 'PageUp', ' ', 'End', 'Home', 'ArrowDown', 'ArrowUp'].includes(e.key)) markGesture(`key:${e.key}`);
5953
5948
  }, sig);
5954
5949
 
5955
5950
  // Correct on EVERY scroll event: whether it's the browser's
@@ -6014,7 +6009,7 @@
6014
6009
  }
6015
6010
  if (!dominated) return;
6016
6011
 
6017
- const wrapper = document.querySelector('[data-monodesign-variants="' + sessionId + '"]');
6012
+ const wrapper = document.querySelector(`[data-monodesign-variants="${sessionId}"]`);
6018
6013
  if (!wrapper) return;
6019
6014
 
6020
6015
  const variants = wrapper.querySelectorAll('[data-monodesign-variant]:not([data-monodesign-variant="original"])');
@@ -6061,6 +6056,7 @@
6061
6056
  if (visEl) selectedElement = visEl;
6062
6057
  }
6063
6058
 
6059
+ // biome-ignore lint/correctness/useParseIntRadix: data-monodesign-variant-count can be hand-written in page source (reference/live.md), so a 0x value is not provably excluded
6064
6060
  const expected = parseInt(wrapper.dataset.monodesignVariantCount || '0');
6065
6061
  if (expected > 0) expectedVariants = expected;
6066
6062
 
@@ -6134,7 +6130,7 @@
6134
6130
  const SSE_MAX_RETRIES = 20; // generous: heartbeats keep the connection alive, so retries mean real trouble
6135
6131
 
6136
6132
  function connectSSE() {
6137
- evtSource = new EventSource('http://localhost:' + PORT + '/events?token=' + TOKEN);
6133
+ evtSource = new EventSource(`http://localhost:${PORT}/events?token=${TOKEN}`);
6138
6134
 
6139
6135
  evtSource.onopen = () => {
6140
6136
  sseRetries = 0; // reset on successful (re)connect
@@ -6235,7 +6231,7 @@
6235
6231
  }
6236
6232
  if (maybeCompleteSteer(msg)) break;
6237
6233
  console.error('[monodesign] Error:', msg.message);
6238
- showToast('Error: ' + msg.message, 5000);
6234
+ showToast(`Error: ${msg.message}`, 5000);
6239
6235
  hideBar();
6240
6236
  renderEditBadge('hidden');
6241
6237
  setLiveState('PICKING');
@@ -6246,7 +6242,7 @@
6246
6242
  evtSource.onerror = () => {
6247
6243
  sseRetries++;
6248
6244
  if (sseRetries <= SSE_MAX_RETRIES) {
6249
- console.log('[monodesign] SSE connection lost. Retry ' + sseRetries + '/' + SSE_MAX_RETRIES + '...');
6245
+ console.log(`[monodesign] SSE connection lost. Retry ${sseRetries}/${SSE_MAX_RETRIES}...`);
6250
6246
  return; // EventSource auto-reconnects
6251
6247
  }
6252
6248
  // Server is gone. Clean up gracefully.
@@ -6283,6 +6279,7 @@
6283
6279
  function sendEvent(msg, opts) {
6284
6280
  msg.token = TOKEN;
6285
6281
  function handleFailure(err) {
6282
+ // biome-ignore lint/complexity/useOptionalChain: exact text pinned by tests/live-browser-source.test.mjs
6286
6283
  if (opts && opts.throwOnError) {
6287
6284
  console.error('[monodesign] Failed to send event:', err);
6288
6285
  throw err;
@@ -6290,13 +6287,14 @@
6290
6287
  console.debug('[monodesign] Dropped optional live event:', err);
6291
6288
  return null;
6292
6289
  }
6293
- return fetch('http://localhost:' + PORT + '/events', {
6290
+ return fetch(`http://localhost:${PORT}/events`, {
6294
6291
  method: 'POST',
6295
6292
  headers: { 'Content-Type': 'application/json' },
6296
6293
  body: JSON.stringify(msg),
6297
6294
  }).then(async res => {
6298
6295
  if (res.ok) return res;
6299
6296
  const body = await res.json().catch(() => ({}));
6297
+ // biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-source.test.mjs:278
6300
6298
  return handleFailure(new Error(body.error || ('HTTP ' + res.status + ' ' + res.statusText)));
6301
6299
  }).catch(handleFailure);
6302
6300
  }
@@ -6543,14 +6541,16 @@
6543
6541
  if (e.key !== 'ArrowUp' && e.key !== 'ArrowDown') return false;
6544
6542
  if (!/^(INPUT|TEXTAREA)$/.test(deepActive.tagName || '')) return false;
6545
6543
  if (deepActive.value) return false;
6544
+ // biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-regression.test.mjs:491
6546
6545
  if (deepActive.id === PREFIX + '-input' && state === 'CONFIGURING') return true;
6546
+ // biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-regression.test.mjs:496
6547
6547
  if (deepActive.id === PREFIX + '-page-chat-input' && state === 'PICKING') return true;
6548
6548
  return false;
6549
6549
  }
6550
6550
 
6551
6551
  function handleKeyDown(e) {
6552
6552
  // When the annotation input is focused, let it handle its own keys.
6553
- if (annotEditing && annotEditing.input && e.target === annotEditing.input) return;
6553
+ if (annotEditing?.input && e.target === annotEditing.input) return;
6554
6554
  const deepActive = activeElementDeep();
6555
6555
  if (
6556
6556
  deepActive
@@ -6670,7 +6670,7 @@
6670
6670
  if (pendingApplyInFlight) { showManualApplyBusyToast(); return; }
6671
6671
  if (!selectedElement || state !== 'CONFIGURING') return;
6672
6672
  stopVoice({ suppressSubmit: true });
6673
- const input = uiGetById(PREFIX + '-input');
6673
+ const input = uiGetById(`${PREFIX}-input`);
6674
6674
  const prompt = input ? input.value.trim() : '';
6675
6675
 
6676
6676
  // Commit any pending pin edit BEFORE we snapshot annotations.
@@ -6744,7 +6744,7 @@
6744
6744
 
6745
6745
  function handleInsertCreate() {
6746
6746
  if (!placeholderElement || !insertAnchorElement || state !== 'CONFIGURING' || configureKind !== 'insert') return;
6747
- const input = uiGetById(PREFIX + '-insert-input');
6747
+ const input = uiGetById(`${PREFIX}-insert-input`);
6748
6748
  const prompt = input ? input.value.trim() : '';
6749
6749
  if (annotEditing) finalizeEditingPin();
6750
6750
  const snapshot = {
@@ -6809,7 +6809,7 @@
6809
6809
  if (msLoadPromise) return msLoadPromise;
6810
6810
  msLoadPromise = new Promise((resolve, reject) => {
6811
6811
  const s = document.createElement('script');
6812
- s.src = 'http://localhost:' + PORT + '/modern-screenshot.js';
6812
+ s.src = `http://localhost:${PORT}/modern-screenshot.js`;
6813
6813
  s.onload = () => resolve(window.modernScreenshot);
6814
6814
  s.onerror = () => { msLoadPromise = null; reject(new Error('modern-screenshot failed to load')); };
6815
6815
  uiAppendStyle(s);
@@ -6854,12 +6854,12 @@
6854
6854
  const buf = await res.arrayBuffer();
6855
6855
  const ext = url.toLowerCase().match(FONT_EXT_RE)?.[1] || 'woff2';
6856
6856
  const mime = FONT_MIME[ext] || 'application/octet-stream';
6857
- map.set(url, 'data:' + mime + ';base64,' + bufferToBase64(buf));
6857
+ map.set(url, `data:${mime};base64,${bufferToBase64(buf)}`);
6858
6858
  } catch { /* skip; fall through to URL */ }
6859
6859
  }));
6860
6860
  return cssText.replace(urlRe, (orig, q, url) => {
6861
6861
  const data = map.get(url);
6862
- return data ? 'url(' + q + data + q + ')' : orig;
6862
+ return data ? `url(${q}${data}${q})` : orig;
6863
6863
  });
6864
6864
  }
6865
6865
  async function collectFontCssText() {
@@ -6933,20 +6933,20 @@
6933
6933
  if (!node || node === document.body || nodes.includes(node)) return;
6934
6934
  nodes.push(node);
6935
6935
  };
6936
- add(document.getElementById(PREFIX + '-root'));
6936
+ add(document.getElementById(`${PREFIX}-root`));
6937
6937
  [
6938
- PREFIX + '-highlight',
6939
- PREFIX + '-tooltip',
6940
- PREFIX + '-bar',
6941
- PREFIX + '-picker',
6942
- PREFIX + '-params-panel',
6943
- PREFIX + '-insert-line',
6944
- PREFIX + '-insert-placeholder',
6945
- PREFIX + '-insert-create-tooltip',
6946
- PREFIX + '-annot',
6947
- PREFIX + '-design-host',
6948
- PREFIX + '-toast',
6949
- PREFIX + '-shader',
6938
+ `${PREFIX}-highlight`,
6939
+ `${PREFIX}-tooltip`,
6940
+ `${PREFIX}-bar`,
6941
+ `${PREFIX}-picker`,
6942
+ `${PREFIX}-params-panel`,
6943
+ `${PREFIX}-insert-line`,
6944
+ `${PREFIX}-insert-placeholder`,
6945
+ `${PREFIX}-insert-create-tooltip`,
6946
+ `${PREFIX}-annot`,
6947
+ `${PREFIX}-design-host`,
6948
+ `${PREFIX}-toast`,
6949
+ `${PREFIX}-shader`,
6950
6950
  ].forEach((id) => add(uiGetById(id)));
6951
6951
  return nodes;
6952
6952
  }
@@ -7313,7 +7313,7 @@ void main() {
7313
7313
  for (let p = 0; p < w * h; p += stride) {
7314
7314
  const i = p * 4;
7315
7315
  if (data[i + 3] < 16) continue;
7316
- const key = (data[i] >> 4) + ',' + (data[i + 1] >> 4) + ',' + (data[i + 2] >> 4);
7316
+ const key = `${data[i] >> 4},${data[i + 1] >> 4},${data[i + 2] >> 4}`;
7317
7317
  const bucket = buckets.get(key) || { count: 0, r: 0, g: 0, b: 0 };
7318
7318
  bucket.count += 1;
7319
7319
  bucket.r += data[i];
@@ -7357,7 +7357,7 @@ void main() {
7357
7357
  if (!gl.getShaderParameter(sh, gl.COMPILE_STATUS)) {
7358
7358
  const info = gl.getShaderInfoLog(sh);
7359
7359
  gl.deleteShader(sh);
7360
- throw new Error('shader compile failed: ' + info);
7360
+ throw new Error(`shader compile failed: ${info}`);
7361
7361
  }
7362
7362
  return sh;
7363
7363
  }
@@ -7368,8 +7368,8 @@ void main() {
7368
7368
  if (!anchor) return;
7369
7369
  const r = anchor.getBoundingClientRect();
7370
7370
  Object.assign(shaderState.canvas.style, {
7371
- top: r.top + 'px', left: r.left + 'px',
7372
- width: r.width + 'px', height: r.height + 'px',
7371
+ top: `${r.top}px`, left: `${r.left}px`,
7372
+ width: `${r.width}px`, height: `${r.height}px`,
7373
7373
  });
7374
7374
  }
7375
7375
 
@@ -7387,16 +7387,17 @@ void main() {
7387
7387
  canvas.remove();
7388
7388
  const objectUrl = URL.createObjectURL(blob);
7389
7389
  const fallback = document.createElement('div');
7390
- fallback.id = PREFIX + '-shader';
7390
+ fallback.id = `${PREFIX}-shader`;
7391
7391
  // Copy positioning via cssText. Object.assign across CSSStyleDeclaration
7392
7392
  // throws in modern Chromium because the source's indexed properties
7393
7393
  // (style[0], [1], ...) are read-only and the engine forbids writing
7394
7394
  // them on the destination.
7395
7395
  fallback.style.cssText = canvas.style.cssText;
7396
+ // biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-regression.test.mjs:62
7396
7397
  fallback.style.backgroundImage = 'url("' + objectUrl + '")';
7397
7398
  fallback.style.backgroundSize = '100% 100%';
7398
7399
  fallback.style.backgroundRepeat = 'no-repeat';
7399
- fallback.style.outline = '2px dashed ' + C.brand;
7400
+ fallback.style.outline = `2px dashed ${C.brand}`;
7400
7401
  fallback.style.outlineOffset = '-2px';
7401
7402
  uiAppend(fallback);
7402
7403
  shaderState = { canvas: fallback, gl: null, program: null, texture: null, rafId: 0, startTime: 0, objectUrl };
@@ -7406,15 +7407,15 @@ void main() {
7406
7407
  hideShaderOverlay();
7407
7408
  if (!blob || !el) return;
7408
7409
  const canvas = document.createElement('canvas');
7409
- canvas.id = PREFIX + '-shader';
7410
+ canvas.id = `${PREFIX}-shader`;
7410
7411
  const dpr = Math.min(window.devicePixelRatio || 1, 2);
7411
7412
  const radius = getComputedStyle(el).borderRadius;
7412
7413
  canvas.width = Math.max(1, Math.floor(rect.width * dpr));
7413
7414
  canvas.height = Math.max(1, Math.floor(rect.height * dpr));
7414
7415
  Object.assign(canvas.style, {
7415
7416
  position: 'fixed',
7416
- top: rect.top + 'px', left: rect.left + 'px',
7417
- width: rect.width + 'px', height: rect.height + 'px',
7417
+ top: `${rect.top}px`, left: `${rect.left}px`,
7418
+ width: `${rect.width}px`, height: `${rect.height}px`,
7418
7419
  borderRadius: radius,
7419
7420
  overflow: 'hidden',
7420
7421
  pointerEvents: 'none',
@@ -7440,7 +7441,7 @@ void main() {
7440
7441
  gl.attachShader(program, fs);
7441
7442
  gl.linkProgram(program);
7442
7443
  if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
7443
- throw new Error('program link failed: ' + gl.getProgramInfoLog(program));
7444
+ throw new Error(`program link failed: ${gl.getProgramInfoLog(program)}`);
7444
7445
  }
7445
7446
  // Full-screen quad
7446
7447
  const buf = gl.createBuffer();
@@ -7529,7 +7530,7 @@ void main() {
7529
7530
  variantId: String(visibleVariant),
7530
7531
  pageUrl: location.pathname,
7531
7532
  };
7532
- const acceptWrapper = document.querySelector('[data-monodesign-variants="' + currentSessionId + '"]');
7533
+ const acceptWrapper = document.querySelector(`[data-monodesign-variants="${currentSessionId}"]`);
7533
7534
  if (Object.keys(paramsCurrentValues).length > 0) {
7534
7535
  acceptPayload.paramValues = { ...paramsCurrentValues };
7535
7536
  }
@@ -7586,8 +7587,9 @@ void main() {
7586
7587
  }
7587
7588
 
7588
7589
  function scheduleAcceptCleanup(accepted) {
7589
- setTimeout(function() {
7590
+ setTimeout(() => {
7590
7591
  if (!accepted?.isSvelteComponent && !acceptedDomAlreadyClean(accepted)) {
7592
+ // biome-ignore lint/complexity/useArrowFunction: tests/live-browser-source.test.mjs pins this fallback as `setTimeout(function() {`
7591
7593
  setTimeout(function() {
7592
7594
  if (pendingAcceptedSession?.id !== accepted?.id) return;
7593
7595
  if (!accepted?.isSvelteComponent) ensureAcceptedDomClean(accepted);
@@ -7600,8 +7602,8 @@ void main() {
7600
7602
  }
7601
7603
 
7602
7604
  function snapshotAcceptedVariantDom(sessionId, variantId) {
7603
- const wrapper = document.querySelector('[data-monodesign-variants="' + sessionId + '"]');
7604
- const accepted = wrapper?.querySelector?.('[data-monodesign-variant="' + variantId + '"]');
7605
+ const wrapper = document.querySelector(`[data-monodesign-variants="${sessionId}"]`);
7606
+ const accepted = wrapper?.querySelector?.(`[data-monodesign-variant="${variantId}"]`);
7605
7607
  const root = accepted?.firstElementChild || null;
7606
7608
  return {
7607
7609
  acceptedHtml: accepted ? accepted.innerHTML : '',
@@ -7613,11 +7615,11 @@ void main() {
7613
7615
  }
7614
7616
 
7615
7617
  function selectorForAcceptedRoot(root) {
7616
- if (!root || !root.tagName) return '';
7618
+ if (!root?.tagName) return '';
7617
7619
  const tag = root.tagName.toLowerCase();
7618
7620
  const classes = [...(root.classList || [])].filter(Boolean);
7619
7621
  if (classes.length === 0) return tag;
7620
- return tag + classes.map((cls) => '.' + cssIdent(cls)).join('');
7622
+ return tag + classes.map((cls) => `.${cssIdent(cls)}`).join('');
7621
7623
  }
7622
7624
 
7623
7625
  function acceptedDomAlreadyClean(pending) {
@@ -7638,7 +7640,7 @@ void main() {
7638
7640
  }
7639
7641
  for (const wrapper of wrappers) {
7640
7642
  if (!wrapper?.isConnected) continue;
7641
- const accepted = wrapper.querySelector?.('[data-monodesign-variant="' + variantId + '"]');
7643
+ const accepted = wrapper.querySelector?.(`[data-monodesign-variant="${variantId}"]`);
7642
7644
  if (!accepted) {
7643
7645
  wrapper.remove();
7644
7646
  continue;
@@ -7656,7 +7658,9 @@ void main() {
7656
7658
  function findAcceptedRuntimeWrappers(sessionId) {
7657
7659
  if (!sessionId) return [];
7658
7660
  return [...new Set([
7661
+ // biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-source.test.mjs:344
7659
7662
  ...document.querySelectorAll('[data-monodesign-variants="' + sessionId + '"]'),
7663
+ // biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-source.test.mjs:344
7660
7664
  ...document.querySelectorAll('[data-monodesign-carbonize="' + sessionId + '"]'),
7661
7665
  ])];
7662
7666
  }
@@ -7685,7 +7689,7 @@ void main() {
7685
7689
 
7686
7690
  function reloadAfterMissingAcceptedDom(pending) {
7687
7691
  if (acceptedDomAlreadyClean(pending)) return;
7688
- if (pending?.id && document.querySelector('[data-monodesign-variants="' + pending.id + '"]')) return;
7692
+ if (pending?.id && document.querySelector(`[data-monodesign-variants="${pending.id}"]`)) return;
7689
7693
  location.reload();
7690
7694
  }
7691
7695
 
@@ -7707,28 +7711,6 @@ void main() {
7707
7711
  setLiveState('PICKING');
7708
7712
  }
7709
7713
 
7710
- function commitAcceptedVariantToDom(sessionId, variantId) {
7711
- const wrapper = document.querySelector('[data-monodesign-variants="' + sessionId + '"]');
7712
- if (!wrapper) return false;
7713
- const accepted = wrapper.querySelector('[data-monodesign-variant="' + variantId + '"]');
7714
- if (!accepted || !accepted.firstElementChild) return false;
7715
- const parent = wrapper.parentElement;
7716
- if (!parent) return false;
7717
-
7718
- const style = wrapper.querySelector('style[data-monodesign-css]');
7719
- if (style && !document.querySelector('style[data-monodesign-accepted-css="' + sessionId + '"]')) {
7720
- const promotedStyle = style.cloneNode(true);
7721
- promotedStyle.setAttribute('data-monodesign-accepted-css', sessionId);
7722
- parent.insertBefore(promotedStyle, wrapper);
7723
- }
7724
-
7725
- const committed = accepted.cloneNode(true);
7726
- committed.removeAttribute('hidden');
7727
- committed.style.display = 'contents';
7728
- parent.replaceChild(committed, wrapper);
7729
- return true;
7730
- }
7731
-
7732
7714
  function handleDiscard() {
7733
7715
  if (pendingApplyInFlight) { showManualApplyBusyToast(); return; }
7734
7716
  if (!currentSessionId) return;
@@ -7934,11 +7916,11 @@ void main() {
7934
7916
  // reconciler later tries to remove a wrapper we already removed.
7935
7917
  // Schedule a 2s fallback that does the manual swap only if HMR hasn't
7936
7918
  // replaced the wrapper by then (keeps static-server / no-HMR flows alive).
7937
- const wrapper = document.querySelector('[data-monodesign-variants="' + cleanupSessionId + '"]');
7919
+ const wrapper = document.querySelector(`[data-monodesign-variants="${cleanupSessionId}"]`);
7938
7920
  if (wrapper) wrapper.style.display = 'none';
7939
- setTimeout(function() {
7921
+ setTimeout(() => {
7940
7922
  if (!cleanupSessionId) return;
7941
- const lateWrapper = document.querySelector('[data-monodesign-variants="' + cleanupSessionId + '"]');
7923
+ const lateWrapper = document.querySelector(`[data-monodesign-variants="${cleanupSessionId}"]`);
7942
7924
  if (!lateWrapper) return;
7943
7925
  const orig = lateWrapper.querySelector('[data-monodesign-variant="original"]');
7944
7926
  if (orig) {
@@ -7990,17 +7972,17 @@ void main() {
7990
7972
  ? Math.max(16, window.innerHeight - barRect.top + 12)
7991
7973
  : 16;
7992
7974
  const currentToast = el('div', {
7993
- position: 'fixed', bottom: barTopFromBottom + 'px', left: '50%',
7975
+ position: 'fixed', bottom: `${barTopFromBottom}px`, left: '50%',
7994
7976
  transform: 'translateX(-50%) translateY(8px)',
7995
7977
  background: C.ink, color: C.white,
7996
7978
  fontFamily: FONT, fontSize: '12px',
7997
7979
  padding: '8px 16px', borderRadius: '8px',
7998
7980
  zIndex: Z.toast, opacity: '0',
7999
- transition: 'opacity 0.25s ' + EASE + ', transform 0.25s ' + EASE,
7981
+ transition: `opacity 0.25s ${EASE}, transform 0.25s ${EASE}`,
8000
7982
  pointerEvents: 'none', maxWidth: '420px', textAlign: 'center',
8001
7983
  });
8002
7984
  toastEl = currentToast;
8003
- currentToast.id = PREFIX + '-toast';
7985
+ currentToast.id = `${PREFIX}-toast`;
8004
7986
  currentToast.textContent = message;
8005
7987
  uiAppend(currentToast);
8006
7988
  requestAnimationFrame(() => {
@@ -8085,6 +8067,7 @@ void main() {
8085
8067
  }
8086
8068
 
8087
8069
  currentSessionId = sessionId;
8070
+ // biome-ignore lint/correctness/useParseIntRadix: data-monodesign-variant-count can be hand-written in page source (reference/live.md), so a 0x value is not provably excluded
8088
8071
  expectedVariants = parseInt(wrapper.dataset.monodesignVariantCount || '0');
8089
8072
  const variants = wrapper.querySelectorAll('[data-monodesign-variant]:not([data-monodesign-variant="original"])');
8090
8073
  arrivedVariants = variants.length;
@@ -8214,14 +8197,6 @@ void main() {
8214
8197
  } catch { /* ignore */ }
8215
8198
  }
8216
8199
 
8217
- function loadPickPref() {
8218
- return loadInteractionPrefs().pickActive;
8219
- }
8220
-
8221
- function savePickPref() {
8222
- saveInteractionPrefs();
8223
- }
8224
-
8225
8200
  let pickActive = loadInteractionPrefs().pickActive;
8226
8201
  let insertActive = loadInteractionPrefs().insertActive;
8227
8202
  let configureKind = 'replace';
@@ -8268,7 +8243,6 @@ void main() {
8268
8243
  /** @type {{ mode: 'steer'|'configure', input: HTMLInputElement, submit: () => void, beforeStart?: () => void } | null} */
8269
8244
  let voiceCtx = null;
8270
8245
  const PAGE_CHAT_COLLAPSED_W = '104px';
8271
- const PAGE_CHAT_PROCESSING_W = '76px';
8272
8246
  const PAGE_CHAT_PLACEHOLDER_COLLAPSED = 'Steer…';
8273
8247
  const PAGE_CHAT_PLACEHOLDER_EXPANDED = 'Steer the page…';
8274
8248
  const STEER_AWAIT_TIMEOUT_MS = 120000;
@@ -8360,10 +8334,10 @@ void main() {
8360
8334
 
8361
8335
  function globalBarModeToggles() {
8362
8336
  return [
8363
- uiGetById(PREFIX + '-pick-toggle'),
8364
- uiGetById(PREFIX + '-insert-toggle'),
8365
- uiGetById(PREFIX + '-detect-toggle'),
8366
- uiGetById(PREFIX + '-design-toggle'),
8337
+ uiGetById(`${PREFIX}-pick-toggle`),
8338
+ uiGetById(`${PREFIX}-insert-toggle`),
8339
+ uiGetById(`${PREFIX}-detect-toggle`),
8340
+ uiGetById(`${PREFIX}-design-toggle`),
8367
8341
  ].filter(Boolean);
8368
8342
  }
8369
8343
 
@@ -8390,13 +8364,13 @@ void main() {
8390
8364
  }
8391
8365
 
8392
8366
  function pageChatExpandedWidth() {
8393
- if (!pageChatEl || !globalBarEl) return PAGE_CHAT_EXPANDED_MAX_W + 'px';
8367
+ if (!pageChatEl || !globalBarEl) return `${PAGE_CHAT_EXPANDED_MAX_W}px`;
8394
8368
  const currentChatWidth = pageChatEl.getBoundingClientRect().width || pageChatCollapsedWidthPx();
8395
8369
  const barWidth = Math.max(globalBarEl.getBoundingClientRect().width || 0, globalBarEl.scrollWidth || 0);
8396
8370
  const nonChatWidth = Math.max(0, barWidth - currentChatWidth);
8397
8371
  const available = window.innerWidth - 16 - nonChatWidth;
8398
8372
  const next = Math.max(pageChatCollapsedWidthPx(), Math.min(PAGE_CHAT_EXPANDED_MAX_W, available));
8399
- return Math.round(next) + 'px';
8373
+ return `${Math.round(next)}px`;
8400
8374
  }
8401
8375
 
8402
8376
  function syncPageChatExpandedWidth() {
@@ -8549,7 +8523,7 @@ void main() {
8549
8523
  function steerFocusTargetLabel(el) {
8550
8524
  if (!el || el === document.body) return 'body';
8551
8525
  if (el === document.documentElement) return 'html';
8552
- if (el.id) return el.tagName.toLowerCase() + '#' + el.id;
8526
+ if (el.id) return `${el.tagName.toLowerCase()}#${el.id}`;
8553
8527
  return el.tagName?.toLowerCase() || String(el);
8554
8528
  }
8555
8529
 
@@ -8582,7 +8556,7 @@ void main() {
8582
8556
 
8583
8557
  function focusConfigureInput(reason) {
8584
8558
  steerFocusLog('focusConfigureInput', { reason });
8585
- const inputId = configureKind === 'insert' ? PREFIX + '-insert-input' : PREFIX + '-input';
8559
+ const inputId = configureKind === 'insert' ? `${PREFIX}-insert-input` : `${PREFIX}-input`;
8586
8560
  const input = uiGetById(inputId);
8587
8561
  if (!input) {
8588
8562
  steerFocusLog('focusConfigureInput missing', { reason });
@@ -8689,8 +8663,8 @@ void main() {
8689
8663
  display: 'inline-block',
8690
8664
  width: '4px', height: '4px', borderRadius: '50%',
8691
8665
  background: P.patinaPale,
8692
- boxShadow: '0 0 6px ' + P.patinaSoft,
8693
- animation: 'monodesign-steer-dot 1.05s ease-in-out ' + (i * 0.14) + 's infinite',
8666
+ boxShadow: `0 0 6px ${P.patinaSoft}`,
8667
+ animation: `monodesign-steer-dot 1.05s ease-in-out ${i * 0.14}s infinite`,
8694
8668
  }));
8695
8669
  }
8696
8670
  return wrap;
@@ -8734,7 +8708,7 @@ void main() {
8734
8708
  return true;
8735
8709
  }
8736
8710
 
8737
- function focusPageChatInput(reason) {
8711
+ function focusPageChatInput(_reason) {
8738
8712
  if (!preparePageChatInputForTyping() || steerLocked) return false;
8739
8713
  try { pageChatInput.focus({ preventScroll: true }); } catch { pageChatInput.focus(); }
8740
8714
  const focused = activeElementDeep() === pageChatInput;
@@ -8876,7 +8850,7 @@ void main() {
8876
8850
  case 'aborted':
8877
8851
  return null;
8878
8852
  default:
8879
- return 'Voice input failed (' + code + ')';
8853
+ return `Voice input failed (${code})`;
8880
8854
  }
8881
8855
  }
8882
8856
 
@@ -8894,7 +8868,7 @@ void main() {
8894
8868
  } else if (voiceCtx?.mode === 'configure') {
8895
8869
  // The bar shows either the replace row's voice button or the insert
8896
8870
  // row's - both run voice through the 'configure' mode.
8897
- const voiceBtn = uiGetById(PREFIX + '-configure-voice') || uiGetById(PREFIX + '-insert-voice');
8871
+ const voiceBtn = uiGetById(`${PREFIX}-configure-voice`) || uiGetById(`${PREFIX}-insert-voice`);
8898
8872
  if (voiceBtn) {
8899
8873
  voiceBtn.dataset.active = listening ? 'true' : 'false';
8900
8874
  voiceBtn.dataset.listening = listening ? 'true' : 'false';
@@ -8906,7 +8880,7 @@ void main() {
8906
8880
  }
8907
8881
 
8908
8882
  function releaseVoiceEngine(opts) {
8909
- if (opts && opts.suppressSubmit) voiceSuppressSubmit = true;
8883
+ if (opts?.suppressSubmit) voiceSuppressSubmit = true;
8910
8884
  const rec = voiceRecognition;
8911
8885
  voiceRecognition = null;
8912
8886
  if (!rec) return;
@@ -8915,7 +8889,7 @@ void main() {
8915
8889
  rec.onerror = null;
8916
8890
  rec.onend = null;
8917
8891
  try {
8918
- if (opts && opts.abort) rec.abort();
8892
+ if (opts?.abort) rec.abort();
8919
8893
  else rec.stop();
8920
8894
  } catch { /* already ended */ }
8921
8895
  }
@@ -8924,7 +8898,7 @@ void main() {
8924
8898
  releaseVoiceEngine(opts);
8925
8899
  syncVoiceUi(false);
8926
8900
  voiceCtx = null;
8927
- if (opts && opts.message) showToast(String(opts.message), opts.duration || 4000);
8901
+ if (opts?.message) showToast(String(opts.message), opts.duration || 4000);
8928
8902
  }
8929
8903
 
8930
8904
  function finishVoiceSession() {
@@ -8965,7 +8939,7 @@ void main() {
8965
8939
  if (ctx.beforeStart) ctx.beforeStart();
8966
8940
 
8967
8941
  voiceInterimBase = ctx.input.value.trim()
8968
- ? ctx.input.value.trim() + ' '
8942
+ ? `${ctx.input.value.trim()} `
8969
8943
  : '';
8970
8944
 
8971
8945
  const rec = new Ctor();
@@ -9028,7 +9002,7 @@ void main() {
9028
9002
 
9029
9003
  function configureVoiceContext() {
9030
9004
  const input = uiGetById(
9031
- configureKind === 'insert' ? PREFIX + '-insert-input' : PREFIX + '-input',
9005
+ configureKind === 'insert' ? `${PREFIX}-insert-input` : `${PREFIX}-input`,
9032
9006
  );
9033
9007
  return {
9034
9008
  mode: 'configure',
@@ -9099,7 +9073,7 @@ void main() {
9099
9073
  }
9100
9074
 
9101
9075
  function expandPageChat(opts) {
9102
- const focus = !opts || opts.focus !== false;
9076
+ const focus = opts?.focus !== false;
9103
9077
  if (!pageChatEl || !pageChatInput || steerLocked) return;
9104
9078
  preparePageChatInputForTyping();
9105
9079
  syncPageChatChrome();
@@ -9134,7 +9108,7 @@ void main() {
9134
9108
  function initPageChat(parent, P) {
9135
9109
  pageChatEl = el('div', {
9136
9110
  display: 'inline-flex', alignItems: 'center',
9137
- height: '28px', margin: '0 4px 0 ' + (GLOBAL_BAR_SECTION_GAP - GLOBAL_BAR_INNER_GAP) + 'px',
9111
+ height: '28px', margin: `0 4px 0 ${GLOBAL_BAR_SECTION_GAP - GLOBAL_BAR_INNER_GAP}px`,
9138
9112
  borderRadius: '7px',
9139
9113
  background: P.chatSurface,
9140
9114
  border: '1px solid transparent',
@@ -9144,6 +9118,7 @@ void main() {
9144
9118
  width: PAGE_CHAT_COLLAPSED_W,
9145
9119
  transition: 'border-color 0.15s ease',
9146
9120
  });
9121
+ // biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-regression.test.mjs:388
9147
9122
  pageChatEl.id = PREFIX + '-page-chat';
9148
9123
  pageChatEl.dataset.expanded = 'false';
9149
9124
  pageChatEl.title = 'Steer the page';
@@ -9166,7 +9141,7 @@ void main() {
9166
9141
  pageChatHint.textContent = 'Steer';
9167
9142
 
9168
9143
  pageChatInput = document.createElement('input');
9169
- pageChatInput.id = PREFIX + '-page-chat-input';
9144
+ pageChatInput.id = `${PREFIX}-page-chat-input`;
9170
9145
  pageChatInput.type = 'text';
9171
9146
  pageChatInput.placeholder = PAGE_CHAT_PLACEHOLDER_COLLAPSED;
9172
9147
  pageChatInput.setAttribute('aria-label', 'Steer the page');
@@ -9187,7 +9162,7 @@ void main() {
9187
9162
  color: P.textDim, cursor: 'pointer',
9188
9163
  transition: 'color 0.12s ease, background 0.12s ease',
9189
9164
  });
9190
- pageChatVoiceBtn.id = PREFIX + '-page-chat-voice';
9165
+ pageChatVoiceBtn.id = `${PREFIX}-page-chat-voice`;
9191
9166
  pageChatVoiceBtn.type = 'button';
9192
9167
  pageChatVoiceBtn.setAttribute('aria-label', 'Voice input');
9193
9168
  pageChatVoiceBtn.innerHTML = ICON_PAGE_VOICE;
@@ -9197,9 +9172,9 @@ void main() {
9197
9172
  pageChatEl.appendChild(pageChatInput);
9198
9173
  pageChatEl.appendChild(pageChatVoiceBtn);
9199
9174
 
9200
- if (!uiGetById(PREFIX + '-page-chat-style')) {
9175
+ if (!uiGetById(`${PREFIX}-page-chat-style`)) {
9201
9176
  const s = document.createElement('style');
9202
- s.id = PREFIX + '-page-chat-style';
9177
+ s.id = `${PREFIX}-page-chat-style`;
9203
9178
  s.textContent =
9204
9179
  '@keyframes monodesign-steer-dot { 0%, 70%, 100% { opacity: 0.28; transform: scale(0.82); } 35% { opacity: 1; transform: scale(1); } }' +
9205
9180
  '@keyframes monodesign-steer-processing { 0%, 100% { border-color: oklch(70% 0.12 188 / 0.28); box-shadow: 0 0 0 0 oklch(70% 0.12 188 / 0); } 50% { border-color: oklch(82% 0.07 188 / 0.55); box-shadow: 0 0 14px oklch(70% 0.12 188 / 0.18); } }' +
@@ -9328,7 +9303,7 @@ void main() {
9328
9303
  padding: '6px 9px',
9329
9304
  borderRadius: '7px',
9330
9305
  background: P.chatSurface,
9331
- border: '1px solid ' + P.hairline,
9306
+ border: `1px solid ${P.hairline}`,
9332
9307
  boxShadow: P.shadow,
9333
9308
  color: P.text,
9334
9309
  fontFamily: FONT,
@@ -9338,7 +9313,7 @@ void main() {
9338
9313
  letterSpacing: '0.01em',
9339
9314
  whiteSpace: 'normal',
9340
9315
  });
9341
- agentPollTooltipEl.id = PREFIX + '-agent-poll-tooltip';
9316
+ agentPollTooltipEl.id = `${PREFIX}-agent-poll-tooltip`;
9342
9317
  agentPollTooltipEl.textContent = AGENT_DISCONNECTED_TIP;
9343
9318
  uiAppend(agentPollTooltipEl);
9344
9319
  return agentPollTooltipEl;
@@ -9355,8 +9330,8 @@ void main() {
9355
9330
  const tipH = tip.offsetHeight;
9356
9331
  const left = Math.max(8, Math.min(window.innerWidth - tipW - 8, r.left + r.width / 2 - tipW / 2));
9357
9332
  const top = Math.max(8, r.top - tipH - 8);
9358
- tip.style.left = left + 'px';
9359
- tip.style.top = top + 'px';
9333
+ tip.style.left = `${left}px`;
9334
+ tip.style.top = `${top}px`;
9360
9335
  }
9361
9336
 
9362
9337
  function hideAgentPollTooltip() {
@@ -9373,7 +9348,7 @@ void main() {
9373
9348
  }
9374
9349
 
9375
9350
  function fetchAgentPollingStatus() {
9376
- fetch('http://localhost:' + PORT + '/status?token=' + TOKEN, { cache: 'no-store' })
9351
+ fetch(`http://localhost:${PORT}/status?token=${TOKEN}`, { cache: 'no-store' })
9377
9352
  .then((res) => (res.ok ? res.json() : null))
9378
9353
  .then((data) => {
9379
9354
  if (data && typeof data.agentPolling === 'boolean') syncAgentPollingUi(data.agentPolling);
@@ -9394,9 +9369,9 @@ void main() {
9394
9369
  // Custom focus-visible for bar buttons. Browser default is a heavy
9395
9370
  // blue ring that looks jarring on the dark capsule. Replace with a
9396
9371
  // soft accent-tinted inner ring that respects the bar's palette.
9397
- if (!uiGetById(PREFIX + '-bar-focus-style')) {
9372
+ if (!uiGetById(`${PREFIX}-bar-focus-style`)) {
9398
9373
  const s = document.createElement('style');
9399
- s.id = PREFIX + '-bar-focus-style';
9374
+ s.id = `${PREFIX}-bar-focus-style`;
9400
9375
  s.textContent =
9401
9376
  '#' + PREFIX + '-global-bar button:focus { outline: none; }' +
9402
9377
  '#' + PREFIX + '-global-bar button:focus-visible {' +
@@ -9417,7 +9392,7 @@ void main() {
9417
9392
  gap: '0',
9418
9393
  width: 'max-content',
9419
9394
  background: P.surface,
9420
- border: '1px solid ' + P.border,
9395
+ border: `1px solid ${P.border}`,
9421
9396
  borderRadius: '8px',
9422
9397
  boxShadow: P.shadow,
9423
9398
  fontFamily: FONT, fontSize: '12px', lineHeight: '1',
@@ -9425,21 +9400,21 @@ void main() {
9425
9400
  overflow: 'hidden', // clip the full-bleed brand mark to the bar radius
9426
9401
  maxWidth: 'calc(100vw - 16px)',
9427
9402
  boxSizing: 'border-box',
9428
- transition: 'opacity 0.3s ' + EASE + ', transform 0.3s ' + EASE,
9403
+ transition: `opacity 0.3s ${EASE}, transform 0.3s ${EASE}`,
9429
9404
  });
9430
- globalBarEl.id = PREFIX + '-global-bar';
9405
+ globalBarEl.id = `${PREFIX}-global-bar`;
9431
9406
  globalBarEl.dataset.theme = theme;
9432
9407
 
9433
9408
  // Brand mark - kinpaku Monodesign icon (site header / favicon paths).
9434
9409
  const brand = el('span', {
9435
9410
  display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
9436
9411
  alignSelf: 'stretch', position: 'relative',
9437
- padding: '0 ' + (GLOBAL_BAR_SECTION_GAP - GLOBAL_BAR_INNER_PAD_LEFT) + 'px 0 14px',
9412
+ padding: `0 ${GLOBAL_BAR_SECTION_GAP - GLOBAL_BAR_INNER_PAD_LEFT}px 0 14px`,
9438
9413
  background: 'transparent',
9439
9414
  color: P.accent,
9440
9415
  flexShrink: '0',
9441
9416
  });
9442
- brand.id = PREFIX + '-global-bar-brand';
9417
+ brand.id = `${PREFIX}-global-bar-brand`;
9443
9418
  brand.dataset.agentConnected = 'false';
9444
9419
  brand.setAttribute('role', 'img');
9445
9420
  brand.setAttribute('aria-label', 'Monodesign live mode - agent not polling');
@@ -9455,7 +9430,7 @@ void main() {
9455
9430
  position: 'absolute', right: '-1px', bottom: '7px',
9456
9431
  width: '6px', height: '6px', borderRadius: '50%',
9457
9432
  background: 'oklch(77% 0.13 82)',
9458
- boxShadow: '0 0 0 2px ' + P.surface,
9433
+ boxShadow: `0 0 0 2px ${P.surface}`,
9459
9434
  display: 'none', pointerEvents: 'none',
9460
9435
  });
9461
9436
  agentDot.dataset.agentDot = 'true';
@@ -9472,10 +9447,10 @@ void main() {
9472
9447
  // Inner wrapper: holds the toggles with normal bar padding.
9473
9448
  const inner = el('div', {
9474
9449
  display: 'flex', alignItems: 'center',
9475
- padding: '4px 5px 4px ' + GLOBAL_BAR_INNER_PAD_LEFT + 'px', gap: GLOBAL_BAR_INNER_GAP + 'px',
9450
+ padding: `4px 5px 4px ${GLOBAL_BAR_INNER_PAD_LEFT}px`, gap: `${GLOBAL_BAR_INNER_GAP}px`,
9476
9451
  flex: '0 0 auto',
9477
9452
  });
9478
- inner.id = PREFIX + '-global-bar-inner';
9453
+ inner.id = `${PREFIX}-global-bar-inner`;
9479
9454
  globalBarEl.appendChild(inner);
9480
9455
 
9481
9456
  // Button factory: icon-only at rest, label slides in on hover/active.
@@ -9522,7 +9497,7 @@ void main() {
9522
9497
 
9523
9498
  // Pick toggle - restored from localStorage; both pick and insert may be off.
9524
9499
  const pickBtn = makeIconBtn({
9525
- id: PREFIX + '-pick-toggle',
9500
+ id: `${PREFIX}-pick-toggle`,
9526
9501
  svg: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="flex-shrink:0"><circle cx="12" cy="12" r="10"/><line x1="22" y1="12" x2="18" y2="12"/><line x1="6" y1="12" x2="2" y2="12"/><line x1="12" y1="6" x2="12" y2="2"/><line x1="12" y1="22" x2="12" y2="18"/></svg>',
9527
9502
  label: 'Pick',
9528
9503
  ariaLabel: 'Pick element',
@@ -9531,6 +9506,7 @@ void main() {
9531
9506
  inner.appendChild(pickBtn);
9532
9507
 
9533
9508
  const insertBtn = makeIconBtn({
9509
+ // biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-regression.test.mjs:620
9534
9510
  id: PREFIX + '-insert-toggle',
9535
9511
  svg: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="flex-shrink:0"><path d="M12 5v14"/><path d="M5 12h14"/></svg>',
9536
9512
  label: 'Insert',
@@ -9541,7 +9517,7 @@ void main() {
9541
9517
 
9542
9518
  // Detect toggle
9543
9519
  const detectBtn = makeIconBtn({
9544
- id: PREFIX + '-detect-toggle',
9520
+ id: `${PREFIX}-detect-toggle`,
9545
9521
  svg: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="flex-shrink:0"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>',
9546
9522
  label: 'Detect',
9547
9523
  ariaLabel: 'Detect anti-patterns',
@@ -9553,13 +9529,13 @@ void main() {
9553
9529
  background: P.accent, color: C.ink,
9554
9530
  display: 'none', fontFamily: MONO, marginLeft: '4px',
9555
9531
  });
9556
- detectBadge.id = PREFIX + '-detect-badge';
9532
+ detectBadge.id = `${PREFIX}-detect-badge`;
9557
9533
  detectBtn.appendChild(detectBadge);
9558
9534
  inner.appendChild(detectBtn);
9559
9535
 
9560
9536
  // DESIGN.md panel toggle - quartet of color squares as the mark.
9561
9537
  const designBtn = makeIconBtn({
9562
- id: PREFIX + '-design-toggle',
9538
+ id: `${PREFIX}-design-toggle`,
9563
9539
  svg: `<span style="display:inline-grid;grid-template-columns:1fr 1fr;grid-template-rows:1fr 1fr;width:14px;height:14px;border-radius:3px;overflow:hidden;box-shadow:inset 0 0 0 1px oklch(92% 0 0 / 0.13);flex-shrink:0">
9564
9540
  <span style="background:oklch(84% 0.19 80.46)"></span>
9565
9541
  <span style="background:oklch(70% 0.12 188)"></span>
@@ -9589,7 +9565,7 @@ void main() {
9589
9565
  fontFamily: FONT,
9590
9566
  pointerEvents: 'auto',
9591
9567
  });
9592
- pendingDockEl.id = PREFIX + '-pending-dock';
9568
+ pendingDockEl.id = `${PREFIX}-pending-dock`;
9593
9569
 
9594
9570
  pendingPillEl = el('button', {
9595
9571
  display: 'none',
@@ -9666,7 +9642,7 @@ void main() {
9666
9642
  justifyContent: 'center',
9667
9643
  padding: '0', boxSizing: 'border-box',
9668
9644
  width: '30px', height: '30px', borderRadius: '999px',
9669
- border: '1px solid ' + P.hairline,
9645
+ border: `1px solid ${P.hairline}`,
9670
9646
  background: P.chatSurface,
9671
9647
  color: P.textDim,
9672
9648
  overflow: 'visible',
@@ -9692,7 +9668,7 @@ void main() {
9692
9668
  lineHeight: '1',
9693
9669
  whiteSpace: 'nowrap',
9694
9670
  textAlign: 'center',
9695
- transition: 'opacity 0.16s ease, transform 0.18s ' + EASE,
9671
+ transition: `opacity 0.16s ease, transform 0.18s ${EASE}`,
9696
9672
  });
9697
9673
  pendingTrashTooltipEl.textContent = 'Discard copy edits';
9698
9674
  pendingTrashTooltipEl.setAttribute('role', 'tooltip');
@@ -9725,7 +9701,7 @@ void main() {
9725
9701
  height: '30px',
9726
9702
  padding: '0 12px',
9727
9703
  borderRadius: '999px',
9728
- border: '1px solid ' + (accent ? P.accent : P.hairline),
9704
+ border: `1px solid ${accent ? P.accent : P.hairline}`,
9729
9705
  background: accent ? P.accent : P.chatSurface,
9730
9706
  color: accent ? C.ink : P.textDim,
9731
9707
  fontFamily: FONT,
@@ -9778,7 +9754,7 @@ void main() {
9778
9754
  color: P.textDim, fontFamily: FONT, fontSize: '0', lineHeight: '0',
9779
9755
  cursor: 'pointer', transition: 'color 0.12s ease, background 0.12s ease',
9780
9756
  });
9781
- exitBtn.id = PREFIX + '-exit';
9757
+ exitBtn.id = `${PREFIX}-exit`;
9782
9758
  exitBtn.innerHTML = '<svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><line x1="3" y1="3" x2="11" y2="11"/><line x1="11" y1="3" x2="3" y2="11"/></svg>';
9783
9759
  exitBtn.title = 'Exit live mode';
9784
9760
  exitBtn.addEventListener('mouseenter', () => { exitBtn.style.color = 'oklch(58% 0.15 35)'; exitBtn.style.background = P.exitHover; });
@@ -9827,11 +9803,11 @@ void main() {
9827
9803
  }
9828
9804
 
9829
9805
  function updateGlobalBarState() {
9830
- const detectToggle = uiGetById(PREFIX + '-detect-toggle');
9831
- const detectBadge = uiGetById(PREFIX + '-detect-badge');
9832
- const pickToggle = uiGetById(PREFIX + '-pick-toggle');
9833
- const insertToggle = uiGetById(PREFIX + '-insert-toggle');
9834
- const designToggle = uiGetById(PREFIX + '-design-toggle');
9806
+ const detectToggle = uiGetById(`${PREFIX}-detect-toggle`);
9807
+ const detectBadge = uiGetById(`${PREFIX}-detect-badge`);
9808
+ const pickToggle = uiGetById(`${PREFIX}-pick-toggle`);
9809
+ const insertToggle = uiGetById(`${PREFIX}-insert-toggle`);
9810
+ const designToggle = uiGetById(`${PREFIX}-design-toggle`);
9835
9811
  const theme = globalBarEl?.dataset.theme || 'light';
9836
9812
  const P = barPaletteForTheme(theme);
9837
9813
 
@@ -9860,6 +9836,7 @@ void main() {
9860
9836
  // If the bar is currently under the cursor, keep all labels expanded -
9861
9837
  // otherwise clicking a toggle that deactivates (e.g. closing DESIGN.md)
9862
9838
  // would collapse its label while the user's mouse is still on the bar.
9839
+ // biome-ignore lint/complexity/useOptionalChain: `?.` would pass undefined instead of null, which switches syncGlobalBarExpandedLabels onto its default-parameter path
9863
9840
  syncGlobalBarExpandedLabels(globalBarEl && globalBarEl.matches(':hover'));
9864
9841
 
9865
9842
  if (detectBadge) {
@@ -9964,7 +9941,7 @@ void main() {
9964
9941
  if (detectScriptLoaded) return;
9965
9942
  detectScriptLoaded = true;
9966
9943
  const s = document.createElement('script');
9967
- s.src = 'http://localhost:' + PORT + '/detect.js';
9944
+ s.src = `http://localhost:${PORT}/detect.js`;
9968
9945
  s.dataset.monodesignExtension = 'true';
9969
9946
  document.head.appendChild(s);
9970
9947
  }
@@ -10039,7 +10016,7 @@ void main() {
10039
10016
  if (tooltipEl) { tooltipEl.remove(); tooltipEl = null; }
10040
10017
  if (barEl) { barEl.remove(); barEl = null; }
10041
10018
  if (pickerEl) { pickerEl.remove(); pickerEl = null; }
10042
- if (paramsPanelEl) { paramsPanelEl.remove(); paramsPanelEl = null; paramsPanelInner = null; paramsPanelBody = null; }
10019
+ if (paramsPanelEl) { paramsPanelEl.remove(); paramsPanelEl = null; paramsPanelBody = null; }
10043
10020
  if (editBadgeProxyRoot) { editBadgeProxyRoot.remove(); editBadgeProxyRoot = null; editBadgeProxyByTarget = new Map(); }
10044
10021
  if (evtSource) { evtSource.close(); evtSource = null; }
10045
10022
  document.removeEventListener('mousemove', handleMouseMove, true);
@@ -10064,7 +10041,7 @@ void main() {
10064
10041
 
10065
10042
  let designHost = null;
10066
10043
  let designShadow = null;
10067
- let designState = {
10044
+ const designState = {
10068
10045
  open: false,
10069
10046
  tab: 'visual', // 'visual' | 'raw'
10070
10047
  parsed: null, // parseDesignMd output (frontmatter + body sections)
@@ -10106,7 +10083,7 @@ void main() {
10106
10083
 
10107
10084
  function initDesignPanel() {
10108
10085
  designHost = document.createElement('div');
10109
- designHost.id = PREFIX + '-design-host';
10086
+ designHost.id = `${PREFIX}-design-host`;
10110
10087
  Object.assign(designHost.style, {
10111
10088
  position: 'fixed', top: '0', left: '0',
10112
10089
  width: '0', height: '0',
@@ -10674,7 +10651,7 @@ void main() {
10674
10651
  }
10675
10652
 
10676
10653
  function findProseDescription(proseColors, key, displayName) {
10677
- if (!proseColors || !proseColors.groups) return null;
10654
+ if (!proseColors?.groups) return null;
10678
10655
  const needles = [key, displayName].filter(Boolean).map((s) => s.toLowerCase());
10679
10656
  for (const g of proseColors.groups) {
10680
10657
  for (const c of g.colors || []) {
@@ -10773,7 +10750,7 @@ void main() {
10773
10750
  // The system's actual sample size for this role, shown as small mono meta below.
10774
10751
  if (t.sampleSize) {
10775
10752
  const scale = document.createElement('div');
10776
- scale.style.cssText = 'font-family:' + MONO + '; font-size: 10px; color:' + DP.meta + '; margin-top: 2px;';
10753
+ scale.style.cssText = `font-family:${MONO}; font-size: 10px; color:${DP.meta}; margin-top: 2px;`;
10777
10754
  scale.textContent = t.sampleSize;
10778
10755
  tile.appendChild(scale);
10779
10756
  }
@@ -10924,7 +10901,7 @@ void main() {
10924
10901
  const groups = [];
10925
10902
  for (const c of components) {
10926
10903
  const last = groups[groups.length - 1];
10927
- if (last && last[0].kind && c.kind === last[0].kind) {
10904
+ if (last?.[0].kind && c.kind === last[0].kind) {
10928
10905
  last.push(c);
10929
10906
  } else {
10930
10907
  groups.push([c]);
@@ -10933,7 +10910,7 @@ void main() {
10933
10910
  return groups;
10934
10911
  }
10935
10912
 
10936
- function titleForKind(kind, count) {
10913
+ function titleForKind(kind, _count) {
10937
10914
  const labels = {
10938
10915
  button: 'Buttons',
10939
10916
  input: 'Inputs',
@@ -10942,7 +10919,7 @@ void main() {
10942
10919
  card: 'Cards',
10943
10920
  custom: 'Components',
10944
10921
  };
10945
- return labels[kind] || (kind ? kind.charAt(0).toUpperCase() + kind.slice(1) + 's' : 'Components');
10922
+ return labels[kind] || (kind ? `${kind.charAt(0).toUpperCase() + kind.slice(1)}s` : 'Components');
10946
10923
  }
10947
10924
 
10948
10925
  // Collapsibles.
@@ -11018,7 +10995,7 @@ void main() {
11018
10995
  if (n.northStar) {
11019
10996
  const star = document.createElement('span');
11020
10997
  star.className = 'north-star';
11021
- star.textContent = '“' + n.northStar + '”';
10998
+ star.textContent = `“${n.northStar}”`;
11022
10999
  ov.appendChild(star);
11023
11000
  }
11024
11001
  if (n.overview) {
@@ -11165,10 +11142,6 @@ void main() {
11165
11142
  return s;
11166
11143
  }
11167
11144
 
11168
- function highlightBold(text) {
11169
- return inlineMd(text);
11170
- }
11171
-
11172
11145
  function escapeHtml(s) {
11173
11146
  return String(s)
11174
11147
  .replace(/&/g, '&amp;')
@@ -11182,7 +11155,7 @@ void main() {
11182
11155
  if (!text) return;
11183
11156
  try {
11184
11157
  navigator.clipboard.writeText(text);
11185
- showToast('Copied: ' + text);
11158
+ showToast(`Copied: ${text}`);
11186
11159
  } catch { /* ignore */ }
11187
11160
  }
11188
11161
 
@@ -11219,12 +11192,12 @@ void main() {
11219
11192
  if (!wrapper) return;
11220
11193
  scout.disconnect();
11221
11194
  if (resumeSession()) {
11222
- console.log('[monodesign] Resumed deferred session ' + currentSessionId + ' (post-hydration).');
11195
+ console.log(`[monodesign] Resumed deferred session ${currentSessionId} (post-hydration).`);
11223
11196
  }
11224
11197
  });
11225
11198
  scout.observe(document.body, { childList: true, subtree: true });
11226
11199
  } else {
11227
- console.log('[monodesign] Resumed active variant session ' + currentSessionId + ' (' + arrivedVariants + '/' + expectedVariants + ' variants).');
11200
+ console.log(`[monodesign] Resumed active variant session ${currentSessionId} (${arrivedVariants}/${expectedVariants} variants).`);
11228
11201
  }
11229
11202
 
11230
11203
  if (state === 'IDLE' && (pickActive || insertActive)) setLiveState('PICKING');