glitchgrab 1.33.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.js CHANGED
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  // src/index.ts
32
32
  var index_exports = {};
33
33
  __export(index_exports, {
34
+ BookDemoButton: () => BookDemoButton,
34
35
  FeedbackButton: () => FeedbackButton,
35
36
  GLITCHGRAB_SHORTCUT: () => GLITCHGRAB_SHORTCUT2,
36
37
  GLITCHGRAB_SHORTCUT_MAC: () => GLITCHGRAB_SHORTCUT_MAC2,
@@ -67,7 +68,7 @@ __export(index_exports, {
67
68
  module.exports = __toCommonJS(index_exports);
68
69
 
69
70
  // src/provider.tsx
70
- var import_react3 = require("react");
71
+ var import_react5 = require("react");
71
72
 
72
73
  // src/error-boundary.tsx
73
74
  var React = __toESM(require("react"));
@@ -645,6 +646,43 @@ async function enhanceText(text, token, baseUrl, screenshot, context) {
645
646
  return text;
646
647
  }
647
648
  }
649
+ async function assistTurn(params, token, baseUrl) {
650
+ var _a, _b, _c, _d, _e, _f, _g;
651
+ const offline = {
652
+ conversationId: null,
653
+ question: null,
654
+ report: null,
655
+ degraded: "The assistant is unavailable \u2014 write your report below and send it as normal."
656
+ };
657
+ try {
658
+ const url = `${baseUrl != null ? baseUrl : DEFAULT_BASE_URL}/api/v1/ai/report-chat`;
659
+ const response = await fetch(url, {
660
+ method: "POST",
661
+ headers: {
662
+ "Content-Type": "application/json",
663
+ Authorization: `Bearer ${token}`
664
+ },
665
+ body: JSON.stringify(params)
666
+ });
667
+ const envelope = await response.json().catch(() => null);
668
+ if (!response.ok || !(envelope == null ? void 0 : envelope.success)) {
669
+ return {
670
+ conversationId: null,
671
+ question: null,
672
+ report: null,
673
+ degraded: (_a = envelope == null ? void 0 : envelope.error) != null ? _a : offline.degraded
674
+ };
675
+ }
676
+ return {
677
+ conversationId: (_c = (_b = envelope.data) == null ? void 0 : _b.conversationId) != null ? _c : null,
678
+ question: (_e = (_d = envelope.data) == null ? void 0 : _d.question) != null ? _e : null,
679
+ report: (_g = (_f = envelope.data) == null ? void 0 : _f.report) != null ? _g : null,
680
+ degraded: null
681
+ };
682
+ } catch (e) {
683
+ return offline;
684
+ }
685
+ }
648
686
  async function transcribeAudio(blob, token, baseUrl) {
649
687
  var _a;
650
688
  try {
@@ -688,9 +726,9 @@ function topStackFrame(stack) {
688
726
  if (!stack) return "";
689
727
  const lines = stack.split("\n");
690
728
  for (const line of lines) {
691
- const t = line.trim();
692
- if (t.startsWith("at ") || t.includes("@")) {
693
- return t;
729
+ const t2 = line.trim();
730
+ if (t2.startsWith("at ") || t2.includes("@")) {
731
+ return t2;
694
732
  }
695
733
  }
696
734
  return "";
@@ -856,7 +894,10 @@ var import_react = require("react");
856
894
  var import_react_dom = require("react-dom");
857
895
  var import_react2 = require("react");
858
896
  var import_jsx_runtime = require("react/jsx-runtime");
897
+ var import_react3 = require("react");
898
+ var import_react_dom2 = require("react-dom");
859
899
  var import_jsx_runtime2 = require("react/jsx-runtime");
900
+ var import_jsx_runtime3 = require("react/jsx-runtime");
860
901
  var MAX_SCREENSHOT_DATA_URL_LENGTH = 18e5;
861
902
  var QUALITY_LADDER = [0.92, 0.85, 0.75];
862
903
  var DOWNSCALE_FACTOR = 0.7;
@@ -1162,6 +1203,693 @@ function AnnotationCanvas({ imageSrc, onSave, onCancel }) {
1162
1203
  }
1163
1204
  );
1164
1205
  }
1206
+ var STARTERS = [
1207
+ "Something on this page is broken",
1208
+ "It did the wrong thing",
1209
+ "I wish it could\u2026"
1210
+ ];
1211
+ var NARROW_QUERY = "(max-width: 640px)";
1212
+ function useIsNarrow() {
1213
+ const [narrow, setNarrow] = (0, import_react3.useState)(false);
1214
+ (0, import_react3.useEffect)(() => {
1215
+ try {
1216
+ const mq = window.matchMedia(NARROW_QUERY);
1217
+ setNarrow(mq.matches);
1218
+ const onChange = (e) => setNarrow(e.matches);
1219
+ mq.addEventListener("change", onChange);
1220
+ return () => mq.removeEventListener("change", onChange);
1221
+ } catch (e) {
1222
+ }
1223
+ }, []);
1224
+ return narrow;
1225
+ }
1226
+ function Sparkle({ color, size = 14 }) {
1227
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1228
+ "path",
1229
+ {
1230
+ 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",
1231
+ stroke: color,
1232
+ strokeWidth: "1.5",
1233
+ strokeLinejoin: "round"
1234
+ }
1235
+ ) });
1236
+ }
1237
+ function Avatar({
1238
+ who,
1239
+ theme: t2,
1240
+ initials
1241
+ }) {
1242
+ const isAi = who === "assistant";
1243
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1244
+ "span",
1245
+ {
1246
+ "aria-hidden": "true",
1247
+ style: {
1248
+ flexShrink: 0,
1249
+ width: "24px",
1250
+ height: "24px",
1251
+ borderRadius: "50%",
1252
+ display: "inline-flex",
1253
+ alignItems: "center",
1254
+ justifyContent: "center",
1255
+ marginTop: "2px",
1256
+ backgroundColor: isAi ? `${t2.accent}22` : t2.bgSecondary,
1257
+ border: `1px solid ${isAi ? t2.accent : t2.inputBorder}`,
1258
+ color: isAi ? t2.accent : t2.textMuted,
1259
+ fontSize: "10px",
1260
+ fontWeight: 700
1261
+ },
1262
+ children: isAi ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Sparkle, { color: t2.accent, size: 12 }) : initials ? initials : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: [
1263
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "12", cy: "8", r: "3.4", stroke: "currentColor", strokeWidth: "1.8" }),
1264
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1265
+ "path",
1266
+ {
1267
+ d: "M5 20c0-3.6 3.1-5.6 7-5.6s7 2 7 5.6",
1268
+ stroke: "currentColor",
1269
+ strokeWidth: "1.8",
1270
+ strokeLinecap: "round"
1271
+ }
1272
+ )
1273
+ ] })
1274
+ }
1275
+ );
1276
+ }
1277
+ function AssistSheet({
1278
+ assist,
1279
+ theme: t2,
1280
+ screenshot,
1281
+ attachmentCount,
1282
+ context,
1283
+ reportTypeLabel,
1284
+ projectSlot,
1285
+ reporterName,
1286
+ description,
1287
+ onDescriptionChange,
1288
+ severity,
1289
+ onSeverityChange,
1290
+ showSeverity,
1291
+ isSubmitting,
1292
+ submitted,
1293
+ onSend,
1294
+ onDegrade,
1295
+ onClose
1296
+ }) {
1297
+ const narrow = useIsNarrow();
1298
+ const [messages, setMessages] = (0, import_react3.useState)([]);
1299
+ const [input, setInput] = (0, import_react3.useState)("");
1300
+ const [busy, setBusy] = (0, import_react3.useState)(false);
1301
+ const [conversationId, setConversationId] = (0, import_react3.useState)(null);
1302
+ const [phase, setPhase] = (0, import_react3.useState)("chat");
1303
+ const scrollRef = (0, import_react3.useRef)(null);
1304
+ const inputRef = (0, import_react3.useRef)(null);
1305
+ const draftRef = (0, import_react3.useRef)(null);
1306
+ const seededRef = (0, import_react3.useRef)(false);
1307
+ (0, import_react3.useEffect)(() => {
1308
+ const el = scrollRef.current;
1309
+ if (el) el.scrollTop = el.scrollHeight;
1310
+ }, [messages, busy, phase]);
1311
+ (0, import_react3.useEffect)(() => {
1312
+ var _a;
1313
+ if (phase === "draft") (_a = draftRef.current) == null ? void 0 : _a.focus();
1314
+ }, [phase]);
1315
+ async function runTurn(history2) {
1316
+ setBusy(true);
1317
+ let result;
1318
+ try {
1319
+ result = await assist({ messages: history2, conversationId, screenshot, context });
1320
+ } catch (e) {
1321
+ onDegrade("The assistant is unavailable \u2014 write your report below and send it as normal.");
1322
+ return;
1323
+ } finally {
1324
+ setBusy(false);
1325
+ }
1326
+ if (result.degraded) {
1327
+ onDegrade(result.degraded);
1328
+ return;
1329
+ }
1330
+ if (result.conversationId) setConversationId(result.conversationId);
1331
+ if (result.report) {
1332
+ onDescriptionChange(result.report);
1333
+ setMessages([...history2, { role: "assistant", content: "Here's your report \u2014 have a read." }]);
1334
+ setPhase("draft");
1335
+ return;
1336
+ }
1337
+ if (result.question) {
1338
+ setMessages([...history2, { role: "assistant", content: result.question }]);
1339
+ return;
1340
+ }
1341
+ onDegrade("The assistant had nothing to add \u2014 write your report below and send it as normal.");
1342
+ }
1343
+ (0, import_react3.useEffect)(() => {
1344
+ if (seededRef.current) return;
1345
+ seededRef.current = true;
1346
+ const seed = description.trim();
1347
+ if (!seed) return;
1348
+ const history2 = [{ role: "user", content: seed }];
1349
+ setMessages(history2);
1350
+ void runTurn(history2);
1351
+ }, []);
1352
+ function send(text) {
1353
+ const value = text.trim();
1354
+ if (!value || busy) return;
1355
+ const history2 = [...messages, { role: "user", content: value }];
1356
+ setMessages(history2);
1357
+ setInput("");
1358
+ void runTurn(history2);
1359
+ }
1360
+ const empty = messages.length === 0 && !busy;
1361
+ const initials = (reporterName != null ? reporterName : "").split(/\s+/).filter(Boolean).slice(0, 2).map((w) => {
1362
+ var _a, _b;
1363
+ return (_b = (_a = w[0]) == null ? void 0 : _a.toUpperCase()) != null ? _b : "";
1364
+ }).join("");
1365
+ const panelStyle = narrow ? {
1366
+ width: "100%",
1367
+ maxHeight: "88dvh",
1368
+ borderTopLeftRadius: "16px",
1369
+ borderTopRightRadius: "16px",
1370
+ animation: "gg-sheet-up .22s cubic-bezier(.2,.8,.2,1)"
1371
+ } : {
1372
+ width: "440px",
1373
+ maxWidth: "100%",
1374
+ height: "100dvh",
1375
+ borderLeft: `1px solid ${t2.border}`,
1376
+ animation: "gg-sheet-in .22s cubic-bezier(.2,.8,.2,1)"
1377
+ };
1378
+ return (0, import_react_dom2.createPortal)(
1379
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
1380
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { children: `
1381
+ @keyframes gg-sheet-in{from{transform:translateX(24px);opacity:0}to{transform:translateX(0);opacity:1}}
1382
+ @keyframes gg-sheet-up{from{transform:translateY(24px);opacity:0}to{transform:translateY(0);opacity:1}}
1383
+ @keyframes gg-sheet-fade{from{opacity:0}to{opacity:1}}
1384
+ @keyframes gg-dot{0%,80%,100%{transform:translateY(0);opacity:.4}40%{transform:translateY(-3px);opacity:1}}
1385
+ [data-gg-sheet-send]:focus-visible,[data-gg-chip]:focus-visible{outline:2px solid currentColor;outline-offset:2px}
1386
+ ` }),
1387
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1388
+ "div",
1389
+ {
1390
+ "data-glitchgrab-layer": "",
1391
+ role: "dialog",
1392
+ "aria-modal": "true",
1393
+ "aria-label": "Describe your report with AI",
1394
+ style: {
1395
+ position: "fixed",
1396
+ inset: 0,
1397
+ zIndex: 2147483647,
1398
+ display: "flex",
1399
+ alignItems: narrow ? "flex-end" : "stretch",
1400
+ justifyContent: narrow ? "center" : "flex-end",
1401
+ backgroundColor: "rgba(0,0,0,0.5)",
1402
+ animation: "gg-sheet-fade .18s ease",
1403
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
1404
+ },
1405
+ onClick: onClose,
1406
+ onPointerDown: (e) => e.stopPropagation(),
1407
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1408
+ "div",
1409
+ {
1410
+ onClick: (e) => e.stopPropagation(),
1411
+ style: {
1412
+ ...panelStyle,
1413
+ display: "flex",
1414
+ flexDirection: "column",
1415
+ // A flex child defaults to min-width:auto, so a long chat bubble
1416
+ // grows the sheet past the viewport instead of wrapping inside it.
1417
+ // This is what keeps the bottom sheet on screen.
1418
+ minWidth: 0,
1419
+ maxWidth: "100%",
1420
+ boxSizing: "border-box",
1421
+ backgroundColor: t2.bg,
1422
+ color: t2.text,
1423
+ boxShadow: "0 20px 60px rgba(0,0,0,.35)",
1424
+ overflow: "hidden",
1425
+ isolation: "isolate"
1426
+ },
1427
+ children: [
1428
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1429
+ "div",
1430
+ {
1431
+ style: {
1432
+ flexShrink: 0,
1433
+ padding: "14px 16px",
1434
+ borderBottom: `1px solid ${t2.border}`,
1435
+ display: "flex",
1436
+ alignItems: "flex-start",
1437
+ justifyContent: "space-between",
1438
+ gap: "12px",
1439
+ minWidth: 0
1440
+ },
1441
+ children: [
1442
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { minWidth: 0, overflow: "hidden" }, children: [
1443
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1444
+ "div",
1445
+ {
1446
+ style: {
1447
+ display: "flex",
1448
+ alignItems: "center",
1449
+ gap: "7px",
1450
+ fontSize: "14px",
1451
+ fontWeight: 600
1452
+ },
1453
+ children: [
1454
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Sparkle, { color: t2.accent }),
1455
+ "Describe it with AI",
1456
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1457
+ "span",
1458
+ {
1459
+ style: {
1460
+ fontSize: "10px",
1461
+ fontWeight: 600,
1462
+ letterSpacing: ".04em",
1463
+ textTransform: "uppercase",
1464
+ color: t2.accent,
1465
+ border: `1px solid ${t2.accent}55`,
1466
+ borderRadius: "4px",
1467
+ padding: "1px 5px"
1468
+ },
1469
+ children: "Beta"
1470
+ }
1471
+ )
1472
+ ]
1473
+ }
1474
+ ),
1475
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { fontSize: "11.5px", color: t2.textMuted, marginTop: "3px" }, children: [
1476
+ reportTypeLabel,
1477
+ projectSlot ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { marginLeft: "6px" }, children: projectSlot }) : null
1478
+ ] })
1479
+ ] }),
1480
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1481
+ "button",
1482
+ {
1483
+ type: "button",
1484
+ onClick: onClose,
1485
+ "aria-label": "Close and write it myself",
1486
+ style: {
1487
+ flexShrink: 0,
1488
+ border: "none",
1489
+ background: "transparent",
1490
+ color: t2.textMuted,
1491
+ cursor: "pointer",
1492
+ fontSize: narrow ? "18px" : "12px",
1493
+ lineHeight: 1,
1494
+ fontFamily: "inherit",
1495
+ padding: narrow ? "4px 6px" : "6px 4px"
1496
+ },
1497
+ children: narrow ? "\xD7" : "Write it myself"
1498
+ }
1499
+ )
1500
+ ]
1501
+ }
1502
+ ),
1503
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1504
+ "div",
1505
+ {
1506
+ ref: scrollRef,
1507
+ style: {
1508
+ flex: 1,
1509
+ minHeight: narrow ? "180px" : 0,
1510
+ overflowY: "auto",
1511
+ padding: "16px",
1512
+ display: "flex",
1513
+ flexDirection: "column"
1514
+ },
1515
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1516
+ "div",
1517
+ {
1518
+ style: {
1519
+ marginTop: "auto",
1520
+ display: "flex",
1521
+ flexDirection: "column",
1522
+ gap: "12px",
1523
+ minWidth: 0
1524
+ },
1525
+ children: [
1526
+ empty && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
1527
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
1528
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Avatar, { who: "assistant", theme: t2 }),
1529
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1530
+ "div",
1531
+ {
1532
+ style: {
1533
+ padding: "9px 12px",
1534
+ borderRadius: "12px 12px 12px 4px",
1535
+ backgroundColor: t2.bgSecondary,
1536
+ fontSize: "13px",
1537
+ lineHeight: 1.55,
1538
+ maxWidth: "88%"
1539
+ },
1540
+ children: [
1541
+ reporterName ? `Hi ${reporterName.split(" ")[0]} \u2014 t` : "T",
1542
+ "ell me what went wrong in your own words. I can already see your screenshot and what you clicked, so skip the boring parts."
1543
+ ]
1544
+ }
1545
+ )
1546
+ ] }),
1547
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1548
+ "div",
1549
+ {
1550
+ style: {
1551
+ display: "flex",
1552
+ flexWrap: "wrap",
1553
+ gap: "6px",
1554
+ paddingLeft: "32px"
1555
+ },
1556
+ children: STARTERS.map((s) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1557
+ "button",
1558
+ {
1559
+ type: "button",
1560
+ "data-gg-chip": "",
1561
+ onClick: () => send(s),
1562
+ style: {
1563
+ border: `1px solid ${t2.inputBorder}`,
1564
+ background: "transparent",
1565
+ color: t2.textMuted,
1566
+ borderRadius: "999px",
1567
+ padding: "6px 11px",
1568
+ fontSize: "12px",
1569
+ fontFamily: "inherit",
1570
+ cursor: "pointer"
1571
+ },
1572
+ children: s
1573
+ },
1574
+ s
1575
+ ))
1576
+ }
1577
+ )
1578
+ ] }),
1579
+ messages.map((m, i) => {
1580
+ const mine = m.role === "user";
1581
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1582
+ "div",
1583
+ {
1584
+ style: {
1585
+ display: "flex",
1586
+ gap: "8px",
1587
+ minWidth: 0,
1588
+ flexDirection: mine ? "row-reverse" : "row"
1589
+ },
1590
+ children: [
1591
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Avatar, { who: m.role, theme: t2, initials }),
1592
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1593
+ "div",
1594
+ {
1595
+ style: {
1596
+ maxWidth: "82%",
1597
+ padding: "9px 12px",
1598
+ borderRadius: mine ? "12px 12px 4px 12px" : "12px 12px 12px 4px",
1599
+ fontSize: "13px",
1600
+ lineHeight: 1.55,
1601
+ whiteSpace: "pre-wrap",
1602
+ wordBreak: "break-word",
1603
+ backgroundColor: mine ? t2.accent : t2.bgSecondary,
1604
+ color: mine ? t2.accentText : t2.text
1605
+ },
1606
+ children: m.content
1607
+ }
1608
+ )
1609
+ ]
1610
+ },
1611
+ i
1612
+ );
1613
+ }),
1614
+ busy && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", gap: "8px" }, role: "status", "aria-label": "Thinking", children: [
1615
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Avatar, { who: "assistant", theme: t2 }),
1616
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1617
+ "span",
1618
+ {
1619
+ style: {
1620
+ display: "inline-flex",
1621
+ alignItems: "center",
1622
+ gap: "4px",
1623
+ padding: "12px",
1624
+ borderRadius: "12px 12px 12px 4px",
1625
+ backgroundColor: t2.bgSecondary
1626
+ },
1627
+ children: [0, 1, 2].map((i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1628
+ "span",
1629
+ {
1630
+ style: {
1631
+ width: "5px",
1632
+ height: "5px",
1633
+ borderRadius: "50%",
1634
+ backgroundColor: t2.textMuted,
1635
+ animation: `gg-dot 1.1s ease-in-out ${i * 0.15}s infinite`
1636
+ }
1637
+ },
1638
+ i
1639
+ ))
1640
+ }
1641
+ )
1642
+ ] }),
1643
+ phase === "draft" && !submitted && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1644
+ "div",
1645
+ {
1646
+ style: {
1647
+ border: `1px solid ${t2.accent}`,
1648
+ borderRadius: "12px",
1649
+ backgroundColor: t2.bgSecondary,
1650
+ padding: "12px",
1651
+ display: "flex",
1652
+ flexDirection: "column",
1653
+ gap: "10px",
1654
+ minWidth: 0,
1655
+ boxSizing: "border-box"
1656
+ },
1657
+ children: [
1658
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1659
+ "span",
1660
+ {
1661
+ style: {
1662
+ fontSize: "10px",
1663
+ fontWeight: 700,
1664
+ letterSpacing: ".06em",
1665
+ textTransform: "uppercase",
1666
+ color: t2.accent
1667
+ },
1668
+ children: "Your report \xB7 edit anything"
1669
+ }
1670
+ ),
1671
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1672
+ "textarea",
1673
+ {
1674
+ ref: draftRef,
1675
+ value: description,
1676
+ onChange: (e) => onDescriptionChange(e.target.value),
1677
+ rows: 6,
1678
+ style: {
1679
+ width: "100%",
1680
+ minHeight: "120px",
1681
+ padding: "10px",
1682
+ borderRadius: "8px",
1683
+ border: `1px solid ${t2.inputBorder}`,
1684
+ backgroundColor: t2.inputBg,
1685
+ color: t2.text,
1686
+ fontSize: "13px",
1687
+ lineHeight: 1.55,
1688
+ fontFamily: "inherit",
1689
+ resize: "vertical",
1690
+ outline: "none",
1691
+ boxSizing: "border-box"
1692
+ }
1693
+ }
1694
+ ),
1695
+ showSeverity && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
1696
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1697
+ "span",
1698
+ {
1699
+ style: {
1700
+ fontSize: "11.5px",
1701
+ color: t2.textMuted,
1702
+ display: "block",
1703
+ marginBottom: "6px"
1704
+ },
1705
+ children: "How bad is it?"
1706
+ }
1707
+ ),
1708
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { display: "flex", gap: "6px" }, children: ["low", "medium", "high"].map((s) => {
1709
+ const on = severity === s;
1710
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1711
+ "button",
1712
+ {
1713
+ type: "button",
1714
+ onClick: () => onSeverityChange(s),
1715
+ "aria-pressed": on,
1716
+ style: {
1717
+ flex: 1,
1718
+ minWidth: 0,
1719
+ padding: "8px 0",
1720
+ borderRadius: "8px",
1721
+ border: `1px solid ${on ? t2.accent : t2.inputBorder}`,
1722
+ backgroundColor: on ? t2.accent : "transparent",
1723
+ color: on ? t2.accentText : t2.textMuted,
1724
+ fontSize: "12px",
1725
+ fontWeight: 600,
1726
+ fontFamily: "inherit",
1727
+ textTransform: "capitalize",
1728
+ cursor: "pointer"
1729
+ },
1730
+ children: s
1731
+ },
1732
+ s
1733
+ );
1734
+ }) })
1735
+ ] }),
1736
+ attachmentCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: { fontSize: "11.5px", color: t2.textMuted }, children: [
1737
+ attachmentCount,
1738
+ " ",
1739
+ attachmentCount === 1 ? "attachment" : "attachments",
1740
+ " will be sent with this."
1741
+ ] }),
1742
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1743
+ "button",
1744
+ {
1745
+ type: "button",
1746
+ onClick: () => setPhase("chat"),
1747
+ style: {
1748
+ alignSelf: "flex-start",
1749
+ border: "none",
1750
+ background: "transparent",
1751
+ color: t2.textMuted,
1752
+ fontSize: "12px",
1753
+ fontFamily: "inherit",
1754
+ padding: 0,
1755
+ cursor: "pointer",
1756
+ textDecoration: "underline"
1757
+ },
1758
+ children: "Not quite \u2014 keep chatting"
1759
+ }
1760
+ )
1761
+ ]
1762
+ }
1763
+ ),
1764
+ submitted && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1765
+ "div",
1766
+ {
1767
+ style: {
1768
+ textAlign: "center",
1769
+ padding: "24px 0",
1770
+ color: t2.accent,
1771
+ fontSize: "14px",
1772
+ fontWeight: 600
1773
+ },
1774
+ children: [
1775
+ reportTypeLabel,
1776
+ " sent. Thank you!"
1777
+ ]
1778
+ }
1779
+ )
1780
+ ]
1781
+ }
1782
+ )
1783
+ }
1784
+ ),
1785
+ !submitted && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1786
+ "div",
1787
+ {
1788
+ style: {
1789
+ flexShrink: 0,
1790
+ borderTop: `1px solid ${t2.border}`,
1791
+ padding: "12px 16px",
1792
+ paddingBottom: narrow ? "max(12px, env(safe-area-inset-bottom))" : "12px",
1793
+ backgroundColor: t2.bg
1794
+ },
1795
+ children: phase === "draft" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1796
+ "button",
1797
+ {
1798
+ type: "button",
1799
+ "data-gg-sheet-send": "",
1800
+ onClick: onSend,
1801
+ disabled: isSubmitting || !description.trim(),
1802
+ style: {
1803
+ width: "100%",
1804
+ padding: "12px",
1805
+ borderRadius: "10px",
1806
+ border: "none",
1807
+ backgroundColor: isSubmitting || !description.trim() ? t2.bgSecondary : t2.accent,
1808
+ color: isSubmitting || !description.trim() ? t2.textMuted : t2.accentText,
1809
+ fontSize: "14px",
1810
+ fontWeight: 700,
1811
+ fontFamily: "inherit",
1812
+ cursor: isSubmitting || !description.trim() ? "default" : "pointer"
1813
+ },
1814
+ children: isSubmitting ? "Sending\u2026" : "Send Report"
1815
+ }
1816
+ ) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "flex-end" }, children: [
1817
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1818
+ "textarea",
1819
+ {
1820
+ ref: inputRef,
1821
+ value: input,
1822
+ onChange: (e) => setInput(e.target.value),
1823
+ onKeyDown: (e) => {
1824
+ if (e.key === "Enter" && !e.shiftKey) {
1825
+ e.preventDefault();
1826
+ send(input);
1827
+ }
1828
+ },
1829
+ placeholder: "Type your answer\u2026",
1830
+ rows: 1,
1831
+ disabled: busy,
1832
+ autoFocus: true,
1833
+ style: {
1834
+ flex: 1,
1835
+ minHeight: "42px",
1836
+ maxHeight: "120px",
1837
+ padding: "11px 12px",
1838
+ borderRadius: "10px",
1839
+ border: `1px solid ${t2.inputBorder}`,
1840
+ backgroundColor: t2.inputBg,
1841
+ color: t2.text,
1842
+ fontSize: "13px",
1843
+ lineHeight: 1.4,
1844
+ fontFamily: "inherit",
1845
+ resize: "none",
1846
+ outline: "none",
1847
+ boxSizing: "border-box"
1848
+ }
1849
+ }
1850
+ ),
1851
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1852
+ "button",
1853
+ {
1854
+ type: "button",
1855
+ "data-gg-sheet-send": "",
1856
+ onClick: () => send(input),
1857
+ disabled: busy || !input.trim(),
1858
+ "aria-label": "Send message",
1859
+ style: {
1860
+ flexShrink: 0,
1861
+ width: "42px",
1862
+ height: "42px",
1863
+ borderRadius: "10px",
1864
+ border: "none",
1865
+ display: "inline-flex",
1866
+ alignItems: "center",
1867
+ justifyContent: "center",
1868
+ backgroundColor: busy || !input.trim() ? t2.bgSecondary : t2.accent,
1869
+ color: busy || !input.trim() ? t2.textMuted : t2.accentText,
1870
+ cursor: busy || !input.trim() ? "default" : "pointer"
1871
+ },
1872
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "17", height: "17", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1873
+ "path",
1874
+ {
1875
+ d: "M3 20.5L21.5 12 3 3.5V10l12 2-12 2v6.5z",
1876
+ fill: "currentColor"
1877
+ }
1878
+ ) })
1879
+ }
1880
+ )
1881
+ ] })
1882
+ }
1883
+ )
1884
+ ]
1885
+ }
1886
+ )
1887
+ }
1888
+ )
1889
+ ] }),
1890
+ document.body
1891
+ );
1892
+ }
1165
1893
  var GLITCHGRAB_SHORTCUT = "Ctrl+Shift+G";
1166
1894
  var GLITCHGRAB_SHORTCUT_MAC = "\u2318\u21E7G";
1167
1895
  function isMac() {
@@ -1327,7 +2055,7 @@ function initialsOf(name) {
1327
2055
  }
1328
2056
  function ReporterChip({
1329
2057
  reporter,
1330
- t
2058
+ t: t2
1331
2059
  }) {
1332
2060
  var _a;
1333
2061
  const [avatarFailed, setAvatarFailed] = (0, import_react.useState)(false);
@@ -1341,13 +2069,13 @@ function ReporterChip({
1341
2069
  const label = isAnonymous ? "Anonymous" : name;
1342
2070
  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 ");
1343
2071
  const showAvatarImage = !!avatarUrl && !avatarFailed;
1344
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
2072
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1345
2073
  "span",
1346
2074
  {
1347
2075
  title,
1348
2076
  style: { display: "flex", alignItems: "center", gap: "6px", minWidth: 0 },
1349
2077
  children: [
1350
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2078
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1351
2079
  "span",
1352
2080
  {
1353
2081
  "aria-hidden": "true",
@@ -1363,11 +2091,11 @@ function ReporterChip({
1363
2091
  fontSize: "8px",
1364
2092
  fontWeight: 700,
1365
2093
  letterSpacing: "0.02em",
1366
- background: isAnonymous ? t.inputBg : t.accent,
1367
- color: isAnonymous ? t.textMuted : t.accentText,
1368
- border: `1px solid ${isAnonymous ? t.inputBorder : "transparent"}`
2094
+ background: isAnonymous ? t2.inputBg : t2.accent,
2095
+ color: isAnonymous ? t2.textMuted : t2.accentText,
2096
+ border: `1px solid ${isAnonymous ? t2.inputBorder : "transparent"}`
1369
2097
  },
1370
- children: showAvatarImage ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2098
+ children: showAvatarImage ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1371
2099
  "img",
1372
2100
  {
1373
2101
  src: avatarUrl,
@@ -1377,9 +2105,9 @@ function ReporterChip({
1377
2105
  onError: () => setAvatarFailed(true),
1378
2106
  style: { width: "100%", height: "100%", objectFit: "cover" }
1379
2107
  }
1380
- ) : initials ? initials : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "10", height: "10", viewBox: "0 0 16 16", fill: "none", children: [
1381
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "8", cy: "5.5", r: "2.75", stroke: "currentColor", strokeWidth: "1.4" }),
1382
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2108
+ ) : initials ? initials : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { width: "10", height: "10", viewBox: "0 0 16 16", fill: "none", children: [
2109
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "8", cy: "5.5", r: "2.75", stroke: "currentColor", strokeWidth: "1.4" }),
2110
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1383
2111
  "path",
1384
2112
  {
1385
2113
  d: "M2.75 13.5c0-2.35 2.35-3.75 5.25-3.75s5.25 1.4 5.25 3.75",
@@ -1391,12 +2119,12 @@ function ReporterChip({
1391
2119
  ] })
1392
2120
  }
1393
2121
  ),
1394
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
2122
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1395
2123
  "span",
1396
2124
  {
1397
2125
  style: {
1398
2126
  fontSize: "11px",
1399
- color: t.textMuted,
2127
+ color: t2.textMuted,
1400
2128
  overflow: "hidden",
1401
2129
  textOverflow: "ellipsis",
1402
2130
  whiteSpace: "nowrap"
@@ -1505,6 +2233,8 @@ function ReportDialog({
1505
2233
  report,
1506
2234
  sendFeedback: sendFeedback2,
1507
2235
  enhanceText: enhanceText2,
2236
+ assist,
2237
+ assistContext = null,
1508
2238
  transcribeAudio: transcribeAudio2,
1509
2239
  types,
1510
2240
  showSeverity = true,
@@ -1513,7 +2243,11 @@ function ReportDialog({
1513
2243
  onClose,
1514
2244
  headerSlot
1515
2245
  }) {
2246
+ var _a, _b;
1516
2247
  const [isEnhancing, setIsEnhancing] = (0, import_react.useState)(false);
2248
+ const [assistOpen, setAssistOpen] = (0, import_react.useState)(false);
2249
+ const [assistNotice, setAssistNotice] = (0, import_react.useState)(null);
2250
+ const [assistUsed, setAssistUsed] = (0, import_react.useState)(false);
1517
2251
  const [isEnhanced, setIsEnhanced] = (0, import_react.useState)(false);
1518
2252
  const [originalDescription, setOriginalDescription] = (0, import_react.useState)(
1519
2253
  null
@@ -1639,11 +2373,11 @@ function ReportDialog({
1639
2373
  return () => window.removeEventListener("keydown", onKey);
1640
2374
  }, [isOpen, step, sendFeedback2, availableTypes.join(",")]);
1641
2375
  const handleTileGridKeyDown = (e) => {
1642
- var _a, _b, _c;
2376
+ var _a2, _b2, _c;
1643
2377
  const keys = ["ArrowRight", "ArrowLeft", "ArrowDown", "ArrowUp"];
1644
2378
  if (!keys.includes(e.key)) return;
1645
2379
  const tiles = Array.from(
1646
- (_b = (_a = tileGridRef.current) == null ? void 0 : _a.querySelectorAll("button[data-gg-type]")) != null ? _b : []
2380
+ (_b2 = (_a2 = tileGridRef.current) == null ? void 0 : _a2.querySelectorAll("button[data-gg-type]")) != null ? _b2 : []
1647
2381
  );
1648
2382
  if (tiles.length === 0) return;
1649
2383
  e.preventDefault();
@@ -1653,7 +2387,7 @@ function ReportDialog({
1653
2387
  (_c = tiles[next]) == null ? void 0 : _c.focus();
1654
2388
  };
1655
2389
  const isDark = useIsDark();
1656
- const t = getTheme(isDark);
2390
+ const t2 = getTheme(isDark);
1657
2391
  const canZoomPreview = previewNatural !== null && typeof window !== "undefined" && (previewNatural.w > window.innerWidth - 32 || previewNatural.h > window.innerHeight - 80);
1658
2392
  const handleFileUpload = (e) => {
1659
2393
  const files = e.target.files;
@@ -1721,8 +2455,8 @@ function ReportDialog({
1721
2455
  (0, import_react.useEffect)(() => {
1722
2456
  if (previewIndex === null || annotatingIndex !== null) return;
1723
2457
  const handlePointerDown = (e) => {
1724
- var _a;
1725
- if (!((_a = previewImgRef.current) == null ? void 0 : _a.contains(e.target))) {
2458
+ var _a2;
2459
+ if (!((_a2 = previewImgRef.current) == null ? void 0 : _a2.contains(e.target))) {
1726
2460
  closePreview();
1727
2461
  }
1728
2462
  };
@@ -1730,17 +2464,17 @@ function ReportDialog({
1730
2464
  return () => document.removeEventListener("pointerdown", handlePointerDown, true);
1731
2465
  }, [previewIndex, annotatingIndex]);
1732
2466
  (0, import_react.useEffect)(() => {
1733
- var _a;
2467
+ var _a2;
1734
2468
  const el = previewScrollRef.current;
1735
2469
  if (!previewZoomed || !el) return;
1736
- const anchor = (_a = zoomAnchorRef.current) != null ? _a : { fx: 0.5, fy: 0.5 };
2470
+ const anchor = (_a2 = zoomAnchorRef.current) != null ? _a2 : { fx: 0.5, fy: 0.5 };
1737
2471
  el.scrollLeft = anchor.fx * el.scrollWidth - el.clientWidth / 2;
1738
2472
  el.scrollTop = anchor.fy * el.scrollHeight - el.clientHeight / 2;
1739
2473
  }, [previewZoomed]);
1740
2474
  const togglePreviewZoom = (e) => {
1741
- var _a;
2475
+ var _a2;
1742
2476
  e.stopPropagation();
1743
- if ((_a = panRef.current) == null ? void 0 : _a.moved) return;
2477
+ if ((_a2 = panRef.current) == null ? void 0 : _a2.moved) return;
1744
2478
  if (!previewZoomed && !canZoomPreview) return;
1745
2479
  const img = previewImgElRef.current;
1746
2480
  if (!previewZoomed && img) {
@@ -1775,9 +2509,9 @@ function ReportDialog({
1775
2509
  el.scrollTop = start.top - dy;
1776
2510
  };
1777
2511
  const handlePanEnd = (e) => {
1778
- var _a, _b;
2512
+ var _a2, _b2;
1779
2513
  const el = previewScrollRef.current;
1780
- const moved = (_b = (_a = panRef.current) == null ? void 0 : _a.moved) != null ? _b : false;
2514
+ const moved = (_b2 = (_a2 = panRef.current) == null ? void 0 : _a2.moved) != null ? _b2 : false;
1781
2515
  try {
1782
2516
  el == null ? void 0 : el.releasePointerCapture(e.pointerId);
1783
2517
  } catch (e2) {
@@ -1794,9 +2528,9 @@ function ReportDialog({
1794
2528
  (0, import_react.useEffect)(() => {
1795
2529
  if (!isOpen) return;
1796
2530
  const handlePaste = (e) => {
1797
- var _a;
2531
+ var _a2;
1798
2532
  try {
1799
- const items = (_a = e.clipboardData) == null ? void 0 : _a.items;
2533
+ const items = (_a2 = e.clipboardData) == null ? void 0 : _a2.items;
1800
2534
  if (!items) return;
1801
2535
  const pasted = [];
1802
2536
  for (let i = 0; i < items.length; i++) {
@@ -1822,16 +2556,16 @@ function ReportDialog({
1822
2556
  return () => clearInterval(id);
1823
2557
  }, [isOpen, transcribeAudio2]);
1824
2558
  const stopVoice = () => {
1825
- var _a, _b;
2559
+ var _a2, _b2;
1826
2560
  usingWebSpeechRef.current = false;
1827
- (_a = recognitionRef.current) == null ? void 0 : _a.stop();
2561
+ (_a2 = recognitionRef.current) == null ? void 0 : _a2.stop();
1828
2562
  recognitionRef.current = null;
1829
2563
  sarvamChunksRef.current = [];
1830
2564
  const stream = streamRef.current;
1831
2565
  streamRef.current = null;
1832
- stream == null ? void 0 : stream.getTracks().forEach((t2) => t2.stop());
2566
+ stream == null ? void 0 : stream.getTracks().forEach((t22) => t22.stop());
1833
2567
  try {
1834
- (_b = mediaRecorderRef.current) == null ? void 0 : _b.stop();
2568
+ (_b2 = mediaRecorderRef.current) == null ? void 0 : _b2.stop();
1835
2569
  } catch (e) {
1836
2570
  }
1837
2571
  mediaRecorderRef.current = null;
@@ -1839,16 +2573,28 @@ function ReportDialog({
1839
2573
  setIsTranscribing(false);
1840
2574
  };
1841
2575
  const stopListeningAndTranscribe = () => {
1842
- var _a, _b;
2576
+ var _a2, _b2;
1843
2577
  usingWebSpeechRef.current = false;
1844
- (_a = recognitionRef.current) == null ? void 0 : _a.stop();
2578
+ (_a2 = recognitionRef.current) == null ? void 0 : _a2.stop();
1845
2579
  recognitionRef.current = null;
1846
2580
  setIsListening(false);
1847
2581
  try {
1848
- (_b = mediaRecorderRef.current) == null ? void 0 : _b.stop();
2582
+ (_b2 = mediaRecorderRef.current) == null ? void 0 : _b2.stop();
1849
2583
  } catch (e) {
1850
2584
  }
1851
2585
  };
2586
+ const sheetUp = !!assist && assistOpen && !isRating;
2587
+ (0, import_react.useEffect)(() => {
2588
+ const el = modalRef.current;
2589
+ if (!el) return;
2590
+ if (sheetUp) {
2591
+ el.setAttribute("inert", "");
2592
+ el.setAttribute("aria-hidden", "true");
2593
+ } else {
2594
+ el.removeAttribute("inert");
2595
+ el.removeAttribute("aria-hidden");
2596
+ }
2597
+ }, [sheetUp, isOpen]);
1852
2598
  const handleClose = () => {
1853
2599
  stopVoice();
1854
2600
  setIsOpen(false);
@@ -1864,6 +2610,9 @@ function ReportDialog({
1864
2610
  setVoiceError(null);
1865
2611
  setIsEnhanced(false);
1866
2612
  setOriginalDescription(null);
2613
+ setAssistOpen(false);
2614
+ setAssistUsed(false);
2615
+ setAssistNotice(null);
1867
2616
  };
1868
2617
  const toggleVoice = async () => {
1869
2618
  if (isListening) {
@@ -1891,7 +2640,7 @@ function ReportDialog({
1891
2640
  if (e.data.size > 0) sarvamChunksRef.current.push(e.data);
1892
2641
  };
1893
2642
  rec.onstop = async () => {
1894
- stream.getTracks().forEach((t2) => t2.stop());
2643
+ stream.getTracks().forEach((t22) => t22.stop());
1895
2644
  if (streamRef.current === stream) streamRef.current = null;
1896
2645
  mediaRecorderRef.current = null;
1897
2646
  const chunks = sarvamChunksRef.current;
@@ -1966,7 +2715,7 @@ function ReportDialog({
1966
2715
  }
1967
2716
  };
1968
2717
  const handleSpaceDown = (e) => {
1969
- var _a;
2718
+ var _a2;
1970
2719
  if (e.code !== "Space") return;
1971
2720
  if (isListening || isPushToTalkRef.current) {
1972
2721
  e.preventDefault();
@@ -1974,7 +2723,7 @@ function ReportDialog({
1974
2723
  }
1975
2724
  if (e.repeat || !transcribeAudio2 || isTranscribing || spaceTimerRef.current)
1976
2725
  return;
1977
- const pos = (_a = e.currentTarget.selectionStart) != null ? _a : description.length;
2726
+ const pos = (_a2 = e.currentTarget.selectionStart) != null ? _a2 : description.length;
1978
2727
  spaceTimerRef.current = setTimeout(() => {
1979
2728
  spaceTimerRef.current = null;
1980
2729
  isPushToTalkRef.current = true;
@@ -2063,9 +2812,9 @@ function ReportDialog({
2063
2812
  }
2064
2813
  };
2065
2814
  if (!mounted) return null;
2066
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
2815
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
2067
2816
  isOpen && (0, import_react_dom.createPortal)(
2068
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { children: `
2817
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("style", { children: `
2069
2818
  @keyframes gg-pulse{0%,100%{opacity:1}50%{opacity:0.35}}
2070
2819
  @keyframes gg-b1{0%,100%{height:3px}40%{height:13px}}
2071
2820
  @keyframes gg-b2{0%,100%{height:8px}50%{height:3px}}
@@ -2092,7 +2841,7 @@ function ReportDialog({
2092
2841
  button[data-gg-type]{transition:transform .15s ease,border-color .15s ease,box-shadow .15s ease,background-color .15s ease}
2093
2842
  button[data-gg-type]:hover{transform:translateY(-2px);box-shadow:0 6px 16px rgba(0,0,0,.18)}
2094
2843
  button[data-gg-type]:active{transform:translateY(0) scale(.985);box-shadow:none}
2095
- button[data-gg-type]:focus-visible{outline:2px solid ${t.accent};outline-offset:2px}
2844
+ button[data-gg-type]:focus-visible{outline:2px solid ${t2.accent};outline-offset:2px}
2096
2845
  @keyframes gg-star-pop{0%{transform:scale(.6);opacity:0}60%{transform:scale(1.12)}100%{transform:scale(1);opacity:1}}
2097
2846
  button[data-gg-star]{transition:transform .12s ease}
2098
2847
  button[data-gg-star]:hover{transform:scale(1.18)}
@@ -2102,7 +2851,7 @@ function ReportDialog({
2102
2851
  document.body
2103
2852
  ),
2104
2853
  isOpen && (0, import_react_dom.createPortal)(
2105
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2854
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2106
2855
  "div",
2107
2856
  {
2108
2857
  "data-glitchgrab-layer": "",
@@ -2111,7 +2860,10 @@ function ReportDialog({
2111
2860
  inset: 0,
2112
2861
  zIndex: 2147483647,
2113
2862
  pointerEvents: "auto",
2114
- display: "flex",
2863
+ // Hidden, not unmounted, while the AI sheet is in charge — the
2864
+ // dialog's state IS the report, and unmounting would drop the
2865
+ // screenshots, attachments and step the reporter is on.
2866
+ display: sheetUp ? "none" : "flex",
2115
2867
  alignItems: "center",
2116
2868
  justifyContent: "center",
2117
2869
  backgroundColor: "rgba(0,0,0,0.5)",
@@ -2122,7 +2874,7 @@ function ReportDialog({
2122
2874
  },
2123
2875
  onPointerDown: (e) => e.stopPropagation(),
2124
2876
  onFocus: (e) => e.stopPropagation(),
2125
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
2877
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2126
2878
  "div",
2127
2879
  {
2128
2880
  ref: modalRef,
@@ -2135,25 +2887,25 @@ function ReportDialog({
2135
2887
  maxHeight: "calc(100dvh - 32px)",
2136
2888
  display: "flex",
2137
2889
  flexDirection: "column",
2138
- backgroundColor: t.bg,
2890
+ backgroundColor: t2.bg,
2139
2891
  borderRadius: "12px",
2140
2892
  boxShadow: "0 20px 60px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1)",
2141
2893
  fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
2142
2894
  overflow: "hidden",
2143
- color: t.text,
2895
+ color: t2.text,
2144
2896
  isolation: "isolate"
2145
2897
  },
2146
2898
  children: [
2147
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
2899
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2148
2900
  "div",
2149
2901
  {
2150
2902
  style: {
2151
2903
  flexShrink: 0,
2152
2904
  padding: "16px 16px 12px",
2153
- borderBottom: `1px solid ${t.border}`
2905
+ borderBottom: `1px solid ${t2.border}`
2154
2906
  },
2155
2907
  children: [
2156
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
2908
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2157
2909
  "div",
2158
2910
  {
2159
2911
  style: {
@@ -2162,7 +2914,7 @@ function ReportDialog({
2162
2914
  alignItems: "center"
2163
2915
  },
2164
2916
  children: [
2165
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
2917
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2166
2918
  "div",
2167
2919
  {
2168
2920
  style: {
@@ -2171,7 +2923,7 @@ function ReportDialog({
2171
2923
  gap: "8px"
2172
2924
  },
2173
2925
  children: [
2174
- step > 1 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2926
+ step > 1 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2175
2927
  "button",
2176
2928
  {
2177
2929
  type: "button",
@@ -2185,18 +2937,18 @@ function ReportDialog({
2185
2937
  alignItems: "center"
2186
2938
  },
2187
2939
  "aria-label": "Back",
2188
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2940
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2189
2941
  "svg",
2190
2942
  {
2191
2943
  width: "16",
2192
2944
  height: "16",
2193
2945
  viewBox: "0 0 16 16",
2194
2946
  fill: "none",
2195
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2947
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2196
2948
  "path",
2197
2949
  {
2198
2950
  d: "M10 3L5 8L10 13",
2199
- stroke: t.textMuted,
2951
+ stroke: t2.textMuted,
2200
2952
  strokeWidth: "2",
2201
2953
  strokeLinecap: "round",
2202
2954
  strokeLinejoin: "round"
@@ -2206,13 +2958,13 @@ function ReportDialog({
2206
2958
  )
2207
2959
  }
2208
2960
  ),
2209
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2961
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2210
2962
  "span",
2211
2963
  {
2212
2964
  style: {
2213
2965
  fontSize: "15px",
2214
2966
  fontWeight: 600,
2215
- color: t.text
2967
+ color: t2.text
2216
2968
  },
2217
2969
  children: step === 1 ? "What's on your mind?" : "Tell us more"
2218
2970
  }
@@ -2220,7 +2972,7 @@ function ReportDialog({
2220
2972
  ]
2221
2973
  }
2222
2974
  ),
2223
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
2975
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2224
2976
  "div",
2225
2977
  {
2226
2978
  style: {
@@ -2229,7 +2981,7 @@ function ReportDialog({
2229
2981
  gap: "8px"
2230
2982
  },
2231
2983
  children: [
2232
- step === 1 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2984
+ step === 1 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2233
2985
  "span",
2234
2986
  {
2235
2987
  title: "Press this anywhere to open Glitchgrab",
@@ -2239,15 +2991,15 @@ function ReportDialog({
2239
2991
  lineHeight: 1,
2240
2992
  padding: "3px 6px",
2241
2993
  borderRadius: "4px",
2242
- border: `1px solid ${t.inputBorder}`,
2243
- background: t.inputBg,
2244
- color: t.textMuted,
2994
+ border: `1px solid ${t2.inputBorder}`,
2995
+ background: t2.inputBg,
2996
+ color: t2.textMuted,
2245
2997
  whiteSpace: "nowrap"
2246
2998
  },
2247
2999
  children: getShortcutLabel()
2248
3000
  }
2249
3001
  ),
2250
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3002
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2251
3003
  "button",
2252
3004
  {
2253
3005
  type: "button",
@@ -2262,7 +3014,7 @@ function ReportDialog({
2262
3014
  justifyContent: "center"
2263
3015
  },
2264
3016
  "aria-label": "Close",
2265
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3017
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2266
3018
  "svg",
2267
3019
  {
2268
3020
  width: "16",
@@ -2270,11 +3022,11 @@ function ReportDialog({
2270
3022
  viewBox: "0 0 16 16",
2271
3023
  fill: "none",
2272
3024
  style: { display: "block" },
2273
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3025
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2274
3026
  "path",
2275
3027
  {
2276
3028
  d: "M4 4L12 12M12 4L4 12",
2277
- stroke: t.textMuted,
3029
+ stroke: t2.textMuted,
2278
3030
  strokeWidth: "2",
2279
3031
  strokeLinecap: "round"
2280
3032
  }
@@ -2289,7 +3041,7 @@ function ReportDialog({
2289
3041
  ]
2290
3042
  }
2291
3043
  ),
2292
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3044
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2293
3045
  "div",
2294
3046
  {
2295
3047
  style: {
@@ -2299,30 +3051,30 @@ function ReportDialog({
2299
3051
  gap: "0",
2300
3052
  marginTop: "12px"
2301
3053
  },
2302
- children: [1, 2].map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
3054
+ children: [1, 2].map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2303
3055
  "div",
2304
3056
  {
2305
3057
  style: { display: "flex", alignItems: "center" },
2306
3058
  children: [
2307
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3059
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2308
3060
  "div",
2309
3061
  {
2310
3062
  style: {
2311
3063
  width: "8px",
2312
3064
  height: "8px",
2313
3065
  borderRadius: "50%",
2314
- backgroundColor: s <= step ? t.accent : t.inputBorder,
3066
+ backgroundColor: s <= step ? t2.accent : t2.inputBorder,
2315
3067
  transition: "background-color 0.2s ease"
2316
3068
  }
2317
3069
  }
2318
3070
  ),
2319
- i < 1 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3071
+ i < 1 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2320
3072
  "div",
2321
3073
  {
2322
3074
  style: {
2323
3075
  width: "40px",
2324
3076
  height: "2px",
2325
- backgroundColor: s < step ? t.accent : t.inputBorder,
3077
+ backgroundColor: s < step ? t2.accent : t2.inputBorder,
2326
3078
  transition: "background-color 0.2s ease"
2327
3079
  }
2328
3080
  }
@@ -2336,7 +3088,7 @@ function ReportDialog({
2336
3088
  ]
2337
3089
  }
2338
3090
  ),
2339
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3091
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2340
3092
  "div",
2341
3093
  {
2342
3094
  style: {
@@ -2345,13 +3097,13 @@ function ReportDialog({
2345
3097
  flex: "1 1 auto",
2346
3098
  minHeight: 0
2347
3099
  },
2348
- children: submitted ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
3100
+ children: submitted ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2349
3101
  "div",
2350
3102
  {
2351
3103
  style: {
2352
3104
  textAlign: "center",
2353
3105
  padding: "20px 0",
2354
- color: t.accent,
3106
+ color: t2.accent,
2355
3107
  fontSize: "14px",
2356
3108
  fontWeight: 500
2357
3109
  },
@@ -2360,9 +3112,9 @@ function ReportDialog({
2360
3112
  " sent. Thank you!"
2361
3113
  ]
2362
3114
  }
2363
- ) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
2364
- step === 1 && headerSlot ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { marginBottom: "14px" }, children: headerSlot }) : null,
2365
- step === 1 && sendFeedback2 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
3115
+ ) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
3116
+ step === 1 && headerSlot ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { marginBottom: "14px" }, children: headerSlot }) : null,
3117
+ step === 1 && sendFeedback2 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2366
3118
  "div",
2367
3119
  {
2368
3120
  style: {
@@ -2379,16 +3131,16 @@ function ReportDialog({
2379
3131
  },
2380
3132
  onMouseLeave: () => setHoveredStar(0),
2381
3133
  children: [
2382
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3134
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2383
3135
  "span",
2384
3136
  {
2385
- style: { fontSize: "13px", fontWeight: 600, color: t.text },
3137
+ style: { fontSize: "13px", fontWeight: 600, color: t2.text },
2386
3138
  children: "How are we doing?"
2387
3139
  }
2388
3140
  ),
2389
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { display: "flex", gap: "4px" }, children: [1, 2, 3, 4, 5].map((star) => {
3141
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { display: "flex", gap: "4px" }, children: [1, 2, 3, 4, 5].map((star) => {
2390
3142
  const filled = star <= (hoveredStar || rating);
2391
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3143
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2392
3144
  "button",
2393
3145
  {
2394
3146
  type: "button",
@@ -2408,7 +3160,7 @@ function ReportDialog({
2408
3160
  cursor: "pointer",
2409
3161
  lineHeight: 0
2410
3162
  },
2411
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "26", height: "26", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3163
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: "26", height: "26", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2412
3164
  "path",
2413
3165
  {
2414
3166
  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",
@@ -2425,7 +3177,7 @@ function ReportDialog({
2425
3177
  ]
2426
3178
  }
2427
3179
  ),
2428
- step === 1 && sendFeedback2 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
3180
+ step === 1 && sendFeedback2 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2429
3181
  "div",
2430
3182
  {
2431
3183
  style: {
@@ -2435,13 +3187,13 @@ function ReportDialog({
2435
3187
  marginBottom: "16px"
2436
3188
  },
2437
3189
  children: [
2438
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { flex: 1, height: "1px", background: t.border } }),
2439
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: "11px", color: t.textMuted }, children: "or report something" }),
2440
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { flex: 1, height: "1px", background: t.border } })
3190
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { flex: 1, height: "1px", background: t2.border } }),
3191
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { fontSize: "11px", color: t2.textMuted }, children: "or report something" }),
3192
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { flex: 1, height: "1px", background: t2.border } })
2441
3193
  ]
2442
3194
  }
2443
3195
  ),
2444
- step === 1 && screenshots.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
3196
+ step === 1 && screenshots.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2445
3197
  "div",
2446
3198
  {
2447
3199
  style: {
@@ -2450,12 +3202,12 @@ function ReportDialog({
2450
3202
  gap: "10px",
2451
3203
  marginBottom: "14px",
2452
3204
  padding: "8px 10px",
2453
- border: `1px solid ${t.inputBorder}`,
3205
+ border: `1px solid ${t2.inputBorder}`,
2454
3206
  borderRadius: "8px",
2455
- background: t.inputBg
3207
+ background: t2.inputBg
2456
3208
  },
2457
3209
  children: [
2458
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3210
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2459
3211
  "img",
2460
3212
  {
2461
3213
  src: screenshots[0],
@@ -2465,13 +3217,13 @@ function ReportDialog({
2465
3217
  height: "24px",
2466
3218
  objectFit: "cover",
2467
3219
  borderRadius: "4px",
2468
- border: `1px solid ${t.border}`,
3220
+ border: `1px solid ${t2.border}`,
2469
3221
  flexShrink: 0
2470
3222
  }
2471
3223
  }
2472
3224
  ),
2473
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: "11px", color: t.textMuted, flex: 1 }, children: "Screenshot attached" }),
2474
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3225
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { fontSize: "11px", color: t2.textMuted, flex: 1 }, children: "Screenshot attached" }),
3226
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2475
3227
  "button",
2476
3228
  {
2477
3229
  type: "button",
@@ -2480,7 +3232,7 @@ function ReportDialog({
2480
3232
  style: {
2481
3233
  border: "none",
2482
3234
  background: "transparent",
2483
- color: t.textMuted,
3235
+ color: t2.textMuted,
2484
3236
  cursor: "pointer",
2485
3237
  fontSize: "15px",
2486
3238
  lineHeight: 1,
@@ -2492,7 +3244,7 @@ function ReportDialog({
2492
3244
  ]
2493
3245
  }
2494
3246
  ),
2495
- step === 1 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3247
+ step === 1 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2496
3248
  "div",
2497
3249
  {
2498
3250
  ref: tileGridRef,
@@ -2502,7 +3254,7 @@ function ReportDialog({
2502
3254
  gridTemplateColumns: "1fr 1fr 1fr",
2503
3255
  gap: "10px"
2504
3256
  },
2505
- children: availableTypes.map((type) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
3257
+ children: availableTypes.map((type) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2506
3258
  "button",
2507
3259
  {
2508
3260
  type: "button",
@@ -2518,21 +3270,21 @@ function ReportDialog({
2518
3270
  gap: "9px",
2519
3271
  padding: "18px 10px",
2520
3272
  borderRadius: "8px",
2521
- border: `1px solid ${t.inputBorder}`,
2522
- background: t.inputBg,
3273
+ border: `1px solid ${t2.inputBorder}`,
3274
+ background: t2.inputBg,
2523
3275
  cursor: "pointer",
2524
- color: t.text,
3276
+ color: t2.text,
2525
3277
  fontFamily: "inherit"
2526
3278
  },
2527
3279
  onMouseEnter: (e) => {
2528
- e.currentTarget.style.borderColor = t.accent;
3280
+ e.currentTarget.style.borderColor = t2.accent;
2529
3281
  },
2530
3282
  onMouseLeave: (e) => {
2531
- e.currentTarget.style.borderColor = t.inputBorder;
3283
+ e.currentTarget.style.borderColor = t2.inputBorder;
2532
3284
  },
2533
3285
  children: [
2534
- getTypeIcon(type, t.accent, 22),
2535
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3286
+ getTypeIcon(type, t2.accent, 22),
3287
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2536
3288
  "span",
2537
3289
  {
2538
3290
  style: {
@@ -2550,8 +3302,8 @@ function ReportDialog({
2550
3302
  ))
2551
3303
  }
2552
3304
  ),
2553
- step === 2 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
2554
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
3305
+ step === 2 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
3306
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2555
3307
  "button",
2556
3308
  {
2557
3309
  type: "button",
@@ -2563,22 +3315,22 @@ function ReportDialog({
2563
3315
  marginBottom: "10px",
2564
3316
  padding: "4px 10px 4px 8px",
2565
3317
  borderRadius: "999px",
2566
- border: `1px solid ${isRating ? "rgba(245,158,11,0.4)" : t.inputBorder}`,
2567
- background: isRating ? "rgba(245,158,11,0.1)" : t.inputBg,
2568
- color: t.text,
3318
+ border: `1px solid ${isRating ? "rgba(245,158,11,0.4)" : t2.inputBorder}`,
3319
+ background: isRating ? "rgba(245,158,11,0.1)" : t2.inputBg,
3320
+ color: t2.text,
2569
3321
  fontSize: "11px",
2570
3322
  fontWeight: 600,
2571
3323
  fontFamily: "inherit",
2572
3324
  cursor: "pointer"
2573
3325
  },
2574
3326
  children: [
2575
- getTypeIcon(reportType, isRating ? "#f59e0b" : t.accent, 13),
3327
+ getTypeIcon(reportType, isRating ? "#f59e0b" : t2.accent, 13),
2576
3328
  getTypeLabel(reportType),
2577
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { color: t.textMuted, fontWeight: 400 }, children: "\xB7 change" })
3329
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: t2.textMuted, fontWeight: 400 }, children: "\xB7 change" })
2578
3330
  ]
2579
3331
  }
2580
3332
  ),
2581
- isRating && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3333
+ isRating && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2582
3334
  "div",
2583
3335
  {
2584
3336
  style: {
@@ -2589,7 +3341,7 @@ function ReportDialog({
2589
3341
  onMouseLeave: () => setHoveredStar(0),
2590
3342
  children: [1, 2, 3, 4, 5].map((star) => {
2591
3343
  const filled = star <= (hoveredStar || rating);
2592
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3344
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2593
3345
  "button",
2594
3346
  {
2595
3347
  type: "button",
@@ -2606,12 +3358,12 @@ function ReportDialog({
2606
3358
  cursor: "pointer",
2607
3359
  lineHeight: 0
2608
3360
  },
2609
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "30", height: "30", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3361
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: "30", height: "30", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2610
3362
  "path",
2611
3363
  {
2612
3364
  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",
2613
3365
  fill: filled ? "#f59e0b" : "transparent",
2614
- stroke: filled ? "#f59e0b" : t.inputBorder,
3366
+ stroke: filled ? "#f59e0b" : t2.inputBorder,
2615
3367
  strokeWidth: "1.5",
2616
3368
  strokeLinejoin: "round"
2617
3369
  }
@@ -2622,8 +3374,47 @@ function ReportDialog({
2622
3374
  })
2623
3375
  }
2624
3376
  ),
2625
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { position: "relative" }, children: [
2626
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3377
+ assist && !isRating && !assistUsed && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3378
+ "button",
3379
+ {
3380
+ type: "button",
3381
+ onClick: () => {
3382
+ setAssistNotice(null);
3383
+ setAssistOpen(true);
3384
+ },
3385
+ style: {
3386
+ display: "inline-flex",
3387
+ alignItems: "center",
3388
+ gap: "6px",
3389
+ marginBottom: "10px",
3390
+ // 8px vertical keeps the tap target at ~32px.
3391
+ padding: "8px 10px",
3392
+ borderRadius: "6px",
3393
+ border: `1px solid ${t2.accent}`,
3394
+ background: "transparent",
3395
+ color: t2.accent,
3396
+ fontSize: "12px",
3397
+ fontWeight: 600,
3398
+ fontFamily: "inherit",
3399
+ cursor: "pointer"
3400
+ },
3401
+ title: "Answer a question or two and the assistant writes the report for you",
3402
+ children: [
3403
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3404
+ "path",
3405
+ {
3406
+ 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",
3407
+ stroke: t2.accent,
3408
+ strokeWidth: "1.5",
3409
+ strokeLinejoin: "round"
3410
+ }
3411
+ ) }),
3412
+ "Describe it with AI"
3413
+ ]
3414
+ }
3415
+ ),
3416
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { position: "relative" }, children: [
3417
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2627
3418
  "textarea",
2628
3419
  {
2629
3420
  ref: textareaRef,
@@ -2642,29 +3433,29 @@ function ReportDialog({
2642
3433
  minHeight: "100px",
2643
3434
  padding: enhanceText2 ? "28px 12px 36px" : transcribeAudio2 ? "10px 12px 36px" : "10px 12px",
2644
3435
  borderRadius: "8px",
2645
- border: `1px solid ${isTranscribing ? "#f59e0b" : isListening ? t.accent : t.inputBorder}`,
3436
+ border: `1px solid ${isTranscribing ? "#f59e0b" : isListening ? t2.accent : t2.inputBorder}`,
2646
3437
  fontSize: "14px",
2647
3438
  fontFamily: "inherit",
2648
3439
  resize: "none",
2649
3440
  outline: "none",
2650
3441
  boxSizing: "border-box",
2651
- color: t.text,
2652
- backgroundColor: t.inputBg,
3442
+ color: t2.text,
3443
+ backgroundColor: t2.inputBg,
2653
3444
  transition: "border-color 0.2s ease"
2654
3445
  },
2655
3446
  onKeyDown: handleSpaceDown,
2656
3447
  onKeyUp: handleSpaceUp,
2657
3448
  onFocus: (e) => {
2658
- e.target.style.borderColor = t.accent;
3449
+ e.target.style.borderColor = t2.accent;
2659
3450
  },
2660
3451
  onBlur: (e) => {
2661
3452
  if (!isListening && !isTranscribing)
2662
- e.target.style.borderColor = t.inputBorder;
3453
+ e.target.style.borderColor = t2.inputBorder;
2663
3454
  },
2664
3455
  autoFocus: true
2665
3456
  }
2666
3457
  ),
2667
- (isListening || isTranscribing) && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
3458
+ (isListening || isTranscribing) && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2668
3459
  "span",
2669
3460
  {
2670
3461
  style: {
@@ -2682,7 +3473,7 @@ function ReportDialog({
2682
3473
  zIndex: 1
2683
3474
  },
2684
3475
  children: [
2685
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3476
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2686
3477
  "span",
2687
3478
  {
2688
3479
  style: {
@@ -2697,7 +3488,7 @@ function ReportDialog({
2697
3488
  }
2698
3489
  ),
2699
3490
  isTranscribing ? "Transcribing\u2026" : "REC",
2700
- isListening && !isTranscribing && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3491
+ isListening && !isTranscribing && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2701
3492
  "span",
2702
3493
  {
2703
3494
  style: {
@@ -2724,7 +3515,7 @@ function ReportDialog({
2724
3515
  dur: "0.55s",
2725
3516
  delay: "0.15s"
2726
3517
  }
2727
- ].map((b, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3518
+ ].map((b, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2728
3519
  "span",
2729
3520
  {
2730
3521
  style: {
@@ -2744,18 +3535,18 @@ function ReportDialog({
2744
3535
  ]
2745
3536
  }
2746
3537
  ),
2747
- enhanceText2 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
3538
+ enhanceText2 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2748
3539
  "button",
2749
3540
  {
2750
3541
  type: "button",
2751
3542
  onClick: async () => {
2752
- var _a;
3543
+ var _a2;
2753
3544
  if (!description.trim() || isEnhancing) return;
2754
3545
  setIsEnhancing(true);
2755
3546
  try {
2756
3547
  const polished = await enhanceText2(
2757
3548
  description,
2758
- (_a = screenshots[0]) != null ? _a : null
3549
+ (_a2 = screenshots[0]) != null ? _a2 : null
2759
3550
  );
2760
3551
  if (polished && polished !== description) {
2761
3552
  setOriginalDescription(description);
@@ -2776,20 +3567,20 @@ function ReportDialog({
2776
3567
  display: "inline-flex",
2777
3568
  alignItems: "center",
2778
3569
  gap: "4px",
2779
- background: t.inputBg,
3570
+ background: t2.inputBg,
2780
3571
  border: "none",
2781
3572
  padding: "2px 6px",
2782
3573
  borderRadius: "4px",
2783
3574
  fontFamily: "inherit",
2784
3575
  fontSize: "11px",
2785
- color: t.textMuted,
3576
+ color: t2.textMuted,
2786
3577
  cursor: !description.trim() || isEnhancing ? "default" : "pointer",
2787
3578
  opacity: !description.trim() ? 0.5 : 1,
2788
3579
  zIndex: 1
2789
3580
  },
2790
3581
  title: "Polish grammar \u2014 preserves your meaning",
2791
3582
  children: [
2792
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3583
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2793
3584
  "svg",
2794
3585
  {
2795
3586
  width: "11",
@@ -2797,11 +3588,11 @@ function ReportDialog({
2797
3588
  viewBox: "0 0 24 24",
2798
3589
  fill: "none",
2799
3590
  "aria-hidden": "true",
2800
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3591
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2801
3592
  "path",
2802
3593
  {
2803
3594
  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",
2804
- stroke: t.textMuted,
3595
+ stroke: t2.textMuted,
2805
3596
  strokeWidth: "1.5",
2806
3597
  strokeLinejoin: "round"
2807
3598
  }
@@ -2812,7 +3603,7 @@ function ReportDialog({
2812
3603
  ]
2813
3604
  }
2814
3605
  ),
2815
- transcribeAudio2 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3606
+ transcribeAudio2 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2816
3607
  "button",
2817
3608
  {
2818
3609
  type: "button",
@@ -2830,15 +3621,15 @@ function ReportDialog({
2830
3621
  alignItems: "center",
2831
3622
  justifyContent: "center",
2832
3623
  background: "transparent",
2833
- border: `1.5px solid ${isListening ? "#ef4444" : t.inputBorder}`,
3624
+ border: `1.5px solid ${isListening ? "#ef4444" : t2.inputBorder}`,
2834
3625
  borderRadius: "6px",
2835
- color: isListening ? "#ef4444" : t.textMuted,
3626
+ color: isListening ? "#ef4444" : t2.textMuted,
2836
3627
  cursor: "pointer",
2837
3628
  zIndex: 1,
2838
3629
  padding: 0,
2839
3630
  transition: "border-color 0.2s ease, color 0.2s ease"
2840
3631
  },
2841
- children: isListening ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3632
+ children: isListening ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2842
3633
  "svg",
2843
3634
  {
2844
3635
  width: "12",
@@ -2846,7 +3637,7 @@ function ReportDialog({
2846
3637
  viewBox: "0 0 24 24",
2847
3638
  fill: "currentColor",
2848
3639
  "aria-hidden": "true",
2849
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3640
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2850
3641
  "rect",
2851
3642
  {
2852
3643
  x: "6",
@@ -2857,7 +3648,7 @@ function ReportDialog({
2857
3648
  }
2858
3649
  )
2859
3650
  }
2860
- ) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
3651
+ ) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2861
3652
  "svg",
2862
3653
  {
2863
3654
  width: "13",
@@ -2866,7 +3657,7 @@ function ReportDialog({
2866
3657
  fill: "none",
2867
3658
  "aria-hidden": "true",
2868
3659
  children: [
2869
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3660
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2870
3661
  "rect",
2871
3662
  {
2872
3663
  x: "9",
@@ -2878,7 +3669,7 @@ function ReportDialog({
2878
3669
  strokeWidth: "1.8"
2879
3670
  }
2880
3671
  ),
2881
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3672
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2882
3673
  "path",
2883
3674
  {
2884
3675
  d: "M5 10a7 7 0 0014 0M12 19v3M9 22h6",
@@ -2893,7 +3684,7 @@ function ReportDialog({
2893
3684
  }
2894
3685
  )
2895
3686
  ] }),
2896
- transcribeAudio2 && !isListening && !isTranscribing && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
3687
+ transcribeAudio2 && !isListening && !isTranscribing && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2897
3688
  "div",
2898
3689
  {
2899
3690
  style: {
@@ -2902,21 +3693,21 @@ function ReportDialog({
2902
3693
  gap: "5px",
2903
3694
  marginTop: "5px",
2904
3695
  fontSize: "11px",
2905
- color: t.text,
3696
+ color: t2.text,
2906
3697
  opacity: 0.55,
2907
3698
  userSelect: "none"
2908
3699
  },
2909
3700
  children: [
2910
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2911
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z" }),
2912
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
2913
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "12", x2: "12", y1: "19", y2: "22" })
3701
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
3702
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z" }),
3703
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
3704
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "12", x2: "12", y1: "19", y2: "22" })
2914
3705
  ] }),
2915
3706
  "Hold Space to speak \u2014 we'll transcribe it"
2916
3707
  ]
2917
3708
  }
2918
3709
  ),
2919
- isEnhanced && originalDescription !== null && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
3710
+ isEnhanced && originalDescription !== null && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2920
3711
  "div",
2921
3712
  {
2922
3713
  style: {
@@ -2927,10 +3718,10 @@ function ReportDialog({
2927
3718
  padding: "6px 8px",
2928
3719
  borderRadius: "6px",
2929
3720
  background: isDark ? "rgba(34,211,238,0.06)" : "rgba(8,145,178,0.05)",
2930
- border: `1px solid ${t.accent}40`
3721
+ border: `1px solid ${t2.accent}40`
2931
3722
  },
2932
3723
  children: [
2933
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3724
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2934
3725
  "svg",
2935
3726
  {
2936
3727
  width: "12",
@@ -2938,29 +3729,29 @@ function ReportDialog({
2938
3729
  viewBox: "0 0 24 24",
2939
3730
  fill: "none",
2940
3731
  style: { flexShrink: 0 },
2941
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3732
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2942
3733
  "path",
2943
3734
  {
2944
3735
  d: "M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3z",
2945
- stroke: t.accent,
3736
+ stroke: t2.accent,
2946
3737
  strokeWidth: "1.5",
2947
3738
  strokeLinejoin: "round"
2948
3739
  }
2949
3740
  )
2950
3741
  }
2951
3742
  ),
2952
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3743
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2953
3744
  "span",
2954
3745
  {
2955
3746
  style: {
2956
3747
  fontSize: "11px",
2957
- color: t.textMuted,
3748
+ color: t2.textMuted,
2958
3749
  flex: 1
2959
3750
  },
2960
3751
  children: "AI enhanced"
2961
3752
  }
2962
3753
  ),
2963
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3754
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2964
3755
  "button",
2965
3756
  {
2966
3757
  type: "button",
@@ -2971,9 +3762,9 @@ function ReportDialog({
2971
3762
  style: {
2972
3763
  padding: "2px 8px",
2973
3764
  borderRadius: "4px",
2974
- border: `1px solid ${t.accent}`,
2975
- background: t.accent,
2976
- color: t.accentText,
3765
+ border: `1px solid ${t2.accent}`,
3766
+ background: t2.accent,
3767
+ color: t2.accentText,
2977
3768
  fontSize: "11px",
2978
3769
  fontWeight: 600,
2979
3770
  cursor: "pointer",
@@ -2982,7 +3773,7 @@ function ReportDialog({
2982
3773
  children: "Keep"
2983
3774
  }
2984
3775
  ),
2985
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3776
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2986
3777
  "button",
2987
3778
  {
2988
3779
  type: "button",
@@ -2994,9 +3785,9 @@ function ReportDialog({
2994
3785
  style: {
2995
3786
  padding: "2px 8px",
2996
3787
  borderRadius: "4px",
2997
- border: `1px solid ${t.inputBorder}`,
3788
+ border: `1px solid ${t2.inputBorder}`,
2998
3789
  background: "transparent",
2999
- color: t.textMuted,
3790
+ color: t2.textMuted,
3000
3791
  fontSize: "11px",
3001
3792
  fontWeight: 600,
3002
3793
  cursor: "pointer",
@@ -3008,7 +3799,7 @@ function ReportDialog({
3008
3799
  ]
3009
3800
  }
3010
3801
  ),
3011
- voiceError && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3802
+ voiceError && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3012
3803
  "p",
3013
3804
  {
3014
3805
  style: {
@@ -3020,13 +3811,26 @@ function ReportDialog({
3020
3811
  children: voiceError
3021
3812
  }
3022
3813
  ),
3023
- !isRating && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { marginTop: "10px" }, children: [
3024
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
3814
+ assistNotice && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3815
+ "p",
3816
+ {
3817
+ style: {
3818
+ color: t2.textMuted,
3819
+ fontSize: "12px",
3820
+ marginTop: "6px",
3821
+ marginBottom: 0,
3822
+ lineHeight: 1.5
3823
+ },
3824
+ children: assistNotice
3825
+ }
3826
+ ),
3827
+ !isRating && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { marginTop: "10px" }, children: [
3828
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3025
3829
  "span",
3026
3830
  {
3027
3831
  style: {
3028
3832
  fontSize: "12px",
3029
- color: t.textMuted,
3833
+ color: t2.textMuted,
3030
3834
  marginBottom: "6px",
3031
3835
  display: "block",
3032
3836
  fontWeight: 500
@@ -3037,7 +3841,7 @@ function ReportDialog({
3037
3841
  ]
3038
3842
  }
3039
3843
  ),
3040
- screenshots.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3844
+ screenshots.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3041
3845
  "div",
3042
3846
  {
3043
3847
  style: {
@@ -3046,7 +3850,7 @@ function ReportDialog({
3046
3850
  gap: "8px",
3047
3851
  marginBottom: "8px"
3048
3852
  },
3049
- children: screenshots.map((src, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
3853
+ children: screenshots.map((src, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3050
3854
  "div",
3051
3855
  {
3052
3856
  style: {
@@ -3055,7 +3859,7 @@ function ReportDialog({
3055
3859
  height: "56px"
3056
3860
  },
3057
3861
  children: [
3058
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3862
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3059
3863
  "img",
3060
3864
  {
3061
3865
  src,
@@ -3065,7 +3869,7 @@ function ReportDialog({
3065
3869
  width: "100%",
3066
3870
  height: "100%",
3067
3871
  borderRadius: "6px",
3068
- border: `1px solid ${t.border}`,
3872
+ border: `1px solid ${t2.border}`,
3069
3873
  objectFit: "cover",
3070
3874
  objectPosition: "top",
3071
3875
  cursor: "zoom-in",
@@ -3073,7 +3877,7 @@ function ReportDialog({
3073
3877
  }
3074
3878
  }
3075
3879
  ),
3076
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3880
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3077
3881
  "button",
3078
3882
  {
3079
3883
  type: "button",
@@ -3099,14 +3903,14 @@ function ReportDialog({
3099
3903
  alignItems: "center",
3100
3904
  justifyContent: "center"
3101
3905
  },
3102
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3906
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3103
3907
  "svg",
3104
3908
  {
3105
3909
  width: "8",
3106
3910
  height: "8",
3107
3911
  viewBox: "0 0 10 10",
3108
3912
  fill: "none",
3109
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3913
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3110
3914
  "path",
3111
3915
  {
3112
3916
  d: "M1 1L9 9M9 1L1 9",
@@ -3119,7 +3923,7 @@ function ReportDialog({
3119
3923
  )
3120
3924
  }
3121
3925
  ),
3122
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3926
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3123
3927
  "button",
3124
3928
  {
3125
3929
  type: "button",
@@ -3135,8 +3939,8 @@ function ReportDialog({
3135
3939
  height: "24px",
3136
3940
  borderRadius: "50%",
3137
3941
  border: "none",
3138
- background: t.accent,
3139
- color: t.accentText,
3942
+ background: t2.accent,
3943
+ color: t2.accentText,
3140
3944
  padding: 0,
3141
3945
  cursor: "pointer",
3142
3946
  display: "flex",
@@ -3144,14 +3948,14 @@ function ReportDialog({
3144
3948
  justifyContent: "center",
3145
3949
  boxShadow: "0 2px 8px rgba(0,0,0,0.45)"
3146
3950
  },
3147
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3951
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3148
3952
  "svg",
3149
3953
  {
3150
3954
  width: "12",
3151
3955
  height: "12",
3152
3956
  viewBox: "0 0 24 24",
3153
3957
  fill: "none",
3154
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3958
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3155
3959
  "path",
3156
3960
  {
3157
3961
  d: "M12 20h9M16.5 3.5a2.12 2.12 0 013 3L7 19l-4 1 1-4L16.5 3.5z",
@@ -3171,7 +3975,7 @@ function ReportDialog({
3171
3975
  ))
3172
3976
  }
3173
3977
  ),
3174
- attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3978
+ attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3175
3979
  "div",
3176
3980
  {
3177
3981
  style: {
@@ -3180,7 +3984,7 @@ function ReportDialog({
3180
3984
  gap: "6px",
3181
3985
  marginBottom: "8px"
3182
3986
  },
3183
- children: attachments.map((a, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
3987
+ children: attachments.map((a, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3184
3988
  "div",
3185
3989
  {
3186
3990
  style: {
@@ -3189,10 +3993,10 @@ function ReportDialog({
3189
3993
  gap: "8px",
3190
3994
  padding: "6px 8px",
3191
3995
  borderRadius: "6px",
3192
- border: `1px solid ${t.border}`
3996
+ border: `1px solid ${t2.border}`
3193
3997
  },
3194
3998
  children: [
3195
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
3999
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3196
4000
  "svg",
3197
4001
  {
3198
4002
  width: "14",
@@ -3201,21 +4005,21 @@ function ReportDialog({
3201
4005
  fill: "none",
3202
4006
  style: { flexShrink: 0, opacity: 0.6 },
3203
4007
  children: [
3204
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4008
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3205
4009
  "path",
3206
4010
  {
3207
4011
  d: "M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z",
3208
- stroke: t.textMuted,
4012
+ stroke: t2.textMuted,
3209
4013
  strokeWidth: "1.5",
3210
4014
  strokeLinecap: "round",
3211
4015
  strokeLinejoin: "round"
3212
4016
  }
3213
4017
  ),
3214
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4018
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3215
4019
  "path",
3216
4020
  {
3217
4021
  d: "M14 2v6h6",
3218
- stroke: t.textMuted,
4022
+ stroke: t2.textMuted,
3219
4023
  strokeWidth: "1.5",
3220
4024
  strokeLinecap: "round",
3221
4025
  strokeLinejoin: "round"
@@ -3224,12 +4028,12 @@ function ReportDialog({
3224
4028
  ]
3225
4029
  }
3226
4030
  ),
3227
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4031
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3228
4032
  "span",
3229
4033
  {
3230
4034
  style: {
3231
4035
  fontSize: "11px",
3232
- color: t.text,
4036
+ color: t2.text,
3233
4037
  flex: 1,
3234
4038
  overflow: "hidden",
3235
4039
  textOverflow: "ellipsis",
@@ -3238,17 +4042,17 @@ function ReportDialog({
3238
4042
  children: a.name
3239
4043
  }
3240
4044
  ),
3241
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
4045
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3242
4046
  "span",
3243
4047
  {
3244
- style: { fontSize: "10px", color: t.textMuted },
4048
+ style: { fontSize: "10px", color: t2.textMuted },
3245
4049
  children: [
3246
4050
  (a.size / 1024).toFixed(0),
3247
4051
  "KB"
3248
4052
  ]
3249
4053
  }
3250
4054
  ),
3251
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4055
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3252
4056
  "button",
3253
4057
  {
3254
4058
  type: "button",
@@ -3272,14 +4076,14 @@ function ReportDialog({
3272
4076
  justifyContent: "center",
3273
4077
  flexShrink: 0
3274
4078
  },
3275
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4079
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3276
4080
  "svg",
3277
4081
  {
3278
4082
  width: "8",
3279
4083
  height: "8",
3280
4084
  viewBox: "0 0 10 10",
3281
4085
  fill: "none",
3282
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4086
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3283
4087
  "path",
3284
4088
  {
3285
4089
  d: "M1 1L9 9M9 1L1 9",
@@ -3298,12 +4102,12 @@ function ReportDialog({
3298
4102
  ))
3299
4103
  }
3300
4104
  ),
3301
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4105
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3302
4106
  "div",
3303
4107
  {
3304
4108
  onClick: () => {
3305
- var _a;
3306
- return (_a = fileInputRef.current) == null ? void 0 : _a.click();
4109
+ var _a2;
4110
+ return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
3307
4111
  },
3308
4112
  onDrop: (e) => {
3309
4113
  e.preventDefault();
@@ -3316,7 +4120,7 @@ function ReportDialog({
3316
4120
  },
3317
4121
  onDragLeave: () => setScreenshotDragOver(false),
3318
4122
  style: {
3319
- border: `1.5px dashed ${screenshotDragOver ? t.accent : t.inputBorder}`,
4123
+ border: `1.5px dashed ${screenshotDragOver ? t2.accent : t2.inputBorder}`,
3320
4124
  borderRadius: "8px",
3321
4125
  padding: screenshots.length + attachments.length > 0 ? "8px 12px" : "18px 12px",
3322
4126
  textAlign: "center",
@@ -3324,19 +4128,19 @@ function ReportDialog({
3324
4128
  background: screenshotDragOver ? isDark ? "rgba(34,211,238,0.06)" : "rgba(8,145,178,0.04)" : "transparent",
3325
4129
  transition: "border-color 0.15s ease, background 0.15s ease"
3326
4130
  },
3327
- children: screenshots.length + attachments.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4131
+ children: screenshots.length + attachments.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3328
4132
  "p",
3329
4133
  {
3330
4134
  style: {
3331
4135
  margin: 0,
3332
4136
  fontSize: "11px",
3333
4137
  fontWeight: 500,
3334
- color: t.textMuted
4138
+ color: t2.textMuted
3335
4139
  },
3336
4140
  children: screenshotDragOver ? "Drop to attach" : "+ Add more \xB7 Drag & drop \xB7 Paste"
3337
4141
  }
3338
- ) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
3339
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
4142
+ ) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
4143
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3340
4144
  "svg",
3341
4145
  {
3342
4146
  width: "22",
@@ -3349,7 +4153,7 @@ function ReportDialog({
3349
4153
  opacity: 0.45
3350
4154
  },
3351
4155
  children: [
3352
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4156
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3353
4157
  "rect",
3354
4158
  {
3355
4159
  x: "3",
@@ -3357,25 +4161,25 @@ function ReportDialog({
3357
4161
  width: "18",
3358
4162
  height: "18",
3359
4163
  rx: "2",
3360
- stroke: t.textMuted,
4164
+ stroke: t2.textMuted,
3361
4165
  strokeWidth: "1.5"
3362
4166
  }
3363
4167
  ),
3364
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4168
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3365
4169
  "circle",
3366
4170
  {
3367
4171
  cx: "8.5",
3368
4172
  cy: "8.5",
3369
4173
  r: "1.5",
3370
- stroke: t.textMuted,
4174
+ stroke: t2.textMuted,
3371
4175
  strokeWidth: "1.5"
3372
4176
  }
3373
4177
  ),
3374
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4178
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3375
4179
  "path",
3376
4180
  {
3377
4181
  d: "M21 15l-5-5L5 21",
3378
- stroke: t.textMuted,
4182
+ stroke: t2.textMuted,
3379
4183
  strokeWidth: "1.5",
3380
4184
  strokeLinecap: "round",
3381
4185
  strokeLinejoin: "round"
@@ -3384,25 +4188,25 @@ function ReportDialog({
3384
4188
  ]
3385
4189
  }
3386
4190
  ),
3387
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4191
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3388
4192
  "p",
3389
4193
  {
3390
4194
  style: {
3391
4195
  margin: 0,
3392
4196
  fontSize: "12px",
3393
4197
  fontWeight: 600,
3394
- color: t.text
4198
+ color: t2.text
3395
4199
  },
3396
4200
  children: screenshotDragOver ? "Drop to attach" : "Add screenshots or files"
3397
4201
  }
3398
4202
  ),
3399
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4203
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3400
4204
  "p",
3401
4205
  {
3402
4206
  style: {
3403
4207
  margin: "3px 0 0",
3404
4208
  fontSize: "11px",
3405
- color: t.textMuted
4209
+ color: t2.textMuted
3406
4210
  },
3407
4211
  children: "Images, PDF, DOC, XLS \xB7 Drag & drop \xB7 Paste \u2318V / Ctrl+V \xB7 Click to browse"
3408
4212
  }
@@ -3411,20 +4215,20 @@ function ReportDialog({
3411
4215
  }
3412
4216
  )
3413
4217
  ] }),
3414
- showSeverity && reportType === "BUG" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { marginTop: "10px" }, children: [
3415
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4218
+ showSeverity && reportType === "BUG" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { marginTop: "10px" }, children: [
4219
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3416
4220
  "span",
3417
4221
  {
3418
4222
  style: {
3419
4223
  fontSize: "12px",
3420
- color: t.textMuted,
4224
+ color: t2.textMuted,
3421
4225
  marginBottom: "6px",
3422
4226
  display: "block"
3423
4227
  },
3424
4228
  children: "Severity"
3425
4229
  }
3426
4230
  ),
3427
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { display: "flex", gap: "6px" }, children: ["low", "medium", "high"].map((s) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4231
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { display: "flex", gap: "6px" }, children: ["low", "medium", "high"].map((s) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3428
4232
  "button",
3429
4233
  {
3430
4234
  type: "button",
@@ -3433,9 +4237,9 @@ function ReportDialog({
3433
4237
  flex: 1,
3434
4238
  padding: "6px 0",
3435
4239
  borderRadius: "6px",
3436
- border: `1px solid ${severity === s ? t.accent : t.inputBorder}`,
3437
- background: severity === s ? t.accent : "transparent",
3438
- color: severity === s ? t.accentText : t.text,
4240
+ border: `1px solid ${severity === s ? t2.accent : t2.inputBorder}`,
4241
+ background: severity === s ? t2.accent : "transparent",
4242
+ color: severity === s ? t2.accentText : t2.text,
3439
4243
  fontSize: "12px",
3440
4244
  fontWeight: 600,
3441
4245
  cursor: "pointer",
@@ -3448,7 +4252,7 @@ function ReportDialog({
3448
4252
  s
3449
4253
  )) })
3450
4254
  ] }),
3451
- validationError && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4255
+ validationError && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3452
4256
  "p",
3453
4257
  {
3454
4258
  style: {
@@ -3459,7 +4263,7 @@ function ReportDialog({
3459
4263
  children: validationError
3460
4264
  }
3461
4265
  ),
3462
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4266
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3463
4267
  "button",
3464
4268
  {
3465
4269
  type: "button",
@@ -3471,8 +4275,8 @@ function ReportDialog({
3471
4275
  padding: "10px",
3472
4276
  borderRadius: "8px",
3473
4277
  border: "none",
3474
- backgroundColor: submitDisabled ? t.bgSecondary : t.accent,
3475
- color: submitDisabled ? t.textMuted : t.accentText,
4278
+ backgroundColor: submitDisabled ? t2.bgSecondary : t2.accent,
4279
+ color: submitDisabled ? t2.textMuted : t2.accentText,
3476
4280
  fontSize: "14px",
3477
4281
  fontWeight: 600,
3478
4282
  cursor: submitDisabled ? "not-allowed" : "pointer",
@@ -3486,25 +4290,25 @@ function ReportDialog({
3486
4290
  ] })
3487
4291
  }
3488
4292
  ),
3489
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
4293
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3490
4294
  "div",
3491
4295
  {
3492
4296
  style: {
3493
4297
  padding: "8px 16px 10px",
3494
- borderTop: `1px solid ${t.border}`,
4298
+ borderTop: `1px solid ${t2.border}`,
3495
4299
  display: "flex",
3496
4300
  alignItems: "center",
3497
4301
  justifyContent: "space-between",
3498
4302
  gap: "12px"
3499
4303
  },
3500
4304
  children: [
3501
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ReporterChip, { reporter, t }),
3502
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4305
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ReporterChip, { reporter, t: t2 }),
4306
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3503
4307
  "span",
3504
4308
  {
3505
4309
  style: {
3506
4310
  fontSize: "11px",
3507
- color: t.textMuted,
4311
+ color: t2.textMuted,
3508
4312
  whiteSpace: "nowrap",
3509
4313
  flexShrink: 0
3510
4314
  },
@@ -3521,7 +4325,7 @@ function ReportDialog({
3521
4325
  ),
3522
4326
  document.body
3523
4327
  ),
3524
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4328
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3525
4329
  "input",
3526
4330
  {
3527
4331
  ref: fileInputRef,
@@ -3533,7 +4337,7 @@ function ReportDialog({
3533
4337
  }
3534
4338
  ),
3535
4339
  isOpen && previewIndex !== null && screenshots[previewIndex] && (0, import_react_dom.createPortal)(
3536
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
4340
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3537
4341
  "div",
3538
4342
  {
3539
4343
  "data-glitchgrab-layer": "",
@@ -3555,7 +4359,7 @@ function ReportDialog({
3555
4359
  },
3556
4360
  onMouseDown: (e) => e.stopPropagation(),
3557
4361
  children: [
3558
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
4362
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3559
4363
  "div",
3560
4364
  {
3561
4365
  ref: previewImgRef,
@@ -3567,7 +4371,7 @@ function ReportDialog({
3567
4371
  },
3568
4372
  onClick: (e) => e.stopPropagation(),
3569
4373
  children: [
3570
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4374
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3571
4375
  "div",
3572
4376
  {
3573
4377
  ref: previewScrollRef,
@@ -3586,7 +4390,7 @@ function ReportDialog({
3586
4390
  touchAction: "none",
3587
4391
  cursor: "grab"
3588
4392
  } : { maxWidth: "100%", lineHeight: 0 },
3589
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4393
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3590
4394
  "img",
3591
4395
  {
3592
4396
  ref: previewImgElRef,
@@ -3614,7 +4418,7 @@ function ReportDialog({
3614
4418
  )
3615
4419
  }
3616
4420
  ),
3617
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
4421
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3618
4422
  "button",
3619
4423
  {
3620
4424
  type: "button",
@@ -3632,8 +4436,8 @@ function ReportDialog({
3632
4436
  padding: "8px 14px",
3633
4437
  borderRadius: "999px",
3634
4438
  border: "none",
3635
- background: t.accent,
3636
- color: t.accentText,
4439
+ background: t2.accent,
4440
+ color: t2.accentText,
3637
4441
  fontSize: "13px",
3638
4442
  fontWeight: 700,
3639
4443
  cursor: "pointer",
@@ -3642,7 +4446,7 @@ function ReportDialog({
3642
4446
  animation: "gg-pulse 2s ease-in-out infinite"
3643
4447
  },
3644
4448
  children: [
3645
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4449
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3646
4450
  "path",
3647
4451
  {
3648
4452
  d: "M12 20h9M16.5 3.5a2.12 2.12 0 013 3L7 19l-4 1 1-4L16.5 3.5z",
@@ -3659,7 +4463,7 @@ function ReportDialog({
3659
4463
  ]
3660
4464
  }
3661
4465
  ),
3662
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4466
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3663
4467
  "div",
3664
4468
  {
3665
4469
  style: {
@@ -3668,11 +4472,11 @@ function ReportDialog({
3668
4472
  alignItems: "center",
3669
4473
  gap: "12px"
3670
4474
  },
3671
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4475
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3672
4476
  "span",
3673
4477
  {
3674
4478
  style: {
3675
- color: t.textMuted,
4479
+ color: t2.textMuted,
3676
4480
  fontSize: "12px"
3677
4481
  },
3678
4482
  children: [
@@ -3690,7 +4494,7 @@ function ReportDialog({
3690
4494
  document.body
3691
4495
  ),
3692
4496
  isOpen && annotatingIndex !== null && screenshots[annotatingIndex] && (0, import_react_dom.createPortal)(
3693
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4497
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3694
4498
  AnnotationCanvas,
3695
4499
  {
3696
4500
  imageSrc: screenshots[annotatingIndex],
@@ -3704,6 +4508,52 @@ function ReportDialog({
3704
4508
  }
3705
4509
  ),
3706
4510
  document.body
4511
+ ),
4512
+ isOpen && sheetUp && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
4513
+ AssistSheet,
4514
+ {
4515
+ assist,
4516
+ theme: {
4517
+ bg: t2.bg,
4518
+ bgSecondary: t2.bgSecondary,
4519
+ border: t2.border,
4520
+ text: t2.text,
4521
+ textMuted: t2.textMuted,
4522
+ inputBg: t2.inputBg,
4523
+ inputBorder: t2.inputBorder,
4524
+ accent: t2.accent,
4525
+ accentText: t2.accentText
4526
+ },
4527
+ screenshot: (_a = screenshots[0]) != null ? _a : null,
4528
+ attachmentCount: screenshots.length + attachments.length,
4529
+ context: { ...assistContext != null ? assistContext : {}, reportType },
4530
+ reportTypeLabel: getTypeLabel(reportType),
4531
+ projectSlot: headerSlot,
4532
+ reporterName: (_b = reporter == null ? void 0 : reporter.name) != null ? _b : null,
4533
+ description,
4534
+ onDescriptionChange: (value) => {
4535
+ setDescription(value);
4536
+ if (validationError) setValidationError(null);
4537
+ },
4538
+ severity,
4539
+ onSeverityChange: setSeverity,
4540
+ showSeverity,
4541
+ isSubmitting,
4542
+ submitted,
4543
+ onSend: () => void handleSubmit(),
4544
+ onDegrade: (message) => {
4545
+ setAssistOpen(false);
4546
+ setAssistUsed(true);
4547
+ setAssistNotice(message);
4548
+ },
4549
+ onClose: () => {
4550
+ setAssistOpen(false);
4551
+ requestAnimationFrame(() => {
4552
+ var _a2;
4553
+ return (_a2 = textareaRef.current) == null ? void 0 : _a2.focus();
4554
+ });
4555
+ }
4556
+ }
3707
4557
  )
3708
4558
  ] });
3709
4559
  }
@@ -3757,7 +4607,7 @@ function getTypeIcon(type, color, size = 24) {
3757
4607
  };
3758
4608
  switch (type) {
3759
4609
  case "RATING":
3760
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4610
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3761
4611
  "path",
3762
4612
  {
3763
4613
  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",
@@ -3767,7 +4617,7 @@ function getTypeIcon(type, color, size = 24) {
3767
4617
  }
3768
4618
  ) });
3769
4619
  case "BUG":
3770
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4620
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3771
4621
  "path",
3772
4622
  {
3773
4623
  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",
@@ -3777,7 +4627,7 @@ function getTypeIcon(type, color, size = 24) {
3777
4627
  }
3778
4628
  ) });
3779
4629
  case "FEATURE_REQUEST":
3780
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4630
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3781
4631
  "path",
3782
4632
  {
3783
4633
  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",
@@ -3787,8 +4637,8 @@ function getTypeIcon(type, color, size = 24) {
3787
4637
  }
3788
4638
  ) });
3789
4639
  case "UI_IMPROVEMENT":
3790
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...props, children: [
3791
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4640
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { ...props, children: [
4641
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3792
4642
  "rect",
3793
4643
  {
3794
4644
  x: "3",
@@ -3800,7 +4650,7 @@ function getTypeIcon(type, color, size = 24) {
3800
4650
  strokeWidth: "1.5"
3801
4651
  }
3802
4652
  ),
3803
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4653
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3804
4654
  "path",
3805
4655
  {
3806
4656
  d: "M3 9h18M9 21V9",
@@ -3811,7 +4661,7 @@ function getTypeIcon(type, color, size = 24) {
3811
4661
  )
3812
4662
  ] });
3813
4663
  case "PERFORMANCE":
3814
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4664
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3815
4665
  "path",
3816
4666
  {
3817
4667
  d: "M12 21a9 9 0 100-18 9 9 0 000 18zM12 12l4-4M12 7v.01",
@@ -3822,7 +4672,7 @@ function getTypeIcon(type, color, size = 24) {
3822
4672
  }
3823
4673
  ) });
3824
4674
  case "SECURITY":
3825
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4675
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3826
4676
  "path",
3827
4677
  {
3828
4678
  d: "M12 3l7 3v5c0 4.5-3 8.5-7 10-4-1.5-7-5.5-7-10V6l7-3z",
@@ -3832,9 +4682,9 @@ function getTypeIcon(type, color, size = 24) {
3832
4682
  }
3833
4683
  ) });
3834
4684
  case "QUESTION":
3835
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...props, children: [
3836
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "12", cy: "12", r: "10", stroke: color, strokeWidth: "1.5" }),
3837
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4685
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { ...props, children: [
4686
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "12", cy: "12", r: "10", stroke: color, strokeWidth: "1.5" }),
4687
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3838
4688
  "path",
3839
4689
  {
3840
4690
  d: "M9.09 9a3 3 0 015.83 1c0 2-3 3-3 3M12 17h.01",
@@ -3846,7 +4696,7 @@ function getTypeIcon(type, color, size = 24) {
3846
4696
  )
3847
4697
  ] });
3848
4698
  case "OTHER":
3849
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4699
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3850
4700
  "path",
3851
4701
  {
3852
4702
  d: "M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2v10z",
@@ -3858,6 +4708,400 @@ function getTypeIcon(type, color, size = 24) {
3858
4708
  }
3859
4709
  }
3860
4710
 
4711
+ // src/booking-dialog.tsx
4712
+ var import_react4 = require("react");
4713
+ var import_jsx_runtime4 = require("react/jsx-runtime");
4714
+ var t = {
4715
+ bg: "#141414",
4716
+ surface: "#1c1c1c",
4717
+ border: "#2a2a2a",
4718
+ text: "#e5e5e5",
4719
+ muted: "#9aa0a6",
4720
+ accent: "#3b82f6",
4721
+ danger: "#f87171"
4722
+ };
4723
+ function localZone() {
4724
+ try {
4725
+ return Intl.DateTimeFormat().resolvedOptions().timeZone;
4726
+ } catch (e) {
4727
+ return "UTC";
4728
+ }
4729
+ }
4730
+ function dayKey(iso) {
4731
+ return new Date(iso).toDateString();
4732
+ }
4733
+ function formatDay(iso) {
4734
+ return new Date(iso).toLocaleDateString(void 0, {
4735
+ weekday: "short",
4736
+ day: "numeric",
4737
+ month: "short"
4738
+ });
4739
+ }
4740
+ function formatTime(iso) {
4741
+ return new Date(iso).toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit" });
4742
+ }
4743
+ function BookingDialog({
4744
+ token,
4745
+ baseUrl,
4746
+ open,
4747
+ onClose
4748
+ }) {
4749
+ var _a;
4750
+ const [step, setStep] = (0, import_react4.useState)("slots");
4751
+ const [slots, setSlots] = (0, import_react4.useState)(null);
4752
+ const [heading, setHeading] = (0, import_react4.useState)({
4753
+ title: "Book a demo",
4754
+ description: null
4755
+ });
4756
+ const [whatsappUrl, setWhatsappUrl] = (0, import_react4.useState)(null);
4757
+ const [selected, setSelected] = (0, import_react4.useState)(null);
4758
+ const [name, setName] = (0, import_react4.useState)("");
4759
+ const [email, setEmail] = (0, import_react4.useState)("");
4760
+ const [phone, setPhone] = (0, import_react4.useState)("");
4761
+ const [note, setNote] = (0, import_react4.useState)("");
4762
+ const [code, setCode] = (0, import_react4.useState)("");
4763
+ const [bookingId, setBookingId] = (0, import_react4.useState)(null);
4764
+ const [meetUrl, setMeetUrl] = (0, import_react4.useState)(null);
4765
+ const [busy, setBusy] = (0, import_react4.useState)(false);
4766
+ const [error, setError] = (0, import_react4.useState)(null);
4767
+ const headers = (0, import_react4.useMemo)(
4768
+ () => ({ Authorization: `Bearer ${token}`, "Content-Type": "application/json" }),
4769
+ [token]
4770
+ );
4771
+ const loadSlots = (0, import_react4.useCallback)(async () => {
4772
+ var _a2, _b, _c;
4773
+ setError(null);
4774
+ setSlots(null);
4775
+ try {
4776
+ const from = (/* @__PURE__ */ new Date()).toISOString();
4777
+ const to = new Date(Date.now() + 21 * 864e5).toISOString();
4778
+ const res = await fetch(
4779
+ `${baseUrl}/api/v1/sdk/booking/availability?from=${encodeURIComponent(from)}&to=${encodeURIComponent(to)}`,
4780
+ { headers }
4781
+ );
4782
+ const json = await res.json();
4783
+ if (!json.success) {
4784
+ setError((_a2 = json.error) != null ? _a2 : "Couldn't load available times");
4785
+ setSlots([]);
4786
+ return;
4787
+ }
4788
+ setSlots((_b = json.data.slots) != null ? _b : []);
4789
+ setHeading({ title: json.data.title, description: json.data.description });
4790
+ setWhatsappUrl((_c = json.data.whatsappUrl) != null ? _c : null);
4791
+ } catch (e) {
4792
+ setError("Couldn't reach the booking service");
4793
+ setSlots([]);
4794
+ }
4795
+ }, [baseUrl, headers]);
4796
+ (0, import_react4.useEffect)(() => {
4797
+ if (!open) return;
4798
+ setStep("slots");
4799
+ setSelected(null);
4800
+ setCode("");
4801
+ setBookingId(null);
4802
+ setError(null);
4803
+ void loadSlots();
4804
+ }, [open, loadSlots]);
4805
+ (0, import_react4.useEffect)(() => {
4806
+ if (!open) return;
4807
+ const onKey = (e) => {
4808
+ if (e.key === "Escape") onClose();
4809
+ };
4810
+ document.addEventListener("keydown", onKey, true);
4811
+ return () => document.removeEventListener("keydown", onKey, true);
4812
+ }, [open, onClose]);
4813
+ if (!open) return null;
4814
+ const byDay = /* @__PURE__ */ new Map();
4815
+ for (const slot of slots != null ? slots : []) {
4816
+ const key = dayKey(slot.startsAt);
4817
+ byDay.set(key, [...(_a = byDay.get(key)) != null ? _a : [], slot]);
4818
+ }
4819
+ async function startBooking() {
4820
+ var _a2;
4821
+ if (!selected) return;
4822
+ setBusy(true);
4823
+ setError(null);
4824
+ try {
4825
+ const res = await fetch(`${baseUrl}/api/v1/sdk/booking`, {
4826
+ method: "POST",
4827
+ headers,
4828
+ body: JSON.stringify({
4829
+ name,
4830
+ email,
4831
+ phone,
4832
+ note,
4833
+ startsAt: selected.startsAt,
4834
+ timezone: localZone()
4835
+ })
4836
+ });
4837
+ const json = await res.json();
4838
+ if (!json.success) {
4839
+ setError((_a2 = json.error) != null ? _a2 : "Couldn't hold that slot");
4840
+ return;
4841
+ }
4842
+ setBookingId(json.data.bookingId);
4843
+ setStep("code");
4844
+ } catch (e) {
4845
+ setError("Couldn't reach the booking service");
4846
+ } finally {
4847
+ setBusy(false);
4848
+ }
4849
+ }
4850
+ async function confirmBooking() {
4851
+ var _a2;
4852
+ if (!bookingId) return;
4853
+ setBusy(true);
4854
+ setError(null);
4855
+ try {
4856
+ const res = await fetch(`${baseUrl}/api/v1/sdk/booking/verify`, {
4857
+ method: "POST",
4858
+ headers,
4859
+ body: JSON.stringify({ bookingId, code })
4860
+ });
4861
+ const json = await res.json();
4862
+ if (!json.success) {
4863
+ setError((_a2 = json.error) != null ? _a2 : "Couldn't confirm that code");
4864
+ return;
4865
+ }
4866
+ setMeetUrl(json.data.meetUrl);
4867
+ setStep("done");
4868
+ } catch (e) {
4869
+ setError("Couldn't reach the booking service");
4870
+ } finally {
4871
+ setBusy(false);
4872
+ }
4873
+ }
4874
+ const canSubmitDetails = name.trim() && email.includes("@") && phone.replace(/\D/g, "").length >= 8;
4875
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4876
+ "div",
4877
+ {
4878
+ onClick: (e) => {
4879
+ if (e.target === e.currentTarget) onClose();
4880
+ },
4881
+ style: {
4882
+ position: "fixed",
4883
+ inset: 0,
4884
+ zIndex: 2147483e3,
4885
+ background: "rgba(0,0,0,.6)",
4886
+ display: "flex",
4887
+ alignItems: "center",
4888
+ justifyContent: "center",
4889
+ padding: 16,
4890
+ fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
4891
+ },
4892
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
4893
+ "div",
4894
+ {
4895
+ role: "dialog",
4896
+ "aria-modal": "true",
4897
+ "aria-label": heading.title,
4898
+ style: {
4899
+ width: "min(440px, 100%)",
4900
+ maxHeight: "min(660px, 90vh)",
4901
+ display: "flex",
4902
+ flexDirection: "column",
4903
+ background: t.bg,
4904
+ color: t.text,
4905
+ borderRadius: 16,
4906
+ boxShadow: "0 20px 60px rgba(0,0,0,.55)",
4907
+ overflow: "hidden"
4908
+ },
4909
+ children: [
4910
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
4911
+ "div",
4912
+ {
4913
+ style: {
4914
+ padding: "16px 18px",
4915
+ borderBottom: `1px solid ${t.border}`,
4916
+ display: "flex",
4917
+ alignItems: "flex-start",
4918
+ justifyContent: "space-between",
4919
+ gap: 12
4920
+ },
4921
+ children: [
4922
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
4923
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { fontSize: 15, fontWeight: 600 }, children: heading.title }),
4924
+ heading.description && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { fontSize: 12, color: t.muted, marginTop: 2 }, children: heading.description })
4925
+ ] }),
4926
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4927
+ "button",
4928
+ {
4929
+ onClick: onClose,
4930
+ "aria-label": "Close",
4931
+ style: { border: 0, background: "transparent", color: t.muted, fontSize: 20, cursor: "pointer", lineHeight: 1 },
4932
+ children: "\xD7"
4933
+ }
4934
+ )
4935
+ ]
4936
+ }
4937
+ ),
4938
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { padding: 18, overflowY: "auto", flex: "1 1 auto" }, children: [
4939
+ error && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { color: t.danger, fontSize: 12, marginBottom: 12, lineHeight: 1.5 }, children: error }),
4940
+ step === "slots" && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
4941
+ whatsappUrl && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
4942
+ "a",
4943
+ {
4944
+ href: whatsappUrl,
4945
+ target: "_blank",
4946
+ rel: "noreferrer",
4947
+ style: {
4948
+ display: "block",
4949
+ marginBottom: 16,
4950
+ padding: "10px 14px",
4951
+ borderRadius: 10,
4952
+ border: `1px solid ${t.border}`,
4953
+ background: t.surface,
4954
+ color: t.text,
4955
+ fontSize: 13,
4956
+ textDecoration: "none"
4957
+ },
4958
+ children: [
4959
+ "\u{1F4AC} Rather book on WhatsApp?",
4960
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { display: "block", fontSize: 11, color: t.muted, marginTop: 2 }, children: "We'll ask the same questions in chat." })
4961
+ ]
4962
+ }
4963
+ ),
4964
+ slots === null && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { color: t.muted, fontSize: 13 }, children: "Finding times\u2026" }),
4965
+ (slots == null ? void 0 : slots.length) === 0 && !error && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { color: t.muted, fontSize: 13 }, children: "No times available right now." }),
4966
+ [...byDay.entries()].map(([day, daySlots]) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { marginBottom: 18 }, children: [
4967
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { fontSize: 11, color: t.muted, marginBottom: 8, textTransform: "uppercase", letterSpacing: ".6px" }, children: formatDay(daySlots[0].startsAt) }),
4968
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: 8 }, children: daySlots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4969
+ "button",
4970
+ {
4971
+ onClick: () => {
4972
+ setSelected(slot);
4973
+ setStep("details");
4974
+ },
4975
+ style: {
4976
+ padding: "8px 14px",
4977
+ borderRadius: 999,
4978
+ border: `1px solid ${t.border}`,
4979
+ background: t.surface,
4980
+ color: t.text,
4981
+ fontSize: 13,
4982
+ cursor: "pointer"
4983
+ },
4984
+ children: formatTime(slot.startsAt)
4985
+ },
4986
+ slot.startsAt
4987
+ )) })
4988
+ ] }, day))
4989
+ ] }),
4990
+ step === "details" && selected && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: [
4991
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { fontSize: 13, color: t.muted }, children: [
4992
+ formatDay(selected.startsAt),
4993
+ " \xB7 ",
4994
+ formatTime(selected.startsAt),
4995
+ " \xB7 ",
4996
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4997
+ "button",
4998
+ {
4999
+ onClick: () => setStep("slots"),
5000
+ style: { border: 0, background: "transparent", color: t.accent, cursor: "pointer", fontSize: 13, padding: 0 },
5001
+ children: "change"
5002
+ }
5003
+ )
5004
+ ] }),
5005
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Field, { label: "Your name", value: name, onChange: setName }),
5006
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Field, { label: "Email", value: email, onChange: setEmail, type: "email" }),
5007
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
5008
+ Field,
5009
+ {
5010
+ label: "Mobile number",
5011
+ value: phone,
5012
+ onChange: setPhone,
5013
+ type: "tel",
5014
+ hint: "We send a code here to confirm, then a reminder before the call."
5015
+ }
5016
+ ),
5017
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Field, { label: "Anything we should know? (optional)", value: note, onChange: setNote }),
5018
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
5019
+ "button",
5020
+ {
5021
+ onClick: startBooking,
5022
+ disabled: !canSubmitDetails || busy,
5023
+ style: primaryStyle(!canSubmitDetails || busy),
5024
+ children: busy ? "Sending code\u2026" : "Send verification code"
5025
+ }
5026
+ )
5027
+ ] }),
5028
+ step === "code" && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: [
5029
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("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." }),
5030
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Field, { label: "Code", value: code, onChange: setCode }),
5031
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
5032
+ "button",
5033
+ {
5034
+ onClick: confirmBooking,
5035
+ disabled: code.trim().length < 4 || busy,
5036
+ style: primaryStyle(code.trim().length < 4 || busy),
5037
+ children: busy ? "Confirming\u2026" : "Confirm booking"
5038
+ }
5039
+ )
5040
+ ] }),
5041
+ step === "done" && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: [
5042
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { fontSize: 15, fontWeight: 600 }, children: "You're booked." }),
5043
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { fontSize: 13, color: t.muted, lineHeight: 1.6 }, children: [
5044
+ selected && `${formatDay(selected.startsAt)} at ${formatTime(selected.startsAt)}. `,
5045
+ "A calendar invite is on its way to ",
5046
+ email,
5047
+ ", and we'll send a WhatsApp reminder before the call."
5048
+ ] }),
5049
+ meetUrl && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("a", { href: meetUrl, target: "_blank", rel: "noreferrer", style: { ...primaryStyle(false), textAlign: "center", textDecoration: "none" }, children: "Open the meeting link" })
5050
+ ] })
5051
+ ] })
5052
+ ]
5053
+ }
5054
+ )
5055
+ }
5056
+ );
5057
+ }
5058
+ function primaryStyle(disabled) {
5059
+ return {
5060
+ marginTop: 4,
5061
+ padding: "10px 16px",
5062
+ borderRadius: 999,
5063
+ border: 0,
5064
+ background: disabled ? "#2a2a2a" : t.accent,
5065
+ color: disabled ? "#6b7280" : "#fff",
5066
+ fontSize: 14,
5067
+ fontWeight: 500,
5068
+ cursor: disabled ? "default" : "pointer"
5069
+ };
5070
+ }
5071
+ function Field({
5072
+ label,
5073
+ value,
5074
+ onChange,
5075
+ type = "text",
5076
+ hint
5077
+ }) {
5078
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { style: { display: "block", fontSize: 11, color: t.muted }, children: [
5079
+ label,
5080
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
5081
+ "input",
5082
+ {
5083
+ type,
5084
+ value,
5085
+ onChange: (e) => onChange(e.target.value),
5086
+ style: {
5087
+ display: "block",
5088
+ width: "100%",
5089
+ boxSizing: "border-box",
5090
+ marginTop: 4,
5091
+ padding: "9px 12px",
5092
+ background: t.surface,
5093
+ color: t.text,
5094
+ border: `1px solid ${t.border}`,
5095
+ borderRadius: 8,
5096
+ fontSize: 13,
5097
+ outline: "none"
5098
+ }
5099
+ }
5100
+ ),
5101
+ hint && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { marginTop: 4, fontSize: 10, color: t.muted }, children: hint })
5102
+ ] });
5103
+ }
5104
+
3861
5105
  // src/rejection.ts
3862
5106
  var DETAILS_MAX_LENGTH = 1e3;
3863
5107
  var MESSAGE_MAX_LENGTH = 200;
@@ -3913,6 +5157,36 @@ function describeShape(reason) {
3913
5157
  return "";
3914
5158
  }
3915
5159
  }
5160
+ var EVENT_URL_MAX_LENGTH = 120;
5161
+ function isEventLike(reason) {
5162
+ try {
5163
+ if (typeof Event !== "undefined" && reason instanceof Event) return true;
5164
+ const source = reason;
5165
+ return typeof (source == null ? void 0 : source.type) === "string" && typeof (source == null ? void 0 : source.isTrusted) === "boolean";
5166
+ } catch (e) {
5167
+ return false;
5168
+ }
5169
+ }
5170
+ function describeEvent(reason) {
5171
+ var _a, _b, _c, _d, _e;
5172
+ const parts = [];
5173
+ try {
5174
+ const source = reason;
5175
+ const name = ((_a = source.constructor) == null ? void 0 : _a.name) || "Event";
5176
+ parts.push(`${name} ("${String((_b = source.type) != null ? _b : "")}")`);
5177
+ } catch (e) {
5178
+ parts.push("Event");
5179
+ }
5180
+ try {
5181
+ const target = reason.target;
5182
+ const tag = (_c = target == null ? void 0 : target.tagName) == null ? void 0 : _c.toLowerCase();
5183
+ if (tag) parts.push(`from <${tag}>`);
5184
+ const url = (_e = (_d = readString(target == null ? void 0 : target.currentSrc)) != null ? _d : readString(target == null ? void 0 : target.src)) != null ? _e : readString(target == null ? void 0 : target.href);
5185
+ if (url) parts.push(`\u2014 ${url.split(/[?#]/)[0].slice(0, EVENT_URL_MAX_LENGTH)}`);
5186
+ } catch (e) {
5187
+ }
5188
+ return parts.join(" ").slice(0, MESSAGE_MAX_LENGTH);
5189
+ }
3916
5190
  function describeRejection(reason) {
3917
5191
  var _a, _b, _c, _d, _e, _f, _g, _h;
3918
5192
  try {
@@ -3937,7 +5211,7 @@ function describeRejection(reason) {
3937
5211
  const message = (_h = (_g = (_f = (_e = (_d = (_c = (_b = readString(source.message)) != null ? _b : readString(nestedError)) != null ? _c : readString(nestedError == null ? void 0 : nestedError.message)) != null ? _d : readScalar(source.code)) != null ? _e : readString(source.name)) != null ? _f : readScalar(source.status)) != null ? _g : readString(source.statusText)) != null ? _h : "";
3938
5212
  const details = serialize(reason);
3939
5213
  return {
3940
- message: message || describeShape(reason),
5214
+ message: message || (isEventLike(reason) ? describeEvent(reason) : describeShape(reason)),
3941
5215
  stack,
3942
5216
  details
3943
5217
  };
@@ -3965,11 +5239,11 @@ function matchesShortcut(e) {
3965
5239
  }
3966
5240
 
3967
5241
  // src/provider.tsx
3968
- var import_jsx_runtime3 = require("react/jsx-runtime");
5242
+ var import_jsx_runtime5 = require("react/jsx-runtime");
3969
5243
  var DEFAULT_BASE_URL2 = "https://glitchgrab.dev";
3970
- var GlitchgrabContext = (0, import_react3.createContext)(null);
5244
+ var GlitchgrabContext = (0, import_react5.createContext)(null);
3971
5245
  function useGlitchgrab() {
3972
- const ctx = (0, import_react3.useContext)(GlitchgrabContext);
5246
+ const ctx = (0, import_react5.useContext)(GlitchgrabContext);
3973
5247
  if (!ctx) {
3974
5248
  throw new Error("useGlitchgrab must be used within a GlitchgrabProvider");
3975
5249
  }
@@ -3992,7 +5266,7 @@ function GlitchgrabProviderInner({
3992
5266
  context: appContext2,
3993
5267
  responseBodyOrigins: responseBodyOrigins2
3994
5268
  }) {
3995
- const visitedPagesRef = (0, import_react3.useRef)([]);
5269
+ const visitedPagesRef = (0, import_react5.useRef)([]);
3996
5270
  setRelease(release2);
3997
5271
  if (appContext2) setContexts(appContext2);
3998
5272
  registerCaptureConfig({
@@ -4004,12 +5278,12 @@ function GlitchgrabProviderInner({
4004
5278
  onError,
4005
5279
  onReportSent
4006
5280
  });
4007
- (0, import_react3.useEffect)(() => {
5281
+ (0, import_react5.useEffect)(() => {
4008
5282
  if (enableBreadcrumbs) {
4009
5283
  initBreadcrumbs(maxBreadcrumbs2, { responseBodyOrigins: responseBodyOrigins2 });
4010
5284
  }
4011
5285
  }, [enableBreadcrumbs, maxBreadcrumbs2, responseBodyOrigins2 == null ? void 0 : responseBodyOrigins2.join(",")]);
4012
- (0, import_react3.useEffect)(() => {
5286
+ (0, import_react5.useEffect)(() => {
4013
5287
  try {
4014
5288
  if (typeof window === "undefined") return;
4015
5289
  const trackPage = () => {
@@ -4046,7 +5320,7 @@ function GlitchgrabProviderInner({
4046
5320
  } catch (e) {
4047
5321
  }
4048
5322
  }, []);
4049
- (0, import_react3.useEffect)(() => {
5323
+ (0, import_react5.useEffect)(() => {
4050
5324
  try {
4051
5325
  if (typeof window === "undefined") return;
4052
5326
  if (process.env.NODE_ENV === "development") return;
@@ -4173,7 +5447,7 @@ function GlitchgrabProviderInner({
4173
5447
  } catch (e) {
4174
5448
  }
4175
5449
  }, [token, baseUrl, onError, onReportSent, session, ignoreErrors]);
4176
- const report = (0, import_react3.useCallback)(
5450
+ const report = (0, import_react5.useCallback)(
4177
5451
  async (type, description, metadata) => {
4178
5452
  var _a;
4179
5453
  try {
@@ -4207,11 +5481,11 @@ function GlitchgrabProviderInner({
4207
5481
  },
4208
5482
  [token, baseUrl, onReportSent, session]
4209
5483
  );
4210
- const reportBug = (0, import_react3.useCallback)(
5484
+ const reportBug = (0, import_react5.useCallback)(
4211
5485
  (description, metadata) => report("BUG", description, metadata),
4212
5486
  [report]
4213
5487
  );
4214
- const feedback = (0, import_react3.useCallback)(
5488
+ const feedback = (0, import_react5.useCallback)(
4215
5489
  async (rating, message, metadata) => {
4216
5490
  try {
4217
5491
  const context = captureContext(visitedPagesRef.current);
@@ -4239,32 +5513,32 @@ function GlitchgrabProviderInner({
4239
5513
  },
4240
5514
  [token, baseUrl, session]
4241
5515
  );
4242
- const openFeedbackDialog = (0, import_react3.useCallback)(() => {
5516
+ const openFeedbackDialog = (0, import_react5.useCallback)(() => {
4243
5517
  if (typeof window !== "undefined") {
4244
5518
  window.dispatchEvent(
4245
5519
  new CustomEvent("glitchgrab:open-report", { detail: { type: "RATING" } })
4246
5520
  );
4247
5521
  }
4248
5522
  }, []);
4249
- const captureError2 = (0, import_react3.useCallback)(
5523
+ const captureError2 = (0, import_react5.useCallback)(
4250
5524
  (error, options) => {
4251
5525
  captureError(error, options);
4252
5526
  },
4253
5527
  []
4254
5528
  );
4255
- const setContext2 = (0, import_react3.useCallback)((key, value) => {
5529
+ const setContext2 = (0, import_react5.useCallback)((key, value) => {
4256
5530
  setContext(key, value);
4257
5531
  }, []);
4258
- const setContexts2 = (0, import_react3.useCallback)((values) => {
5532
+ const setContexts2 = (0, import_react5.useCallback)((values) => {
4259
5533
  setContexts(values);
4260
5534
  }, []);
4261
- const addBreadcrumb2 = (0, import_react3.useCallback)(
5535
+ const addBreadcrumb2 = (0, import_react5.useCallback)(
4262
5536
  (message, data) => {
4263
5537
  addBreadcrumb("custom", message, data);
4264
5538
  },
4265
5539
  []
4266
5540
  );
4267
- const enhance = (0, import_react3.useCallback)(
5541
+ const enhance = (0, import_react5.useCallback)(
4268
5542
  async (text, screenshot) => {
4269
5543
  try {
4270
5544
  const ctx = captureContext(visitedPagesRef.current);
@@ -4280,7 +5554,27 @@ function GlitchgrabProviderInner({
4280
5554
  },
4281
5555
  [token, baseUrl]
4282
5556
  );
4283
- const transcribe = (0, import_react3.useCallback)(
5557
+ const assist = (0, import_react5.useCallback)(
5558
+ async (params) => {
5559
+ var _a;
5560
+ const ctx = captureContext(visitedPagesRef.current);
5561
+ return assistTurn(
5562
+ {
5563
+ ...params,
5564
+ context: {
5565
+ ...(_a = params.context) != null ? _a : {},
5566
+ url: ctx.url,
5567
+ visitedPages: ctx.visitedPages.slice(-5),
5568
+ breadcrumbs: ctx.breadcrumbs.slice(-25).map((b) => ({ type: b.type, message: b.message }))
5569
+ }
5570
+ },
5571
+ token,
5572
+ baseUrl
5573
+ );
5574
+ },
5575
+ [token, baseUrl]
5576
+ );
5577
+ const transcribe = (0, import_react5.useCallback)(
4284
5578
  async (blob) => {
4285
5579
  try {
4286
5580
  return await transcribeAudio(blob, token, baseUrl);
@@ -4290,12 +5584,12 @@ function GlitchgrabProviderInner({
4290
5584
  },
4291
5585
  [token, baseUrl]
4292
5586
  );
4293
- const openReportDialog = (0, import_react3.useCallback)((options) => {
5587
+ const openReportDialog = (0, import_react5.useCallback)((options) => {
4294
5588
  if (typeof window !== "undefined") {
4295
5589
  window.dispatchEvent(new CustomEvent("glitchgrab:open-report", { detail: options }));
4296
5590
  }
4297
5591
  }, []);
4298
- (0, import_react3.useEffect)(() => {
5592
+ (0, import_react5.useEffect)(() => {
4299
5593
  try {
4300
5594
  if (typeof document === "undefined") return;
4301
5595
  document.documentElement.setAttribute("data-glitchgrab-sdk", "1");
@@ -4303,8 +5597,11 @@ function GlitchgrabProviderInner({
4303
5597
  } catch (e) {
4304
5598
  }
4305
5599
  }, []);
4306
- const [projectName, setProjectName] = (0, import_react3.useState)(null);
4307
- (0, import_react3.useEffect)(() => {
5600
+ const [projectName, setProjectName] = (0, import_react5.useState)(null);
5601
+ const [aiAssist, setAiAssist] = (0, import_react5.useState)(false);
5602
+ const [bookingOpen, setBookingOpen] = (0, import_react5.useState)(false);
5603
+ const openBookingDialog = (0, import_react5.useCallback)(() => setBookingOpen(true), []);
5604
+ (0, import_react5.useEffect)(() => {
4308
5605
  let cancelled = false;
4309
5606
  fetch(`${baseUrl}/api/v1/sdk/project`, {
4310
5607
  headers: { Authorization: `Bearer ${token}` }
@@ -4312,13 +5609,14 @@ function GlitchgrabProviderInner({
4312
5609
  var _a;
4313
5610
  if (cancelled || !(json == null ? void 0 : json.success) || !((_a = json.data) == null ? void 0 : _a.name)) return;
4314
5611
  setProjectName(json.data.name);
5612
+ setAiAssist(json.data.aiAssist === true);
4315
5613
  }).catch(() => {
4316
5614
  });
4317
5615
  return () => {
4318
5616
  cancelled = true;
4319
5617
  };
4320
5618
  }, [baseUrl, token]);
4321
- (0, import_react3.useEffect)(() => {
5619
+ (0, import_react5.useEffect)(() => {
4322
5620
  try {
4323
5621
  if (typeof window === "undefined") return;
4324
5622
  const handleKeyDown = (e) => {
@@ -4332,7 +5630,7 @@ function GlitchgrabProviderInner({
4332
5630
  } catch (e) {
4333
5631
  }
4334
5632
  }, [openReportDialog]);
4335
- const reporter = (0, import_react3.useMemo)(() => {
5633
+ const reporter = (0, import_react5.useMemo)(() => {
4336
5634
  var _a;
4337
5635
  if (!session) return null;
4338
5636
  const avatar = (_a = session.avatarUrl) != null ? _a : session.image;
@@ -4342,11 +5640,11 @@ function GlitchgrabProviderInner({
4342
5640
  avatarUrl: typeof avatar === "string" ? avatar : null
4343
5641
  };
4344
5642
  }, [session]);
4345
- const [shortcutLabel, setShortcutLabel] = (0, import_react3.useState)(GLITCHGRAB_SHORTCUT2);
4346
- (0, import_react3.useEffect)(() => {
5643
+ const [shortcutLabel, setShortcutLabel] = (0, import_react5.useState)(GLITCHGRAB_SHORTCUT2);
5644
+ (0, import_react5.useEffect)(() => {
4347
5645
  setShortcutLabel(getShortcutLabel2());
4348
5646
  }, []);
4349
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
5647
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
4350
5648
  GlitchgrabContext.Provider,
4351
5649
  {
4352
5650
  value: {
@@ -4361,11 +5659,12 @@ function GlitchgrabProviderInner({
4361
5659
  openFeedbackDialog,
4362
5660
  addBreadcrumb: addBreadcrumb2,
4363
5661
  openReportDialog,
5662
+ openBookingDialog,
4364
5663
  enhanceText: enhance,
4365
5664
  shortcutLabel
4366
5665
  },
4367
5666
  children: [
4368
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
5667
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4369
5668
  GlitchgrabErrorBoundary,
4370
5669
  {
4371
5670
  token,
@@ -4377,19 +5676,29 @@ function GlitchgrabProviderInner({
4377
5676
  children
4378
5677
  }
4379
5678
  ),
4380
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
5679
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
5680
+ BookingDialog,
5681
+ {
5682
+ token,
5683
+ baseUrl: baseUrl != null ? baseUrl : DEFAULT_BASE_URL2,
5684
+ open: bookingOpen,
5685
+ onClose: () => setBookingOpen(false)
5686
+ }
5687
+ ),
5688
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4381
5689
  ReportDialog,
4382
5690
  {
4383
5691
  report,
4384
5692
  sendFeedback: feedback,
4385
5693
  enhanceText: enhance,
5694
+ assist: aiAssist ? assist : void 0,
4386
5695
  transcribeAudio: transcribe,
4387
5696
  types,
4388
5697
  showSeverity,
4389
5698
  reporter,
4390
- headerSlot: projectName ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { fontSize: 11, color: "#9aa0a6" }, children: [
5699
+ headerSlot: projectName ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { fontSize: 11, color: "#9aa0a6" }, children: [
4391
5700
  "Reporting to ",
4392
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { style: { color: "#e5e5e5" }, children: projectName })
5701
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("strong", { style: { color: "#e5e5e5" }, children: projectName })
4393
5702
  ] }) : null
4394
5703
  }
4395
5704
  )
@@ -4398,21 +5707,21 @@ function GlitchgrabProviderInner({
4398
5707
  );
4399
5708
  }
4400
5709
  function GlitchgrabProvider(props) {
4401
- if (!props.token) return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: props.children });
5710
+ if (!props.token) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: props.children });
4402
5711
  const resolvedProps = {
4403
5712
  ...props,
4404
5713
  baseUrl: props.baseUrl || DEFAULT_BASE_URL2
4405
5714
  };
4406
5715
  try {
4407
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(GlitchgrabProviderInner, { ...resolvedProps });
5716
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(GlitchgrabProviderInner, { ...resolvedProps });
4408
5717
  } catch (e) {
4409
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: props.children });
5718
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: props.children });
4410
5719
  }
4411
5720
  }
4412
5721
 
4413
5722
  // src/report-button.tsx
4414
- var import_react4 = require("react");
4415
- var import_jsx_runtime4 = require("react/jsx-runtime");
5723
+ var import_react6 = require("react");
5724
+ var import_jsx_runtime6 = require("react/jsx-runtime");
4416
5725
  function useGlitchgrabSafe() {
4417
5726
  try {
4418
5727
  return useGlitchgrab();
@@ -4427,7 +5736,7 @@ function ReportButton({
4427
5736
  children
4428
5737
  }) {
4429
5738
  var _a, _b;
4430
- const [capturing, setCapturing] = (0, import_react4.useState)(false);
5739
+ const [capturing, setCapturing] = (0, import_react6.useState)(false);
4431
5740
  const glitchgrab = useGlitchgrabSafe();
4432
5741
  if (!glitchgrab) return null;
4433
5742
  const handleClick = async () => {
@@ -4436,7 +5745,7 @@ function ReportButton({
4436
5745
  setCapturing(false);
4437
5746
  };
4438
5747
  if (children) {
4439
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: children({ onClick: handleClick, capturing }) });
5748
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: children({ onClick: handleClick, capturing }) });
4440
5749
  }
4441
5750
  const isTop = (_a = position == null ? void 0 : position.startsWith("top")) != null ? _a : false;
4442
5751
  const isLeft = (_b = position == null ? void 0 : position.endsWith("left")) != null ? _b : false;
@@ -4444,7 +5753,7 @@ function ReportButton({
4444
5753
  ...isLeft ? { left: "16px" } : { right: "16px" },
4445
5754
  ...isTop ? { top: "16px" } : { bottom: "16px" }
4446
5755
  };
4447
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
5756
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4448
5757
  "button",
4449
5758
  {
4450
5759
  type: "button",
@@ -4479,7 +5788,7 @@ function ReportButton({
4479
5788
  },
4480
5789
  "aria-label": label,
4481
5790
  children: [
4482
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
5791
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4483
5792
  "svg",
4484
5793
  {
4485
5794
  width: "16",
@@ -4487,7 +5796,7 @@ function ReportButton({
4487
5796
  viewBox: "0 0 16 16",
4488
5797
  fill: "none",
4489
5798
  style: { flexShrink: 0 },
4490
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
5799
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4491
5800
  "path",
4492
5801
  {
4493
5802
  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",
@@ -4502,8 +5811,38 @@ function ReportButton({
4502
5811
  );
4503
5812
  }
4504
5813
 
5814
+ // src/book-demo-button.tsx
5815
+ var import_jsx_runtime7 = require("react/jsx-runtime");
5816
+ function BookDemoButton({
5817
+ label = "Book a demo",
5818
+ className,
5819
+ children
5820
+ }) {
5821
+ const { openBookingDialog } = useGlitchgrab();
5822
+ if (children) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: children({ onClick: openBookingDialog }) });
5823
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5824
+ "button",
5825
+ {
5826
+ type: "button",
5827
+ onClick: openBookingDialog,
5828
+ className,
5829
+ style: className ? void 0 : {
5830
+ padding: "10px 18px",
5831
+ borderRadius: 999,
5832
+ border: 0,
5833
+ background: "#3b82f6",
5834
+ color: "#fff",
5835
+ fontSize: 14,
5836
+ fontWeight: 500,
5837
+ cursor: "pointer"
5838
+ },
5839
+ children: label
5840
+ }
5841
+ );
5842
+ }
5843
+
4505
5844
  // src/feedback-button.tsx
4506
- var import_jsx_runtime5 = require("react/jsx-runtime");
5845
+ var import_jsx_runtime8 = require("react/jsx-runtime");
4507
5846
  function useGlitchgrabSafe2() {
4508
5847
  try {
4509
5848
  return useGlitchgrab();
@@ -4522,7 +5861,7 @@ function FeedbackButton({
4522
5861
  if (!glitchgrab) return null;
4523
5862
  const handleClick = () => glitchgrab.openFeedbackDialog();
4524
5863
  if (children) {
4525
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: children({ onClick: handleClick }) });
5864
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children: children({ onClick: handleClick }) });
4526
5865
  }
4527
5866
  const isTop = (_a = position == null ? void 0 : position.startsWith("top")) != null ? _a : false;
4528
5867
  const isLeft = (_b = position == null ? void 0 : position.endsWith("left")) != null ? _b : false;
@@ -4530,7 +5869,7 @@ function FeedbackButton({
4530
5869
  ...isLeft ? { left: "16px" } : { right: "16px" },
4531
5870
  ...isTop ? { top: "16px" } : { bottom: "16px" }
4532
5871
  };
4533
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
5872
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
4534
5873
  "button",
4535
5874
  {
4536
5875
  type: "button",
@@ -4563,7 +5902,7 @@ function FeedbackButton({
4563
5902
  },
4564
5903
  "aria-label": label,
4565
5904
  children: [
4566
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
5905
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4567
5906
  "svg",
4568
5907
  {
4569
5908
  width: "16",
@@ -4572,7 +5911,7 @@ function FeedbackButton({
4572
5911
  fill: "none",
4573
5912
  style: { flexShrink: 0 },
4574
5913
  "aria-hidden": "true",
4575
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
5914
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4576
5915
  "path",
4577
5916
  {
4578
5917
  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",
@@ -4588,18 +5927,18 @@ function FeedbackButton({
4588
5927
  }
4589
5928
 
4590
5929
  // src/use-reports.ts
4591
- var import_react5 = require("react");
5930
+ var import_react7 = require("react");
4592
5931
  var BASE_URL = "https://glitchgrab.dev";
4593
5932
  function useGlitchgrabReports({
4594
5933
  token,
4595
5934
  userId,
4596
5935
  limit = 100
4597
5936
  }) {
4598
- const [reports, setReports] = (0, import_react5.useState)([]);
4599
- const [isLoading, setIsLoading] = (0, import_react5.useState)(true);
4600
- const [isFetching, setIsFetching] = (0, import_react5.useState)(false);
4601
- const [error, setError] = (0, import_react5.useState)(null);
4602
- const fetchReports = (0, import_react5.useCallback)(async () => {
5937
+ const [reports, setReports] = (0, import_react7.useState)([]);
5938
+ const [isLoading, setIsLoading] = (0, import_react7.useState)(true);
5939
+ const [isFetching, setIsFetching] = (0, import_react7.useState)(false);
5940
+ const [error, setError] = (0, import_react7.useState)(null);
5941
+ const fetchReports = (0, import_react7.useCallback)(async () => {
4603
5942
  var _a, _b;
4604
5943
  if (!token || !userId) {
4605
5944
  setIsLoading(false);
@@ -4625,7 +5964,7 @@ function useGlitchgrabReports({
4625
5964
  setIsFetching(false);
4626
5965
  }
4627
5966
  }, [token, userId, limit]);
4628
- (0, import_react5.useEffect)(() => {
5967
+ (0, import_react7.useEffect)(() => {
4629
5968
  fetchReports();
4630
5969
  }, [fetchReports]);
4631
5970
  return { reports, isLoading, isFetching, error, refetch: fetchReports };
@@ -4662,9 +6001,9 @@ function useGlitchgrabActions({
4662
6001
  onSuccess,
4663
6002
  onError
4664
6003
  }) {
4665
- const [isPending, setIsPending] = (0, import_react5.useState)(false);
4666
- const [error, setError] = (0, import_react5.useState)(null);
4667
- const run = (0, import_react5.useCallback)(
6004
+ const [isPending, setIsPending] = (0, import_react7.useState)(false);
6005
+ const [error, setError] = (0, import_react7.useState)(null);
6006
+ const run = (0, import_react7.useCallback)(
4668
6007
  async (reportId, body) => {
4669
6008
  setIsPending(true);
4670
6009
  setError(null);
@@ -4694,7 +6033,7 @@ function useGlitchgrabActions({
4694
6033
  }
4695
6034
 
4696
6035
  // src/use-feedback.ts
4697
- var import_react6 = require("react");
6036
+ var import_react8 = require("react");
4698
6037
  var DEFAULT_BASE_URL3 = "https://glitchgrab.dev";
4699
6038
  function buildUrl({
4700
6039
  approvedOnly,
@@ -4720,11 +6059,11 @@ async function fetchGlitchgrabFeedback(query) {
4720
6059
  }
4721
6060
  function useGlitchgrabFeedback(query) {
4722
6061
  const { token, approvedOnly, userId, minRating, limit, baseUrl } = query;
4723
- const [feedback, setFeedback] = (0, import_react6.useState)([]);
4724
- const [isLoading, setIsLoading] = (0, import_react6.useState)(true);
4725
- const [isFetching, setIsFetching] = (0, import_react6.useState)(false);
4726
- const [error, setError] = (0, import_react6.useState)(null);
4727
- const load = (0, import_react6.useCallback)(async () => {
6062
+ const [feedback, setFeedback] = (0, import_react8.useState)([]);
6063
+ const [isLoading, setIsLoading] = (0, import_react8.useState)(true);
6064
+ const [isFetching, setIsFetching] = (0, import_react8.useState)(false);
6065
+ const [error, setError] = (0, import_react8.useState)(null);
6066
+ const load = (0, import_react8.useCallback)(async () => {
4728
6067
  if (!token) {
4729
6068
  setIsLoading(false);
4730
6069
  return;
@@ -4748,13 +6087,14 @@ function useGlitchgrabFeedback(query) {
4748
6087
  setIsFetching(false);
4749
6088
  }
4750
6089
  }, [token, approvedOnly, userId, minRating, limit, baseUrl]);
4751
- (0, import_react6.useEffect)(() => {
6090
+ (0, import_react8.useEffect)(() => {
4752
6091
  load();
4753
6092
  }, [load]);
4754
6093
  return { feedback, isLoading, isFetching, error, refetch: load };
4755
6094
  }
4756
6095
  // Annotate the CommonJS export names for ESM import in node:
4757
6096
  0 && (module.exports = {
6097
+ BookDemoButton,
4758
6098
  FeedbackButton,
4759
6099
  GLITCHGRAB_SHORTCUT,
4760
6100
  GLITCHGRAB_SHORTCUT_MAC,