glitchgrab 1.34.0 → 1.35.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 useRef3,
8
- useEffect as useEffect4,
7
+ useRef as useRef4,
8
+ useEffect as useEffect5,
9
9
  useCallback as useCallback2,
10
10
  useMemo as useMemo2,
11
- useState as useState4
11
+ useState as useState5
12
12
  } from "react";
13
13
 
14
14
  // src/error-boundary.tsx
@@ -587,6 +587,43 @@ async function enhanceText(text, token, baseUrl, screenshot, context) {
587
587
  return text;
588
588
  }
589
589
  }
590
+ async function assistTurn(params, token, baseUrl) {
591
+ var _a, _b, _c, _d, _e, _f, _g;
592
+ const offline = {
593
+ conversationId: null,
594
+ question: null,
595
+ report: null,
596
+ degraded: "The assistant is unavailable \u2014 write your report below and send it as normal."
597
+ };
598
+ try {
599
+ const url = `${baseUrl != null ? baseUrl : DEFAULT_BASE_URL}/api/v1/ai/report-chat`;
600
+ const response = await fetch(url, {
601
+ method: "POST",
602
+ headers: {
603
+ "Content-Type": "application/json",
604
+ Authorization: `Bearer ${token}`
605
+ },
606
+ body: JSON.stringify(params)
607
+ });
608
+ const envelope = await response.json().catch(() => null);
609
+ if (!response.ok || !(envelope == null ? void 0 : envelope.success)) {
610
+ return {
611
+ conversationId: null,
612
+ question: null,
613
+ report: null,
614
+ degraded: (_a = envelope == null ? void 0 : envelope.error) != null ? _a : offline.degraded
615
+ };
616
+ }
617
+ return {
618
+ conversationId: (_c = (_b = envelope.data) == null ? void 0 : _b.conversationId) != null ? _c : null,
619
+ question: (_e = (_d = envelope.data) == null ? void 0 : _d.question) != null ? _e : null,
620
+ report: (_g = (_f = envelope.data) == null ? void 0 : _f.report) != null ? _g : null,
621
+ degraded: null
622
+ };
623
+ } catch (e) {
624
+ return offline;
625
+ }
626
+ }
590
627
  async function transcribeAudio(blob, token, baseUrl) {
591
628
  var _a;
592
629
  try {
@@ -795,14 +832,17 @@ var GlitchgrabErrorBoundary = class extends React.Component {
795
832
 
796
833
  // ../report-ui/dist/index.mjs
797
834
  import {
798
- useState as useState2,
799
- useRef as useRef2,
800
- useEffect as useEffect2
835
+ useState as useState3,
836
+ useRef as useRef3,
837
+ useEffect as useEffect3
801
838
  } from "react";
802
- import { createPortal } from "react-dom";
839
+ import { createPortal as createPortal2 } from "react-dom";
803
840
  import { useEffect, useRef, useState } from "react";
804
841
  import { jsx, jsxs } from "react/jsx-runtime";
842
+ import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
843
+ import { createPortal } from "react-dom";
805
844
  import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
845
+ import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
806
846
  var MAX_SCREENSHOT_DATA_URL_LENGTH = 18e5;
807
847
  var QUALITY_LADDER = [0.92, 0.85, 0.75];
808
848
  var DOWNSCALE_FACTOR = 0.7;
@@ -1108,6 +1148,693 @@ function AnnotationCanvas({ imageSrc, onSave, onCancel }) {
1108
1148
  }
1109
1149
  );
1110
1150
  }
1151
+ var STARTERS = [
1152
+ "Something on this page is broken",
1153
+ "It did the wrong thing",
1154
+ "I wish it could\u2026"
1155
+ ];
1156
+ var NARROW_QUERY = "(max-width: 640px)";
1157
+ function useIsNarrow() {
1158
+ const [narrow, setNarrow] = useState2(false);
1159
+ useEffect2(() => {
1160
+ try {
1161
+ const mq = window.matchMedia(NARROW_QUERY);
1162
+ setNarrow(mq.matches);
1163
+ const onChange = (e) => setNarrow(e.matches);
1164
+ mq.addEventListener("change", onChange);
1165
+ return () => mq.removeEventListener("change", onChange);
1166
+ } catch (e) {
1167
+ }
1168
+ }, []);
1169
+ return narrow;
1170
+ }
1171
+ function Sparkle({ color, size = 14 }) {
1172
+ return /* @__PURE__ */ jsx2("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx2(
1173
+ "path",
1174
+ {
1175
+ 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",
1176
+ stroke: color,
1177
+ strokeWidth: "1.5",
1178
+ strokeLinejoin: "round"
1179
+ }
1180
+ ) });
1181
+ }
1182
+ function Avatar({
1183
+ who,
1184
+ theme: t2,
1185
+ initials
1186
+ }) {
1187
+ const isAi = who === "assistant";
1188
+ return /* @__PURE__ */ jsx2(
1189
+ "span",
1190
+ {
1191
+ "aria-hidden": "true",
1192
+ style: {
1193
+ flexShrink: 0,
1194
+ width: "24px",
1195
+ height: "24px",
1196
+ borderRadius: "50%",
1197
+ display: "inline-flex",
1198
+ alignItems: "center",
1199
+ justifyContent: "center",
1200
+ marginTop: "2px",
1201
+ backgroundColor: isAi ? `${t2.accent}22` : t2.bgSecondary,
1202
+ border: `1px solid ${isAi ? t2.accent : t2.inputBorder}`,
1203
+ color: isAi ? t2.accent : t2.textMuted,
1204
+ fontSize: "10px",
1205
+ fontWeight: 700
1206
+ },
1207
+ children: isAi ? /* @__PURE__ */ jsx2(Sparkle, { color: t2.accent, size: 12 }) : initials ? initials : /* @__PURE__ */ jsxs2("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: [
1208
+ /* @__PURE__ */ jsx2("circle", { cx: "12", cy: "8", r: "3.4", stroke: "currentColor", strokeWidth: "1.8" }),
1209
+ /* @__PURE__ */ jsx2(
1210
+ "path",
1211
+ {
1212
+ d: "M5 20c0-3.6 3.1-5.6 7-5.6s7 2 7 5.6",
1213
+ stroke: "currentColor",
1214
+ strokeWidth: "1.8",
1215
+ strokeLinecap: "round"
1216
+ }
1217
+ )
1218
+ ] })
1219
+ }
1220
+ );
1221
+ }
1222
+ function AssistSheet({
1223
+ assist,
1224
+ theme: t2,
1225
+ screenshot,
1226
+ attachmentCount,
1227
+ context,
1228
+ reportTypeLabel,
1229
+ projectSlot,
1230
+ reporterName,
1231
+ description,
1232
+ onDescriptionChange,
1233
+ severity,
1234
+ onSeverityChange,
1235
+ showSeverity,
1236
+ isSubmitting,
1237
+ submitted,
1238
+ onSend,
1239
+ onDegrade,
1240
+ onClose
1241
+ }) {
1242
+ const narrow = useIsNarrow();
1243
+ const [messages, setMessages] = useState2([]);
1244
+ const [input, setInput] = useState2("");
1245
+ const [busy, setBusy] = useState2(false);
1246
+ const [conversationId, setConversationId] = useState2(null);
1247
+ const [phase, setPhase] = useState2("chat");
1248
+ const scrollRef = useRef2(null);
1249
+ const inputRef = useRef2(null);
1250
+ const draftRef = useRef2(null);
1251
+ const seededRef = useRef2(false);
1252
+ useEffect2(() => {
1253
+ const el = scrollRef.current;
1254
+ if (el) el.scrollTop = el.scrollHeight;
1255
+ }, [messages, busy, phase]);
1256
+ useEffect2(() => {
1257
+ var _a;
1258
+ if (phase === "draft") (_a = draftRef.current) == null ? void 0 : _a.focus();
1259
+ }, [phase]);
1260
+ async function runTurn(history2) {
1261
+ setBusy(true);
1262
+ let result;
1263
+ try {
1264
+ result = await assist({ messages: history2, conversationId, screenshot, context });
1265
+ } catch (e) {
1266
+ onDegrade("The assistant is unavailable \u2014 write your report below and send it as normal.");
1267
+ return;
1268
+ } finally {
1269
+ setBusy(false);
1270
+ }
1271
+ if (result.degraded) {
1272
+ onDegrade(result.degraded);
1273
+ return;
1274
+ }
1275
+ if (result.conversationId) setConversationId(result.conversationId);
1276
+ if (result.report) {
1277
+ onDescriptionChange(result.report);
1278
+ setMessages([...history2, { role: "assistant", content: "Here's your report \u2014 have a read." }]);
1279
+ setPhase("draft");
1280
+ return;
1281
+ }
1282
+ if (result.question) {
1283
+ setMessages([...history2, { role: "assistant", content: result.question }]);
1284
+ return;
1285
+ }
1286
+ onDegrade("The assistant had nothing to add \u2014 write your report below and send it as normal.");
1287
+ }
1288
+ useEffect2(() => {
1289
+ if (seededRef.current) return;
1290
+ seededRef.current = true;
1291
+ const seed = description.trim();
1292
+ if (!seed) return;
1293
+ const history2 = [{ role: "user", content: seed }];
1294
+ setMessages(history2);
1295
+ void runTurn(history2);
1296
+ }, []);
1297
+ function send(text) {
1298
+ const value = text.trim();
1299
+ if (!value || busy) return;
1300
+ const history2 = [...messages, { role: "user", content: value }];
1301
+ setMessages(history2);
1302
+ setInput("");
1303
+ void runTurn(history2);
1304
+ }
1305
+ const empty = messages.length === 0 && !busy;
1306
+ const initials = (reporterName != null ? reporterName : "").split(/\s+/).filter(Boolean).slice(0, 2).map((w) => {
1307
+ var _a, _b;
1308
+ return (_b = (_a = w[0]) == null ? void 0 : _a.toUpperCase()) != null ? _b : "";
1309
+ }).join("");
1310
+ const panelStyle = narrow ? {
1311
+ width: "100%",
1312
+ maxHeight: "88dvh",
1313
+ borderTopLeftRadius: "16px",
1314
+ borderTopRightRadius: "16px",
1315
+ animation: "gg-sheet-up .22s cubic-bezier(.2,.8,.2,1)"
1316
+ } : {
1317
+ width: "440px",
1318
+ maxWidth: "100%",
1319
+ height: "100dvh",
1320
+ borderLeft: `1px solid ${t2.border}`,
1321
+ animation: "gg-sheet-in .22s cubic-bezier(.2,.8,.2,1)"
1322
+ };
1323
+ return createPortal(
1324
+ /* @__PURE__ */ jsxs2(Fragment, { children: [
1325
+ /* @__PURE__ */ jsx2("style", { children: `
1326
+ @keyframes gg-sheet-in{from{transform:translateX(24px);opacity:0}to{transform:translateX(0);opacity:1}}
1327
+ @keyframes gg-sheet-up{from{transform:translateY(24px);opacity:0}to{transform:translateY(0);opacity:1}}
1328
+ @keyframes gg-sheet-fade{from{opacity:0}to{opacity:1}}
1329
+ @keyframes gg-dot{0%,80%,100%{transform:translateY(0);opacity:.4}40%{transform:translateY(-3px);opacity:1}}
1330
+ [data-gg-sheet-send]:focus-visible,[data-gg-chip]:focus-visible{outline:2px solid currentColor;outline-offset:2px}
1331
+ ` }),
1332
+ /* @__PURE__ */ jsx2(
1333
+ "div",
1334
+ {
1335
+ "data-glitchgrab-layer": "",
1336
+ role: "dialog",
1337
+ "aria-modal": "true",
1338
+ "aria-label": "Describe your report with AI",
1339
+ style: {
1340
+ position: "fixed",
1341
+ inset: 0,
1342
+ zIndex: 2147483647,
1343
+ display: "flex",
1344
+ alignItems: narrow ? "flex-end" : "stretch",
1345
+ justifyContent: narrow ? "center" : "flex-end",
1346
+ backgroundColor: "rgba(0,0,0,0.5)",
1347
+ animation: "gg-sheet-fade .18s ease",
1348
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
1349
+ },
1350
+ onClick: onClose,
1351
+ onPointerDown: (e) => e.stopPropagation(),
1352
+ children: /* @__PURE__ */ jsxs2(
1353
+ "div",
1354
+ {
1355
+ onClick: (e) => e.stopPropagation(),
1356
+ style: {
1357
+ ...panelStyle,
1358
+ display: "flex",
1359
+ flexDirection: "column",
1360
+ // A flex child defaults to min-width:auto, so a long chat bubble
1361
+ // grows the sheet past the viewport instead of wrapping inside it.
1362
+ // This is what keeps the bottom sheet on screen.
1363
+ minWidth: 0,
1364
+ maxWidth: "100%",
1365
+ boxSizing: "border-box",
1366
+ backgroundColor: t2.bg,
1367
+ color: t2.text,
1368
+ boxShadow: "0 20px 60px rgba(0,0,0,.35)",
1369
+ overflow: "hidden",
1370
+ isolation: "isolate"
1371
+ },
1372
+ children: [
1373
+ /* @__PURE__ */ jsxs2(
1374
+ "div",
1375
+ {
1376
+ style: {
1377
+ flexShrink: 0,
1378
+ padding: "14px 16px",
1379
+ borderBottom: `1px solid ${t2.border}`,
1380
+ display: "flex",
1381
+ alignItems: "flex-start",
1382
+ justifyContent: "space-between",
1383
+ gap: "12px",
1384
+ minWidth: 0
1385
+ },
1386
+ children: [
1387
+ /* @__PURE__ */ jsxs2("div", { style: { minWidth: 0, overflow: "hidden" }, children: [
1388
+ /* @__PURE__ */ jsxs2(
1389
+ "div",
1390
+ {
1391
+ style: {
1392
+ display: "flex",
1393
+ alignItems: "center",
1394
+ gap: "7px",
1395
+ fontSize: "14px",
1396
+ fontWeight: 600
1397
+ },
1398
+ children: [
1399
+ /* @__PURE__ */ jsx2(Sparkle, { color: t2.accent }),
1400
+ "Describe it with AI",
1401
+ /* @__PURE__ */ jsx2(
1402
+ "span",
1403
+ {
1404
+ style: {
1405
+ fontSize: "10px",
1406
+ fontWeight: 600,
1407
+ letterSpacing: ".04em",
1408
+ textTransform: "uppercase",
1409
+ color: t2.accent,
1410
+ border: `1px solid ${t2.accent}55`,
1411
+ borderRadius: "4px",
1412
+ padding: "1px 5px"
1413
+ },
1414
+ children: "Beta"
1415
+ }
1416
+ )
1417
+ ]
1418
+ }
1419
+ ),
1420
+ /* @__PURE__ */ jsxs2("div", { style: { fontSize: "11.5px", color: t2.textMuted, marginTop: "3px" }, children: [
1421
+ reportTypeLabel,
1422
+ projectSlot ? /* @__PURE__ */ jsx2("span", { style: { marginLeft: "6px" }, children: projectSlot }) : null
1423
+ ] })
1424
+ ] }),
1425
+ /* @__PURE__ */ jsx2(
1426
+ "button",
1427
+ {
1428
+ type: "button",
1429
+ onClick: onClose,
1430
+ "aria-label": "Close and write it myself",
1431
+ style: {
1432
+ flexShrink: 0,
1433
+ border: "none",
1434
+ background: "transparent",
1435
+ color: t2.textMuted,
1436
+ cursor: "pointer",
1437
+ fontSize: narrow ? "18px" : "12px",
1438
+ lineHeight: 1,
1439
+ fontFamily: "inherit",
1440
+ padding: narrow ? "4px 6px" : "6px 4px"
1441
+ },
1442
+ children: narrow ? "\xD7" : "Write it myself"
1443
+ }
1444
+ )
1445
+ ]
1446
+ }
1447
+ ),
1448
+ /* @__PURE__ */ jsx2(
1449
+ "div",
1450
+ {
1451
+ ref: scrollRef,
1452
+ style: {
1453
+ flex: 1,
1454
+ minHeight: narrow ? "180px" : 0,
1455
+ overflowY: "auto",
1456
+ padding: "16px",
1457
+ display: "flex",
1458
+ flexDirection: "column"
1459
+ },
1460
+ children: /* @__PURE__ */ jsxs2(
1461
+ "div",
1462
+ {
1463
+ style: {
1464
+ marginTop: "auto",
1465
+ display: "flex",
1466
+ flexDirection: "column",
1467
+ gap: "12px",
1468
+ minWidth: 0
1469
+ },
1470
+ children: [
1471
+ empty && /* @__PURE__ */ jsxs2("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
1472
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: "8px" }, children: [
1473
+ /* @__PURE__ */ jsx2(Avatar, { who: "assistant", theme: t2 }),
1474
+ /* @__PURE__ */ jsxs2(
1475
+ "div",
1476
+ {
1477
+ style: {
1478
+ padding: "9px 12px",
1479
+ borderRadius: "12px 12px 12px 4px",
1480
+ backgroundColor: t2.bgSecondary,
1481
+ fontSize: "13px",
1482
+ lineHeight: 1.55,
1483
+ maxWidth: "88%"
1484
+ },
1485
+ children: [
1486
+ reporterName ? `Hi ${reporterName.split(" ")[0]} \u2014 t` : "T",
1487
+ "ell me what went wrong in your own words. I can already see your screenshot and what you clicked, so skip the boring parts."
1488
+ ]
1489
+ }
1490
+ )
1491
+ ] }),
1492
+ /* @__PURE__ */ jsx2(
1493
+ "div",
1494
+ {
1495
+ style: {
1496
+ display: "flex",
1497
+ flexWrap: "wrap",
1498
+ gap: "6px",
1499
+ paddingLeft: "32px"
1500
+ },
1501
+ children: STARTERS.map((s) => /* @__PURE__ */ jsx2(
1502
+ "button",
1503
+ {
1504
+ type: "button",
1505
+ "data-gg-chip": "",
1506
+ onClick: () => send(s),
1507
+ style: {
1508
+ border: `1px solid ${t2.inputBorder}`,
1509
+ background: "transparent",
1510
+ color: t2.textMuted,
1511
+ borderRadius: "999px",
1512
+ padding: "6px 11px",
1513
+ fontSize: "12px",
1514
+ fontFamily: "inherit",
1515
+ cursor: "pointer"
1516
+ },
1517
+ children: s
1518
+ },
1519
+ s
1520
+ ))
1521
+ }
1522
+ )
1523
+ ] }),
1524
+ messages.map((m, i) => {
1525
+ const mine = m.role === "user";
1526
+ return /* @__PURE__ */ jsxs2(
1527
+ "div",
1528
+ {
1529
+ style: {
1530
+ display: "flex",
1531
+ gap: "8px",
1532
+ minWidth: 0,
1533
+ flexDirection: mine ? "row-reverse" : "row"
1534
+ },
1535
+ children: [
1536
+ /* @__PURE__ */ jsx2(Avatar, { who: m.role, theme: t2, initials }),
1537
+ /* @__PURE__ */ jsx2(
1538
+ "div",
1539
+ {
1540
+ style: {
1541
+ maxWidth: "82%",
1542
+ padding: "9px 12px",
1543
+ borderRadius: mine ? "12px 12px 4px 12px" : "12px 12px 12px 4px",
1544
+ fontSize: "13px",
1545
+ lineHeight: 1.55,
1546
+ whiteSpace: "pre-wrap",
1547
+ wordBreak: "break-word",
1548
+ backgroundColor: mine ? t2.accent : t2.bgSecondary,
1549
+ color: mine ? t2.accentText : t2.text
1550
+ },
1551
+ children: m.content
1552
+ }
1553
+ )
1554
+ ]
1555
+ },
1556
+ i
1557
+ );
1558
+ }),
1559
+ busy && /* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: "8px" }, role: "status", "aria-label": "Thinking", children: [
1560
+ /* @__PURE__ */ jsx2(Avatar, { who: "assistant", theme: t2 }),
1561
+ /* @__PURE__ */ jsx2(
1562
+ "span",
1563
+ {
1564
+ style: {
1565
+ display: "inline-flex",
1566
+ alignItems: "center",
1567
+ gap: "4px",
1568
+ padding: "12px",
1569
+ borderRadius: "12px 12px 12px 4px",
1570
+ backgroundColor: t2.bgSecondary
1571
+ },
1572
+ children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx2(
1573
+ "span",
1574
+ {
1575
+ style: {
1576
+ width: "5px",
1577
+ height: "5px",
1578
+ borderRadius: "50%",
1579
+ backgroundColor: t2.textMuted,
1580
+ animation: `gg-dot 1.1s ease-in-out ${i * 0.15}s infinite`
1581
+ }
1582
+ },
1583
+ i
1584
+ ))
1585
+ }
1586
+ )
1587
+ ] }),
1588
+ phase === "draft" && !submitted && /* @__PURE__ */ jsxs2(
1589
+ "div",
1590
+ {
1591
+ style: {
1592
+ border: `1px solid ${t2.accent}`,
1593
+ borderRadius: "12px",
1594
+ backgroundColor: t2.bgSecondary,
1595
+ padding: "12px",
1596
+ display: "flex",
1597
+ flexDirection: "column",
1598
+ gap: "10px",
1599
+ minWidth: 0,
1600
+ boxSizing: "border-box"
1601
+ },
1602
+ children: [
1603
+ /* @__PURE__ */ jsx2(
1604
+ "span",
1605
+ {
1606
+ style: {
1607
+ fontSize: "10px",
1608
+ fontWeight: 700,
1609
+ letterSpacing: ".06em",
1610
+ textTransform: "uppercase",
1611
+ color: t2.accent
1612
+ },
1613
+ children: "Your report \xB7 edit anything"
1614
+ }
1615
+ ),
1616
+ /* @__PURE__ */ jsx2(
1617
+ "textarea",
1618
+ {
1619
+ ref: draftRef,
1620
+ value: description,
1621
+ onChange: (e) => onDescriptionChange(e.target.value),
1622
+ rows: 6,
1623
+ style: {
1624
+ width: "100%",
1625
+ minHeight: "120px",
1626
+ padding: "10px",
1627
+ borderRadius: "8px",
1628
+ border: `1px solid ${t2.inputBorder}`,
1629
+ backgroundColor: t2.inputBg,
1630
+ color: t2.text,
1631
+ fontSize: "13px",
1632
+ lineHeight: 1.55,
1633
+ fontFamily: "inherit",
1634
+ resize: "vertical",
1635
+ outline: "none",
1636
+ boxSizing: "border-box"
1637
+ }
1638
+ }
1639
+ ),
1640
+ showSeverity && /* @__PURE__ */ jsxs2("div", { children: [
1641
+ /* @__PURE__ */ jsx2(
1642
+ "span",
1643
+ {
1644
+ style: {
1645
+ fontSize: "11.5px",
1646
+ color: t2.textMuted,
1647
+ display: "block",
1648
+ marginBottom: "6px"
1649
+ },
1650
+ children: "How bad is it?"
1651
+ }
1652
+ ),
1653
+ /* @__PURE__ */ jsx2("div", { style: { display: "flex", gap: "6px" }, children: ["low", "medium", "high"].map((s) => {
1654
+ const on = severity === s;
1655
+ return /* @__PURE__ */ jsx2(
1656
+ "button",
1657
+ {
1658
+ type: "button",
1659
+ onClick: () => onSeverityChange(s),
1660
+ "aria-pressed": on,
1661
+ style: {
1662
+ flex: 1,
1663
+ minWidth: 0,
1664
+ padding: "8px 0",
1665
+ borderRadius: "8px",
1666
+ border: `1px solid ${on ? t2.accent : t2.inputBorder}`,
1667
+ backgroundColor: on ? t2.accent : "transparent",
1668
+ color: on ? t2.accentText : t2.textMuted,
1669
+ fontSize: "12px",
1670
+ fontWeight: 600,
1671
+ fontFamily: "inherit",
1672
+ textTransform: "capitalize",
1673
+ cursor: "pointer"
1674
+ },
1675
+ children: s
1676
+ },
1677
+ s
1678
+ );
1679
+ }) })
1680
+ ] }),
1681
+ attachmentCount > 0 && /* @__PURE__ */ jsxs2("span", { style: { fontSize: "11.5px", color: t2.textMuted }, children: [
1682
+ attachmentCount,
1683
+ " ",
1684
+ attachmentCount === 1 ? "attachment" : "attachments",
1685
+ " will be sent with this."
1686
+ ] }),
1687
+ /* @__PURE__ */ jsx2(
1688
+ "button",
1689
+ {
1690
+ type: "button",
1691
+ onClick: () => setPhase("chat"),
1692
+ style: {
1693
+ alignSelf: "flex-start",
1694
+ border: "none",
1695
+ background: "transparent",
1696
+ color: t2.textMuted,
1697
+ fontSize: "12px",
1698
+ fontFamily: "inherit",
1699
+ padding: 0,
1700
+ cursor: "pointer",
1701
+ textDecoration: "underline"
1702
+ },
1703
+ children: "Not quite \u2014 keep chatting"
1704
+ }
1705
+ )
1706
+ ]
1707
+ }
1708
+ ),
1709
+ submitted && /* @__PURE__ */ jsxs2(
1710
+ "div",
1711
+ {
1712
+ style: {
1713
+ textAlign: "center",
1714
+ padding: "24px 0",
1715
+ color: t2.accent,
1716
+ fontSize: "14px",
1717
+ fontWeight: 600
1718
+ },
1719
+ children: [
1720
+ reportTypeLabel,
1721
+ " sent. Thank you!"
1722
+ ]
1723
+ }
1724
+ )
1725
+ ]
1726
+ }
1727
+ )
1728
+ }
1729
+ ),
1730
+ !submitted && /* @__PURE__ */ jsx2(
1731
+ "div",
1732
+ {
1733
+ style: {
1734
+ flexShrink: 0,
1735
+ borderTop: `1px solid ${t2.border}`,
1736
+ padding: "12px 16px",
1737
+ paddingBottom: narrow ? "max(12px, env(safe-area-inset-bottom))" : "12px",
1738
+ backgroundColor: t2.bg
1739
+ },
1740
+ children: phase === "draft" ? /* @__PURE__ */ jsx2(
1741
+ "button",
1742
+ {
1743
+ type: "button",
1744
+ "data-gg-sheet-send": "",
1745
+ onClick: onSend,
1746
+ disabled: isSubmitting || !description.trim(),
1747
+ style: {
1748
+ width: "100%",
1749
+ padding: "12px",
1750
+ borderRadius: "10px",
1751
+ border: "none",
1752
+ backgroundColor: isSubmitting || !description.trim() ? t2.bgSecondary : t2.accent,
1753
+ color: isSubmitting || !description.trim() ? t2.textMuted : t2.accentText,
1754
+ fontSize: "14px",
1755
+ fontWeight: 700,
1756
+ fontFamily: "inherit",
1757
+ cursor: isSubmitting || !description.trim() ? "default" : "pointer"
1758
+ },
1759
+ children: isSubmitting ? "Sending\u2026" : "Send Report"
1760
+ }
1761
+ ) : /* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: "8px", alignItems: "flex-end" }, children: [
1762
+ /* @__PURE__ */ jsx2(
1763
+ "textarea",
1764
+ {
1765
+ ref: inputRef,
1766
+ value: input,
1767
+ onChange: (e) => setInput(e.target.value),
1768
+ onKeyDown: (e) => {
1769
+ if (e.key === "Enter" && !e.shiftKey) {
1770
+ e.preventDefault();
1771
+ send(input);
1772
+ }
1773
+ },
1774
+ placeholder: "Type your answer\u2026",
1775
+ rows: 1,
1776
+ disabled: busy,
1777
+ autoFocus: true,
1778
+ style: {
1779
+ flex: 1,
1780
+ minHeight: "42px",
1781
+ maxHeight: "120px",
1782
+ padding: "11px 12px",
1783
+ borderRadius: "10px",
1784
+ border: `1px solid ${t2.inputBorder}`,
1785
+ backgroundColor: t2.inputBg,
1786
+ color: t2.text,
1787
+ fontSize: "13px",
1788
+ lineHeight: 1.4,
1789
+ fontFamily: "inherit",
1790
+ resize: "none",
1791
+ outline: "none",
1792
+ boxSizing: "border-box"
1793
+ }
1794
+ }
1795
+ ),
1796
+ /* @__PURE__ */ jsx2(
1797
+ "button",
1798
+ {
1799
+ type: "button",
1800
+ "data-gg-sheet-send": "",
1801
+ onClick: () => send(input),
1802
+ disabled: busy || !input.trim(),
1803
+ "aria-label": "Send message",
1804
+ style: {
1805
+ flexShrink: 0,
1806
+ width: "42px",
1807
+ height: "42px",
1808
+ borderRadius: "10px",
1809
+ border: "none",
1810
+ display: "inline-flex",
1811
+ alignItems: "center",
1812
+ justifyContent: "center",
1813
+ backgroundColor: busy || !input.trim() ? t2.bgSecondary : t2.accent,
1814
+ color: busy || !input.trim() ? t2.textMuted : t2.accentText,
1815
+ cursor: busy || !input.trim() ? "default" : "pointer"
1816
+ },
1817
+ children: /* @__PURE__ */ jsx2("svg", { width: "17", height: "17", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx2(
1818
+ "path",
1819
+ {
1820
+ d: "M3 20.5L21.5 12 3 3.5V10l12 2-12 2v6.5z",
1821
+ fill: "currentColor"
1822
+ }
1823
+ ) })
1824
+ }
1825
+ )
1826
+ ] })
1827
+ }
1828
+ )
1829
+ ]
1830
+ }
1831
+ )
1832
+ }
1833
+ )
1834
+ ] }),
1835
+ document.body
1836
+ );
1837
+ }
1111
1838
  var GLITCHGRAB_SHORTCUT = "Ctrl+Shift+G";
1112
1839
  var GLITCHGRAB_SHORTCUT_MAC = "\u2318\u21E7G";
1113
1840
  function isMac() {
@@ -1276,9 +2003,9 @@ function ReporterChip({
1276
2003
  t: t2
1277
2004
  }) {
1278
2005
  var _a;
1279
- const [avatarFailed, setAvatarFailed] = useState2(false);
2006
+ const [avatarFailed, setAvatarFailed] = useState3(false);
1280
2007
  const avatarUrl = (reporter == null ? void 0 : reporter.avatarUrl) || "";
1281
- useEffect2(() => {
2008
+ useEffect3(() => {
1282
2009
  setAvatarFailed(false);
1283
2010
  }, [avatarUrl]);
1284
2011
  const name = ((_a = reporter == null ? void 0 : reporter.name) == null ? void 0 : _a.trim()) || "";
@@ -1287,13 +2014,13 @@ function ReporterChip({
1287
2014
  const label = isAnonymous ? "Anonymous" : name;
1288
2015
  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 ");
1289
2016
  const showAvatarImage = !!avatarUrl && !avatarFailed;
1290
- return /* @__PURE__ */ jsxs2(
2017
+ return /* @__PURE__ */ jsxs3(
1291
2018
  "span",
1292
2019
  {
1293
2020
  title,
1294
2021
  style: { display: "flex", alignItems: "center", gap: "6px", minWidth: 0 },
1295
2022
  children: [
1296
- /* @__PURE__ */ jsx2(
2023
+ /* @__PURE__ */ jsx3(
1297
2024
  "span",
1298
2025
  {
1299
2026
  "aria-hidden": "true",
@@ -1313,7 +2040,7 @@ function ReporterChip({
1313
2040
  color: isAnonymous ? t2.textMuted : t2.accentText,
1314
2041
  border: `1px solid ${isAnonymous ? t2.inputBorder : "transparent"}`
1315
2042
  },
1316
- children: showAvatarImage ? /* @__PURE__ */ jsx2(
2043
+ children: showAvatarImage ? /* @__PURE__ */ jsx3(
1317
2044
  "img",
1318
2045
  {
1319
2046
  src: avatarUrl,
@@ -1323,9 +2050,9 @@ function ReporterChip({
1323
2050
  onError: () => setAvatarFailed(true),
1324
2051
  style: { width: "100%", height: "100%", objectFit: "cover" }
1325
2052
  }
1326
- ) : initials ? initials : /* @__PURE__ */ jsxs2("svg", { width: "10", height: "10", viewBox: "0 0 16 16", fill: "none", children: [
1327
- /* @__PURE__ */ jsx2("circle", { cx: "8", cy: "5.5", r: "2.75", stroke: "currentColor", strokeWidth: "1.4" }),
1328
- /* @__PURE__ */ jsx2(
2053
+ ) : initials ? initials : /* @__PURE__ */ jsxs3("svg", { width: "10", height: "10", viewBox: "0 0 16 16", fill: "none", children: [
2054
+ /* @__PURE__ */ jsx3("circle", { cx: "8", cy: "5.5", r: "2.75", stroke: "currentColor", strokeWidth: "1.4" }),
2055
+ /* @__PURE__ */ jsx3(
1329
2056
  "path",
1330
2057
  {
1331
2058
  d: "M2.75 13.5c0-2.35 2.35-3.75 5.25-3.75s5.25 1.4 5.25 3.75",
@@ -1337,7 +2064,7 @@ function ReporterChip({
1337
2064
  ] })
1338
2065
  }
1339
2066
  ),
1340
- /* @__PURE__ */ jsxs2(
2067
+ /* @__PURE__ */ jsxs3(
1341
2068
  "span",
1342
2069
  {
1343
2070
  style: {
@@ -1451,6 +2178,8 @@ function ReportDialog({
1451
2178
  report,
1452
2179
  sendFeedback: sendFeedback2,
1453
2180
  enhanceText: enhanceText2,
2181
+ assist,
2182
+ assistContext = null,
1454
2183
  transcribeAudio: transcribeAudio2,
1455
2184
  types,
1456
2185
  showSeverity = true,
@@ -1459,33 +2188,37 @@ function ReportDialog({
1459
2188
  onClose,
1460
2189
  headerSlot
1461
2190
  }) {
1462
- const [isEnhancing, setIsEnhancing] = useState2(false);
1463
- const [isEnhanced, setIsEnhanced] = useState2(false);
1464
- const [originalDescription, setOriginalDescription] = useState2(
2191
+ var _a, _b;
2192
+ const [isEnhancing, setIsEnhancing] = useState3(false);
2193
+ const [assistOpen, setAssistOpen] = useState3(false);
2194
+ const [assistNotice, setAssistNotice] = useState3(null);
2195
+ const [assistUsed, setAssistUsed] = useState3(false);
2196
+ const [isEnhanced, setIsEnhanced] = useState3(false);
2197
+ const [originalDescription, setOriginalDescription] = useState3(
1465
2198
  null
1466
2199
  );
1467
- const [isListening, setIsListening] = useState2(false);
1468
- const [isTranscribing, setIsTranscribing] = useState2(false);
1469
- const [voiceError, setVoiceError] = useState2(null);
1470
- const [screenshotDragOver, setScreenshotDragOver] = useState2(false);
1471
- const [mounted, setMounted] = useState2(false);
1472
- useEffect2(() => {
2200
+ const [isListening, setIsListening] = useState3(false);
2201
+ const [isTranscribing, setIsTranscribing] = useState3(false);
2202
+ const [voiceError, setVoiceError] = useState3(null);
2203
+ const [screenshotDragOver, setScreenshotDragOver] = useState3(false);
2204
+ const [mounted, setMounted] = useState3(false);
2205
+ useEffect3(() => {
1473
2206
  setMounted(true);
1474
2207
  }, []);
1475
- const [isOpen, setIsOpen] = useState2(false);
1476
- const [description, setDescription] = useState2("");
1477
- const [isSubmitting, setIsSubmitting] = useState2(false);
1478
- const [submitted, setSubmitted] = useState2(false);
1479
- const [screenshots, setScreenshots] = useState2([]);
1480
- const [attachments, setAttachments] = useState2([]);
1481
- const [previewIndex, setPreviewIndex] = useState2(null);
1482
- const [annotatingIndex, setAnnotatingIndex] = useState2(null);
1483
- const [previewZoomed, setPreviewZoomed] = useState2(false);
1484
- const [previewNatural, setPreviewNatural] = useState2(null);
1485
- const previewScrollRef = useRef2(null);
1486
- const previewImgElRef = useRef2(null);
1487
- const panRef = useRef2(null);
1488
- const zoomAnchorRef = useRef2(null);
2208
+ const [isOpen, setIsOpen] = useState3(false);
2209
+ const [description, setDescription] = useState3("");
2210
+ const [isSubmitting, setIsSubmitting] = useState3(false);
2211
+ const [submitted, setSubmitted] = useState3(false);
2212
+ const [screenshots, setScreenshots] = useState3([]);
2213
+ const [attachments, setAttachments] = useState3([]);
2214
+ const [previewIndex, setPreviewIndex] = useState3(null);
2215
+ const [annotatingIndex, setAnnotatingIndex] = useState3(null);
2216
+ const [previewZoomed, setPreviewZoomed] = useState3(false);
2217
+ const [previewNatural, setPreviewNatural] = useState3(null);
2218
+ const previewScrollRef = useRef3(null);
2219
+ const previewImgElRef = useRef3(null);
2220
+ const panRef = useRef3(null);
2221
+ const zoomAnchorRef = useRef3(null);
1489
2222
  const resetPreviewZoom = () => {
1490
2223
  setPreviewZoomed(false);
1491
2224
  setPreviewNatural(null);
@@ -1499,20 +2232,20 @@ function ReportDialog({
1499
2232
  resetPreviewZoom();
1500
2233
  setPreviewIndex(null);
1501
2234
  };
1502
- const fileInputRef = useRef2(null);
1503
- const modalRef = useRef2(null);
1504
- const previewImgRef = useRef2(null);
1505
- const textareaRef = useRef2(null);
1506
- const recognitionRef = useRef2(null);
1507
- const voiceBaseRef = useRef2("");
1508
- const usingWebSpeechRef = useRef2(false);
1509
- const textBeforeVoiceRef = useRef2("");
1510
- const mediaRecorderRef = useRef2(null);
1511
- const streamRef = useRef2(null);
1512
- const sarvamChunksRef = useRef2([]);
1513
- const spaceTimerRef = useRef2(null);
1514
- const isPushToTalkRef = useRef2(false);
1515
- useEffect2(() => {
2235
+ const fileInputRef = useRef3(null);
2236
+ const modalRef = useRef3(null);
2237
+ const previewImgRef = useRef3(null);
2238
+ const textareaRef = useRef3(null);
2239
+ const recognitionRef = useRef3(null);
2240
+ const voiceBaseRef = useRef3("");
2241
+ const usingWebSpeechRef = useRef3(false);
2242
+ const textBeforeVoiceRef = useRef3("");
2243
+ const mediaRecorderRef = useRef3(null);
2244
+ const streamRef = useRef3(null);
2245
+ const sarvamChunksRef = useRef3([]);
2246
+ const spaceTimerRef = useRef3(null);
2247
+ const isPushToTalkRef = useRef3(false);
2248
+ useEffect3(() => {
1516
2249
  if (!isOpen) return;
1517
2250
  const HOST_LAYERS = '[role="dialog"],[role="alertdialog"],[role="menu"],[role="listbox"]';
1518
2251
  const inerted = /* @__PURE__ */ new Set();
@@ -1538,13 +2271,13 @@ function ReportDialog({
1538
2271
  inerted.forEach((el) => el.removeAttribute("inert"));
1539
2272
  };
1540
2273
  }, [isOpen]);
1541
- const [step, setStep] = useState2(1);
1542
- const [reportType, setReportType] = useState2("BUG");
1543
- const [severity, setSeverity] = useState2("medium");
1544
- const [validationError, setValidationError] = useState2(null);
1545
- const [placeholderIdx, setPlaceholderIdx] = useState2(0);
1546
- const [rating, setRating] = useState2(0);
1547
- const [hoveredStar, setHoveredStar] = useState2(0);
2274
+ const [step, setStep] = useState3(1);
2275
+ const [reportType, setReportType] = useState3("BUG");
2276
+ const [severity, setSeverity] = useState3("medium");
2277
+ const [validationError, setValidationError] = useState3(null);
2278
+ const [placeholderIdx, setPlaceholderIdx] = useState3(0);
2279
+ const [rating, setRating] = useState3(0);
2280
+ const [hoveredStar, setHoveredStar] = useState3(0);
1548
2281
  const isRating = reportType === "RATING";
1549
2282
  const submitDisabled = isSubmitting || (isRating ? rating < 1 : !description.trim());
1550
2283
  const availableTypes = types != null ? types : [
@@ -1555,8 +2288,8 @@ function ReportDialog({
1555
2288
  "SECURITY",
1556
2289
  "QUESTION"
1557
2290
  ];
1558
- const tileGridRef = useRef2(null);
1559
- useEffect2(() => {
2291
+ const tileGridRef = useRef3(null);
2292
+ useEffect3(() => {
1560
2293
  if (!isOpen || step !== 1) return;
1561
2294
  const onKey = (e) => {
1562
2295
  const el = e.target;
@@ -1585,11 +2318,11 @@ function ReportDialog({
1585
2318
  return () => window.removeEventListener("keydown", onKey);
1586
2319
  }, [isOpen, step, sendFeedback2, availableTypes.join(",")]);
1587
2320
  const handleTileGridKeyDown = (e) => {
1588
- var _a, _b, _c;
2321
+ var _a2, _b2, _c;
1589
2322
  const keys = ["ArrowRight", "ArrowLeft", "ArrowDown", "ArrowUp"];
1590
2323
  if (!keys.includes(e.key)) return;
1591
2324
  const tiles = Array.from(
1592
- (_b = (_a = tileGridRef.current) == null ? void 0 : _a.querySelectorAll("button[data-gg-type]")) != null ? _b : []
2325
+ (_b2 = (_a2 = tileGridRef.current) == null ? void 0 : _a2.querySelectorAll("button[data-gg-type]")) != null ? _b2 : []
1593
2326
  );
1594
2327
  if (tiles.length === 0) return;
1595
2328
  e.preventDefault();
@@ -1637,7 +2370,7 @@ function ReportDialog({
1637
2370
  if (shot) setScreenshots([shot]);
1638
2371
  setIsOpen(true);
1639
2372
  };
1640
- useEffect2(() => {
2373
+ useEffect3(() => {
1641
2374
  const handler = (e) => {
1642
2375
  if (isOpen) return;
1643
2376
  const detail = e.detail;
@@ -1651,7 +2384,7 @@ function ReportDialog({
1651
2384
  window.addEventListener("glitchgrab:open-report", handler);
1652
2385
  return () => window.removeEventListener("glitchgrab:open-report", handler);
1653
2386
  }, [isOpen, handleOpen]);
1654
- useEffect2(() => {
2387
+ useEffect3(() => {
1655
2388
  if (!isOpen) return;
1656
2389
  const handleEsc = (e) => {
1657
2390
  if (e.key === "Escape") {
@@ -1664,29 +2397,29 @@ function ReportDialog({
1664
2397
  document.addEventListener("keydown", handleEsc);
1665
2398
  return () => document.removeEventListener("keydown", handleEsc);
1666
2399
  }, [isOpen, previewIndex, previewZoomed, annotatingIndex]);
1667
- useEffect2(() => {
2400
+ useEffect3(() => {
1668
2401
  if (previewIndex === null || annotatingIndex !== null) return;
1669
2402
  const handlePointerDown = (e) => {
1670
- var _a;
1671
- if (!((_a = previewImgRef.current) == null ? void 0 : _a.contains(e.target))) {
2403
+ var _a2;
2404
+ if (!((_a2 = previewImgRef.current) == null ? void 0 : _a2.contains(e.target))) {
1672
2405
  closePreview();
1673
2406
  }
1674
2407
  };
1675
2408
  document.addEventListener("pointerdown", handlePointerDown, true);
1676
2409
  return () => document.removeEventListener("pointerdown", handlePointerDown, true);
1677
2410
  }, [previewIndex, annotatingIndex]);
1678
- useEffect2(() => {
1679
- var _a;
2411
+ useEffect3(() => {
2412
+ var _a2;
1680
2413
  const el = previewScrollRef.current;
1681
2414
  if (!previewZoomed || !el) return;
1682
- const anchor = (_a = zoomAnchorRef.current) != null ? _a : { fx: 0.5, fy: 0.5 };
2415
+ const anchor = (_a2 = zoomAnchorRef.current) != null ? _a2 : { fx: 0.5, fy: 0.5 };
1683
2416
  el.scrollLeft = anchor.fx * el.scrollWidth - el.clientWidth / 2;
1684
2417
  el.scrollTop = anchor.fy * el.scrollHeight - el.clientHeight / 2;
1685
2418
  }, [previewZoomed]);
1686
2419
  const togglePreviewZoom = (e) => {
1687
- var _a;
2420
+ var _a2;
1688
2421
  e.stopPropagation();
1689
- if ((_a = panRef.current) == null ? void 0 : _a.moved) return;
2422
+ if ((_a2 = panRef.current) == null ? void 0 : _a2.moved) return;
1690
2423
  if (!previewZoomed && !canZoomPreview) return;
1691
2424
  const img = previewImgElRef.current;
1692
2425
  if (!previewZoomed && img) {
@@ -1721,9 +2454,9 @@ function ReportDialog({
1721
2454
  el.scrollTop = start.top - dy;
1722
2455
  };
1723
2456
  const handlePanEnd = (e) => {
1724
- var _a, _b;
2457
+ var _a2, _b2;
1725
2458
  const el = previewScrollRef.current;
1726
- const moved = (_b = (_a = panRef.current) == null ? void 0 : _a.moved) != null ? _b : false;
2459
+ const moved = (_b2 = (_a2 = panRef.current) == null ? void 0 : _a2.moved) != null ? _b2 : false;
1727
2460
  try {
1728
2461
  el == null ? void 0 : el.releasePointerCapture(e.pointerId);
1729
2462
  } catch (e2) {
@@ -1737,12 +2470,12 @@ function ReportDialog({
1737
2470
  panRef.current = null;
1738
2471
  }
1739
2472
  };
1740
- useEffect2(() => {
2473
+ useEffect3(() => {
1741
2474
  if (!isOpen) return;
1742
2475
  const handlePaste = (e) => {
1743
- var _a;
2476
+ var _a2;
1744
2477
  try {
1745
- const items = (_a = e.clipboardData) == null ? void 0 : _a.items;
2478
+ const items = (_a2 = e.clipboardData) == null ? void 0 : _a2.items;
1746
2479
  if (!items) return;
1747
2480
  const pasted = [];
1748
2481
  for (let i = 0; i < items.length; i++) {
@@ -1760,7 +2493,7 @@ function ReportDialog({
1760
2493
  window.addEventListener("paste", handlePaste);
1761
2494
  return () => window.removeEventListener("paste", handlePaste);
1762
2495
  }, [isOpen]);
1763
- useEffect2(() => {
2496
+ useEffect3(() => {
1764
2497
  if (!isOpen || !transcribeAudio2) return;
1765
2498
  const id = setInterval(() => {
1766
2499
  setPlaceholderIdx((i) => (i + 1) % 2);
@@ -1768,16 +2501,16 @@ function ReportDialog({
1768
2501
  return () => clearInterval(id);
1769
2502
  }, [isOpen, transcribeAudio2]);
1770
2503
  const stopVoice = () => {
1771
- var _a, _b;
2504
+ var _a2, _b2;
1772
2505
  usingWebSpeechRef.current = false;
1773
- (_a = recognitionRef.current) == null ? void 0 : _a.stop();
2506
+ (_a2 = recognitionRef.current) == null ? void 0 : _a2.stop();
1774
2507
  recognitionRef.current = null;
1775
2508
  sarvamChunksRef.current = [];
1776
2509
  const stream = streamRef.current;
1777
2510
  streamRef.current = null;
1778
2511
  stream == null ? void 0 : stream.getTracks().forEach((t22) => t22.stop());
1779
2512
  try {
1780
- (_b = mediaRecorderRef.current) == null ? void 0 : _b.stop();
2513
+ (_b2 = mediaRecorderRef.current) == null ? void 0 : _b2.stop();
1781
2514
  } catch (e) {
1782
2515
  }
1783
2516
  mediaRecorderRef.current = null;
@@ -1785,16 +2518,28 @@ function ReportDialog({
1785
2518
  setIsTranscribing(false);
1786
2519
  };
1787
2520
  const stopListeningAndTranscribe = () => {
1788
- var _a, _b;
2521
+ var _a2, _b2;
1789
2522
  usingWebSpeechRef.current = false;
1790
- (_a = recognitionRef.current) == null ? void 0 : _a.stop();
2523
+ (_a2 = recognitionRef.current) == null ? void 0 : _a2.stop();
1791
2524
  recognitionRef.current = null;
1792
2525
  setIsListening(false);
1793
2526
  try {
1794
- (_b = mediaRecorderRef.current) == null ? void 0 : _b.stop();
2527
+ (_b2 = mediaRecorderRef.current) == null ? void 0 : _b2.stop();
1795
2528
  } catch (e) {
1796
2529
  }
1797
2530
  };
2531
+ const sheetUp = !!assist && assistOpen && !isRating;
2532
+ useEffect3(() => {
2533
+ const el = modalRef.current;
2534
+ if (!el) return;
2535
+ if (sheetUp) {
2536
+ el.setAttribute("inert", "");
2537
+ el.setAttribute("aria-hidden", "true");
2538
+ } else {
2539
+ el.removeAttribute("inert");
2540
+ el.removeAttribute("aria-hidden");
2541
+ }
2542
+ }, [sheetUp, isOpen]);
1798
2543
  const handleClose = () => {
1799
2544
  stopVoice();
1800
2545
  setIsOpen(false);
@@ -1810,6 +2555,9 @@ function ReportDialog({
1810
2555
  setVoiceError(null);
1811
2556
  setIsEnhanced(false);
1812
2557
  setOriginalDescription(null);
2558
+ setAssistOpen(false);
2559
+ setAssistUsed(false);
2560
+ setAssistNotice(null);
1813
2561
  };
1814
2562
  const toggleVoice = async () => {
1815
2563
  if (isListening) {
@@ -1912,7 +2660,7 @@ function ReportDialog({
1912
2660
  }
1913
2661
  };
1914
2662
  const handleSpaceDown = (e) => {
1915
- var _a;
2663
+ var _a2;
1916
2664
  if (e.code !== "Space") return;
1917
2665
  if (isListening || isPushToTalkRef.current) {
1918
2666
  e.preventDefault();
@@ -1920,7 +2668,7 @@ function ReportDialog({
1920
2668
  }
1921
2669
  if (e.repeat || !transcribeAudio2 || isTranscribing || spaceTimerRef.current)
1922
2670
  return;
1923
- const pos = (_a = e.currentTarget.selectionStart) != null ? _a : description.length;
2671
+ const pos = (_a2 = e.currentTarget.selectionStart) != null ? _a2 : description.length;
1924
2672
  spaceTimerRef.current = setTimeout(() => {
1925
2673
  spaceTimerRef.current = null;
1926
2674
  isPushToTalkRef.current = true;
@@ -2009,9 +2757,9 @@ function ReportDialog({
2009
2757
  }
2010
2758
  };
2011
2759
  if (!mounted) return null;
2012
- return /* @__PURE__ */ jsxs2(Fragment, { children: [
2013
- isOpen && createPortal(
2014
- /* @__PURE__ */ jsx2("style", { children: `
2760
+ return /* @__PURE__ */ jsxs3(Fragment2, { children: [
2761
+ isOpen && createPortal2(
2762
+ /* @__PURE__ */ jsx3("style", { children: `
2015
2763
  @keyframes gg-pulse{0%,100%{opacity:1}50%{opacity:0.35}}
2016
2764
  @keyframes gg-b1{0%,100%{height:3px}40%{height:13px}}
2017
2765
  @keyframes gg-b2{0%,100%{height:8px}50%{height:3px}}
@@ -2047,8 +2795,8 @@ function ReportDialog({
2047
2795
  ` }),
2048
2796
  document.body
2049
2797
  ),
2050
- isOpen && createPortal(
2051
- /* @__PURE__ */ jsx2(
2798
+ isOpen && createPortal2(
2799
+ /* @__PURE__ */ jsx3(
2052
2800
  "div",
2053
2801
  {
2054
2802
  "data-glitchgrab-layer": "",
@@ -2057,7 +2805,10 @@ function ReportDialog({
2057
2805
  inset: 0,
2058
2806
  zIndex: 2147483647,
2059
2807
  pointerEvents: "auto",
2060
- display: "flex",
2808
+ // Hidden, not unmounted, while the AI sheet is in charge — the
2809
+ // dialog's state IS the report, and unmounting would drop the
2810
+ // screenshots, attachments and step the reporter is on.
2811
+ display: sheetUp ? "none" : "flex",
2061
2812
  alignItems: "center",
2062
2813
  justifyContent: "center",
2063
2814
  backgroundColor: "rgba(0,0,0,0.5)",
@@ -2068,7 +2819,7 @@ function ReportDialog({
2068
2819
  },
2069
2820
  onPointerDown: (e) => e.stopPropagation(),
2070
2821
  onFocus: (e) => e.stopPropagation(),
2071
- children: /* @__PURE__ */ jsxs2(
2822
+ children: /* @__PURE__ */ jsxs3(
2072
2823
  "div",
2073
2824
  {
2074
2825
  ref: modalRef,
@@ -2090,7 +2841,7 @@ function ReportDialog({
2090
2841
  isolation: "isolate"
2091
2842
  },
2092
2843
  children: [
2093
- /* @__PURE__ */ jsxs2(
2844
+ /* @__PURE__ */ jsxs3(
2094
2845
  "div",
2095
2846
  {
2096
2847
  style: {
@@ -2099,7 +2850,7 @@ function ReportDialog({
2099
2850
  borderBottom: `1px solid ${t2.border}`
2100
2851
  },
2101
2852
  children: [
2102
- /* @__PURE__ */ jsxs2(
2853
+ /* @__PURE__ */ jsxs3(
2103
2854
  "div",
2104
2855
  {
2105
2856
  style: {
@@ -2108,7 +2859,7 @@ function ReportDialog({
2108
2859
  alignItems: "center"
2109
2860
  },
2110
2861
  children: [
2111
- /* @__PURE__ */ jsxs2(
2862
+ /* @__PURE__ */ jsxs3(
2112
2863
  "div",
2113
2864
  {
2114
2865
  style: {
@@ -2117,7 +2868,7 @@ function ReportDialog({
2117
2868
  gap: "8px"
2118
2869
  },
2119
2870
  children: [
2120
- step > 1 && /* @__PURE__ */ jsx2(
2871
+ step > 1 && /* @__PURE__ */ jsx3(
2121
2872
  "button",
2122
2873
  {
2123
2874
  type: "button",
@@ -2131,14 +2882,14 @@ function ReportDialog({
2131
2882
  alignItems: "center"
2132
2883
  },
2133
2884
  "aria-label": "Back",
2134
- children: /* @__PURE__ */ jsx2(
2885
+ children: /* @__PURE__ */ jsx3(
2135
2886
  "svg",
2136
2887
  {
2137
2888
  width: "16",
2138
2889
  height: "16",
2139
2890
  viewBox: "0 0 16 16",
2140
2891
  fill: "none",
2141
- children: /* @__PURE__ */ jsx2(
2892
+ children: /* @__PURE__ */ jsx3(
2142
2893
  "path",
2143
2894
  {
2144
2895
  d: "M10 3L5 8L10 13",
@@ -2152,7 +2903,7 @@ function ReportDialog({
2152
2903
  )
2153
2904
  }
2154
2905
  ),
2155
- /* @__PURE__ */ jsx2(
2906
+ /* @__PURE__ */ jsx3(
2156
2907
  "span",
2157
2908
  {
2158
2909
  style: {
@@ -2166,7 +2917,7 @@ function ReportDialog({
2166
2917
  ]
2167
2918
  }
2168
2919
  ),
2169
- /* @__PURE__ */ jsxs2(
2920
+ /* @__PURE__ */ jsxs3(
2170
2921
  "div",
2171
2922
  {
2172
2923
  style: {
@@ -2175,7 +2926,7 @@ function ReportDialog({
2175
2926
  gap: "8px"
2176
2927
  },
2177
2928
  children: [
2178
- step === 1 && /* @__PURE__ */ jsx2(
2929
+ step === 1 && /* @__PURE__ */ jsx3(
2179
2930
  "span",
2180
2931
  {
2181
2932
  title: "Press this anywhere to open Glitchgrab",
@@ -2193,7 +2944,7 @@ function ReportDialog({
2193
2944
  children: getShortcutLabel()
2194
2945
  }
2195
2946
  ),
2196
- /* @__PURE__ */ jsx2(
2947
+ /* @__PURE__ */ jsx3(
2197
2948
  "button",
2198
2949
  {
2199
2950
  type: "button",
@@ -2208,7 +2959,7 @@ function ReportDialog({
2208
2959
  justifyContent: "center"
2209
2960
  },
2210
2961
  "aria-label": "Close",
2211
- children: /* @__PURE__ */ jsx2(
2962
+ children: /* @__PURE__ */ jsx3(
2212
2963
  "svg",
2213
2964
  {
2214
2965
  width: "16",
@@ -2216,7 +2967,7 @@ function ReportDialog({
2216
2967
  viewBox: "0 0 16 16",
2217
2968
  fill: "none",
2218
2969
  style: { display: "block" },
2219
- children: /* @__PURE__ */ jsx2(
2970
+ children: /* @__PURE__ */ jsx3(
2220
2971
  "path",
2221
2972
  {
2222
2973
  d: "M4 4L12 12M12 4L4 12",
@@ -2235,7 +2986,7 @@ function ReportDialog({
2235
2986
  ]
2236
2987
  }
2237
2988
  ),
2238
- /* @__PURE__ */ jsx2(
2989
+ /* @__PURE__ */ jsx3(
2239
2990
  "div",
2240
2991
  {
2241
2992
  style: {
@@ -2245,12 +2996,12 @@ function ReportDialog({
2245
2996
  gap: "0",
2246
2997
  marginTop: "12px"
2247
2998
  },
2248
- children: [1, 2].map((s, i) => /* @__PURE__ */ jsxs2(
2999
+ children: [1, 2].map((s, i) => /* @__PURE__ */ jsxs3(
2249
3000
  "div",
2250
3001
  {
2251
3002
  style: { display: "flex", alignItems: "center" },
2252
3003
  children: [
2253
- /* @__PURE__ */ jsx2(
3004
+ /* @__PURE__ */ jsx3(
2254
3005
  "div",
2255
3006
  {
2256
3007
  style: {
@@ -2262,7 +3013,7 @@ function ReportDialog({
2262
3013
  }
2263
3014
  }
2264
3015
  ),
2265
- i < 1 && /* @__PURE__ */ jsx2(
3016
+ i < 1 && /* @__PURE__ */ jsx3(
2266
3017
  "div",
2267
3018
  {
2268
3019
  style: {
@@ -2282,7 +3033,7 @@ function ReportDialog({
2282
3033
  ]
2283
3034
  }
2284
3035
  ),
2285
- /* @__PURE__ */ jsx2(
3036
+ /* @__PURE__ */ jsx3(
2286
3037
  "div",
2287
3038
  {
2288
3039
  style: {
@@ -2291,7 +3042,7 @@ function ReportDialog({
2291
3042
  flex: "1 1 auto",
2292
3043
  minHeight: 0
2293
3044
  },
2294
- children: submitted ? /* @__PURE__ */ jsxs2(
3045
+ children: submitted ? /* @__PURE__ */ jsxs3(
2295
3046
  "div",
2296
3047
  {
2297
3048
  style: {
@@ -2306,9 +3057,9 @@ function ReportDialog({
2306
3057
  " sent. Thank you!"
2307
3058
  ]
2308
3059
  }
2309
- ) : /* @__PURE__ */ jsxs2(Fragment, { children: [
2310
- step === 1 && headerSlot ? /* @__PURE__ */ jsx2("div", { style: { marginBottom: "14px" }, children: headerSlot }) : null,
2311
- step === 1 && sendFeedback2 && /* @__PURE__ */ jsxs2(
3060
+ ) : /* @__PURE__ */ jsxs3(Fragment2, { children: [
3061
+ step === 1 && headerSlot ? /* @__PURE__ */ jsx3("div", { style: { marginBottom: "14px" }, children: headerSlot }) : null,
3062
+ step === 1 && sendFeedback2 && /* @__PURE__ */ jsxs3(
2312
3063
  "div",
2313
3064
  {
2314
3065
  style: {
@@ -2325,16 +3076,16 @@ function ReportDialog({
2325
3076
  },
2326
3077
  onMouseLeave: () => setHoveredStar(0),
2327
3078
  children: [
2328
- /* @__PURE__ */ jsx2(
3079
+ /* @__PURE__ */ jsx3(
2329
3080
  "span",
2330
3081
  {
2331
3082
  style: { fontSize: "13px", fontWeight: 600, color: t2.text },
2332
3083
  children: "How are we doing?"
2333
3084
  }
2334
3085
  ),
2335
- /* @__PURE__ */ jsx2("span", { style: { display: "flex", gap: "4px" }, children: [1, 2, 3, 4, 5].map((star) => {
3086
+ /* @__PURE__ */ jsx3("span", { style: { display: "flex", gap: "4px" }, children: [1, 2, 3, 4, 5].map((star) => {
2336
3087
  const filled = star <= (hoveredStar || rating);
2337
- return /* @__PURE__ */ jsx2(
3088
+ return /* @__PURE__ */ jsx3(
2338
3089
  "button",
2339
3090
  {
2340
3091
  type: "button",
@@ -2354,7 +3105,7 @@ function ReportDialog({
2354
3105
  cursor: "pointer",
2355
3106
  lineHeight: 0
2356
3107
  },
2357
- children: /* @__PURE__ */ jsx2("svg", { width: "26", height: "26", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx2(
3108
+ children: /* @__PURE__ */ jsx3("svg", { width: "26", height: "26", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx3(
2358
3109
  "path",
2359
3110
  {
2360
3111
  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",
@@ -2371,7 +3122,7 @@ function ReportDialog({
2371
3122
  ]
2372
3123
  }
2373
3124
  ),
2374
- step === 1 && sendFeedback2 && /* @__PURE__ */ jsxs2(
3125
+ step === 1 && sendFeedback2 && /* @__PURE__ */ jsxs3(
2375
3126
  "div",
2376
3127
  {
2377
3128
  style: {
@@ -2381,13 +3132,13 @@ function ReportDialog({
2381
3132
  marginBottom: "16px"
2382
3133
  },
2383
3134
  children: [
2384
- /* @__PURE__ */ jsx2("span", { style: { flex: 1, height: "1px", background: t2.border } }),
2385
- /* @__PURE__ */ jsx2("span", { style: { fontSize: "11px", color: t2.textMuted }, children: "or report something" }),
2386
- /* @__PURE__ */ jsx2("span", { style: { flex: 1, height: "1px", background: t2.border } })
3135
+ /* @__PURE__ */ jsx3("span", { style: { flex: 1, height: "1px", background: t2.border } }),
3136
+ /* @__PURE__ */ jsx3("span", { style: { fontSize: "11px", color: t2.textMuted }, children: "or report something" }),
3137
+ /* @__PURE__ */ jsx3("span", { style: { flex: 1, height: "1px", background: t2.border } })
2387
3138
  ]
2388
3139
  }
2389
3140
  ),
2390
- step === 1 && screenshots.length > 0 && /* @__PURE__ */ jsxs2(
3141
+ step === 1 && screenshots.length > 0 && /* @__PURE__ */ jsxs3(
2391
3142
  "div",
2392
3143
  {
2393
3144
  style: {
@@ -2401,7 +3152,7 @@ function ReportDialog({
2401
3152
  background: t2.inputBg
2402
3153
  },
2403
3154
  children: [
2404
- /* @__PURE__ */ jsx2(
3155
+ /* @__PURE__ */ jsx3(
2405
3156
  "img",
2406
3157
  {
2407
3158
  src: screenshots[0],
@@ -2416,8 +3167,8 @@ function ReportDialog({
2416
3167
  }
2417
3168
  }
2418
3169
  ),
2419
- /* @__PURE__ */ jsx2("span", { style: { fontSize: "11px", color: t2.textMuted, flex: 1 }, children: "Screenshot attached" }),
2420
- /* @__PURE__ */ jsx2(
3170
+ /* @__PURE__ */ jsx3("span", { style: { fontSize: "11px", color: t2.textMuted, flex: 1 }, children: "Screenshot attached" }),
3171
+ /* @__PURE__ */ jsx3(
2421
3172
  "button",
2422
3173
  {
2423
3174
  type: "button",
@@ -2438,7 +3189,7 @@ function ReportDialog({
2438
3189
  ]
2439
3190
  }
2440
3191
  ),
2441
- step === 1 && /* @__PURE__ */ jsx2(
3192
+ step === 1 && /* @__PURE__ */ jsx3(
2442
3193
  "div",
2443
3194
  {
2444
3195
  ref: tileGridRef,
@@ -2448,7 +3199,7 @@ function ReportDialog({
2448
3199
  gridTemplateColumns: "1fr 1fr 1fr",
2449
3200
  gap: "10px"
2450
3201
  },
2451
- children: availableTypes.map((type) => /* @__PURE__ */ jsxs2(
3202
+ children: availableTypes.map((type) => /* @__PURE__ */ jsxs3(
2452
3203
  "button",
2453
3204
  {
2454
3205
  type: "button",
@@ -2478,7 +3229,7 @@ function ReportDialog({
2478
3229
  },
2479
3230
  children: [
2480
3231
  getTypeIcon(type, t2.accent, 22),
2481
- /* @__PURE__ */ jsx2(
3232
+ /* @__PURE__ */ jsx3(
2482
3233
  "span",
2483
3234
  {
2484
3235
  style: {
@@ -2496,8 +3247,8 @@ function ReportDialog({
2496
3247
  ))
2497
3248
  }
2498
3249
  ),
2499
- step === 2 && /* @__PURE__ */ jsxs2(Fragment, { children: [
2500
- /* @__PURE__ */ jsxs2(
3250
+ step === 2 && /* @__PURE__ */ jsxs3(Fragment2, { children: [
3251
+ /* @__PURE__ */ jsxs3(
2501
3252
  "button",
2502
3253
  {
2503
3254
  type: "button",
@@ -2520,11 +3271,11 @@ function ReportDialog({
2520
3271
  children: [
2521
3272
  getTypeIcon(reportType, isRating ? "#f59e0b" : t2.accent, 13),
2522
3273
  getTypeLabel(reportType),
2523
- /* @__PURE__ */ jsx2("span", { style: { color: t2.textMuted, fontWeight: 400 }, children: "\xB7 change" })
3274
+ /* @__PURE__ */ jsx3("span", { style: { color: t2.textMuted, fontWeight: 400 }, children: "\xB7 change" })
2524
3275
  ]
2525
3276
  }
2526
3277
  ),
2527
- isRating && /* @__PURE__ */ jsx2(
3278
+ isRating && /* @__PURE__ */ jsx3(
2528
3279
  "div",
2529
3280
  {
2530
3281
  style: {
@@ -2535,7 +3286,7 @@ function ReportDialog({
2535
3286
  onMouseLeave: () => setHoveredStar(0),
2536
3287
  children: [1, 2, 3, 4, 5].map((star) => {
2537
3288
  const filled = star <= (hoveredStar || rating);
2538
- return /* @__PURE__ */ jsx2(
3289
+ return /* @__PURE__ */ jsx3(
2539
3290
  "button",
2540
3291
  {
2541
3292
  type: "button",
@@ -2552,7 +3303,7 @@ function ReportDialog({
2552
3303
  cursor: "pointer",
2553
3304
  lineHeight: 0
2554
3305
  },
2555
- children: /* @__PURE__ */ jsx2("svg", { width: "30", height: "30", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx2(
3306
+ children: /* @__PURE__ */ jsx3("svg", { width: "30", height: "30", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx3(
2556
3307
  "path",
2557
3308
  {
2558
3309
  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",
@@ -2568,8 +3319,47 @@ function ReportDialog({
2568
3319
  })
2569
3320
  }
2570
3321
  ),
2571
- /* @__PURE__ */ jsxs2("div", { style: { position: "relative" }, children: [
2572
- /* @__PURE__ */ jsx2(
3322
+ assist && !isRating && !assistUsed && /* @__PURE__ */ jsxs3(
3323
+ "button",
3324
+ {
3325
+ type: "button",
3326
+ onClick: () => {
3327
+ setAssistNotice(null);
3328
+ setAssistOpen(true);
3329
+ },
3330
+ style: {
3331
+ display: "inline-flex",
3332
+ alignItems: "center",
3333
+ gap: "6px",
3334
+ marginBottom: "10px",
3335
+ // 8px vertical keeps the tap target at ~32px.
3336
+ padding: "8px 10px",
3337
+ borderRadius: "6px",
3338
+ border: `1px solid ${t2.accent}`,
3339
+ background: "transparent",
3340
+ color: t2.accent,
3341
+ fontSize: "12px",
3342
+ fontWeight: 600,
3343
+ fontFamily: "inherit",
3344
+ cursor: "pointer"
3345
+ },
3346
+ title: "Answer a question or two and the assistant writes the report for you",
3347
+ children: [
3348
+ /* @__PURE__ */ jsx3("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx3(
3349
+ "path",
3350
+ {
3351
+ 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",
3352
+ stroke: t2.accent,
3353
+ strokeWidth: "1.5",
3354
+ strokeLinejoin: "round"
3355
+ }
3356
+ ) }),
3357
+ "Describe it with AI"
3358
+ ]
3359
+ }
3360
+ ),
3361
+ /* @__PURE__ */ jsxs3("div", { style: { position: "relative" }, children: [
3362
+ /* @__PURE__ */ jsx3(
2573
3363
  "textarea",
2574
3364
  {
2575
3365
  ref: textareaRef,
@@ -2610,7 +3400,7 @@ function ReportDialog({
2610
3400
  autoFocus: true
2611
3401
  }
2612
3402
  ),
2613
- (isListening || isTranscribing) && /* @__PURE__ */ jsxs2(
3403
+ (isListening || isTranscribing) && /* @__PURE__ */ jsxs3(
2614
3404
  "span",
2615
3405
  {
2616
3406
  style: {
@@ -2628,7 +3418,7 @@ function ReportDialog({
2628
3418
  zIndex: 1
2629
3419
  },
2630
3420
  children: [
2631
- /* @__PURE__ */ jsx2(
3421
+ /* @__PURE__ */ jsx3(
2632
3422
  "span",
2633
3423
  {
2634
3424
  style: {
@@ -2643,7 +3433,7 @@ function ReportDialog({
2643
3433
  }
2644
3434
  ),
2645
3435
  isTranscribing ? "Transcribing\u2026" : "REC",
2646
- isListening && !isTranscribing && /* @__PURE__ */ jsx2(
3436
+ isListening && !isTranscribing && /* @__PURE__ */ jsx3(
2647
3437
  "span",
2648
3438
  {
2649
3439
  style: {
@@ -2670,7 +3460,7 @@ function ReportDialog({
2670
3460
  dur: "0.55s",
2671
3461
  delay: "0.15s"
2672
3462
  }
2673
- ].map((b, i) => /* @__PURE__ */ jsx2(
3463
+ ].map((b, i) => /* @__PURE__ */ jsx3(
2674
3464
  "span",
2675
3465
  {
2676
3466
  style: {
@@ -2690,18 +3480,18 @@ function ReportDialog({
2690
3480
  ]
2691
3481
  }
2692
3482
  ),
2693
- enhanceText2 && /* @__PURE__ */ jsxs2(
3483
+ enhanceText2 && /* @__PURE__ */ jsxs3(
2694
3484
  "button",
2695
3485
  {
2696
3486
  type: "button",
2697
3487
  onClick: async () => {
2698
- var _a;
3488
+ var _a2;
2699
3489
  if (!description.trim() || isEnhancing) return;
2700
3490
  setIsEnhancing(true);
2701
3491
  try {
2702
3492
  const polished = await enhanceText2(
2703
3493
  description,
2704
- (_a = screenshots[0]) != null ? _a : null
3494
+ (_a2 = screenshots[0]) != null ? _a2 : null
2705
3495
  );
2706
3496
  if (polished && polished !== description) {
2707
3497
  setOriginalDescription(description);
@@ -2735,7 +3525,7 @@ function ReportDialog({
2735
3525
  },
2736
3526
  title: "Polish grammar \u2014 preserves your meaning",
2737
3527
  children: [
2738
- /* @__PURE__ */ jsx2(
3528
+ /* @__PURE__ */ jsx3(
2739
3529
  "svg",
2740
3530
  {
2741
3531
  width: "11",
@@ -2743,7 +3533,7 @@ function ReportDialog({
2743
3533
  viewBox: "0 0 24 24",
2744
3534
  fill: "none",
2745
3535
  "aria-hidden": "true",
2746
- children: /* @__PURE__ */ jsx2(
3536
+ children: /* @__PURE__ */ jsx3(
2747
3537
  "path",
2748
3538
  {
2749
3539
  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",
@@ -2758,7 +3548,7 @@ function ReportDialog({
2758
3548
  ]
2759
3549
  }
2760
3550
  ),
2761
- transcribeAudio2 && /* @__PURE__ */ jsx2(
3551
+ transcribeAudio2 && /* @__PURE__ */ jsx3(
2762
3552
  "button",
2763
3553
  {
2764
3554
  type: "button",
@@ -2784,7 +3574,7 @@ function ReportDialog({
2784
3574
  padding: 0,
2785
3575
  transition: "border-color 0.2s ease, color 0.2s ease"
2786
3576
  },
2787
- children: isListening ? /* @__PURE__ */ jsx2(
3577
+ children: isListening ? /* @__PURE__ */ jsx3(
2788
3578
  "svg",
2789
3579
  {
2790
3580
  width: "12",
@@ -2792,7 +3582,7 @@ function ReportDialog({
2792
3582
  viewBox: "0 0 24 24",
2793
3583
  fill: "currentColor",
2794
3584
  "aria-hidden": "true",
2795
- children: /* @__PURE__ */ jsx2(
3585
+ children: /* @__PURE__ */ jsx3(
2796
3586
  "rect",
2797
3587
  {
2798
3588
  x: "6",
@@ -2803,7 +3593,7 @@ function ReportDialog({
2803
3593
  }
2804
3594
  )
2805
3595
  }
2806
- ) : /* @__PURE__ */ jsxs2(
3596
+ ) : /* @__PURE__ */ jsxs3(
2807
3597
  "svg",
2808
3598
  {
2809
3599
  width: "13",
@@ -2812,7 +3602,7 @@ function ReportDialog({
2812
3602
  fill: "none",
2813
3603
  "aria-hidden": "true",
2814
3604
  children: [
2815
- /* @__PURE__ */ jsx2(
3605
+ /* @__PURE__ */ jsx3(
2816
3606
  "rect",
2817
3607
  {
2818
3608
  x: "9",
@@ -2824,7 +3614,7 @@ function ReportDialog({
2824
3614
  strokeWidth: "1.8"
2825
3615
  }
2826
3616
  ),
2827
- /* @__PURE__ */ jsx2(
3617
+ /* @__PURE__ */ jsx3(
2828
3618
  "path",
2829
3619
  {
2830
3620
  d: "M5 10a7 7 0 0014 0M12 19v3M9 22h6",
@@ -2839,7 +3629,7 @@ function ReportDialog({
2839
3629
  }
2840
3630
  )
2841
3631
  ] }),
2842
- transcribeAudio2 && !isListening && !isTranscribing && /* @__PURE__ */ jsxs2(
3632
+ transcribeAudio2 && !isListening && !isTranscribing && /* @__PURE__ */ jsxs3(
2843
3633
  "div",
2844
3634
  {
2845
3635
  style: {
@@ -2853,16 +3643,16 @@ function ReportDialog({
2853
3643
  userSelect: "none"
2854
3644
  },
2855
3645
  children: [
2856
- /* @__PURE__ */ jsxs2("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2857
- /* @__PURE__ */ jsx2("path", { d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z" }),
2858
- /* @__PURE__ */ jsx2("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
2859
- /* @__PURE__ */ jsx2("line", { x1: "12", x2: "12", y1: "19", y2: "22" })
3646
+ /* @__PURE__ */ jsxs3("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3647
+ /* @__PURE__ */ jsx3("path", { d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z" }),
3648
+ /* @__PURE__ */ jsx3("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
3649
+ /* @__PURE__ */ jsx3("line", { x1: "12", x2: "12", y1: "19", y2: "22" })
2860
3650
  ] }),
2861
3651
  "Hold Space to speak \u2014 we'll transcribe it"
2862
3652
  ]
2863
3653
  }
2864
3654
  ),
2865
- isEnhanced && originalDescription !== null && /* @__PURE__ */ jsxs2(
3655
+ isEnhanced && originalDescription !== null && /* @__PURE__ */ jsxs3(
2866
3656
  "div",
2867
3657
  {
2868
3658
  style: {
@@ -2876,7 +3666,7 @@ function ReportDialog({
2876
3666
  border: `1px solid ${t2.accent}40`
2877
3667
  },
2878
3668
  children: [
2879
- /* @__PURE__ */ jsx2(
3669
+ /* @__PURE__ */ jsx3(
2880
3670
  "svg",
2881
3671
  {
2882
3672
  width: "12",
@@ -2884,7 +3674,7 @@ function ReportDialog({
2884
3674
  viewBox: "0 0 24 24",
2885
3675
  fill: "none",
2886
3676
  style: { flexShrink: 0 },
2887
- children: /* @__PURE__ */ jsx2(
3677
+ children: /* @__PURE__ */ jsx3(
2888
3678
  "path",
2889
3679
  {
2890
3680
  d: "M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3z",
@@ -2895,7 +3685,7 @@ function ReportDialog({
2895
3685
  )
2896
3686
  }
2897
3687
  ),
2898
- /* @__PURE__ */ jsx2(
3688
+ /* @__PURE__ */ jsx3(
2899
3689
  "span",
2900
3690
  {
2901
3691
  style: {
@@ -2906,7 +3696,7 @@ function ReportDialog({
2906
3696
  children: "AI enhanced"
2907
3697
  }
2908
3698
  ),
2909
- /* @__PURE__ */ jsx2(
3699
+ /* @__PURE__ */ jsx3(
2910
3700
  "button",
2911
3701
  {
2912
3702
  type: "button",
@@ -2928,7 +3718,7 @@ function ReportDialog({
2928
3718
  children: "Keep"
2929
3719
  }
2930
3720
  ),
2931
- /* @__PURE__ */ jsx2(
3721
+ /* @__PURE__ */ jsx3(
2932
3722
  "button",
2933
3723
  {
2934
3724
  type: "button",
@@ -2954,7 +3744,7 @@ function ReportDialog({
2954
3744
  ]
2955
3745
  }
2956
3746
  ),
2957
- voiceError && /* @__PURE__ */ jsx2(
3747
+ voiceError && /* @__PURE__ */ jsx3(
2958
3748
  "p",
2959
3749
  {
2960
3750
  style: {
@@ -2966,8 +3756,21 @@ function ReportDialog({
2966
3756
  children: voiceError
2967
3757
  }
2968
3758
  ),
2969
- !isRating && /* @__PURE__ */ jsxs2("div", { style: { marginTop: "10px" }, children: [
2970
- /* @__PURE__ */ jsxs2(
3759
+ assistNotice && /* @__PURE__ */ jsx3(
3760
+ "p",
3761
+ {
3762
+ style: {
3763
+ color: t2.textMuted,
3764
+ fontSize: "12px",
3765
+ marginTop: "6px",
3766
+ marginBottom: 0,
3767
+ lineHeight: 1.5
3768
+ },
3769
+ children: assistNotice
3770
+ }
3771
+ ),
3772
+ !isRating && /* @__PURE__ */ jsxs3("div", { style: { marginTop: "10px" }, children: [
3773
+ /* @__PURE__ */ jsxs3(
2971
3774
  "span",
2972
3775
  {
2973
3776
  style: {
@@ -2983,7 +3786,7 @@ function ReportDialog({
2983
3786
  ]
2984
3787
  }
2985
3788
  ),
2986
- screenshots.length > 0 && /* @__PURE__ */ jsx2(
3789
+ screenshots.length > 0 && /* @__PURE__ */ jsx3(
2987
3790
  "div",
2988
3791
  {
2989
3792
  style: {
@@ -2992,7 +3795,7 @@ function ReportDialog({
2992
3795
  gap: "8px",
2993
3796
  marginBottom: "8px"
2994
3797
  },
2995
- children: screenshots.map((src, i) => /* @__PURE__ */ jsxs2(
3798
+ children: screenshots.map((src, i) => /* @__PURE__ */ jsxs3(
2996
3799
  "div",
2997
3800
  {
2998
3801
  style: {
@@ -3001,7 +3804,7 @@ function ReportDialog({
3001
3804
  height: "56px"
3002
3805
  },
3003
3806
  children: [
3004
- /* @__PURE__ */ jsx2(
3807
+ /* @__PURE__ */ jsx3(
3005
3808
  "img",
3006
3809
  {
3007
3810
  src,
@@ -3019,7 +3822,7 @@ function ReportDialog({
3019
3822
  }
3020
3823
  }
3021
3824
  ),
3022
- /* @__PURE__ */ jsx2(
3825
+ /* @__PURE__ */ jsx3(
3023
3826
  "button",
3024
3827
  {
3025
3828
  type: "button",
@@ -3045,14 +3848,14 @@ function ReportDialog({
3045
3848
  alignItems: "center",
3046
3849
  justifyContent: "center"
3047
3850
  },
3048
- children: /* @__PURE__ */ jsx2(
3851
+ children: /* @__PURE__ */ jsx3(
3049
3852
  "svg",
3050
3853
  {
3051
3854
  width: "8",
3052
3855
  height: "8",
3053
3856
  viewBox: "0 0 10 10",
3054
3857
  fill: "none",
3055
- children: /* @__PURE__ */ jsx2(
3858
+ children: /* @__PURE__ */ jsx3(
3056
3859
  "path",
3057
3860
  {
3058
3861
  d: "M1 1L9 9M9 1L1 9",
@@ -3065,7 +3868,7 @@ function ReportDialog({
3065
3868
  )
3066
3869
  }
3067
3870
  ),
3068
- /* @__PURE__ */ jsx2(
3871
+ /* @__PURE__ */ jsx3(
3069
3872
  "button",
3070
3873
  {
3071
3874
  type: "button",
@@ -3090,14 +3893,14 @@ function ReportDialog({
3090
3893
  justifyContent: "center",
3091
3894
  boxShadow: "0 2px 8px rgba(0,0,0,0.45)"
3092
3895
  },
3093
- children: /* @__PURE__ */ jsx2(
3896
+ children: /* @__PURE__ */ jsx3(
3094
3897
  "svg",
3095
3898
  {
3096
3899
  width: "12",
3097
3900
  height: "12",
3098
3901
  viewBox: "0 0 24 24",
3099
3902
  fill: "none",
3100
- children: /* @__PURE__ */ jsx2(
3903
+ children: /* @__PURE__ */ jsx3(
3101
3904
  "path",
3102
3905
  {
3103
3906
  d: "M12 20h9M16.5 3.5a2.12 2.12 0 013 3L7 19l-4 1 1-4L16.5 3.5z",
@@ -3117,7 +3920,7 @@ function ReportDialog({
3117
3920
  ))
3118
3921
  }
3119
3922
  ),
3120
- attachments.length > 0 && /* @__PURE__ */ jsx2(
3923
+ attachments.length > 0 && /* @__PURE__ */ jsx3(
3121
3924
  "div",
3122
3925
  {
3123
3926
  style: {
@@ -3126,7 +3929,7 @@ function ReportDialog({
3126
3929
  gap: "6px",
3127
3930
  marginBottom: "8px"
3128
3931
  },
3129
- children: attachments.map((a, i) => /* @__PURE__ */ jsxs2(
3932
+ children: attachments.map((a, i) => /* @__PURE__ */ jsxs3(
3130
3933
  "div",
3131
3934
  {
3132
3935
  style: {
@@ -3138,7 +3941,7 @@ function ReportDialog({
3138
3941
  border: `1px solid ${t2.border}`
3139
3942
  },
3140
3943
  children: [
3141
- /* @__PURE__ */ jsxs2(
3944
+ /* @__PURE__ */ jsxs3(
3142
3945
  "svg",
3143
3946
  {
3144
3947
  width: "14",
@@ -3147,7 +3950,7 @@ function ReportDialog({
3147
3950
  fill: "none",
3148
3951
  style: { flexShrink: 0, opacity: 0.6 },
3149
3952
  children: [
3150
- /* @__PURE__ */ jsx2(
3953
+ /* @__PURE__ */ jsx3(
3151
3954
  "path",
3152
3955
  {
3153
3956
  d: "M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z",
@@ -3157,7 +3960,7 @@ function ReportDialog({
3157
3960
  strokeLinejoin: "round"
3158
3961
  }
3159
3962
  ),
3160
- /* @__PURE__ */ jsx2(
3963
+ /* @__PURE__ */ jsx3(
3161
3964
  "path",
3162
3965
  {
3163
3966
  d: "M14 2v6h6",
@@ -3170,7 +3973,7 @@ function ReportDialog({
3170
3973
  ]
3171
3974
  }
3172
3975
  ),
3173
- /* @__PURE__ */ jsx2(
3976
+ /* @__PURE__ */ jsx3(
3174
3977
  "span",
3175
3978
  {
3176
3979
  style: {
@@ -3184,7 +3987,7 @@ function ReportDialog({
3184
3987
  children: a.name
3185
3988
  }
3186
3989
  ),
3187
- /* @__PURE__ */ jsxs2(
3990
+ /* @__PURE__ */ jsxs3(
3188
3991
  "span",
3189
3992
  {
3190
3993
  style: { fontSize: "10px", color: t2.textMuted },
@@ -3194,7 +3997,7 @@ function ReportDialog({
3194
3997
  ]
3195
3998
  }
3196
3999
  ),
3197
- /* @__PURE__ */ jsx2(
4000
+ /* @__PURE__ */ jsx3(
3198
4001
  "button",
3199
4002
  {
3200
4003
  type: "button",
@@ -3218,14 +4021,14 @@ function ReportDialog({
3218
4021
  justifyContent: "center",
3219
4022
  flexShrink: 0
3220
4023
  },
3221
- children: /* @__PURE__ */ jsx2(
4024
+ children: /* @__PURE__ */ jsx3(
3222
4025
  "svg",
3223
4026
  {
3224
4027
  width: "8",
3225
4028
  height: "8",
3226
4029
  viewBox: "0 0 10 10",
3227
4030
  fill: "none",
3228
- children: /* @__PURE__ */ jsx2(
4031
+ children: /* @__PURE__ */ jsx3(
3229
4032
  "path",
3230
4033
  {
3231
4034
  d: "M1 1L9 9M9 1L1 9",
@@ -3244,12 +4047,12 @@ function ReportDialog({
3244
4047
  ))
3245
4048
  }
3246
4049
  ),
3247
- /* @__PURE__ */ jsx2(
4050
+ /* @__PURE__ */ jsx3(
3248
4051
  "div",
3249
4052
  {
3250
4053
  onClick: () => {
3251
- var _a;
3252
- return (_a = fileInputRef.current) == null ? void 0 : _a.click();
4054
+ var _a2;
4055
+ return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
3253
4056
  },
3254
4057
  onDrop: (e) => {
3255
4058
  e.preventDefault();
@@ -3270,7 +4073,7 @@ function ReportDialog({
3270
4073
  background: screenshotDragOver ? isDark ? "rgba(34,211,238,0.06)" : "rgba(8,145,178,0.04)" : "transparent",
3271
4074
  transition: "border-color 0.15s ease, background 0.15s ease"
3272
4075
  },
3273
- children: screenshots.length + attachments.length > 0 ? /* @__PURE__ */ jsx2(
4076
+ children: screenshots.length + attachments.length > 0 ? /* @__PURE__ */ jsx3(
3274
4077
  "p",
3275
4078
  {
3276
4079
  style: {
@@ -3281,8 +4084,8 @@ function ReportDialog({
3281
4084
  },
3282
4085
  children: screenshotDragOver ? "Drop to attach" : "+ Add more \xB7 Drag & drop \xB7 Paste"
3283
4086
  }
3284
- ) : /* @__PURE__ */ jsxs2(Fragment, { children: [
3285
- /* @__PURE__ */ jsxs2(
4087
+ ) : /* @__PURE__ */ jsxs3(Fragment2, { children: [
4088
+ /* @__PURE__ */ jsxs3(
3286
4089
  "svg",
3287
4090
  {
3288
4091
  width: "22",
@@ -3295,7 +4098,7 @@ function ReportDialog({
3295
4098
  opacity: 0.45
3296
4099
  },
3297
4100
  children: [
3298
- /* @__PURE__ */ jsx2(
4101
+ /* @__PURE__ */ jsx3(
3299
4102
  "rect",
3300
4103
  {
3301
4104
  x: "3",
@@ -3307,7 +4110,7 @@ function ReportDialog({
3307
4110
  strokeWidth: "1.5"
3308
4111
  }
3309
4112
  ),
3310
- /* @__PURE__ */ jsx2(
4113
+ /* @__PURE__ */ jsx3(
3311
4114
  "circle",
3312
4115
  {
3313
4116
  cx: "8.5",
@@ -3317,7 +4120,7 @@ function ReportDialog({
3317
4120
  strokeWidth: "1.5"
3318
4121
  }
3319
4122
  ),
3320
- /* @__PURE__ */ jsx2(
4123
+ /* @__PURE__ */ jsx3(
3321
4124
  "path",
3322
4125
  {
3323
4126
  d: "M21 15l-5-5L5 21",
@@ -3330,7 +4133,7 @@ function ReportDialog({
3330
4133
  ]
3331
4134
  }
3332
4135
  ),
3333
- /* @__PURE__ */ jsx2(
4136
+ /* @__PURE__ */ jsx3(
3334
4137
  "p",
3335
4138
  {
3336
4139
  style: {
@@ -3342,7 +4145,7 @@ function ReportDialog({
3342
4145
  children: screenshotDragOver ? "Drop to attach" : "Add screenshots or files"
3343
4146
  }
3344
4147
  ),
3345
- /* @__PURE__ */ jsx2(
4148
+ /* @__PURE__ */ jsx3(
3346
4149
  "p",
3347
4150
  {
3348
4151
  style: {
@@ -3357,8 +4160,8 @@ function ReportDialog({
3357
4160
  }
3358
4161
  )
3359
4162
  ] }),
3360
- showSeverity && reportType === "BUG" && /* @__PURE__ */ jsxs2("div", { style: { marginTop: "10px" }, children: [
3361
- /* @__PURE__ */ jsx2(
4163
+ showSeverity && reportType === "BUG" && /* @__PURE__ */ jsxs3("div", { style: { marginTop: "10px" }, children: [
4164
+ /* @__PURE__ */ jsx3(
3362
4165
  "span",
3363
4166
  {
3364
4167
  style: {
@@ -3370,7 +4173,7 @@ function ReportDialog({
3370
4173
  children: "Severity"
3371
4174
  }
3372
4175
  ),
3373
- /* @__PURE__ */ jsx2("div", { style: { display: "flex", gap: "6px" }, children: ["low", "medium", "high"].map((s) => /* @__PURE__ */ jsx2(
4176
+ /* @__PURE__ */ jsx3("div", { style: { display: "flex", gap: "6px" }, children: ["low", "medium", "high"].map((s) => /* @__PURE__ */ jsx3(
3374
4177
  "button",
3375
4178
  {
3376
4179
  type: "button",
@@ -3394,7 +4197,7 @@ function ReportDialog({
3394
4197
  s
3395
4198
  )) })
3396
4199
  ] }),
3397
- validationError && /* @__PURE__ */ jsx2(
4200
+ validationError && /* @__PURE__ */ jsx3(
3398
4201
  "p",
3399
4202
  {
3400
4203
  style: {
@@ -3405,7 +4208,7 @@ function ReportDialog({
3405
4208
  children: validationError
3406
4209
  }
3407
4210
  ),
3408
- /* @__PURE__ */ jsx2(
4211
+ /* @__PURE__ */ jsx3(
3409
4212
  "button",
3410
4213
  {
3411
4214
  type: "button",
@@ -3432,7 +4235,7 @@ function ReportDialog({
3432
4235
  ] })
3433
4236
  }
3434
4237
  ),
3435
- /* @__PURE__ */ jsxs2(
4238
+ /* @__PURE__ */ jsxs3(
3436
4239
  "div",
3437
4240
  {
3438
4241
  style: {
@@ -3444,8 +4247,8 @@ function ReportDialog({
3444
4247
  gap: "12px"
3445
4248
  },
3446
4249
  children: [
3447
- /* @__PURE__ */ jsx2(ReporterChip, { reporter, t: t2 }),
3448
- /* @__PURE__ */ jsx2(
4250
+ /* @__PURE__ */ jsx3(ReporterChip, { reporter, t: t2 }),
4251
+ /* @__PURE__ */ jsx3(
3449
4252
  "span",
3450
4253
  {
3451
4254
  style: {
@@ -3467,7 +4270,7 @@ function ReportDialog({
3467
4270
  ),
3468
4271
  document.body
3469
4272
  ),
3470
- /* @__PURE__ */ jsx2(
4273
+ /* @__PURE__ */ jsx3(
3471
4274
  "input",
3472
4275
  {
3473
4276
  ref: fileInputRef,
@@ -3478,8 +4281,8 @@ function ReportDialog({
3478
4281
  style: { display: "none" }
3479
4282
  }
3480
4283
  ),
3481
- isOpen && previewIndex !== null && screenshots[previewIndex] && createPortal(
3482
- /* @__PURE__ */ jsxs2(
4284
+ isOpen && previewIndex !== null && screenshots[previewIndex] && createPortal2(
4285
+ /* @__PURE__ */ jsxs3(
3483
4286
  "div",
3484
4287
  {
3485
4288
  "data-glitchgrab-layer": "",
@@ -3501,7 +4304,7 @@ function ReportDialog({
3501
4304
  },
3502
4305
  onMouseDown: (e) => e.stopPropagation(),
3503
4306
  children: [
3504
- /* @__PURE__ */ jsxs2(
4307
+ /* @__PURE__ */ jsxs3(
3505
4308
  "div",
3506
4309
  {
3507
4310
  ref: previewImgRef,
@@ -3513,7 +4316,7 @@ function ReportDialog({
3513
4316
  },
3514
4317
  onClick: (e) => e.stopPropagation(),
3515
4318
  children: [
3516
- /* @__PURE__ */ jsx2(
4319
+ /* @__PURE__ */ jsx3(
3517
4320
  "div",
3518
4321
  {
3519
4322
  ref: previewScrollRef,
@@ -3532,7 +4335,7 @@ function ReportDialog({
3532
4335
  touchAction: "none",
3533
4336
  cursor: "grab"
3534
4337
  } : { maxWidth: "100%", lineHeight: 0 },
3535
- children: /* @__PURE__ */ jsx2(
4338
+ children: /* @__PURE__ */ jsx3(
3536
4339
  "img",
3537
4340
  {
3538
4341
  ref: previewImgElRef,
@@ -3560,7 +4363,7 @@ function ReportDialog({
3560
4363
  )
3561
4364
  }
3562
4365
  ),
3563
- /* @__PURE__ */ jsxs2(
4366
+ /* @__PURE__ */ jsxs3(
3564
4367
  "button",
3565
4368
  {
3566
4369
  type: "button",
@@ -3588,7 +4391,7 @@ function ReportDialog({
3588
4391
  animation: "gg-pulse 2s ease-in-out infinite"
3589
4392
  },
3590
4393
  children: [
3591
- /* @__PURE__ */ jsx2("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx2(
4394
+ /* @__PURE__ */ jsx3("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx3(
3592
4395
  "path",
3593
4396
  {
3594
4397
  d: "M12 20h9M16.5 3.5a2.12 2.12 0 013 3L7 19l-4 1 1-4L16.5 3.5z",
@@ -3605,7 +4408,7 @@ function ReportDialog({
3605
4408
  ]
3606
4409
  }
3607
4410
  ),
3608
- /* @__PURE__ */ jsx2(
4411
+ /* @__PURE__ */ jsx3(
3609
4412
  "div",
3610
4413
  {
3611
4414
  style: {
@@ -3614,7 +4417,7 @@ function ReportDialog({
3614
4417
  alignItems: "center",
3615
4418
  gap: "12px"
3616
4419
  },
3617
- children: /* @__PURE__ */ jsx2(
4420
+ children: /* @__PURE__ */ jsx3(
3618
4421
  "span",
3619
4422
  {
3620
4423
  style: {
@@ -3635,8 +4438,8 @@ function ReportDialog({
3635
4438
  ),
3636
4439
  document.body
3637
4440
  ),
3638
- isOpen && annotatingIndex !== null && screenshots[annotatingIndex] && createPortal(
3639
- /* @__PURE__ */ jsx2(
4441
+ isOpen && annotatingIndex !== null && screenshots[annotatingIndex] && createPortal2(
4442
+ /* @__PURE__ */ jsx3(
3640
4443
  AnnotationCanvas,
3641
4444
  {
3642
4445
  imageSrc: screenshots[annotatingIndex],
@@ -3650,6 +4453,52 @@ function ReportDialog({
3650
4453
  }
3651
4454
  ),
3652
4455
  document.body
4456
+ ),
4457
+ isOpen && sheetUp && /* @__PURE__ */ jsx3(
4458
+ AssistSheet,
4459
+ {
4460
+ assist,
4461
+ theme: {
4462
+ bg: t2.bg,
4463
+ bgSecondary: t2.bgSecondary,
4464
+ border: t2.border,
4465
+ text: t2.text,
4466
+ textMuted: t2.textMuted,
4467
+ inputBg: t2.inputBg,
4468
+ inputBorder: t2.inputBorder,
4469
+ accent: t2.accent,
4470
+ accentText: t2.accentText
4471
+ },
4472
+ screenshot: (_a = screenshots[0]) != null ? _a : null,
4473
+ attachmentCount: screenshots.length + attachments.length,
4474
+ context: { ...assistContext != null ? assistContext : {}, reportType },
4475
+ reportTypeLabel: getTypeLabel(reportType),
4476
+ projectSlot: headerSlot,
4477
+ reporterName: (_b = reporter == null ? void 0 : reporter.name) != null ? _b : null,
4478
+ description,
4479
+ onDescriptionChange: (value) => {
4480
+ setDescription(value);
4481
+ if (validationError) setValidationError(null);
4482
+ },
4483
+ severity,
4484
+ onSeverityChange: setSeverity,
4485
+ showSeverity,
4486
+ isSubmitting,
4487
+ submitted,
4488
+ onSend: () => void handleSubmit(),
4489
+ onDegrade: (message) => {
4490
+ setAssistOpen(false);
4491
+ setAssistUsed(true);
4492
+ setAssistNotice(message);
4493
+ },
4494
+ onClose: () => {
4495
+ setAssistOpen(false);
4496
+ requestAnimationFrame(() => {
4497
+ var _a2;
4498
+ return (_a2 = textareaRef.current) == null ? void 0 : _a2.focus();
4499
+ });
4500
+ }
4501
+ }
3653
4502
  )
3654
4503
  ] });
3655
4504
  }
@@ -3703,7 +4552,7 @@ function getTypeIcon(type, color, size = 24) {
3703
4552
  };
3704
4553
  switch (type) {
3705
4554
  case "RATING":
3706
- return /* @__PURE__ */ jsx2("svg", { ...props, children: /* @__PURE__ */ jsx2(
4555
+ return /* @__PURE__ */ jsx3("svg", { ...props, children: /* @__PURE__ */ jsx3(
3707
4556
  "path",
3708
4557
  {
3709
4558
  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",
@@ -3713,7 +4562,7 @@ function getTypeIcon(type, color, size = 24) {
3713
4562
  }
3714
4563
  ) });
3715
4564
  case "BUG":
3716
- return /* @__PURE__ */ jsx2("svg", { ...props, children: /* @__PURE__ */ jsx2(
4565
+ return /* @__PURE__ */ jsx3("svg", { ...props, children: /* @__PURE__ */ jsx3(
3717
4566
  "path",
3718
4567
  {
3719
4568
  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",
@@ -3723,7 +4572,7 @@ function getTypeIcon(type, color, size = 24) {
3723
4572
  }
3724
4573
  ) });
3725
4574
  case "FEATURE_REQUEST":
3726
- return /* @__PURE__ */ jsx2("svg", { ...props, children: /* @__PURE__ */ jsx2(
4575
+ return /* @__PURE__ */ jsx3("svg", { ...props, children: /* @__PURE__ */ jsx3(
3727
4576
  "path",
3728
4577
  {
3729
4578
  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",
@@ -3733,8 +4582,8 @@ function getTypeIcon(type, color, size = 24) {
3733
4582
  }
3734
4583
  ) });
3735
4584
  case "UI_IMPROVEMENT":
3736
- return /* @__PURE__ */ jsxs2("svg", { ...props, children: [
3737
- /* @__PURE__ */ jsx2(
4585
+ return /* @__PURE__ */ jsxs3("svg", { ...props, children: [
4586
+ /* @__PURE__ */ jsx3(
3738
4587
  "rect",
3739
4588
  {
3740
4589
  x: "3",
@@ -3746,7 +4595,7 @@ function getTypeIcon(type, color, size = 24) {
3746
4595
  strokeWidth: "1.5"
3747
4596
  }
3748
4597
  ),
3749
- /* @__PURE__ */ jsx2(
4598
+ /* @__PURE__ */ jsx3(
3750
4599
  "path",
3751
4600
  {
3752
4601
  d: "M3 9h18M9 21V9",
@@ -3757,7 +4606,7 @@ function getTypeIcon(type, color, size = 24) {
3757
4606
  )
3758
4607
  ] });
3759
4608
  case "PERFORMANCE":
3760
- return /* @__PURE__ */ jsx2("svg", { ...props, children: /* @__PURE__ */ jsx2(
4609
+ return /* @__PURE__ */ jsx3("svg", { ...props, children: /* @__PURE__ */ jsx3(
3761
4610
  "path",
3762
4611
  {
3763
4612
  d: "M12 21a9 9 0 100-18 9 9 0 000 18zM12 12l4-4M12 7v.01",
@@ -3768,7 +4617,7 @@ function getTypeIcon(type, color, size = 24) {
3768
4617
  }
3769
4618
  ) });
3770
4619
  case "SECURITY":
3771
- return /* @__PURE__ */ jsx2("svg", { ...props, children: /* @__PURE__ */ jsx2(
4620
+ return /* @__PURE__ */ jsx3("svg", { ...props, children: /* @__PURE__ */ jsx3(
3772
4621
  "path",
3773
4622
  {
3774
4623
  d: "M12 3l7 3v5c0 4.5-3 8.5-7 10-4-1.5-7-5.5-7-10V6l7-3z",
@@ -3778,9 +4627,9 @@ function getTypeIcon(type, color, size = 24) {
3778
4627
  }
3779
4628
  ) });
3780
4629
  case "QUESTION":
3781
- return /* @__PURE__ */ jsxs2("svg", { ...props, children: [
3782
- /* @__PURE__ */ jsx2("circle", { cx: "12", cy: "12", r: "10", stroke: color, strokeWidth: "1.5" }),
3783
- /* @__PURE__ */ jsx2(
4630
+ return /* @__PURE__ */ jsxs3("svg", { ...props, children: [
4631
+ /* @__PURE__ */ jsx3("circle", { cx: "12", cy: "12", r: "10", stroke: color, strokeWidth: "1.5" }),
4632
+ /* @__PURE__ */ jsx3(
3784
4633
  "path",
3785
4634
  {
3786
4635
  d: "M9.09 9a3 3 0 015.83 1c0 2-3 3-3 3M12 17h.01",
@@ -3792,7 +4641,7 @@ function getTypeIcon(type, color, size = 24) {
3792
4641
  )
3793
4642
  ] });
3794
4643
  case "OTHER":
3795
- return /* @__PURE__ */ jsx2("svg", { ...props, children: /* @__PURE__ */ jsx2(
4644
+ return /* @__PURE__ */ jsx3("svg", { ...props, children: /* @__PURE__ */ jsx3(
3796
4645
  "path",
3797
4646
  {
3798
4647
  d: "M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2v10z",
@@ -3805,8 +4654,8 @@ function getTypeIcon(type, color, size = 24) {
3805
4654
  }
3806
4655
 
3807
4656
  // src/booking-dialog.tsx
3808
- import { useCallback, useEffect as useEffect3, useMemo, useState as useState3 } from "react";
3809
- import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
4657
+ import { useCallback, useEffect as useEffect4, useMemo, useState as useState4 } from "react";
4658
+ import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
3810
4659
  var t = {
3811
4660
  bg: "#141414",
3812
4661
  surface: "#1c1c1c",
@@ -3843,23 +4692,23 @@ function BookingDialog({
3843
4692
  onClose
3844
4693
  }) {
3845
4694
  var _a;
3846
- const [step, setStep] = useState3("slots");
3847
- const [slots, setSlots] = useState3(null);
3848
- const [heading, setHeading] = useState3({
4695
+ const [step, setStep] = useState4("slots");
4696
+ const [slots, setSlots] = useState4(null);
4697
+ const [heading, setHeading] = useState4({
3849
4698
  title: "Book a demo",
3850
4699
  description: null
3851
4700
  });
3852
- const [whatsappUrl, setWhatsappUrl] = useState3(null);
3853
- const [selected, setSelected] = useState3(null);
3854
- const [name, setName] = useState3("");
3855
- const [email, setEmail] = useState3("");
3856
- const [phone, setPhone] = useState3("");
3857
- const [note, setNote] = useState3("");
3858
- const [code, setCode] = useState3("");
3859
- const [bookingId, setBookingId] = useState3(null);
3860
- const [meetUrl, setMeetUrl] = useState3(null);
3861
- const [busy, setBusy] = useState3(false);
3862
- const [error, setError] = useState3(null);
4701
+ const [whatsappUrl, setWhatsappUrl] = useState4(null);
4702
+ const [selected, setSelected] = useState4(null);
4703
+ const [name, setName] = useState4("");
4704
+ const [email, setEmail] = useState4("");
4705
+ const [phone, setPhone] = useState4("");
4706
+ const [note, setNote] = useState4("");
4707
+ const [code, setCode] = useState4("");
4708
+ const [bookingId, setBookingId] = useState4(null);
4709
+ const [meetUrl, setMeetUrl] = useState4(null);
4710
+ const [busy, setBusy] = useState4(false);
4711
+ const [error, setError] = useState4(null);
3863
4712
  const headers = useMemo(
3864
4713
  () => ({ Authorization: `Bearer ${token}`, "Content-Type": "application/json" }),
3865
4714
  [token]
@@ -3889,7 +4738,7 @@ function BookingDialog({
3889
4738
  setSlots([]);
3890
4739
  }
3891
4740
  }, [baseUrl, headers]);
3892
- useEffect3(() => {
4741
+ useEffect4(() => {
3893
4742
  if (!open) return;
3894
4743
  setStep("slots");
3895
4744
  setSelected(null);
@@ -3898,7 +4747,7 @@ function BookingDialog({
3898
4747
  setError(null);
3899
4748
  void loadSlots();
3900
4749
  }, [open, loadSlots]);
3901
- useEffect3(() => {
4750
+ useEffect4(() => {
3902
4751
  if (!open) return;
3903
4752
  const onKey = (e) => {
3904
4753
  if (e.key === "Escape") onClose();
@@ -3968,7 +4817,7 @@ function BookingDialog({
3968
4817
  }
3969
4818
  }
3970
4819
  const canSubmitDetails = name.trim() && email.includes("@") && phone.replace(/\D/g, "").length >= 8;
3971
- return /* @__PURE__ */ jsx3(
4820
+ return /* @__PURE__ */ jsx4(
3972
4821
  "div",
3973
4822
  {
3974
4823
  onClick: (e) => {
@@ -3985,7 +4834,7 @@ function BookingDialog({
3985
4834
  padding: 16,
3986
4835
  fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
3987
4836
  },
3988
- children: /* @__PURE__ */ jsxs3(
4837
+ children: /* @__PURE__ */ jsxs4(
3989
4838
  "div",
3990
4839
  {
3991
4840
  role: "dialog",
@@ -4003,7 +4852,7 @@ function BookingDialog({
4003
4852
  overflow: "hidden"
4004
4853
  },
4005
4854
  children: [
4006
- /* @__PURE__ */ jsxs3(
4855
+ /* @__PURE__ */ jsxs4(
4007
4856
  "div",
4008
4857
  {
4009
4858
  style: {
@@ -4015,11 +4864,11 @@ function BookingDialog({
4015
4864
  gap: 12
4016
4865
  },
4017
4866
  children: [
4018
- /* @__PURE__ */ jsxs3("div", { children: [
4019
- /* @__PURE__ */ jsx3("div", { style: { fontSize: 15, fontWeight: 600 }, children: heading.title }),
4020
- heading.description && /* @__PURE__ */ jsx3("div", { style: { fontSize: 12, color: t.muted, marginTop: 2 }, children: heading.description })
4867
+ /* @__PURE__ */ jsxs4("div", { children: [
4868
+ /* @__PURE__ */ jsx4("div", { style: { fontSize: 15, fontWeight: 600 }, children: heading.title }),
4869
+ heading.description && /* @__PURE__ */ jsx4("div", { style: { fontSize: 12, color: t.muted, marginTop: 2 }, children: heading.description })
4021
4870
  ] }),
4022
- /* @__PURE__ */ jsx3(
4871
+ /* @__PURE__ */ jsx4(
4023
4872
  "button",
4024
4873
  {
4025
4874
  onClick: onClose,
@@ -4031,10 +4880,10 @@ function BookingDialog({
4031
4880
  ]
4032
4881
  }
4033
4882
  ),
4034
- /* @__PURE__ */ jsxs3("div", { style: { padding: 18, overflowY: "auto", flex: "1 1 auto" }, children: [
4035
- error && /* @__PURE__ */ jsx3("div", { style: { color: t.danger, fontSize: 12, marginBottom: 12, lineHeight: 1.5 }, children: error }),
4036
- step === "slots" && /* @__PURE__ */ jsxs3(Fragment2, { children: [
4037
- whatsappUrl && /* @__PURE__ */ jsxs3(
4883
+ /* @__PURE__ */ jsxs4("div", { style: { padding: 18, overflowY: "auto", flex: "1 1 auto" }, children: [
4884
+ error && /* @__PURE__ */ jsx4("div", { style: { color: t.danger, fontSize: 12, marginBottom: 12, lineHeight: 1.5 }, children: error }),
4885
+ step === "slots" && /* @__PURE__ */ jsxs4(Fragment3, { children: [
4886
+ whatsappUrl && /* @__PURE__ */ jsxs4(
4038
4887
  "a",
4039
4888
  {
4040
4889
  href: whatsappUrl,
@@ -4053,15 +4902,15 @@ function BookingDialog({
4053
4902
  },
4054
4903
  children: [
4055
4904
  "\u{1F4AC} Rather book on WhatsApp?",
4056
- /* @__PURE__ */ jsx3("span", { style: { display: "block", fontSize: 11, color: t.muted, marginTop: 2 }, children: "We'll ask the same questions in chat." })
4905
+ /* @__PURE__ */ jsx4("span", { style: { display: "block", fontSize: 11, color: t.muted, marginTop: 2 }, children: "We'll ask the same questions in chat." })
4057
4906
  ]
4058
4907
  }
4059
4908
  ),
4060
- slots === null && /* @__PURE__ */ jsx3("div", { style: { color: t.muted, fontSize: 13 }, children: "Finding times\u2026" }),
4061
- (slots == null ? void 0 : slots.length) === 0 && !error && /* @__PURE__ */ jsx3("div", { style: { color: t.muted, fontSize: 13 }, children: "No times available right now." }),
4062
- [...byDay.entries()].map(([day, daySlots]) => /* @__PURE__ */ jsxs3("div", { style: { marginBottom: 18 }, children: [
4063
- /* @__PURE__ */ jsx3("div", { style: { fontSize: 11, color: t.muted, marginBottom: 8, textTransform: "uppercase", letterSpacing: ".6px" }, children: formatDay(daySlots[0].startsAt) }),
4064
- /* @__PURE__ */ jsx3("div", { style: { display: "flex", flexWrap: "wrap", gap: 8 }, children: daySlots.map((slot) => /* @__PURE__ */ jsx3(
4909
+ slots === null && /* @__PURE__ */ jsx4("div", { style: { color: t.muted, fontSize: 13 }, children: "Finding times\u2026" }),
4910
+ (slots == null ? void 0 : slots.length) === 0 && !error && /* @__PURE__ */ jsx4("div", { style: { color: t.muted, fontSize: 13 }, children: "No times available right now." }),
4911
+ [...byDay.entries()].map(([day, daySlots]) => /* @__PURE__ */ jsxs4("div", { style: { marginBottom: 18 }, children: [
4912
+ /* @__PURE__ */ jsx4("div", { style: { fontSize: 11, color: t.muted, marginBottom: 8, textTransform: "uppercase", letterSpacing: ".6px" }, children: formatDay(daySlots[0].startsAt) }),
4913
+ /* @__PURE__ */ jsx4("div", { style: { display: "flex", flexWrap: "wrap", gap: 8 }, children: daySlots.map((slot) => /* @__PURE__ */ jsx4(
4065
4914
  "button",
4066
4915
  {
4067
4916
  onClick: () => {
@@ -4083,13 +4932,13 @@ function BookingDialog({
4083
4932
  )) })
4084
4933
  ] }, day))
4085
4934
  ] }),
4086
- step === "details" && selected && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: [
4087
- /* @__PURE__ */ jsxs3("div", { style: { fontSize: 13, color: t.muted }, children: [
4935
+ step === "details" && selected && /* @__PURE__ */ jsxs4("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: [
4936
+ /* @__PURE__ */ jsxs4("div", { style: { fontSize: 13, color: t.muted }, children: [
4088
4937
  formatDay(selected.startsAt),
4089
4938
  " \xB7 ",
4090
4939
  formatTime(selected.startsAt),
4091
4940
  " \xB7 ",
4092
- /* @__PURE__ */ jsx3(
4941
+ /* @__PURE__ */ jsx4(
4093
4942
  "button",
4094
4943
  {
4095
4944
  onClick: () => setStep("slots"),
@@ -4098,9 +4947,9 @@ function BookingDialog({
4098
4947
  }
4099
4948
  )
4100
4949
  ] }),
4101
- /* @__PURE__ */ jsx3(Field, { label: "Your name", value: name, onChange: setName }),
4102
- /* @__PURE__ */ jsx3(Field, { label: "Email", value: email, onChange: setEmail, type: "email" }),
4103
- /* @__PURE__ */ jsx3(
4950
+ /* @__PURE__ */ jsx4(Field, { label: "Your name", value: name, onChange: setName }),
4951
+ /* @__PURE__ */ jsx4(Field, { label: "Email", value: email, onChange: setEmail, type: "email" }),
4952
+ /* @__PURE__ */ jsx4(
4104
4953
  Field,
4105
4954
  {
4106
4955
  label: "Mobile number",
@@ -4110,8 +4959,8 @@ function BookingDialog({
4110
4959
  hint: "We send a code here to confirm, then a reminder before the call."
4111
4960
  }
4112
4961
  ),
4113
- /* @__PURE__ */ jsx3(Field, { label: "Anything we should know? (optional)", value: note, onChange: setNote }),
4114
- /* @__PURE__ */ jsx3(
4962
+ /* @__PURE__ */ jsx4(Field, { label: "Anything we should know? (optional)", value: note, onChange: setNote }),
4963
+ /* @__PURE__ */ jsx4(
4115
4964
  "button",
4116
4965
  {
4117
4966
  onClick: startBooking,
@@ -4121,10 +4970,10 @@ function BookingDialog({
4121
4970
  }
4122
4971
  )
4123
4972
  ] }),
4124
- step === "code" && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: [
4125
- /* @__PURE__ */ jsx3("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." }),
4126
- /* @__PURE__ */ jsx3(Field, { label: "Code", value: code, onChange: setCode }),
4127
- /* @__PURE__ */ jsx3(
4973
+ step === "code" && /* @__PURE__ */ jsxs4("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: [
4974
+ /* @__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." }),
4975
+ /* @__PURE__ */ jsx4(Field, { label: "Code", value: code, onChange: setCode }),
4976
+ /* @__PURE__ */ jsx4(
4128
4977
  "button",
4129
4978
  {
4130
4979
  onClick: confirmBooking,
@@ -4134,15 +4983,15 @@ function BookingDialog({
4134
4983
  }
4135
4984
  )
4136
4985
  ] }),
4137
- step === "done" && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: [
4138
- /* @__PURE__ */ jsx3("div", { style: { fontSize: 15, fontWeight: 600 }, children: "You're booked." }),
4139
- /* @__PURE__ */ jsxs3("div", { style: { fontSize: 13, color: t.muted, lineHeight: 1.6 }, children: [
4986
+ step === "done" && /* @__PURE__ */ jsxs4("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: [
4987
+ /* @__PURE__ */ jsx4("div", { style: { fontSize: 15, fontWeight: 600 }, children: "You're booked." }),
4988
+ /* @__PURE__ */ jsxs4("div", { style: { fontSize: 13, color: t.muted, lineHeight: 1.6 }, children: [
4140
4989
  selected && `${formatDay(selected.startsAt)} at ${formatTime(selected.startsAt)}. `,
4141
4990
  "A calendar invite is on its way to ",
4142
4991
  email,
4143
4992
  ", and we'll send a WhatsApp reminder before the call."
4144
4993
  ] }),
4145
- meetUrl && /* @__PURE__ */ jsx3("a", { href: meetUrl, target: "_blank", rel: "noreferrer", style: { ...primaryStyle(false), textAlign: "center", textDecoration: "none" }, children: "Open the meeting link" })
4994
+ meetUrl && /* @__PURE__ */ jsx4("a", { href: meetUrl, target: "_blank", rel: "noreferrer", style: { ...primaryStyle(false), textAlign: "center", textDecoration: "none" }, children: "Open the meeting link" })
4146
4995
  ] })
4147
4996
  ] })
4148
4997
  ]
@@ -4171,9 +5020,9 @@ function Field({
4171
5020
  type = "text",
4172
5021
  hint
4173
5022
  }) {
4174
- return /* @__PURE__ */ jsxs3("label", { style: { display: "block", fontSize: 11, color: t.muted }, children: [
5023
+ return /* @__PURE__ */ jsxs4("label", { style: { display: "block", fontSize: 11, color: t.muted }, children: [
4175
5024
  label,
4176
- /* @__PURE__ */ jsx3(
5025
+ /* @__PURE__ */ jsx4(
4177
5026
  "input",
4178
5027
  {
4179
5028
  type,
@@ -4194,7 +5043,7 @@ function Field({
4194
5043
  }
4195
5044
  }
4196
5045
  ),
4197
- hint && /* @__PURE__ */ jsx3("div", { style: { marginTop: 4, fontSize: 10, color: t.muted }, children: hint })
5046
+ hint && /* @__PURE__ */ jsx4("div", { style: { marginTop: 4, fontSize: 10, color: t.muted }, children: hint })
4198
5047
  ] });
4199
5048
  }
4200
5049
 
@@ -4335,7 +5184,7 @@ function matchesShortcut(e) {
4335
5184
  }
4336
5185
 
4337
5186
  // src/provider.tsx
4338
- import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
5187
+ import { Fragment as Fragment4, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
4339
5188
  var DEFAULT_BASE_URL2 = "https://glitchgrab.dev";
4340
5189
  var GlitchgrabContext = createContext(null);
4341
5190
  function useGlitchgrab() {
@@ -4362,7 +5211,7 @@ function GlitchgrabProviderInner({
4362
5211
  context: appContext2,
4363
5212
  responseBodyOrigins: responseBodyOrigins2
4364
5213
  }) {
4365
- const visitedPagesRef = useRef3([]);
5214
+ const visitedPagesRef = useRef4([]);
4366
5215
  setRelease(release2);
4367
5216
  if (appContext2) setContexts(appContext2);
4368
5217
  registerCaptureConfig({
@@ -4374,12 +5223,12 @@ function GlitchgrabProviderInner({
4374
5223
  onError,
4375
5224
  onReportSent
4376
5225
  });
4377
- useEffect4(() => {
5226
+ useEffect5(() => {
4378
5227
  if (enableBreadcrumbs) {
4379
5228
  initBreadcrumbs(maxBreadcrumbs2, { responseBodyOrigins: responseBodyOrigins2 });
4380
5229
  }
4381
5230
  }, [enableBreadcrumbs, maxBreadcrumbs2, responseBodyOrigins2 == null ? void 0 : responseBodyOrigins2.join(",")]);
4382
- useEffect4(() => {
5231
+ useEffect5(() => {
4383
5232
  try {
4384
5233
  if (typeof window === "undefined") return;
4385
5234
  const trackPage = () => {
@@ -4416,7 +5265,7 @@ function GlitchgrabProviderInner({
4416
5265
  } catch (e) {
4417
5266
  }
4418
5267
  }, []);
4419
- useEffect4(() => {
5268
+ useEffect5(() => {
4420
5269
  try {
4421
5270
  if (typeof window === "undefined") return;
4422
5271
  if (process.env.NODE_ENV === "development") return;
@@ -4650,6 +5499,26 @@ function GlitchgrabProviderInner({
4650
5499
  },
4651
5500
  [token, baseUrl]
4652
5501
  );
5502
+ const assist = useCallback2(
5503
+ async (params) => {
5504
+ var _a;
5505
+ const ctx = captureContext(visitedPagesRef.current);
5506
+ return assistTurn(
5507
+ {
5508
+ ...params,
5509
+ context: {
5510
+ ...(_a = params.context) != null ? _a : {},
5511
+ url: ctx.url,
5512
+ visitedPages: ctx.visitedPages.slice(-5),
5513
+ breadcrumbs: ctx.breadcrumbs.slice(-25).map((b) => ({ type: b.type, message: b.message }))
5514
+ }
5515
+ },
5516
+ token,
5517
+ baseUrl
5518
+ );
5519
+ },
5520
+ [token, baseUrl]
5521
+ );
4653
5522
  const transcribe = useCallback2(
4654
5523
  async (blob) => {
4655
5524
  try {
@@ -4665,7 +5534,7 @@ function GlitchgrabProviderInner({
4665
5534
  window.dispatchEvent(new CustomEvent("glitchgrab:open-report", { detail: options }));
4666
5535
  }
4667
5536
  }, []);
4668
- useEffect4(() => {
5537
+ useEffect5(() => {
4669
5538
  try {
4670
5539
  if (typeof document === "undefined") return;
4671
5540
  document.documentElement.setAttribute("data-glitchgrab-sdk", "1");
@@ -4673,10 +5542,11 @@ function GlitchgrabProviderInner({
4673
5542
  } catch (e) {
4674
5543
  }
4675
5544
  }, []);
4676
- const [projectName, setProjectName] = useState4(null);
4677
- const [bookingOpen, setBookingOpen] = useState4(false);
5545
+ const [projectName, setProjectName] = useState5(null);
5546
+ const [aiAssist, setAiAssist] = useState5(false);
5547
+ const [bookingOpen, setBookingOpen] = useState5(false);
4678
5548
  const openBookingDialog = useCallback2(() => setBookingOpen(true), []);
4679
- useEffect4(() => {
5549
+ useEffect5(() => {
4680
5550
  let cancelled = false;
4681
5551
  fetch(`${baseUrl}/api/v1/sdk/project`, {
4682
5552
  headers: { Authorization: `Bearer ${token}` }
@@ -4684,13 +5554,14 @@ function GlitchgrabProviderInner({
4684
5554
  var _a;
4685
5555
  if (cancelled || !(json == null ? void 0 : json.success) || !((_a = json.data) == null ? void 0 : _a.name)) return;
4686
5556
  setProjectName(json.data.name);
5557
+ setAiAssist(json.data.aiAssist === true);
4687
5558
  }).catch(() => {
4688
5559
  });
4689
5560
  return () => {
4690
5561
  cancelled = true;
4691
5562
  };
4692
5563
  }, [baseUrl, token]);
4693
- useEffect4(() => {
5564
+ useEffect5(() => {
4694
5565
  try {
4695
5566
  if (typeof window === "undefined") return;
4696
5567
  const handleKeyDown = (e) => {
@@ -4714,11 +5585,11 @@ function GlitchgrabProviderInner({
4714
5585
  avatarUrl: typeof avatar === "string" ? avatar : null
4715
5586
  };
4716
5587
  }, [session]);
4717
- const [shortcutLabel, setShortcutLabel] = useState4(GLITCHGRAB_SHORTCUT2);
4718
- useEffect4(() => {
5588
+ const [shortcutLabel, setShortcutLabel] = useState5(GLITCHGRAB_SHORTCUT2);
5589
+ useEffect5(() => {
4719
5590
  setShortcutLabel(getShortcutLabel2());
4720
5591
  }, []);
4721
- return /* @__PURE__ */ jsxs4(
5592
+ return /* @__PURE__ */ jsxs5(
4722
5593
  GlitchgrabContext.Provider,
4723
5594
  {
4724
5595
  value: {
@@ -4738,7 +5609,7 @@ function GlitchgrabProviderInner({
4738
5609
  shortcutLabel
4739
5610
  },
4740
5611
  children: [
4741
- /* @__PURE__ */ jsx4(
5612
+ /* @__PURE__ */ jsx5(
4742
5613
  GlitchgrabErrorBoundary,
4743
5614
  {
4744
5615
  token,
@@ -4750,7 +5621,7 @@ function GlitchgrabProviderInner({
4750
5621
  children
4751
5622
  }
4752
5623
  ),
4753
- /* @__PURE__ */ jsx4(
5624
+ /* @__PURE__ */ jsx5(
4754
5625
  BookingDialog,
4755
5626
  {
4756
5627
  token,
@@ -4759,19 +5630,20 @@ function GlitchgrabProviderInner({
4759
5630
  onClose: () => setBookingOpen(false)
4760
5631
  }
4761
5632
  ),
4762
- /* @__PURE__ */ jsx4(
5633
+ /* @__PURE__ */ jsx5(
4763
5634
  ReportDialog,
4764
5635
  {
4765
5636
  report,
4766
5637
  sendFeedback: feedback,
4767
5638
  enhanceText: enhance,
5639
+ assist: aiAssist ? assist : void 0,
4768
5640
  transcribeAudio: transcribe,
4769
5641
  types,
4770
5642
  showSeverity,
4771
5643
  reporter,
4772
- headerSlot: projectName ? /* @__PURE__ */ jsxs4("div", { style: { fontSize: 11, color: "#9aa0a6" }, children: [
5644
+ headerSlot: projectName ? /* @__PURE__ */ jsxs5("div", { style: { fontSize: 11, color: "#9aa0a6" }, children: [
4773
5645
  "Reporting to ",
4774
- /* @__PURE__ */ jsx4("strong", { style: { color: "#e5e5e5" }, children: projectName })
5646
+ /* @__PURE__ */ jsx5("strong", { style: { color: "#e5e5e5" }, children: projectName })
4775
5647
  ] }) : null
4776
5648
  }
4777
5649
  )
@@ -4780,21 +5652,21 @@ function GlitchgrabProviderInner({
4780
5652
  );
4781
5653
  }
4782
5654
  function GlitchgrabProvider(props) {
4783
- if (!props.token) return /* @__PURE__ */ jsx4(Fragment3, { children: props.children });
5655
+ if (!props.token) return /* @__PURE__ */ jsx5(Fragment4, { children: props.children });
4784
5656
  const resolvedProps = {
4785
5657
  ...props,
4786
5658
  baseUrl: props.baseUrl || DEFAULT_BASE_URL2
4787
5659
  };
4788
5660
  try {
4789
- return /* @__PURE__ */ jsx4(GlitchgrabProviderInner, { ...resolvedProps });
5661
+ return /* @__PURE__ */ jsx5(GlitchgrabProviderInner, { ...resolvedProps });
4790
5662
  } catch (e) {
4791
- return /* @__PURE__ */ jsx4(Fragment3, { children: props.children });
5663
+ return /* @__PURE__ */ jsx5(Fragment4, { children: props.children });
4792
5664
  }
4793
5665
  }
4794
5666
 
4795
5667
  // src/report-button.tsx
4796
- import { useState as useState5 } from "react";
4797
- import { Fragment as Fragment4, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
5668
+ import { useState as useState6 } from "react";
5669
+ import { Fragment as Fragment5, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
4798
5670
  function useGlitchgrabSafe() {
4799
5671
  try {
4800
5672
  return useGlitchgrab();
@@ -4809,7 +5681,7 @@ function ReportButton({
4809
5681
  children
4810
5682
  }) {
4811
5683
  var _a, _b;
4812
- const [capturing, setCapturing] = useState5(false);
5684
+ const [capturing, setCapturing] = useState6(false);
4813
5685
  const glitchgrab = useGlitchgrabSafe();
4814
5686
  if (!glitchgrab) return null;
4815
5687
  const handleClick = async () => {
@@ -4818,7 +5690,7 @@ function ReportButton({
4818
5690
  setCapturing(false);
4819
5691
  };
4820
5692
  if (children) {
4821
- return /* @__PURE__ */ jsx5(Fragment4, { children: children({ onClick: handleClick, capturing }) });
5693
+ return /* @__PURE__ */ jsx6(Fragment5, { children: children({ onClick: handleClick, capturing }) });
4822
5694
  }
4823
5695
  const isTop = (_a = position == null ? void 0 : position.startsWith("top")) != null ? _a : false;
4824
5696
  const isLeft = (_b = position == null ? void 0 : position.endsWith("left")) != null ? _b : false;
@@ -4826,7 +5698,7 @@ function ReportButton({
4826
5698
  ...isLeft ? { left: "16px" } : { right: "16px" },
4827
5699
  ...isTop ? { top: "16px" } : { bottom: "16px" }
4828
5700
  };
4829
- return /* @__PURE__ */ jsxs5(
5701
+ return /* @__PURE__ */ jsxs6(
4830
5702
  "button",
4831
5703
  {
4832
5704
  type: "button",
@@ -4861,7 +5733,7 @@ function ReportButton({
4861
5733
  },
4862
5734
  "aria-label": label,
4863
5735
  children: [
4864
- /* @__PURE__ */ jsx5(
5736
+ /* @__PURE__ */ jsx6(
4865
5737
  "svg",
4866
5738
  {
4867
5739
  width: "16",
@@ -4869,7 +5741,7 @@ function ReportButton({
4869
5741
  viewBox: "0 0 16 16",
4870
5742
  fill: "none",
4871
5743
  style: { flexShrink: 0 },
4872
- children: /* @__PURE__ */ jsx5(
5744
+ children: /* @__PURE__ */ jsx6(
4873
5745
  "path",
4874
5746
  {
4875
5747
  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",
@@ -4885,15 +5757,15 @@ function ReportButton({
4885
5757
  }
4886
5758
 
4887
5759
  // src/book-demo-button.tsx
4888
- import { Fragment as Fragment5, jsx as jsx6 } from "react/jsx-runtime";
5760
+ import { Fragment as Fragment6, jsx as jsx7 } from "react/jsx-runtime";
4889
5761
  function BookDemoButton({
4890
5762
  label = "Book a demo",
4891
5763
  className,
4892
5764
  children
4893
5765
  }) {
4894
5766
  const { openBookingDialog } = useGlitchgrab();
4895
- if (children) return /* @__PURE__ */ jsx6(Fragment5, { children: children({ onClick: openBookingDialog }) });
4896
- return /* @__PURE__ */ jsx6(
5767
+ if (children) return /* @__PURE__ */ jsx7(Fragment6, { children: children({ onClick: openBookingDialog }) });
5768
+ return /* @__PURE__ */ jsx7(
4897
5769
  "button",
4898
5770
  {
4899
5771
  type: "button",
@@ -4915,7 +5787,7 @@ function BookDemoButton({
4915
5787
  }
4916
5788
 
4917
5789
  // src/feedback-button.tsx
4918
- import { Fragment as Fragment6, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
5790
+ import { Fragment as Fragment7, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
4919
5791
  function useGlitchgrabSafe2() {
4920
5792
  try {
4921
5793
  return useGlitchgrab();
@@ -4934,7 +5806,7 @@ function FeedbackButton({
4934
5806
  if (!glitchgrab) return null;
4935
5807
  const handleClick = () => glitchgrab.openFeedbackDialog();
4936
5808
  if (children) {
4937
- return /* @__PURE__ */ jsx7(Fragment6, { children: children({ onClick: handleClick }) });
5809
+ return /* @__PURE__ */ jsx8(Fragment7, { children: children({ onClick: handleClick }) });
4938
5810
  }
4939
5811
  const isTop = (_a = position == null ? void 0 : position.startsWith("top")) != null ? _a : false;
4940
5812
  const isLeft = (_b = position == null ? void 0 : position.endsWith("left")) != null ? _b : false;
@@ -4942,7 +5814,7 @@ function FeedbackButton({
4942
5814
  ...isLeft ? { left: "16px" } : { right: "16px" },
4943
5815
  ...isTop ? { top: "16px" } : { bottom: "16px" }
4944
5816
  };
4945
- return /* @__PURE__ */ jsxs6(
5817
+ return /* @__PURE__ */ jsxs7(
4946
5818
  "button",
4947
5819
  {
4948
5820
  type: "button",
@@ -4975,7 +5847,7 @@ function FeedbackButton({
4975
5847
  },
4976
5848
  "aria-label": label,
4977
5849
  children: [
4978
- /* @__PURE__ */ jsx7(
5850
+ /* @__PURE__ */ jsx8(
4979
5851
  "svg",
4980
5852
  {
4981
5853
  width: "16",
@@ -4984,7 +5856,7 @@ function FeedbackButton({
4984
5856
  fill: "none",
4985
5857
  style: { flexShrink: 0 },
4986
5858
  "aria-hidden": "true",
4987
- children: /* @__PURE__ */ jsx7(
5859
+ children: /* @__PURE__ */ jsx8(
4988
5860
  "path",
4989
5861
  {
4990
5862
  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",
@@ -5000,17 +5872,17 @@ function FeedbackButton({
5000
5872
  }
5001
5873
 
5002
5874
  // src/use-reports.ts
5003
- import { useState as useState6, useEffect as useEffect5, useCallback as useCallback3 } from "react";
5875
+ import { useState as useState7, useEffect as useEffect6, useCallback as useCallback3 } from "react";
5004
5876
  var BASE_URL = "https://glitchgrab.dev";
5005
5877
  function useGlitchgrabReports({
5006
5878
  token,
5007
5879
  userId,
5008
5880
  limit = 100
5009
5881
  }) {
5010
- const [reports, setReports] = useState6([]);
5011
- const [isLoading, setIsLoading] = useState6(true);
5012
- const [isFetching, setIsFetching] = useState6(false);
5013
- const [error, setError] = useState6(null);
5882
+ const [reports, setReports] = useState7([]);
5883
+ const [isLoading, setIsLoading] = useState7(true);
5884
+ const [isFetching, setIsFetching] = useState7(false);
5885
+ const [error, setError] = useState7(null);
5014
5886
  const fetchReports = useCallback3(async () => {
5015
5887
  var _a, _b;
5016
5888
  if (!token || !userId) {
@@ -5037,7 +5909,7 @@ function useGlitchgrabReports({
5037
5909
  setIsFetching(false);
5038
5910
  }
5039
5911
  }, [token, userId, limit]);
5040
- useEffect5(() => {
5912
+ useEffect6(() => {
5041
5913
  fetchReports();
5042
5914
  }, [fetchReports]);
5043
5915
  return { reports, isLoading, isFetching, error, refetch: fetchReports };
@@ -5074,8 +5946,8 @@ function useGlitchgrabActions({
5074
5946
  onSuccess,
5075
5947
  onError
5076
5948
  }) {
5077
- const [isPending, setIsPending] = useState6(false);
5078
- const [error, setError] = useState6(null);
5949
+ const [isPending, setIsPending] = useState7(false);
5950
+ const [error, setError] = useState7(null);
5079
5951
  const run = useCallback3(
5080
5952
  async (reportId, body) => {
5081
5953
  setIsPending(true);
@@ -5106,7 +5978,7 @@ function useGlitchgrabActions({
5106
5978
  }
5107
5979
 
5108
5980
  // src/use-feedback.ts
5109
- import { useState as useState7, useEffect as useEffect6, useCallback as useCallback4 } from "react";
5981
+ import { useState as useState8, useEffect as useEffect7, useCallback as useCallback4 } from "react";
5110
5982
  var DEFAULT_BASE_URL3 = "https://glitchgrab.dev";
5111
5983
  function buildUrl({
5112
5984
  approvedOnly,
@@ -5132,10 +6004,10 @@ async function fetchGlitchgrabFeedback(query) {
5132
6004
  }
5133
6005
  function useGlitchgrabFeedback(query) {
5134
6006
  const { token, approvedOnly, userId, minRating, limit, baseUrl } = query;
5135
- const [feedback, setFeedback] = useState7([]);
5136
- const [isLoading, setIsLoading] = useState7(true);
5137
- const [isFetching, setIsFetching] = useState7(false);
5138
- const [error, setError] = useState7(null);
6007
+ const [feedback, setFeedback] = useState8([]);
6008
+ const [isLoading, setIsLoading] = useState8(true);
6009
+ const [isFetching, setIsFetching] = useState8(false);
6010
+ const [error, setError] = useState8(null);
5139
6011
  const load = useCallback4(async () => {
5140
6012
  if (!token) {
5141
6013
  setIsLoading(false);
@@ -5160,7 +6032,7 @@ function useGlitchgrabFeedback(query) {
5160
6032
  setIsFetching(false);
5161
6033
  }
5162
6034
  }, [token, approvedOnly, userId, minRating, limit, baseUrl]);
5163
- useEffect6(() => {
6035
+ useEffect7(() => {
5164
6036
  load();
5165
6037
  }, [load]);
5166
6038
  return { feedback, isLoading, isFetching, error, refetch: load };