@mhosaic/feedback 0.32.0 → 0.33.0

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.
@@ -145,6 +145,32 @@ function createApiClient(options) {
145
145
  if (response.status === 404) return [];
146
146
  return readJsonArray(response, "listMine");
147
147
  }
148
+ async function diagnose(opts) {
149
+ const onLine = opts?.onLine ?? (typeof navigator !== "undefined" ? navigator.onLine : true);
150
+ if (onLine === false) return "offline";
151
+ const probeUrl = `${endpoint}/api/feedback/v1/widget-manifest/?pk=${encodeURIComponent(options.apiKey)}`;
152
+ let simple;
153
+ try {
154
+ simple = await fetcher(probeUrl, { method: "GET", redirect: "manual" });
155
+ } catch {
156
+ return "blocked";
157
+ }
158
+ if (simple.type === "opaqueredirect" || simple.status >= 300 && simple.status < 400) {
159
+ return "intercepted";
160
+ }
161
+ let authed;
162
+ try {
163
+ authed = await fetcher(probeUrl, {
164
+ method: "GET",
165
+ headers: { Authorization: `Bearer ${options.apiKey}` }
166
+ });
167
+ } catch {
168
+ return "preflight";
169
+ }
170
+ if (authed.status === 401 || authed.status === 403) return "key";
171
+ if (authed.status === 429) return "throttle";
172
+ return "healthy";
173
+ }
148
174
  async function listChangelog(externalId) {
149
175
  const response = await fetcher(
150
176
  `${endpoint}/api/feedback/v1/reports/widget/changelog/`,
@@ -330,6 +356,14 @@ function createApiClient(options) {
330
356
  checkVisibility,
331
357
  listMine,
332
358
  listChangelog,
359
+ diagnose,
360
+ endpointHost: (() => {
361
+ try {
362
+ return new URL(endpoint).host;
363
+ } catch {
364
+ return endpoint;
365
+ }
366
+ })(),
333
367
  getReport,
334
368
  getReportBySeq,
335
369
  addComment,
@@ -739,6 +773,15 @@ var DEFAULT_STRINGS = {
739
773
  "mine.empty.title": "No reports yet",
740
774
  "mine.empty.body": "Once you send feedback you can follow the thread here.",
741
775
  "mine.refresh": "Refresh",
776
+ "diag.run": "Diagnose",
777
+ "diag.running": "Checking the connection\u2026",
778
+ "diag.offline": "You appear to be offline. Reconnect and retry.",
779
+ "diag.blocked": "The feedback service is unreachable from this network. A firewall or proxy is blocking it \u2014 ask IT to allow {host}.",
780
+ "diag.intercepted": "Your corporate network (SSL-inspection proxy) is intercepting widget traffic. Ask IT to add {host} to the inspection bypass list.",
781
+ "diag.preflight": "A network proxy is blocking the widget\u2019s secure requests (CORS preflight). Ask IT to allow {host}.",
782
+ "diag.key": "The widget\u2019s access key was rejected. Contact the site team.",
783
+ "diag.throttle": "Too many requests right now \u2014 wait a moment and retry.",
784
+ "diag.healthy": "The service is reachable \u2014 this looks like a temporary hiccup. Retry.",
742
785
  "mine.loading": "Loading\u2026",
743
786
  "mine.error": "Could not load your reports.",
744
787
  "mine.jump.placeholder": "#",
@@ -926,6 +969,15 @@ var FRENCH_STRINGS = {
926
969
  "mine.empty.title": "Aucun rapport",
927
970
  "mine.empty.body": "Apr\xE8s votre premier envoi vous pourrez suivre la conversation ici.",
928
971
  "mine.refresh": "Actualiser",
972
+ "diag.run": "Diagnostiquer",
973
+ "diag.running": "V\xE9rification de la connexion\u2026",
974
+ "diag.offline": "Vous semblez hors ligne. Reconnectez-vous puis r\xE9essayez.",
975
+ "diag.blocked": "Le service de feedback est injoignable depuis ce r\xE9seau. Un pare-feu ou proxy le bloque \u2014 demandez \xE0 votre TI d\u2019autoriser {host}.",
976
+ "diag.intercepted": "Votre r\xE9seau d\u2019entreprise (inspection SSL) intercepte le trafic du widget. Demandez \xE0 votre TI d\u2019ajouter {host} \xE0 la liste d\u2019exclusion.",
977
+ "diag.preflight": "Un proxy r\xE9seau bloque les requ\xEAtes s\xE9curis\xE9es du widget (pr\xE9flight CORS). Demandez \xE0 votre TI d\u2019autoriser {host}.",
978
+ "diag.key": "La cl\xE9 d\u2019acc\xE8s du widget a \xE9t\xE9 refus\xE9e. Contactez l\u2019\xE9quipe du site.",
979
+ "diag.throttle": "Trop de requ\xEAtes pour le moment \u2014 patientez puis r\xE9essayez.",
980
+ "diag.healthy": "Le service est joignable \u2014 le probl\xE8me semble passager. R\xE9essayez.",
929
981
  "mine.loading": "Chargement\u2026",
930
982
  "mine.error": "Impossible de charger vos rapports.",
931
983
  "mine.jump.placeholder": "#",
@@ -1017,7 +1069,7 @@ function resolveStrings(overrides, options = {}) {
1017
1069
 
1018
1070
  // src/widget/mount.tsx
1019
1071
  import { h, render } from "preact";
1020
- import { useCallback as useCallback2, useEffect as useEffect10, useRef as useRef7, useState as useState9 } from "preact/hooks";
1072
+ import { useCallback as useCallback2, useEffect as useEffect10, useRef as useRef7, useState as useState10 } from "preact/hooks";
1021
1073
 
1022
1074
  // src/widget/currentPage.ts
1023
1075
  function currentPagePath(opts) {
@@ -1050,7 +1102,30 @@ function onLocationChange(cb) {
1050
1102
  }
1051
1103
 
1052
1104
  // src/widget/BoardView.tsx
1053
- import { useEffect as useEffect2, useMemo, useState as useState2 } from "preact/hooks";
1105
+ import { useEffect as useEffect2, useMemo, useState as useState3 } from "preact/hooks";
1106
+
1107
+ // src/widget/DiagnosticHint.tsx
1108
+ import { useState } from "preact/hooks";
1109
+ import { jsx } from "preact/jsx-runtime";
1110
+ function DiagnosticHint({ api, strings, host }) {
1111
+ const [state, setState] = useState("idle");
1112
+ const run = async () => {
1113
+ setState("running");
1114
+ try {
1115
+ setState(await api.diagnose());
1116
+ } catch {
1117
+ setState("blocked");
1118
+ }
1119
+ };
1120
+ if (state === "idle") {
1121
+ return /* @__PURE__ */ jsx("button", { type: "button", class: "btn diag-btn", onClick: () => void run(), children: strings["diag.run"] });
1122
+ }
1123
+ if (state === "running") {
1124
+ return /* @__PURE__ */ jsx("div", { class: "diag-result", children: strings["diag.running"] });
1125
+ }
1126
+ const key = `diag.${state}`;
1127
+ return /* @__PURE__ */ jsx("div", { class: "diag-result", children: (strings[key] ?? state).replace("{host}", host) });
1128
+ }
1054
1129
 
1055
1130
  // src/widget/boardCache.ts
1056
1131
  var TTL_MS = 6e4;
@@ -1142,7 +1217,7 @@ function rateLimitMessage(err, strings) {
1142
1217
  }
1143
1218
 
1144
1219
  // src/widget/ReportDetailView.tsx
1145
- import { useEffect, useRef, useState } from "preact/hooks";
1220
+ import { useEffect, useRef, useState as useState2 } from "preact/hooks";
1146
1221
 
1147
1222
  // src/widget/linkifySeq.tsx
1148
1223
  import { jsxs } from "preact/jsx-runtime";
@@ -1179,7 +1254,7 @@ function linkifySeq(text, onOpenSeq) {
1179
1254
  }
1180
1255
 
1181
1256
  // src/widget/CommentBubble.tsx
1182
- import { jsx, jsxs as jsxs2 } from "preact/jsx-runtime";
1257
+ import { jsx as jsx2, jsxs as jsxs2 } from "preact/jsx-runtime";
1183
1258
  function CommentBubble({ comment, strings, onOpenSeq, stableUrl }) {
1184
1259
  const isMine = comment.is_mine;
1185
1260
  const isAgent = !isMine && comment.author_source === "mcp";
@@ -1189,23 +1264,23 @@ function CommentBubble({ comment, strings, onOpenSeq, stableUrl }) {
1189
1264
  const label = comment.author_label || strings[labelKey];
1190
1265
  const images = (comment.attachments ?? []).filter((a) => a.url);
1191
1266
  return /* @__PURE__ */ jsxs2("div", { class: `comment-bubble ${isMine ? "is-mine" : "is-other"}`, children: [
1192
- !isMine && label && /* @__PURE__ */ jsx("div", { class: `comment-author comment-author--${variant}`, children: label }),
1193
- comment.body && /* @__PURE__ */ jsx("div", { class: "comment-body", children: linkifySeq(comment.body, onOpenSeq) }),
1194
- images.length > 0 && /* @__PURE__ */ jsx("div", { class: "comment-attachments", children: images.map((a) => {
1267
+ !isMine && label && /* @__PURE__ */ jsx2("div", { class: `comment-author comment-author--${variant}`, children: label }),
1268
+ comment.body && /* @__PURE__ */ jsx2("div", { class: "comment-body", children: linkifySeq(comment.body, onOpenSeq) }),
1269
+ images.length > 0 && /* @__PURE__ */ jsx2("div", { class: "comment-attachments", children: images.map((a) => {
1195
1270
  const src = stableUrl ? stableUrl(`att:${a.id}`, a.url) : a.url;
1196
- return /* @__PURE__ */ jsx(
1271
+ return /* @__PURE__ */ jsx2(
1197
1272
  "a",
1198
1273
  {
1199
1274
  class: "comment-attachment",
1200
1275
  href: src,
1201
1276
  target: "_blank",
1202
1277
  rel: "noopener noreferrer",
1203
- children: /* @__PURE__ */ jsx("img", { src, alt: strings["detail.attachment_alt"], loading: "lazy" })
1278
+ children: /* @__PURE__ */ jsx2("img", { src, alt: strings["detail.attachment_alt"], loading: "lazy" })
1204
1279
  },
1205
1280
  a.id
1206
1281
  );
1207
1282
  }) }),
1208
- /* @__PURE__ */ jsx("div", { class: "comment-time", children: formatTime(comment.created_at) })
1283
+ /* @__PURE__ */ jsx2("div", { class: "comment-time", children: formatTime(comment.created_at) })
1209
1284
  ] });
1210
1285
  }
1211
1286
  function formatTime(iso) {
@@ -1260,7 +1335,7 @@ function safeExternalHref(url) {
1260
1335
  }
1261
1336
 
1262
1337
  // src/widget/ReportDetailView.tsx
1263
- import { Fragment, jsx as jsx2, jsxs as jsxs3 } from "preact/jsx-runtime";
1338
+ import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "preact/jsx-runtime";
1264
1339
  var POLL_MS = 3e4;
1265
1340
  function ReportDetailView({
1266
1341
  api,
@@ -1274,23 +1349,23 @@ function ReportDetailView({
1274
1349
  buildPermalink,
1275
1350
  seed
1276
1351
  }) {
1277
- const [detail, setDetail] = useState(null);
1278
- const [error, setError] = useState(null);
1279
- const [copied, setCopied] = useState(false);
1280
- const [editing, setEditing] = useState(false);
1281
- const [editBody, setEditBody] = useState("");
1282
- const [savingEdit, setSavingEdit] = useState(false);
1283
- const [editError, setEditError] = useState(false);
1284
- const [composeBody, setComposeBody] = useState("");
1285
- const [sending, setSending] = useState(false);
1286
- const [closing, setClosing] = useState(false);
1287
- const [reopening, setReopening] = useState(false);
1288
- const [composeShots, setComposeShots] = useState([]);
1289
- const [attachError, setAttachError] = useState("");
1352
+ const [detail, setDetail] = useState2(null);
1353
+ const [error, setError] = useState2(null);
1354
+ const [copied, setCopied] = useState2(false);
1355
+ const [editing, setEditing] = useState2(false);
1356
+ const [editBody, setEditBody] = useState2("");
1357
+ const [savingEdit, setSavingEdit] = useState2(false);
1358
+ const [editError, setEditError] = useState2(false);
1359
+ const [composeBody, setComposeBody] = useState2("");
1360
+ const [sending, setSending] = useState2(false);
1361
+ const [closing, setClosing] = useState2(false);
1362
+ const [reopening, setReopening] = useState2(false);
1363
+ const [composeShots, setComposeShots] = useState2([]);
1364
+ const [attachError, setAttachError] = useState2("");
1290
1365
  const fileInputRef = useRef(null);
1291
1366
  const mountedRef = useRef(true);
1292
1367
  const urlPins = useRef(/* @__PURE__ */ new Map());
1293
- const [, bumpPinTick] = useState(0);
1368
+ const [, bumpPinTick] = useState2(0);
1294
1369
  const PIN_MAX_AGE_MS = 45 * 6e4;
1295
1370
  const pinUrl = (key, url) => {
1296
1371
  if (!url) return url;
@@ -1474,7 +1549,7 @@ function ReportDetailView({
1474
1549
  };
1475
1550
  if (!detail && !error) {
1476
1551
  if (seed) {
1477
- const seedPill = /* @__PURE__ */ jsx2("span", { class: `pill pill-status pill-status--${seed.status}`, children: strings[`status.${seed.status}`] ?? seed.status });
1552
+ const seedPill = /* @__PURE__ */ jsx3("span", { class: `pill pill-status pill-status--${seed.status}`, children: strings[`status.${seed.status}`] ?? seed.status });
1478
1553
  return /* @__PURE__ */ jsxs3("div", { class: `report-detail variant-${variant} is-seeded`, children: [
1479
1554
  variant === "modal" && /* @__PURE__ */ jsxs3("div", { class: "report-detail-header", children: [
1480
1555
  /* @__PURE__ */ jsxs3("button", { type: "button", class: "btn", onClick: onBack, children: [
@@ -1500,19 +1575,19 @@ function ReportDetailView({
1500
1575
  seedPill
1501
1576
  ] }),
1502
1577
  /* @__PURE__ */ jsxs3("div", { class: "report-detail-body", children: [
1503
- /* @__PURE__ */ jsx2("div", { class: "report-detail-description-row", children: /* @__PURE__ */ jsx2("p", { class: "report-detail-description", children: linkifySeq(seed.description, onOpenSeq) }) }),
1504
- /* @__PURE__ */ jsx2("h3", { class: "report-detail-section", children: strings["detail.thread"] }),
1505
- /* @__PURE__ */ jsx2("div", { class: "mine-loading", children: strings["mine.loading"] })
1578
+ /* @__PURE__ */ jsx3("div", { class: "report-detail-description-row", children: /* @__PURE__ */ jsx3("p", { class: "report-detail-description", children: linkifySeq(seed.description, onOpenSeq) }) }),
1579
+ /* @__PURE__ */ jsx3("h3", { class: "report-detail-section", children: strings["detail.thread"] }),
1580
+ /* @__PURE__ */ jsx3("div", { class: "mine-loading", children: strings["mine.loading"] })
1506
1581
  ] })
1507
1582
  ] });
1508
1583
  }
1509
- return /* @__PURE__ */ jsx2("div", { class: "mine-loading", children: strings["mine.loading"] });
1584
+ return /* @__PURE__ */ jsx3("div", { class: "mine-loading", children: strings["mine.loading"] });
1510
1585
  }
1511
1586
  if (!detail) {
1512
1587
  if (error && error !== "load_failed") {
1513
1588
  return /* @__PURE__ */ jsxs3("div", { class: "report-detail-empty-state", role: "alert", children: [
1514
- /* @__PURE__ */ jsx2("p", { class: "report-detail-empty-state-body", children: error }),
1515
- /* @__PURE__ */ jsx2("button", { type: "button", class: "btn", onClick: () => void fetchDetail(), children: strings["board.retry"] }),
1589
+ /* @__PURE__ */ jsx3("p", { class: "report-detail-empty-state-body", children: error }),
1590
+ /* @__PURE__ */ jsx3("button", { type: "button", class: "btn", onClick: () => void fetchDetail(), children: strings["board.retry"] }),
1516
1591
  /* @__PURE__ */ jsxs3("button", { type: "button", class: "btn", onClick: onBack, children: [
1517
1592
  "\u2190 ",
1518
1593
  strings["detail.load_failed.cta"]
@@ -1520,8 +1595,8 @@ function ReportDetailView({
1520
1595
  ] });
1521
1596
  }
1522
1597
  return /* @__PURE__ */ jsxs3("div", { class: "report-detail-empty-state", role: "alert", children: [
1523
- /* @__PURE__ */ jsx2("p", { class: "report-detail-empty-state-title", children: strings["detail.load_failed.title"] }),
1524
- /* @__PURE__ */ jsx2("p", { class: "report-detail-empty-state-body", children: strings["detail.load_failed.body"] }),
1598
+ /* @__PURE__ */ jsx3("p", { class: "report-detail-empty-state-title", children: strings["detail.load_failed.title"] }),
1599
+ /* @__PURE__ */ jsx3("p", { class: "report-detail-empty-state-body", children: strings["detail.load_failed.body"] }),
1525
1600
  /* @__PURE__ */ jsxs3("button", { type: "button", class: "btn", onClick: onBack, children: [
1526
1601
  "\u2190 ",
1527
1602
  strings["detail.load_failed.cta"]
@@ -1538,7 +1613,7 @@ function ReportDetailView({
1538
1613
  "\u2190 ",
1539
1614
  strings["detail.back"]
1540
1615
  ] }),
1541
- /* @__PURE__ */ jsx2("span", { class: `pill pill-status pill-status--${detail.status}`, children: strings[`status.${detail.status}`] ?? detail.status })
1616
+ /* @__PURE__ */ jsx3("span", { class: `pill pill-status pill-status--${detail.status}`, children: strings[`status.${detail.status}`] ?? detail.status })
1542
1617
  ] }),
1543
1618
  variant === "board" && /* @__PURE__ */ jsxs3("div", { class: "report-detail-header report-detail-header--board", children: [
1544
1619
  /* @__PURE__ */ jsxs3(
@@ -1554,12 +1629,12 @@ function ReportDetailView({
1554
1629
  ]
1555
1630
  }
1556
1631
  ),
1557
- /* @__PURE__ */ jsx2("span", { class: `pill pill-status pill-status--${detail.status}`, children: strings[`status.${detail.status}`] ?? detail.status })
1632
+ /* @__PURE__ */ jsx3("span", { class: `pill pill-status pill-status--${detail.status}`, children: strings[`status.${detail.status}`] ?? detail.status })
1558
1633
  ] }),
1559
1634
  /* @__PURE__ */ jsxs3("div", { class: "report-detail-body", children: [
1560
- /* @__PURE__ */ jsx2(ContextBlock, { detail, strings }),
1635
+ /* @__PURE__ */ jsx3(ContextBlock, { detail, strings }),
1561
1636
  editing ? /* @__PURE__ */ jsxs3("div", { class: "report-detail-edit", children: [
1562
- /* @__PURE__ */ jsx2(
1637
+ /* @__PURE__ */ jsx3(
1563
1638
  "textarea",
1564
1639
  {
1565
1640
  class: "report-detail-edit-input",
@@ -1571,9 +1646,9 @@ function ReportDetailView({
1571
1646
  disabled: savingEdit
1572
1647
  }
1573
1648
  ),
1574
- editError && /* @__PURE__ */ jsx2("p", { class: "error", role: "alert", children: strings["detail.edit_failed"] }),
1649
+ editError && /* @__PURE__ */ jsx3("p", { class: "error", role: "alert", children: strings["detail.edit_failed"] }),
1575
1650
  /* @__PURE__ */ jsxs3("div", { class: "report-detail-edit-actions", children: [
1576
- /* @__PURE__ */ jsx2(
1651
+ /* @__PURE__ */ jsx3(
1577
1652
  "button",
1578
1653
  {
1579
1654
  type: "button",
@@ -1583,7 +1658,7 @@ function ReportDetailView({
1583
1658
  children: strings["detail.edit_cancel"]
1584
1659
  }
1585
1660
  ),
1586
- /* @__PURE__ */ jsx2(
1661
+ /* @__PURE__ */ jsx3(
1587
1662
  "button",
1588
1663
  {
1589
1664
  type: "button",
@@ -1595,8 +1670,8 @@ function ReportDetailView({
1595
1670
  )
1596
1671
  ] })
1597
1672
  ] }) : /* @__PURE__ */ jsxs3("div", { class: "report-detail-description-row", children: [
1598
- /* @__PURE__ */ jsx2("p", { class: "report-detail-description", children: linkifySeq(detail.description, onOpenSeq) }),
1599
- isMine && /* @__PURE__ */ jsx2(
1673
+ /* @__PURE__ */ jsx3("p", { class: "report-detail-description", children: linkifySeq(detail.description, onOpenSeq) }),
1674
+ isMine && /* @__PURE__ */ jsx3(
1600
1675
  "button",
1601
1676
  {
1602
1677
  type: "button",
@@ -1606,7 +1681,7 @@ function ReportDetailView({
1606
1681
  }
1607
1682
  )
1608
1683
  ] }),
1609
- buildPermalink && /* @__PURE__ */ jsx2("div", { class: "report-detail-permalink", children: /* @__PURE__ */ jsx2(
1684
+ buildPermalink && /* @__PURE__ */ jsx3("div", { class: "report-detail-permalink", children: /* @__PURE__ */ jsx3(
1610
1685
  "button",
1611
1686
  {
1612
1687
  type: "button",
@@ -1617,19 +1692,19 @@ function ReportDetailView({
1617
1692
  ) }),
1618
1693
  (detail.screenshots?.length ? detail.screenshots.map((s) => s.url) : [detail.screenshot_url]).map((url, i) => ({ url: pinUrl(`shot:${i}`, url ?? null), pinKey: `shot:${i}` })).filter((s) => Boolean(s.url)).map(({ url, pinKey }) => {
1619
1694
  const safeHref = safeExternalHref(url);
1620
- return safeHref ? /* @__PURE__ */ jsx2(
1695
+ return safeHref ? /* @__PURE__ */ jsx3(
1621
1696
  "a",
1622
1697
  {
1623
1698
  class: "report-detail-screenshot",
1624
1699
  href: safeHref,
1625
1700
  target: "_blank",
1626
1701
  rel: "noopener noreferrer",
1627
- children: /* @__PURE__ */ jsx2("img", { src: url, alt: "", loading: "lazy", onError: () => unpinUrl(pinKey) })
1702
+ children: /* @__PURE__ */ jsx3("img", { src: url, alt: "", loading: "lazy", onError: () => unpinUrl(pinKey) })
1628
1703
  }
1629
- ) : /* @__PURE__ */ jsx2("div", { class: "report-detail-screenshot", children: /* @__PURE__ */ jsx2("img", { src: url, alt: "", loading: "lazy", onError: () => unpinUrl(pinKey) }) });
1704
+ ) : /* @__PURE__ */ jsx3("div", { class: "report-detail-screenshot", children: /* @__PURE__ */ jsx3("img", { src: url, alt: "", loading: "lazy", onError: () => unpinUrl(pinKey) }) });
1630
1705
  }),
1631
- /* @__PURE__ */ jsx2("h3", { class: "report-detail-section", children: strings["detail.thread"] }),
1632
- detail.comments.length === 0 ? /* @__PURE__ */ jsx2("p", { class: "report-detail-empty", children: strings["detail.no_replies"] }) : /* @__PURE__ */ jsx2("ul", { class: "report-comments", children: detail.comments.map((c) => /* @__PURE__ */ jsx2("li", { children: /* @__PURE__ */ jsx2(
1706
+ /* @__PURE__ */ jsx3("h3", { class: "report-detail-section", children: strings["detail.thread"] }),
1707
+ detail.comments.length === 0 ? /* @__PURE__ */ jsx3("p", { class: "report-detail-empty", children: strings["detail.no_replies"] }) : /* @__PURE__ */ jsx3("ul", { class: "report-comments", children: detail.comments.map((c) => /* @__PURE__ */ jsx3("li", { children: /* @__PURE__ */ jsx3(
1633
1708
  CommentBubble,
1634
1709
  {
1635
1710
  comment: c,
@@ -1638,10 +1713,10 @@ function ReportDetailView({
1638
1713
  stableUrl: (key, url) => pinUrl(key, url) ?? url
1639
1714
  }
1640
1715
  ) })) }),
1641
- detail.status_history && detail.status_history.length > 0 && /* @__PURE__ */ jsx2(StatusHistorySection, { rows: detail.status_history, strings }),
1642
- detail.technical_context && /* @__PURE__ */ jsx2(TechnicalContextDrawer, { ctx: detail.technical_context, strings }),
1716
+ detail.status_history && detail.status_history.length > 0 && /* @__PURE__ */ jsx3(StatusHistorySection, { rows: detail.status_history, strings }),
1717
+ detail.technical_context && /* @__PURE__ */ jsx3(TechnicalContextDrawer, { ctx: detail.technical_context, strings }),
1643
1718
  showComposeBox ? /* @__PURE__ */ jsxs3("div", { class: "report-compose", children: [
1644
- /* @__PURE__ */ jsx2(
1719
+ /* @__PURE__ */ jsx3(
1645
1720
  "textarea",
1646
1721
  {
1647
1722
  value: composeBody,
@@ -1650,9 +1725,9 @@ function ReportDetailView({
1650
1725
  disabled: sending
1651
1726
  }
1652
1727
  ),
1653
- composeShots.length > 0 && /* @__PURE__ */ jsx2("div", { class: "compose-attachments", children: composeShots.map((s, i) => /* @__PURE__ */ jsxs3("div", { class: "compose-attachment", children: [
1654
- /* @__PURE__ */ jsx2("img", { src: s.preview, alt: strings["detail.attachment_alt"] }),
1655
- /* @__PURE__ */ jsx2(
1728
+ composeShots.length > 0 && /* @__PURE__ */ jsx3("div", { class: "compose-attachments", children: composeShots.map((s, i) => /* @__PURE__ */ jsxs3("div", { class: "compose-attachment", children: [
1729
+ /* @__PURE__ */ jsx3("img", { src: s.preview, alt: strings["detail.attachment_alt"] }),
1730
+ /* @__PURE__ */ jsx3(
1656
1731
  "button",
1657
1732
  {
1658
1733
  type: "button",
@@ -1664,8 +1739,8 @@ function ReportDetailView({
1664
1739
  }
1665
1740
  )
1666
1741
  ] }, s.preview)) }),
1667
- attachError && /* @__PURE__ */ jsx2("p", { class: "compose-attach-error", role: "alert", children: attachError }),
1668
- /* @__PURE__ */ jsx2(
1742
+ attachError && /* @__PURE__ */ jsx3("p", { class: "compose-attach-error", role: "alert", children: attachError }),
1743
+ /* @__PURE__ */ jsx3(
1669
1744
  "input",
1670
1745
  {
1671
1746
  ref: fileInputRef,
@@ -1678,7 +1753,7 @@ function ReportDetailView({
1678
1753
  }
1679
1754
  ),
1680
1755
  /* @__PURE__ */ jsxs3("div", { class: "report-compose-actions", children: [
1681
- /* @__PURE__ */ jsx2(
1756
+ /* @__PURE__ */ jsx3(
1682
1757
  "button",
1683
1758
  {
1684
1759
  type: "button",
@@ -1688,7 +1763,7 @@ function ReportDetailView({
1688
1763
  children: strings["detail.attach_add"]
1689
1764
  }
1690
1765
  ),
1691
- showCloseCta && /* @__PURE__ */ jsx2(
1766
+ showCloseCta && /* @__PURE__ */ jsx3(
1692
1767
  "button",
1693
1768
  {
1694
1769
  type: "button",
@@ -1698,7 +1773,7 @@ function ReportDetailView({
1698
1773
  children: closing ? strings["detail.close_busy"] : strings["detail.close_cta"]
1699
1774
  }
1700
1775
  ),
1701
- showCloseCta && /* @__PURE__ */ jsx2(
1776
+ showCloseCta && /* @__PURE__ */ jsx3(
1702
1777
  "button",
1703
1778
  {
1704
1779
  type: "button",
@@ -1708,7 +1783,7 @@ function ReportDetailView({
1708
1783
  children: reopening ? strings["detail.reopen_busy"] : strings["detail.reopen_cta"]
1709
1784
  }
1710
1785
  ),
1711
- /* @__PURE__ */ jsx2(
1786
+ /* @__PURE__ */ jsx3(
1712
1787
  "button",
1713
1788
  {
1714
1789
  type: "button",
@@ -1724,9 +1799,9 @@ function ReportDetailView({
1724
1799
  // to the submitter, so we hide the compose box entirely (action
1725
1800
  // is genuinely unavailable) and surface a short notice so the
1726
1801
  // viewer understands why.
1727
- /* @__PURE__ */ jsx2("p", { class: "report-detail-teammate-notice", role: "note", children: strings["detail.teammate_notice"] })
1802
+ /* @__PURE__ */ jsx3("p", { class: "report-detail-teammate-notice", role: "note", children: strings["detail.teammate_notice"] })
1728
1803
  ),
1729
- error && /* @__PURE__ */ jsx2("div", { class: "error", children: error })
1804
+ error && /* @__PURE__ */ jsx3("div", { class: "error", children: error })
1730
1805
  ] })
1731
1806
  ] });
1732
1807
  }
@@ -1739,19 +1814,19 @@ function ContextBlock({ detail, strings }) {
1739
1814
  const captureLabel = strings[captureKey] ?? detail.capture_method;
1740
1815
  return /* @__PURE__ */ jsxs3("div", { class: "report-detail-context", children: [
1741
1816
  /* @__PURE__ */ jsxs3("div", { class: "report-detail-context-pills", children: [
1742
- /* @__PURE__ */ jsx2("span", { class: "pill pill-type", children: strings[`type.${detail.feedback_type}`] }),
1743
- /* @__PURE__ */ jsx2("span", { class: `pill pill-severity pill-severity--${detail.severity}`, children: strings[`severity.${detail.severity}`] }),
1744
- /* @__PURE__ */ jsx2("span", { class: "pill pill-capture", children: captureLabel })
1817
+ /* @__PURE__ */ jsx3("span", { class: "pill pill-type", children: strings[`type.${detail.feedback_type}`] }),
1818
+ /* @__PURE__ */ jsx3("span", { class: `pill pill-severity pill-severity--${detail.severity}`, children: strings[`severity.${detail.severity}`] }),
1819
+ /* @__PURE__ */ jsx3("span", { class: "pill pill-capture", children: captureLabel })
1745
1820
  ] }),
1746
1821
  /* @__PURE__ */ jsxs3("div", { class: "report-detail-context-line", children: [
1747
- /* @__PURE__ */ jsx2("span", { class: "report-detail-context-label", children: strings["detail.context.submitted_at"] }),
1748
- /* @__PURE__ */ jsx2("span", { children: formatSubmittedAt(detail.created_at) })
1822
+ /* @__PURE__ */ jsx3("span", { class: "report-detail-context-label", children: strings["detail.context.submitted_at"] }),
1823
+ /* @__PURE__ */ jsx3("span", { children: formatSubmittedAt(detail.created_at) })
1749
1824
  ] }),
1750
1825
  detail.page_url && (() => {
1751
1826
  const safeHref = safeExternalHref(detail.page_url);
1752
1827
  return /* @__PURE__ */ jsxs3("div", { class: "report-detail-context-line", title: detail.page_url, children: [
1753
- /* @__PURE__ */ jsx2("span", { class: "report-detail-context-label", children: strings["detail.context.page"] }),
1754
- safeHref ? /* @__PURE__ */ jsx2(
1828
+ /* @__PURE__ */ jsx3("span", { class: "report-detail-context-label", children: strings["detail.context.page"] }),
1829
+ safeHref ? /* @__PURE__ */ jsx3(
1755
1830
  "a",
1756
1831
  {
1757
1832
  class: "report-detail-context-url",
@@ -1760,7 +1835,7 @@ function ContextBlock({ detail, strings }) {
1760
1835
  rel: "noopener noreferrer",
1761
1836
  children: truncateUrl(detail.page_url, 64)
1762
1837
  }
1763
- ) : /* @__PURE__ */ jsx2("span", { class: "report-detail-context-url", children: truncateUrl(detail.page_url, 64) })
1838
+ ) : /* @__PURE__ */ jsx3("span", { class: "report-detail-context-url", children: truncateUrl(detail.page_url, 64) })
1764
1839
  ] });
1765
1840
  })()
1766
1841
  ] });
@@ -1787,12 +1862,12 @@ function TechnicalContextDrawer({ ctx, strings }) {
1787
1862
  const errorCount = errors.length;
1788
1863
  const summary = errorCount > 0 ? `${strings["detail.tech.title"]} \xB7 ${errorCount} ${errorCount === 1 ? strings["detail.tech.errors_one"] : strings["detail.tech.errors_many"]}` : strings["detail.tech.title"];
1789
1864
  return /* @__PURE__ */ jsxs3("details", { class: "report-detail-tech", children: [
1790
- /* @__PURE__ */ jsx2("summary", { children: summary }),
1865
+ /* @__PURE__ */ jsx3("summary", { children: summary }),
1791
1866
  /* @__PURE__ */ jsxs3("div", { class: "tech-body", children: [
1792
- device && /* @__PURE__ */ jsx2(DeviceSection, { device, strings }),
1793
- errors.length > 0 && /* @__PURE__ */ jsx2(ErrorsSection, { errors, strings }),
1794
- consoleLogs.length > 0 && /* @__PURE__ */ jsx2(ConsoleSection, { logs: consoleLogs, strings }),
1795
- network.length > 0 && /* @__PURE__ */ jsx2(NetworkSection, { rows: network, strings })
1867
+ device && /* @__PURE__ */ jsx3(DeviceSection, { device, strings }),
1868
+ errors.length > 0 && /* @__PURE__ */ jsx3(ErrorsSection, { errors, strings }),
1869
+ consoleLogs.length > 0 && /* @__PURE__ */ jsx3(ConsoleSection, { logs: consoleLogs, strings }),
1870
+ network.length > 0 && /* @__PURE__ */ jsx3(NetworkSection, { rows: network, strings })
1796
1871
  ] })
1797
1872
  ] });
1798
1873
  }
@@ -1814,10 +1889,10 @@ function DeviceSection({
1814
1889
  if (device?.connection) parts.push({ label: strings["detail.tech.device.connection"], value: device.connection });
1815
1890
  if (parts.length === 0) return null;
1816
1891
  return /* @__PURE__ */ jsxs3("div", { class: "tech-section", children: [
1817
- /* @__PURE__ */ jsx2("h4", { children: strings["detail.tech.device"] }),
1818
- /* @__PURE__ */ jsx2("dl", { class: "tech-device", children: parts.map((p) => /* @__PURE__ */ jsxs3(Fragment, { children: [
1819
- /* @__PURE__ */ jsx2("dt", { children: p.label }),
1820
- /* @__PURE__ */ jsx2("dd", { children: p.value })
1892
+ /* @__PURE__ */ jsx3("h4", { children: strings["detail.tech.device"] }),
1893
+ /* @__PURE__ */ jsx3("dl", { class: "tech-device", children: parts.map((p) => /* @__PURE__ */ jsxs3(Fragment, { children: [
1894
+ /* @__PURE__ */ jsx3("dt", { children: p.label }),
1895
+ /* @__PURE__ */ jsx3("dd", { children: p.value })
1821
1896
  ] })) })
1822
1897
  ] });
1823
1898
  }
@@ -1826,10 +1901,10 @@ function ErrorsSection({
1826
1901
  strings
1827
1902
  }) {
1828
1903
  return /* @__PURE__ */ jsxs3("div", { class: "tech-section", children: [
1829
- /* @__PURE__ */ jsx2("h4", { children: strings["detail.tech.errors"] }),
1830
- /* @__PURE__ */ jsx2("ul", { class: "tech-errors", children: errors.map((e) => /* @__PURE__ */ jsxs3("li", { children: [
1831
- /* @__PURE__ */ jsx2("div", { class: "tech-errors-msg", children: e.message }),
1832
- e.stack && /* @__PURE__ */ jsx2("pre", { class: "tech-errors-stack", children: truncateStack(e.stack) })
1904
+ /* @__PURE__ */ jsx3("h4", { children: strings["detail.tech.errors"] }),
1905
+ /* @__PURE__ */ jsx3("ul", { class: "tech-errors", children: errors.map((e) => /* @__PURE__ */ jsxs3("li", { children: [
1906
+ /* @__PURE__ */ jsx3("div", { class: "tech-errors-msg", children: e.message }),
1907
+ e.stack && /* @__PURE__ */ jsx3("pre", { class: "tech-errors-stack", children: truncateStack(e.stack) })
1833
1908
  ] })) })
1834
1909
  ] });
1835
1910
  }
@@ -1838,10 +1913,10 @@ function ConsoleSection({
1838
1913
  strings
1839
1914
  }) {
1840
1915
  return /* @__PURE__ */ jsxs3("div", { class: "tech-section", children: [
1841
- /* @__PURE__ */ jsx2("h4", { children: strings["detail.tech.console"] }),
1842
- /* @__PURE__ */ jsx2("ul", { class: "tech-console", children: logs.map((l) => /* @__PURE__ */ jsxs3("li", { class: `tech-console-row tech-console-row--${l.level}`, children: [
1843
- /* @__PURE__ */ jsx2("span", { class: "tech-console-level", children: l.level }),
1844
- /* @__PURE__ */ jsx2("span", { class: "tech-console-msg", children: l.message })
1916
+ /* @__PURE__ */ jsx3("h4", { children: strings["detail.tech.console"] }),
1917
+ /* @__PURE__ */ jsx3("ul", { class: "tech-console", children: logs.map((l) => /* @__PURE__ */ jsxs3("li", { class: `tech-console-row tech-console-row--${l.level}`, children: [
1918
+ /* @__PURE__ */ jsx3("span", { class: "tech-console-level", children: l.level }),
1919
+ /* @__PURE__ */ jsx3("span", { class: "tech-console-msg", children: l.message })
1845
1920
  ] })) })
1846
1921
  ] });
1847
1922
  }
@@ -1850,13 +1925,13 @@ function NetworkSection({
1850
1925
  strings
1851
1926
  }) {
1852
1927
  return /* @__PURE__ */ jsxs3("div", { class: "tech-section", children: [
1853
- /* @__PURE__ */ jsx2("h4", { children: strings["detail.tech.network"] }),
1854
- /* @__PURE__ */ jsx2("ul", { class: "tech-network", children: rows.map((n) => {
1928
+ /* @__PURE__ */ jsx3("h4", { children: strings["detail.tech.network"] }),
1929
+ /* @__PURE__ */ jsx3("ul", { class: "tech-network", children: rows.map((n) => {
1855
1930
  const failed = n.status >= 400 || n.status === 0;
1856
1931
  return /* @__PURE__ */ jsxs3("li", { class: `tech-network-row${failed ? " tech-network-row--fail" : ""}`, children: [
1857
- /* @__PURE__ */ jsx2("span", { class: "tech-network-status", children: n.status || "\u2014" }),
1858
- /* @__PURE__ */ jsx2("span", { class: "tech-network-method", children: n.method }),
1859
- /* @__PURE__ */ jsx2("span", { class: "tech-network-url", title: n.url, children: truncateUrl(n.url, 56) }),
1932
+ /* @__PURE__ */ jsx3("span", { class: "tech-network-status", children: n.status || "\u2014" }),
1933
+ /* @__PURE__ */ jsx3("span", { class: "tech-network-method", children: n.method }),
1934
+ /* @__PURE__ */ jsx3("span", { class: "tech-network-url", title: n.url, children: truncateUrl(n.url, 56) }),
1860
1935
  /* @__PURE__ */ jsxs3("span", { class: "tech-network-time", children: [
1861
1936
  Math.round(n.durationMs),
1862
1937
  "ms"
@@ -1872,26 +1947,26 @@ function truncateStack(stack) {
1872
1947
  }
1873
1948
  function StatusHistorySection({ rows, strings }) {
1874
1949
  return /* @__PURE__ */ jsxs3("div", { class: "report-detail-history", children: [
1875
- /* @__PURE__ */ jsx2("h3", { class: "report-detail-section", children: strings["detail.history"] }),
1876
- /* @__PURE__ */ jsx2("ol", { class: "status-history", children: rows.map((r) => {
1950
+ /* @__PURE__ */ jsx3("h3", { class: "report-detail-section", children: strings["detail.history"] }),
1951
+ /* @__PURE__ */ jsx3("ol", { class: "status-history", children: rows.map((r) => {
1877
1952
  const from = strings[`status.${r.from_status}`] ?? r.from_status;
1878
1953
  const to = strings[`status.${r.to_status}`] ?? r.to_status;
1879
1954
  const sourceKey = r.changed_by_source === "mcp" ? "detail.author.mcp" : r.changed_by_source === "system" ? "detail.author.system" : "detail.author.staff";
1880
1955
  return /* @__PURE__ */ jsxs3("li", { class: "status-history-row", children: [
1881
- /* @__PURE__ */ jsx2("span", { class: "status-history-time", children: formatSubmittedAt(r.created_at) }),
1956
+ /* @__PURE__ */ jsx3("span", { class: "status-history-time", children: formatSubmittedAt(r.created_at) }),
1882
1957
  /* @__PURE__ */ jsxs3("span", { class: "status-history-transition", children: [
1883
- /* @__PURE__ */ jsx2("span", { class: `pill pill-status pill-status--${r.from_status}`, children: from }),
1884
- /* @__PURE__ */ jsx2("span", { class: "status-history-arrow", "aria-hidden": "true", children: "\u2192" }),
1885
- /* @__PURE__ */ jsx2("span", { class: `pill pill-status pill-status--${r.to_status}`, children: to })
1958
+ /* @__PURE__ */ jsx3("span", { class: `pill pill-status pill-status--${r.from_status}`, children: from }),
1959
+ /* @__PURE__ */ jsx3("span", { class: "status-history-arrow", "aria-hidden": "true", children: "\u2192" }),
1960
+ /* @__PURE__ */ jsx3("span", { class: `pill pill-status pill-status--${r.to_status}`, children: to })
1886
1961
  ] }),
1887
- /* @__PURE__ */ jsx2("span", { class: `status-history-source status-history-source--${r.changed_by_source}`, children: strings[sourceKey] })
1962
+ /* @__PURE__ */ jsx3("span", { class: `status-history-source status-history-source--${r.changed_by_source}`, children: strings[sourceKey] })
1888
1963
  ] });
1889
1964
  }) })
1890
1965
  ] });
1891
1966
  }
1892
1967
 
1893
1968
  // src/widget/BoardView.tsx
1894
- import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs4 } from "preact/jsx-runtime";
1969
+ import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "preact/jsx-runtime";
1895
1970
  var POLL_MS2 = 3e4;
1896
1971
  var SEARCH_DEBOUNCE_MS = 300;
1897
1972
  var SORT_OPTIONS = ["recent", "oldest", "updated", "severity", "status"];
@@ -1911,22 +1986,22 @@ function BoardView({
1911
1986
  getCurrentPage,
1912
1987
  initialSelectedId
1913
1988
  }) {
1914
- const [filters, setFilters] = useState2(() => loadBoardView(externalId));
1915
- const [thisPage, setThisPage] = useState2(true);
1989
+ const [filters, setFilters] = useState3(() => loadBoardView(externalId));
1990
+ const [thisPage, setThisPage] = useState3(true);
1916
1991
  useEffect2(() => {
1917
1992
  saveBoardView(externalId, filters);
1918
1993
  }, [externalId, filtersHash(filters)]);
1919
- const [page, setPage] = useState2(null);
1920
- const [kpis, setKpis] = useState2(null);
1921
- const [loading, setLoading] = useState2(true);
1922
- const [stale, setStale] = useState2(false);
1923
- const [error, setError] = useState2(null);
1924
- const [selectedId, setSelectedId] = useState2(initialSelectedId ?? null);
1925
- const [detailKey, setDetailKey] = useState2(0);
1926
- const [reloadTick, setReloadTick] = useState2(0);
1927
- const [extra, setExtra] = useState2(null);
1928
- const [loadingMore, setLoadingMore] = useState2(false);
1929
- const [qDraft, setQDraft] = useState2(filters.q ?? "");
1994
+ const [page, setPage] = useState3(null);
1995
+ const [kpis, setKpis] = useState3(null);
1996
+ const [loading, setLoading] = useState3(true);
1997
+ const [stale, setStale] = useState3(false);
1998
+ const [error, setError] = useState3(null);
1999
+ const [selectedId, setSelectedId] = useState3(initialSelectedId ?? null);
2000
+ const [detailKey, setDetailKey] = useState3(0);
2001
+ const [reloadTick, setReloadTick] = useState3(0);
2002
+ const [extra, setExtra] = useState3(null);
2003
+ const [loadingMore, setLoadingMore] = useState3(false);
2004
+ const [qDraft, setQDraft] = useState3(filters.q ?? "");
1930
2005
  const debouncedQ = useDebouncedValue(qDraft, SEARCH_DEBOUNCE_MS);
1931
2006
  useEffect2(() => {
1932
2007
  setFilters((f) => {
@@ -2033,8 +2108,8 @@ function BoardView({
2033
2108
  setDetailKey((k) => k + 1);
2034
2109
  };
2035
2110
  return /* @__PURE__ */ jsxs4("div", { class: `board-view ${stale ? "is-stale" : ""}`, children: [
2036
- /* @__PURE__ */ jsx3(BoardHeader, { strings, kpis, thisPage }),
2037
- /* @__PURE__ */ jsx3(
2111
+ /* @__PURE__ */ jsx4(BoardHeader, { strings, kpis, thisPage }),
2112
+ /* @__PURE__ */ jsx4(
2038
2113
  BoardFilters,
2039
2114
  {
2040
2115
  filters,
@@ -2050,8 +2125,8 @@ function BoardView({
2050
2125
  /* @__PURE__ */ jsxs4("div", { class: "board-body", children: [
2051
2126
  /* @__PURE__ */ jsxs4("div", { class: "board-list-wrap", "aria-busy": loading, children: [
2052
2127
  error && /* @__PURE__ */ jsxs4("div", { class: "board-error", role: "alert", children: [
2053
- /* @__PURE__ */ jsx3("span", { children: error }),
2054
- /* @__PURE__ */ jsx3(
2128
+ /* @__PURE__ */ jsx4("span", { children: error }),
2129
+ /* @__PURE__ */ jsx4(
2055
2130
  "button",
2056
2131
  {
2057
2132
  type: "button",
@@ -2063,10 +2138,11 @@ function BoardView({
2063
2138
  },
2064
2139
  children: strings["board.retry"]
2065
2140
  }
2066
- )
2141
+ ),
2142
+ /* @__PURE__ */ jsx4(DiagnosticHint, { api, strings, host: api.endpointHost })
2067
2143
  ] }),
2068
- !error && loading && !page && /* @__PURE__ */ jsx3(BoardListSkeleton, {}),
2069
- !error && page && visibleRows.length === 0 && (!loading || stale) && /* @__PURE__ */ jsx3(
2144
+ !error && loading && !page && /* @__PURE__ */ jsx4(BoardListSkeleton, {}),
2145
+ !error && page && visibleRows.length === 0 && (!loading || stale) && /* @__PURE__ */ jsx4(
2070
2146
  BoardEmpty,
2071
2147
  {
2072
2148
  strings,
@@ -2075,7 +2151,7 @@ function BoardView({
2075
2151
  }
2076
2152
  ),
2077
2153
  !error && page && visibleRows.length > 0 && /* @__PURE__ */ jsxs4(Fragment2, { children: [
2078
- /* @__PURE__ */ jsx3(
2154
+ /* @__PURE__ */ jsx4(
2079
2155
  BoardList,
2080
2156
  {
2081
2157
  rows: visibleRows,
@@ -2086,7 +2162,7 @@ function BoardView({
2086
2162
  thisPage
2087
2163
  }
2088
2164
  ),
2089
- hasMore && !stale && /* @__PURE__ */ jsx3(
2165
+ hasMore && !stale && /* @__PURE__ */ jsx4(
2090
2166
  "button",
2091
2167
  {
2092
2168
  type: "button",
@@ -2098,7 +2174,7 @@ function BoardView({
2098
2174
  )
2099
2175
  ] })
2100
2176
  ] }),
2101
- /* @__PURE__ */ jsx3("div", { class: `board-detail-wrap ${selectedId ? "has-selection" : ""}`, children: selectedId ? /* @__PURE__ */ jsx3(
2177
+ /* @__PURE__ */ jsx4("div", { class: `board-detail-wrap ${selectedId ? "has-selection" : ""}`, children: selectedId ? /* @__PURE__ */ jsx4(
2102
2178
  ReportDetailView,
2103
2179
  {
2104
2180
  api,
@@ -2119,8 +2195,8 @@ function BoardView({
2119
2195
  },
2120
2196
  detailKey
2121
2197
  ) : /* @__PURE__ */ jsxs4("div", { class: "board-detail-empty", children: [
2122
- /* @__PURE__ */ jsx3(DetailEmptyIllustration, {}),
2123
- /* @__PURE__ */ jsx3("p", { children: strings["board.detail.empty"] })
2198
+ /* @__PURE__ */ jsx4(DetailEmptyIllustration, {}),
2199
+ /* @__PURE__ */ jsx4("p", { children: strings["board.detail.empty"] })
2124
2200
  ] }) })
2125
2201
  ] })
2126
2202
  ] });
@@ -2133,13 +2209,13 @@ function BoardHeader({
2133
2209
  const scopeLabel = thisPage ? strings["board.scope.onThisPage"] : kpis?.scope === "project" ? strings["board.scope.project"] : strings["board.scope.mine"];
2134
2210
  return /* @__PURE__ */ jsxs4("header", { class: "board-header", children: [
2135
2211
  /* @__PURE__ */ jsxs4("div", { class: "board-header-title", children: [
2136
- /* @__PURE__ */ jsx3("span", { class: "board-header-emoji", "aria-hidden": "true", children: "\u{1F4CB}" }),
2212
+ /* @__PURE__ */ jsx4("span", { class: "board-header-emoji", "aria-hidden": "true", children: "\u{1F4CB}" }),
2137
2213
  /* @__PURE__ */ jsxs4("div", { children: [
2138
- /* @__PURE__ */ jsx3("h2", { class: "board-header-h", children: strings["tab.board"] }),
2139
- /* @__PURE__ */ jsx3("p", { class: "board-header-sub", children: kpis ? `${kpis.total} \xB7 ${scopeLabel}` : scopeLabel })
2214
+ /* @__PURE__ */ jsx4("h2", { class: "board-header-h", children: strings["tab.board"] }),
2215
+ /* @__PURE__ */ jsx4("p", { class: "board-header-sub", children: kpis ? `${kpis.total} \xB7 ${scopeLabel}` : scopeLabel })
2140
2216
  ] })
2141
2217
  ] }),
2142
- /* @__PURE__ */ jsx3(BoardKpiStrip, { kpis, strings })
2218
+ /* @__PURE__ */ jsx4(BoardKpiStrip, { kpis, strings })
2143
2219
  ] });
2144
2220
  }
2145
2221
  function BoardKpiStrip({
@@ -2172,9 +2248,9 @@ function BoardKpiStrip({
2172
2248
  tone: "tone-rate"
2173
2249
  }
2174
2250
  ];
2175
- return /* @__PURE__ */ jsx3("div", { class: `board-kpi-strip ${kpis ? "is-ready" : "is-loading"}`, "aria-live": "polite", children: cells.map((c) => /* @__PURE__ */ jsxs4("div", { class: `board-kpi-card ${c.tone}`, children: [
2176
- /* @__PURE__ */ jsx3("div", { class: "board-kpi-value", children: c.value }),
2177
- /* @__PURE__ */ jsx3("div", { class: "board-kpi-label", children: c.label })
2251
+ return /* @__PURE__ */ jsx4("div", { class: `board-kpi-strip ${kpis ? "is-ready" : "is-loading"}`, "aria-live": "polite", children: cells.map((c) => /* @__PURE__ */ jsxs4("div", { class: `board-kpi-card ${c.tone}`, children: [
2252
+ /* @__PURE__ */ jsx4("div", { class: "board-kpi-value", children: c.value }),
2253
+ /* @__PURE__ */ jsx4("div", { class: "board-kpi-label", children: c.label })
2178
2254
  ] }, c.key)) });
2179
2255
  }
2180
2256
  function BoardFilters({
@@ -2227,7 +2303,7 @@ function BoardFilters({
2227
2303
  const clear = () => onChange({});
2228
2304
  return /* @__PURE__ */ jsxs4("div", { class: "board-filters", children: [
2229
2305
  /* @__PURE__ */ jsxs4("div", { class: "board-scope", role: "group", "aria-label": strings["board.scope.thisPage"], children: [
2230
- /* @__PURE__ */ jsx3(
2306
+ /* @__PURE__ */ jsx4(
2231
2307
  "button",
2232
2308
  {
2233
2309
  type: "button",
@@ -2237,7 +2313,7 @@ function BoardFilters({
2237
2313
  children: strings["board.scope.thisPage"]
2238
2314
  }
2239
2315
  ),
2240
- /* @__PURE__ */ jsx3(
2316
+ /* @__PURE__ */ jsx4(
2241
2317
  "button",
2242
2318
  {
2243
2319
  type: "button",
@@ -2248,14 +2324,14 @@ function BoardFilters({
2248
2324
  }
2249
2325
  )
2250
2326
  ] }),
2251
- /* @__PURE__ */ jsx3(
2327
+ /* @__PURE__ */ jsx4(
2252
2328
  "select",
2253
2329
  {
2254
2330
  class: "board-filter-select",
2255
2331
  "aria-label": strings["board.sort"],
2256
2332
  value: filters.ordering ?? "recent",
2257
2333
  onChange: (e) => setOrdering(e.target.value),
2258
- children: SORT_OPTIONS.map((o) => /* @__PURE__ */ jsx3("option", { value: o, children: strings[`board.sort.${o}`] }, o))
2334
+ children: SORT_OPTIONS.map((o) => /* @__PURE__ */ jsx4("option", { value: o, children: strings[`board.sort.${o}`] }, o))
2259
2335
  }
2260
2336
  ),
2261
2337
  /* @__PURE__ */ jsxs4(
@@ -2266,8 +2342,8 @@ function BoardFilters({
2266
2342
  value: filters.status?.[0] ?? "",
2267
2343
  onChange: (e) => setStatus(e.target.value),
2268
2344
  children: [
2269
- /* @__PURE__ */ jsx3("option", { value: "", children: strings["board.filter.status"] }),
2270
- STATUSES.map((s) => /* @__PURE__ */ jsx3("option", { value: s, children: strings[`board.kpi.${s}`] ?? s }, s))
2345
+ /* @__PURE__ */ jsx4("option", { value: "", children: strings["board.filter.status"] }),
2346
+ STATUSES.map((s) => /* @__PURE__ */ jsx4("option", { value: s, children: strings[`board.kpi.${s}`] ?? s }, s))
2271
2347
  ]
2272
2348
  }
2273
2349
  ),
@@ -2279,8 +2355,8 @@ function BoardFilters({
2279
2355
  value: filters.type?.[0] ?? "",
2280
2356
  onChange: (e) => setType(e.target.value),
2281
2357
  children: [
2282
- /* @__PURE__ */ jsx3("option", { value: "", children: strings["board.filter.type"] }),
2283
- TYPES.map((t) => /* @__PURE__ */ jsx3("option", { value: t, children: strings[`type.${t}`] ?? t }, t))
2358
+ /* @__PURE__ */ jsx4("option", { value: "", children: strings["board.filter.type"] }),
2359
+ TYPES.map((t) => /* @__PURE__ */ jsx4("option", { value: t, children: strings[`type.${t}`] ?? t }, t))
2284
2360
  ]
2285
2361
  }
2286
2362
  ),
@@ -2292,12 +2368,12 @@ function BoardFilters({
2292
2368
  value: filters.severity?.[0] ?? "",
2293
2369
  onChange: (e) => setSeverity(e.target.value),
2294
2370
  children: [
2295
- /* @__PURE__ */ jsx3("option", { value: "", children: strings["board.filter.severity"] }),
2296
- SEVERITIES.map((s) => /* @__PURE__ */ jsx3("option", { value: s, children: strings[`severity.${s}`] ?? s }, s))
2371
+ /* @__PURE__ */ jsx4("option", { value: "", children: strings["board.filter.severity"] }),
2372
+ SEVERITIES.map((s) => /* @__PURE__ */ jsx4("option", { value: s, children: strings[`severity.${s}`] ?? s }, s))
2297
2373
  ]
2298
2374
  }
2299
2375
  ),
2300
- /* @__PURE__ */ jsx3(
2376
+ /* @__PURE__ */ jsx4(
2301
2377
  "input",
2302
2378
  {
2303
2379
  type: "search",
@@ -2308,7 +2384,7 @@ function BoardFilters({
2308
2384
  }
2309
2385
  ),
2310
2386
  /* @__PURE__ */ jsxs4("label", { class: "board-filter-toggle", children: [
2311
- /* @__PURE__ */ jsx3(
2387
+ /* @__PURE__ */ jsx4(
2312
2388
  "input",
2313
2389
  {
2314
2390
  type: "checkbox",
@@ -2316,10 +2392,10 @@ function BoardFilters({
2316
2392
  onChange: toggleMine
2317
2393
  }
2318
2394
  ),
2319
- /* @__PURE__ */ jsx3("span", { children: strings["board.filter.mine"] })
2395
+ /* @__PURE__ */ jsx4("span", { children: strings["board.filter.mine"] })
2320
2396
  ] }),
2321
2397
  activeCount > 0 && /* @__PURE__ */ jsxs4("button", { type: "button", class: "board-filter-clear", onClick: clear, children: [
2322
- /* @__PURE__ */ jsx3(CloseIcon, {}),
2398
+ /* @__PURE__ */ jsx4(CloseIcon, {}),
2323
2399
  strings["board.filter.clear"]
2324
2400
  ] })
2325
2401
  ] });
@@ -2333,8 +2409,8 @@ function BoardList({
2333
2409
  thisPage
2334
2410
  }) {
2335
2411
  return /* @__PURE__ */ jsxs4(Fragment2, { children: [
2336
- /* @__PURE__ */ jsx3("div", { class: "board-list-count", children: strings[thisPage ? "board.list.count.page" : "board.list.count"].replace("{n}", String(rows.length)).replace("{total}", String(total)) }),
2337
- /* @__PURE__ */ jsx3("ul", { class: "board-list", role: "list", children: rows.map((row) => /* @__PURE__ */ jsx3(
2412
+ /* @__PURE__ */ jsx4("div", { class: "board-list-count", children: strings[thisPage ? "board.list.count.page" : "board.list.count"].replace("{n}", String(rows.length)).replace("{total}", String(total)) }),
2413
+ /* @__PURE__ */ jsx4("ul", { class: "board-list", role: "list", children: rows.map((row) => /* @__PURE__ */ jsx4(
2338
2414
  BoardRowCard,
2339
2415
  {
2340
2416
  row,
@@ -2353,7 +2429,7 @@ function BoardRowCard({
2353
2429
  strings
2354
2430
  }) {
2355
2431
  const author = row.is_mine ? strings["board.list.you"] : row.author_label || "\u2014";
2356
- return /* @__PURE__ */ jsx3("li", { children: /* @__PURE__ */ jsxs4(
2432
+ return /* @__PURE__ */ jsx4("li", { children: /* @__PURE__ */ jsxs4(
2357
2433
  "button",
2358
2434
  {
2359
2435
  type: "button",
@@ -2362,18 +2438,18 @@ function BoardRowCard({
2362
2438
  "aria-pressed": selected,
2363
2439
  children: [
2364
2440
  /* @__PURE__ */ jsxs4("div", { class: "board-row-badges", children: [
2365
- /* @__PURE__ */ jsx3("span", { class: `badge status-${row.status}`, children: strings[`status.${row.status}`] ?? row.status }),
2366
- /* @__PURE__ */ jsx3("span", { class: `badge severity-${row.severity}`, children: strings[`severity.${row.severity}`] ?? row.severity })
2441
+ /* @__PURE__ */ jsx4("span", { class: `badge status-${row.status}`, children: strings[`status.${row.status}`] ?? row.status }),
2442
+ /* @__PURE__ */ jsx4("span", { class: `badge severity-${row.severity}`, children: strings[`severity.${row.severity}`] ?? row.severity })
2367
2443
  ] }),
2368
- /* @__PURE__ */ jsx3("div", { class: "board-row-description", children: row.description }),
2444
+ /* @__PURE__ */ jsx4("div", { class: "board-row-description", children: row.description }),
2369
2445
  /* @__PURE__ */ jsxs4("div", { class: "board-row-meta", children: [
2370
- /* @__PURE__ */ jsx3("span", { class: "board-row-author", children: author }),
2446
+ /* @__PURE__ */ jsx4("span", { class: "board-row-author", children: author }),
2371
2447
  row.comment_count > 0 && /* @__PURE__ */ jsxs4("span", { class: "board-row-comments", children: [
2372
- /* @__PURE__ */ jsx3(CommentIcon, {}),
2448
+ /* @__PURE__ */ jsx4(CommentIcon, {}),
2373
2449
  " ",
2374
2450
  row.comment_count
2375
2451
  ] }),
2376
- /* @__PURE__ */ jsx3("span", { class: "board-row-time", children: formatRelative(row.created_at) })
2452
+ /* @__PURE__ */ jsx4("span", { class: "board-row-time", children: formatRelative(row.created_at) })
2377
2453
  ] })
2378
2454
  ]
2379
2455
  }
@@ -2385,44 +2461,44 @@ function BoardEmpty({
2385
2461
  onAllPages
2386
2462
  }) {
2387
2463
  return /* @__PURE__ */ jsxs4("div", { class: "board-empty", children: [
2388
- /* @__PURE__ */ jsx3(EmptyIllustration, {}),
2389
- /* @__PURE__ */ jsx3("h3", { children: strings[thisPage ? "board.list.empty.page.title" : "board.list.empty.title"] }),
2390
- /* @__PURE__ */ jsx3("p", { children: strings[thisPage ? "board.list.empty.page.description" : "board.list.empty.description"] }),
2391
- thisPage && /* @__PURE__ */ jsx3("button", { type: "button", class: "btn btn--ghost", onClick: onAllPages, children: strings["board.scope.allPages"] })
2464
+ /* @__PURE__ */ jsx4(EmptyIllustration, {}),
2465
+ /* @__PURE__ */ jsx4("h3", { children: strings[thisPage ? "board.list.empty.page.title" : "board.list.empty.title"] }),
2466
+ /* @__PURE__ */ jsx4("p", { children: strings[thisPage ? "board.list.empty.page.description" : "board.list.empty.description"] }),
2467
+ thisPage && /* @__PURE__ */ jsx4("button", { type: "button", class: "btn btn--ghost", onClick: onAllPages, children: strings["board.scope.allPages"] })
2392
2468
  ] });
2393
2469
  }
2394
2470
  function BoardListSkeleton() {
2395
- return /* @__PURE__ */ jsx3("ul", { class: "board-list board-list-skeleton", "aria-hidden": "true", children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsx3("li", { children: /* @__PURE__ */ jsxs4("div", { class: "board-row skeleton-row", children: [
2396
- /* @__PURE__ */ jsx3("div", { class: "skeleton-line skeleton-badges" }),
2397
- /* @__PURE__ */ jsx3("div", { class: "skeleton-line skeleton-text" }),
2398
- /* @__PURE__ */ jsx3("div", { class: "skeleton-line skeleton-text short" })
2471
+ return /* @__PURE__ */ jsx4("ul", { class: "board-list board-list-skeleton", "aria-hidden": "true", children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsx4("li", { children: /* @__PURE__ */ jsxs4("div", { class: "board-row skeleton-row", children: [
2472
+ /* @__PURE__ */ jsx4("div", { class: "skeleton-line skeleton-badges" }),
2473
+ /* @__PURE__ */ jsx4("div", { class: "skeleton-line skeleton-text" }),
2474
+ /* @__PURE__ */ jsx4("div", { class: "skeleton-line skeleton-text short" })
2399
2475
  ] }) }, i)) });
2400
2476
  }
2401
2477
  function CommentIcon() {
2402
- return /* @__PURE__ */ jsx3("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx3("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) });
2478
+ return /* @__PURE__ */ jsx4("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx4("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) });
2403
2479
  }
2404
2480
  function CloseIcon() {
2405
2481
  return /* @__PURE__ */ jsxs4("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true", children: [
2406
- /* @__PURE__ */ jsx3("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
2407
- /* @__PURE__ */ jsx3("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
2482
+ /* @__PURE__ */ jsx4("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
2483
+ /* @__PURE__ */ jsx4("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
2408
2484
  ] });
2409
2485
  }
2410
2486
  function EmptyIllustration() {
2411
2487
  return /* @__PURE__ */ jsxs4("svg", { width: "64", height: "64", viewBox: "0 0 64 64", fill: "none", "aria-hidden": "true", children: [
2412
- /* @__PURE__ */ jsx3("circle", { cx: "32", cy: "32", r: "28", stroke: "currentColor", "stroke-opacity": "0.18", "stroke-width": "2" }),
2413
- /* @__PURE__ */ jsx3("path", { d: "M22 32h20M32 22v20", stroke: "currentColor", "stroke-opacity": "0.35", "stroke-width": "2", "stroke-linecap": "round" })
2488
+ /* @__PURE__ */ jsx4("circle", { cx: "32", cy: "32", r: "28", stroke: "currentColor", "stroke-opacity": "0.18", "stroke-width": "2" }),
2489
+ /* @__PURE__ */ jsx4("path", { d: "M22 32h20M32 22v20", stroke: "currentColor", "stroke-opacity": "0.35", "stroke-width": "2", "stroke-linecap": "round" })
2414
2490
  ] });
2415
2491
  }
2416
2492
  function DetailEmptyIllustration() {
2417
2493
  return /* @__PURE__ */ jsxs4("svg", { width: "80", height: "80", viewBox: "0 0 64 64", fill: "none", "aria-hidden": "true", children: [
2418
- /* @__PURE__ */ jsx3("rect", { x: "10", y: "12", width: "44", height: "36", rx: "4", stroke: "currentColor", "stroke-opacity": "0.22", "stroke-width": "2" }),
2419
- /* @__PURE__ */ jsx3("line", { x1: "18", y1: "22", x2: "46", y2: "22", stroke: "currentColor", "stroke-opacity": "0.22", "stroke-width": "2", "stroke-linecap": "round" }),
2420
- /* @__PURE__ */ jsx3("line", { x1: "18", y1: "30", x2: "38", y2: "30", stroke: "currentColor", "stroke-opacity": "0.18", "stroke-width": "2", "stroke-linecap": "round" }),
2421
- /* @__PURE__ */ jsx3("line", { x1: "18", y1: "38", x2: "32", y2: "38", stroke: "currentColor", "stroke-opacity": "0.14", "stroke-width": "2", "stroke-linecap": "round" })
2494
+ /* @__PURE__ */ jsx4("rect", { x: "10", y: "12", width: "44", height: "36", rx: "4", stroke: "currentColor", "stroke-opacity": "0.22", "stroke-width": "2" }),
2495
+ /* @__PURE__ */ jsx4("line", { x1: "18", y1: "22", x2: "46", y2: "22", stroke: "currentColor", "stroke-opacity": "0.22", "stroke-width": "2", "stroke-linecap": "round" }),
2496
+ /* @__PURE__ */ jsx4("line", { x1: "18", y1: "30", x2: "38", y2: "30", stroke: "currentColor", "stroke-opacity": "0.18", "stroke-width": "2", "stroke-linecap": "round" }),
2497
+ /* @__PURE__ */ jsx4("line", { x1: "18", y1: "38", x2: "32", y2: "38", stroke: "currentColor", "stroke-opacity": "0.14", "stroke-width": "2", "stroke-linecap": "round" })
2422
2498
  ] });
2423
2499
  }
2424
2500
  function useDebouncedValue(value, ms) {
2425
- const [debounced, setDebounced] = useState2(value);
2501
+ const [debounced, setDebounced] = useState3(value);
2426
2502
  useEffect2(() => {
2427
2503
  const t = setTimeout(() => setDebounced(value), ms);
2428
2504
  return () => clearTimeout(t);
@@ -2482,10 +2558,10 @@ function formatRelative(iso) {
2482
2558
  }
2483
2559
 
2484
2560
  // src/widget/ChangelogList.tsx
2485
- import { useEffect as useEffect3, useMemo as useMemo2, useRef as useRef2, useState as useState3 } from "preact/hooks";
2561
+ import { useEffect as useEffect3, useMemo as useMemo2, useRef as useRef2, useState as useState4 } from "preact/hooks";
2486
2562
 
2487
2563
  // src/widget/ReportRow.tsx
2488
- import { jsx as jsx4, jsxs as jsxs5 } from "preact/jsx-runtime";
2564
+ import { jsx as jsx5, jsxs as jsxs5 } from "preact/jsx-runtime";
2489
2565
  function statusClassName(status) {
2490
2566
  return `pill pill-status pill-status--${status}`;
2491
2567
  }
@@ -2515,13 +2591,13 @@ function ReportRow({ row, strings, onClick, extraMeta }) {
2515
2591
  const preview = row.description.length > 120 ? row.description.slice(0, 117) + "\u2026" : row.description;
2516
2592
  return /* @__PURE__ */ jsxs5("button", { type: "button", class: "mine-row", onClick, children: [
2517
2593
  /* @__PURE__ */ jsxs5("div", { class: "mine-row-pills", children: [
2518
- /* @__PURE__ */ jsx4("span", { class: statusClassName(row.status), children: strings[`status.${row.status}`] ?? row.status }),
2519
- /* @__PURE__ */ jsx4("span", { class: typeClassName(), children: strings[`type.${row.feedback_type}`] }),
2520
- /* @__PURE__ */ jsx4("span", { class: severityClassName(row.severity), children: strings[`severity.${row.severity}`] })
2594
+ /* @__PURE__ */ jsx5("span", { class: statusClassName(row.status), children: strings[`status.${row.status}`] ?? row.status }),
2595
+ /* @__PURE__ */ jsx5("span", { class: typeClassName(), children: strings[`type.${row.feedback_type}`] }),
2596
+ /* @__PURE__ */ jsx5("span", { class: severityClassName(row.severity), children: strings[`severity.${row.severity}`] })
2521
2597
  ] }),
2522
- /* @__PURE__ */ jsx4("div", { class: "mine-row-preview", children: preview }),
2598
+ /* @__PURE__ */ jsx5("div", { class: "mine-row-preview", children: preview }),
2523
2599
  /* @__PURE__ */ jsxs5("div", { class: "mine-row-meta", children: [
2524
- /* @__PURE__ */ jsx4("span", { children: formatRelative2(row.updated_at || row.created_at) }),
2600
+ /* @__PURE__ */ jsx5("span", { children: formatRelative2(row.updated_at || row.created_at) }),
2525
2601
  row.comment_count > 0 && /* @__PURE__ */ jsxs5("span", { children: [
2526
2602
  "\xB7 ",
2527
2603
  repliesLabel(row.comment_count, strings)
@@ -2535,7 +2611,7 @@ function ReportRow({ row, strings, onClick, extraMeta }) {
2535
2611
  }
2536
2612
 
2537
2613
  // src/widget/ChangelogList.tsx
2538
- import { jsx as jsx5, jsxs as jsxs6 } from "preact/jsx-runtime";
2614
+ import { jsx as jsx6, jsxs as jsxs6 } from "preact/jsx-runtime";
2539
2615
  var POLL_MS3 = 3e4;
2540
2616
  function isoWeekKey(iso) {
2541
2617
  const d = new Date(iso);
@@ -2571,9 +2647,9 @@ function formatWeekLabel(weekKey) {
2571
2647
  }
2572
2648
  }
2573
2649
  function ChangelogList({ api, externalId, strings, onSelect }) {
2574
- const [rows, setRows] = useState3(null);
2575
- const [error, setError] = useState3(null);
2576
- const [refreshing, setRefreshing] = useState3(false);
2650
+ const [rows, setRows] = useState4(null);
2651
+ const [error, setError] = useState4(null);
2652
+ const [refreshing, setRefreshing] = useState4(false);
2577
2653
  const mountedRef = useRef2(true);
2578
2654
  const fetchRows = async () => {
2579
2655
  setRefreshing(true);
@@ -2606,8 +2682,8 @@ function ChangelogList({ api, externalId, strings, onSelect }) {
2606
2682
  const isEmpty = rows !== null && rows.length === 0;
2607
2683
  return /* @__PURE__ */ jsxs6("div", { class: "mine-list", children: [
2608
2684
  /* @__PURE__ */ jsxs6("div", { class: "mine-list-header", children: [
2609
- /* @__PURE__ */ jsx5("h2", { children: strings["tab.changelog"] }),
2610
- /* @__PURE__ */ jsx5(
2685
+ /* @__PURE__ */ jsx6("h2", { children: strings["tab.changelog"] }),
2686
+ /* @__PURE__ */ jsx6(
2611
2687
  "button",
2612
2688
  {
2613
2689
  type: "button",
@@ -2620,20 +2696,20 @@ function ChangelogList({ api, externalId, strings, onSelect }) {
2620
2696
  }
2621
2697
  )
2622
2698
  ] }),
2623
- isLoading && /* @__PURE__ */ jsx5("div", { class: "mine-loading", children: strings["mine.loading"] }),
2624
- error && /* @__PURE__ */ jsx5("div", { class: "error", children: error }),
2699
+ isLoading && /* @__PURE__ */ jsx6("div", { class: "mine-loading", children: strings["mine.loading"] }),
2700
+ error && /* @__PURE__ */ jsx6("div", { class: "error", children: error }),
2625
2701
  isEmpty && /* @__PURE__ */ jsxs6("div", { class: "mine-empty", children: [
2626
- /* @__PURE__ */ jsx5("strong", { children: strings["changelog.empty.title"] }),
2627
- /* @__PURE__ */ jsx5("p", { children: strings["changelog.empty.body"] })
2702
+ /* @__PURE__ */ jsx6("strong", { children: strings["changelog.empty.title"] }),
2703
+ /* @__PURE__ */ jsx6("p", { children: strings["changelog.empty.body"] })
2628
2704
  ] }),
2629
- groups.length > 0 && /* @__PURE__ */ jsx5("div", { class: "changelog-groups", children: groups.map((g) => /* @__PURE__ */ jsxs6("section", { class: "changelog-group", children: [
2705
+ groups.length > 0 && /* @__PURE__ */ jsx6("div", { class: "changelog-groups", children: groups.map((g) => /* @__PURE__ */ jsxs6("section", { class: "changelog-group", children: [
2630
2706
  /* @__PURE__ */ jsxs6("header", { class: "changelog-group-header", children: [
2631
- /* @__PURE__ */ jsx5("span", { class: "changelog-group-marker", "aria-hidden": "true", children: "\u25CF" }),
2632
- /* @__PURE__ */ jsx5("span", { class: "changelog-group-label", children: strings["changelog.week_of"].replace("{date}", g.label) }),
2633
- /* @__PURE__ */ jsx5("span", { class: "changelog-group-rule", "aria-hidden": "true" }),
2634
- /* @__PURE__ */ jsx5("span", { class: "changelog-group-count", children: strings[g.rows.length === 1 ? "changelog.resolved_one" : "changelog.resolved_many"].replace("{count}", String(g.rows.length)) })
2707
+ /* @__PURE__ */ jsx6("span", { class: "changelog-group-marker", "aria-hidden": "true", children: "\u25CF" }),
2708
+ /* @__PURE__ */ jsx6("span", { class: "changelog-group-label", children: strings["changelog.week_of"].replace("{date}", g.label) }),
2709
+ /* @__PURE__ */ jsx6("span", { class: "changelog-group-rule", "aria-hidden": "true" }),
2710
+ /* @__PURE__ */ jsx6("span", { class: "changelog-group-count", children: strings[g.rows.length === 1 ? "changelog.resolved_one" : "changelog.resolved_many"].replace("{count}", String(g.rows.length)) })
2635
2711
  ] }),
2636
- /* @__PURE__ */ jsx5("ul", { class: "mine-rows", children: g.rows.map((row) => /* @__PURE__ */ jsx5("li", { children: /* @__PURE__ */ jsx5(
2712
+ /* @__PURE__ */ jsx6("ul", { class: "mine-rows", children: g.rows.map((row) => /* @__PURE__ */ jsx6("li", { children: /* @__PURE__ */ jsx6(
2637
2713
  ReportRow,
2638
2714
  {
2639
2715
  row,
@@ -2647,7 +2723,7 @@ function ChangelogList({ api, externalId, strings, onSelect }) {
2647
2723
  }
2648
2724
 
2649
2725
  // src/widget/Fab.tsx
2650
- import { jsx as jsx6, jsxs as jsxs7 } from "preact/jsx-runtime";
2726
+ import { jsx as jsx7, jsxs as jsxs7 } from "preact/jsx-runtime";
2651
2727
  function BugIcon() {
2652
2728
  return /* @__PURE__ */ jsxs7(
2653
2729
  "svg",
@@ -2663,34 +2739,34 @@ function BugIcon() {
2663
2739
  "aria-hidden": "true",
2664
2740
  focusable: "false",
2665
2741
  children: [
2666
- /* @__PURE__ */ jsx6("path", { d: "m8 2 1.88 1.88" }),
2667
- /* @__PURE__ */ jsx6("path", { d: "M14.12 3.88 16 2" }),
2668
- /* @__PURE__ */ jsx6("path", { d: "M9 7.13v-1a3.003 3.003 0 1 1 6 0v1" }),
2669
- /* @__PURE__ */ jsx6("path", { d: "M12 20c-3.3 0-6-2.7-6-6v-3a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v3c0 3.3-2.7 6-6 6" }),
2670
- /* @__PURE__ */ jsx6("path", { d: "M12 20v-9" }),
2671
- /* @__PURE__ */ jsx6("path", { d: "M6.53 9C4.6 8.8 3 7.1 3 5" }),
2672
- /* @__PURE__ */ jsx6("path", { d: "M6 13H2" }),
2673
- /* @__PURE__ */ jsx6("path", { d: "M3 21c0-2.1 1.7-3.9 3.8-4" }),
2674
- /* @__PURE__ */ jsx6("path", { d: "M20.97 5c0 2.1-1.6 3.8-3.5 4" }),
2675
- /* @__PURE__ */ jsx6("path", { d: "M22 13h-4" }),
2676
- /* @__PURE__ */ jsx6("path", { d: "M17.2 17c2.1.1 3.8 1.9 3.8 4" })
2742
+ /* @__PURE__ */ jsx7("path", { d: "m8 2 1.88 1.88" }),
2743
+ /* @__PURE__ */ jsx7("path", { d: "M14.12 3.88 16 2" }),
2744
+ /* @__PURE__ */ jsx7("path", { d: "M9 7.13v-1a3.003 3.003 0 1 1 6 0v1" }),
2745
+ /* @__PURE__ */ jsx7("path", { d: "M12 20c-3.3 0-6-2.7-6-6v-3a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v3c0 3.3-2.7 6-6 6" }),
2746
+ /* @__PURE__ */ jsx7("path", { d: "M12 20v-9" }),
2747
+ /* @__PURE__ */ jsx7("path", { d: "M6.53 9C4.6 8.8 3 7.1 3 5" }),
2748
+ /* @__PURE__ */ jsx7("path", { d: "M6 13H2" }),
2749
+ /* @__PURE__ */ jsx7("path", { d: "M3 21c0-2.1 1.7-3.9 3.8-4" }),
2750
+ /* @__PURE__ */ jsx7("path", { d: "M20.97 5c0 2.1-1.6 3.8-3.5 4" }),
2751
+ /* @__PURE__ */ jsx7("path", { d: "M22 13h-4" }),
2752
+ /* @__PURE__ */ jsx7("path", { d: "M17.2 17c2.1.1 3.8 1.9 3.8 4" })
2677
2753
  ]
2678
2754
  }
2679
2755
  );
2680
2756
  }
2681
2757
  function Fab({ label, onClick, count }) {
2682
2758
  return /* @__PURE__ */ jsxs7("button", { type: "button", class: "fab", "aria-label": label, title: label, onClick, children: [
2683
- /* @__PURE__ */ jsx6(BugIcon, {}),
2684
- count !== void 0 && count > 0 && /* @__PURE__ */ jsx6("span", { class: "fab-badge", "aria-hidden": "true", children: count > 9 ? "9+" : String(count) })
2759
+ /* @__PURE__ */ jsx7(BugIcon, {}),
2760
+ count !== void 0 && count > 0 && /* @__PURE__ */ jsx7("span", { class: "fab-badge", "aria-hidden": "true", children: count > 9 ? "9+" : String(count) })
2685
2761
  ] });
2686
2762
  }
2687
2763
 
2688
2764
  // src/widget/Form.tsx
2689
- import { useEffect as useEffect5, useRef as useRef4, useState as useState5 } from "preact/hooks";
2765
+ import { useEffect as useEffect5, useRef as useRef4, useState as useState6 } from "preact/hooks";
2690
2766
 
2691
2767
  // src/widget/Annotator.tsx
2692
- import { useEffect as useEffect4, useLayoutEffect, useRef as useRef3, useState as useState4 } from "preact/hooks";
2693
- import { jsx as jsx7, jsxs as jsxs8 } from "preact/jsx-runtime";
2768
+ import { useEffect as useEffect4, useLayoutEffect, useRef as useRef3, useState as useState5 } from "preact/hooks";
2769
+ import { jsx as jsx8, jsxs as jsxs8 } from "preact/jsx-runtime";
2694
2770
  var COLORS = ["#ef4444", "#f59e0b", "#10b981", "#3b82f6", "#ffffff"];
2695
2771
  var HIGHLIGHT_ALPHA = 0.35;
2696
2772
  function drawShape(ctx, shape, sourceImage) {
@@ -2812,43 +2888,43 @@ function drawBlur(ctx, shape, sourceImage) {
2812
2888
  ctx.imageSmoothingEnabled = true;
2813
2889
  }
2814
2890
  var Icon = {
2815
- rect: /* @__PURE__ */ jsx7("svg", { width: "16", height: "16", viewBox: "0 0 16 16", "aria-hidden": "true", children: /* @__PURE__ */ jsx7("rect", { x: "2", y: "3", width: "12", height: "10", fill: "none", stroke: "currentColor", "stroke-width": "1.5" }) }),
2816
- arrow: /* @__PURE__ */ jsx7("svg", { width: "16", height: "16", viewBox: "0 0 16 16", "aria-hidden": "true", children: /* @__PURE__ */ jsx7("path", { d: "M2 8h11M9 4l4 4-4 4", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round" }) }),
2817
- pencil: /* @__PURE__ */ jsx7("svg", { width: "16", height: "16", viewBox: "0 0 16 16", "aria-hidden": "true", children: /* @__PURE__ */ jsx7("path", { d: "M11.5 2.5l2 2L5 13H3v-2l8.5-8.5z", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linejoin": "round" }) }),
2818
- text: /* @__PURE__ */ jsx7("svg", { width: "16", height: "16", viewBox: "0 0 16 16", "aria-hidden": "true", children: /* @__PURE__ */ jsx7("path", { d: "M3 3h10M8 3v10M5 13h6", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round" }) }),
2891
+ rect: /* @__PURE__ */ jsx8("svg", { width: "16", height: "16", viewBox: "0 0 16 16", "aria-hidden": "true", children: /* @__PURE__ */ jsx8("rect", { x: "2", y: "3", width: "12", height: "10", fill: "none", stroke: "currentColor", "stroke-width": "1.5" }) }),
2892
+ arrow: /* @__PURE__ */ jsx8("svg", { width: "16", height: "16", viewBox: "0 0 16 16", "aria-hidden": "true", children: /* @__PURE__ */ jsx8("path", { d: "M2 8h11M9 4l4 4-4 4", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round" }) }),
2893
+ pencil: /* @__PURE__ */ jsx8("svg", { width: "16", height: "16", viewBox: "0 0 16 16", "aria-hidden": "true", children: /* @__PURE__ */ jsx8("path", { d: "M11.5 2.5l2 2L5 13H3v-2l8.5-8.5z", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linejoin": "round" }) }),
2894
+ text: /* @__PURE__ */ jsx8("svg", { width: "16", height: "16", viewBox: "0 0 16 16", "aria-hidden": "true", children: /* @__PURE__ */ jsx8("path", { d: "M3 3h10M8 3v10M5 13h6", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round" }) }),
2819
2895
  highlight: /* @__PURE__ */ jsxs8("svg", { width: "16", height: "16", viewBox: "0 0 16 16", "aria-hidden": "true", children: [
2820
- /* @__PURE__ */ jsx7("path", { d: "M3 13l3-3L11 5l-2-2-5 5-3 3v2h2zM10 4l2 2", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round" }),
2821
- /* @__PURE__ */ jsx7("path", { d: "M2 14h12", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round" })
2896
+ /* @__PURE__ */ jsx8("path", { d: "M3 13l3-3L11 5l-2-2-5 5-3 3v2h2zM10 4l2 2", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round" }),
2897
+ /* @__PURE__ */ jsx8("path", { d: "M2 14h12", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round" })
2822
2898
  ] }),
2823
2899
  blur: /* @__PURE__ */ jsxs8("svg", { width: "16", height: "16", viewBox: "0 0 16 16", "aria-hidden": "true", children: [
2824
- /* @__PURE__ */ jsx7("rect", { x: "2", y: "2", width: "4", height: "4", fill: "currentColor", opacity: "0.85" }),
2825
- /* @__PURE__ */ jsx7("rect", { x: "7", y: "2", width: "3", height: "3", fill: "currentColor", opacity: "0.55" }),
2826
- /* @__PURE__ */ jsx7("rect", { x: "11", y: "2", width: "3", height: "4", fill: "currentColor", opacity: "0.4" }),
2827
- /* @__PURE__ */ jsx7("rect", { x: "2", y: "7", width: "3", height: "3", fill: "currentColor", opacity: "0.6" }),
2828
- /* @__PURE__ */ jsx7("rect", { x: "6", y: "7", width: "3", height: "3", fill: "currentColor", opacity: "0.85" }),
2829
- /* @__PURE__ */ jsx7("rect", { x: "10", y: "7", width: "4", height: "3", fill: "currentColor", opacity: "0.5" }),
2830
- /* @__PURE__ */ jsx7("rect", { x: "2", y: "11", width: "4", height: "3", fill: "currentColor", opacity: "0.4" }),
2831
- /* @__PURE__ */ jsx7("rect", { x: "7", y: "11", width: "3", height: "3", fill: "currentColor", opacity: "0.65" }),
2832
- /* @__PURE__ */ jsx7("rect", { x: "11", y: "11", width: "3", height: "3", fill: "currentColor", opacity: "0.85" })
2900
+ /* @__PURE__ */ jsx8("rect", { x: "2", y: "2", width: "4", height: "4", fill: "currentColor", opacity: "0.85" }),
2901
+ /* @__PURE__ */ jsx8("rect", { x: "7", y: "2", width: "3", height: "3", fill: "currentColor", opacity: "0.55" }),
2902
+ /* @__PURE__ */ jsx8("rect", { x: "11", y: "2", width: "3", height: "4", fill: "currentColor", opacity: "0.4" }),
2903
+ /* @__PURE__ */ jsx8("rect", { x: "2", y: "7", width: "3", height: "3", fill: "currentColor", opacity: "0.6" }),
2904
+ /* @__PURE__ */ jsx8("rect", { x: "6", y: "7", width: "3", height: "3", fill: "currentColor", opacity: "0.85" }),
2905
+ /* @__PURE__ */ jsx8("rect", { x: "10", y: "7", width: "4", height: "3", fill: "currentColor", opacity: "0.5" }),
2906
+ /* @__PURE__ */ jsx8("rect", { x: "2", y: "11", width: "4", height: "3", fill: "currentColor", opacity: "0.4" }),
2907
+ /* @__PURE__ */ jsx8("rect", { x: "7", y: "11", width: "3", height: "3", fill: "currentColor", opacity: "0.65" }),
2908
+ /* @__PURE__ */ jsx8("rect", { x: "11", y: "11", width: "3", height: "3", fill: "currentColor", opacity: "0.85" })
2833
2909
  ] }),
2834
- undo: /* @__PURE__ */ jsx7("svg", { width: "14", height: "14", viewBox: "0 0 16 16", "aria-hidden": "true", children: /* @__PURE__ */ jsx7("path", { d: "M4 7l3-3M4 7l3 3M4 7h6a3 3 0 0 1 0 6H7", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round" }) }),
2835
- redo: /* @__PURE__ */ jsx7("svg", { width: "14", height: "14", viewBox: "0 0 16 16", "aria-hidden": "true", children: /* @__PURE__ */ jsx7("path", { d: "M12 7l-3-3M12 7l-3 3M12 7H6a3 3 0 0 0 0 6h2", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round" }) }),
2836
- trash: /* @__PURE__ */ jsx7("svg", { width: "14", height: "14", viewBox: "0 0 16 16", "aria-hidden": "true", children: /* @__PURE__ */ jsx7("path", { d: "M3 4h10M6 4V2.5h4V4M5 4l.5 9h5L11 4", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round" }) }),
2837
- close: /* @__PURE__ */ jsx7("svg", { width: "16", height: "16", viewBox: "0 0 16 16", "aria-hidden": "true", children: /* @__PURE__ */ jsx7("path", { d: "M4 4l8 8M12 4l-8 8", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round" }) })
2910
+ undo: /* @__PURE__ */ jsx8("svg", { width: "14", height: "14", viewBox: "0 0 16 16", "aria-hidden": "true", children: /* @__PURE__ */ jsx8("path", { d: "M4 7l3-3M4 7l3 3M4 7h6a3 3 0 0 1 0 6H7", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round" }) }),
2911
+ redo: /* @__PURE__ */ jsx8("svg", { width: "14", height: "14", viewBox: "0 0 16 16", "aria-hidden": "true", children: /* @__PURE__ */ jsx8("path", { d: "M12 7l-3-3M12 7l-3 3M12 7H6a3 3 0 0 0 0 6h2", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round" }) }),
2912
+ trash: /* @__PURE__ */ jsx8("svg", { width: "14", height: "14", viewBox: "0 0 16 16", "aria-hidden": "true", children: /* @__PURE__ */ jsx8("path", { d: "M3 4h10M6 4V2.5h4V4M5 4l.5 9h5L11 4", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round" }) }),
2913
+ close: /* @__PURE__ */ jsx8("svg", { width: "16", height: "16", viewBox: "0 0 16 16", "aria-hidden": "true", children: /* @__PURE__ */ jsx8("path", { d: "M4 4l8 8M12 4l-8 8", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round" }) })
2838
2914
  };
2839
2915
  function Annotator({ imageBlob, strings, onSave, onCancel }) {
2840
2916
  const canvasRef = useRef3(null);
2841
2917
  const containerRef = useRef3(null);
2842
2918
  const imageRef = useRef3(null);
2843
- const [tool, setTool] = useState4("rectangle");
2844
- const [color, setColor] = useState4(COLORS[0]);
2845
- const [shapes, setShapes] = useState4([]);
2846
- const [past, setPast] = useState4([]);
2847
- const [future, setFuture] = useState4([]);
2919
+ const [tool, setTool] = useState5("rectangle");
2920
+ const [color, setColor] = useState5(COLORS[0]);
2921
+ const [shapes, setShapes] = useState5([]);
2922
+ const [past, setPast] = useState5([]);
2923
+ const [future, setFuture] = useState5([]);
2848
2924
  const isDrawingRef = useRef3(false);
2849
- const [draftShape, setDraftShape] = useState4(null);
2850
- const [imageLoaded, setImageLoaded] = useState4(false);
2851
- const [saving, setSaving] = useState4(false);
2925
+ const [draftShape, setDraftShape] = useState5(null);
2926
+ const [imageLoaded, setImageLoaded] = useState5(false);
2927
+ const [saving, setSaving] = useState5(false);
2852
2928
  const scaleRef = useRef3(1);
2853
2929
  function addShape(shape) {
2854
2930
  setShapes((s) => {
@@ -3068,7 +3144,7 @@ function Annotator({ imageBlob, strings, onSave, onCancel }) {
3068
3144
  { id: "highlight", icon: Icon.highlight, label: strings["annotator.tool.highlight"] },
3069
3145
  { id: "blur", icon: Icon.blur, label: strings["annotator.tool.blur"] }
3070
3146
  ];
3071
- return /* @__PURE__ */ jsx7(
3147
+ return /* @__PURE__ */ jsx8(
3072
3148
  "div",
3073
3149
  {
3074
3150
  class: "annotator-backdrop",
@@ -3078,8 +3154,8 @@ function Annotator({ imageBlob, strings, onSave, onCancel }) {
3078
3154
  },
3079
3155
  children: /* @__PURE__ */ jsxs8("div", { class: "annotator", role: "dialog", "aria-modal": "true", "aria-label": strings["annotator.title"], children: [
3080
3156
  /* @__PURE__ */ jsxs8("div", { class: "annotator-header", children: [
3081
- /* @__PURE__ */ jsx7("span", { children: strings["annotator.title"] }),
3082
- /* @__PURE__ */ jsx7(
3157
+ /* @__PURE__ */ jsx8("span", { children: strings["annotator.title"] }),
3158
+ /* @__PURE__ */ jsx8(
3083
3159
  "button",
3084
3160
  {
3085
3161
  type: "button",
@@ -3091,7 +3167,7 @@ function Annotator({ imageBlob, strings, onSave, onCancel }) {
3091
3167
  )
3092
3168
  ] }),
3093
3169
  /* @__PURE__ */ jsxs8("div", { class: "annotator-toolbar", children: [
3094
- /* @__PURE__ */ jsx7("div", { class: "annotator-tools", children: tools.map((t) => /* @__PURE__ */ jsx7(
3170
+ /* @__PURE__ */ jsx8("div", { class: "annotator-tools", children: tools.map((t) => /* @__PURE__ */ jsx8(
3095
3171
  "button",
3096
3172
  {
3097
3173
  type: "button",
@@ -3104,9 +3180,9 @@ function Annotator({ imageBlob, strings, onSave, onCancel }) {
3104
3180
  },
3105
3181
  t.id
3106
3182
  )) }),
3107
- /* @__PURE__ */ jsx7("span", { class: "annotator-sep" }),
3183
+ /* @__PURE__ */ jsx8("span", { class: "annotator-sep" }),
3108
3184
  /* @__PURE__ */ jsxs8("div", { class: "annotator-colors", children: [
3109
- COLORS.map((c) => /* @__PURE__ */ jsx7(
3185
+ COLORS.map((c) => /* @__PURE__ */ jsx8(
3110
3186
  "button",
3111
3187
  {
3112
3188
  type: "button",
@@ -3118,7 +3194,7 @@ function Annotator({ imageBlob, strings, onSave, onCancel }) {
3118
3194
  },
3119
3195
  c
3120
3196
  )),
3121
- /* @__PURE__ */ jsx7("label", { class: "annotator-color annotator-color-picker", title: strings["annotator.color_picker"], children: /* @__PURE__ */ jsx7(
3197
+ /* @__PURE__ */ jsx8("label", { class: "annotator-color annotator-color-picker", title: strings["annotator.color_picker"], children: /* @__PURE__ */ jsx8(
3122
3198
  "input",
3123
3199
  {
3124
3200
  type: "color",
@@ -3128,7 +3204,7 @@ function Annotator({ imageBlob, strings, onSave, onCancel }) {
3128
3204
  }
3129
3205
  ) })
3130
3206
  ] }),
3131
- /* @__PURE__ */ jsx7("span", { class: "annotator-sep" }),
3207
+ /* @__PURE__ */ jsx8("span", { class: "annotator-sep" }),
3132
3208
  /* @__PURE__ */ jsxs8(
3133
3209
  "button",
3134
3210
  {
@@ -3139,7 +3215,7 @@ function Annotator({ imageBlob, strings, onSave, onCancel }) {
3139
3215
  title: strings["annotator.undo"],
3140
3216
  children: [
3141
3217
  Icon.undo,
3142
- /* @__PURE__ */ jsx7("span", { children: strings["annotator.undo"] })
3218
+ /* @__PURE__ */ jsx8("span", { children: strings["annotator.undo"] })
3143
3219
  ]
3144
3220
  }
3145
3221
  ),
@@ -3153,7 +3229,7 @@ function Annotator({ imageBlob, strings, onSave, onCancel }) {
3153
3229
  title: strings["annotator.redo"],
3154
3230
  children: [
3155
3231
  Icon.redo,
3156
- /* @__PURE__ */ jsx7("span", { children: strings["annotator.redo"] })
3232
+ /* @__PURE__ */ jsx8("span", { children: strings["annotator.redo"] })
3157
3233
  ]
3158
3234
  }
3159
3235
  ),
@@ -3166,18 +3242,18 @@ function Annotator({ imageBlob, strings, onSave, onCancel }) {
3166
3242
  disabled: shapes.length === 0,
3167
3243
  children: [
3168
3244
  Icon.trash,
3169
- /* @__PURE__ */ jsx7("span", { children: strings["annotator.clear"] })
3245
+ /* @__PURE__ */ jsx8("span", { children: strings["annotator.clear"] })
3170
3246
  ]
3171
3247
  }
3172
3248
  ),
3173
- /* @__PURE__ */ jsx7("span", { class: "annotator-spacer" }),
3249
+ /* @__PURE__ */ jsx8("span", { class: "annotator-spacer" }),
3174
3250
  /* @__PURE__ */ jsxs8("span", { class: "annotator-count", children: [
3175
3251
  shapes.length,
3176
3252
  " ",
3177
3253
  strings["annotator.count_suffix"]
3178
3254
  ] })
3179
3255
  ] }),
3180
- /* @__PURE__ */ jsx7("div", { ref: containerRef, class: "annotator-canvas-wrap", children: !imageLoaded ? /* @__PURE__ */ jsx7("span", { class: "annotator-loading", children: strings["annotator.loading"] }) : /* @__PURE__ */ jsx7(
3256
+ /* @__PURE__ */ jsx8("div", { ref: containerRef, class: "annotator-canvas-wrap", children: !imageLoaded ? /* @__PURE__ */ jsx8("span", { class: "annotator-loading", children: strings["annotator.loading"] }) : /* @__PURE__ */ jsx8(
3181
3257
  "canvas",
3182
3258
  {
3183
3259
  ref: canvasRef,
@@ -3189,8 +3265,8 @@ function Annotator({ imageBlob, strings, onSave, onCancel }) {
3189
3265
  }
3190
3266
  ) }),
3191
3267
  /* @__PURE__ */ jsxs8("div", { class: "annotator-footer", children: [
3192
- /* @__PURE__ */ jsx7("button", { type: "button", class: "btn", onClick: onCancel, children: strings["form.cancel"] }),
3193
- /* @__PURE__ */ jsx7(
3268
+ /* @__PURE__ */ jsx8("button", { type: "button", class: "btn", onClick: onCancel, children: strings["form.cancel"] }),
3269
+ /* @__PURE__ */ jsx8(
3194
3270
  "button",
3195
3271
  {
3196
3272
  type: "button",
@@ -3207,7 +3283,7 @@ function Annotator({ imageBlob, strings, onSave, onCancel }) {
3207
3283
  }
3208
3284
 
3209
3285
  // src/widget/Form.tsx
3210
- import { jsx as jsx8, jsxs as jsxs9 } from "preact/jsx-runtime";
3286
+ import { jsx as jsx9, jsxs as jsxs9 } from "preact/jsx-runtime";
3211
3287
  var TYPES2 = ["bug", "feature", "question", "praise", "typo"];
3212
3288
  var SEVERITIES2 = ["blocker", "high", "medium", "low"];
3213
3289
  function Form({
@@ -3219,13 +3295,13 @@ function Form({
3219
3295
  submittedSeq,
3220
3296
  onDirtyChange
3221
3297
  }) {
3222
- const [description, setDescription] = useState5("");
3223
- const [feedbackType, setFeedbackType] = useState5("bug");
3224
- const [severity, setSeverity] = useState5("medium");
3225
- const [localError, setLocalError] = useState5("");
3226
- const [shots, setShots] = useState5([]);
3227
- const [isDragOver, setIsDragOver] = useState5(false);
3228
- const [annotatingIndex, setAnnotatingIndex] = useState5(null);
3298
+ const [description, setDescription] = useState6("");
3299
+ const [feedbackType, setFeedbackType] = useState6("bug");
3300
+ const [severity, setSeverity] = useState6("medium");
3301
+ const [localError, setLocalError] = useState6("");
3302
+ const [shots, setShots] = useState6([]);
3303
+ const [isDragOver, setIsDragOver] = useState6(false);
3304
+ const [annotatingIndex, setAnnotatingIndex] = useState6(null);
3229
3305
  const fileInputRef = useRef4(null);
3230
3306
  const dropZoneRef = useRef4(null);
3231
3307
  const submitting = status === "submitting";
@@ -3347,10 +3423,10 @@ function Form({
3347
3423
  onSubmit(values);
3348
3424
  };
3349
3425
  return /* @__PURE__ */ jsxs9("form", { onSubmit: handleSubmit, children: [
3350
- /* @__PURE__ */ jsx8("h2", { children: strings["form.title"] }),
3426
+ /* @__PURE__ */ jsx9("h2", { children: strings["form.title"] }),
3351
3427
  /* @__PURE__ */ jsxs9("div", { class: "field", children: [
3352
- /* @__PURE__ */ jsx8("label", { for: "mfb-desc", children: strings["form.description.label"] }),
3353
- /* @__PURE__ */ jsx8(
3428
+ /* @__PURE__ */ jsx9("label", { for: "mfb-desc", children: strings["form.description.label"] }),
3429
+ /* @__PURE__ */ jsx9(
3354
3430
  "textarea",
3355
3431
  {
3356
3432
  id: "mfb-desc",
@@ -3362,33 +3438,33 @@ function Form({
3362
3438
  ] }),
3363
3439
  /* @__PURE__ */ jsxs9("div", { class: "row", children: [
3364
3440
  /* @__PURE__ */ jsxs9("div", { class: "field", children: [
3365
- /* @__PURE__ */ jsx8("label", { for: "mfb-type", children: strings["form.type.label"] }),
3366
- /* @__PURE__ */ jsx8(
3441
+ /* @__PURE__ */ jsx9("label", { for: "mfb-type", children: strings["form.type.label"] }),
3442
+ /* @__PURE__ */ jsx9(
3367
3443
  "select",
3368
3444
  {
3369
3445
  id: "mfb-type",
3370
3446
  value: feedbackType,
3371
3447
  onChange: (e) => setFeedbackType(e.target.value),
3372
- children: TYPES2.map((t) => /* @__PURE__ */ jsx8("option", { value: t, children: strings[`type.${t}`] }))
3448
+ children: TYPES2.map((t) => /* @__PURE__ */ jsx9("option", { value: t, children: strings[`type.${t}`] }))
3373
3449
  }
3374
3450
  )
3375
3451
  ] }),
3376
3452
  /* @__PURE__ */ jsxs9("div", { class: "field", children: [
3377
- /* @__PURE__ */ jsx8("label", { for: "mfb-sev", children: strings["form.severity.label"] }),
3378
- /* @__PURE__ */ jsx8(
3453
+ /* @__PURE__ */ jsx9("label", { for: "mfb-sev", children: strings["form.severity.label"] }),
3454
+ /* @__PURE__ */ jsx9(
3379
3455
  "select",
3380
3456
  {
3381
3457
  id: "mfb-sev",
3382
3458
  value: severity,
3383
3459
  onChange: (e) => setSeverity(e.target.value),
3384
- children: SEVERITIES2.map((s) => /* @__PURE__ */ jsx8("option", { value: s, children: strings[`severity.${s}`] }))
3460
+ children: SEVERITIES2.map((s) => /* @__PURE__ */ jsx9("option", { value: s, children: strings[`severity.${s}`] }))
3385
3461
  }
3386
3462
  )
3387
3463
  ] })
3388
3464
  ] }),
3389
3465
  /* @__PURE__ */ jsxs9("div", { class: "field", children: [
3390
- /* @__PURE__ */ jsx8("label", { children: strings["form.screenshot.label"] }),
3391
- /* @__PURE__ */ jsx8(
3466
+ /* @__PURE__ */ jsx9("label", { children: strings["form.screenshot.label"] }),
3467
+ /* @__PURE__ */ jsx9(
3392
3468
  "input",
3393
3469
  {
3394
3470
  ref: fileInputRef,
@@ -3401,8 +3477,8 @@ function Form({
3401
3477
  tabIndex: -1
3402
3478
  }
3403
3479
  ),
3404
- shots.length > 0 && /* @__PURE__ */ jsx8("div", { class: "screenshot-strip", children: shots.map((shot, index) => /* @__PURE__ */ jsxs9("div", { class: "screenshot-preview", children: [
3405
- /* @__PURE__ */ jsx8("img", { src: shot.preview, alt: "" }),
3480
+ shots.length > 0 && /* @__PURE__ */ jsx9("div", { class: "screenshot-strip", children: shots.map((shot, index) => /* @__PURE__ */ jsxs9("div", { class: "screenshot-preview", children: [
3481
+ /* @__PURE__ */ jsx9("img", { src: shot.preview, alt: "" }),
3406
3482
  /* @__PURE__ */ jsxs9("div", { class: "screenshot-preview-actions", children: [
3407
3483
  /* @__PURE__ */ jsxs9(
3408
3484
  "button",
@@ -3412,15 +3488,15 @@ function Form({
3412
3488
  onClick: () => setAnnotatingIndex(index),
3413
3489
  children: [
3414
3490
  /* @__PURE__ */ jsxs9("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true", children: [
3415
- /* @__PURE__ */ jsx8("path", { d: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }),
3416
- /* @__PURE__ */ jsx8("path", { d: "M18.5 2.5a2.12 2.12 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
3491
+ /* @__PURE__ */ jsx9("path", { d: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }),
3492
+ /* @__PURE__ */ jsx9("path", { d: "M18.5 2.5a2.12 2.12 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
3417
3493
  ] }),
3418
3494
  strings["form.screenshot.annotate"]
3419
3495
  ]
3420
3496
  }
3421
3497
  ),
3422
3498
  /* @__PURE__ */ jsxs9("button", { type: "button", class: "btn", onClick: () => removeShot(index), children: [
3423
- /* @__PURE__ */ jsx8("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx8("path", { d: "M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2m3 0v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6h14z" }) }),
3499
+ /* @__PURE__ */ jsx9("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx9("path", { d: "M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2m3 0v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6h14z" }) }),
3424
3500
  strings["form.screenshot.remove"]
3425
3501
  ] })
3426
3502
  ] })
@@ -3445,33 +3521,33 @@ function Form({
3445
3521
  onDrop: handleDrop,
3446
3522
  children: [
3447
3523
  /* @__PURE__ */ jsxs9("svg", { class: "screenshot-icon", width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "1.6", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true", children: [
3448
- /* @__PURE__ */ jsx8("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
3449
- /* @__PURE__ */ jsx8("polyline", { points: "17 8 12 3 7 8" }),
3450
- /* @__PURE__ */ jsx8("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
3524
+ /* @__PURE__ */ jsx9("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
3525
+ /* @__PURE__ */ jsx9("polyline", { points: "17 8 12 3 7 8" }),
3526
+ /* @__PURE__ */ jsx9("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
3451
3527
  ] }),
3452
3528
  /* @__PURE__ */ jsxs9("div", { class: "screenshot-cta", children: [
3453
- /* @__PURE__ */ jsx8("strong", { children: strings["form.screenshot.cta_click"] }),
3529
+ /* @__PURE__ */ jsx9("strong", { children: strings["form.screenshot.cta_click"] }),
3454
3530
  ", ",
3455
3531
  strings["form.screenshot.cta_rest"]
3456
3532
  ] }),
3457
- /* @__PURE__ */ jsx8("div", { class: "screenshot-formats", children: strings["form.screenshot.formats"] })
3533
+ /* @__PURE__ */ jsx9("div", { class: "screenshot-formats", children: strings["form.screenshot.formats"] })
3458
3534
  ]
3459
3535
  }
3460
3536
  )
3461
3537
  ] }),
3462
3538
  pageUrl && /* @__PURE__ */ jsxs9("div", { class: "page-context", title: pageUrl, children: [
3463
- /* @__PURE__ */ jsx8("span", { class: "page-context-label", children: strings["form.context.label"] }),
3464
- /* @__PURE__ */ jsx8("span", { class: "page-context-url", children: truncateUrl(pageUrl, 90) })
3539
+ /* @__PURE__ */ jsx9("span", { class: "page-context-label", children: strings["form.context.label"] }),
3540
+ /* @__PURE__ */ jsx9("span", { class: "page-context-url", children: truncateUrl(pageUrl, 90) })
3465
3541
  ] }),
3466
- /* @__PURE__ */ jsx8("div", { class: "capture-notice", children: strings["form.capture.notice"] }),
3467
- localError && /* @__PURE__ */ jsx8("div", { class: "error", children: localError }),
3468
- status === "error" && errorMessage && /* @__PURE__ */ jsx8("div", { class: "error", children: errorMessage }),
3469
- status === "success" && /* @__PURE__ */ jsx8("div", { class: "success", children: submittedSeq !== void 0 ? strings["form.success.seq"].replace("{seq}", String(submittedSeq)) : strings["form.success"] }),
3542
+ /* @__PURE__ */ jsx9("div", { class: "capture-notice", children: strings["form.capture.notice"] }),
3543
+ localError && /* @__PURE__ */ jsx9("div", { class: "error", children: localError }),
3544
+ status === "error" && errorMessage && /* @__PURE__ */ jsx9("div", { class: "error", children: errorMessage }),
3545
+ status === "success" && /* @__PURE__ */ jsx9("div", { class: "success", children: submittedSeq !== void 0 ? strings["form.success.seq"].replace("{seq}", String(submittedSeq)) : strings["form.success"] }),
3470
3546
  /* @__PURE__ */ jsxs9("div", { class: "actions", children: [
3471
- /* @__PURE__ */ jsx8("button", { type: "button", class: "btn", onClick: onCancel, disabled: submitting, children: strings["form.cancel"] }),
3472
- /* @__PURE__ */ jsx8("button", { type: "submit", class: "btn btn--primary", disabled: submitting, children: submitLabel })
3547
+ /* @__PURE__ */ jsx9("button", { type: "button", class: "btn", onClick: onCancel, disabled: submitting, children: strings["form.cancel"] }),
3548
+ /* @__PURE__ */ jsx9("button", { type: "submit", class: "btn btn--primary", disabled: submitting, children: submitLabel })
3473
3549
  ] }),
3474
- annotatingIndex !== null && shots[annotatingIndex] && /* @__PURE__ */ jsx8(
3550
+ annotatingIndex !== null && shots[annotatingIndex] && /* @__PURE__ */ jsx9(
3475
3551
  Annotator,
3476
3552
  {
3477
3553
  imageBlob: shots[annotatingIndex].blob,
@@ -3484,10 +3560,10 @@ function Form({
3484
3560
  }
3485
3561
 
3486
3562
  // src/widget/MineList.tsx
3487
- import { useEffect as useEffect6, useRef as useRef5, useState as useState6 } from "preact/hooks";
3563
+ import { useEffect as useEffect6, useRef as useRef5, useState as useState7 } from "preact/hooks";
3488
3564
 
3489
3565
  // src/widget/KpiStrip.tsx
3490
- import { jsx as jsx9, jsxs as jsxs10 } from "preact/jsx-runtime";
3566
+ import { jsx as jsx10, jsxs as jsxs10 } from "preact/jsx-runtime";
3491
3567
  function computeKpiCounts(rows) {
3492
3568
  const counts = {
3493
3569
  new: 0,
@@ -3554,7 +3630,7 @@ function KpiStrip({ rows, filter, onFilter, strings }) {
3554
3630
  value: resolutionRate === null ? "\u2014" : `${resolutionRate}%`
3555
3631
  }
3556
3632
  ];
3557
- return /* @__PURE__ */ jsx9("div", { class: "kpi-strip", role: "toolbar", children: cells.map((c) => {
3633
+ return /* @__PURE__ */ jsx10("div", { class: "kpi-strip", role: "toolbar", children: cells.map((c) => {
3558
3634
  const active = filter === c.key;
3559
3635
  const toggleTo = active ? "all" : c.key;
3560
3636
  return /* @__PURE__ */ jsxs10(
@@ -3565,8 +3641,8 @@ function KpiStrip({ rows, filter, onFilter, strings }) {
3565
3641
  onClick: () => onFilter(toggleTo),
3566
3642
  "aria-pressed": active,
3567
3643
  children: [
3568
- /* @__PURE__ */ jsx9("span", { class: "kpi-value", children: c.value }),
3569
- /* @__PURE__ */ jsx9("span", { class: "kpi-label", children: c.label })
3644
+ /* @__PURE__ */ jsx10("span", { class: "kpi-value", children: c.value }),
3645
+ /* @__PURE__ */ jsx10("span", { class: "kpi-label", children: c.label })
3570
3646
  ]
3571
3647
  }
3572
3648
  );
@@ -3574,16 +3650,16 @@ function KpiStrip({ rows, filter, onFilter, strings }) {
3574
3650
  }
3575
3651
 
3576
3652
  // src/widget/MineList.tsx
3577
- import { jsx as jsx10, jsxs as jsxs11 } from "preact/jsx-runtime";
3653
+ import { jsx as jsx11, jsxs as jsxs11 } from "preact/jsx-runtime";
3578
3654
  var POLL_MS4 = 3e4;
3579
3655
  function MineList({ api, externalId, strings, onSelect, onOpenSeq }) {
3580
- const [rows, setRows] = useState6(null);
3581
- const [error, setError] = useState6(null);
3582
- const [refreshing, setRefreshing] = useState6(false);
3583
- const [filter, setFilter] = useState6("all");
3584
- const [jumpValue, setJumpValue] = useState6("");
3585
- const [jumpError, setJumpError] = useState6(false);
3586
- const [jumping, setJumping] = useState6(false);
3656
+ const [rows, setRows] = useState7(null);
3657
+ const [error, setError] = useState7(null);
3658
+ const [refreshing, setRefreshing] = useState7(false);
3659
+ const [filter, setFilter] = useState7("all");
3660
+ const [jumpValue, setJumpValue] = useState7("");
3661
+ const [jumpError, setJumpError] = useState7(false);
3662
+ const [jumping, setJumping] = useState7(false);
3587
3663
  const mountedRef = useRef5(true);
3588
3664
  const handleJump = async (e) => {
3589
3665
  e.preventDefault();
@@ -3635,10 +3711,10 @@ function MineList({ api, externalId, strings, onSelect, onOpenSeq }) {
3635
3711
  const visibleEmpty = !!rows && rows.length > 0 && (visibleRows?.length ?? 0) === 0;
3636
3712
  return /* @__PURE__ */ jsxs11("div", { class: "mine-list", children: [
3637
3713
  /* @__PURE__ */ jsxs11("div", { class: "mine-list-header", children: [
3638
- /* @__PURE__ */ jsx10("h2", { children: strings["tab.mine"] }),
3714
+ /* @__PURE__ */ jsx11("h2", { children: strings["tab.mine"] }),
3639
3715
  /* @__PURE__ */ jsxs11("div", { class: "mine-list-header-actions", children: [
3640
3716
  onOpenSeq && /* @__PURE__ */ jsxs11("form", { class: "mine-jump", onSubmit: handleJump, children: [
3641
- /* @__PURE__ */ jsx10(
3717
+ /* @__PURE__ */ jsx11(
3642
3718
  "input",
3643
3719
  {
3644
3720
  type: "text",
@@ -3653,9 +3729,9 @@ function MineList({ api, externalId, strings, onSelect, onOpenSeq }) {
3653
3729
  disabled: jumping
3654
3730
  }
3655
3731
  ),
3656
- /* @__PURE__ */ jsx10("button", { type: "submit", class: "btn", disabled: jumping || !jumpValue.trim(), children: strings["mine.jump.go"] })
3732
+ /* @__PURE__ */ jsx11("button", { type: "submit", class: "btn", disabled: jumping || !jumpValue.trim(), children: strings["mine.jump.go"] })
3657
3733
  ] }),
3658
- /* @__PURE__ */ jsx10(
3734
+ /* @__PURE__ */ jsx11(
3659
3735
  "button",
3660
3736
  {
3661
3737
  type: "button",
@@ -3669,22 +3745,25 @@ function MineList({ api, externalId, strings, onSelect, onOpenSeq }) {
3669
3745
  )
3670
3746
  ] })
3671
3747
  ] }),
3672
- jumpError && /* @__PURE__ */ jsx10("div", { class: "mine-jump-error error", role: "alert", children: strings["mine.jump.not_found"] }),
3673
- rows && rows.length > 0 && /* @__PURE__ */ jsx10(KpiStrip, { rows, filter, onFilter: setFilter, strings }),
3674
- isLoading && /* @__PURE__ */ jsx10("div", { class: "mine-loading", children: strings["mine.loading"] }),
3675
- error && /* @__PURE__ */ jsx10("div", { class: "error", children: error }),
3748
+ jumpError && /* @__PURE__ */ jsx11("div", { class: "mine-jump-error error", role: "alert", children: strings["mine.jump.not_found"] }),
3749
+ rows && rows.length > 0 && /* @__PURE__ */ jsx11(KpiStrip, { rows, filter, onFilter: setFilter, strings }),
3750
+ isLoading && /* @__PURE__ */ jsx11("div", { class: "mine-loading", children: strings["mine.loading"] }),
3751
+ error && /* @__PURE__ */ jsxs11("div", { class: "error", children: [
3752
+ error,
3753
+ /* @__PURE__ */ jsx11(DiagnosticHint, { api, strings, host: api.endpointHost })
3754
+ ] }),
3676
3755
  isEmpty && /* @__PURE__ */ jsxs11("div", { class: "mine-empty", children: [
3677
- /* @__PURE__ */ jsx10("strong", { children: strings["mine.empty.title"] }),
3678
- /* @__PURE__ */ jsx10("p", { children: strings["mine.empty.body"] })
3756
+ /* @__PURE__ */ jsx11("strong", { children: strings["mine.empty.title"] }),
3757
+ /* @__PURE__ */ jsx11("p", { children: strings["mine.empty.body"] })
3679
3758
  ] }),
3680
- visibleEmpty && /* @__PURE__ */ jsx10("div", { class: "mine-empty", children: /* @__PURE__ */ jsx10("p", { children: strings["mine.filter.empty"] }) }),
3681
- visibleRows && visibleRows.length > 0 && /* @__PURE__ */ jsx10("ul", { class: "mine-rows", children: visibleRows.map((row) => /* @__PURE__ */ jsx10("li", { children: /* @__PURE__ */ jsx10(ReportRow, { row, strings, onClick: () => onSelect(row) }) })) })
3759
+ visibleEmpty && /* @__PURE__ */ jsx11("div", { class: "mine-empty", children: /* @__PURE__ */ jsx11("p", { children: strings["mine.filter.empty"] }) }),
3760
+ visibleRows && visibleRows.length > 0 && /* @__PURE__ */ jsx11("ul", { class: "mine-rows", children: visibleRows.map((row) => /* @__PURE__ */ jsx11("li", { children: /* @__PURE__ */ jsx11(ReportRow, { row, strings, onClick: () => onSelect(row) }) })) })
3682
3761
  ] });
3683
3762
  }
3684
3763
 
3685
3764
  // src/widget/Modal.tsx
3686
3765
  import { useEffect as useEffect7, useRef as useRef6 } from "preact/hooks";
3687
- import { jsx as jsx11, jsxs as jsxs12 } from "preact/jsx-runtime";
3766
+ import { jsx as jsx12, jsxs as jsxs12 } from "preact/jsx-runtime";
3688
3767
  function Modal({ onDismiss, children, closeLabel = "Close", expanded = false }) {
3689
3768
  const modalRef = useRef6(null);
3690
3769
  const previouslyFocused = useRef6(null);
@@ -3710,7 +3789,7 @@ function Modal({ onDismiss, children, closeLabel = "Close", expanded = false })
3710
3789
  if (prev && typeof prev.focus === "function") prev.focus();
3711
3790
  };
3712
3791
  }, [onDismiss]);
3713
- return /* @__PURE__ */ jsx11(
3792
+ return /* @__PURE__ */ jsx12(
3714
3793
  "div",
3715
3794
  {
3716
3795
  class: `backdrop ${expanded ? "is-expanded" : ""}`,
@@ -3726,7 +3805,7 @@ function Modal({ onDismiss, children, closeLabel = "Close", expanded = false })
3726
3805
  role: "dialog",
3727
3806
  "aria-modal": "true",
3728
3807
  children: [
3729
- /* @__PURE__ */ jsx11(
3808
+ /* @__PURE__ */ jsx12(
3730
3809
  "button",
3731
3810
  {
3732
3811
  type: "button",
@@ -3745,7 +3824,7 @@ function Modal({ onDismiss, children, closeLabel = "Close", expanded = false })
3745
3824
  }
3746
3825
 
3747
3826
  // src/widget/PageActivityStrip.tsx
3748
- import { jsx as jsx12, jsxs as jsxs13 } from "preact/jsx-runtime";
3827
+ import { jsx as jsx13, jsxs as jsxs13 } from "preact/jsx-runtime";
3749
3828
  function PageActivityStrip({
3750
3829
  open,
3751
3830
  strings,
@@ -3754,14 +3833,14 @@ function PageActivityStrip({
3754
3833
  if (open === 0) return null;
3755
3834
  const text = open === 1 ? strings["page.strip.text.one"] : strings["page.strip.text"].replace("{n}", String(open));
3756
3835
  return /* @__PURE__ */ jsxs13("div", { class: "page-strip", children: [
3757
- /* @__PURE__ */ jsx12("span", { children: text }),
3758
- /* @__PURE__ */ jsx12("button", { type: "button", class: "page-strip-view", onClick: onView, children: strings["page.strip.view"] })
3836
+ /* @__PURE__ */ jsx13("span", { children: text }),
3837
+ /* @__PURE__ */ jsx13("button", { type: "button", class: "page-strip-view", onClick: onView, children: strings["page.strip.view"] })
3759
3838
  ] });
3760
3839
  }
3761
3840
 
3762
3841
  // src/widget/PagePeekPanel.tsx
3763
- import { useEffect as useEffect8, useState as useState7 } from "preact/hooks";
3764
- import { jsx as jsx13, jsxs as jsxs14 } from "preact/jsx-runtime";
3842
+ import { useEffect as useEffect8, useState as useState8 } from "preact/hooks";
3843
+ import { jsx as jsx14, jsxs as jsxs14 } from "preact/jsx-runtime";
3765
3844
  function PagePeekPanel({
3766
3845
  api,
3767
3846
  externalId,
@@ -3772,8 +3851,8 @@ function PagePeekPanel({
3772
3851
  onPickRow,
3773
3852
  onSend
3774
3853
  }) {
3775
- const [rows, setRows] = useState7(null);
3776
- const [failed, setFailed] = useState7(false);
3854
+ const [rows, setRows] = useState8(null);
3855
+ const [failed, setFailed] = useState8(false);
3777
3856
  useEffect8(() => {
3778
3857
  let cancelled = false;
3779
3858
  const pagePath = currentPagePath(getCurrentPage !== void 0 ? { getCurrentPage } : {});
@@ -3790,11 +3869,11 @@ function PagePeekPanel({
3790
3869
  };
3791
3870
  }, [api, externalId]);
3792
3871
  return /* @__PURE__ */ jsxs14("div", { class: "page-peek", role: "region", "aria-label": strings["page.peek.title"], children: [
3793
- /* @__PURE__ */ jsx13("div", { class: "page-peek-title", children: strings["page.peek.title"] }),
3872
+ /* @__PURE__ */ jsx14("div", { class: "page-peek-title", children: strings["page.peek.title"] }),
3794
3873
  rows === null && !failed && /* @__PURE__ */ jsxs14("div", { class: "page-peek-skeleton", "aria-hidden": "true", children: [
3795
- /* @__PURE__ */ jsx13("div", {}),
3874
+ /* @__PURE__ */ jsx14("div", {}),
3796
3875
  " ",
3797
- /* @__PURE__ */ jsx13("div", {})
3876
+ /* @__PURE__ */ jsx14("div", {})
3798
3877
  ] }),
3799
3878
  rows !== null && rows.map((row) => /* @__PURE__ */ jsxs14(
3800
3879
  "button",
@@ -3803,21 +3882,21 @@ function PagePeekPanel({
3803
3882
  class: "page-peek-row",
3804
3883
  onClick: () => onPickRow?.(row.id),
3805
3884
  children: [
3806
- /* @__PURE__ */ jsx13("span", { class: `page-peek-dot status-${row.status}`, "aria-hidden": "true" }),
3807
- /* @__PURE__ */ jsx13("span", { class: "page-peek-desc", children: row.description })
3885
+ /* @__PURE__ */ jsx14("span", { class: `page-peek-dot status-${row.status}`, "aria-hidden": "true" }),
3886
+ /* @__PURE__ */ jsx14("span", { class: "page-peek-desc", children: row.description })
3808
3887
  ]
3809
3888
  },
3810
3889
  row.id
3811
3890
  )),
3812
3891
  /* @__PURE__ */ jsxs14("div", { class: "page-peek-footer", children: [
3813
- /* @__PURE__ */ jsx13("button", { type: "button", class: "page-peek-viewall", onClick: onViewAll, children: open === 1 ? strings["page.peek.viewAll.one"] : strings["page.peek.viewAll"].replace("{n}", String(open)) }),
3814
- /* @__PURE__ */ jsx13("button", { type: "button", class: "page-peek-send", onClick: onSend, children: strings["fab.label"] })
3892
+ /* @__PURE__ */ jsx14("button", { type: "button", class: "page-peek-viewall", onClick: onViewAll, children: open === 1 ? strings["page.peek.viewAll.one"] : strings["page.peek.viewAll"].replace("{n}", String(open)) }),
3893
+ /* @__PURE__ */ jsx14("button", { type: "button", class: "page-peek-send", onClick: onSend, children: strings["fab.label"] })
3815
3894
  ] })
3816
3895
  ] });
3817
3896
  }
3818
3897
 
3819
3898
  // src/widget/pageSignal.ts
3820
- import { useCallback, useEffect as useEffect9, useState as useState8 } from "preact/hooks";
3899
+ import { useCallback, useEffect as useEffect9, useState as useState9 } from "preact/hooks";
3821
3900
  var TTL_MS2 = 6e4;
3822
3901
  function computeOpenCount(kpis) {
3823
3902
  const s = kpis.by_status;
@@ -3846,8 +3925,8 @@ function fetchOpen(api, externalId, path) {
3846
3925
  }
3847
3926
  function usePageOpenCount(opts) {
3848
3927
  const { api, externalId, getCurrentPage, enabled } = opts;
3849
- const [open, setOpen] = useState8(0);
3850
- const [tick, setTick] = useState8(0);
3928
+ const [open, setOpen] = useState9(0);
3929
+ const [tick, setTick] = useState9(0);
3851
3930
  const refresh = useCallback(() => {
3852
3931
  invalidatePageSignal();
3853
3932
  setTick((t) => t + 1);
@@ -5942,7 +6021,7 @@ button.report-detail-edit {
5942
6021
  `;
5943
6022
 
5944
6023
  // src/widget/mount.tsx
5945
- import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs15 } from "preact/jsx-runtime";
6024
+ import { Fragment as Fragment3, jsx as jsx15, jsxs as jsxs15 } from "preact/jsx-runtime";
5946
6025
  function computeFabVisible(opts, externalId, visibilityAllowed) {
5947
6026
  if (!opts.showFAB) return false;
5948
6027
  if (opts.getExternalId !== void 0 && !externalId) return false;
@@ -6040,7 +6119,7 @@ function mountWidget(options) {
6040
6119
  enabled: pageActivityEnabled
6041
6120
  });
6042
6121
  const fabLabel = pageSignal.open === 1 ? options.strings["page.badge.aria.one"] : pageSignal.open > 0 ? options.strings["page.badge.aria"].replace("{n}", String(pageSignal.open)) : options.strings["fab.label"];
6043
- const [visibilityAllowed, setVisibilityAllowed] = useState9(
6122
+ const [visibilityAllowed, setVisibilityAllowed] = useState10(
6044
6123
  !options.requiresVisibilityCheck
6045
6124
  );
6046
6125
  useEffect10(() => {
@@ -6064,7 +6143,7 @@ function mountWidget(options) {
6064
6143
  }, [externalId]);
6065
6144
  const fabVisible = computeFabVisible(options, externalId, visibilityAllowed);
6066
6145
  const showMineTab = Boolean(options.api && externalId);
6067
- const [peekOpen, setPeekOpen] = useState9(false);
6146
+ const [peekOpen, setPeekOpen] = useState10(false);
6068
6147
  const peekTimers = useRef7({});
6069
6148
  const peekEnter = () => {
6070
6149
  if (peekTimers.current.close) clearTimeout(peekTimers.current.close);
@@ -6088,7 +6167,7 @@ function mountWidget(options) {
6088
6167
  onFocusOut: () => setPeekOpen(false),
6089
6168
  onKeyDown: (e) => e.key === "Escape" && setPeekOpen(false),
6090
6169
  children: [
6091
- peekOpen && !state.open && pageActivityEnabled && pageSignal.open > 0 && options.api && externalId && /* @__PURE__ */ jsx14(
6170
+ peekOpen && !state.open && pageActivityEnabled && pageSignal.open > 0 && options.api && externalId && /* @__PURE__ */ jsx15(
6092
6171
  PagePeekPanel,
6093
6172
  {
6094
6173
  api: options.api,
@@ -6112,7 +6191,7 @@ function mountWidget(options) {
6112
6191
  }
6113
6192
  }
6114
6193
  ),
6115
- /* @__PURE__ */ jsx14(
6194
+ /* @__PURE__ */ jsx15(
6116
6195
  Fab,
6117
6196
  {
6118
6197
  label: fabLabel,
@@ -6144,11 +6223,11 @@ function mountWidget(options) {
6144
6223
  closeLabel: options.strings["form.close"],
6145
6224
  expanded: state.tab === "board",
6146
6225
  children: [
6147
- state.confirmingDiscard && /* @__PURE__ */ jsx14("div", { class: "discard-confirm", role: "alertdialog", "aria-modal": "true", children: /* @__PURE__ */ jsxs15("div", { class: "discard-confirm-card", children: [
6148
- /* @__PURE__ */ jsx14("p", { class: "discard-confirm-title", children: options.strings["form.discard.title"] }),
6149
- /* @__PURE__ */ jsx14("p", { class: "discard-confirm-body", children: options.strings["form.discard.body"] }),
6226
+ state.confirmingDiscard && /* @__PURE__ */ jsx15("div", { class: "discard-confirm", role: "alertdialog", "aria-modal": "true", children: /* @__PURE__ */ jsxs15("div", { class: "discard-confirm-card", children: [
6227
+ /* @__PURE__ */ jsx15("p", { class: "discard-confirm-title", children: options.strings["form.discard.title"] }),
6228
+ /* @__PURE__ */ jsx15("p", { class: "discard-confirm-body", children: options.strings["form.discard.body"] }),
6150
6229
  /* @__PURE__ */ jsxs15("div", { class: "discard-confirm-actions", children: [
6151
- /* @__PURE__ */ jsx14(
6230
+ /* @__PURE__ */ jsx15(
6152
6231
  "button",
6153
6232
  {
6154
6233
  type: "button",
@@ -6157,7 +6236,7 @@ function mountWidget(options) {
6157
6236
  children: options.strings["form.discard.keep"]
6158
6237
  }
6159
6238
  ),
6160
- /* @__PURE__ */ jsx14(
6239
+ /* @__PURE__ */ jsx15(
6161
6240
  "button",
6162
6241
  {
6163
6242
  type: "button",
@@ -6179,7 +6258,7 @@ function mountWidget(options) {
6179
6258
  ] })
6180
6259
  ] }) }),
6181
6260
  showMineTab && /* @__PURE__ */ jsxs15("div", { class: "tab-strip", role: "tablist", children: [
6182
- /* @__PURE__ */ jsx14(
6261
+ /* @__PURE__ */ jsx15(
6183
6262
  "button",
6184
6263
  {
6185
6264
  type: "button",
@@ -6190,7 +6269,7 @@ function mountWidget(options) {
6190
6269
  children: options.strings["tab.send"]
6191
6270
  }
6192
6271
  ),
6193
- /* @__PURE__ */ jsx14(
6272
+ /* @__PURE__ */ jsx15(
6194
6273
  "button",
6195
6274
  {
6196
6275
  type: "button",
@@ -6201,7 +6280,7 @@ function mountWidget(options) {
6201
6280
  children: options.strings["tab.mine"]
6202
6281
  }
6203
6282
  ),
6204
- /* @__PURE__ */ jsx14(
6283
+ /* @__PURE__ */ jsx15(
6205
6284
  "button",
6206
6285
  {
6207
6286
  type: "button",
@@ -6212,7 +6291,7 @@ function mountWidget(options) {
6212
6291
  children: options.strings["tab.changelog"]
6213
6292
  }
6214
6293
  ),
6215
- /* @__PURE__ */ jsx14(
6294
+ /* @__PURE__ */ jsx15(
6216
6295
  "button",
6217
6296
  {
6218
6297
  type: "button",
@@ -6225,7 +6304,7 @@ function mountWidget(options) {
6225
6304
  )
6226
6305
  ] }),
6227
6306
  state.tab === "send" && /* @__PURE__ */ jsxs15(Fragment3, { children: [
6228
- showMineTab && pageActivityEnabled && /* @__PURE__ */ jsx14(
6307
+ showMineTab && pageActivityEnabled && /* @__PURE__ */ jsx15(
6229
6308
  PageActivityStrip,
6230
6309
  {
6231
6310
  open: pageSignal.open,
@@ -6233,7 +6312,7 @@ function mountWidget(options) {
6233
6312
  onView: () => rerender(clearSelected({ ...currentState, tab: "board" }))
6234
6313
  }
6235
6314
  ),
6236
- /* @__PURE__ */ jsx14(
6315
+ /* @__PURE__ */ jsx15(
6237
6316
  Form,
6238
6317
  {
6239
6318
  strings: options.strings,
@@ -6250,7 +6329,7 @@ function mountWidget(options) {
6250
6329
  }
6251
6330
  )
6252
6331
  ] }),
6253
- state.tab === "mine" && options.api && externalId && !state.selectedReportId && /* @__PURE__ */ jsx14(
6332
+ state.tab === "mine" && options.api && externalId && !state.selectedReportId && /* @__PURE__ */ jsx15(
6254
6333
  MineList,
6255
6334
  {
6256
6335
  api: options.api,
@@ -6260,7 +6339,7 @@ function mountWidget(options) {
6260
6339
  onOpenSeq: openSeq
6261
6340
  }
6262
6341
  ),
6263
- (state.tab === "mine" || state.tab === "changelog") && options.api && externalId && state.selectedReportId && /* @__PURE__ */ jsx14(
6342
+ (state.tab === "mine" || state.tab === "changelog") && options.api && externalId && state.selectedReportId && /* @__PURE__ */ jsx15(
6264
6343
  ReportDetailView,
6265
6344
  {
6266
6345
  api: options.api,
@@ -6272,7 +6351,7 @@ function mountWidget(options) {
6272
6351
  ...buildPermalink && { buildPermalink }
6273
6352
  }
6274
6353
  ),
6275
- state.tab === "changelog" && options.api && externalId && !state.selectedReportId && /* @__PURE__ */ jsx14(
6354
+ state.tab === "changelog" && options.api && externalId && !state.selectedReportId && /* @__PURE__ */ jsx15(
6276
6355
  ChangelogList,
6277
6356
  {
6278
6357
  api: options.api,
@@ -6283,7 +6362,7 @@ function mountWidget(options) {
6283
6362
  ),
6284
6363
  state.tab === "board" && options.api && externalId && // BoardView owns its own master/detail navigation — no
6285
6364
  // selectedReportId routing through the modal-level state.
6286
- /* @__PURE__ */ jsx14(
6365
+ /* @__PURE__ */ jsx15(
6287
6366
  BoardView,
6288
6367
  {
6289
6368
  api: options.api,
@@ -6404,8 +6483,8 @@ function createFeedback(config) {
6404
6483
  capture_method: captureMethod,
6405
6484
  technical_context
6406
6485
  };
6407
- if ("0.32.0") {
6408
- payload.widget_version = "0.32.0";
6486
+ if ("0.33.0") {
6487
+ payload.widget_version = "0.33.0";
6409
6488
  }
6410
6489
  if (manualScreenshots?.length) {
6411
6490
  payload.screenshots = manualScreenshots;
@@ -6531,4 +6610,4 @@ function createFeedback(config) {
6531
6610
  export {
6532
6611
  createFeedback
6533
6612
  };
6534
- //# sourceMappingURL=chunk-YNDBZR37.mjs.map
6613
+ //# sourceMappingURL=chunk-RR6UB75B.mjs.map