glitchgrab 1.42.0 → 1.43.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.
package/dist/index.mjs CHANGED
@@ -4,11 +4,11 @@
4
4
  import {
5
5
  createContext,
6
6
  useContext,
7
- useRef as useRef4,
8
- useEffect as useEffect5,
7
+ useRef as useRef5,
8
+ useEffect as useEffect6,
9
9
  useCallback as useCallback2,
10
- useMemo as useMemo2,
11
- useState as useState5
10
+ useMemo as useMemo3,
11
+ useState as useState6
12
12
  } from "react";
13
13
 
14
14
  // src/error-boundary.tsx
@@ -127,21 +127,84 @@ function interceptConsole() {
127
127
  origError.apply(console, args);
128
128
  };
129
129
  }
130
+ var CONSOLE_TEXT_MAX = 200;
130
131
  function argsToString(args) {
131
132
  try {
132
133
  return args.map((a) => {
133
- if (typeof a === "string") return a;
134
+ if (typeof a === "string") return a.slice(0, CONSOLE_TEXT_MAX);
134
135
  if (a instanceof Error) return a.message;
135
136
  try {
136
- return JSON.stringify(a);
137
+ return previewJson(a, CONSOLE_TEXT_MAX);
137
138
  } catch (e) {
138
139
  return String(a);
139
140
  }
140
- }).join(" ").slice(0, 200);
141
+ }).join(" ").slice(0, CONSOLE_TEXT_MAX);
141
142
  } catch (e) {
142
143
  return "[unknown]";
143
144
  }
144
145
  }
146
+ function previewJson(value, max) {
147
+ let out = "";
148
+ const path = /* @__PURE__ */ new WeakSet();
149
+ const write = (input, inArray) => {
150
+ if (out.length > max) return;
151
+ let v = input;
152
+ if (v !== null && typeof v === "object" && typeof v.toJSON === "function") {
153
+ v = v.toJSON();
154
+ }
155
+ if (v === null) {
156
+ out += "null";
157
+ return;
158
+ }
159
+ switch (typeof v) {
160
+ case "string":
161
+ out += JSON.stringify(v.length > max ? v.slice(0, max) : v);
162
+ return;
163
+ case "number":
164
+ out += Number.isFinite(v) ? String(v) : "null";
165
+ return;
166
+ case "boolean":
167
+ case "bigint":
168
+ out += String(v);
169
+ return;
170
+ case "object":
171
+ break;
172
+ default:
173
+ if (inArray) out += "null";
174
+ return;
175
+ }
176
+ const obj = v;
177
+ if (path.has(obj)) {
178
+ out += '"[Circular]"';
179
+ return;
180
+ }
181
+ path.add(obj);
182
+ if (Array.isArray(obj)) {
183
+ out += "[";
184
+ for (let i = 0; i < obj.length && out.length <= max; i++) {
185
+ if (i > 0) out += ",";
186
+ write(obj[i], true);
187
+ }
188
+ out += "]";
189
+ } else {
190
+ out += "{";
191
+ let first = true;
192
+ for (const key in obj) {
193
+ if (out.length > max) break;
194
+ if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;
195
+ const child = obj[key];
196
+ if (child === void 0 || typeof child === "function" || typeof child === "symbol") continue;
197
+ out += `${first ? "" : ","}${JSON.stringify(key)}:`;
198
+ first = false;
199
+ write(child, false);
200
+ }
201
+ out += "}";
202
+ }
203
+ path.delete(obj);
204
+ };
205
+ write(value, false);
206
+ return out;
207
+ }
145
208
  async function readErrorBody(response, url) {
146
209
  try {
147
210
  if (response.ok) return "";
@@ -258,15 +321,27 @@ function interceptNavigation() {
258
321
  addBreadcrumb("navigation", `Back/Forward to ${window.location.pathname}`);
259
322
  });
260
323
  }
324
+ var CLICK_TEXT_MAX = 50;
325
+ var CLICK_TEXT_NODE_LIMIT = 500;
326
+ function leadingText(el, max) {
327
+ var _a;
328
+ let text = "";
329
+ let visited = 0;
330
+ const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
331
+ while (text.trimStart().length < max && visited++ < CLICK_TEXT_NODE_LIMIT && walker.nextNode()) {
332
+ text += (_a = walker.currentNode.nodeValue) != null ? _a : "";
333
+ }
334
+ return text.trim().slice(0, max);
335
+ }
261
336
  function interceptClicks() {
262
337
  document.addEventListener(
263
338
  "click",
264
339
  (e) => {
265
- var _a, _b, _c;
340
+ var _a;
266
341
  try {
267
342
  const target = e.target;
268
343
  const tag = (_a = target.tagName) == null ? void 0 : _a.toLowerCase();
269
- const text = (_c = (_b = target.textContent) == null ? void 0 : _b.trim().slice(0, 50)) != null ? _c : "";
344
+ const text = target instanceof Node ? leadingText(target, CLICK_TEXT_MAX) : "";
270
345
  const id = target.id ? `#${target.id}` : "";
271
346
  const cls = target.className && typeof target.className === "string" ? `.${target.className.split(" ")[0]}` : "";
272
347
  addBreadcrumb("click", `Click ${tag}${id}${cls} "${text}"`);
@@ -588,7 +663,7 @@ async function enhanceText(text, token, baseUrl, screenshot, context) {
588
663
  }
589
664
  }
590
665
  async function assistTurn(params, token, baseUrl) {
591
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
666
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
592
667
  const offline = {
593
668
  conversationId: null,
594
669
  question: null,
@@ -621,6 +696,7 @@ async function assistTurn(params, token, baseUrl) {
621
696
  report: (_i = (_h = envelope.data) == null ? void 0 : _h.report) != null ? _i : null,
622
697
  duplicate: (_k = (_j = envelope.data) == null ? void 0 : _j.duplicate) != null ? _k : null,
623
698
  solved: (_m = (_l = envelope.data) == null ? void 0 : _l.solved) != null ? _m : null,
699
+ aboutGlitchgrab: ((_n = envelope.data) == null ? void 0 : _n.aboutGlitchgrab) === true,
624
700
  degraded: null
625
701
  };
626
702
  } catch (e) {
@@ -835,17 +911,21 @@ var GlitchgrabErrorBoundary = class extends React.Component {
835
911
 
836
912
  // ../report-ui/dist/index.mjs
837
913
  import {
838
- useState as useState3,
839
- useRef as useRef3,
840
- useEffect as useEffect3
914
+ useState as useState4,
915
+ useRef as useRef4,
916
+ useEffect as useEffect4,
917
+ useMemo
841
918
  } from "react";
842
- import { createPortal as createPortal2 } from "react-dom";
919
+ import { createPortal as createPortal3 } from "react-dom";
843
920
  import { useEffect, useRef, useState } from "react";
844
921
  import { jsx, jsxs } from "react/jsx-runtime";
845
922
  import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
846
923
  import { createPortal } from "react-dom";
847
924
  import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
925
+ import { useEffect as useEffect3, useRef as useRef3, useState as useState3 } from "react";
926
+ import { createPortal as createPortal2 } from "react-dom";
848
927
  import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
928
+ import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
849
929
  var MAX_SCREENSHOT_DATA_URL_LENGTH = 18e5;
850
930
  var QUALITY_LADDER = [0.92, 0.85, 0.75];
851
931
  var DOWNSCALE_FACTOR = 0.7;
@@ -1337,7 +1417,8 @@ function AssistSheet({
1337
1417
  onSend,
1338
1418
  onDegrade,
1339
1419
  onClose,
1340
- onFinish
1420
+ onFinish,
1421
+ onReportGlitchgrabProblem
1341
1422
  }) {
1342
1423
  const narrow = useIsNarrow();
1343
1424
  const severityAsked = showSeverity && currentTile === "BUG";
@@ -1348,6 +1429,7 @@ function AssistSheet({
1348
1429
  const [hoveredStar, setHoveredStar] = useState2(0);
1349
1430
  const [options, setOptions] = useState2([]);
1350
1431
  const [duplicate, setDuplicate] = useState2(null);
1432
+ const [glitchgrabOffer, setGlitchgrabOffer] = useState2(false);
1351
1433
  const [solved, setSolved] = useState2(null);
1352
1434
  const [phase, setPhase] = useState2(
1353
1435
  !typePicked ? "type" : currentTile === "RATING" ? "rating" : "chat"
@@ -1415,7 +1497,10 @@ function AssistSheet({
1415
1497
  screenshots: sent,
1416
1498
  context: {
1417
1499
  ...context != null ? context : {},
1418
- imageSources: sent.map((shot) => pageShot && shot === pageShot ? "page" : "attached")
1500
+ imageSources: sent.map((shot) => pageShot && shot === pageShot ? "page" : "attached"),
1501
+ // Whether this dialog can open the #366 panel at all. A hint — the
1502
+ // server decides whether the model may offer it.
1503
+ canReportGlitchgrab: !!onReportGlitchgrabProblem
1419
1504
  },
1420
1505
  events
1421
1506
  });
@@ -1438,6 +1523,7 @@ function AssistSheet({
1438
1523
  }
1439
1524
  setDuplicate((_a = result.duplicate) != null ? _a : null);
1440
1525
  onDuplicateChange == null ? void 0 : onDuplicateChange((_c = (_b = result.duplicate) == null ? void 0 : _b.number) != null ? _c : null);
1526
+ setGlitchgrabOffer(!!result.aboutGlitchgrab && !!onReportGlitchgrabProblem && !!result.question);
1441
1527
  if (result.solved) {
1442
1528
  setSolved(result.solved);
1443
1529
  setOptions([]);
@@ -1474,6 +1560,7 @@ function AssistSheet({
1474
1560
  const value = text.trim();
1475
1561
  if (!value || busy) return;
1476
1562
  setOptions([]);
1563
+ setGlitchgrabOffer(false);
1477
1564
  const underDraft = phase === "draft";
1478
1565
  if (underDraft) {
1479
1566
  const edited = aiDraftRef.current !== null && description.trim() !== aiDraftRef.current.trim();
@@ -2031,7 +2118,82 @@ function AssistSheet({
2031
2118
  );
2032
2119
  }),
2033
2120
  duplicate && !busy && phase === "chat" && /* @__PURE__ */ jsx2("div", { style: { paddingLeft: "32px", minWidth: 0 }, children: renderKnownIssue({ title: false }) }),
2034
- options.length > 0 && !busy && phase === "chat" && /* @__PURE__ */ jsx2(
2121
+ glitchgrabOffer && onReportGlitchgrabProblem && !busy && phase === "chat" && /* @__PURE__ */ jsx2("div", { style: { paddingLeft: "32px", minWidth: 0 }, children: /* @__PURE__ */ jsxs2(
2122
+ "div",
2123
+ {
2124
+ "data-gg-glitchgrab-offer": "",
2125
+ style: {
2126
+ display: "flex",
2127
+ flexDirection: "column",
2128
+ gap: "8px",
2129
+ padding: "10px",
2130
+ borderRadius: "8px",
2131
+ border: `1px solid ${t2.accent}55`,
2132
+ backgroundColor: `${t2.accent}14`,
2133
+ fontSize: "12px",
2134
+ lineHeight: 1.5
2135
+ },
2136
+ children: [
2137
+ /* @__PURE__ */ jsx2("span", { style: { color: t2.text, fontWeight: 600 }, children: "This is about Glitchgrab, not this app" }),
2138
+ /* @__PURE__ */ jsx2("span", { style: { color: t2.textMuted }, children: "It goes to the team that builds this reporter, with your chat attached." }),
2139
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", flexWrap: "wrap", gap: "6px" }, children: [
2140
+ /* @__PURE__ */ jsx2(
2141
+ "button",
2142
+ {
2143
+ type: "button",
2144
+ "data-gg-glitchgrab-offer-send": "",
2145
+ onClick: () => {
2146
+ logEvent("glitchgrab_offer_tap");
2147
+ setGlitchgrabOffer(false);
2148
+ onReportGlitchgrabProblem(
2149
+ messages.filter((m) => m.role === "user").map((m) => m.content.trim()).filter(Boolean).join("\n\n")
2150
+ );
2151
+ },
2152
+ style: {
2153
+ padding: "8px 12px",
2154
+ borderRadius: "999px",
2155
+ border: "none",
2156
+ backgroundColor: t2.accent,
2157
+ color: t2.accentText,
2158
+ fontSize: "12px",
2159
+ fontWeight: 700,
2160
+ fontFamily: "inherit",
2161
+ cursor: "pointer",
2162
+ // Both stretch, so on a phone each wrapped line reads as
2163
+ // a choice rather than one button left stranded.
2164
+ flex: "1 1 auto"
2165
+ },
2166
+ children: "Send to the Glitchgrab team"
2167
+ }
2168
+ ),
2169
+ /* @__PURE__ */ jsx2(
2170
+ "button",
2171
+ {
2172
+ type: "button",
2173
+ "data-gg-glitchgrab-offer-no": "",
2174
+ onClick: () => {
2175
+ logEvent("glitchgrab_offer_declined");
2176
+ send("No \u2014 it's about this app, not the reporting tool");
2177
+ },
2178
+ style: {
2179
+ padding: "8px 12px",
2180
+ borderRadius: "999px",
2181
+ border: `1px solid ${t2.inputBorder}`,
2182
+ background: "transparent",
2183
+ color: t2.textMuted,
2184
+ fontSize: "12px",
2185
+ fontFamily: "inherit",
2186
+ cursor: "pointer",
2187
+ flex: "1 1 auto"
2188
+ },
2189
+ children: "No, it's about this app"
2190
+ }
2191
+ )
2192
+ ] })
2193
+ ]
2194
+ }
2195
+ ) }),
2196
+ options.length > 0 && !busy && phase === "chat" && !glitchgrabOffer && /* @__PURE__ */ jsx2(
2035
2197
  "div",
2036
2198
  {
2037
2199
  style: {
@@ -2617,6 +2779,30 @@ function AssistSheet({
2617
2779
  },
2618
2780
  children: "Not getting it? Fill the form yourself \u2192"
2619
2781
  }
2782
+ ),
2783
+ onReportGlitchgrabProblem && phase !== "solved" && !glitchgrabOffer && /* @__PURE__ */ jsx2(
2784
+ "button",
2785
+ {
2786
+ type: "button",
2787
+ "data-gg-self-report": "",
2788
+ onClick: () => onReportGlitchgrabProblem(),
2789
+ style: {
2790
+ display: "block",
2791
+ // ~32px tap target; the negative margins keep the composer
2792
+ // from growing to make room for it.
2793
+ margin: "-2px auto -8px",
2794
+ border: "none",
2795
+ background: "transparent",
2796
+ color: t2.textMuted,
2797
+ fontSize: "11.5px",
2798
+ fontFamily: "inherit",
2799
+ padding: "10px 8px",
2800
+ cursor: "pointer",
2801
+ textDecoration: "underline",
2802
+ textUnderlineOffset: "2px"
2803
+ },
2804
+ children: "Assistant misbehaving? Tell Glitchgrab"
2805
+ }
2620
2806
  )
2621
2807
  ]
2622
2808
  }
@@ -2630,6 +2816,240 @@ function AssistSheet({
2630
2816
  document.body
2631
2817
  );
2632
2818
  }
2819
+ var FONT = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
2820
+ var FAILED = "Couldn't send it. Try again in a moment.";
2821
+ function describeSentAlong(hasChat, screenshotCount) {
2822
+ const parts = [
2823
+ ...hasChat ? ["your AI chat"] : [],
2824
+ "what you did on this page",
2825
+ ...screenshotCount > 0 ? [`${screenshotCount} screenshot${screenshotCount === 1 ? "" : "s"}`] : []
2826
+ ];
2827
+ if (parts.length === 1) return parts[0];
2828
+ return `${parts.slice(0, -1).join(", ")} and ${parts[parts.length - 1]}`;
2829
+ }
2830
+ function GlitchgrabProblemPanel({
2831
+ send,
2832
+ theme: t2,
2833
+ surface,
2834
+ conversationId,
2835
+ reportType,
2836
+ screenshots,
2837
+ initialText = "",
2838
+ onClose
2839
+ }) {
2840
+ const [text, setText] = useState3(initialText);
2841
+ const [busy, setBusy] = useState3(false);
2842
+ const [sent, setSent] = useState3(false);
2843
+ const [error, setError] = useState3(null);
2844
+ const inputRef = useRef3(null);
2845
+ useEffect3(() => {
2846
+ var _a;
2847
+ (_a = inputRef.current) == null ? void 0 : _a.focus();
2848
+ }, []);
2849
+ useEffect3(() => {
2850
+ const onKey = (e) => {
2851
+ if (e.key !== "Escape") return;
2852
+ e.stopPropagation();
2853
+ onClose();
2854
+ };
2855
+ window.addEventListener("keydown", onKey, true);
2856
+ return () => window.removeEventListener("keydown", onKey, true);
2857
+ }, [onClose]);
2858
+ const submit = async () => {
2859
+ const description = text.trim();
2860
+ if (!description || busy) return;
2861
+ setBusy(true);
2862
+ setError(null);
2863
+ try {
2864
+ const result = await send({ description, surface, conversationId, reportType, screenshots });
2865
+ if (result == null ? void 0 : result.success) setSent(true);
2866
+ else setError((result == null ? void 0 : result.message) || FAILED);
2867
+ } catch (e) {
2868
+ setError(FAILED);
2869
+ } finally {
2870
+ setBusy(false);
2871
+ }
2872
+ };
2873
+ const canSend = !!text.trim() && !busy;
2874
+ const secondaryButton = {
2875
+ padding: "10px 14px",
2876
+ borderRadius: "8px",
2877
+ border: `1px solid ${t2.inputBorder}`,
2878
+ background: "transparent",
2879
+ color: t2.text,
2880
+ fontSize: "13px",
2881
+ fontWeight: 600,
2882
+ fontFamily: "inherit",
2883
+ cursor: "pointer"
2884
+ };
2885
+ const primaryButton = (enabled) => ({
2886
+ padding: "10px 14px",
2887
+ borderRadius: "8px",
2888
+ border: "none",
2889
+ backgroundColor: enabled ? t2.accent : t2.bgSecondary,
2890
+ color: enabled ? t2.accentText : t2.textMuted,
2891
+ fontSize: "13px",
2892
+ fontWeight: 700,
2893
+ fontFamily: "inherit",
2894
+ cursor: enabled ? "pointer" : "default"
2895
+ });
2896
+ return createPortal2(
2897
+ // No close on backdrop click: a stray click would throw away what they typed.
2898
+ // `data-glitchgrab-layer` exempts this from the dialog's anti-focus-trap
2899
+ // sweep, which sets `inert` on every other role="dialog" on the page —
2900
+ // without it the panel renders but cannot be typed into.
2901
+ /* @__PURE__ */ jsx3(
2902
+ "div",
2903
+ {
2904
+ "data-glitchgrab-layer": "",
2905
+ "data-gg-self-report-panel": "",
2906
+ role: "dialog",
2907
+ "aria-modal": "true",
2908
+ "aria-labelledby": "gg-self-report-title",
2909
+ style: {
2910
+ position: "fixed",
2911
+ inset: 0,
2912
+ zIndex: 2147483647,
2913
+ backgroundColor: "rgba(0,0,0,0.55)",
2914
+ display: "flex",
2915
+ alignItems: "center",
2916
+ justifyContent: "center",
2917
+ padding: "16px",
2918
+ boxSizing: "border-box",
2919
+ fontFamily: FONT
2920
+ },
2921
+ children: /* @__PURE__ */ jsx3(
2922
+ "div",
2923
+ {
2924
+ style: {
2925
+ width: "100%",
2926
+ maxWidth: "420px",
2927
+ boxSizing: "border-box",
2928
+ backgroundColor: t2.bg,
2929
+ color: t2.text,
2930
+ border: `1px solid ${t2.border}`,
2931
+ borderRadius: "12px",
2932
+ boxShadow: "0 20px 50px rgba(0,0,0,0.5)",
2933
+ padding: "18px"
2934
+ },
2935
+ children: sent ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
2936
+ /* @__PURE__ */ jsx3("div", { id: "gg-self-report-title", style: { fontSize: "15px", fontWeight: 600 }, children: "Sent to the Glitchgrab team" }),
2937
+ /* @__PURE__ */ jsx3("p", { style: { margin: "6px 0 16px", fontSize: "13px", lineHeight: 1.5, color: t2.textMuted }, children: "Thanks \u2014 we'll look into it. Your report is still open behind this, exactly as you left it." }),
2938
+ /* @__PURE__ */ jsx3(
2939
+ "button",
2940
+ {
2941
+ type: "button",
2942
+ "data-gg-self-report-done": "",
2943
+ onClick: onClose,
2944
+ style: { ...primaryButton(true), width: "100%" },
2945
+ children: "Back to your report"
2946
+ }
2947
+ )
2948
+ ] }) : /* @__PURE__ */ jsxs3(Fragment2, { children: [
2949
+ /* @__PURE__ */ jsxs3(
2950
+ "div",
2951
+ {
2952
+ style: {
2953
+ display: "flex",
2954
+ alignItems: "flex-start",
2955
+ justifyContent: "space-between",
2956
+ gap: "12px"
2957
+ },
2958
+ children: [
2959
+ /* @__PURE__ */ jsx3("div", { id: "gg-self-report-title", style: { fontSize: "15px", fontWeight: 600 }, children: "Problem with Glitchgrab?" }),
2960
+ /* @__PURE__ */ jsx3(
2961
+ "button",
2962
+ {
2963
+ type: "button",
2964
+ onClick: onClose,
2965
+ "aria-label": "Close",
2966
+ style: {
2967
+ border: "none",
2968
+ background: "transparent",
2969
+ color: t2.textMuted,
2970
+ fontSize: "18px",
2971
+ lineHeight: 1,
2972
+ cursor: "pointer",
2973
+ padding: "4px 6px",
2974
+ margin: "-4px -6px 0 0"
2975
+ },
2976
+ children: "\xD7"
2977
+ }
2978
+ )
2979
+ ]
2980
+ }
2981
+ ),
2982
+ /* @__PURE__ */ jsx3("p", { style: { margin: "6px 0 12px", fontSize: "13px", lineHeight: 1.5, color: t2.textMuted }, children: "This goes to the people who build this reporter \u2014 not to this project's team. Tell us what went wrong: the AI chat, a button, anything." }),
2983
+ /* @__PURE__ */ jsx3(
2984
+ "textarea",
2985
+ {
2986
+ ref: inputRef,
2987
+ "data-gg-self-report-input": "",
2988
+ value: text,
2989
+ onChange: (e) => {
2990
+ setText(e.target.value);
2991
+ if (error) setError(null);
2992
+ },
2993
+ onKeyDown: (e) => {
2994
+ if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
2995
+ e.preventDefault();
2996
+ void submit();
2997
+ }
2998
+ },
2999
+ rows: 4,
3000
+ placeholder: "e.g. The assistant kept asking the same question and never wrote a draft",
3001
+ style: {
3002
+ width: "100%",
3003
+ boxSizing: "border-box",
3004
+ resize: "vertical",
3005
+ padding: "10px 12px",
3006
+ borderRadius: "8px",
3007
+ border: `1px solid ${t2.inputBorder}`,
3008
+ backgroundColor: t2.inputBg,
3009
+ color: t2.text,
3010
+ fontSize: "14px",
3011
+ lineHeight: 1.45,
3012
+ fontFamily: "inherit",
3013
+ outline: "none"
3014
+ }
3015
+ }
3016
+ ),
3017
+ /* @__PURE__ */ jsxs3(
3018
+ "p",
3019
+ {
3020
+ "data-gg-self-report-includes": "",
3021
+ style: { margin: "8px 0 0", fontSize: "11.5px", lineHeight: 1.45, color: t2.textMuted },
3022
+ children: [
3023
+ "Also sent, so we can see what happened:",
3024
+ " ",
3025
+ describeSentAlong(conversationId !== null, screenshots.length),
3026
+ "."
3027
+ ]
3028
+ }
3029
+ ),
3030
+ error && /* @__PURE__ */ jsx3("p", { role: "alert", style: { margin: "8px 0 0", fontSize: "12px", color: "#ef4444" }, children: error }),
3031
+ /* @__PURE__ */ jsxs3("div", { style: { display: "flex", justifyContent: "flex-end", gap: "8px", marginTop: "14px" }, children: [
3032
+ /* @__PURE__ */ jsx3("button", { type: "button", onClick: onClose, style: secondaryButton, children: "Cancel" }),
3033
+ /* @__PURE__ */ jsx3(
3034
+ "button",
3035
+ {
3036
+ type: "button",
3037
+ "data-gg-self-report-send": "",
3038
+ onClick: () => void submit(),
3039
+ disabled: !canSend,
3040
+ style: primaryButton(canSend),
3041
+ children: busy ? "Sending\u2026" : "Send to Glitchgrab"
3042
+ }
3043
+ )
3044
+ ] })
3045
+ ] })
3046
+ }
3047
+ )
3048
+ }
3049
+ ),
3050
+ document.body
3051
+ );
3052
+ }
2633
3053
  var GLITCHGRAB_SHORTCUT = "Ctrl+Shift+G";
2634
3054
  var GLITCHGRAB_SHORTCUT_MAC = "\u2318\u21E7G";
2635
3055
  function isMac() {
@@ -2677,6 +3097,7 @@ var ATTACHMENT_ACCEPT = [
2677
3097
  ].join(",");
2678
3098
  var MAX_SCALE = 2;
2679
3099
  var FRAME_TIMEOUT_MS = 3e3;
3100
+ var GRAB_TIMEOUT_MS = FRAME_TIMEOUT_MS + 2e3;
2680
3101
  function canCaptureTabPixels() {
2681
3102
  var _a;
2682
3103
  try {
@@ -2743,7 +3164,13 @@ async function captureViaTabPixels() {
2743
3164
  stream = await navigator.mediaDevices.getDisplayMedia(options);
2744
3165
  const surface = (_b = (_a = stream.getVideoTracks()[0]) == null ? void 0 : _a.getSettings()) == null ? void 0 : _b.displaySurface;
2745
3166
  if (surface && surface !== "browser") return null;
2746
- const canvas = await grabFrame(stream);
3167
+ let timer;
3168
+ const timedOut = new Promise((resolve) => {
3169
+ timer = setTimeout(() => resolve(null), GRAB_TIMEOUT_MS);
3170
+ });
3171
+ const canvas = await Promise.race([grabFrame(stream), timedOut]).finally(
3172
+ () => clearTimeout(timer)
3173
+ );
2747
3174
  return canvas ? encodeScreenshot(canvas) : null;
2748
3175
  } catch (e) {
2749
3176
  return null;
@@ -2751,6 +3178,10 @@ async function captureViaTabPixels() {
2751
3178
  stream == null ? void 0 : stream.getTracks().forEach((track) => track.stop());
2752
3179
  }
2753
3180
  }
3181
+ var IMAGE_TIMEOUT_MS = 3e3;
3182
+ function isGlitchgrabLayer(el) {
3183
+ return el.hasAttribute("data-glitchgrab-layer");
3184
+ }
2754
3185
  async function captureViaHtml2Canvas() {
2755
3186
  try {
2756
3187
  const { default: html2canvas } = await import("html2canvas-pro");
@@ -2760,6 +3191,8 @@ async function captureViaHtml2Canvas() {
2760
3191
  logging: false,
2761
3192
  useCORS: true,
2762
3193
  allowTaint: true,
3194
+ imageTimeout: IMAGE_TIMEOUT_MS,
3195
+ ignoreElements: isGlitchgrabLayer,
2763
3196
  x: window.scrollX,
2764
3197
  y: window.scrollY,
2765
3198
  width: window.innerWidth,
@@ -2772,12 +3205,40 @@ async function captureViaHtml2Canvas() {
2772
3205
  return null;
2773
3206
  }
2774
3207
  }
2775
- async function captureDefaultScreenshot() {
2776
- var _a;
2777
- return (_a = await captureViaTabPixels()) != null ? _a : await captureViaHtml2Canvas();
3208
+ var inFlight = null;
3209
+ function nextPaint() {
3210
+ return new Promise((resolve) => {
3211
+ const cap = setTimeout(resolve, 100);
3212
+ if (typeof requestAnimationFrame !== "function") return;
3213
+ requestAnimationFrame(
3214
+ () => setTimeout(() => {
3215
+ clearTimeout(cap);
3216
+ resolve();
3217
+ }, 0)
3218
+ );
3219
+ });
3220
+ }
3221
+ function captureDefaultScreenshot(options) {
3222
+ if (inFlight) return inFlight;
3223
+ inFlight = (async () => {
3224
+ const pixels = await captureViaTabPixels();
3225
+ if (pixels) return pixels;
3226
+ if (options == null ? void 0 : options.onRedraw) {
3227
+ try {
3228
+ options.onRedraw();
3229
+ } catch (e) {
3230
+ }
3231
+ await nextPaint();
3232
+ }
3233
+ return captureViaHtml2Canvas();
3234
+ })().finally(() => {
3235
+ inFlight = null;
3236
+ });
3237
+ return inFlight;
2778
3238
  }
2779
3239
  var SEVERITY_REQUIRED = "Pick how bad it is before sending.";
2780
- function useIsDark() {
3240
+ var SHOT_WAIT_MS = 3e3;
3241
+ function detectDark() {
2781
3242
  if (typeof window === "undefined") return true;
2782
3243
  try {
2783
3244
  for (const el of [document.body, document.documentElement]) {
@@ -2900,9 +3361,9 @@ function ReporterChip({
2900
3361
  t: t2
2901
3362
  }) {
2902
3363
  var _a;
2903
- const [avatarFailed, setAvatarFailed] = useState3(false);
3364
+ const [avatarFailed, setAvatarFailed] = useState4(false);
2904
3365
  const avatarUrl = (reporter == null ? void 0 : reporter.avatarUrl) || "";
2905
- useEffect3(() => {
3366
+ useEffect4(() => {
2906
3367
  setAvatarFailed(false);
2907
3368
  }, [avatarUrl]);
2908
3369
  const name = ((_a = reporter == null ? void 0 : reporter.name) == null ? void 0 : _a.trim()) || "";
@@ -2911,13 +3372,13 @@ function ReporterChip({
2911
3372
  const label = isAnonymous ? "Anonymous" : name;
2912
3373
  const title = isAnonymous ? "No reporter identity was passed to Glitchgrab \u2014 this report won't be attributed to anyone" : [name, reporter == null ? void 0 : reporter.email, reporter == null ? void 0 : reporter.role].filter(Boolean).join(" \xB7 ");
2913
3374
  const showAvatarImage = !!avatarUrl && !avatarFailed;
2914
- return /* @__PURE__ */ jsxs3(
3375
+ return /* @__PURE__ */ jsxs4(
2915
3376
  "span",
2916
3377
  {
2917
3378
  title,
2918
3379
  style: { display: "flex", alignItems: "center", gap: "6px", minWidth: 0 },
2919
3380
  children: [
2920
- /* @__PURE__ */ jsx3(
3381
+ /* @__PURE__ */ jsx4(
2921
3382
  "span",
2922
3383
  {
2923
3384
  "aria-hidden": "true",
@@ -2937,7 +3398,7 @@ function ReporterChip({
2937
3398
  color: isAnonymous ? t2.textMuted : t2.accentText,
2938
3399
  border: `1px solid ${isAnonymous ? t2.inputBorder : "transparent"}`
2939
3400
  },
2940
- children: showAvatarImage ? /* @__PURE__ */ jsx3(
3401
+ children: showAvatarImage ? /* @__PURE__ */ jsx4(
2941
3402
  "img",
2942
3403
  {
2943
3404
  src: avatarUrl,
@@ -2947,9 +3408,9 @@ function ReporterChip({
2947
3408
  onError: () => setAvatarFailed(true),
2948
3409
  style: { width: "100%", height: "100%", objectFit: "cover" }
2949
3410
  }
2950
- ) : initials ? initials : /* @__PURE__ */ jsxs3("svg", { width: "10", height: "10", viewBox: "0 0 16 16", fill: "none", children: [
2951
- /* @__PURE__ */ jsx3("circle", { cx: "8", cy: "5.5", r: "2.75", stroke: "currentColor", strokeWidth: "1.4" }),
2952
- /* @__PURE__ */ jsx3(
3411
+ ) : initials ? initials : /* @__PURE__ */ jsxs4("svg", { width: "10", height: "10", viewBox: "0 0 16 16", fill: "none", children: [
3412
+ /* @__PURE__ */ jsx4("circle", { cx: "8", cy: "5.5", r: "2.75", stroke: "currentColor", strokeWidth: "1.4" }),
3413
+ /* @__PURE__ */ jsx4(
2953
3414
  "path",
2954
3415
  {
2955
3416
  d: "M2.75 13.5c0-2.35 2.35-3.75 5.25-3.75s5.25 1.4 5.25 3.75",
@@ -2961,7 +3422,7 @@ function ReporterChip({
2961
3422
  ] })
2962
3423
  }
2963
3424
  ),
2964
- /* @__PURE__ */ jsxs3(
3425
+ /* @__PURE__ */ jsxs4(
2965
3426
  "span",
2966
3427
  {
2967
3428
  style: {
@@ -3090,43 +3551,49 @@ function ReportDialog({
3090
3551
  captureScreenshot = captureDefaultScreenshot,
3091
3552
  reporter,
3092
3553
  onClose,
3093
- headerSlot
3554
+ headerSlot,
3555
+ reportGlitchgrabProblem
3094
3556
  }) {
3095
3557
  var _a;
3096
- const [isEnhancing, setIsEnhancing] = useState3(false);
3097
- const [assistOpen, setAssistOpen] = useState3(false);
3098
- const [assistNotice, setAssistNotice] = useState3(null);
3099
- const [assistUsed, setAssistUsed] = useState3(false);
3100
- const [typeChosen, setTypeChosen] = useState3(false);
3101
- const [duplicateIssueNumber, setDuplicateIssueNumber] = useState3(null);
3102
- const [aiConversationId, setAiConversationId] = useState3(null);
3103
- const [isEnhanced, setIsEnhanced] = useState3(false);
3104
- const [originalDescription, setOriginalDescription] = useState3(
3558
+ const [isEnhancing, setIsEnhancing] = useState4(false);
3559
+ const [assistOpen, setAssistOpen] = useState4(false);
3560
+ const [assistNotice, setAssistNotice] = useState4(null);
3561
+ const [assistUsed, setAssistUsed] = useState4(false);
3562
+ const [selfReportFrom, setSelfReportFrom] = useState4(null);
3563
+ const [selfReportPrefill, setSelfReportPrefill] = useState4("");
3564
+ const [typeChosen, setTypeChosen] = useState4(false);
3565
+ const [duplicateIssueNumber, setDuplicateIssueNumber] = useState4(null);
3566
+ const [aiConversationId, setAiConversationId] = useState4(null);
3567
+ const [isEnhanced, setIsEnhanced] = useState4(false);
3568
+ const [originalDescription, setOriginalDescription] = useState4(
3105
3569
  null
3106
3570
  );
3107
- const [isListening, setIsListening] = useState3(false);
3108
- const [isTranscribing, setIsTranscribing] = useState3(false);
3109
- const [voiceError, setVoiceError] = useState3(null);
3110
- const [screenshotDragOver, setScreenshotDragOver] = useState3(false);
3111
- const [mounted, setMounted] = useState3(false);
3112
- useEffect3(() => {
3571
+ const [isListening, setIsListening] = useState4(false);
3572
+ const [isTranscribing, setIsTranscribing] = useState4(false);
3573
+ const [voiceError, setVoiceError] = useState4(null);
3574
+ const [screenshotDragOver, setScreenshotDragOver] = useState4(false);
3575
+ const [mounted, setMounted] = useState4(false);
3576
+ useEffect4(() => {
3113
3577
  setMounted(true);
3114
3578
  }, []);
3115
- const [isOpen, setIsOpen] = useState3(false);
3116
- const [description, setDescription] = useState3("");
3117
- const [isSubmitting, setIsSubmitting] = useState3(false);
3118
- const [submitted, setSubmitted] = useState3(false);
3119
- const [screenshots, setScreenshots] = useState3([]);
3120
- const [pageShot, setPageShot] = useState3(null);
3121
- const [attachments, setAttachments] = useState3([]);
3122
- const [previewIndex, setPreviewIndex] = useState3(null);
3123
- const [annotatingIndex, setAnnotatingIndex] = useState3(null);
3124
- const [previewZoomed, setPreviewZoomed] = useState3(false);
3125
- const [previewNatural, setPreviewNatural] = useState3(null);
3126
- const previewScrollRef = useRef3(null);
3127
- const previewImgElRef = useRef3(null);
3128
- const panRef = useRef3(null);
3129
- const zoomAnchorRef = useRef3(null);
3579
+ const [isOpen, setIsOpen] = useState4(false);
3580
+ const [description, setDescription] = useState4("");
3581
+ const [isSubmitting, setIsSubmitting] = useState4(false);
3582
+ const [submitted, setSubmitted] = useState4(false);
3583
+ const [screenshots, setScreenshots] = useState4([]);
3584
+ const [pageShot, setPageShot] = useState4(null);
3585
+ const [shotPending, setShotPending] = useState4(false);
3586
+ const pendingShotRef = useRef4(null);
3587
+ const openGenRef = useRef4(0);
3588
+ const [attachments, setAttachments] = useState4([]);
3589
+ const [previewIndex, setPreviewIndex] = useState4(null);
3590
+ const [annotatingIndex, setAnnotatingIndex] = useState4(null);
3591
+ const [previewZoomed, setPreviewZoomed] = useState4(false);
3592
+ const [previewNatural, setPreviewNatural] = useState4(null);
3593
+ const previewScrollRef = useRef4(null);
3594
+ const previewImgElRef = useRef4(null);
3595
+ const panRef = useRef4(null);
3596
+ const zoomAnchorRef = useRef4(null);
3130
3597
  const resetPreviewZoom = () => {
3131
3598
  setPreviewZoomed(false);
3132
3599
  setPreviewNatural(null);
@@ -3140,24 +3607,24 @@ function ReportDialog({
3140
3607
  resetPreviewZoom();
3141
3608
  setPreviewIndex(null);
3142
3609
  };
3143
- const fileInputRef = useRef3(null);
3144
- const modalRef = useRef3(null);
3145
- const previewImgRef = useRef3(null);
3146
- const textareaRef = useRef3(null);
3147
- const recognitionRef = useRef3(null);
3148
- const voiceBaseRef = useRef3("");
3149
- const usingWebSpeechRef = useRef3(false);
3150
- const textBeforeVoiceRef = useRef3("");
3151
- const mediaRecorderRef = useRef3(null);
3152
- const streamRef = useRef3(null);
3153
- const sarvamChunksRef = useRef3([]);
3154
- const spaceTimerRef = useRef3(null);
3155
- const isPushToTalkRef = useRef3(false);
3156
- const spaceEditsRef = useRef3(0);
3157
- const descriptionRef = useRef3("");
3158
- const lastVoiceTextRef = useRef3(null);
3159
- const hadWebSpeechRef = useRef3(false);
3160
- useEffect3(() => {
3610
+ const fileInputRef = useRef4(null);
3611
+ const modalRef = useRef4(null);
3612
+ const previewImgRef = useRef4(null);
3613
+ const textareaRef = useRef4(null);
3614
+ const recognitionRef = useRef4(null);
3615
+ const voiceBaseRef = useRef4("");
3616
+ const usingWebSpeechRef = useRef4(false);
3617
+ const textBeforeVoiceRef = useRef4("");
3618
+ const mediaRecorderRef = useRef4(null);
3619
+ const streamRef = useRef4(null);
3620
+ const sarvamChunksRef = useRef4([]);
3621
+ const spaceTimerRef = useRef4(null);
3622
+ const isPushToTalkRef = useRef4(false);
3623
+ const spaceEditsRef = useRef4(0);
3624
+ const descriptionRef = useRef4("");
3625
+ const lastVoiceTextRef = useRef4(null);
3626
+ const hadWebSpeechRef = useRef4(false);
3627
+ useEffect4(() => {
3161
3628
  if (!isOpen) return;
3162
3629
  const HOST_LAYERS = '[role="dialog"],[role="alertdialog"],[role="menu"],[role="listbox"]';
3163
3630
  const inerted = /* @__PURE__ */ new Set();
@@ -3183,13 +3650,13 @@ function ReportDialog({
3183
3650
  inerted.forEach((el) => el.removeAttribute("inert"));
3184
3651
  };
3185
3652
  }, [isOpen]);
3186
- const [step, setStep] = useState3(1);
3187
- const [reportType, setReportType] = useState3("BUG");
3188
- const [severity, setSeverity] = useState3(null);
3189
- const [validationError, setValidationError] = useState3(null);
3190
- const [placeholderIdx, setPlaceholderIdx] = useState3(0);
3191
- const [rating, setRating] = useState3(0);
3192
- const [hoveredStar, setHoveredStar] = useState3(0);
3653
+ const [step, setStep] = useState4(1);
3654
+ const [reportType, setReportType] = useState4("BUG");
3655
+ const [severity, setSeverity] = useState4(null);
3656
+ const [validationError, setValidationError] = useState4(null);
3657
+ const [placeholderIdx, setPlaceholderIdx] = useState4(0);
3658
+ const [rating, setRating] = useState4(0);
3659
+ const [hoveredStar, setHoveredStar] = useState4(0);
3193
3660
  const isRating = reportType === "RATING";
3194
3661
  const submitDisabled = isSubmitting || (isRating ? rating < 1 : !description.trim());
3195
3662
  const needsSeverity = validationError === SEVERITY_REQUIRED && showSeverity && reportType === "BUG" && !severity;
@@ -3201,8 +3668,8 @@ function ReportDialog({
3201
3668
  "SECURITY",
3202
3669
  "QUESTION"
3203
3670
  ];
3204
- const tileGridRef = useRef3(null);
3205
- useEffect3(() => {
3671
+ const tileGridRef = useRef4(null);
3672
+ useEffect4(() => {
3206
3673
  if (!isOpen || step !== 1) return;
3207
3674
  const onKey = (e) => {
3208
3675
  const el = e.target;
@@ -3246,8 +3713,19 @@ function ReportDialog({
3246
3713
  const next = current === -1 ? 0 : Math.min(Math.max(current + delta, 0), tiles.length - 1);
3247
3714
  (_c = tiles[next]) == null ? void 0 : _c.focus();
3248
3715
  };
3249
- const isDark = useIsDark();
3716
+ const isDark = useMemo(() => isOpen ? detectDark() : true, [isOpen]);
3250
3717
  const t2 = getTheme(isDark);
3718
+ const layerTheme = {
3719
+ bg: t2.bg,
3720
+ bgSecondary: t2.bgSecondary,
3721
+ border: t2.border,
3722
+ text: t2.text,
3723
+ textMuted: t2.textMuted,
3724
+ inputBg: t2.inputBg,
3725
+ inputBorder: t2.inputBorder,
3726
+ accent: t2.accent,
3727
+ accentText: t2.accentText
3728
+ };
3251
3729
  const canZoomPreview = previewNatural !== null && typeof window !== "undefined" && (previewNatural.w > window.innerWidth - 32 || previewNatural.h > window.innerHeight - 80);
3252
3730
  const handleFileUpload = (e) => {
3253
3731
  const files = e.target.files;
@@ -3277,6 +3755,7 @@ function ReportDialog({
3277
3755
  });
3278
3756
  };
3279
3757
  const handleOpen = async () => {
3758
+ const gen = openGenRef.current;
3280
3759
  setSubmitted(false);
3281
3760
  closePreview();
3282
3761
  setAnnotatingIndex(null);
@@ -3285,13 +3764,34 @@ function ReportDialog({
3285
3764
  setTypeChosen(true);
3286
3765
  setStep(2);
3287
3766
  }
3288
- const shot = await captureScreenshot();
3767
+ const show = () => {
3768
+ if (gen !== openGenRef.current) return;
3769
+ if (assist && !assistUsed) setAssistOpen(true);
3770
+ setIsOpen(true);
3771
+ };
3772
+ const capture = captureScreenshot({
3773
+ onRedraw: () => {
3774
+ if (gen !== openGenRef.current) return;
3775
+ setShotPending(true);
3776
+ show();
3777
+ }
3778
+ });
3779
+ pendingShotRef.current = capture;
3780
+ const previousPageShot = pageShot;
3781
+ const shot = await capture.catch(() => null);
3782
+ if (gen !== openGenRef.current) return;
3783
+ pendingShotRef.current = null;
3784
+ setShotPending(false);
3289
3785
  setPageShot(shot != null ? shot : null);
3290
- if (shot) setScreenshots([shot]);
3291
- if (assist && !assistUsed) setAssistOpen(true);
3292
- setIsOpen(true);
3786
+ if (shot) {
3787
+ setScreenshots((prev) => [
3788
+ shot,
3789
+ ...prev.filter((s) => s !== shot && s !== previousPageShot)
3790
+ ]);
3791
+ }
3792
+ show();
3293
3793
  };
3294
- useEffect3(() => {
3794
+ useEffect4(() => {
3295
3795
  const handler = (e) => {
3296
3796
  if (isOpen) return;
3297
3797
  const detail = e.detail;
@@ -3306,7 +3806,7 @@ function ReportDialog({
3306
3806
  window.addEventListener("glitchgrab:open-report", handler);
3307
3807
  return () => window.removeEventListener("glitchgrab:open-report", handler);
3308
3808
  }, [isOpen, handleOpen]);
3309
- useEffect3(() => {
3809
+ useEffect4(() => {
3310
3810
  if (!isOpen) return;
3311
3811
  const handleEsc = (e) => {
3312
3812
  if (e.key === "Escape") {
@@ -3319,7 +3819,7 @@ function ReportDialog({
3319
3819
  document.addEventListener("keydown", handleEsc);
3320
3820
  return () => document.removeEventListener("keydown", handleEsc);
3321
3821
  }, [isOpen, previewIndex, previewZoomed, annotatingIndex]);
3322
- useEffect3(() => {
3822
+ useEffect4(() => {
3323
3823
  if (previewIndex === null || annotatingIndex !== null) return;
3324
3824
  const handlePointerDown = (e) => {
3325
3825
  var _a2;
@@ -3330,7 +3830,7 @@ function ReportDialog({
3330
3830
  document.addEventListener("pointerdown", handlePointerDown, true);
3331
3831
  return () => document.removeEventListener("pointerdown", handlePointerDown, true);
3332
3832
  }, [previewIndex, annotatingIndex]);
3333
- useEffect3(() => {
3833
+ useEffect4(() => {
3334
3834
  var _a2;
3335
3835
  const el = previewScrollRef.current;
3336
3836
  if (!previewZoomed || !el) return;
@@ -3392,7 +3892,7 @@ function ReportDialog({
3392
3892
  panRef.current = null;
3393
3893
  }
3394
3894
  };
3395
- useEffect3(() => {
3895
+ useEffect4(() => {
3396
3896
  if (!isOpen) return;
3397
3897
  const handlePaste = (e) => {
3398
3898
  var _a2;
@@ -3415,14 +3915,14 @@ function ReportDialog({
3415
3915
  window.addEventListener("paste", handlePaste);
3416
3916
  return () => window.removeEventListener("paste", handlePaste);
3417
3917
  }, [isOpen]);
3418
- useEffect3(() => {
3918
+ useEffect4(() => {
3419
3919
  if (!isOpen || !transcribeAudio2) return;
3420
3920
  const id = setInterval(() => {
3421
3921
  setPlaceholderIdx((i) => (i + 1) % 2);
3422
3922
  }, 3e3);
3423
3923
  return () => clearInterval(id);
3424
3924
  }, [isOpen, transcribeAudio2]);
3425
- useEffect3(() => {
3925
+ useEffect4(() => {
3426
3926
  descriptionRef.current = description;
3427
3927
  }, [description]);
3428
3928
  const rebaseVoiceOnUserEdits = () => {
@@ -3467,7 +3967,7 @@ function ReportDialog({
3467
3967
  }
3468
3968
  };
3469
3969
  const sheetUp = !!assist && assistOpen;
3470
- useEffect3(() => {
3970
+ useEffect4(() => {
3471
3971
  const el = modalRef.current;
3472
3972
  if (!el) return;
3473
3973
  if (sheetUp) {
@@ -3482,6 +3982,9 @@ function ReportDialog({
3482
3982
  stopVoice();
3483
3983
  setIsOpen(false);
3484
3984
  onClose == null ? void 0 : onClose();
3985
+ openGenRef.current += 1;
3986
+ pendingShotRef.current = null;
3987
+ setShotPending(false);
3485
3988
  closePreview();
3486
3989
  setAnnotatingIndex(null);
3487
3990
  setStep(1);
@@ -3492,6 +3995,7 @@ function ReportDialog({
3492
3995
  setDuplicateIssueNumber(null);
3493
3996
  setSeverity(null);
3494
3997
  setValidationError(null);
3998
+ setSelfReportFrom(null);
3495
3999
  setVoiceError(null);
3496
4000
  setIsEnhanced(false);
3497
4001
  setOriginalDescription(null);
@@ -3714,8 +4218,19 @@ function ReportDialog({
3714
4218
  return;
3715
4219
  }
3716
4220
  setIsSubmitting(true);
4221
+ let shots = screenshots;
4222
+ const pending = pendingShotRef.current;
4223
+ if (pending) {
4224
+ const shot = await Promise.race([
4225
+ pending.catch(() => null),
4226
+ new Promise((resolve) => setTimeout(() => resolve(null), SHOT_WAIT_MS))
4227
+ ]);
4228
+ if (shot && !shots.includes(shot)) {
4229
+ shots = [shot, ...shots.filter((s) => s !== pageShot)];
4230
+ }
4231
+ }
3717
4232
  const metadata = {};
3718
- if (screenshots.length > 0) metadata.screenshots = JSON.stringify(screenshots);
4233
+ if (shots.length > 0) metadata.screenshots = JSON.stringify(shots);
3719
4234
  if (attachments.length > 0) metadata.attachments = JSON.stringify(attachments);
3720
4235
  if (showSeverity && reportType === "BUG" && severity) {
3721
4236
  metadata.severity = severity;
@@ -3751,9 +4266,9 @@ function ReportDialog({
3751
4266
  }
3752
4267
  };
3753
4268
  if (!mounted) return null;
3754
- return /* @__PURE__ */ jsxs3(Fragment2, { children: [
3755
- isOpen && createPortal2(
3756
- /* @__PURE__ */ jsx3("style", { children: `
4269
+ return /* @__PURE__ */ jsxs4(Fragment3, { children: [
4270
+ isOpen && createPortal3(
4271
+ /* @__PURE__ */ jsx4("style", { children: `
3757
4272
  @keyframes gg-pulse{0%,100%{opacity:1}50%{opacity:0.35}}
3758
4273
  @keyframes gg-b1{0%,100%{height:3px}40%{height:13px}}
3759
4274
  @keyframes gg-b2{0%,100%{height:8px}50%{height:3px}}
@@ -3789,8 +4304,8 @@ function ReportDialog({
3789
4304
  ` }),
3790
4305
  document.body
3791
4306
  ),
3792
- isOpen && createPortal2(
3793
- /* @__PURE__ */ jsx3(
4307
+ isOpen && createPortal3(
4308
+ /* @__PURE__ */ jsx4(
3794
4309
  "div",
3795
4310
  {
3796
4311
  "data-glitchgrab-layer": "",
@@ -3813,10 +4328,13 @@ function ReportDialog({
3813
4328
  },
3814
4329
  onPointerDown: (e) => e.stopPropagation(),
3815
4330
  onFocus: (e) => e.stopPropagation(),
3816
- children: /* @__PURE__ */ jsxs3(
4331
+ children: /* @__PURE__ */ jsxs4(
3817
4332
  "div",
3818
4333
  {
3819
4334
  ref: modalRef,
4335
+ role: "dialog",
4336
+ "aria-modal": "true",
4337
+ "aria-label": "Report an issue",
3820
4338
  onClick: (e) => e.stopPropagation(),
3821
4339
  style: {
3822
4340
  position: "relative",
@@ -3835,7 +4353,7 @@ function ReportDialog({
3835
4353
  isolation: "isolate"
3836
4354
  },
3837
4355
  children: [
3838
- /* @__PURE__ */ jsxs3(
4356
+ /* @__PURE__ */ jsxs4(
3839
4357
  "div",
3840
4358
  {
3841
4359
  style: {
@@ -3844,7 +4362,7 @@ function ReportDialog({
3844
4362
  borderBottom: `1px solid ${t2.border}`
3845
4363
  },
3846
4364
  children: [
3847
- /* @__PURE__ */ jsxs3(
4365
+ /* @__PURE__ */ jsxs4(
3848
4366
  "div",
3849
4367
  {
3850
4368
  style: {
@@ -3853,7 +4371,7 @@ function ReportDialog({
3853
4371
  alignItems: "center"
3854
4372
  },
3855
4373
  children: [
3856
- /* @__PURE__ */ jsxs3(
4374
+ /* @__PURE__ */ jsxs4(
3857
4375
  "div",
3858
4376
  {
3859
4377
  style: {
@@ -3862,7 +4380,7 @@ function ReportDialog({
3862
4380
  gap: "8px"
3863
4381
  },
3864
4382
  children: [
3865
- step > 1 && /* @__PURE__ */ jsx3(
4383
+ step > 1 && /* @__PURE__ */ jsx4(
3866
4384
  "button",
3867
4385
  {
3868
4386
  type: "button",
@@ -3876,14 +4394,14 @@ function ReportDialog({
3876
4394
  alignItems: "center"
3877
4395
  },
3878
4396
  "aria-label": "Back",
3879
- children: /* @__PURE__ */ jsx3(
4397
+ children: /* @__PURE__ */ jsx4(
3880
4398
  "svg",
3881
4399
  {
3882
4400
  width: "16",
3883
4401
  height: "16",
3884
4402
  viewBox: "0 0 16 16",
3885
4403
  fill: "none",
3886
- children: /* @__PURE__ */ jsx3(
4404
+ children: /* @__PURE__ */ jsx4(
3887
4405
  "path",
3888
4406
  {
3889
4407
  d: "M10 3L5 8L10 13",
@@ -3897,7 +4415,7 @@ function ReportDialog({
3897
4415
  )
3898
4416
  }
3899
4417
  ),
3900
- /* @__PURE__ */ jsx3(
4418
+ /* @__PURE__ */ jsx4(
3901
4419
  "span",
3902
4420
  {
3903
4421
  style: {
@@ -3911,7 +4429,7 @@ function ReportDialog({
3911
4429
  ]
3912
4430
  }
3913
4431
  ),
3914
- /* @__PURE__ */ jsxs3(
4432
+ /* @__PURE__ */ jsxs4(
3915
4433
  "div",
3916
4434
  {
3917
4435
  style: {
@@ -3920,7 +4438,7 @@ function ReportDialog({
3920
4438
  gap: "8px"
3921
4439
  },
3922
4440
  children: [
3923
- step === 1 && /* @__PURE__ */ jsx3(
4441
+ step === 1 && /* @__PURE__ */ jsx4(
3924
4442
  "span",
3925
4443
  {
3926
4444
  title: "Press this anywhere to open Glitchgrab",
@@ -3938,7 +4456,7 @@ function ReportDialog({
3938
4456
  children: getShortcutLabel()
3939
4457
  }
3940
4458
  ),
3941
- /* @__PURE__ */ jsx3(
4459
+ /* @__PURE__ */ jsx4(
3942
4460
  "button",
3943
4461
  {
3944
4462
  type: "button",
@@ -3953,7 +4471,7 @@ function ReportDialog({
3953
4471
  justifyContent: "center"
3954
4472
  },
3955
4473
  "aria-label": "Close",
3956
- children: /* @__PURE__ */ jsx3(
4474
+ children: /* @__PURE__ */ jsx4(
3957
4475
  "svg",
3958
4476
  {
3959
4477
  width: "16",
@@ -3961,7 +4479,7 @@ function ReportDialog({
3961
4479
  viewBox: "0 0 16 16",
3962
4480
  fill: "none",
3963
4481
  style: { display: "block" },
3964
- children: /* @__PURE__ */ jsx3(
4482
+ children: /* @__PURE__ */ jsx4(
3965
4483
  "path",
3966
4484
  {
3967
4485
  d: "M4 4L12 12M12 4L4 12",
@@ -3980,7 +4498,7 @@ function ReportDialog({
3980
4498
  ]
3981
4499
  }
3982
4500
  ),
3983
- /* @__PURE__ */ jsx3(
4501
+ /* @__PURE__ */ jsx4(
3984
4502
  "div",
3985
4503
  {
3986
4504
  style: {
@@ -3990,12 +4508,12 @@ function ReportDialog({
3990
4508
  gap: "0",
3991
4509
  marginTop: "12px"
3992
4510
  },
3993
- children: [1, 2].map((s, i) => /* @__PURE__ */ jsxs3(
4511
+ children: [1, 2].map((s, i) => /* @__PURE__ */ jsxs4(
3994
4512
  "div",
3995
4513
  {
3996
4514
  style: { display: "flex", alignItems: "center" },
3997
4515
  children: [
3998
- /* @__PURE__ */ jsx3(
4516
+ /* @__PURE__ */ jsx4(
3999
4517
  "div",
4000
4518
  {
4001
4519
  style: {
@@ -4007,7 +4525,7 @@ function ReportDialog({
4007
4525
  }
4008
4526
  }
4009
4527
  ),
4010
- i < 1 && /* @__PURE__ */ jsx3(
4528
+ i < 1 && /* @__PURE__ */ jsx4(
4011
4529
  "div",
4012
4530
  {
4013
4531
  style: {
@@ -4027,7 +4545,7 @@ function ReportDialog({
4027
4545
  ]
4028
4546
  }
4029
4547
  ),
4030
- /* @__PURE__ */ jsx3(
4548
+ /* @__PURE__ */ jsx4(
4031
4549
  "div",
4032
4550
  {
4033
4551
  style: {
@@ -4036,7 +4554,7 @@ function ReportDialog({
4036
4554
  flex: "1 1 auto",
4037
4555
  minHeight: 0
4038
4556
  },
4039
- children: submitted ? /* @__PURE__ */ jsxs3(
4557
+ children: submitted ? /* @__PURE__ */ jsxs4(
4040
4558
  "div",
4041
4559
  {
4042
4560
  style: {
@@ -4051,9 +4569,9 @@ function ReportDialog({
4051
4569
  " sent. Thank you!"
4052
4570
  ]
4053
4571
  }
4054
- ) : /* @__PURE__ */ jsxs3(Fragment2, { children: [
4055
- step === 1 && headerSlot ? /* @__PURE__ */ jsx3("div", { style: { marginBottom: "14px" }, children: headerSlot }) : null,
4056
- step === 1 && sendFeedback2 && /* @__PURE__ */ jsxs3(
4572
+ ) : /* @__PURE__ */ jsxs4(Fragment3, { children: [
4573
+ step === 1 && headerSlot ? /* @__PURE__ */ jsx4("div", { style: { marginBottom: "14px" }, children: headerSlot }) : null,
4574
+ step === 1 && sendFeedback2 && /* @__PURE__ */ jsxs4(
4057
4575
  "div",
4058
4576
  {
4059
4577
  style: {
@@ -4070,16 +4588,16 @@ function ReportDialog({
4070
4588
  },
4071
4589
  onMouseLeave: () => setHoveredStar(0),
4072
4590
  children: [
4073
- /* @__PURE__ */ jsx3(
4591
+ /* @__PURE__ */ jsx4(
4074
4592
  "span",
4075
4593
  {
4076
4594
  style: { fontSize: "13px", fontWeight: 600, color: t2.text },
4077
4595
  children: "How are we doing?"
4078
4596
  }
4079
4597
  ),
4080
- /* @__PURE__ */ jsx3("span", { style: { display: "flex", gap: "4px" }, children: [1, 2, 3, 4, 5].map((star) => {
4598
+ /* @__PURE__ */ jsx4("span", { style: { display: "flex", gap: "4px" }, children: [1, 2, 3, 4, 5].map((star) => {
4081
4599
  const filled = star <= (hoveredStar || rating);
4082
- return /* @__PURE__ */ jsx3(
4600
+ return /* @__PURE__ */ jsx4(
4083
4601
  "button",
4084
4602
  {
4085
4603
  type: "button",
@@ -4100,7 +4618,7 @@ function ReportDialog({
4100
4618
  cursor: "pointer",
4101
4619
  lineHeight: 0
4102
4620
  },
4103
- children: /* @__PURE__ */ jsx3("svg", { width: "26", height: "26", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx3(
4621
+ children: /* @__PURE__ */ jsx4("svg", { width: "26", height: "26", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx4(
4104
4622
  "path",
4105
4623
  {
4106
4624
  d: "M12 3l2.6 5.3 5.9.9-4.3 4.1 1 5.8L12 16.4 6.8 19.1l1-5.8L3.5 9.2l5.9-.9L12 3z",
@@ -4117,7 +4635,7 @@ function ReportDialog({
4117
4635
  ]
4118
4636
  }
4119
4637
  ),
4120
- step === 1 && sendFeedback2 && /* @__PURE__ */ jsxs3(
4638
+ step === 1 && sendFeedback2 && /* @__PURE__ */ jsxs4(
4121
4639
  "div",
4122
4640
  {
4123
4641
  style: {
@@ -4127,13 +4645,13 @@ function ReportDialog({
4127
4645
  marginBottom: "16px"
4128
4646
  },
4129
4647
  children: [
4130
- /* @__PURE__ */ jsx3("span", { style: { flex: 1, height: "1px", background: t2.border } }),
4131
- /* @__PURE__ */ jsx3("span", { style: { fontSize: "11px", color: t2.textMuted }, children: "or report something" }),
4132
- /* @__PURE__ */ jsx3("span", { style: { flex: 1, height: "1px", background: t2.border } })
4648
+ /* @__PURE__ */ jsx4("span", { style: { flex: 1, height: "1px", background: t2.border } }),
4649
+ /* @__PURE__ */ jsx4("span", { style: { fontSize: "11px", color: t2.textMuted }, children: "or report something" }),
4650
+ /* @__PURE__ */ jsx4("span", { style: { flex: 1, height: "1px", background: t2.border } })
4133
4651
  ]
4134
4652
  }
4135
4653
  ),
4136
- step === 1 && screenshots.length > 0 && /* @__PURE__ */ jsxs3(
4654
+ step === 1 && screenshots.length > 0 && /* @__PURE__ */ jsxs4(
4137
4655
  "div",
4138
4656
  {
4139
4657
  style: {
@@ -4147,7 +4665,7 @@ function ReportDialog({
4147
4665
  background: t2.inputBg
4148
4666
  },
4149
4667
  children: [
4150
- /* @__PURE__ */ jsx3(
4668
+ /* @__PURE__ */ jsx4(
4151
4669
  "img",
4152
4670
  {
4153
4671
  src: screenshots[0],
@@ -4162,8 +4680,8 @@ function ReportDialog({
4162
4680
  }
4163
4681
  }
4164
4682
  ),
4165
- /* @__PURE__ */ jsx3("span", { style: { fontSize: "11px", color: t2.textMuted, flex: 1 }, children: "Screenshot attached" }),
4166
- /* @__PURE__ */ jsx3(
4683
+ /* @__PURE__ */ jsx4("span", { style: { fontSize: "11px", color: t2.textMuted, flex: 1 }, children: "Screenshot attached" }),
4684
+ /* @__PURE__ */ jsx4(
4167
4685
  "button",
4168
4686
  {
4169
4687
  type: "button",
@@ -4184,7 +4702,7 @@ function ReportDialog({
4184
4702
  ]
4185
4703
  }
4186
4704
  ),
4187
- step === 1 && /* @__PURE__ */ jsx3(
4705
+ step === 1 && /* @__PURE__ */ jsx4(
4188
4706
  "div",
4189
4707
  {
4190
4708
  ref: tileGridRef,
@@ -4194,7 +4712,7 @@ function ReportDialog({
4194
4712
  gridTemplateColumns: "1fr 1fr 1fr",
4195
4713
  gap: "10px"
4196
4714
  },
4197
- children: availableTypes.map((type) => /* @__PURE__ */ jsxs3(
4715
+ children: availableTypes.map((type) => /* @__PURE__ */ jsxs4(
4198
4716
  "button",
4199
4717
  {
4200
4718
  type: "button",
@@ -4225,7 +4743,7 @@ function ReportDialog({
4225
4743
  },
4226
4744
  children: [
4227
4745
  getTypeIcon(type, t2.accent, 22),
4228
- /* @__PURE__ */ jsx3(
4746
+ /* @__PURE__ */ jsx4(
4229
4747
  "span",
4230
4748
  {
4231
4749
  style: {
@@ -4243,8 +4761,8 @@ function ReportDialog({
4243
4761
  ))
4244
4762
  }
4245
4763
  ),
4246
- step === 2 && /* @__PURE__ */ jsxs3(Fragment2, { children: [
4247
- /* @__PURE__ */ jsxs3(
4764
+ step === 2 && /* @__PURE__ */ jsxs4(Fragment3, { children: [
4765
+ /* @__PURE__ */ jsxs4(
4248
4766
  "button",
4249
4767
  {
4250
4768
  type: "button",
@@ -4267,11 +4785,11 @@ function ReportDialog({
4267
4785
  children: [
4268
4786
  getTypeIcon(reportType, isRating ? "#f59e0b" : t2.accent, 13),
4269
4787
  getTypeLabel(reportType),
4270
- /* @__PURE__ */ jsx3("span", { style: { color: t2.textMuted, fontWeight: 400 }, children: "\xB7 change" })
4788
+ /* @__PURE__ */ jsx4("span", { style: { color: t2.textMuted, fontWeight: 400 }, children: "\xB7 change" })
4271
4789
  ]
4272
4790
  }
4273
4791
  ),
4274
- isRating && /* @__PURE__ */ jsx3(
4792
+ isRating && /* @__PURE__ */ jsx4(
4275
4793
  "div",
4276
4794
  {
4277
4795
  style: {
@@ -4282,7 +4800,7 @@ function ReportDialog({
4282
4800
  onMouseLeave: () => setHoveredStar(0),
4283
4801
  children: [1, 2, 3, 4, 5].map((star) => {
4284
4802
  const filled = star <= (hoveredStar || rating);
4285
- return /* @__PURE__ */ jsx3(
4803
+ return /* @__PURE__ */ jsx4(
4286
4804
  "button",
4287
4805
  {
4288
4806
  type: "button",
@@ -4299,7 +4817,7 @@ function ReportDialog({
4299
4817
  cursor: "pointer",
4300
4818
  lineHeight: 0
4301
4819
  },
4302
- children: /* @__PURE__ */ jsx3("svg", { width: "30", height: "30", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx3(
4820
+ children: /* @__PURE__ */ jsx4("svg", { width: "30", height: "30", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx4(
4303
4821
  "path",
4304
4822
  {
4305
4823
  d: "M12 3l2.6 5.3 5.9.9-4.3 4.1 1 5.8L12 16.4 6.8 19.1l1-5.8L3.5 9.2l5.9-.9L12 3z",
@@ -4315,7 +4833,7 @@ function ReportDialog({
4315
4833
  })
4316
4834
  }
4317
4835
  ),
4318
- assist && !isRating && !assistUsed && /* @__PURE__ */ jsxs3(
4836
+ assist && !isRating && !assistUsed && /* @__PURE__ */ jsxs4(
4319
4837
  "button",
4320
4838
  {
4321
4839
  type: "button",
@@ -4342,7 +4860,7 @@ function ReportDialog({
4342
4860
  },
4343
4861
  title: "Answer a question or two and the assistant writes the report for you",
4344
4862
  children: [
4345
- /* @__PURE__ */ jsx3("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx3(
4863
+ /* @__PURE__ */ jsx4("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx4(
4346
4864
  "path",
4347
4865
  {
4348
4866
  d: "M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3zM19 15l.75 2.25L22 18l-2.25.75L19 21l-.75-2.25L16 18l2.25-.75L19 15z",
@@ -4355,8 +4873,8 @@ function ReportDialog({
4355
4873
  ]
4356
4874
  }
4357
4875
  ),
4358
- /* @__PURE__ */ jsxs3("div", { style: { position: "relative" }, children: [
4359
- /* @__PURE__ */ jsx3(
4876
+ /* @__PURE__ */ jsxs4("div", { style: { position: "relative" }, children: [
4877
+ /* @__PURE__ */ jsx4(
4360
4878
  "textarea",
4361
4879
  {
4362
4880
  ref: textareaRef,
@@ -4398,7 +4916,7 @@ function ReportDialog({
4398
4916
  autoFocus: true
4399
4917
  }
4400
4918
  ),
4401
- (isListening || isTranscribing) && /* @__PURE__ */ jsxs3(
4919
+ (isListening || isTranscribing) && /* @__PURE__ */ jsxs4(
4402
4920
  "span",
4403
4921
  {
4404
4922
  style: {
@@ -4416,7 +4934,7 @@ function ReportDialog({
4416
4934
  zIndex: 1
4417
4935
  },
4418
4936
  children: [
4419
- /* @__PURE__ */ jsx3(
4937
+ /* @__PURE__ */ jsx4(
4420
4938
  "span",
4421
4939
  {
4422
4940
  style: {
@@ -4431,7 +4949,7 @@ function ReportDialog({
4431
4949
  }
4432
4950
  ),
4433
4951
  isTranscribing ? "Transcribing\u2026" : "REC",
4434
- isListening && !isTranscribing && /* @__PURE__ */ jsx3(
4952
+ isListening && !isTranscribing && /* @__PURE__ */ jsx4(
4435
4953
  "span",
4436
4954
  {
4437
4955
  style: {
@@ -4458,7 +4976,7 @@ function ReportDialog({
4458
4976
  dur: "0.55s",
4459
4977
  delay: "0.15s"
4460
4978
  }
4461
- ].map((b, i) => /* @__PURE__ */ jsx3(
4979
+ ].map((b, i) => /* @__PURE__ */ jsx4(
4462
4980
  "span",
4463
4981
  {
4464
4982
  style: {
@@ -4478,7 +4996,7 @@ function ReportDialog({
4478
4996
  ]
4479
4997
  }
4480
4998
  ),
4481
- enhanceText2 && /* @__PURE__ */ jsxs3(
4999
+ enhanceText2 && /* @__PURE__ */ jsxs4(
4482
5000
  "button",
4483
5001
  {
4484
5002
  type: "button",
@@ -4523,7 +5041,7 @@ function ReportDialog({
4523
5041
  },
4524
5042
  title: "Polish grammar \u2014 preserves your meaning",
4525
5043
  children: [
4526
- /* @__PURE__ */ jsx3(
5044
+ /* @__PURE__ */ jsx4(
4527
5045
  "svg",
4528
5046
  {
4529
5047
  width: "11",
@@ -4531,7 +5049,7 @@ function ReportDialog({
4531
5049
  viewBox: "0 0 24 24",
4532
5050
  fill: "none",
4533
5051
  "aria-hidden": "true",
4534
- children: /* @__PURE__ */ jsx3(
5052
+ children: /* @__PURE__ */ jsx4(
4535
5053
  "path",
4536
5054
  {
4537
5055
  d: "M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3zM19 15l.75 2.25L22 18l-2.25.75L19 21l-.75-2.25L16 18l2.25-.75L19 15z",
@@ -4546,7 +5064,7 @@ function ReportDialog({
4546
5064
  ]
4547
5065
  }
4548
5066
  ),
4549
- transcribeAudio2 && /* @__PURE__ */ jsx3(
5067
+ transcribeAudio2 && /* @__PURE__ */ jsx4(
4550
5068
  "button",
4551
5069
  {
4552
5070
  type: "button",
@@ -4572,7 +5090,7 @@ function ReportDialog({
4572
5090
  padding: 0,
4573
5091
  transition: "border-color 0.2s ease, color 0.2s ease"
4574
5092
  },
4575
- children: isListening ? /* @__PURE__ */ jsx3(
5093
+ children: isListening ? /* @__PURE__ */ jsx4(
4576
5094
  "svg",
4577
5095
  {
4578
5096
  width: "12",
@@ -4580,7 +5098,7 @@ function ReportDialog({
4580
5098
  viewBox: "0 0 24 24",
4581
5099
  fill: "currentColor",
4582
5100
  "aria-hidden": "true",
4583
- children: /* @__PURE__ */ jsx3(
5101
+ children: /* @__PURE__ */ jsx4(
4584
5102
  "rect",
4585
5103
  {
4586
5104
  x: "6",
@@ -4591,7 +5109,7 @@ function ReportDialog({
4591
5109
  }
4592
5110
  )
4593
5111
  }
4594
- ) : /* @__PURE__ */ jsxs3(
5112
+ ) : /* @__PURE__ */ jsxs4(
4595
5113
  "svg",
4596
5114
  {
4597
5115
  width: "13",
@@ -4600,7 +5118,7 @@ function ReportDialog({
4600
5118
  fill: "none",
4601
5119
  "aria-hidden": "true",
4602
5120
  children: [
4603
- /* @__PURE__ */ jsx3(
5121
+ /* @__PURE__ */ jsx4(
4604
5122
  "rect",
4605
5123
  {
4606
5124
  x: "9",
@@ -4612,7 +5130,7 @@ function ReportDialog({
4612
5130
  strokeWidth: "1.8"
4613
5131
  }
4614
5132
  ),
4615
- /* @__PURE__ */ jsx3(
5133
+ /* @__PURE__ */ jsx4(
4616
5134
  "path",
4617
5135
  {
4618
5136
  d: "M5 10a7 7 0 0014 0M12 19v3M9 22h6",
@@ -4627,7 +5145,7 @@ function ReportDialog({
4627
5145
  }
4628
5146
  )
4629
5147
  ] }),
4630
- transcribeAudio2 && !isListening && !isTranscribing && !voiceError && /* @__PURE__ */ jsxs3(
5148
+ transcribeAudio2 && !isListening && !isTranscribing && !voiceError && /* @__PURE__ */ jsxs4(
4631
5149
  "div",
4632
5150
  {
4633
5151
  style: {
@@ -4641,16 +5159,16 @@ function ReportDialog({
4641
5159
  userSelect: "none"
4642
5160
  },
4643
5161
  children: [
4644
- /* @__PURE__ */ jsxs3("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
4645
- /* @__PURE__ */ jsx3("path", { d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z" }),
4646
- /* @__PURE__ */ jsx3("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
4647
- /* @__PURE__ */ jsx3("line", { x1: "12", x2: "12", y1: "19", y2: "22" })
5162
+ /* @__PURE__ */ jsxs4("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
5163
+ /* @__PURE__ */ jsx4("path", { d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z" }),
5164
+ /* @__PURE__ */ jsx4("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
5165
+ /* @__PURE__ */ jsx4("line", { x1: "12", x2: "12", y1: "19", y2: "22" })
4648
5166
  ] }),
4649
5167
  "Hold Space to speak \u2014 we'll transcribe it"
4650
5168
  ]
4651
5169
  }
4652
5170
  ),
4653
- isEnhanced && originalDescription !== null && /* @__PURE__ */ jsxs3(
5171
+ isEnhanced && originalDescription !== null && /* @__PURE__ */ jsxs4(
4654
5172
  "div",
4655
5173
  {
4656
5174
  style: {
@@ -4664,7 +5182,7 @@ function ReportDialog({
4664
5182
  border: `1px solid ${t2.accent}40`
4665
5183
  },
4666
5184
  children: [
4667
- /* @__PURE__ */ jsx3(
5185
+ /* @__PURE__ */ jsx4(
4668
5186
  "svg",
4669
5187
  {
4670
5188
  width: "12",
@@ -4672,7 +5190,7 @@ function ReportDialog({
4672
5190
  viewBox: "0 0 24 24",
4673
5191
  fill: "none",
4674
5192
  style: { flexShrink: 0 },
4675
- children: /* @__PURE__ */ jsx3(
5193
+ children: /* @__PURE__ */ jsx4(
4676
5194
  "path",
4677
5195
  {
4678
5196
  d: "M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3z",
@@ -4683,7 +5201,7 @@ function ReportDialog({
4683
5201
  )
4684
5202
  }
4685
5203
  ),
4686
- /* @__PURE__ */ jsx3(
5204
+ /* @__PURE__ */ jsx4(
4687
5205
  "span",
4688
5206
  {
4689
5207
  style: {
@@ -4694,7 +5212,7 @@ function ReportDialog({
4694
5212
  children: "AI enhanced"
4695
5213
  }
4696
5214
  ),
4697
- /* @__PURE__ */ jsx3(
5215
+ /* @__PURE__ */ jsx4(
4698
5216
  "button",
4699
5217
  {
4700
5218
  type: "button",
@@ -4716,7 +5234,7 @@ function ReportDialog({
4716
5234
  children: "Keep"
4717
5235
  }
4718
5236
  ),
4719
- /* @__PURE__ */ jsx3(
5237
+ /* @__PURE__ */ jsx4(
4720
5238
  "button",
4721
5239
  {
4722
5240
  type: "button",
@@ -4742,7 +5260,7 @@ function ReportDialog({
4742
5260
  ]
4743
5261
  }
4744
5262
  ),
4745
- voiceError && /* @__PURE__ */ jsx3(
5263
+ voiceError && /* @__PURE__ */ jsx4(
4746
5264
  "p",
4747
5265
  {
4748
5266
  role: "alert",
@@ -4756,7 +5274,7 @@ function ReportDialog({
4756
5274
  children: voiceError
4757
5275
  }
4758
5276
  ),
4759
- assistNotice && /* @__PURE__ */ jsx3(
5277
+ assistNotice && /* @__PURE__ */ jsx4(
4760
5278
  "p",
4761
5279
  {
4762
5280
  style: {
@@ -4769,8 +5287,8 @@ function ReportDialog({
4769
5287
  children: assistNotice
4770
5288
  }
4771
5289
  ),
4772
- !isRating && /* @__PURE__ */ jsxs3("div", { style: { marginTop: "10px" }, children: [
4773
- /* @__PURE__ */ jsxs3(
5290
+ !isRating && /* @__PURE__ */ jsxs4("div", { style: { marginTop: "10px" }, children: [
5291
+ /* @__PURE__ */ jsxs4(
4774
5292
  "span",
4775
5293
  {
4776
5294
  style: {
@@ -4786,7 +5304,7 @@ function ReportDialog({
4786
5304
  ]
4787
5305
  }
4788
5306
  ),
4789
- screenshots.length > 0 && /* @__PURE__ */ jsx3(
5307
+ (screenshots.length > 0 || shotPending) && /* @__PURE__ */ jsxs4(
4790
5308
  "div",
4791
5309
  {
4792
5310
  style: {
@@ -4795,132 +5313,159 @@ function ReportDialog({
4795
5313
  gap: "8px",
4796
5314
  marginBottom: "8px"
4797
5315
  },
4798
- children: screenshots.map((src, i) => /* @__PURE__ */ jsxs3(
4799
- "div",
4800
- {
4801
- style: {
4802
- position: "relative",
4803
- width: "56px",
4804
- height: "56px"
4805
- },
4806
- children: [
4807
- /* @__PURE__ */ jsx3(
4808
- "img",
4809
- {
4810
- src,
4811
- alt: `Screenshot ${i + 1}`,
4812
- onClick: () => openPreview(i),
4813
- style: {
4814
- width: "100%",
4815
- height: "100%",
4816
- borderRadius: "6px",
4817
- border: `1px solid ${t2.border}`,
4818
- objectFit: "cover",
4819
- objectPosition: "top",
4820
- cursor: "zoom-in",
4821
- display: "block"
4822
- }
4823
- }
4824
- ),
4825
- /* @__PURE__ */ jsx3(
4826
- "button",
4827
- {
4828
- type: "button",
4829
- onClick: () => setScreenshots(
4830
- (prev) => prev.filter((_, idx) => idx !== i)
4831
- ),
4832
- "aria-label": `Remove screenshot ${i + 1}`,
4833
- style: {
4834
- position: "absolute",
4835
- top: "-6px",
4836
- right: "-6px",
4837
- width: "17px",
4838
- height: "17px",
4839
- borderRadius: "50%",
4840
- border: "none",
4841
- background: "#ef4444",
4842
- color: "#fff",
4843
- fontSize: "11px",
4844
- lineHeight: 1,
4845
- padding: 0,
4846
- cursor: "pointer",
4847
- display: "flex",
4848
- alignItems: "center",
4849
- justifyContent: "center"
4850
- },
4851
- children: /* @__PURE__ */ jsx3(
4852
- "svg",
4853
- {
4854
- width: "8",
4855
- height: "8",
4856
- viewBox: "0 0 10 10",
4857
- fill: "none",
4858
- children: /* @__PURE__ */ jsx3(
4859
- "path",
4860
- {
4861
- d: "M1 1L9 9M9 1L1 9",
4862
- stroke: "currentColor",
4863
- strokeWidth: "1.5",
4864
- strokeLinecap: "round"
4865
- }
4866
- )
4867
- }
4868
- )
4869
- }
4870
- ),
4871
- /* @__PURE__ */ jsx3(
4872
- "button",
4873
- {
4874
- type: "button",
4875
- onClick: () => setAnnotatingIndex(i),
4876
- "aria-label": `Annotate screenshot ${i + 1}`,
4877
- title: "Annotate",
4878
- style: {
4879
- position: "absolute",
4880
- top: "50%",
4881
- left: "50%",
4882
- transform: "translate(-50%, -50%)",
4883
- width: "24px",
4884
- height: "24px",
4885
- borderRadius: "50%",
4886
- border: "none",
4887
- background: t2.accent,
4888
- color: t2.accentText,
4889
- padding: 0,
4890
- cursor: "pointer",
4891
- display: "flex",
4892
- alignItems: "center",
4893
- justifyContent: "center",
4894
- boxShadow: "0 2px 8px rgba(0,0,0,0.45)"
4895
- },
4896
- children: /* @__PURE__ */ jsx3(
4897
- "svg",
4898
- {
4899
- width: "12",
4900
- height: "12",
4901
- viewBox: "0 0 24 24",
4902
- fill: "none",
4903
- children: /* @__PURE__ */ jsx3(
4904
- "path",
4905
- {
4906
- d: "M12 20h9M16.5 3.5a2.12 2.12 0 013 3L7 19l-4 1 1-4L16.5 3.5z",
4907
- stroke: "currentColor",
4908
- strokeWidth: "2.2",
4909
- strokeLinecap: "round",
4910
- strokeLinejoin: "round"
4911
- }
4912
- )
5316
+ children: [
5317
+ shotPending && /* @__PURE__ */ jsx4(
5318
+ "div",
5319
+ {
5320
+ role: "status",
5321
+ "aria-label": "Capturing screenshot",
5322
+ title: "Capturing a screenshot of the page\u2026",
5323
+ style: {
5324
+ width: "56px",
5325
+ height: "56px",
5326
+ borderRadius: "6px",
5327
+ border: `1px dashed ${t2.border}`,
5328
+ display: "flex",
5329
+ alignItems: "center",
5330
+ justifyContent: "center",
5331
+ padding: "4px",
5332
+ boxSizing: "border-box",
5333
+ fontSize: "9px",
5334
+ lineHeight: 1.2,
5335
+ textAlign: "center",
5336
+ color: t2.textMuted,
5337
+ animation: "gg-pulse 1.4s ease-in-out infinite"
5338
+ },
5339
+ children: "Capturing\u2026"
5340
+ }
5341
+ ),
5342
+ screenshots.map((src, i) => /* @__PURE__ */ jsxs4(
5343
+ "div",
5344
+ {
5345
+ style: {
5346
+ position: "relative",
5347
+ width: "56px",
5348
+ height: "56px"
5349
+ },
5350
+ children: [
5351
+ /* @__PURE__ */ jsx4(
5352
+ "img",
5353
+ {
5354
+ src,
5355
+ alt: `Screenshot ${i + 1}`,
5356
+ onClick: () => openPreview(i),
5357
+ style: {
5358
+ width: "100%",
5359
+ height: "100%",
5360
+ borderRadius: "6px",
5361
+ border: `1px solid ${t2.border}`,
5362
+ objectFit: "cover",
5363
+ objectPosition: "top",
5364
+ cursor: "zoom-in",
5365
+ display: "block"
4913
5366
  }
4914
- )
4915
- }
4916
- )
4917
- ]
4918
- },
4919
- i
4920
- ))
5367
+ }
5368
+ ),
5369
+ /* @__PURE__ */ jsx4(
5370
+ "button",
5371
+ {
5372
+ type: "button",
5373
+ onClick: () => setScreenshots(
5374
+ (prev) => prev.filter((_, idx) => idx !== i)
5375
+ ),
5376
+ "aria-label": `Remove screenshot ${i + 1}`,
5377
+ style: {
5378
+ position: "absolute",
5379
+ top: "-6px",
5380
+ right: "-6px",
5381
+ width: "17px",
5382
+ height: "17px",
5383
+ borderRadius: "50%",
5384
+ border: "none",
5385
+ background: "#ef4444",
5386
+ color: "#fff",
5387
+ fontSize: "11px",
5388
+ lineHeight: 1,
5389
+ padding: 0,
5390
+ cursor: "pointer",
5391
+ display: "flex",
5392
+ alignItems: "center",
5393
+ justifyContent: "center"
5394
+ },
5395
+ children: /* @__PURE__ */ jsx4(
5396
+ "svg",
5397
+ {
5398
+ width: "8",
5399
+ height: "8",
5400
+ viewBox: "0 0 10 10",
5401
+ fill: "none",
5402
+ children: /* @__PURE__ */ jsx4(
5403
+ "path",
5404
+ {
5405
+ d: "M1 1L9 9M9 1L1 9",
5406
+ stroke: "currentColor",
5407
+ strokeWidth: "1.5",
5408
+ strokeLinecap: "round"
5409
+ }
5410
+ )
5411
+ }
5412
+ )
5413
+ }
5414
+ ),
5415
+ /* @__PURE__ */ jsx4(
5416
+ "button",
5417
+ {
5418
+ type: "button",
5419
+ onClick: () => setAnnotatingIndex(i),
5420
+ "aria-label": `Annotate screenshot ${i + 1}`,
5421
+ title: "Annotate",
5422
+ style: {
5423
+ position: "absolute",
5424
+ top: "50%",
5425
+ left: "50%",
5426
+ transform: "translate(-50%, -50%)",
5427
+ width: "24px",
5428
+ height: "24px",
5429
+ borderRadius: "50%",
5430
+ border: "none",
5431
+ background: t2.accent,
5432
+ color: t2.accentText,
5433
+ padding: 0,
5434
+ cursor: "pointer",
5435
+ display: "flex",
5436
+ alignItems: "center",
5437
+ justifyContent: "center",
5438
+ boxShadow: "0 2px 8px rgba(0,0,0,0.45)"
5439
+ },
5440
+ children: /* @__PURE__ */ jsx4(
5441
+ "svg",
5442
+ {
5443
+ width: "12",
5444
+ height: "12",
5445
+ viewBox: "0 0 24 24",
5446
+ fill: "none",
5447
+ children: /* @__PURE__ */ jsx4(
5448
+ "path",
5449
+ {
5450
+ d: "M12 20h9M16.5 3.5a2.12 2.12 0 013 3L7 19l-4 1 1-4L16.5 3.5z",
5451
+ stroke: "currentColor",
5452
+ strokeWidth: "2.2",
5453
+ strokeLinecap: "round",
5454
+ strokeLinejoin: "round"
5455
+ }
5456
+ )
5457
+ }
5458
+ )
5459
+ }
5460
+ )
5461
+ ]
5462
+ },
5463
+ i
5464
+ ))
5465
+ ]
4921
5466
  }
4922
5467
  ),
4923
- attachments.length > 0 && /* @__PURE__ */ jsx3(
5468
+ attachments.length > 0 && /* @__PURE__ */ jsx4(
4924
5469
  "div",
4925
5470
  {
4926
5471
  style: {
@@ -4929,7 +5474,7 @@ function ReportDialog({
4929
5474
  gap: "6px",
4930
5475
  marginBottom: "8px"
4931
5476
  },
4932
- children: attachments.map((a, i) => /* @__PURE__ */ jsxs3(
5477
+ children: attachments.map((a, i) => /* @__PURE__ */ jsxs4(
4933
5478
  "div",
4934
5479
  {
4935
5480
  style: {
@@ -4941,7 +5486,7 @@ function ReportDialog({
4941
5486
  border: `1px solid ${t2.border}`
4942
5487
  },
4943
5488
  children: [
4944
- /* @__PURE__ */ jsxs3(
5489
+ /* @__PURE__ */ jsxs4(
4945
5490
  "svg",
4946
5491
  {
4947
5492
  width: "14",
@@ -4950,7 +5495,7 @@ function ReportDialog({
4950
5495
  fill: "none",
4951
5496
  style: { flexShrink: 0, opacity: 0.6 },
4952
5497
  children: [
4953
- /* @__PURE__ */ jsx3(
5498
+ /* @__PURE__ */ jsx4(
4954
5499
  "path",
4955
5500
  {
4956
5501
  d: "M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z",
@@ -4960,7 +5505,7 @@ function ReportDialog({
4960
5505
  strokeLinejoin: "round"
4961
5506
  }
4962
5507
  ),
4963
- /* @__PURE__ */ jsx3(
5508
+ /* @__PURE__ */ jsx4(
4964
5509
  "path",
4965
5510
  {
4966
5511
  d: "M14 2v6h6",
@@ -4973,7 +5518,7 @@ function ReportDialog({
4973
5518
  ]
4974
5519
  }
4975
5520
  ),
4976
- /* @__PURE__ */ jsx3(
5521
+ /* @__PURE__ */ jsx4(
4977
5522
  "span",
4978
5523
  {
4979
5524
  style: {
@@ -4987,7 +5532,7 @@ function ReportDialog({
4987
5532
  children: a.name
4988
5533
  }
4989
5534
  ),
4990
- /* @__PURE__ */ jsxs3(
5535
+ /* @__PURE__ */ jsxs4(
4991
5536
  "span",
4992
5537
  {
4993
5538
  style: { fontSize: "10px", color: t2.textMuted },
@@ -4997,7 +5542,7 @@ function ReportDialog({
4997
5542
  ]
4998
5543
  }
4999
5544
  ),
5000
- /* @__PURE__ */ jsx3(
5545
+ /* @__PURE__ */ jsx4(
5001
5546
  "button",
5002
5547
  {
5003
5548
  type: "button",
@@ -5021,14 +5566,14 @@ function ReportDialog({
5021
5566
  justifyContent: "center",
5022
5567
  flexShrink: 0
5023
5568
  },
5024
- children: /* @__PURE__ */ jsx3(
5569
+ children: /* @__PURE__ */ jsx4(
5025
5570
  "svg",
5026
5571
  {
5027
5572
  width: "8",
5028
5573
  height: "8",
5029
5574
  viewBox: "0 0 10 10",
5030
5575
  fill: "none",
5031
- children: /* @__PURE__ */ jsx3(
5576
+ children: /* @__PURE__ */ jsx4(
5032
5577
  "path",
5033
5578
  {
5034
5579
  d: "M1 1L9 9M9 1L1 9",
@@ -5047,7 +5592,7 @@ function ReportDialog({
5047
5592
  ))
5048
5593
  }
5049
5594
  ),
5050
- /* @__PURE__ */ jsx3(
5595
+ /* @__PURE__ */ jsx4(
5051
5596
  "div",
5052
5597
  {
5053
5598
  onClick: () => {
@@ -5073,7 +5618,7 @@ function ReportDialog({
5073
5618
  background: screenshotDragOver ? isDark ? "rgba(34,211,238,0.06)" : "rgba(8,145,178,0.04)" : "transparent",
5074
5619
  transition: "border-color 0.15s ease, background 0.15s ease"
5075
5620
  },
5076
- children: screenshots.length + attachments.length > 0 ? /* @__PURE__ */ jsx3(
5621
+ children: screenshots.length + attachments.length > 0 ? /* @__PURE__ */ jsx4(
5077
5622
  "p",
5078
5623
  {
5079
5624
  style: {
@@ -5084,8 +5629,8 @@ function ReportDialog({
5084
5629
  },
5085
5630
  children: screenshotDragOver ? "Drop to attach" : "+ Add more \xB7 Drag & drop \xB7 Paste"
5086
5631
  }
5087
- ) : /* @__PURE__ */ jsxs3(Fragment2, { children: [
5088
- /* @__PURE__ */ jsxs3(
5632
+ ) : /* @__PURE__ */ jsxs4(Fragment3, { children: [
5633
+ /* @__PURE__ */ jsxs4(
5089
5634
  "svg",
5090
5635
  {
5091
5636
  width: "22",
@@ -5098,7 +5643,7 @@ function ReportDialog({
5098
5643
  opacity: 0.45
5099
5644
  },
5100
5645
  children: [
5101
- /* @__PURE__ */ jsx3(
5646
+ /* @__PURE__ */ jsx4(
5102
5647
  "rect",
5103
5648
  {
5104
5649
  x: "3",
@@ -5110,7 +5655,7 @@ function ReportDialog({
5110
5655
  strokeWidth: "1.5"
5111
5656
  }
5112
5657
  ),
5113
- /* @__PURE__ */ jsx3(
5658
+ /* @__PURE__ */ jsx4(
5114
5659
  "circle",
5115
5660
  {
5116
5661
  cx: "8.5",
@@ -5120,7 +5665,7 @@ function ReportDialog({
5120
5665
  strokeWidth: "1.5"
5121
5666
  }
5122
5667
  ),
5123
- /* @__PURE__ */ jsx3(
5668
+ /* @__PURE__ */ jsx4(
5124
5669
  "path",
5125
5670
  {
5126
5671
  d: "M21 15l-5-5L5 21",
@@ -5133,7 +5678,7 @@ function ReportDialog({
5133
5678
  ]
5134
5679
  }
5135
5680
  ),
5136
- /* @__PURE__ */ jsx3(
5681
+ /* @__PURE__ */ jsx4(
5137
5682
  "p",
5138
5683
  {
5139
5684
  style: {
@@ -5145,7 +5690,7 @@ function ReportDialog({
5145
5690
  children: screenshotDragOver ? "Drop to attach" : "Add screenshots or files"
5146
5691
  }
5147
5692
  ),
5148
- /* @__PURE__ */ jsx3(
5693
+ /* @__PURE__ */ jsx4(
5149
5694
  "p",
5150
5695
  {
5151
5696
  style: {
@@ -5160,8 +5705,8 @@ function ReportDialog({
5160
5705
  }
5161
5706
  )
5162
5707
  ] }),
5163
- showSeverity && reportType === "BUG" && /* @__PURE__ */ jsxs3("div", { style: { marginTop: "10px" }, children: [
5164
- /* @__PURE__ */ jsxs3(
5708
+ showSeverity && reportType === "BUG" && /* @__PURE__ */ jsxs4("div", { style: { marginTop: "10px" }, children: [
5709
+ /* @__PURE__ */ jsxs4(
5165
5710
  "span",
5166
5711
  {
5167
5712
  style: {
@@ -5174,7 +5719,7 @@ function ReportDialog({
5174
5719
  },
5175
5720
  children: [
5176
5721
  "How bad is it?",
5177
- /* @__PURE__ */ jsx3(
5722
+ /* @__PURE__ */ jsx4(
5178
5723
  "span",
5179
5724
  {
5180
5725
  style: {
@@ -5187,7 +5732,7 @@ function ReportDialog({
5187
5732
  ]
5188
5733
  }
5189
5734
  ),
5190
- /* @__PURE__ */ jsx3(
5735
+ /* @__PURE__ */ jsx4(
5191
5736
  "div",
5192
5737
  {
5193
5738
  role: "radiogroup",
@@ -5195,7 +5740,7 @@ function ReportDialog({
5195
5740
  style: { display: "flex", gap: "6px" },
5196
5741
  children: SEVERITY_LEVELS.map((s) => {
5197
5742
  const on = severity === s;
5198
- return /* @__PURE__ */ jsx3(
5743
+ return /* @__PURE__ */ jsx4(
5199
5744
  "button",
5200
5745
  {
5201
5746
  type: "button",
@@ -5236,7 +5781,7 @@ function ReportDialog({
5236
5781
  }
5237
5782
  )
5238
5783
  ] }),
5239
- validationError && /* @__PURE__ */ jsx3(
5784
+ validationError && /* @__PURE__ */ jsx4(
5240
5785
  "p",
5241
5786
  {
5242
5787
  style: {
@@ -5247,7 +5792,7 @@ function ReportDialog({
5247
5792
  children: validationError
5248
5793
  }
5249
5794
  ),
5250
- /* @__PURE__ */ jsx3(
5795
+ /* @__PURE__ */ jsx4(
5251
5796
  "button",
5252
5797
  {
5253
5798
  type: "button",
@@ -5267,14 +5812,14 @@ function ReportDialog({
5267
5812
  fontFamily: "inherit",
5268
5813
  transition: "background-color 0.15s ease"
5269
5814
  },
5270
- children: isSubmitting ? "Sending..." : isRating ? "Send Rating" : "Send Report"
5815
+ children: isSubmitting ? shotPending && !isRating ? "Attaching screenshot\u2026" : "Sending..." : isRating ? "Send Rating" : "Send Report"
5271
5816
  }
5272
5817
  )
5273
5818
  ] })
5274
5819
  ] })
5275
5820
  }
5276
5821
  ),
5277
- /* @__PURE__ */ jsxs3(
5822
+ /* @__PURE__ */ jsxs4(
5278
5823
  "div",
5279
5824
  {
5280
5825
  style: {
@@ -5286,8 +5831,35 @@ function ReportDialog({
5286
5831
  gap: "12px"
5287
5832
  },
5288
5833
  children: [
5289
- /* @__PURE__ */ jsx3(ReporterChip, { reporter, t: t2 }),
5290
- /* @__PURE__ */ jsx3(
5834
+ /* @__PURE__ */ jsx4(ReporterChip, { reporter, t: t2 }),
5835
+ reportGlitchgrabProblem ? /* @__PURE__ */ jsx4(
5836
+ "button",
5837
+ {
5838
+ type: "button",
5839
+ "data-gg-self-report": "",
5840
+ onClick: () => {
5841
+ setSelfReportPrefill("");
5842
+ setSelfReportFrom("form");
5843
+ },
5844
+ title: "Something wrong with this reporter itself? Tell the Glitchgrab team.",
5845
+ style: {
5846
+ fontSize: "11px",
5847
+ color: t2.textMuted,
5848
+ whiteSpace: "nowrap",
5849
+ flexShrink: 0,
5850
+ border: "none",
5851
+ background: "transparent",
5852
+ fontFamily: "inherit",
5853
+ cursor: "pointer",
5854
+ textDecoration: "underline",
5855
+ textUnderlineOffset: "2px",
5856
+ // A ~30px tap target without growing the footer.
5857
+ padding: "9px 0",
5858
+ margin: "-9px 0"
5859
+ },
5860
+ children: "Problem with Glitchgrab?"
5861
+ }
5862
+ ) : /* @__PURE__ */ jsx4(
5291
5863
  "span",
5292
5864
  {
5293
5865
  style: {
@@ -5309,7 +5881,7 @@ function ReportDialog({
5309
5881
  ),
5310
5882
  document.body
5311
5883
  ),
5312
- /* @__PURE__ */ jsx3(
5884
+ /* @__PURE__ */ jsx4(
5313
5885
  "input",
5314
5886
  {
5315
5887
  ref: fileInputRef,
@@ -5320,8 +5892,8 @@ function ReportDialog({
5320
5892
  style: { display: "none" }
5321
5893
  }
5322
5894
  ),
5323
- isOpen && previewIndex !== null && screenshots[previewIndex] && createPortal2(
5324
- /* @__PURE__ */ jsxs3(
5895
+ isOpen && previewIndex !== null && screenshots[previewIndex] && createPortal3(
5896
+ /* @__PURE__ */ jsxs4(
5325
5897
  "div",
5326
5898
  {
5327
5899
  "data-glitchgrab-layer": "",
@@ -5343,7 +5915,7 @@ function ReportDialog({
5343
5915
  },
5344
5916
  onMouseDown: (e) => e.stopPropagation(),
5345
5917
  children: [
5346
- /* @__PURE__ */ jsxs3(
5918
+ /* @__PURE__ */ jsxs4(
5347
5919
  "div",
5348
5920
  {
5349
5921
  ref: previewImgRef,
@@ -5355,7 +5927,7 @@ function ReportDialog({
5355
5927
  },
5356
5928
  onClick: (e) => e.stopPropagation(),
5357
5929
  children: [
5358
- /* @__PURE__ */ jsx3(
5930
+ /* @__PURE__ */ jsx4(
5359
5931
  "div",
5360
5932
  {
5361
5933
  ref: previewScrollRef,
@@ -5374,7 +5946,7 @@ function ReportDialog({
5374
5946
  touchAction: "none",
5375
5947
  cursor: "grab"
5376
5948
  } : { maxWidth: "100%", lineHeight: 0 },
5377
- children: /* @__PURE__ */ jsx3(
5949
+ children: /* @__PURE__ */ jsx4(
5378
5950
  "img",
5379
5951
  {
5380
5952
  ref: previewImgElRef,
@@ -5402,7 +5974,7 @@ function ReportDialog({
5402
5974
  )
5403
5975
  }
5404
5976
  ),
5405
- /* @__PURE__ */ jsxs3(
5977
+ /* @__PURE__ */ jsxs4(
5406
5978
  "button",
5407
5979
  {
5408
5980
  type: "button",
@@ -5430,7 +6002,7 @@ function ReportDialog({
5430
6002
  animation: "gg-pulse 2s ease-in-out infinite"
5431
6003
  },
5432
6004
  children: [
5433
- /* @__PURE__ */ jsx3("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx3(
6005
+ /* @__PURE__ */ jsx4("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx4(
5434
6006
  "path",
5435
6007
  {
5436
6008
  d: "M12 20h9M16.5 3.5a2.12 2.12 0 013 3L7 19l-4 1 1-4L16.5 3.5z",
@@ -5447,7 +6019,7 @@ function ReportDialog({
5447
6019
  ]
5448
6020
  }
5449
6021
  ),
5450
- /* @__PURE__ */ jsx3(
6022
+ /* @__PURE__ */ jsx4(
5451
6023
  "div",
5452
6024
  {
5453
6025
  style: {
@@ -5456,7 +6028,7 @@ function ReportDialog({
5456
6028
  alignItems: "center",
5457
6029
  gap: "12px"
5458
6030
  },
5459
- children: /* @__PURE__ */ jsx3(
6031
+ children: /* @__PURE__ */ jsx4(
5460
6032
  "span",
5461
6033
  {
5462
6034
  style: {
@@ -5477,8 +6049,8 @@ function ReportDialog({
5477
6049
  ),
5478
6050
  document.body
5479
6051
  ),
5480
- isOpen && annotatingIndex !== null && screenshots[annotatingIndex] && createPortal2(
5481
- /* @__PURE__ */ jsx3(
6052
+ isOpen && annotatingIndex !== null && screenshots[annotatingIndex] && createPortal3(
6053
+ /* @__PURE__ */ jsx4(
5482
6054
  AnnotationCanvas,
5483
6055
  {
5484
6056
  imageSrc: screenshots[annotatingIndex],
@@ -5494,21 +6066,24 @@ function ReportDialog({
5494
6066
  ),
5495
6067
  document.body
5496
6068
  ),
5497
- isOpen && sheetUp && /* @__PURE__ */ jsx3(
6069
+ isOpen && selfReportFrom && reportGlitchgrabProblem && /* @__PURE__ */ jsx4(
6070
+ GlitchgrabProblemPanel,
6071
+ {
6072
+ send: reportGlitchgrabProblem,
6073
+ theme: layerTheme,
6074
+ surface: selfReportFrom,
6075
+ conversationId: aiConversationId,
6076
+ reportType,
6077
+ screenshots,
6078
+ initialText: selfReportPrefill,
6079
+ onClose: () => setSelfReportFrom(null)
6080
+ }
6081
+ ),
6082
+ isOpen && sheetUp && /* @__PURE__ */ jsx4(
5498
6083
  AssistSheet,
5499
6084
  {
5500
6085
  assist,
5501
- theme: {
5502
- bg: t2.bg,
5503
- bgSecondary: t2.bgSecondary,
5504
- border: t2.border,
5505
- text: t2.text,
5506
- textMuted: t2.textMuted,
5507
- inputBg: t2.inputBg,
5508
- inputBorder: t2.inputBorder,
5509
- accent: t2.accent,
5510
- accentText: t2.accentText
5511
- },
6086
+ theme: layerTheme,
5512
6087
  screenshots,
5513
6088
  pageShot,
5514
6089
  onAddImages: addFiles,
@@ -5550,6 +6125,10 @@ function ReportDialog({
5550
6125
  isSubmitting,
5551
6126
  submitted,
5552
6127
  onSend: () => void handleSubmit(),
6128
+ onReportGlitchgrabProblem: reportGlitchgrabProblem ? (prefill) => {
6129
+ setSelfReportPrefill(prefill != null ? prefill : "");
6130
+ setSelfReportFrom("assist");
6131
+ } : void 0,
5553
6132
  onDegrade: (message) => {
5554
6133
  setAssistOpen(false);
5555
6134
  setAssistUsed(true);
@@ -5596,7 +6175,7 @@ function getTypeIcon(type, color, size = 24) {
5596
6175
  };
5597
6176
  switch (type) {
5598
6177
  case "RATING":
5599
- return /* @__PURE__ */ jsx3("svg", { ...props, children: /* @__PURE__ */ jsx3(
6178
+ return /* @__PURE__ */ jsx4("svg", { ...props, children: /* @__PURE__ */ jsx4(
5600
6179
  "path",
5601
6180
  {
5602
6181
  d: "M12 3l2.6 5.3 5.9.9-4.3 4.1 1 5.8L12 16.4 6.8 19.1l1-5.8L3.5 9.2l5.9-.9L12 3z",
@@ -5606,7 +6185,7 @@ function getTypeIcon(type, color, size = 24) {
5606
6185
  }
5607
6186
  ) });
5608
6187
  case "BUG":
5609
- return /* @__PURE__ */ jsx3("svg", { ...props, children: /* @__PURE__ */ jsx3(
6188
+ return /* @__PURE__ */ jsx4("svg", { ...props, children: /* @__PURE__ */ jsx4(
5610
6189
  "path",
5611
6190
  {
5612
6191
  d: "M8 2L6.5 3.5M16 2L17.5 3.5M3 9H7M17 9H21M12 2a5 5 0 015 5v4a5 5 0 01-10 0V7a5 5 0 015-5zM7 16l-2 3M17 16l2 3",
@@ -5616,7 +6195,7 @@ function getTypeIcon(type, color, size = 24) {
5616
6195
  }
5617
6196
  ) });
5618
6197
  case "FEATURE_REQUEST":
5619
- return /* @__PURE__ */ jsx3("svg", { ...props, children: /* @__PURE__ */ jsx3(
6198
+ return /* @__PURE__ */ jsx4("svg", { ...props, children: /* @__PURE__ */ jsx4(
5620
6199
  "path",
5621
6200
  {
5622
6201
  d: "M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2z",
@@ -5626,8 +6205,8 @@ function getTypeIcon(type, color, size = 24) {
5626
6205
  }
5627
6206
  ) });
5628
6207
  case "UI_IMPROVEMENT":
5629
- return /* @__PURE__ */ jsxs3("svg", { ...props, children: [
5630
- /* @__PURE__ */ jsx3(
6208
+ return /* @__PURE__ */ jsxs4("svg", { ...props, children: [
6209
+ /* @__PURE__ */ jsx4(
5631
6210
  "rect",
5632
6211
  {
5633
6212
  x: "3",
@@ -5639,7 +6218,7 @@ function getTypeIcon(type, color, size = 24) {
5639
6218
  strokeWidth: "1.5"
5640
6219
  }
5641
6220
  ),
5642
- /* @__PURE__ */ jsx3(
6221
+ /* @__PURE__ */ jsx4(
5643
6222
  "path",
5644
6223
  {
5645
6224
  d: "M3 9h18M9 21V9",
@@ -5650,7 +6229,7 @@ function getTypeIcon(type, color, size = 24) {
5650
6229
  )
5651
6230
  ] });
5652
6231
  case "PERFORMANCE":
5653
- return /* @__PURE__ */ jsx3("svg", { ...props, children: /* @__PURE__ */ jsx3(
6232
+ return /* @__PURE__ */ jsx4("svg", { ...props, children: /* @__PURE__ */ jsx4(
5654
6233
  "path",
5655
6234
  {
5656
6235
  d: "M12 21a9 9 0 100-18 9 9 0 000 18zM12 12l4-4M12 7v.01",
@@ -5661,7 +6240,7 @@ function getTypeIcon(type, color, size = 24) {
5661
6240
  }
5662
6241
  ) });
5663
6242
  case "SECURITY":
5664
- return /* @__PURE__ */ jsx3("svg", { ...props, children: /* @__PURE__ */ jsx3(
6243
+ return /* @__PURE__ */ jsx4("svg", { ...props, children: /* @__PURE__ */ jsx4(
5665
6244
  "path",
5666
6245
  {
5667
6246
  d: "M12 3l7 3v5c0 4.5-3 8.5-7 10-4-1.5-7-5.5-7-10V6l7-3z",
@@ -5671,9 +6250,9 @@ function getTypeIcon(type, color, size = 24) {
5671
6250
  }
5672
6251
  ) });
5673
6252
  case "QUESTION":
5674
- return /* @__PURE__ */ jsxs3("svg", { ...props, children: [
5675
- /* @__PURE__ */ jsx3("circle", { cx: "12", cy: "12", r: "10", stroke: color, strokeWidth: "1.5" }),
5676
- /* @__PURE__ */ jsx3(
6253
+ return /* @__PURE__ */ jsxs4("svg", { ...props, children: [
6254
+ /* @__PURE__ */ jsx4("circle", { cx: "12", cy: "12", r: "10", stroke: color, strokeWidth: "1.5" }),
6255
+ /* @__PURE__ */ jsx4(
5677
6256
  "path",
5678
6257
  {
5679
6258
  d: "M9.09 9a3 3 0 015.83 1c0 2-3 3-3 3M12 17h.01",
@@ -5685,7 +6264,7 @@ function getTypeIcon(type, color, size = 24) {
5685
6264
  )
5686
6265
  ] });
5687
6266
  case "OTHER":
5688
- return /* @__PURE__ */ jsx3("svg", { ...props, children: /* @__PURE__ */ jsx3(
6267
+ return /* @__PURE__ */ jsx4("svg", { ...props, children: /* @__PURE__ */ jsx4(
5689
6268
  "path",
5690
6269
  {
5691
6270
  d: "M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2v10z",
@@ -5698,8 +6277,8 @@ function getTypeIcon(type, color, size = 24) {
5698
6277
  }
5699
6278
 
5700
6279
  // src/booking-dialog.tsx
5701
- import { useCallback, useEffect as useEffect4, useMemo, useState as useState4 } from "react";
5702
- import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
6280
+ import { useCallback, useEffect as useEffect5, useMemo as useMemo2, useState as useState5 } from "react";
6281
+ import { Fragment as Fragment4, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
5703
6282
  var t = {
5704
6283
  bg: "#141414",
5705
6284
  surface: "#1c1c1c",
@@ -5736,24 +6315,24 @@ function BookingDialog({
5736
6315
  onClose
5737
6316
  }) {
5738
6317
  var _a;
5739
- const [step, setStep] = useState4("slots");
5740
- const [slots, setSlots] = useState4(null);
5741
- const [heading, setHeading] = useState4({
6318
+ const [step, setStep] = useState5("slots");
6319
+ const [slots, setSlots] = useState5(null);
6320
+ const [heading, setHeading] = useState5({
5742
6321
  title: "Book a demo",
5743
6322
  description: null
5744
6323
  });
5745
- const [whatsappUrl, setWhatsappUrl] = useState4(null);
5746
- const [selected, setSelected] = useState4(null);
5747
- const [name, setName] = useState4("");
5748
- const [email, setEmail] = useState4("");
5749
- const [phone, setPhone] = useState4("");
5750
- const [note, setNote] = useState4("");
5751
- const [code, setCode] = useState4("");
5752
- const [bookingId, setBookingId] = useState4(null);
5753
- const [meetUrl, setMeetUrl] = useState4(null);
5754
- const [busy, setBusy] = useState4(false);
5755
- const [error, setError] = useState4(null);
5756
- const headers = useMemo(
6324
+ const [whatsappUrl, setWhatsappUrl] = useState5(null);
6325
+ const [selected, setSelected] = useState5(null);
6326
+ const [name, setName] = useState5("");
6327
+ const [email, setEmail] = useState5("");
6328
+ const [phone, setPhone] = useState5("");
6329
+ const [note, setNote] = useState5("");
6330
+ const [code, setCode] = useState5("");
6331
+ const [bookingId, setBookingId] = useState5(null);
6332
+ const [meetUrl, setMeetUrl] = useState5(null);
6333
+ const [busy, setBusy] = useState5(false);
6334
+ const [error, setError] = useState5(null);
6335
+ const headers = useMemo2(
5757
6336
  () => ({ Authorization: `Bearer ${token}`, "Content-Type": "application/json" }),
5758
6337
  [token]
5759
6338
  );
@@ -5782,7 +6361,7 @@ function BookingDialog({
5782
6361
  setSlots([]);
5783
6362
  }
5784
6363
  }, [baseUrl, headers]);
5785
- useEffect4(() => {
6364
+ useEffect5(() => {
5786
6365
  if (!open) return;
5787
6366
  setStep("slots");
5788
6367
  setSelected(null);
@@ -5791,7 +6370,7 @@ function BookingDialog({
5791
6370
  setError(null);
5792
6371
  void loadSlots();
5793
6372
  }, [open, loadSlots]);
5794
- useEffect4(() => {
6373
+ useEffect5(() => {
5795
6374
  if (!open) return;
5796
6375
  const onKey = (e) => {
5797
6376
  if (e.key === "Escape") onClose();
@@ -5861,7 +6440,7 @@ function BookingDialog({
5861
6440
  }
5862
6441
  }
5863
6442
  const canSubmitDetails = name.trim() && email.includes("@") && phone.replace(/\D/g, "").length >= 8;
5864
- return /* @__PURE__ */ jsx4(
6443
+ return /* @__PURE__ */ jsx5(
5865
6444
  "div",
5866
6445
  {
5867
6446
  onClick: (e) => {
@@ -5878,7 +6457,7 @@ function BookingDialog({
5878
6457
  padding: 16,
5879
6458
  fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
5880
6459
  },
5881
- children: /* @__PURE__ */ jsxs4(
6460
+ children: /* @__PURE__ */ jsxs5(
5882
6461
  "div",
5883
6462
  {
5884
6463
  role: "dialog",
@@ -5896,7 +6475,7 @@ function BookingDialog({
5896
6475
  overflow: "hidden"
5897
6476
  },
5898
6477
  children: [
5899
- /* @__PURE__ */ jsxs4(
6478
+ /* @__PURE__ */ jsxs5(
5900
6479
  "div",
5901
6480
  {
5902
6481
  style: {
@@ -5908,11 +6487,11 @@ function BookingDialog({
5908
6487
  gap: 12
5909
6488
  },
5910
6489
  children: [
5911
- /* @__PURE__ */ jsxs4("div", { children: [
5912
- /* @__PURE__ */ jsx4("div", { style: { fontSize: 15, fontWeight: 600 }, children: heading.title }),
5913
- heading.description && /* @__PURE__ */ jsx4("div", { style: { fontSize: 12, color: t.muted, marginTop: 2 }, children: heading.description })
6490
+ /* @__PURE__ */ jsxs5("div", { children: [
6491
+ /* @__PURE__ */ jsx5("div", { style: { fontSize: 15, fontWeight: 600 }, children: heading.title }),
6492
+ heading.description && /* @__PURE__ */ jsx5("div", { style: { fontSize: 12, color: t.muted, marginTop: 2 }, children: heading.description })
5914
6493
  ] }),
5915
- /* @__PURE__ */ jsx4(
6494
+ /* @__PURE__ */ jsx5(
5916
6495
  "button",
5917
6496
  {
5918
6497
  onClick: onClose,
@@ -5924,10 +6503,10 @@ function BookingDialog({
5924
6503
  ]
5925
6504
  }
5926
6505
  ),
5927
- /* @__PURE__ */ jsxs4("div", { style: { padding: 18, overflowY: "auto", flex: "1 1 auto" }, children: [
5928
- error && /* @__PURE__ */ jsx4("div", { style: { color: t.danger, fontSize: 12, marginBottom: 12, lineHeight: 1.5 }, children: error }),
5929
- step === "slots" && /* @__PURE__ */ jsxs4(Fragment3, { children: [
5930
- whatsappUrl && /* @__PURE__ */ jsxs4(
6506
+ /* @__PURE__ */ jsxs5("div", { style: { padding: 18, overflowY: "auto", flex: "1 1 auto" }, children: [
6507
+ error && /* @__PURE__ */ jsx5("div", { style: { color: t.danger, fontSize: 12, marginBottom: 12, lineHeight: 1.5 }, children: error }),
6508
+ step === "slots" && /* @__PURE__ */ jsxs5(Fragment4, { children: [
6509
+ whatsappUrl && /* @__PURE__ */ jsxs5(
5931
6510
  "a",
5932
6511
  {
5933
6512
  href: whatsappUrl,
@@ -5946,15 +6525,15 @@ function BookingDialog({
5946
6525
  },
5947
6526
  children: [
5948
6527
  "\u{1F4AC} Rather book on WhatsApp?",
5949
- /* @__PURE__ */ jsx4("span", { style: { display: "block", fontSize: 11, color: t.muted, marginTop: 2 }, children: "We'll ask the same questions in chat." })
6528
+ /* @__PURE__ */ jsx5("span", { style: { display: "block", fontSize: 11, color: t.muted, marginTop: 2 }, children: "We'll ask the same questions in chat." })
5950
6529
  ]
5951
6530
  }
5952
6531
  ),
5953
- slots === null && /* @__PURE__ */ jsx4("div", { style: { color: t.muted, fontSize: 13 }, children: "Finding times\u2026" }),
5954
- (slots == null ? void 0 : slots.length) === 0 && !error && /* @__PURE__ */ jsx4("div", { style: { color: t.muted, fontSize: 13 }, children: "No times available right now." }),
5955
- [...byDay.entries()].map(([day, daySlots]) => /* @__PURE__ */ jsxs4("div", { style: { marginBottom: 18 }, children: [
5956
- /* @__PURE__ */ jsx4("div", { style: { fontSize: 11, color: t.muted, marginBottom: 8, textTransform: "uppercase", letterSpacing: ".6px" }, children: formatDay(daySlots[0].startsAt) }),
5957
- /* @__PURE__ */ jsx4("div", { style: { display: "flex", flexWrap: "wrap", gap: 8 }, children: daySlots.map((slot) => /* @__PURE__ */ jsx4(
6532
+ slots === null && /* @__PURE__ */ jsx5("div", { style: { color: t.muted, fontSize: 13 }, children: "Finding times\u2026" }),
6533
+ (slots == null ? void 0 : slots.length) === 0 && !error && /* @__PURE__ */ jsx5("div", { style: { color: t.muted, fontSize: 13 }, children: "No times available right now." }),
6534
+ [...byDay.entries()].map(([day, daySlots]) => /* @__PURE__ */ jsxs5("div", { style: { marginBottom: 18 }, children: [
6535
+ /* @__PURE__ */ jsx5("div", { style: { fontSize: 11, color: t.muted, marginBottom: 8, textTransform: "uppercase", letterSpacing: ".6px" }, children: formatDay(daySlots[0].startsAt) }),
6536
+ /* @__PURE__ */ jsx5("div", { style: { display: "flex", flexWrap: "wrap", gap: 8 }, children: daySlots.map((slot) => /* @__PURE__ */ jsx5(
5958
6537
  "button",
5959
6538
  {
5960
6539
  onClick: () => {
@@ -5976,13 +6555,13 @@ function BookingDialog({
5976
6555
  )) })
5977
6556
  ] }, day))
5978
6557
  ] }),
5979
- step === "details" && selected && /* @__PURE__ */ jsxs4("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: [
5980
- /* @__PURE__ */ jsxs4("div", { style: { fontSize: 13, color: t.muted }, children: [
6558
+ step === "details" && selected && /* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: [
6559
+ /* @__PURE__ */ jsxs5("div", { style: { fontSize: 13, color: t.muted }, children: [
5981
6560
  formatDay(selected.startsAt),
5982
6561
  " \xB7 ",
5983
6562
  formatTime(selected.startsAt),
5984
6563
  " \xB7 ",
5985
- /* @__PURE__ */ jsx4(
6564
+ /* @__PURE__ */ jsx5(
5986
6565
  "button",
5987
6566
  {
5988
6567
  onClick: () => setStep("slots"),
@@ -5991,9 +6570,9 @@ function BookingDialog({
5991
6570
  }
5992
6571
  )
5993
6572
  ] }),
5994
- /* @__PURE__ */ jsx4(Field, { label: "Your name", value: name, onChange: setName }),
5995
- /* @__PURE__ */ jsx4(Field, { label: "Email", value: email, onChange: setEmail, type: "email" }),
5996
- /* @__PURE__ */ jsx4(
6573
+ /* @__PURE__ */ jsx5(Field, { label: "Your name", value: name, onChange: setName }),
6574
+ /* @__PURE__ */ jsx5(Field, { label: "Email", value: email, onChange: setEmail, type: "email" }),
6575
+ /* @__PURE__ */ jsx5(
5997
6576
  Field,
5998
6577
  {
5999
6578
  label: "Mobile number",
@@ -6003,8 +6582,8 @@ function BookingDialog({
6003
6582
  hint: "We send a code here to confirm, then a reminder before the call."
6004
6583
  }
6005
6584
  ),
6006
- /* @__PURE__ */ jsx4(Field, { label: "Anything we should know? (optional)", value: note, onChange: setNote }),
6007
- /* @__PURE__ */ jsx4(
6585
+ /* @__PURE__ */ jsx5(Field, { label: "Anything we should know? (optional)", value: note, onChange: setNote }),
6586
+ /* @__PURE__ */ jsx5(
6008
6587
  "button",
6009
6588
  {
6010
6589
  onClick: startBooking,
@@ -6014,10 +6593,10 @@ function BookingDialog({
6014
6593
  }
6015
6594
  )
6016
6595
  ] }),
6017
- step === "code" && /* @__PURE__ */ jsxs4("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: [
6018
- /* @__PURE__ */ jsx4("div", { style: { fontSize: 13, color: t.muted, lineHeight: 1.5 }, children: "We sent a 4-digit code to your phone. Your slot is held for 10 minutes." }),
6019
- /* @__PURE__ */ jsx4(Field, { label: "Code", value: code, onChange: setCode }),
6020
- /* @__PURE__ */ jsx4(
6596
+ step === "code" && /* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: [
6597
+ /* @__PURE__ */ jsx5("div", { style: { fontSize: 13, color: t.muted, lineHeight: 1.5 }, children: "We sent a 4-digit code to your phone. Your slot is held for 10 minutes." }),
6598
+ /* @__PURE__ */ jsx5(Field, { label: "Code", value: code, onChange: setCode }),
6599
+ /* @__PURE__ */ jsx5(
6021
6600
  "button",
6022
6601
  {
6023
6602
  onClick: confirmBooking,
@@ -6027,15 +6606,15 @@ function BookingDialog({
6027
6606
  }
6028
6607
  )
6029
6608
  ] }),
6030
- step === "done" && /* @__PURE__ */ jsxs4("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: [
6031
- /* @__PURE__ */ jsx4("div", { style: { fontSize: 15, fontWeight: 600 }, children: "You're booked." }),
6032
- /* @__PURE__ */ jsxs4("div", { style: { fontSize: 13, color: t.muted, lineHeight: 1.6 }, children: [
6609
+ step === "done" && /* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: [
6610
+ /* @__PURE__ */ jsx5("div", { style: { fontSize: 15, fontWeight: 600 }, children: "You're booked." }),
6611
+ /* @__PURE__ */ jsxs5("div", { style: { fontSize: 13, color: t.muted, lineHeight: 1.6 }, children: [
6033
6612
  selected && `${formatDay(selected.startsAt)} at ${formatTime(selected.startsAt)}. `,
6034
6613
  "A calendar invite is on its way to ",
6035
6614
  email,
6036
6615
  ", and we'll send a WhatsApp reminder before the call."
6037
6616
  ] }),
6038
- meetUrl && /* @__PURE__ */ jsx4("a", { href: meetUrl, target: "_blank", rel: "noreferrer", style: { ...primaryStyle(false), textAlign: "center", textDecoration: "none" }, children: "Open the meeting link" })
6617
+ meetUrl && /* @__PURE__ */ jsx5("a", { href: meetUrl, target: "_blank", rel: "noreferrer", style: { ...primaryStyle(false), textAlign: "center", textDecoration: "none" }, children: "Open the meeting link" })
6039
6618
  ] })
6040
6619
  ] })
6041
6620
  ]
@@ -6064,9 +6643,9 @@ function Field({
6064
6643
  type = "text",
6065
6644
  hint
6066
6645
  }) {
6067
- return /* @__PURE__ */ jsxs4("label", { style: { display: "block", fontSize: 11, color: t.muted }, children: [
6646
+ return /* @__PURE__ */ jsxs5("label", { style: { display: "block", fontSize: 11, color: t.muted }, children: [
6068
6647
  label,
6069
- /* @__PURE__ */ jsx4(
6648
+ /* @__PURE__ */ jsx5(
6070
6649
  "input",
6071
6650
  {
6072
6651
  type,
@@ -6087,7 +6666,7 @@ function Field({
6087
6666
  }
6088
6667
  }
6089
6668
  ),
6090
- hint && /* @__PURE__ */ jsx4("div", { style: { marginTop: 4, fontSize: 10, color: t.muted }, children: hint })
6669
+ hint && /* @__PURE__ */ jsx5("div", { style: { marginTop: 4, fontSize: 10, color: t.muted }, children: hint })
6091
6670
  ] });
6092
6671
  }
6093
6672
 
@@ -6228,7 +6807,7 @@ function matchesShortcut(e) {
6228
6807
  }
6229
6808
 
6230
6809
  // src/provider.tsx
6231
- import { Fragment as Fragment4, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
6810
+ import { Fragment as Fragment5, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
6232
6811
  var DEFAULT_BASE_URL2 = "https://glitchgrab.dev";
6233
6812
  var GlitchgrabContext = createContext(null);
6234
6813
  function useGlitchgrab() {
@@ -6240,7 +6819,7 @@ function useGlitchgrab() {
6240
6819
  }
6241
6820
  function GlitchgrabProviderInner({
6242
6821
  token,
6243
- session,
6822
+ session: sessionProp,
6244
6823
  baseUrl,
6245
6824
  onError,
6246
6825
  onReportSent,
@@ -6255,7 +6834,16 @@ function GlitchgrabProviderInner({
6255
6834
  context: appContext2,
6256
6835
  responseBodyOrigins: responseBodyOrigins2
6257
6836
  }) {
6258
- const visitedPagesRef = useRef4([]);
6837
+ const visitedPagesRef = useRef5([]);
6838
+ const sessionKey = sessionProp ? [
6839
+ sessionProp.userId,
6840
+ sessionProp.name,
6841
+ sessionProp.email,
6842
+ sessionProp.phone,
6843
+ sessionProp.avatarUrl,
6844
+ sessionProp.image
6845
+ ].map((v) => v == null ? "" : String(v)).join("\0") : "";
6846
+ const session = useMemo3(() => sessionProp, [sessionKey]);
6259
6847
  setRelease(release2);
6260
6848
  if (appContext2) setContexts(appContext2);
6261
6849
  registerCaptureConfig({
@@ -6267,12 +6855,12 @@ function GlitchgrabProviderInner({
6267
6855
  onError,
6268
6856
  onReportSent
6269
6857
  });
6270
- useEffect5(() => {
6858
+ useEffect6(() => {
6271
6859
  if (enableBreadcrumbs) {
6272
6860
  initBreadcrumbs(maxBreadcrumbs2, { responseBodyOrigins: responseBodyOrigins2 });
6273
6861
  }
6274
6862
  }, [enableBreadcrumbs, maxBreadcrumbs2, responseBodyOrigins2 == null ? void 0 : responseBodyOrigins2.join(",")]);
6275
- useEffect5(() => {
6863
+ useEffect6(() => {
6276
6864
  try {
6277
6865
  if (typeof window === "undefined") return;
6278
6866
  const trackPage = () => {
@@ -6309,7 +6897,7 @@ function GlitchgrabProviderInner({
6309
6897
  } catch (e) {
6310
6898
  }
6311
6899
  }, []);
6312
- useEffect5(() => {
6900
+ useEffect6(() => {
6313
6901
  try {
6314
6902
  if (typeof window === "undefined") return;
6315
6903
  if (process.env.NODE_ENV === "development") return;
@@ -6474,6 +7062,40 @@ function GlitchgrabProviderInner({
6474
7062
  (description, metadata) => report("BUG", description, metadata),
6475
7063
  [report]
6476
7064
  );
7065
+ const reportGlitchgrabProblem = useCallback2(
7066
+ async (params) => {
7067
+ var _a, _b;
7068
+ try {
7069
+ const context = captureContext(visitedPagesRef.current);
7070
+ const body = JSON.stringify({
7071
+ ...params,
7072
+ pageUrl: context.url,
7073
+ userAgent: context.userAgent,
7074
+ deviceInfo: (_a = context.deviceInfo) != null ? _a : void 0,
7075
+ visitedPages: context.visitedPages,
7076
+ breadcrumbs: context.breadcrumbs,
7077
+ ...(session == null ? void 0 : session.userId) ? { reporterId: session.userId } : {},
7078
+ ...(session == null ? void 0 : session.name) ? { reporterName: String(session.name) } : {},
7079
+ ...(session == null ? void 0 : session.email) ? { reporterEmail: String(session.email) } : {}
7080
+ });
7081
+ const res = await fetch(`${baseUrl}/api/v1/sdk/glitchgrab-report`, {
7082
+ method: "POST",
7083
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
7084
+ body,
7085
+ // keepalive caps the body at 64KB — screenshots blow past it.
7086
+ ...body.length < 6e4 ? { keepalive: true } : {}
7087
+ });
7088
+ const json = await res.json().catch(() => null);
7089
+ if (!res.ok || !(json == null ? void 0 : json.success)) {
7090
+ return { success: false, message: (_b = json == null ? void 0 : json.error) != null ? _b : "Couldn't send it" };
7091
+ }
7092
+ return { success: true, ...json.data };
7093
+ } catch (e) {
7094
+ return null;
7095
+ }
7096
+ },
7097
+ [token, baseUrl, session]
7098
+ );
6477
7099
  const feedback = useCallback2(
6478
7100
  async (rating, message, metadata) => {
6479
7101
  try {
@@ -6584,7 +7206,7 @@ function GlitchgrabProviderInner({
6584
7206
  window.dispatchEvent(new CustomEvent("glitchgrab:open-report", { detail: options }));
6585
7207
  }
6586
7208
  }, []);
6587
- useEffect5(() => {
7209
+ useEffect6(() => {
6588
7210
  try {
6589
7211
  if (typeof document === "undefined") return;
6590
7212
  document.documentElement.setAttribute("data-glitchgrab-sdk", "1");
@@ -6592,11 +7214,12 @@ function GlitchgrabProviderInner({
6592
7214
  } catch (e) {
6593
7215
  }
6594
7216
  }, []);
6595
- const [projectName, setProjectName] = useState5(null);
6596
- const [aiAssist, setAiAssist] = useState5(false);
6597
- const [bookingOpen, setBookingOpen] = useState5(false);
7217
+ const [projectName, setProjectName] = useState6(null);
7218
+ const [aiAssist, setAiAssist] = useState6(false);
7219
+ const [glitchgrabReport, setGlitchgrabReport] = useState6(false);
7220
+ const [bookingOpen, setBookingOpen] = useState6(false);
6598
7221
  const openBookingDialog = useCallback2(() => setBookingOpen(true), []);
6599
- useEffect5(() => {
7222
+ useEffect6(() => {
6600
7223
  let cancelled = false;
6601
7224
  fetch(`${baseUrl}/api/v1/sdk/project`, {
6602
7225
  headers: { Authorization: `Bearer ${token}` }
@@ -6605,13 +7228,14 @@ function GlitchgrabProviderInner({
6605
7228
  if (cancelled || !(json == null ? void 0 : json.success) || !((_a = json.data) == null ? void 0 : _a.name)) return;
6606
7229
  setProjectName(json.data.name);
6607
7230
  setAiAssist(json.data.aiAssist === true);
7231
+ setGlitchgrabReport(json.data.glitchgrabReport === true);
6608
7232
  }).catch(() => {
6609
7233
  });
6610
7234
  return () => {
6611
7235
  cancelled = true;
6612
7236
  };
6613
7237
  }, [baseUrl, token]);
6614
- useEffect5(() => {
7238
+ useEffect6(() => {
6615
7239
  try {
6616
7240
  if (typeof window === "undefined") return;
6617
7241
  const handleKeyDown = (e) => {
@@ -6625,7 +7249,7 @@ function GlitchgrabProviderInner({
6625
7249
  } catch (e) {
6626
7250
  }
6627
7251
  }, [openReportDialog]);
6628
- const reporter = useMemo2(() => {
7252
+ const reporter = useMemo3(() => {
6629
7253
  var _a;
6630
7254
  if (!session) return null;
6631
7255
  const avatar = (_a = session.avatarUrl) != null ? _a : session.image;
@@ -6635,11 +7259,11 @@ function GlitchgrabProviderInner({
6635
7259
  avatarUrl: typeof avatar === "string" ? avatar : null
6636
7260
  };
6637
7261
  }, [session]);
6638
- const [shortcutLabel, setShortcutLabel] = useState5(GLITCHGRAB_SHORTCUT2);
6639
- useEffect5(() => {
7262
+ const [shortcutLabel, setShortcutLabel] = useState6(GLITCHGRAB_SHORTCUT2);
7263
+ useEffect6(() => {
6640
7264
  setShortcutLabel(getShortcutLabel2());
6641
7265
  }, []);
6642
- return /* @__PURE__ */ jsxs5(
7266
+ return /* @__PURE__ */ jsxs6(
6643
7267
  GlitchgrabContext.Provider,
6644
7268
  {
6645
7269
  value: {
@@ -6659,7 +7283,7 @@ function GlitchgrabProviderInner({
6659
7283
  shortcutLabel
6660
7284
  },
6661
7285
  children: [
6662
- /* @__PURE__ */ jsx5(
7286
+ /* @__PURE__ */ jsx6(
6663
7287
  GlitchgrabErrorBoundary,
6664
7288
  {
6665
7289
  token,
@@ -6671,7 +7295,7 @@ function GlitchgrabProviderInner({
6671
7295
  children
6672
7296
  }
6673
7297
  ),
6674
- /* @__PURE__ */ jsx5(
7298
+ /* @__PURE__ */ jsx6(
6675
7299
  BookingDialog,
6676
7300
  {
6677
7301
  token,
@@ -6680,20 +7304,21 @@ function GlitchgrabProviderInner({
6680
7304
  onClose: () => setBookingOpen(false)
6681
7305
  }
6682
7306
  ),
6683
- /* @__PURE__ */ jsx5(
7307
+ /* @__PURE__ */ jsx6(
6684
7308
  ReportDialog,
6685
7309
  {
6686
7310
  report,
6687
7311
  sendFeedback: feedback,
6688
7312
  enhanceText: enhance,
6689
7313
  assist: aiAssist ? assist : void 0,
7314
+ reportGlitchgrabProblem: glitchgrabReport ? reportGlitchgrabProblem : void 0,
6690
7315
  transcribeAudio: transcribe,
6691
7316
  types,
6692
7317
  showSeverity,
6693
7318
  reporter,
6694
- headerSlot: projectName ? /* @__PURE__ */ jsxs5("div", { style: { fontSize: 11, color: "#9aa0a6" }, children: [
7319
+ headerSlot: projectName ? /* @__PURE__ */ jsxs6("div", { style: { fontSize: 11, color: "#9aa0a6" }, children: [
6695
7320
  "Reporting to ",
6696
- /* @__PURE__ */ jsx5("strong", { style: { color: "#e5e5e5" }, children: projectName })
7321
+ /* @__PURE__ */ jsx6("strong", { style: { color: "#e5e5e5" }, children: projectName })
6697
7322
  ] }) : null
6698
7323
  }
6699
7324
  )
@@ -6702,21 +7327,21 @@ function GlitchgrabProviderInner({
6702
7327
  );
6703
7328
  }
6704
7329
  function GlitchgrabProvider(props) {
6705
- if (!props.token) return /* @__PURE__ */ jsx5(Fragment4, { children: props.children });
7330
+ if (!props.token) return /* @__PURE__ */ jsx6(Fragment5, { children: props.children });
6706
7331
  const resolvedProps = {
6707
7332
  ...props,
6708
7333
  baseUrl: props.baseUrl || DEFAULT_BASE_URL2
6709
7334
  };
6710
7335
  try {
6711
- return /* @__PURE__ */ jsx5(GlitchgrabProviderInner, { ...resolvedProps });
7336
+ return /* @__PURE__ */ jsx6(GlitchgrabProviderInner, { ...resolvedProps });
6712
7337
  } catch (e) {
6713
- return /* @__PURE__ */ jsx5(Fragment4, { children: props.children });
7338
+ return /* @__PURE__ */ jsx6(Fragment5, { children: props.children });
6714
7339
  }
6715
7340
  }
6716
7341
 
6717
7342
  // src/report-button.tsx
6718
- import { useState as useState6 } from "react";
6719
- import { Fragment as Fragment5, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
7343
+ import { useState as useState7 } from "react";
7344
+ import { Fragment as Fragment6, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
6720
7345
  function useGlitchgrabSafe() {
6721
7346
  try {
6722
7347
  return useGlitchgrab();
@@ -6731,7 +7356,7 @@ function ReportButton({
6731
7356
  children
6732
7357
  }) {
6733
7358
  var _a, _b;
6734
- const [capturing, setCapturing] = useState6(false);
7359
+ const [capturing, setCapturing] = useState7(false);
6735
7360
  const glitchgrab = useGlitchgrabSafe();
6736
7361
  if (!glitchgrab) return null;
6737
7362
  const handleClick = async () => {
@@ -6740,7 +7365,7 @@ function ReportButton({
6740
7365
  setCapturing(false);
6741
7366
  };
6742
7367
  if (children) {
6743
- return /* @__PURE__ */ jsx6(Fragment5, { children: children({ onClick: handleClick, capturing }) });
7368
+ return /* @__PURE__ */ jsx7(Fragment6, { children: children({ onClick: handleClick, capturing }) });
6744
7369
  }
6745
7370
  const isTop = (_a = position == null ? void 0 : position.startsWith("top")) != null ? _a : false;
6746
7371
  const isLeft = (_b = position == null ? void 0 : position.endsWith("left")) != null ? _b : false;
@@ -6748,7 +7373,7 @@ function ReportButton({
6748
7373
  ...isLeft ? { left: "16px" } : { right: "16px" },
6749
7374
  ...isTop ? { top: "16px" } : { bottom: "16px" }
6750
7375
  };
6751
- return /* @__PURE__ */ jsxs6(
7376
+ return /* @__PURE__ */ jsxs7(
6752
7377
  "button",
6753
7378
  {
6754
7379
  type: "button",
@@ -6783,7 +7408,7 @@ function ReportButton({
6783
7408
  },
6784
7409
  "aria-label": label,
6785
7410
  children: [
6786
- /* @__PURE__ */ jsx6(
7411
+ /* @__PURE__ */ jsx7(
6787
7412
  "svg",
6788
7413
  {
6789
7414
  width: "16",
@@ -6791,7 +7416,7 @@ function ReportButton({
6791
7416
  viewBox: "0 0 16 16",
6792
7417
  fill: "none",
6793
7418
  style: { flexShrink: 0 },
6794
- children: /* @__PURE__ */ jsx6(
7419
+ children: /* @__PURE__ */ jsx7(
6795
7420
  "path",
6796
7421
  {
6797
7422
  d: "M8 1C4.134 1 1 4.134 1 8s3.134 7 7 7 7-3.134 7-7-3.134-7-7-7zm0 12.5a.75.75 0 110-1.5.75.75 0 010 1.5zm.75-3.5a.75.75 0 01-1.5 0V5a.75.75 0 011.5 0v5z",
@@ -6807,15 +7432,15 @@ function ReportButton({
6807
7432
  }
6808
7433
 
6809
7434
  // src/book-demo-button.tsx
6810
- import { Fragment as Fragment6, jsx as jsx7 } from "react/jsx-runtime";
7435
+ import { Fragment as Fragment7, jsx as jsx8 } from "react/jsx-runtime";
6811
7436
  function BookDemoButton({
6812
7437
  label = "Book a demo",
6813
7438
  className,
6814
7439
  children
6815
7440
  }) {
6816
7441
  const { openBookingDialog } = useGlitchgrab();
6817
- if (children) return /* @__PURE__ */ jsx7(Fragment6, { children: children({ onClick: openBookingDialog }) });
6818
- return /* @__PURE__ */ jsx7(
7442
+ if (children) return /* @__PURE__ */ jsx8(Fragment7, { children: children({ onClick: openBookingDialog }) });
7443
+ return /* @__PURE__ */ jsx8(
6819
7444
  "button",
6820
7445
  {
6821
7446
  type: "button",
@@ -6837,7 +7462,7 @@ function BookDemoButton({
6837
7462
  }
6838
7463
 
6839
7464
  // src/feedback-button.tsx
6840
- import { Fragment as Fragment7, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
7465
+ import { Fragment as Fragment8, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
6841
7466
  function useGlitchgrabSafe2() {
6842
7467
  try {
6843
7468
  return useGlitchgrab();
@@ -6856,7 +7481,7 @@ function FeedbackButton({
6856
7481
  if (!glitchgrab) return null;
6857
7482
  const handleClick = () => glitchgrab.openFeedbackDialog();
6858
7483
  if (children) {
6859
- return /* @__PURE__ */ jsx8(Fragment7, { children: children({ onClick: handleClick }) });
7484
+ return /* @__PURE__ */ jsx9(Fragment8, { children: children({ onClick: handleClick }) });
6860
7485
  }
6861
7486
  const isTop = (_a = position == null ? void 0 : position.startsWith("top")) != null ? _a : false;
6862
7487
  const isLeft = (_b = position == null ? void 0 : position.endsWith("left")) != null ? _b : false;
@@ -6864,7 +7489,7 @@ function FeedbackButton({
6864
7489
  ...isLeft ? { left: "16px" } : { right: "16px" },
6865
7490
  ...isTop ? { top: "16px" } : { bottom: "16px" }
6866
7491
  };
6867
- return /* @__PURE__ */ jsxs7(
7492
+ return /* @__PURE__ */ jsxs8(
6868
7493
  "button",
6869
7494
  {
6870
7495
  type: "button",
@@ -6897,7 +7522,7 @@ function FeedbackButton({
6897
7522
  },
6898
7523
  "aria-label": label,
6899
7524
  children: [
6900
- /* @__PURE__ */ jsx8(
7525
+ /* @__PURE__ */ jsx9(
6901
7526
  "svg",
6902
7527
  {
6903
7528
  width: "16",
@@ -6906,7 +7531,7 @@ function FeedbackButton({
6906
7531
  fill: "none",
6907
7532
  style: { flexShrink: 0 },
6908
7533
  "aria-hidden": "true",
6909
- children: /* @__PURE__ */ jsx8(
7534
+ children: /* @__PURE__ */ jsx9(
6910
7535
  "path",
6911
7536
  {
6912
7537
  d: "M12 2.5l2.9 5.9 6.5.9-4.7 4.6 1.1 6.5L12 17.4l-5.8 3 1.1-6.5L2.6 9.3l6.5-.9L12 2.5z",
@@ -6922,17 +7547,17 @@ function FeedbackButton({
6922
7547
  }
6923
7548
 
6924
7549
  // src/use-reports.ts
6925
- import { useState as useState7, useEffect as useEffect6, useCallback as useCallback3 } from "react";
7550
+ import { useState as useState8, useEffect as useEffect7, useCallback as useCallback3 } from "react";
6926
7551
  var BASE_URL = "https://glitchgrab.dev";
6927
7552
  function useGlitchgrabReports({
6928
7553
  token,
6929
7554
  userId,
6930
7555
  limit = 100
6931
7556
  }) {
6932
- const [reports, setReports] = useState7([]);
6933
- const [isLoading, setIsLoading] = useState7(true);
6934
- const [isFetching, setIsFetching] = useState7(false);
6935
- const [error, setError] = useState7(null);
7557
+ const [reports, setReports] = useState8([]);
7558
+ const [isLoading, setIsLoading] = useState8(true);
7559
+ const [isFetching, setIsFetching] = useState8(false);
7560
+ const [error, setError] = useState8(null);
6936
7561
  const fetchReports = useCallback3(async () => {
6937
7562
  var _a, _b;
6938
7563
  if (!token || !userId) {
@@ -6959,7 +7584,7 @@ function useGlitchgrabReports({
6959
7584
  setIsFetching(false);
6960
7585
  }
6961
7586
  }, [token, userId, limit]);
6962
- useEffect6(() => {
7587
+ useEffect7(() => {
6963
7588
  fetchReports();
6964
7589
  }, [fetchReports]);
6965
7590
  return { reports, isLoading, isFetching, error, refetch: fetchReports };
@@ -6996,8 +7621,8 @@ function useGlitchgrabActions({
6996
7621
  onSuccess,
6997
7622
  onError
6998
7623
  }) {
6999
- const [isPending, setIsPending] = useState7(false);
7000
- const [error, setError] = useState7(null);
7624
+ const [isPending, setIsPending] = useState8(false);
7625
+ const [error, setError] = useState8(null);
7001
7626
  const run = useCallback3(
7002
7627
  async (reportId, body) => {
7003
7628
  setIsPending(true);
@@ -7028,7 +7653,7 @@ function useGlitchgrabActions({
7028
7653
  }
7029
7654
 
7030
7655
  // src/use-feedback.ts
7031
- import { useState as useState8, useEffect as useEffect7, useCallback as useCallback4 } from "react";
7656
+ import { useState as useState9, useEffect as useEffect8, useCallback as useCallback4 } from "react";
7032
7657
  var DEFAULT_BASE_URL3 = "https://glitchgrab.dev";
7033
7658
  function buildUrl({
7034
7659
  approvedOnly,
@@ -7054,10 +7679,10 @@ async function fetchGlitchgrabFeedback(query) {
7054
7679
  }
7055
7680
  function useGlitchgrabFeedback(query) {
7056
7681
  const { token, approvedOnly, userId, minRating, limit, baseUrl } = query;
7057
- const [feedback, setFeedback] = useState8([]);
7058
- const [isLoading, setIsLoading] = useState8(true);
7059
- const [isFetching, setIsFetching] = useState8(false);
7060
- const [error, setError] = useState8(null);
7682
+ const [feedback, setFeedback] = useState9([]);
7683
+ const [isLoading, setIsLoading] = useState9(true);
7684
+ const [isFetching, setIsFetching] = useState9(false);
7685
+ const [error, setError] = useState9(null);
7061
7686
  const load = useCallback4(async () => {
7062
7687
  if (!token) {
7063
7688
  setIsLoading(false);
@@ -7082,7 +7707,7 @@ function useGlitchgrabFeedback(query) {
7082
7707
  setIsFetching(false);
7083
7708
  }
7084
7709
  }, [token, approvedOnly, userId, minRating, limit, baseUrl]);
7085
- useEffect7(() => {
7710
+ useEffect8(() => {
7086
7711
  load();
7087
7712
  }, [load]);
7088
7713
  return { feedback, isLoading, isFetching, error, refetch: load };