PageSourceSearch

https://aimathproblemsolver.com/assets/B8ejy0IY.js

js aimathproblemsolver.com collected 2026-10-02 00:45:41 UTC 72,840 bytes, 1,915 lines download raw bytes

1const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/D2a8Cx-C.js","assets/BkXa9QNX.js","assets/BmDlrdls.js","assets/GKSP12iv.js","assets/B-mNdDrH.js","assets/CMChhlKQ.js","assets/DH44VkHe.js","assets/CDsG-L8b.js","assets/CC1DGAqk.js","assets/BbS5JWlq.js","assets/CduXoNkY.js","assets/BanWWZt2.js","assets/CrLHLS9U.js","assets/2INXKiLw.js","assets/CsaeKhul.js","assets/DqQDN-_H.css","assets/pLQ8JASp.js","assets/uPi-84l2.js","assets/FndHqydU.js","assets/CPxQk51H.js","assets/BGGUBa6A.js","assets/ji1faxdD.js"])))=>i.map(i=>d[i]);
2import { r as reactExports, V as Viewport, R as Root2, A as Action, C as Close, T as Title, D as Description, j as jsxRuntimeExports, X, P as Provider, z, a as Toaster$2, b as Content2, d as Portal, e as Root3, f as Trigger, h as Provider$1, B as BrowserRouter, i as Routes, k as Route, N as Navigate, S as Slot, O as Overlay, l as Content, m as Title$1, n as Description$1, o as Portal$1, p as Close$1, q as Root, s as reatomComponent, Z as ZoomIn, I as Image, t as CornerDownLeft, u as useNavigate, M as Minimize2, v as Maximize2, w as Scissors, x as Sparkles, y as Brain, E as Zap, F as clientExports, G as reatomContext } from "./BkXa9QNX.js";
3import { t as twMerge, c as clsx, a as cva } from "./CMChhlKQ.js";
4import "./CsaeKhul.js";
5import { a as atom, f as withAssign, e as action, t as toAbortError, r as reatomAsync, n as noop, g as reatomBoolean, h as reatomNumber, j as withLocalStorage, k as batch, l as createCtx } from "./BmDlrdls.js";
6import { aj as uuidv7obj, ak as uuidv4, al as imageCompression, am as pDefer, an as UAParser } from "./GKSP12iv.js";
7(function polyfill() {
8  const relList = document.createElement("link").relList;
9  if (relList && relList.supports && relList.supports("modulepreload")) {
10    return;
11  }
12  for (const link of document.querySelectorAll('link[rel="modulepreload"]')) {
13    processPreload(link);
14  }
15  new MutationObserver((mutations) => {
16    for (const mutation of mutations) {
17      if (mutation.type !== "childList") {
18        continue;
19      }
20      for (const node of mutation.addedNodes) {
21        if (node.tagName === "LINK" && node.rel === "modulepreload")
22          processPreload(node);
23      }
24    }
25  }).observe(document, { childList: true, subtree: true });
26  function getFetchOpts(link) {
27    const fetchOpts = {};
28    if (link.integrity) fetchOpts.integrity = link.integrity;
29    if (link.referrerPolicy) fetchOpts.referrerPolicy = link.referrerPolicy;
30    if (link.crossOrigin === "use-credentials")
31      fetchOpts.credentials = "include";
32    else if (link.crossOrigin === "anonymous") fetchOpts.credentials = "omit";
33    else fetchOpts.credentials = "same-origin";
34    return fetchOpts;
35  }
36  function processPreload(link) {
37    if (link.ep)
38      return;
39    link.ep = true;
40    const fetchOpts = getFetchOpts(link);
41    fetch(link.href, fetchOpts);
42  }
43})();
44const scriptRel = "modulepreload";
45const assetsURL = function(dep) {
46  return "/" + dep;
47};
48const seen = {};
49const __vitePreload = function preload(baseModule, deps, importerUrl) {
50  let promise = Promise.resolve();
51  if (deps && deps.length > 0) {
52    let allSettled2 = function(promises) {
53      return Promise.all(
54        promises.map(
55          (p) => Promise.resolve(p).then(
56            (value) => ({ status: "fulfilled", value }),
57            (reason) => ({ status: "rejected", reason })
58          )
59        )
60      );
61    };
62    document.getElementsByTagName("link");
63    const cspNonceMeta = document.querySelector(
64      "meta[property=csp-nonce]"
65    );
66    const cspNonce = cspNonceMeta?.nonce || cspNonceMeta?.getAttribute("nonce");
67    promise = allSettled2(
68      deps.map((dep) => {
69        dep = assetsURL(dep);
70        if (dep in seen) return;
71        seen[dep] = true;
72        const isCss = dep.endsWith(".css");
73        const cssSelector = isCss ? '[rel="stylesheet"]' : "";
74        if (document.querySelector(`link[href="${dep}"]${cssSelector}`)) {
75          return;
76        }
77        const link = document.createElement("link");
78        link.rel = isCss ? "stylesheet" : scriptRel;
79        if (!isCss) {
80          link.as = "script";
81        }
82        link.crossOrigin = "";
83        link.href = dep;
84        if (cspNonce) {
85          link.setAttribute("nonce", cspNonce);
86        }
87        document.head.appendChild(link);
88        if (isCss) {
89          return new Promise((res, rej) => {
90            link.addEventListener("load", res);
91            link.addEventListener(
92              "error",
93              () => rej(new Error(`Unable to preload CSS for ${dep}`))
94            );
95          });
96        }
97      })
98    );
99  }
100  function handlePreloadError(err) {
101    const e = new Event("vite:preloadError", {
102      cancelable: true
103    });
104    e.payload = err;
105    window.dispatchEvent(e);
106    if (!e.defaultPrevented) {
107      throw err;
108    }
109  }
110  return promise.then((res) => {
111    for (const item of res || []) {
112      if (item.status !== "rejected") continue;
113      handlePreloadError(item.reason);
114    }
115    return baseModule().catch(handlePreloadError);
116  });
117};
118const TOAST_LIMIT = 1;
119const TOAST_REMOVE_DELAY = 1e6;
120let count = 0;
121function genId() {
122  count = (count + 1) % Number.MAX_SAFE_INTEGER;
123  return count.toString();
124}
125const toastTimeouts = /* @__PURE__ */ new Map();
126const addToRemoveQueue = (toastId) => {
127  if (toastTimeouts.has(toastId)) {
128    return;
129  }
130  const timeout = setTimeout(() => {
131    toastTimeouts.delete(toastId);
132    dispatch({
133      type: "REMOVE_TOAST",
134      toastId
135    });
136  }, TOAST_REMOVE_DELAY);
137  toastTimeouts.set(toastId, timeout);
138};
139const reducer = (state, action2) => {
140  switch (action2.type) {
141    case "ADD_TOAST":
142      return {
143        ...state,
144        toasts: [
145          action2.toast,
146          ...state.toasts
147        ].slice(0, TOAST_LIMIT)
148      };
149    case "UPDATE_TOAST":
150      return {
151        ...state,
152        toasts: state.toasts.map((t) => t.id === action2.toast.id ? {
153          ...t,
154          ...action2.toast
155        } : t)
156      };
157    case "DISMISS_TOAST": {
158      const { toastId } = action2;
159      if (toastId) {
160        addToRemoveQueue(toastId);
161      } else {
162        state.toasts.forEach((toast2) => {
163          addToRemoveQueue(toast2.id);
164        });
165      }
166      return {
167        ...state,
168        toasts: state.toasts.map((t) => t.id === toastId || toastId === void 0 ? {
169          ...t,
170          open: false
171        } : t)
172      };
173    }
174    case "REMOVE_TOAST":
175      if (action2.toastId === void 0) {
176        return {
177          ...state,
178          toasts: []
179        };
180      }
181      return {
182        ...state,
183        toasts: state.toasts.filter((t) => t.id !== action2.toastId)
184      };
185  }
186};
187const listeners = [];
188let memoryState = {
189  toasts: []
190};
191function dispatch(action2) {
192  memoryState = reducer(memoryState, action2);
193  listeners.forEach((listener) => {
194    listener(memoryState);
195  });
196}
197function toast({ ...props }) {
198  const id = genId();
199  const update = (props2) => dispatch({
200    type: "UPDATE_TOAST",
201    toast: {
202      ...props2,
203      id
204    }
205  });
206  const dismiss = () => dispatch({
207    type: "DISMISS_TOAST",
208    toastId: id
209  });
210  dispatch({
211    type: "ADD_TOAST",
212    toast: {
213      ...props,
214      id,
215      open: true,
216      onOpenChange: (open) => {
217        if (!open) dismiss();
218      }
219    }
220  });
221  return {
222    id,
223    dismiss,
224    update
225  };
226}
227function useToast() {
228  const [state, setState] = reactExports.useState(memoryState);
229  reactExports.useEffect(() => {
230    listeners.push(setState);
231    return () => {
232      const index = listeners.indexOf(setState);
233      if (index > -1) {
234        listeners.splice(index, 1);
235      }
236    };
237  }, [
238    state
239  ]);
240  return {
241    ...state,
242    toast,
243    dismiss: (toastId) => dispatch({
244      type: "DISMISS_TOAST",
245      toastId
246    })
247  };
248}
249function cn(...inputs) {
250  return twMerge(clsx(inputs));
251}
252const ToastProvider = Provider;
253const ToastViewport = /* @__PURE__ */ reactExports.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntimeExports.jsx(Viewport, {
254  ref,
255  className: cn("fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]", className),
256  ...props
257}));
258ToastViewport.displayName = Viewport.displayName;
259const toastVariants = cva("group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full", {
260  variants: {
261    variant: {
262      default: "border bg-background text-foreground",
263      destructive: "destructive group border-destructive bg-destructive text-destructive-foreground"
264    }
265  },
266  defaultVariants: {
267    variant: "default"
268  }
269});
270const Toast = /* @__PURE__ */ reactExports.forwardRef(({ className, variant, ...props }, ref) => {
271  return /* @__PURE__ */ jsxRuntimeExports.jsx(Root2, {
272    ref,
273    className: cn(toastVariants({
274      variant
275    }), className),
276    ...props
277  });
278});
279Toast.displayName = Root2.displayName;
280const ToastAction = /* @__PURE__ */ reactExports.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntimeExports.jsx(Action, {
281  ref,
282  className: cn("ring-offset-background hover:bg-secondary focus:ring-ring group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", className),
283  ...props
284}));
285ToastAction.displayName = Action.displayName;
286const ToastClose = /* @__PURE__ */ reactExports.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntimeExports.jsx(Close, {
287  ref,
288  className: cn("text-foreground/50 hover:text-foreground absolute right-2 top-2 rounded-md p-1 opacity-0 transition-opacity focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600", className),
289  "toast-close": "",
290  ...props,
291  children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, {
292    className: "h-4 w-4"
293  })
294}));
295ToastClose.displayName = Close.displayName;
296const ToastTitle = /* @__PURE__ */ reactExports.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntimeExports.jsx(Title, {
297  ref,
298  className: cn("text-sm font-semibold", className),
299  ...props
300}));
301ToastTitle.displayName = Title.displayName;
302const ToastDescription = /* @__PURE__ */ reactExports.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntimeExports.jsx(Description, {
303  ref,
304  className: cn("text-sm opacity-90", className),
305  ...props
306}));
307ToastDescription.displayName = Description.displayName;
308function Toaster$1() {
309  const { toasts } = useToast();
310  return /* @__PURE__ */ jsxRuntimeExports.jsxs(ToastProvider, {
311    children: [
312      toasts.map(function({ id, title, description, action: action2, ...props }) {
313        return /* @__PURE__ */ jsxRuntimeExports.jsxs(Toast, {
314          ...props,
315          children: [
316            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", {
317              className: "grid gap-1",
318              children: [
319                title && /* @__PURE__ */ jsxRuntimeExports.jsx(ToastTitle, {
320                  children: title
321                }),
322                description && /* @__PURE__ */ jsxRuntimeExports.jsx(ToastDescription, {
323                  children: description
324                })
325              ]
326            }),
327            action2,
328            /* @__PURE__ */ jsxRuntimeExports.jsx(ToastClose, {})
329          ]
330        }, id);
331      }),
332      /* @__PURE__ */ jsxRuntimeExports.jsx(ToastViewport, {})
333    ]
334  });
335}
336const Toaster = ({ ...props }) => {
337  const { theme = "system" } = z();
338  return /* @__PURE__ */ jsxRuntimeExports.jsx(Toaster$2, {
339    theme,
340    className: "toaster group",
341    toastOptions: {
342      classNames: {
343        toast: "group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
344        description: "group-[.toast]:text-muted-foreground",
345        actionButton: "group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
346        cancelButton: "group-[.toast]:bg-muted group-[.toast]:text-muted-foreground"
347      }
348    },
349    ...props
350  });
351};
352const TooltipProvider = Provider$1;
353const Tooltip = Root3;
354const TooltipContent = /* @__PURE__ */ reactExports.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsxRuntimeExports.jsx(Portal, {
355  children: /* @__PURE__ */ jsxRuntimeExports.jsx(Content2, {
356    ref,
357    sideOffset,
358    className: cn("z-50 overflow-hidden rounded-md border bg-white/60 px-3 py-1.5 text-sm backdrop-blur-lg", "text-popover-foreground animate-in fade-in-0 zoom-in-95 shadow-md", "data-[state=closed]:animate-out data-[state=closed]:fade-out-0", "data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2", "data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2", "data-[side=top]:slide-in-from-bottom-2", className),
359    ...props
360  })
361}));
362TooltipContent.displayName = Content2.displayName;
363function SimpleTooltip({ children, content, open, defaultOpen, onOpenChange, sideOffset = 4, ...props }) {
364  return /* @__PURE__ */ jsxRuntimeExports.jsxs(Root3, {
365    open,
366    defaultOpen,
367    onOpenChange,
368    children: [
369      /* @__PURE__ */ jsxRuntimeExports.jsx(Trigger, {
370        asChild: true,
371        children
372      }),
373      /* @__PURE__ */ jsxRuntimeExports.jsx(Portal, {
374        className: "max-w-56",
375        children: /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, {
376          sideOffset,
377          ...props,
378          children: typeof content === "string" ? /* @__PURE__ */ jsxRuntimeExports.jsx("p", {
379            className: "max-w-56",
380            children: content
381          }) : content
382        })
383      })
384    ]
385  });
386}
387const AppIndex = /* @__PURE__ */ reactExports.lazy(() => __vitePreload(() => import("./D2a8Cx-C.js"), true ? __vite__mapDeps([0,1,2,3,4,5,6,7,8,9]) : void 0));
388const Chats = /* @__PURE__ */ reactExports.lazy(() => __vitePreload(() => import("./CduXoNkY.js"), true ? __vite__mapDeps([10,1,2,3,4,6,5,7,11,8,12,13,14,15]) : void 0));
389const CurrentChat = /* @__PURE__ */ reactExports.lazy(() => __vitePreload(() => import("./pLQ8JASp.js"), true ? __vite__mapDeps([16,1,2,3,4,6,5,7,8,13,14,15,11,12]) : void 0));
390const Landing = /* @__PURE__ */ reactExports.lazy(() => __vitePreload(() => import("./uPi-84l2.js"), true ? __vite__mapDeps([17,1,2,3,4,9,7,11]) : void 0));
391const Welcome = /* @__PURE__ */ reactExports.lazy(() => __vitePreload(() => import("./FndHqydU.js"), true ? __vite__mapDeps([18,1,2,3,4]) : void 0));
392const PrivacyPolicy = /* @__PURE__ */ reactExports.lazy(() => __vitePreload(() => import("./CPxQk51H.js"), true ? __vite__mapDeps([19,1,2,3,4]) : void 0));
393const TermsOfService = /* @__PURE__ */ reactExports.lazy(() => __vitePreload(() => import("./BGGUBa6A.js"), true ? __vite__mapDeps([20,1,2,3,4]) : void 0));
394const Uninstall = /* @__PURE__ */ reactExports.lazy(() => __vitePreload(() => import("./ji1faxdD.js"), true ? __vite__mapDeps([21,1,2,3,4,6,5,7,12]) : void 0));
395const PageLoader = () => /* @__PURE__ */ jsxRuntimeExports.jsx("div", {
396  className: "flex h-screen w-full items-center justify-center",
397  children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", {
398    className: "h-32 w-32 animate-spin rounded-full border-b-2 border-gray-900"
399  })
400});
401if (typeof document !== "undefined") {
402  document.head.querySelectorAll("title").forEach((el) => el.remove());
403}
404const App = () => {
405  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", {
406    className: "min-w-[300px]",
407    children: /* @__PURE__ */ jsxRuntimeExports.jsxs(TooltipProvider, {
408      children: [
409        /* @__PURE__ */ jsxRuntimeExports.jsx(Toaster$1, {}),
410        /* @__PURE__ */ jsxRuntimeExports.jsx(Toaster, {}),
411        /* @__PURE__ */ jsxRuntimeExports.jsx(BrowserRouter, {
412          children: /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, {
413            fallback: /* @__PURE__ */ jsxRuntimeExports.jsx(PageLoader, {}),
414            children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Routes, {
415              children: [
416                /* @__PURE__ */ jsxRuntimeExports.jsx(Route, {
417                  index: true,
418                  element: /* @__PURE__ */ jsxRuntimeExports.jsx(Landing, {})
419                }),
420                /* @__PURE__ */ jsxRuntimeExports.jsx(Route, {
421                  path: "app",
422                  element: /* @__PURE__ */ jsxRuntimeExports.jsx(AppIndex, {})
423                }),
424                /* @__PURE__ */ jsxRuntimeExports.jsx(Route, {
425                  path: "history",
426                  element: /* @__PURE__ */ jsxRuntimeExports.jsx(Chats, {})
427                }),
428                /* @__P
428URE__ */ jsxRuntimeExports.jsx(Route, {
429                  path: "c/:chatId?/:slug?",
430                  element: /* @__PURE__ */ jsxRuntimeExports.jsx(CurrentChat, {})
431                }),
432                /* @__PURE__ */ jsxRuntimeExports.jsx(Route, {
433                  path: "welcome",
434                  element: /* @__PURE__ */ jsxRuntimeExports.jsx(Welcome, {})
435                }),
436                /* @__PURE__ */ jsxRuntimeExports.jsx(Route, {
437                  path: "privacy-policy",
438                  element: /* @__PURE__ */ jsxRuntimeExports.jsx(PrivacyPolicy, {})
439                }),
440                /* @__PURE__ */ jsxRuntimeExports.jsx(Route, {
441                  path: "terms-of-service",
442                  element: /* @__PURE__ */ jsxRuntimeExports.jsx(TermsOfService, {})
443                }),
444                /* @__PURE__ */ jsxRuntimeExports.jsx(Route, {
445                  path: "uninstall",
446                  element: /* @__PURE__ */ jsxRuntimeExports.jsx(Uninstall, {})
447                }),
448                /* @__PURE__ */ jsxRuntimeExports.jsx(Route, {
449                  path: "*",
450                  element: /* @__PURE__ */ jsxRuntimeExports.jsx(Navigate, {
451                    to: "/",
452                    replace: true
453                  })
454                })
455              ]
456            })
457          })
458        })
459      ]
460    })
461  });
462};
463const isNodeEnvironment = () => typeof process !== "undefined" && process.versions?.node != null;
464const encodeBase64Ascii = (bytes) => {
465  try {
466    if (isNodeEnvironment()) {
467      return Buffer.from(bytes).toString("base64");
468    }
469  } catch (e) {
470    console.error("Failed to encode Base64 using Buffer", e);
471  }
472  return btoa(String.fromCharCode(...bytes));
473};
474const encodeBase64 = (bytes) => {
475  let string = encodeBase64Ascii(bytes);
476  string = string.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
477  return string;
478};
479const isValidUuidv7b64 = (id) => !!id && /^[a-zA-Z0-9_-]{20,22}$/.test(id);
480const uuidv7b64 = () => encodeBase64(uuidv7obj().bytes);
481const randomId = () => uuidv4();
482const u$1 = void 0;
483const BG_COMM_ID = "bg";
484const COMM_ANSWER_TIMEOUT = 96;
485const WEB_APP_ID_PREFIX = "wa-", CS_COMM_ID_PREFIX = "cs-";
486const isCsCommId = (id) => !!id && id.startsWith(CS_COMM_ID_PREFIX);
487var CommMsgType;
488(function(CommMsgType2) {
489  CommMsgType2[CommMsgType2["ping"] = 1] = "ping";
490  CommMsgType2[CommMsgType2["ga"] = 2] = "ga";
491  CommMsgType2[CommMsgType2["extReady"] = 3] = "extReady";
492  CommMsgType2[CommMsgType2["ok"] = 4] = "ok";
493  CommMsgType2[CommMsgType2["startSolvingCmd"] = 10] = "startSolvingCmd";
494  CommMsgType2[CommMsgType2["startImageCaptureCmd"] = 11] = "startImageCaptureCmd";
495  CommMsgType2[CommMsgType2["getTabState"] = 12] = "getTabState";
496  CommMsgType2[CommMsgType2["isPopupOpen"] = 30] = "isPopupOpen";
497  CommMsgType2[CommMsgType2["onPopup"] = 31] = "onPopup";
498  CommMsgType2[CommMsgType2["openSidePanelOrPopup"] = 32] = "openSidePanelOrPopup";
499  CommMsgType2[CommMsgType2["onTabUnload"] = 90] = "onTabUnload";
500})(CommMsgType || (CommMsgType = {}));
501var MsgFrom;
502(function(MsgFrom2) {
503  MsgFrom2[MsgFrom2["ContextMenu"] = 1] = "ContextMenu";
504  MsgFrom2[MsgFrom2["Popup"] = 2] = "Popup";
505  MsgFrom2[MsgFrom2["Options"] = 3] = "Options";
506  MsgFrom2[MsgFrom2["SidePanel"] = 4] = "SidePanel";
507  MsgFrom2[MsgFrom2["Cs"] = 5] = "Cs";
508  MsgFrom2[MsgFrom2["WebApp"] = 6] = "WebApp";
509  MsgFrom2[MsgFrom2["Command"] = 7] = "Command";
510  MsgFrom2[MsgFrom2["Bg"] = 9] = "Bg";
511})(MsgFrom || (MsgFrom = {}));
512var ExtensionState;
513(function(ExtensionState2) {
514  ExtensionState2[ExtensionState2["unknown"] = 1] = "unknown";
515  ExtensionState2[ExtensionState2["unsupported"] = 99] = "unsupported";
516})(ExtensionState || (ExtensionState = {}));
517const fromLabel = (from) => from ? MsgFrom[from] || `${from}` : u$1;
518const msgTypeLabel = (t) => t ? CommMsgType[t] || t : u$1;
519const msgDebug = (msg) => {
520  return isCommMsg(msg) ? removeUndefinedOrNullValues({
521    ...msg,
522    from: msg ? fromLabel(msg.from) : u$1,
523    t: msg ? msgTypeLabel(msg.t) : u$1
524  }) : msg;
525};
526const removeUndefinedOrNullValues = (obj) => Object.fromEntries(Object.entries(obj).filter(([_, value]) => value !== void 0 && value !== null));
527const isCommMsg = (msg) => msg && msg.t && typeof msg.t === "number";
528const PingMsg = { t: CommMsgType.ping };
529const StartImageCaptureMsg = (from, tabId) => removeUndefinedOrNullValues({
530  t: CommMsgType.startImageCaptureCmd,
531  tabId,
532  from,
533  for: CS_COMM_ID_PREFIX
534});
535const isExtensionOrigin = (origin) => {
536  return /^chrome-extension:\/\/[a-zA-Z0-9-]+$/.test(origin);
537};
538const screenCaptureAtom = atom(false, "screenCaptureAtom").pipe(withAssign((isCapturing, name) => {
539  const start = action((ctx, source = "button") => {
540    isCapturing(ctx, true);
541    return ctx.schedule(async () => await ExtBridge.getInstance(ctx).sendMessage(StartImageCaptureMsg(MsgFrom.WebApp)));
542  }, name + ".start");
543  const stop = action((ctx) => {
544    isCapturing(ctx, false);
545  }, name + ".stop");
546  return {
547    start,
548    stop
549  };
550}));
551const EXTENSION_ID_PARAM = "eid";
552const USER_ID_PARAM = "uid";
553const ABORTED = "aborted";
554const createAbortError = (reason = ABORTED) => toAbortError(reason);
555const compressImageAsync = async (image, signal) => {
556  return imageCompression(image, {
557    maxSizeMB: 1,
558    maxWidthOrHeight: 2048,
559    useWebWorker: true,
560    preserveExif: false,
561    libURL: void 0,
562    signal
563  });
564};
565function getFilefromDataUrl(dataUrl, filename, lastModified) {
566  return imageCompression.getFilefromDataUrl(dataUrl, filename, lastModified);
567}
568const USER_ID_KEY = "muid";
569const TEST_KEY = "test";
570const COOKIE_EXPIRY_DAYS = 365;
571const w$2 = window;
572const LS = (() => {
573  let ls;
574  try {
575    ls = localStorage;
576    ls.setItem(TEST_KEY, TEST_KEY);
577    ls.removeItem(TEST_KEY);
578  } catch (error) {
579    console.warn("localStorage not available:", error);
580  }
581  return ls;
582})();
583const setCookie = (name, value, days) => {
584  try {
585    const expires = /* @__PURE__ */ new Date();
586    expires.setTime(expires.getTime() + days * 24 * 60 * 60 * 1e3);
587    const hostname = location.hostname;
588    const isLocalhost = hostname === "localhost";
589    const isIp = /^(\d{1,3}\.){3}\d{1,3}$/.test(hostname) || /^[a-fA-F0-9:]+$/.test(hostname);
590    const domain = isLocalhost || isIp ? hostname : "." + hostname.split(".").slice(-2).join(".");
591    document.cookie = `${name}=${value};expires=${expires.toUTCString()};path=/;domain=${domain}`;
592  } catch (error) {
593    console.error("Failed to set cookie:", error);
594  }
595};
596const getCookie = (name) => {
597  try {
598    const match = document.cookie.match(new RegExp(`(^| )${name}=([^;]+)`));
599    return match ? match[2] : null;
600  } catch (error) {
601    console.error("Failed to get cookie:", error);
602    return null;
603  }
604};
605let UID = null;
606const storeUserId = (uid, ls) => {
607  try {
608    UID = uid;
609    GA.setUserId(uid);
610    setCookie(USER_ID_KEY, uid, COOKIE_EXPIRY_DAYS);
611    ls?.setItem(USER_ID_KEY, uid);
612  } catch (error) {
613    console.error(`Failed to store ${USER_ID_KEY}:`, error);
614  } finally {
615  }
616};
617const getUserId = (ctx = reatomCtx, readonly) => {
618  if (UID) {
619    return UID;
620  }
621  const location1 = w$2.location;
622  const urlParams = new URLSearchParams(location1.search);
623  const uidFromUrl = urlParams.get("uid")?.trim();
624  if (uidFromUrl) {
625    urlParams.delete(USER_ID_PARAM);
626    const urlParamsString = urlParams.toString();
627    const newUrl = `${location1.pathname}${urlParamsString ? `?${urlParamsString}` : ""}${location1.hash}`;
628    w$2.history.replaceState({}, "", newUrl);
629    if (isValidUuidv7b64(uidFromUrl)) {
630      if (!readonly) storeUserId(uidFromUrl, LS);
631      return uidFromUrl;
632    }
633  }
634  const uidFromExt = ctx.get(extensionCtxAtom.userId);
635  if (uidFromExt && isValidUuidv7b64(uidFromExt)) {
636    if (!readonly) storeUserId(uidFromExt, LS);
637    return uidFromExt;
638  }
639  const cookieId = getCookie(USER_ID_KEY)?.trim();
640  if (cookieId && isValidUuidv7b64(cookieId)) {
641    if (!readonly) storeUserId(cookieId, LS);
642    return cookieId;
643  }
644  const storedId = LS?.getItem(USER_ID_KEY)?.trim();
645  if (storedId && isValidUuidv7b64(storedId)) {
646    if (!readonly) storeUserId(storedId, LS);
647    return storedId;
648  }
649  const newId = readonly ? "" : uuidv7b64();
650  if (!readonly) storeUserId(newId, LS);
651  return newId;
652};
653const w$1 = window;
654let userIdSet = false;
655const GA = {
656  setUserId: (userId) => {
657    userIdSet = true;
658    w$1.gtag?.("set", {
659      user_id: userId
660    });
661  },
662  sendEvent: (event, params = {}) => {
663    if (!params.user_id) {
664      try {
665        const userId = getUserId(void 0, true);
666        params.user_id = userId;
667        if (!userIdSet) {
668          GA.setUserId(userId);
669        }
670      } catch (error) {
671        console.error("Failed to get UID:", error);
672      }
673    }
674    w$1.gtag?.("event", event, params);
675  }
676};
677const MAX_IMAGE_SIZE = 5 * 1024 * 1024;
678const IMAGE_MIME = "image/";
679const ALLOWED_IMAGE_TYPES = ["image/jpeg", "image/png", "image/gif"];
680const formatFileSize = (bytes) => {
681  if (bytes === 0)
682    return "0 B";
683  const k = 1024;
684  const sizes = ["B", "KB", "MB", "GB"];
685  const i = Math.floor(Math.log(bytes) / Math.log(k));
686  return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
687};
688const MAX_SIZE_STRING = formatFileSize(MAX_IMAGE_SIZE);
689const fileToBase64 = async (file, signal) => new Promise((resolve, reject) => {
690  const reader = new FileReader();
691  reader.onload = (ev) => {
692    const url = reader.result;
693    if (url)
694      resolve(url);
695    else
696      reject(ev || url);
697  };
698  reader.onerror = reject;
699  reader.onabort = () => reject(createAbortError());
700  signal?.addEventListener("abort", (reason) => {
701    reject(reason || createAbortError());
702    reader.abort();
703  });
704  reader.readAsDataURL(file);
705});
706const DEBUG = false;
707const ALLOWED_HINT = `JPEG, PNG, or GIF; ${MAX_SIZE_STRING} max`;
708const attachedImageAtom = atom(null, "attachedImage").pipe(withAssign((attachedImage, name) => {
709  const previewUrlAtom = atom(null, name + ".previewUrl");
710  const details = atom(null, name + ".details");
711  const reset = action((ctx) => {
712    details(ctx, null);
713    previewUrlAtom(ctx, null);
714    attachedImage(ctx, null);
715  }, name + ".reset");
716  const compressImage = reatomAsync((ctx, image2) => {
717    return compressImageAsync(image2, ctx.controller.signal);
718  });
719  compressImage.onReject.onCall((_, error) => {
720    if (error !== ABORTED || DEBUG) console.error("Failed to compress image", error);
721  });
722  const getBase64FromImage = reatomAsync((ctx, image2) => {
723    return fileToBase64(image2, ctx.controller.signal);
724  });
725  getBase64FromImage.onReject.onCall((_, error) => {
726    if (error !== ABORTED || DEBUG) console.error("Failed to process image", error);
727  });
728  const abortAtom = atom(null, name + ".abort");
729  const onAttachedImageChange = reatomAsync(async (ctx, image2) => {
730    const startTime = Date.now();
731    ctx.get(abortAtom)?.abort(ABORTED);
732    const ac = ctx.controller;
733    const signal = ac.signal;
734    abortAtom(ctx, ac);
735    if (!image2) {
736      previewUrlAtom(ctx, null);
737      details(ctx, null);
738      return;
739    }
740    const format = image2.type.split("/")[1].toUpperCase();
741    const fileSize = image2.size;
742    const sizeFormatted = formatFileSize(fileSize);
743    details(ctx, {
744      size: sizeFormatted,
745      format
746    });
747    let hasCompressed = false;
748    const simple = getBase64FromImage(ctx, image2);
749    simple.then((previewUrl) => {
750      if (!hasCompressed && !signal.aborted) {
751        previewUrlAtom(ctx, previewUrl);
752      }
753      return previewUrl;
754    });
755    const compressed = compressImage(ctx, image2).then((compressedImage) => getBase64FromImage(ctx, compressedImage)).then((previewUrl) => {
756      simple.controller.abort(ABORTED);
757      if (!signal.aborted) {
758        hasCompressed = true;
759        previewUrlAtom(ctx, previewUrl);
760      }
761      return previewUrl;
762    });
763    simple.catch(() => compressed).then((previewUrl) => {
764      const img = document.createElement("img");
765      img.onload = () => {
766        if (!signal.aborted) details(ctx, {
767          size: sizeFormatted,
768          dimensions: `${img.width}×${img.height}`,
769          format
770        });
771      };
772      img.src = previewUrl;
773    });
774    await compressed.catch(() => simple);
775    GA.sendEvent("imageAttached", {
776      format,
777      fileSize,
778      processingMs: Date.now() - startTime,
779      dimensions: ctx.get(details)?.dimensions ?? 0
780    });
781  }, name + ".onChange");
782  onAttachedImageChange.onReject.onCall((ctx, error) => {
783    if (error !== ABORTED) {
784      console.error("Failed to process image", error);
785      reset(ctx);
786      inputErrorAtom(ctx, "Failed to process image");
787    }
788  });
789  attachedImage.onChange(onAttachedImageChange);
790  const image = atom((ctx) => ctx.spy(previewUrlAtom) || ctx.spy(attachedImage), name + ".image");
791  return {
792    previewUrl: previewUrlAtom,
793    image,
794    details,
795    hasImage: atom((ctx) => !!ctx.spy(image), name + ".hasImage"),
796    reset
797  };
798}));
799const inputErrorAtom = atom("", "inputError").pipe(withAssign((target, name) => ({
800  show: action((ctx, description, title = "Error") => {
801    target(ctx, description);
802    ctx.schedule(() => {
803      toast({
804        title,
805        description,
806        variant: "destructive"
807      });
808      GA.sendEvent("inputError", {
809        title,
810        description
811      });
812    }).catch(console.error);
813  }, name + ".show")
814})));
815const validateAndProcessImage = action((ctx, file) => {
816  if (!ALLOWED_IMAGE_TYPES.includes(file.type)) {
817    inputErrorAtom.show(ctx, `Please select a valid image file (${ALLOWED_HINT})`, "Invalid file type");
818    return false;
819  }
820  if (file.size > MAX_IMAGE_SIZE) {
821    inputErrorAtom.show(ctx, "Image size should be less than" + MAX_SIZE_STRING, "File too large");
822    return false;
823  }
824  attachedImageAtom(ctx, file);
825  return true;
826}, "validateAndProcessImage");
827const safeErrorCause = (error, cause) => {
828  const e = error instanceof Error ? error : error === ABORTED ? toAbortError(error) : new Error(error);
829  try {
830    if (error !== cause && cause) {
831      e.cause = cause;
832    } else if (e !== error) {
833      e.cause = error;
834    }
835  } catch (failure) {
836    console.error("Failed to set error cause", failure, e, cause);
837  }
838  return e;
839};
840var __defProp$1 = Object.defineProperty;
841var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
842var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
843const r = chrome.runtime;
844const KEEP_CONNECTION_INTERVAL = 7 * 1e3;
845const DEFAULT_RETRY_DELAY = 1e3;
846const MAX_RETRY_DELAY = 3e4;
847const MAX_RETRIES = 5;
848const u = void 0;
849class WebAppCommunicator {
850  constructor(targetExtensionId, onMessageCb = u, id = newWebAppCommId(), from = MsgFrom.WebApp, title = id) {
851    __publicField$1(this, "port");
852    __publicField$1(this, "id");
853    __publicField$1(this, "targetExtensionId");
854    __publicField$1(this, "title");
855    __publicField$1(this, "onMessageCb");
856    __publicField$1(this, "from");
857    __publicField$1(this, "myTabId");
858    __publicField$1(this, "responseQueue", /* @__PURE__ */ new Map());
859    __publicField$1(this, "lastDisconnectTime", 0);
860    __publicField$1(this, "fastDisconnects", 0);
861    __publicField$1(this, "onMessage", (msg, sender) => {
862      const api2 = this;
863      const { title: title2, id: id2 } = api2;
864      const myTabId = api2.myTabId;
865      const type = msg.t;
866      const for_ = msg.for;
867      const msgTabId = msg.tabId;
868      if (msg.isAnswer) {
869        onAnswerReceived(api2.responseQueue, msg, title2, sender);
870        return 0;
871      }
872      let answer = 0;
873      if (!type) {
874        if (msg && !Number.isInteger(msg)) {
875          {
876            let error = `${title2} Unexpected from ${senderLabel(sender, msg)}`;
877            try {
878              error += `: ${JSON.stringify(msgDebug(msg))}`;
879            } catch (_) {
880              error += `: ${msgDebug(msg)}`;
881            }
882          }
883        }
884      } else if (for_ && for_ !== id2 && !id2.startsWith(for_)) ;
885      else if (msgTabId && myTabId && msgTabId !== myTabId) ;
886      else if (!sender || false) {
887        switch (type) {
888          case CommMsgType.ping:
889            break;
890          default:
891            answer = api2.onMessageCb?.(msg, sender) || 0;
892        }
893      }
894      return prepareAnswer(msg, answer, title2, api2.from);
895    });
896    __publicField$1(this, "portMsgListener", (msg, p) => {
897      const api2 = this, port = p || api2.port;
898      if (msg && port) {
899        const answer = api2.onMessage(msg, port.sender);
900        postMessageSafe(port, answer);
901      }
902    });
903    __publicField$1(this, "openPort", (retry = 0) => {
904      const api2 = this;
905      const id2 = api2.id, port = r.connect(api2.targetExtensionId, {
906        name: id2
907      }), portError = r.lastError;
908      if (portError || !port) {
909        const r2 = retry + 1;
910        const msg = portError?.message || "unknown";
911        const nonRecoverable = !portError || r2 >= MAX_RETRIES || msg.toLowerCase().includes("receiving end");
912        if (!nonRecoverable) {
913          const timeoutMs = Math.min(Math.pow(r2, 2) * DEFAULT_RETRY_DELAY, MAX_RETRY_DELAY);
914          setTimeout(() => api2.openPort(r2), timeoutMs);
915        }
916        if (port) runCatching(() => port.disconnect());
917        return;
918      }
919      api2.port = port;
920      port.onMessage.addListener(api2.portMsgListener);
921      let intervalId;
922      {
923        intervalId = setInterval(api2.sendPing, KEEP_CONNECTION_INTERVAL);
924      }
925      port.onDisconnect.addListener((p) => {
926        clearInterval(intervalId);
927        const _port = p || port;
928        if (api2.port === _port) api2.port = u;
929        const currentTime = Date.now();
930        const timeFromLastDisconnect = currentTime - api2.lastDisconnectTime;
931        api2.lastDisconnectTime = currentTime;
932        {
933          if (timeFromLastDisconnect < 900) {
934            api2.fastDisconnects++;
935            const fastDisconnects = api2.fastDisconnects;
936            if (fastDisconnects > 3) {
937              return;
938            }
939          } else api2.fastDisconnects = 0;
940          api2.openPort();
941        }
942      });
943      return port;
944    });
945    __publicField$1(this, "sendMsg", async (msg, callback, from2 = this.from, to = BG_COMM_ID) => {
946      const api2 = this, isUnloadMsg = msg.t === CommMsgType.onTabUnload, doAnswer = !isUnloadMsg && callback;
947      let cb = callback !== true ? callback : u;
948      let timeout;
949      try {
950        to ? msg.for = to : to = msg.for;
951        if (from2) msg.from = from2;
952        if (doAnswer && !msg.id) msg.id = randomId();
953        const port = isUnloadMsg ? u : api2.port || api2.openPort();
954        if (port && (!doAnswer || msg.id)) {
955          const answer = await postMessageSafeWithAnswer(port, msg, api2.responseQueue);
956          if (answer != false) {
957            cb?.(answer);
958            return answer;
959          }
960        }
961        const smDeferred = pDefer();
962        const t = COMM_ANSWER_TIMEOUT;
963        timeout = isUnloadMsg ? u : setTimeout(() => smDeferred.reject(`timeout ${t}ms`), t);
964        sendMessageSafe(() => r.sendMessage(api2.targetExtensionId, msg), msg).catch(smDeferred.reject).then((response) => {
965          smDeferred.resolve(response);
966          cb?.(response);
967          cb = u;
968        });
969        return await smDeferred.promise;
970      } catch (e) {
971        cb?.(u, e);
972      } finally {
973        clearTimeout(timeout);
974      }
975    });
976    __publicField$1(this, "sendPing", () => {
977      const api2 = this;
978      if (api2.myTabId || !isCsCommId(api2.id)) {
979        api2.sendMsg(PingMsg).catch(noop);
980      } else {
981        api2.sendMsg({
982          t: CommMsgType.ping,
983          id: randomId()
984        }, (msg, error) => {
985          if (msg && !error) {
986            const myTabId = msg.v || msg.d;
987            api2.myTabId = myTabId;
988          }
989        }).catch(noop);
990      }
991    });
992    this.id = id;
993    this.targetExtensionId = targetExtensionId;
994    this.title = title;
995    this.onMessageCb = onMessageCb;
996    this.from = from;
997    const api = this;
998    const rMsgListener = (msg, sender, sendResponse) => {
999      if (msg) sendResponse(api.onMessage(msg, sender));
1000    };
1001    r.onMessage?.addListener(rMsgListener);
1002    api.openPort();
1003  }
1004}
1005const newWebAppCommId = () => `${WEB_APP_ID_PREFIX}${uuidv7b64()}`;
1006const runCatching = (fn, silent) => {
1007  try {
1008    return fn();
1009  } catch (e) {
1010  }
1011};
1012const senderLabel = (sender, msg) => {
1013  const url = sender?.url || sender?.tab?.url || sender?.origin || sender?.nativeApplication || sender?.id;
1014  return url || msg && fromLabel(msg.from) || u;
1015};
1016const onAnswerReceived = (responseQueue, msg, title, sender) => {
1017  const msgId = msg.id;
1018  const deferred = msgId ? responseQueue.get(msgId) : u;
1019  if (!deferred) {
1020    senderLabel(sender, msg);
1021  } else {
1022    deferred.resolve(msg);
1023    responseQueue.delete(msgId);
1024  }
1025};
1026const prepareAnswer = (msg, answer, title, from) => {
1027  if (msg.id && !msg.isAnswer) {
1028    if (!isCommMsg(answer)) {
1029      answer = {
1030        t: CommMsgType.ping,
1031        v: answer
1032      };
1033    }
1034    answer.id = msg.id;
1035    answer.isAnswer = true;
1036    from ? answer.from = from : delete answer.from;
1037  }
1038  return answer;
1039};
1040const postMessageSafe = (port, msg) => {
1041  try {
1042    port.postMessage(msg);
1043    const lastError = r.lastError;
1044    if (!lastError) {
1045      return true;
1046    }
1047  } catch (e) {
1048  }
1049};
1050const postMessageSafeWithAnswer = (port, msg, responseQueue, commTitle, timeoutMs = COMM_ANSWER_TIMEOUT) => new Promise(async (resolve) => {
1051  let timeout;
1052  const msgId = msg && msg.id;
1053  try {
1054    let portDeferred;
1055    if (msgId) {
1056      const d = pDefer();
1057      portDeferred = d;
1058      d.promise.then(resolve);
1059      responseQueue.set(msgId, d);
1060      timeout = setTimeout(() => {
1061        d.resolve(false);
1062      }, timeoutMs);
1063    }
1064    if (postMessageSafe(port, msg)) {
1065      resolve(portDeferred ? await portDeferred.promise : u);
1066    }
1067  } catch (e) {
1068  } finally {
1069    clearTimeout(timeout);
1070    if (msgId) responseQueue.delete(msgId);
1071  }
1072  resolve(false);
1073});
1074const sendMessageSafe = async (sendMessage, ...debugArgs) => {
1075  let e;
1076  let lastError;
1077  try {
1078    const response = await sendMessage();
1079    lastError = r.lastError;
1080    if (!lastError) return response;
1081  } catch (error) {
1082    e = error;
1083    lastError = r.lastError;
1084  }
1085  if (e || lastError) {
1086    throw e || lastError?.message || lastError;
1087  }
1088  return false;
1089};
1090const buttonVariants = cva("inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", {
1091  variants: {
1092    variant: {
1093      default: "bg-primary text-primary-foreground hover:bg-primary/90",
1094      destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
1095      outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
1096      secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
1097      ghost: "hover:bg-accent hover:text-accent-foreground",
1098      link: "text-primary underline-offset-4 hover:underline"
1099    },
1100    size: {
1101      default: "h-10 px-4 py-2",
1102      sm: "h-9 rounded-md px-3",
1103      lg: "h-11 rounded-md px-8",
1104      icon: "h-10 w-10"
1105    }
1106  },
1107  defaultVariants: {
1108    variant: "default",
1109    size: "default"
1110  }
1111});
1112const Button = /* @__PURE__ */ reactExports.forwardRef(({ className, variant, size, asChild = false, ...props }, ref) => {
1113  const Comp = asChild ? Slot : "button";
1114  return /* @__PURE__ */ jsxRuntimeExports.jsx(Comp, {
1115    className: cn(buttonVariants({
1116      variant,
1117      size,
1118      className
1119    })),
1120    ref,
1121    ...props
1122  });
1123});
1124Button.displayName = "Button";
1125const isMac = () => {
1126  if (typeof navigator === "undefined") {
1127    return false;
1128  }
1129  const n = navigator;
1130  const macRegex = /Mac/i;
1131  return macRegex.test(n.userAgentData?.platform || "") || macRegex.test(n.platform || "") || macRegex.test(n.userAgent || "");
1132};
1133const IS_MAC = isMac();
1134const SolutionTypeModes = [
1135  {
1136    id: "answer",
1137    label: "Quick Answer",
1138    description: "direct, concise solution"
1139  },
1140  {
1141    id: "tutor",
1142    label: "AI Tutor",
1143    description: "detailed guidance with best learning experience"
1144  },
1145  {
1146    id: "stepby",
1147    label: "Step-by-Step",
1148    description: "step-by-step guidance tailored to your needs"
1149  }
1150];
1151const findSolutionTypeMode = (value) => value ? SolutionTypeModes.find((mode) => mode.id === value) : null;
1152const MODE_KEY = "mode";
1153const solutionModeAtom = atom(findSolutionTypeMode(LS?.getItem(MODE_KEY)) || SolutionTypeModes[0], "solutionModeAtom");
1154const isDraggingAtom = reatomBoolean(false, "isDraggingAtom").pipe(withAssign((isDragging, name) => {
1155  const error = reatomBoolean(false, name + ".error");
1156  const reset = action((ctx) => {
1157    error.setFalse(ctx);
1158    isDragging.setFalse(ctx);
1159    dragCounter.reset(ctx);
1160  });
1161  let dragCounter = reatomNumber(0, name + ".counter");
1162  return {
1163    error,
1164    reset,
1165    onEnter: action((ctx, e) => {
1166      e.preventDefault();
1167      e.stopPropagation();
1168      if (!ctx.get(isDragging)) isDragging.setTrue(ctx);
1169      if (dragCounter.increment(ctx) >= 1) return;
1170      const items = e.dataTransfer?.items || [];
1171      const hasImageFile = Array.from(items).some((item) => item.type.startsWith(IMAGE_MIME));
1172      error(ctx, !hasImageFile);
1173    }, "onEnter"),
1174    onLeave: action((ctx, e) => {
1175      e.preventDefault();
1176      e.stopPropagation();
1177      if (dragCounter.decrement(ctx) > 0) return;
1178      reset(ctx);
1179    }, "onLeave"),
1180    onDrop: action((ctx, e) => {
1181      e.preventDefault();
1182      e.stopPropagation();
1183      reset(ctx);
1184      handleImageFiles(ctx, e.dataTransfer?.files);
1185    }, "onDrop")
1186  };
1187}));
1188const handleImageFiles = action((ctx, files) => {
1189  if (!files || files.length <= 0) return false;
1190  for (const file of files) {
1191    if (file && file.type.startsWith(IMAGE_MIME)) {
1192      return validateAndProcessImage(ctx, file);
1193    }
1194  }
1195  inputErrorAtom.show(ctx, "Please select a valid image file (JPEG, PNG, or GIF; 5MB max)");
1196  return false;
1197}, "handleImageFiles");
1198const handlePaste = action((ctx, e) => {
1199  const items = e.clipboardData?.items;
1200  if (!items || items.length <= 0) return;
1201  const nonTextItems = Array.from(items).filter((item) => !item.type.startsWith("text")).map((item) => item.getAsFile());
1202  if (nonTextItems.length > 0) {
1203    e.preventDefault();
1204    e.stopPropagation();
1205    handleImageFiles(ctx, nonTextItems);
1206  }
1207}, "handlePaste");
1208const Dialog = Root;
1209const DialogPortal = Portal$1;
1210const DialogOverlay = /* @__PURE__ */ reactExports.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntimeExports.jsx(Overlay, {
1211  ref,
1212  className: cn("data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80", className),
1213  ...props
1214}));
1215DialogOverlay.displayName = Overlay.displayName;
1216const DialogContent = /* @__PURE__ */ reactExports.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogPortal, {
1217  children: [
1218    /* @__PURE__ */ jsxRuntimeExports.jsx(DialogOverlay, {}),
1219    /* @__PURE__ */ jsxRuntimeExports.jsxs(Content, {
1220      ref,
1221      className: cn("bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg", className),
1222      ...props,
1223      children: [
1224        children,
1225        /* @__PURE__ */ jsxRuntimeExports.jsxs(Close$1, {
1226          className: "ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none",
1227          children: [
1228            /* @__PURE__ */ jsxRuntimeExports.jsx(X, {
1229              className: "h-4 w-4"
1230            }),
1231            /* @__PURE__ */ jsxRuntimeExports.jsx("span", {
1232              className: "sr-only",
1233              children: "Close"
1234            })
1235          ]
1236        })
1237      ]
1238    })
1239  ]
1240}));
1241DialogContent.displayName = Content.displayName;
1242const DialogTitle = /* @__PURE__ */ reactExports.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntimeExports.jsx(Title$1, {
1243  ref,
1244  className: cn("text-lg font-semibold leading-none tracking-tight", className),
1245  ...props
1246}));
1247DialogTitle.displayName = Title$1.displayName;
1248const DialogDescription = /* @__PURE__ */ reactExports.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntimeExports.jsx(Description$1, {
1249  ref,
1250  className: cn("text-muted-foreground text-sm", className),
1251  ...props
1252}));
1253DialogDescription.displayName = Description$1.displayName;
1254const ImageAttachment = reatomComponent(({ ctx, onRemove, onUpload, attachShortcut: attachShortcut2, error }) => {
1255  const [isPreviewOpen, setIsPreviewOpen] = reactExports.useState(false);
1256  const imagePreviewUrl = ctx.spy(attachedImageAtom.previewUrl);
1257  const imageDetails = ctx.spy(attachedImageAtom.details);
1258  if (ctx.spy(attachedImageAtom.hasImage)) {
1259    return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, {
1260      children: [
1261        /* @__PURE__ */ jsxRuntimeExports.jsx("div", {
1262          className: "flex items-center gap-2",
1263          children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", {
1264            className: cn("group relative flex items-center gap-2", "rounded-lg bg-gray-100/80", "border border-gray-200/50 shadow-sm", "transition-all duration-200 hover:shadow-md"),
1265            onClick: (e) => e.stopPropagation(),
1266            children: [
1267              /* @__PURE__ */ jsxRuntimeExports.jsx("button", {
1268                type: "button",
1269                onClick: () => setIsPreviewOpen(true),
1270                className: cn("relative ml-[1px] h-8 w-8 overflow-hidden rounded-md border border-gray-200/50", "group-hover:ring-primary/20 transition-all duration-200 group-hover:ring-2", "focus-visible:ring-primary focus-visible:outline-none focus-visible:ring-2"),
1271                "aria-label": "Preview image",
1272                children: imagePreviewUrl ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, {
1273                  children: [
1274                    /* @__PURE__ */ jsxRuntimeExports.jsx("img", {
1275                      src: imagePreviewUrl,
1276                      alt: "Problem preview",
1277                      className: "h-full w-full object-cover"
1278                    }),
1279                    /* @__PURE__ */ jsxRuntimeExports.jsx("div", {
1280                      className: cn("absolute inset-0 bg-black/0 group-hover:bg-black/30", "flex items-center justify-center transition-all duration-200", "opacity-0 group-hover:opacity-100"),
1281                      children: /* @__PURE__ */ jsxRuntimeExports.jsx(ZoomIn, {
1282                        className: "h-4 w-4 text-white"
1283                      })
1284                    })
1285                  ]
1286                }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", {
1287                  className: "h-full w-full animate-spin rounded-full border-b-2 border-gray-900 object-cover"
1288                })
1289              }),
1290              !ctx.spy(inputErrorAtom) && imageDetails && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", {
1291                className: "flex flex-col text-xs text-gray-600",
1292                onClick: () => setIsPreviewOpen(true),
1293                children: [
1294                  imageDetails.format,
1295                  " ",
1296                  imageDetails.dimensions || "",
1297                  " • ",
1298                  imageDetails.size
1299                ]
1300              }),
1301              /* @__PURE__ */ jsxRuntimeExports.jsx(Button, {
1302                onClick: onRemove,
1303                variant: "ghost",
1304                size: "icon",
1305                type: "button",
1306                className: cn("ml-1 mr-1 h-6 w-6 rounded-full", "hover:bg-destructive hover:text-destructive-foreground", "transition-colors duration-200"),
1307                "aria-label": "Remove image",
1308                children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, {
1309                  className: "h-4 w-4"
1310                })
1311              })
1312            ]
1313          })
1314        }),
1315        /* @__PURE__ */ jsxRuntimeExports.jsx(Dialog, {
1316          open: isPreviewOpen,
1317          onOpenChange: setIsPreviewOpen,
1318          children: /* @__PURE__ */ jsxRuntimeExports.jsx(DialogContent, {
1319            className: "max-w-4xl overflow-hidden bg-black/95 p-0",
1320            children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", {
1321              className: "relative",
1322              children: [
1323                /* @__PURE__ */ jsxRuntimeExports.jsx(Button, {
1324                  onClick: () => setIsPreviewOpen(false),
1325                  variant: "ghost",
1326                  size: "icon",
1327                  className: cn("absolute right-2 top-2 z-10", "h-8 w-8 rounded-full", "bg-black/50 hover:bg-black/70", "text-white/70 hover:text-white"),
1328                  "aria-label": "Close preview",
1329                  children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, {
1330                    className: "h-4 w-4"
1331                  })
1332                }),
1333                imagePreviewUrl && /* @__PURE__ */ jsxRuntimeExports.jsx("img", {
1334                  src: imagePreviewUrl,
1335                  alt: "Problem preview",
1336                  className: "h-full max-h-[80vh] w-full object-contain"
1337                })
1338              ]
1339            })
1340          })
1341        })
1342      ]
1343    });
1344  }
1345  return /* @__PURE__ */ jsxRuntimeExports.jsx(SimpleTooltip, {
1346    content: `Attach image (${attachShortcut2}), drag & drop or paste`,
1347    children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Button, {
1348      type: "button",
1349      variant: "outline",
1350      size: "sm",
1351      onClick: onUpload,
1352      className: cn("transition-colors duration-200 hover:bg-gray-100", "border-gray-200/50"),
1353      "aria-label": "Attach image",
1354      children: [
1355        /* @__PURE__ */ jsxRuntimeExports.jsx(Image, {
1356          className: "mr-2 h-4 w-4 text-gray-600"
1357        }),
1358        /* @__PURE__ */ jsxRuntimeExports.jsxs("span", {
1359          className: "text-gray-600",
1360          children: [
1361            "Attach",
1362            !error && /* @__PURE__ */ jsxRuntimeExports.jsxs("small", {
1363              className: "xs:inline hidden",
1364              children: [
1365                " (",
1366                attachShortcut2,
1367                ")"
1368              ]
1369            })
1370          ]
1371        })
1372      ]
1373    })
1374  });
1375}, "ImageAttachment");
1376const ShortcutDisplay = ({ shortcut }) => {
1377  return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, {
1378    children: shortcut.split(" + ").map((part, i) => /* @__PURE__ */ jsxRuntimeExports.jsxs("span", {
1379      children: [
1380        i > 0 && " + ",
1381        part === "Enter" ? /* @__PURE__ */ jsxRuntimeExports.jsx(CornerDownLeft, {
1382          className: "relative top-[-0.25px] inline size-[0.9rem]",
1383          "aria-label": part
1384        }) : part
1385      ]
1386    }, part))
1387  });
1388};
1389let browserInfo;
1390try {
1391  browserInfo = UAParser(navigator?.userAgent || void 0);
1392} catch (e) {
1393  console.error("UAParser error:", e);
1394}
1395const bInfo = browserInfo;
1396const getScreenshotHotkeys = () => {
1397  const bi = bInfo;
1398  const type = bi?.device?.type;
1399  if (type === "mobile" || type === "tablet") {
1400    return null;
1401  }
1402  const osName = bi?.os?.name?.toLowerCase();
1403  if (!osName) {
1404    return null;
1405  }
1406  switch (true) {
1407    case (osName.includes("mac") || IS_MAC):
1408      return [
1409        "⌘ + Shift + 4"
1410      ];
1411    case osName.includes("win"):
1412      return [
1413        "Win + Shift + S"
1414      ];
1415    case osName.includes("linux"):
1416      return [
1417        "Shift + Print Screen (GNOME-based)",
1418        "Meta + Shift + S (KDE Plasma with Spectacle)"
1419      ];
1420    case osName.includes("chrome"):
1421      return [
1422        "Ctrl + Shift + Show Windows (⟳ key)"
1423      ];
1424    default:
1425      return null;
1426  }
1427};
1428const MESSAGE_KEY = "problem";
1429const messageAtom = atom("", "messageAtom").pipe(withLocalStorage(MESSAGE_KEY));
1430const LEVEL_KEY = "level";
1431const levelAtom = atom(void 0, "levelAtom").pipe(withLocalStorage(LEVEL_KEY));
1432const EXPANDED_KEY = "expanded";
1433const isExpandedAtom = reatomBoolean(false, "isExpandedAtom").pipe(withLocalStorage(EXPANDED_KEY));
1434const showExpandButtonAtom = atom((ctx) => {
1435  if (ctx.spy(isExpandedAtom)) return true;
1436  const input = ctx.spy(messageAtom);
1437  return input.length > 60 || input.includes("\n");
1438});
1439const submitProblemForSolving = reatomAsync(async (ctx, navigate) => {
1440  const content = ctx.get(messageAtom)?.trim() || void 0;
1441  const image = ctx.get(attachedImageAtom.image) || void 0;
1442  GA.sendEvent("submit_problem", {
1443    content,
1444    image: !!image
1445  });
1446  navigate("/c", {
1447    state: {
1448      content,
1449      image,
1450      lvl: ctx.get(levelAtom),
1451      type: ctx.get(solutionModeAtom).id
1452    }
1453  });
1454  batch(ctx, () => {
1455    messageAtom(ctx, "");
1456    attachedImageAtom.reset(ctx);
1457    ctx.schedule(() => {
1458      LS?.removeItem(MESSAGE_KEY);
1459    });
1460  });
1461}, "submitProblemForSolving");
1462const ctrlMod = IS_MAC ? "⌘" : "Ctrl";
1463const submitShortcut = `${ctrlMod} + Enter`;
1464const expandShortcut = `${ctrlMod} + E`;
1465const attachShortcut = `${ctrlMod} + U`;
1466const captureShortcut = `${ctrlMod} + Shift + S`;
1467const getInvalidUrlTooltip = () => {
1468  const hotkeys = getScreenshotHotkeys();
1469  const msg = "Screen capture is not available on this page. Please open a regular web page or use your OS screenshot functionality";
1470  if (!hotkeys) {
1471    return msg + ".";
1472  }
1473  const hk = hotkeys.map((t) => t.replace(/ /g, " ")).join(" or ");
1474  return `${msg} (${hk}).`;
1475};
1476const hasInput = atom((ctx) => {
1477  return !!ctx.spy(messageAtom).trim() || ctx.spy(attachedImageAtom.hasImage);
1478}, "hasInput");
1479const MathInput = reatomComponent(({ ctx }) => {
1480  const navigate = useNavigate();
1481  const { dismiss: dismissToast } = useToast();
1482  const textareaRef = reactExports.useRef(null);
1483  const fileInputRef = reactExports.useRef(null);
1484  const [isFocused, setIsFocused] = reactExports.useState(false);
1485  const hideError = reactExports.useCallback(() => {
1486    inputErrorAtom(ctx, "");
1487    dismissToast();
1488  }, [
1489    ctx,
1490    dismissToast
1491  ]);
1492  const input = ctx.get(messageAtom);
1493  const handleSubmit = reactExports.useCallback((e) => {
1494    e?.preventDefault();
1495    if (!ctx.get(messageAtom).trim() && !ctx.get(attachedImageAtom.hasImage)) {
1496      inputErrorAtom.show(ctx, "Please enter a math problem or upload an image");
1497      return;
1498    }
1499    hideError();
1500    submitProblemForSolving(ctx, navigate);
1501    isExpandedAtom(ctx, false);
1502  }, [
1503    ctx,
1504    navigate,
1505    hideError
1506  ]);
1507  const handleKeyDown = reactExports.useCallback((e) => {
1508    if (!e.metaKey && !e.ctrlKey) return;
1509    const key = e.key.toLowerCase();
1510    if (key === "enter") {
1511      handleSubmit(e);
1512    } else if (key === "e") {
1513      e.preventDefault();
1514      isExpandedAtom.toggle(ctx);
1515    } else if (key === "u") {
1516      e.preventDefault();
1517      fileInputRef.current?.click();
1518    } else if (key === "s" && e.shiftKey) {
1519      e.preventDefault();
1520      screenCaptureAtom.start(ctx, "shortcut");
1521    }
1522  }, [
1523    handleSubmit,
1524    ctx
1525  ]);
1526  reactExports.useEffect(() => {
1527    document.addEventListener("keydown", handleKeyDown);
1528    return () => document.removeEventListener("keydown", handleKeyDown);
1529  }, [
1530    ctx,
1531    handleKeyDown
1532  ]);
1533  const removeImage = (e) => {
1534    e?.preventDefault();
1535    attachedImageAtom.reset(ctx);
1536    const fileInput = fileInputRef.current;
1537    if (fileInput) {
1538      fileInput.value = "";
1539    }
1540  };
1541  const error = ctx.spy(inputErrorAtom);
1542  const isExpanded = ctx.spy(isExpandedAtom);
1543  const showExpandButton = ctx.spy(showExpandButtonAtom);
1544  const solutionType = ctx.spy(solutionModeAtom).id;
1545  const TheSolveIcon = solutionType === "stepby" ? Sparkles : solutionType === "tutor" ? Brain : Zap;
1546  const solveButtonAction = solutionType === "tutor" ? "Explain" : "Solve";
1547  return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, {
1548    children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", {
1549      className: "mx-auto w-full max-w-2xl",
1550      onClick: () => {
1551        textareaRef.current?.focus();
1552        hideError();
1553      },
1554      children: /* @__PURE__ */ jsxRuntimeExports.jsxs("form", {
1555        className: cn("relative overflow-hidden rounded-xl transition-all duration-200", "border bg-white/80 shadow-sm backdrop-blur-lg", "focus-within:ring-primary/20 focus-within:shadow-md focus-within:ring-2 hover:shadow-md", error && "ring-destructive ring-2" || isFocused && "ring-primary/20 ring-2"),
1556        onSubmit: handleSubmit,
1557        "aria-label": "Math problem input form",
1558        role: "form",
1559        children: [
1560          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", {
1561            className: "relative",
1562            children: [
1563              /* @__PURE__ */ jsxRuntimeExports.jsx("textarea", {
1564                value: input,
1565                autoFocus: true,
1566                ref: textareaRef,
1567                onChange: (e) => {
1568                  messageAtom(ctx, e.target.value);
1569                  hideError();
1570                },
1571                onFocus: () => setIsFocused(true),
1572                onBlur: () => setIsFocused(false),
1573                onPaste: (e) => handlePaste(ctx, e),
1574                placeholder: !ctx.spy(attachedImageAtom.hasImage) ? "Type your math question or attach an image..." : "Type your math question or comment for the attached image...",
1575                className: cn("min-h-20 w-full bg-transparent outline-none", "p-4 text-gray-800 placeholder:text-gray-400", isExpanded ? "h-48 resize-y" : "h-20 resize-none transition-all duration-75"),
1576                "aria-label": "Math problem input",
1577                "aria-invalid": !!error,
1578                "aria-describedby": error ? "input-error" : void 0
1579              }),
1580              showExpandButton && /* @__PURE__ */ jsxRuntimeExports.jsx(SimpleTooltip, {
1581                content: (isExpanded ? "Collapse" : "Expand") + ` (${expandShortcut})`,
1582                children: /* @__PURE__ */ jsxRuntimeExports.jsx(Button, {
1583                  type: "button",
1584                  variant: "ghost",
1585                  size: "icon",
1586                  onClick: () => isExpandedAtom.toggle(ctx),
1587                  className: "absolute right-2 top-2 h-6 w-6 rounded-lg transition-colors duration-200 hover:bg-gray-100/50",
1588                  "aria-label": isExpanded ? "Collapse input" : "Expand input",
1589                  children: isExpanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(Minimize2, {
1590                    className: "h-4 w-4 text-gray-400"
1591                  }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Maximize2, {
1592                    className: "h-4 w-4 text-gray-400"
1593                  })
1594                })
1595              })
1596            ]
1597          }),
1598          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", {
1599            className: "flex flex-row justify-between gap-1 border-t bg-gray-50/50 p-2 sm:gap-2",
1600            children: [
1601              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", {
1602                className: "flex flex-row items-start gap-1 sm:gap-2",
1603                children: [
1604                  ctx.spy(hasExtensionAtom) && !ctx.spy(attachedImageAtom.hasImage) && /* @__PURE__ */ jsxRuntimeExports.jsx(SimpleTooltip, {
1605                    content: ctx.spy(extensionCtxAtom.isValidUrl) ? `Capture area (${captureShortcut})` : getInvalidUrlTooltip(),
1606                    children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", {
1607                      children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Button, {
1608                        type: "button",
1609                        variant: "outline",
1610                        size: "sm",
1611                        onClick: () => screenCaptureAtom.start(ctx, "button"),
1612                        className: cn("transition-colors duration-200 hover:bg-gray-100", "border-gray-200/50", !ctx.spy(extensionCtxAtom.isValidUrl) && "cursor-not-allowed opacity-50 hover:bg-transparent"),
1613                        "aria-label": "Capture area",
1614                        disabled: !ctx.spy(extensionCtxAtom.isValidUrl),
1615                        children: [
1616                          /* @__PURE__ */ jsxRuntimeExports.jsx(Scissors, {
1617                            className: "mr-2 h-4 w-4 text-gray-600"
1618                          }),
1619                          /* @__PURE__ */ jsxRuntimeExports.jsxs("span", {
1620                            className: "text-gray-600",
1621                            children: [
1622                              "Capture",
1623                              !error && ctx.spy(extensionCtxAtom.isValidUrl) && /* @__PURE__ */ jsxRuntimeExports.jsxs("small", {
1624                                className: "xs:inline hidden",
1625                                children: [
1626                                  " (",
1627                                  captureShortcut,
1628                                  ")"
1629                                ]
1630                              })
1631                            ]
1632                          })
1633                        ]
1634                      })
1635                    })
1636                  }),
1637                  /* @__PURE__ */ jsxRuntimeExports.jsx("div", {
1638                    className: "flex items-center gap-2",
1639                    children: /* @__PURE__ */ jsxRuntimeExports.jsx(ImageAttachment, {
1640                      onRemove: removeImage,
1641                      onUpload: () => fileInputRef.current?.click(),
1642                      attachShortcut
1643                    })
1644                  }),
1645                  error && /* @__PURE__ */ jsxRuntimeExports.jsx("div", {
1646                    id: "input-error",
1647                    className: "text-destructive max-w-full break-words text-sm",
1648                    role: "alert",
1649                    children: error
1650                  })
1651                ]
1652              }),
1653              /* @__PURE__ */ jsxRuntimeExports.jsx(SimpleTooltip, {
1654                content: `${solveButtonAction} (${submitShortcut})`,
1655                children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Button, {
1656                  type: "submit",
1657                  size: "sm",
1658                  className: cn("bg-primary text-white transition-all duration-200", !ctx.spy(hasInput) ? "cursor-not-allowed opacity-50" : "hover:bg-primary/90 hover:scale-[1.02] hover:shadow-md"),
1659                  "aria-label": "Solve math problem",
1660                  children: [
1661                    /* @__PURE__ */ jsxRuntimeExports.jsx(TheSolveIcon, {
1662                      className: "mr-2 h-4 w-4"
1663                    }),
1664                    /* @__PURE__ */ jsxRuntimeExports.jsxs("span", {
1665                      className: "flex items-center gap-1.5",
1666                      children: [
1667                        solveButtonAction,
1668                        !error && /* @__PURE__ */ jsxRuntimeExports.jsxs("small", {
1669                          className: "xs:inline hidden",
1670                          children: [
1671                            " ",
1672                            "(",
1673                            /* @__PURE__ */ jsxRuntimeExports.jsx(ShortcutDisplay, {
1674                              shortcut: submitShortcut
1675                            }),
1676                            ")"
1677                          ]
1678                        })
1679                      ]
1680                    })
1681                  ]
1682                })
1683              })
1684            ]
1685          }),
1686          /* @__PURE__ */ jsxRuntimeExports.jsx("input", {
1687            type: "file",
1688            accept: ALLOWED_IMAGE_TYPES.join(","),
1689            ref: fileInputRef,
1690            className: "hidden",
1691            onChange: (e) => {
1692              if (!handleImageFiles(ctx, e.target.files)) {
1693                e.target.value = "";
1694              }
1695            },
1696            "aria-label": "Upload image"
1697          })
1698        ]
1699      })
1700    })
1701  });
1702});
1703const EXTENSION_ID = "bjilalbcjkmilhhkfagmblkoekicmcnf";
1704var __defProp = Object.defineProperty;
1705var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1706var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
1707const extensionCtxAtom = atom(null, "extensionContext").pipe(withAssign((ext, name) => {
1708  return {
1709    id: atom((ctx) => ctx.spy(ext)?.extensionId, name + ".id"),
1710    userId: atom((ctx) => ctx.spy(ext)?.userId, name + ".userId"),
1711    tabId: atom(0, name + ".tabId"),
1712    url: atom("", name + ".url"),
1713    isValidUrl: atom(true, name + ".isValidUrl")
1714  };
1715}));
1716const hasExtensionAtom = atom((ctx) => !!ctx.spy(extensionCtxAtom.id));
1717const hasWindow = typeof window !== "undefined";
1718const w = hasWindow ? window : {};
1719const parentWindow = hasWindow && w.parent !== w && w.parent;
1720const chromRuntime = hasWindow && "chrome" in window && chrome.runtime;
1721const _ExtBridge = class _ExtBridge2 {
1722  constructor(ctx) {
1723    __publicField(this, "messageHandlers", /* @__PURE__ */ new Map());
1724    __publicField(this, "initialized", false);
1725    __publicField(this, "extensionId", null);
1726    __publicField(this, "comm", null);
1727    __publicField(this, "handleRuntimeMessage", (msg, sender) => {
1728      if (!msg) return;
1729      if (!isCommMsg(msg)) {
1730        return;
1731      }
1732      this.processMessage(msg, "runtime");
1733    });
1734    __publicField(this, "handleMessage", (event) => {
1735      const { data, origin } = event;
1736      if (!isExtensionOrigin(origin) || !isCommMsg(data) && data) {
1737        return;
1738      }
1739      this.processMessage(data, "iframe");
1740    });
1741    __publicField(this, "processMessage", (msg, via) => {
1742      if (msg.eid) {
1743        this.initialized = true;
1744        this.extensionId = msg.eid;
1745      }
1746      this.messageHandlers.get(msg.t)?.forEach((handler) => handler(msg));
1747    });
1748    if (hasWindow) {
1749      const w2 = window;
1750      w2.addEventListener("message", this.handleMessage);
1751      const urlParams = new URLSearchParams(w2.location.search);
1752      const extensionId = urlParams.get(EXTENSION_ID_PARAM) || EXTENSION_ID;
1753      this.extensionId = extensionId;
1754      if (parentWindow) {
1755        const userId = urlParams.get(USER_ID_PARAM);
1756        if (userId) {
1757          getUserId(ctx);
1758        }
1759        extensionCtxAtom(ctx, {
1760          isExtension: true,
1761          userId,
1762          extensionId
1763        });
1764        if (chromRuntime) {
1765          this.comm = new WebAppCommunicator(extensionId, this.handleRuntimeMessage);
1766        }
1767      }
1768      this.onMessage(CommMsgType.startSolvingCmd, async (msg) => {
1769        try {
1770          const d = msg.d;
1771          const text = d?.text?.trim();
1772          if (text) {
1773            messageAtom(ctx, (prev) => {
1774              prev = prev.trim();
1775              return prev ? prev + "\n" + text : text;
1776            });
1777          }
1778          let image = d?.image;
1779          if (image) {
1780            GA.sendEvent("ext_screenshot", {
1781              imageChars: typeof image === "string" ? image.length : 0
1782            });
1783            if (!(image instanceof File)) {
1784              try {
1785                image = await getFilefromDataUrl(image, "screenshot.png");
1786              } catch (error) {
1787                attachedImageAtom.previewUrl(ctx, image);
1788                return;
1789              }
1790            }
1791            validateAndProcessImage(ctx, image);
1792          }
1793        } finally {
1794          screenCaptureAtom.stop(ctx);
1795        }
1796      });
1797      this.onMessage(CommMsgType.getTabState, (msg) => {
1798        batch(ctx, () => {
1799          const tabId = msg.tabId || 0;
1800          const url = String(msg.v || "");
1801          const state = msg.d;
1802          extensionCtxAtom.tabId(ctx, tabId);
1803          extensionCtxAtom.url(ctx, url);
1804          extensionCtxAtom.isValidUrl(ctx, state !== ExtensionState.unsupported);
1805        });
1806      });
1807      this.sendMessage(PingMsg).catch((err) => {
1808      });
1809    }
1810  }
1811  static getInstance(ctx) {
1812    if (!_ExtBridge2.instance) {
1813      if (!ctx) throw new Error("Context required for ExtBridge");
1814      _ExtBridge2.instance = new _ExtBridge2(ctx);
1815    }
1816    return _ExtBridge2.instance;
1817  }
1818  async sendMessage(msg) {
1819    return new Promise(async (resolve, reject) => {
1820      if (!hasWindow) return resolve();
1821      msg.from = MsgFrom.WebApp;
1822      let err;
1823      let couldSend = false;
1824      const comm = this.comm;
1825      if (chromRuntime && comm) {
1826        couldSend = true;
1827        try {
1828          await comm.sendMsg(msg);
1829          return resolve(true);
1830        } catch (error) {
1831          err = safeErrorCause(error);
1832          console.error("Failed to send runtime message:", err);
1833        }
1834      }
1835      if (parentWindow) {
1836        couldSend = true;
1837        try {
1838          parentWindow.postMessage(msg, "*");
1839          return resolve(true);
1840        } catch (error) {
1841          err = safeErrorCause(error, err);
1842          console.error("Failed to send iframe message:", err);
1843        }
1844      }
1845      if (!err && !couldSend) {
1846        return resolve(false);
1847      }
1848      reject(err || new Error("Could not send message"));
1849    });
1850  }
1851  onMessage(type, handler) {
1852    if (!this.messageHandlers.has(type)) {
1853      this.messageHandlers.set(type, /* @__PURE__ */ new Set());
1854    }
1855    this.messageHandlers.get(type).add(handler);
1856    return () => {
1857      const handlers = this.messageHandlers.get(type);
1858      if (handlers) {
1859        handlers.delete(handler);
1860        if (handlers.size === 0) {
1861          this.messageHandlers.delete(type);
1862        }
1863      }
1864    };
1865  }
1866};
1867__publicField(_ExtBridge, "instance");
1868let ExtBridge = _ExtBridge;
1869const reatomCtx = createCtx();
1870const CreateAppInternal = () => /* @__PURE__ */ jsxRuntimeExports.jsx(reatomContext.Provider, {
1871  value: reatomCtx,
1872  children: /* @__PURE__ */ jsxRuntimeExports.jsx(App, {})
1873});
1874const createApp = () => {
1875  return /* @__PURE__ */ jsxRuntimeExports.jsx(CreateAppInternal, {});
1876};
1877const mount = () => {
1878  const rootNode = document.getElementById("app");
1879  if (!rootNode) {
1880    throw new Error("#app element not found");
1881  }
1882  const root = clientExports.createRoot(rootNode);
1883  root.render(createApp());
1884};
1885if (typeof window !== "undefined") {
1886  ExtBridge.getInstance(reatomCtx);
1887  getUserId(reatomCtx);
1888  mount();
1889}
1890export {
1891  ALLOWED_HINT as A,
1892  Button as B,
1893  EXTENSION_ID as E,
1894  GA as G,
1895  IS_MAC as I,
1896  MathInput as M,
1897  SolutionTypeModes as S,
1898  Tooltip as T,
1899  isDraggingAtom as a,
1900  getUserId as b,
1901  cn as c,
1902  hasExtensionAtom as d,
1903  ShortcutDisplay as e,
1904  findSolutionTypeMode as f,
1905  getScreenshotHotkeys as g,
1906  handlePaste as h,
1907  inputErrorAtom as i,
1908  ABORTED as j,
1909  safeErrorCause as k,
1910  uuidv7b64 as l,
1911  fileToBase64 as m,
1912  reatomCtx as r,
1913  solutionModeAtom as s,
1914  useToast as u
1915};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.