PageSourceSearch

https://app.landingsite.ai/assets/ReactWebsiteChatPage-DmjgzGss.js

js landingsite.ai collected 2026-10-01 10:29:13 UTC 664,352 bytes, 15,570 lines download raw bytes

1
2!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="ea5d659a-f734-5a99-962b-fd02b29dfbea")}catch(e){}}();
3const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/SiteViews-DrsHYaEK.js","assets/index-Bv8xuwng.js","assets/index-CWThiHjA.css","assets/index-C0ROMDRt.js","assets/index-Bj-Tdrlr.js","assets/index-CbDwmQ86.js","assets/AlertDialog-DKoWGq1L.js","assets/HeaderSitePicker-BQ3o99R_.js","assets/landingDestination-DvFBkeeK.js","assets/index-DyCuF-Ol.js","assets/createLucideIcon-5bFtwJ8F.js","assets/index-DyMO7Qub.js","assets/index-CgW23jqL.js","assets/styles-CwIrWvkA.css"])))=>i.map(i=>d[i]);
4import { r as reactExports, i as usePostHog, j as jsxRuntimeExports, B as Button, c as cn$1, R as React, a as useAuth, _ as _t, k as useMutation, a8 as useQuery, n as navigate, d as namedRoutes, a9 as reactDomExports, aa as useFloating, ab as offset, ac as shift, ad as flip, ae as size, af as arrow, ag as hide, ah as limitShift, ai as autoUpdate, aj as ReactDOM, b as useMutation$1, h as useLazyQuery, ak as clsx, g as gql, al as RECORD_ACQUISITION, am as stashSurveyAnswer, f as useQuery$1, e as useLocation, an as __vitePreload, ao as useApolloClient } from "./index-Bv8xuwng.js";
5import { c as cn, C as Check, s as siteIdentityText, h as hideOthers, R as ReactRemoveScroll, a as Root2$2, T as Trigger, b as Portal2, d as Content2$1, I as Item2 } from "./HeaderSitePicker-BQ3o99R_.js";
6import { M as Metadata } from "./Metadata-DVDCZJgT.js";
7import { F as FileText, C as ChevronLeft, g as generateId, u as useUploadImage, a as getFreshToken, b as getTokenExpirationInfo, R as ResetButton, A as ArrowDown, c as ChevronsDown, d as ChevronsUp, G as Gallery, e as useBreakpoint, f as useRecordLastViewedWebsite, I as ImpersonationReviewBanner, S as SiteCaseNoticeBanner, P as PaymentPastDueBanner, h as ChatErrorBoundary } from "./useRecordLastViewedWebsite-CnCuCtnj.js";
8import { c as commerceSetupCopy, o as openCommerceWebsiteSetup, C as CommerceSetupCheckedAt, u as useCommerceSetupRefresh, a as commerceSetupNeedsPolling, b as openCommerceStripeDashboard } from "./CommerceSetupCheckedAt-BSwtY7Ui.js";
9import { C as Card, d as CardContent } from "./Card-C12BVEU3.js";
10import { D as Dialog, a as DialogContent, c as DialogTitle, b as DialogHeader, d as DialogDescription, e as DialogFooter } from "./Dialog-Coyn2AE3.js";
11import { T as Textarea } from "./Textarea-DUWZ_F-N.js";
12import { T as TooltipProvider, a as Tooltip, b as TooltipTrigger, c as TooltipContent } from "./Tooltip-B4vM7gok.js";
13import { G as Globe, R as Rocket, P as PublishBlockedModal } from "./PublishBlockedModal-CMrnNTuT.js";
14import { c as createLucideIcon } from "./createLucideIcon-5bFtwJ8F.js";
15import { U as User } from "./user-DSqjZOH1.js";
16import { E as Eye } from "./eye-DgExikkT.js";
17import { I as Image } from "./image-D-MEnABj.js";
18import { I as Info } from "./info-C-I9rgjO.js";
19import { S as Search } from "./search-B5_IJnHE.js";
20import { C as ChevronRight } from "./chevron-right-DfOUACDI.js";
21import { L as LoaderCircle } from "./loader-circle-NFrOwZ3p.js";
22import { C as CircleAlert, T as TriangleAlert } from "./triangle-alert-D7W416og.js";
23import { M as Markdown, r as remarkGfm } from "./index-DXVraWYZ.js";
24import { X } from "./x-CJvENK3D.js";
25import { M as MessageSquare } from "./message-square-29qClUa_.js";
26import { C as ChevronUp } from "./chevron-up-KHSg5zQ5.js";
27import { R as RefreshCw } from "./refresh-cw-CMxI2avz.js";
28import { P as Pencil } from "./pencil-DW93RWca.js";
29import { S as ShieldCheck } from "./shield-check-gSvVll7c.js";
30import { R as ReactNavbar } from "./ReactNavbar-C7WhcDeQ.js";
31import { c as composeEventHandlers, u as useSize } from "./index-DyMO7Qub.js";
32import { u as useComposedRefs, c as createContextScope, a as useLayoutEffect2, b as useControllableState } from "./index-Bj-Tdrlr.js";
33import { u as useEscapeKeydown, a as useId, A as AlertDialog, b as AlertDialogContent, c as AlertDialogHeader, d as AlertDialogTitle, e as AlertDialogDescription, f as AlertDialogFooter, g as AlertDialogCancel, h as AlertDialogAction } from "./AlertDialog-DKoWGq1L.js";
34import { I as Input } from "./Input-Crzez_vD.js";
35import { L as Label } from "./Label-B4OPMqgJ.js";
36import { C as ChevronDown } from "./chevron-down-CL642vyV.js";
37import "./landingDestination-DvFBkeeK.js";
38import "./index-DyCuF-Ol.js";
39import "./Tabs-7vkR9jPC.js";
40import "./index-s9LeGatc.js";
41import "./load-parse-D6ADZb7m.js";
42import "./trash-2-CZVMywOH.js";
43import "./IconBase-B6twkb8E.js";
44/**
45 * @license lucide-react v0.456.0 - ISC
46 *
47 * This source code is licensed under the ISC license.
48 * See the LICENSE file in the root directory of this source tree.
49 */
50const Activity = createLucideIcon("Activity", [
51  [
52    "path",
53    {
54      d: "M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l
54-2.35 8.36A2 2 0 0 1 4.49 12H2",
55      key: "169zse"
56    }
57  ]
58]);
59/**
60 * @license lucide-react v0.456.0 - ISC
61 *
62 * This source code is licensed under the ISC license.
63 * See the LICENSE file in the root directory of this source tree.
64 */
65const AppWindow = createLucideIcon("AppWindow", [
66  ["rect", { x: "2", y: "4", width: "20", height: "16", rx: "2", key: "izxlao" }],
67  ["path", { d: "M10 4v4", key: "pp8u80" }],
68  ["path", { d: "M2 8h20", key: "d11cs7" }],
69  ["path", { d: "M6 4v4", key: "1svtjw" }]
70]);
71/**
72 * @license lucide-react v0.456.0 - ISC
73 *
74 * This source code is licensed under the ISC license.
75 * See the LICENSE file in the root directory of this source tree.
76 */
77const ArrowUp = createLucideIcon("ArrowUp", [
78  ["path", { d: "m5 12 7-7 7 7", key: "hav0vg" }],
79  ["path", { d: "M12 19V5", key: "x0mq9r" }]
80]);
81/**
82 * @license lucide-react v0.456.0 - ISC
83 *
84 * This source code is licensed under the ISC license.
85 * See the LICENSE file in the root directory of this source tree.
86 */
87const Banknote = createLucideIcon("Banknote", [
88  ["rect", { width: "20", height: "12", x: "2", y: "6", rx: "2", key: "9lu3g6" }],
89  ["circle", { cx: "12", cy: "12", r: "2", key: "1c9p78" }],
90  ["path", { d: "M6 12h.01M18 12h.01", key: "113zkx" }]
91]);
92/**
93 * @license lucide-react v0.456.0 - ISC
94 *
95 * This source code is licensed under the ISC license.
96 * See the LICENSE file in the root directory of this source tree.
97 */
98const BookOpen = createLucideIcon("BookOpen", [
99  ["path", { d: "M12 7v14", key: "1akyts" }],
100  [
101    "path",
102    {
103      d: "M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z",
104      key: "ruj8y"
105    }
106  ]
107]);
108/**
109 * @license lucide-react v0.456.0 - ISC
110 *
111 * This source code is licensed under the ISC license.
112 * See the LICENSE file in the root directory of this source tree.
113 */
114const Box = createLucideIcon("Box", [
115  [
116    "path",
117    {
118      d: "M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z",
119      key: "hh9hay"
120    }
121  ],
122  ["path", { d: "m3.3 7 8.7 5 8.7-5", key: "g66t2b" }],
123  ["path", { d: "M12 22V12", key: "d0xqtd" }]
124]);
125/**
126 * @license lucide-react v0.456.0 - ISC
127 *
128 * This source code is licensed under the ISC license.
129 * See the LICENSE file in the root directory of this source tree.
130 */
131const Camera = createLucideIcon("Camera", [
132  [
133    "path",
134    {
135      d: "M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z",
136      key: "1tc9qg"
137    }
138  ],
139  ["circle", { cx: "12", cy: "13", r: "3", key: "1vg3eu" }]
140]);
141/**
142 * @license lucide-react v0.456.0 - ISC
143 *
144 * This source code is licensed under the ISC license.
145 * See the LICENSE file in the root directory of this source tree.
146 */
147const ChartNoAxesColumn = createLucideIcon("ChartNoAxesColumn", [
148  ["line", { x1: "18", x2: "18", y1: "20", y2: "10", key: "1xfpm4" }],
149  ["line", { x1: "12", x2: "12", y1: "20", y2: "4", key: "be30l9" }],
150  ["line", { x1: "6", x2: "6", y1: "20", y2: "14", key: "1r4le6" }]
151]);
152/**
153 * @license lucide-react v0.456.0 - ISC
154 *
155 * This source code is licensed under the ISC license.
156 * See the LICENSE file in the root directory of this source tree.
157 */
158const ClipboardList = createLucideIcon("ClipboardList", [
159  ["rect", { width: "8", height: "4", x: "8", y: "2", rx: "1", ry: "1", key: "tgr4d6" }],
160  [
161    "path",
162    {
163      d: "M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2",
164      key: "116196"
165    }
166  ],
167  ["path", { d: "M12 11h4", key: "1jrz19" }],
168  ["path", { d: "M12 16h4", key: "n85exb" }],
169  ["path", { d: "M8 11h.01", key: "1dfujw" }],
170  ["path", { d: "M8 16h.01", key: "18s6g9" }]
171]);
172/**
173 * @license lucide-react v0.456.0 - ISC
174 *
175 * This source code is licensed under the ISC license.
176 * See the LICENSE file in the root directory of this source tree.
177 */
178const Compass = createLucideIcon("Compass", [
179  [
180    "path",
181    {
182      d: "m16.24 7.76-1.804 5.411a2 2 0 0 1-1.265 1.265L7.76 16.24l1.804-5.411a2 2 0 0 1 1.265-1.265z",
183      key: "9ktpf1"
184    }
185  ],
186  ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }]
187]);
188/**
189 * @license lucide-react v0.456.0 - ISC
190 *
191 * This source code is licensed under the ISC license.
192 * See the LICENSE file in the root directory of this source tree.
193 */
194const CornerDownLeft = createLucideIcon("CornerDownLeft", [
195  ["polyline", { points: "9 10 4 15 9 20", key: "r3jprv" }],
196  ["path", { d: "M20 4v7a4 4 0 0 1-4 4H4", key: "6o5b7l" }]
197]);
198/**
199 * @license lucide-react v0.456.0 - ISC
200 *
201 * This source code is licensed under the ISC license.
202 * See the LICENSE file in the root directory of this source tree.
203 */
204const CreditCard = createLucideIcon("CreditCard", [
205  ["rect", { width: "20", height: "14", x: "2", y: "5", rx: "2", key: "ynyp8z" }],
206  ["line", { x1: "2", x2: "22", y1: "10", y2: "10", key: "1b3vmo" }]
207]);
208/**
209 * @license lucide-react v0.456.0 - ISC
210 *
211 * This source code is licensed under the ISC license.
212 * See the LICENSE file in the root directory of this source tree.
213 */
214const EyeOff = createLucideIcon("EyeOff", [
215  [
216    "path",
217    {
218      d: "M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49",
219      key: "ct8e1f"
220    }
221  ],
222  ["path", { d: "M14.084 14.158a3 3 0 0 1-4.242-4.242", key: "151rxh" }],
223  [
224    "path",
225    {
226      d: "M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143",
227      key: "13bj9a"
228    }
229  ],
230  ["path", { d: "m2 2 20 20", key: "1ooewy" }]
231]);
232/**
233 * @license lucide-react v0.456.0 - ISC
234 *
235 * This source code is licensed under the ISC license.
236 * See the LICENSE file in the root directory of this source tree.
237 */
238const FilePen = createLucideIcon("FilePen", [
239  ["path", { d: "M12.5 22H18a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v9.5", key: "1couwa" }],
240  ["path", { d: "M14 2v4a2 2 0 0 0 2 2h4", key: "tnqrlb" }],
241  [
242    "path",
243    {
244      d: "M13.378 15.626a1 1 0 1 0-3.004-3.004l-5.01 5.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z",
245      key: "1y4qbx"
246    }
247  ]
248]);
249/**
250 * @license lucide-react v0.456.0 - ISC
251 *
252 * This source code is licensed under the ISC license.
253 * See the LICENSE file in the root directory of this source tree.
254 */
255const FilePlus2 = createLucideIcon("FilePlus2", [
256  ["path", { d: "M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4", key: "1pf5j1" }],
257  ["path", { d: "M14 2v4a2 2 0 0 0 2 2h4", key: "tnqrlb" }],
258  ["path", { d: "M3 15h6", key: "4e2qda" }],
259  ["path", { d: "M6 12v6", key: "1u72j0" }]
260]);
261/**
262 * @license lucide-react v0.456.0 - ISC
263 *
264 * This source code is licensed under the ISC license.
265 * See the LICENSE file in the root directory of this source tree.
266 */
267const Files = createLucideIcon("Files", [
268  ["path", { d: "M20 7h-3a2 2 0 0 1-2-2V2", key: "x099mo" }],
269  ["path", { d: "M9 18a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h7l4 4v10a2 2 0 0 1-2 2Z", key: "18t6ie" }],
270  ["path", { d: "M3 7.6v12.8A1.6 1.6 0 0 0 4.6 22h9.8", key: "1nja0z" }]
271]);
272/**
273 * @license lucide-react v0.456.0 - ISC
274 *
275 * This source code is licensed under the ISC license.
276 * See the LICENSE file in the root directory of this source tree.
277 */
278const House = createLucideIcon("House", [
279  ["path", { d: "M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8", key: "5wwlr5" }],
280  [
281    "path",
282    {
283      d: "M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z",
284      key: "1d0kgt"
285    }
286  ]
287]);
288/**
289 * @license lucide-react v0.456.0 - ISC
290 *
291 * This source code is licensed under the ISC license.
292 * See the LICENSE file in the root directory of this source tree.
293 */
294const Images = createLucideIcon("Images", [
295  ["path", { d: "M18 22H4a2 2 0 0 1-2-2V6", key: "pblm9e" }],
296  ["path", { d: "m22 13-1.296-1.296a2.41 2.41 0 0 0-3.408 0L11 18", key: "nf6bnh" }],
297  ["circle", { cx: "12", cy: "8", r: "2", key: "1822b1" }],
298  ["rect", { width: "16", height: "16", x: "6", y: "2", rx: "2", key: "12espp" }]
299]);
300/**
301 * @license lucide-react v0.456.0 - ISC
302 *
303 * This source code is licensed under the ISC license.
304 * See the LICENSE file in the root directory of this source tree.
305 */
306const LayoutGrid = createLucideIcon("LayoutGrid", [
307  ["rect", { width: "7", height: "7", x: "3", y: "3", rx: "1", key: "1g98yp" }],
308  ["rect", { width: "7", height: "7", x: "14", y: "3", rx: "1", key: "6d4xhi" }],
309  ["rect", { width: "7", height: "7", x: "14", y: "14", rx: "1", key: "nxv5o0" }
309],
310  ["rect", { width: "7", height: "7", x: "3", y: "14", rx: "1", key: "1bb6yr" }]
311]);
312/**
313 * @license lucide-react v0.456.0 - ISC
314 *
315 * This source code is licensed under the ISC license.
316 * See the LICENSE file in the root directory of this source tree.
317 */
318const LayoutTemplate = createLucideIcon("LayoutTemplate", [
319  ["rect", { width: "18", height: "7", x: "3", y: "3", rx: "1", key: "f1a2em" }],
320  ["rect", { width: "9", height: "7", x: "3", y: "14", rx: "1", key: "jqznyg" }],
321  ["rect", { width: "5", height: "7", x: "16", y: "14", rx: "1", key: "q5h2i8" }]
322]);
323/**
324 * @license lucide-react v0.456.0 - ISC
325 *
326 * This source code is licensed under the ISC license.
327 * See the LICENSE file in the root directory of this source tree.
328 */
329const Monitor = createLucideIcon("Monitor", [
330  ["rect", { width: "20", height: "14", x: "2", y: "3", rx: "2", key: "48i651" }],
331  ["line", { x1: "8", x2: "16", y1: "21", y2: "21", key: "1svkeh" }],
332  ["line", { x1: "12", x2: "12", y1: "17", y2: "21", key: "vw1qmm" }]
333]);
334/**
335 * @license lucide-react v0.456.0 - ISC
336 *
337 * This source code is licensed under the ISC license.
338 * See the LICENSE file in the root directory of this source tree.
339 */
340const MousePointerClick = createLucideIcon("MousePointerClick", [
341  ["path", { d: "M14 4.1 12 6", key: "ita8i4" }],
342  ["path", { d: "m5.1 8-2.9-.8", key: "1go3kf" }],
343  ["path", { d: "m6 12-1.9 2", key: "mnht97" }],
344  ["path", { d: "M7.2 2.2 8 5.1", key: "1cfko1" }],
345  [
346    "path",
347    {
348      d: "M9.037 9.69a.498.498 0 0 1 .653-.653l11 4.5a.5.5 0 0 1-.074.949l-4.349 1.041a1 1 0 0 0-.74.739l-1.04 4.35a.5.5 0 0 1-.95.074z",
349      key: "s0h3yz"
350    }
351  ]
352]);
353/**
354 * @license lucide-react v0.456.0 - ISC
355 *
356 * This source code is licensed under the ISC license.
357 * See the LICENSE file in the root directory of this source tree.
358 */
359const PackageCheck = createLucideIcon("PackageCheck", [
360  ["path", { d: "m16 16 2 2 4-4", key: "gfu2re" }],
361  [
362    "path",
363    {
364      d: "M21 10V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l2-1.14",
365      key: "e7tb2h"
366    }
367  ],
368  ["path", { d: "m7.5 4.27 9 5.15", key: "1c824w" }],
369  ["polyline", { points: "3.29 7 12 12 20.71 7", key: "ousv84" }],
370  ["line", { x1: "12", x2: "12", y1: "22", y2: "12", key: "a4e8g8" }]
371]);
372/**
373 * @license lucide-react v0.456.0 - ISC
374 *
375 * This source code is licensed under the ISC license.
376 * See the LICENSE file in the root directory of this source tree.
377 */
378const Package = createLucideIcon("Package", [
379  [
380    "path",
381    {
382      d: "M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z",
383      key: "1a0edw"
384    }
385  ],
386  ["path", { d: "M12 22V12", key: "d0xqtd" }],
387  ["path", { d: "m3.3 7 7.703 4.734a2 2 0 0 0 1.994 0L20.7 7", key: "yx3hmr" }],
388  ["path", { d: "m7.5 4.27 9 5.15", key: "1c824w" }]
389]);
390/**
391 * @license lucide-react v0.456.0 - ISC
392 *
393 * This source code is licensed under the ISC license.
394 * See the LICENSE file in the root directory of this source tree.
395 */
396const Palette = createLucideIcon("Palette", [
397  ["circle", { cx: "13.5", cy: "6.5", r: ".5", fill: "currentColor", key: "1okk4w" }],
398  ["circle", { cx: "17.5", cy: "10.5", r: ".5", fill: "currentColor", key: "f64h9f" }],
399  ["circle", { cx: "8.5", cy: "7.5", r: ".5", fill: "currentColor", key: "fotxhn" }],
400  ["circle", { cx: "6.5", cy: "12.5", r: ".5", fill: "currentColor", key: "qy21gx" }],
401  [
402    "path",
403    {
404      d: "M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z",
405      key: "12rzf8"
406    }
407  ]
408]);
409/**
410 * @license lucide-react v0.456.0 - ISC
411 *
412 * This source code is licensed under the ISC license.
413 * See the LICENSE file in the root directory of this source tree.
414 */
415const Paperclip = createLucideIcon("Paperclip", [
416  [
417    "path",
418    {
419      d: "m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48",
420      key: "1u3ebp"
421    }
422  ]
423]);
424/**
425 * @license lucide-react v0.456.0 - ISC
426 *
427 * This source code is licensed under the ISC license.
428 * See the LICENSE file in the root directory of this source tree.
429 */
430const Settings = createLucideIcon("Settings", [
431  [
432    "path",
433    {
434      d: "M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z",
435      key: "1qme2f"
436    }
437  ],
438  ["circle", { cx: "12", cy: "12", r: "3", key: "1v7zrd" }]
439]);
440/**
441 * @license lucide-react v0.456.0 - ISC
442 *
443 * This source code is licensed under the ISC license.
444 * See the LICENSE file in the root directory of this source tree.
445 */
446const ShoppingBag = createLucideIcon("ShoppingBag", [
447  ["path", { d: "M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4Z", key: "hou9p0" }],
448  ["path", { d: "M3 6h18", key: "d0wm0j" }],
449  ["path", { d: "M16 10a4 4 0 0 1-8 0", key: "1ltviw" }]
450]);
451/**
452 * @license lucide-react v0.456.0 - ISC
453 *
454 * This source code is licensed under the ISC license.
455 * See the LICENSE file in the root directory of this source tree.
456 */
457const Smartphone = createLucideIcon("Smartphone", [
458  ["rect", { width: "14", height: "20", x: "5", y: "2", rx: "2", ry: "2", key: "1yt0o3" }],
459  ["path", { d: "M12 18h.01", key: "mhygvu" }]
460]);
461/**
462 * @license lucide-react v0.456.0 - ISC
463 *
464 * This source code is licensed under the ISC license.
465 * See the LICENSE file in the root directory of this source tree.
466 */
467const Sparkles = createLucideIcon("Sparkles", [
468  [
469    "path",
470    {
471      d: "M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z",
472      key: "4pj2yx"
473    }
474  ],
475  ["path", { d: "M20 3v4", key: "1olli1" }
475],
476  ["path", { d: "M22 5h-4", key: "1gvqau" }],
477  ["path", { d: "M4 17v2", key: "vumght" }],
478  ["path", { d: "M5 18H3", key: "zchphs" }]
479]);
480/**
481 * @license lucide-react v0.456.0 - ISC
482 *
483 * This source code is licensed under the ISC license.
484 * See the LICENSE file in the root directory of this source tree.
485 */
486const SquareTerminal = createLucideIcon("SquareTerminal", [
487  ["path", { d: "m7 11 2-2-2-2", key: "1lz0vl" }],
488  ["path", { d: "M11 13h4", key: "1p7l4v" }],
489  ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2", key: "1m3agn" }]
490]);
491/**
492 * @license lucide-react v0.456.0 - ISC
493 *
494 * This source code is licensed under the ISC license.
495 * See the LICENSE file in the root directory of this source tree.
496 */
497const Square = createLucideIcon("Square", [
498  ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", key: "afitv7" }]
499]);
500/**
501 * @license lucide-react v0.456.0 - ISC
502 *
503 * This source code is licensed under the ISC license.
504 * See the LICENSE file in the root directory of this source tree.
505 */
506const Store = createLucideIcon("Store", [
507  ["path", { d: "m2 7 4.41-4.41A2 2 0 0 1 7.83 2h8.34a2 2 0 0 1 1.42.59L22 7", key: "ztvudi" }],
508  ["path", { d: "M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8", key: "1b2hhj" }],
509  ["path", { d: "M15 22v-4a2 2 0 0 0-2-2h-2a2 2 0 0 0-2 2v4", key: "2ebpfo" }],
510  ["path", { d: "M2 7h20", key: "1fcdvo" }],
511  [
512    "path",
513    {
514      d: "M22 7v3a2 2 0 0 1-2 2a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 16 12a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 12 12a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 8 12a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 4 12a2 2 0 0 1-2-2V7",
515      key: "6c3vgh"
516    }
517  ]
518]);
519/**
520 * @license lucide-react v0.456.0 - ISC
521 *
522 * This source code is licensed under the ISC license.
523 * See the LICENSE file in the root directory of this source tree.
524 */
525const Tablet = createLucideIcon("Tablet", [
526  ["rect", { width: "16", height: "20", x: "4", y: "2", rx: "2", ry: "2", key: "76otgf" }],
527  ["line", { x1: "12", x2: "12.01", y1: "18", y2: "18", key: "1dp563" }]
528]);
529/**
530 * @license lucide-react v0.456.0 - ISC
531 *
532 * This source code is licensed under the ISC license.
533 * See the LICENSE file in the root directory of this source tree.
534 */
535const TrendingUp = createLucideIcon("TrendingUp", [
536  ["polyline", { points: "22 7 13.5 15.5 8.5 10.5 2 17", key: "126l90" }],
537  ["polyline", { points: "16 7 22 7 22 13", key: "kwv8wd" }]
538]);
539/**
540 * @license lucide-react v0.456.0 - ISC
541 *
542 * This source code is licensed under the ISC license.
543 * See the LICENSE file in the root directory of this source tree.
544 */
545const Truck = createLucideIcon("Truck", [
546  ["path", { d: "M14 18V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v11a1 1 0 0 0 1 1h2", key: "wrbu53" }],
547  ["path", { d: "M15 18H9", key: "1lyqi6" }],
548  [
549    "path",
550    {
551      d: "M19 18h2a1 1 0 0 0 1-1v-3.65a1 1 0 0 0-.22-.624l-3.48-4.35A1 1 0 0 0 17.52 8H14",
552      key: "lysw3i"
553    }
554  ],
555  ["circle", { cx: "17", cy: "18", r: "2", key: "332jqn" }],
556  ["circle", { cx: "7", cy: "18", r: "2", key: "19iecd" }]
557]);
558/**
559 * @license lucide-react v0.456.0 - ISC
560 *
561 * This source code is licensed under the ISC license.
562 * See the LICENSE file in the root directory of this source tree.
563 */
564const Type = createLucideIcon("Type", [
565  ["polyline", { points: "4 7 4 4 20 4 20 7", key: "1nosan" }],
566  ["line", { x1: "9", x2: "15", y1: "20", y2: "20", key: "swin9y" }],
567  ["line", { x1: "12", x2: "12", y1: "4", y2: "20", key: "1tx1rr" }]
568]);
569/**
570 * @license lucide-react v0.456.0 - ISC
571 *
572 * This source code is licensed under the ISC license.
573 * See the LICENSE file in the root directory of this source tree.
574 */
575const Users = createLucideIcon("Users", [
576  ["path", { d: "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2", key: "1yyitq" }],
577  ["circle", { cx: "9", cy: "7", r: "4", key: "nufk8" }],
578  ["path", { d: "M22 21v-2a4 4 0 0 0-3-3.87", key: "kshegd" }],
579  ["path", { d: "M16 3.13a4 4 0 0 1 0 7.75", key: "1da9ce" }]
580]);
581async function postSessionMessage(url, body, getToken, signal) {
582  var _a;
583  const deadline = Date.now() + 6 * 6e4;
584  const serialized = JSON.stringify(body);
585  while (!signal.aborted) {
586    const token = await getToken();
587    if (!token) throw new Error("Please sign in again to send your message.");
588    const response = await fetch(url, {
589      method: "POST",
590      headers: {
591        "Content-Type": "application/json",
592        Authorization: `Bearer ${token}`
593      },
594      body: serialized,
595      signal
596    });
597    if (response.status !== 202) return response;
598    await ((_a = response.body) == null ? void 0 : _a.cancel());
599    if (Date.now() >= deadline) throw new Error("Chat history is still saving. Please retry your message in a moment.");
600    await new Promise((resolve, reject) => {
601      const aborted = () => {
602        clearTimeout(timer);
603        reject(new DOMException("Aborted", "AbortError"));
604      };
605      const timer = setTimeout(() => {
606        signal.removeEventListener("abort", aborted);
607        resolve();
608      }, 2e3);
609      signal.addEventListener("abort", aborted, {
610        once: true
611      });
612      if (signal.aborted) aborted();
613    });
614  }
615  throw new DOMException("Aborted", "AbortError");
616}
617function sessionUploadWarning(data) {
618  if (data.status === "failed" || data.status === "truncated") return {
619    reason: "session_upload",
620    message: data.status === "truncated" ? "This conversation reached its history limit. Some recent chat history could not be saved. Your website changes are saved separately." : "Some recent chat history could not be saved. Your website changes are saved separately."
621  };
622  return data.warning === true ? {
623    reason: "session_size"
624  } : null;
625}
626async function resumeChatRestore(options) {
627  var _a;
628  let pending = options.pending;
629  if (pending && (pending.websiteId !== options.websiteId || pending.preMessageCommitHash !== options.preMessageCommitHash)) throw new Error("Finish retrying the pending conversation restore before choosing another point.");
630  let result = pending ? await options.advance(pending) : await options.start();
631  const deadline = options.deadline ?? Date.now() + 6 * 6e4;
632  while ((result == null ? void 0 : result.pending) && result.admissionId && result.sourceSessionId) {
633    pending = {
634      websiteId: options.websiteId,
635      preMessageCommitHash: options.preMessageCommitHash,
636      admissionId: result.admissionId,
637      sourceSessionId: result.sourceSessionId
638    };
639    options.remember(pending);
640    if (Date.now() >= deadline) return result;
641    await (((_a = options.wait) == null ? void 0 : _a.call(options)) ?? new Promise((resolve) => setTimeout(resolve, 2e3)));
642    result = await options.advance(pending);
643  }
644  if (result && !result.pending) options.remember(null);
645  return result;
646}
647const ownerSide = (f) => f.role === "OWNER" || f.role === "ADMIN";
648const SITE_SURFACES = [{
649  surface: "website",
650  label: "Website",
651  hint: "Your live site",
652  icon: Globe,
653  // The site itself is never gated: a viewer who can reach the editor at all
654  // can look at the site. Everything below needs edit access first.
655  allowed: () => true
656}, {
657  surface: "orders",
658  label: "Orders",
659  hint: "Sales and shipping",
660  icon: ShoppingBag,
661  allowed: (f) => f.canEdit && ownerSide(f) && f.ownerCommerceEnabled
662}, {
663  surface: "products",
664  label: "Products",
665  hint: "What you sell",
666  icon: Package,
667  // Editor tier, not owner tier: a catalog is the site's content.
668  allowed: (f) => f.canEdit && f.ownerCommerceEnabled
669}, {
670  surface: "leads",
671  label: "Leads",
672  hint: "People who reached out",
673  icon: Users,
674  allowed: (f) => f.canEdit && ownerSide(f) && f.ownerCommerceEnabled
675}, {
676  surface: "invoices",
677  label: "Invoices",
678  hint: "What you’ve billed",
679  icon: FileText,
680  allowed: (f) => f.canEdit && ownerSide(f) && f.ownerCommerceEnabled
681}, {
682  surface: "analytics",
683  label: "Analytics",
684  hint: "Who visits, and from where",
685  icon: ChartNoAxesColumn,
686  /**
687   * DELIBERATELY OUTSIDE `ownerCommerceEnabled`. Analytics shipped behind a
688   * rollout flag of its own; that flag is gone and it is on for every site,
689   * including ones that sell nothing. "Payments off, analytics on" is a real
690   * combination the switcher has to render rather than hiding wholesale.
691   *
692   * It does NOT control collection — the prod-serve-website workers gate
693   * that independently, so a site not yet collecting renders the honest
694   * pre-collection state rather than a broken panel.
695   */
696  allowed: (f) => f.canEdit && ownerSide(f)
697}];
698const SITE_SURFACE_NAMES = SITE_SURFACES.map((s) => s.surface);
699const SITE_SURFACE_NAME_SET = new Set(SITE_SURFACE_NAMES);
700const isSiteSurfaceName = (view) => SITE_SURFACE_NAME_SET.has(view);
701const editorSiteSurfaces = (facts, hasSiteToken) => SITE_SURFACES.filter((s) => s.surface === "website" || hasSiteToken && s.allowed(facts));
702const canOpenSiteSurface = (view, facts, hasSiteToken) => editorSiteSurfaces(facts, hasSiteToken).some((s) => s.surface === view);
703function isToolPart(part) {
704  return typeof part.type === "string" && part.type.startsWith("tool-");
705}
706function getToolCallId(part) {
707  if (!isToolPart(part)) return void 0;
708  return part.toolCallId;
709}
710function makeToolInputPart(fields) {
711  return {
712    type: `tool-${fields.name}`,
713    toolCallId: fields.toolCallId,
714    state: "input-available",
715    input: fields.input,
716    parentToolUseId: fields.parentToolUseId ?? null
717  };
718}
719function applyToolResult(part, result, agentOutput) {
720  const nextAgentOutput = agentOutput ?? part.agentOutput;
721  if (result.isError) {
722    return {
723      type: part.type,
724      toolCallId: part.toolCallId,
725      input: part.input,
726      state: "output-error",
727      errorText: typeof result.output === "string" ? result.output : JSON.stringify(result.output ?? ""),
728      parentToolUseId: part.parentToolUseId ?? null,
729      agentOutput: nextAgentOutput
730    };
731  }
732  return {
733    type: part.type,
734    toolCallId: part.toolCallId,
735    input: part.input,
736    state: "output-available",
737    output: result.output,
738    parentToolUseId: part.parentToolUseId ?? null,
739    agentOutput: nextAgentOutput
740  };
741}
742const genId = () => crypto.randomUUID();
743function partDtoToChatPart(dto) {
744  if (dto.type === "text") {
745    if (typeof dto.text !== "string") return null;
746    return {
747      type: "text",
748      text: dto.text
749    };
750  }
751  if (dto.type.startsWith("tool-")) {
752    if (!dto.toolCallId) return null;
753    const parentToolUseId = dto.parentToolUseId ?? null;
754    let agentOutput;
755    if (dto.type === "tool-Agent" && dto.agentOutput && typeof dto.agentOutput === "object") {
756      const ao = dto.agentOutput;
757      if (ao.status === "completed" || ao.status === "async_launched" || ao.status === "sub_agent_entered") {
758        agentOutput = {
759          status: ao.status,
760          totalToolUseCount: ao.totalToolUseCount,
761          totalDurationMs: ao.totalDurationMs,
762          totalTokens: ao.totalTokens
763        };
764      }
765    }
766    const base = {
767      type: dto.type,
768      toolCallId: dto.toolCallId,
769      parentToolUseId,
770      agentOutput
771    };
772    if (dto.state === "output-available") {
773      const part2 = {
774        ...base,
775        state: "output-available",
776        input: dto.input ?? {},
777        output: dto.output
778      };
779      return part2;
780    }
781    if (dto.state === "output-error") {
782      const part2 = {
783        ...base,
784        state: "output-error",
785        input: dto.input ?? {},
786        errorText: typeof dto.output === "string" ? dto.output : JSON.stringify(dto.output ?? "")
787      };
788      return part2;
789    }
790    const part = {
791      ...base,
792      state: "input-available",
793      input: dto.input ?? {}
794    };
795    return part;
796  }
797  return null;
798}
799function historyMessageToChatMessage(dto) {
800  const parts = [];
801  for (const partDto of dto.parts ?? []) {
802    const part = partDtoToChatPart(partDto);
803    if (part) parts.push(part);
804  }
805  return {
806    id: dto.id,
807    role: dto.role,
808    parts,
809    // metadata is stored as opaque JSON on the GraphQL side; pass
810    // through as-is so existing consumers (e.g., commitHash badges) see
811    // the same object they did before.
812    metadata: dto.metadata ?? void 0
813  };
814}
815function historyToChatMessages(dtos) {
816  if (!dtos) return [];
817  return dtos.map(historyMessageToChatMessage);
818}
819function normalizeQuestions(raw) {
820  const questions = normalizeQuestionList(raw);
821  if (questions.length === 0) {
822    return [{
823      question: "The assistant asked a question, but it arrived empty. Type your answer below.",
824      header: "",
825      options: [],
826      multiSelect: false
827    }];
828  }
829  return questions;
830}
831function normalizeQuestionList(raw) {
832  if (!Array.isArray(raw)) return [];
833  return raw.filter((q) => !!q && typeof q === "object").map((q, i) => {
834    const header = typeof q.header === "string" ? q.header : "";
835    const question = typeof q.question === "string" && q.question ? q.question : header || `Question ${i + 1}`;
836    const options = Array.isArray(q.options) ? q.options.filter((o) => !!o && typeof o === "object" && typeof o.label === "string").map((o) => ({
837      label: o.label,
838      description: typeof o.description === "string" ? o.description : ""
839    })) : [];
840    return {
841      question,
842      header,
843      options,
844      multiSelect: q.multiSelect === true
845    };
846  });
847}
848const isDev = false;
849let sseSeq = 0;
850const turnStartTimes = /* @__PURE__ */ new Map();
851function sseLog(seq, ...args) {
852}
853function sseWarn(seq, ...args) {
854}
855function createTurnContext() {
856  return {
857    seq: ++sseSeq,
858    assistantMsgId: genId(),
859    assistantCreated: false,
860    hasAccumulatedPartials: false,
861    lastEventId: -1
862  };
863}
864function processShowViewEvent(data, pageMountTimeMs, lastShowViewRef, onShowView) {
865  const emittedAt = typeof data.emittedAt === "number" ? data.emittedAt : 0;
866  if (!emittedAt || emittedAt < pageMountTimeMs) return;
867  const nseq = typeof data.nseq === "number" ? data.nseq : null;
868  const last = lastShowViewRef.current;
869  if (emittedAt === last.emittedAt || nseq !== null && nseq <= last.nseq) {
870    return;
871  }
872  const view = typeof data.view === "string" ? data.view : "";
873  if (!isSiteSurfaceName(view)) return;
874  lastShowViewRef.current = {
875    nseq: nseq ?? last.nseq,
876    emittedAt
877  };
878  const params = data.params;
879  const orderId = typeof (params == null ? void 0 : params.orderId) === "string" ? params.orderId : void 0;
880  const invoiceId = typeof (params == null ? void 0 : params.invoiceId) === "string" ? params.invoiceId : void 0;
881  onShowView == null ? void 0 : onShowView(view, orderId || invoiceId ? {
882    ...orderId ? {
883      orderId
884    } : {},
885    ...invoiceId ? {
886      invoiceId
887    } : {}
888  } : void 0);
889}
890function processEvent(type, data, ctx, deps) {
891  var _a, _b, _c, _d, _e, _f, _g;
892  if (typeof data.seq === "number") {
893    ctx.lastEventId = data.seq;
894  }
895  sseLog(ctx.seq, `event:${type}`, type === "text" || type === "partial" ? {
896    len: (_a = data.text) == null ? void 0 : _a.length
897  } : type === "session" ? {
898    sessionId: data.sessionId
899  } : type === "tool_use" ? {
900    tool: data.name
901  } : type === "commit" ? {
902    hash: (_b = data.hash) == null ? void 0 : _b.slice(0, 8)
903  } : type === "debug" ? data : {});
904  const ensureAssistantMessage = () => {
905    if (ctx.assistantCreated) return;
906    ctx.assistantCreated = true;
907    sseLog(ctx.seq, "creating assistant message", {
908      id: ctx.assistantMsgId
909    });
910    deps.setMessages((prev) => [...prev, {
911      id: ctx.assistantMsgId,
912      role: "assistant",
913      parts: []
914    }]);
915  };
916  const updateAssistantMessage = (mutate, label) => {
917    deps.setMessages((prev) => {
918      const updated = [...prev];
919      for (let i = updated.length - 1; i >= 0; i--) {
920        if (updated[i].id === ctx.assistantMsgId) {
921          updated[i] = mutate(updated[i]);
922          return updated;
923        }
924      }
925      sseWarn(ctx.seq, `updateAssistantMessage: assistant msg ${ctx.assistantMsgId} not found${label ? ` (${label})` : ""} — dropping update`, {
926        messageIds: prev.map((m) => m.id),
927        role: prev.map((m) => m.role)
928      });
929      return prev;
930    });
931  };
932  const appendText = (newText) => {
933    if (!newText) return;
934    ctx.hasAccumulatedPartials = true;
935    updateAssistantMessage((msg) => {
936      var _a2, _b2, _c2;
937      const parts = [...msg.parts];
938      const lastIdx = parts.length - 1;
939      const last = lastIdx >= 0 ? parts[lastIdx] : null;
940      let action;
941      if (last && last.type === "text") {
942        action = "extend";
943        parts[lastIdx] = {
944          ...last,
945          type: "text",
946          text: (last.text || "") + newText
947        };
948      } else {
949        action = "push";
950        parts.push({
951          type: "text",
952          text: newText
953        });
954      }
955      sseLog(ctx.seq, "appendText", {
956        action,
957        newTextHead: newText.slice(0, 16),
958        newTextLen: newText.length,
959        priorPartsCount: msg.parts.length,
960        priorLastType: last == null ? void 0 : last.type,
961        priorLastTextLen: (_a2 = last == null ? void 0 : last.text) == null ? void 0 : _a2.length,
962        resultPartsCount: parts.length,
963        resultLastTextLen: (_c2 = (_b2 = parts[parts.length - 1]) == null ? void 0 : _b2.text) == null ? void 0 : _c2.length
964      });
965      return {
966        ...msg,
967        parts
968      };
969    });
970  };
971  switch (type) {
972    case "session":
973      deps.sessionIdRef.current = data.sessionId;
974      ensureAssistantMessage();
975      break;
976    case "user_message":
977      {
978        const text = data.text;
979        deps.setMessages((prev) => {
980          let lastUserIdx = -1;
981          for (let i = prev.length - 1; i >= 0; i--) {
982            if (prev[i].role === "user") {
983              lastUserIdx = i;
984              break;
985            }
986          }
987          if (lastUserIdx >= 0) {
988            const lastText = (prev[lastUserIdx].parts || []).filter((p) => p.type === "text").map((p) => p.text || "").join("");
989            if (lastText === text) {
990              return lastUserIdx + 1 < prev.length ? prev.slice(0, lastUserIdx + 1) : prev;
991            }
992          }
993          return [...prev, {
994            id: genId(),
995            role: "user",
996            parts: [{
997              type: "text",
998              text
999            }]
1000          }];
1001        });
1002      }
1003      break;
1004    case "partial":
1005      deps.setThinking(null);
1006      ensureAssistantMessage();
1007      appendText(data.text);
1008      break;
1009    case "text":
1010      deps.setThinking(null);
1011      ensureAssistantMessage();
1012      if (!ctx.hasAccumulatedPartials) {
1013        appendText(data.text);
1014      } else {
1015        sseLog(ctx.seq, "dropping duplicate text event (partials already streamed)");
1016      }
1017      break;
1018    case "tool_use":
1019      deps.setThinking(null);
1020      ensureAssistantMessage();
1021      {
1022        const toolCallId = data.id;
1023        const toolName = data.name;
1024        const input = data.input ?? {};
1025        const parentToolUseId = typeof data.parentToolUseId === "string" ? data.parentToolUseId : null;
1026        sseLog(ctx.seq, "tool_use", {
1027          name: toolName,
1028          toolCallId,
1029          inputKeys: Object.keys(input).length,
1030          parent: (parentToolUseId == null ? void 0 : parentToolUseId.slice(-8)) ?? null
1031        });
1032        updateAssistantMessage((msg) => {
1033          const existingIdx = msg.parts.findIndex((p) => isToolPart(p) && getToolCallId(p) === toolCallId);
1034          if (existingIdx !== -1) {
1035            const updated = [...msg.parts];
1036            const existing = updated[existingIdx];
1037            const merged = {
1038              ...existing,
1039              type: `tool-${toolName}`,
1040              toolCallId,
1041              input,
1042              // Keep an already-set parentToolUseId if the new event
1043              // omits one (e.g. an old client or a re-broadcast path
1044              // that lost the field). Otherwise trust the new value.
1045              parentToolUseId: parentToolUseId ?? existing.parentToolUseId ?? null
1046            };
1047            updated[existingIdx] = merged;
1048            return {
1049              ...msg,
1050              parts: updated
1051            };
1052          }
1053          const newPart = makeToolInputPart({
1054            name: toolName,
1055            toolCallId,
1056            input,
1057            parentToolUseId
1058          });
1059          return {
1060            ...msg,
1061            parts: [...msg.parts, newPart]
1062          };
1063        }, `tool_use ${toolName}`);
1064      }
1065      break;
1066    case "tool_result":
1067      {
1068        const targetId = data.toolUseId;
1069        const toolNameFromServer = typeof data.toolName === "string" ? data.toolName : null;
1070        const result = {
1071          output: data.content,
1072          isError: Boolean(data.isError)
1073        };
1074        const agentOutput = data.agentOutput && typeof data.agentOutput === "object" ? data.agentOutput : void 0;
1075        const parentToolUseId = typeof data.parentToolUseId === "string" ? data.parentToolUseId : null;
1076        sseLog(ctx.seq, "tool_result apply", {
1077          toolUseId: targetId,
1078          toolName: toolNameFromServer,
1079          isError: result.isError,
1080          hasAgentOutput: Boolean(agentOutput)
1081        });
1082        updateAssistantMessage((msg) => {
1083          let matched = false;
1084          const newParts = msg.parts.map((p) => {
1085            if (isToolPart(p) && getToolCallId(p) === targetId) {
1086              matched = true;
1087              return applyToolResult(p, result, agentOutput);
1088            }
1089            return p;
1090          });
1091          if (!matched) {
1092            sseWarn(ctx.seq, `orphan tool_result — no matching tool_use for ${targetId}; synthesizing ${toolNameFromServer ?? "Unknown"} row`);
1093            const placeholder = applyToolResult({
1094              type: `tool-${toolNameFromServer ?? "Unknown"}`,
1095              toolCallId: targetId,
1096              input: {},
1097              parentToolUseId
1098            }, result, agentOutput);
1099            newParts.push(placeholder);
1100          }
1101          return {
1102            ...msg,
1103            parts: newParts
1104          };
1105        }, `tool_result ${targetId}`);
1106      }
1107      break;
1108    case "tool_discard":
1109      {
1110        const ids = Array.isArray(data.toolUseIds) ? data.toolUseIds : [];
1111        if (ids.length === 0) break;
1112        const discard = new Set(ids);
1113        sseLog(ctx.seq, "tool_discard", {
1114          count: ids.length
1115        });
1116        updateAssistantMessage((msg) => ({
1117          ...msg,
1118          parts: msg.parts.filter((p) => !(isToolPart(p) && discard.has(getToolCallId(p) ?? "")))
1119        }));
1120      }
1121      break;
1122    case "commit":
1123      updateAssistantMessage((msg) => ({
1124        ...msg,
1125        metadata: {
1126          ...msg.metadata || {},
1127          commitHash: data.hash,
1128          commitMessage: data.message,
1129          pushed: data.pushed
1130        }
1131      }));
1132      break;
1133    case "approval_request":
1134      deps.setPendingApproval({
1135        approvalId: data.approvalId,
1136        toolName: data.toolName,
1137        description: data.description
1138      });
1139      break;
1140    case "ask_user_question":
1141      deps.setPendingQuestion({
1142        interactionId: data.interactionId,
1143        questions: normalizeQuestions(data.questions)
1144      });
1145      break;
1146    case "session_upload_status": {
1147      const warning = sessionUploadWarning(data);
1148      if (warning && (!data.emittedAt || Number(data.emittedAt) >= deps.pageMountTimeMs)) (_c = deps.onSessionWarning) == null ? void 0 : _c.call(deps, warning);
1149      break;
1150    }
1151    case "session_warning":
1152      sseLog(ctx.seq, "session_warning", data);
1153      {
1154        const emittedAt = typeof data.emittedAt === "number" ? data.emittedAt : 0;
1155        if (emittedAt && emittedAt < deps.pageMountTimeMs) {
1156          break;
1157        }
1158        (_d = deps.onSessionWarning) == null ? void 0 : _d.call(deps, {
1159          bytes: typeof data.bytes === "number" ? data.bytes : void 0,
1160          reason: typeof data.reason === "string" ? data.reason : void 0,
1161          message: typeof data.message === "string" ? data.message : void 0
1162        });
1163      }
1164      break;
1165    case "show_view":
1166      processShowViewEvent(data, deps.pageMountTimeMs, deps.lastShowViewRef, deps.onShowView);
1167      break;
1168    case "chat_reset":
1169      {
1170        const resetAt = typeof data.resetAt === "number" ? data.resetAt : 0;
1171        if (resetAt < deps.pageMountTimeMs || resetAt <= deps.lastResetAtRef.current) {
1172          sseLog(ctx.seq, "chat_reset ignored (stale replay)", {
1173            eventResetAt: resetAt,
1174            pageMount: deps.pageMountTimeMs,
1175            currentResetAt: deps.lastResetAtRef.current
1176          });
1177          break;
1178        }
1179        sseLog(ctx.seq, "chat_reset received, clearing messages");
1180        deps.setMessages([]);
1181        deps.setPendingApproval(null);
1182        deps.setPendingQuestion(null);
1183        deps.setThinking(null);
1184        deps.setMaxTurnsHit(false);
1185        deps.setHistoryError(null);
1186        deps.sessionIdRef.current = null;
1187        deps.lastResetAtRef.current = resetAt;
1188        (_e = deps.onChatReset) == null ? void 0 : _e.call(deps);
1189      }
1190      break;
1191    case "compaction": {
1192      const preTokens = typeof data.preTokens === "number" ? data.preTokens : null;
1193      const tokenSuffix = preTokens ? ` (${(preTokens / 1e3).toFixed(0)}K tokens condensed)` : "";
1194      const marker = {
1195        id: `compaction-${Date.now()}`,
1196        role: "assistant",
1197        parts: [{
1198          type: "text",
1199          text: `— Conversation summarized to manage context length${tokenSuffix} —`
1200        }]
1201      };
1202      deps.setMessages((prev) => {
1203        let lastUserIdx = -1;
1204        for (let i = prev.length - 1; i >= 0; i--) {
1205          if (prev[i].role === "user") {
1206            lastUserIdx = i;
1207            break;
1208          }
1209        }
1210        const tail = lastUserIdx >= 0 ? prev.slice(lastUserIdx) : [];
1211        return [marker, ...tail];
1212      });
1213      break;
1214    }
1215    case "result":
1216      deps.setThinking(null);
1217      if (data.subtype === "error_max_turns") {
1218        sseLog(ctx.seq, "maxTurns hit — surfacing Continue affordance");
1219        deps.setMaxTurnsHit(true);
1220      }
1221      break;
1222    case "thinking_start": {
1223      ensureAssistantMessage();
1224      const now = Date.now();
1225      deps.setThinking({
1226        active: true,
1227        startedAt: now,
1228        chars: 0,
1229        lastDeltaAt: now
1230      });
1231      updateAssistantMessage((msg) => ({
1232        ...msg,
1233        parts: [...msg.parts, {
1234          type: "thinking",
1235          text: "",
1236          // Mark as in-progress via a dummy duration of -1 so the
1237          // UI can distinguish "still thinking" (animated) from
1238          // "done" (static duration badge).
1239          thinkingDurationMs: -1,
1240          // Client-only: stamp start time so thinking_stop can
1241          // compute the elapsed duration without a second round
1242          // trip through the floating-indicator state.
1243          _startedAt: now
1244        }]
1245      }), "thinking_start");
1246      break;
1247    }
1248    case "thinking_delta": {
1249      const chars = typeof data.chars === "number" ? data.chars : 0;
1250      const text = typeof data.text === "string" ? data.text : "";
1251      const now = Date.now();
1252      deps.setThinking((prev) => prev ? {
1253        ...prev,
1254        chars: prev.chars + chars,
1255        lastDeltaAt: now
1256      } : null);
1257      if (text) {
1258        updateAssistantMessage((msg) => {
1259          const parts = [...msg.parts];
1260          const lastIdx = parts.length - 1;
1261          const last = lastIdx >= 0 ? parts[lastIdx] : null;
1262          if (last && last.type === "thinking") {
1263            parts[lastIdx] = {
1264              ...last,
1265              type: "thinking",
1266              text: (last.text || "") + text
1267            };
1268          } else {
1269            parts.push({
1270              type: "thinking",
1271              text,
1272              thinkingDurationMs: -1
1273            });
1274          }
1275          return {
1276            ...msg,
1277            parts
1278          };
1279        }, "thinking_delta");
1280      }
1281      break;
1282    }
1283    case "thinking_stop": {
1284      const now = Date.now();
1285      updateAssistantMessage((msg) => {
1286        const parts = [...msg.parts];
1287        const lastIdx = parts.length - 1;
1288        const last = lastIdx >= 0 ? parts[lastIdx] : null;
1289        if (last && last.type === "thinking") {
1290          const durationMs = last._startedAt ? now - last._startedAt : 0;
1291          parts[lastIdx] = {
1292            ...last,
1293            thinkingDurationMs: durationMs
1294          };
1295        }
1296        return {
1297          ...msg,
1298          parts
1299        };
1300      }, "thinking_stop");
1301      deps.setThinking(null);
1302      break;
1303    }
1304    case "error":
1305      deps.setThinking(null);
1306      if (data.type === "session_expired") {
1307        (_f = deps.onSessionExpired) == null ? void 0 : _f.call(deps, typeof data.message === "string" ? data.message : "");
1308      } else {
1309        (_g = deps.onError) == null ? void 0 : _g.call(deps, Object.assign(new Error(data.message || "Agent error"), {
1310          type: typeof data.type === "string" ? data.type : void 0
1311        }));
1312      }
1313      break;
1314  }
1315}
1316async function consumeSseStream(body, ctx, onEvent, signal) {
1317  const reader = body.getReader();
1318  const decoder = new TextDecoder();
1319  const parseFrame = (frame) => {
1320    let eventType = "";
1321    const dataLines = [];
1322    for (const line of frame.split("\n")) {
1323      if (line.startsWith("event: ")) {
1324        eventType = line.slice(7).trim();
1325      } else if (line.startsWith("data: ")) {
1326        dataLines.push(line.slice(6));
1327      }
1328    }
1329    if (dataLines.length === 0) return;
1330    try {
1331      const parsed = JSON.parse(dataLines.join("\n"));
1332      onEvent(eventType, parsed);
1333    } catch (e) {
1334      sseWarn(ctx.seq, "Failed to parse event data:", e);
1335    }
1336  };
1337  let buffer = "";
1338  try {
1339    while (true) {
1340      if (signal == null ? void 0 : signal.aborted) break;
1341      const {
1342        done,
1343        value
1344      } = await reader.read();
1345      if (done) break;
1346      buffer += decoder.decode(value, {
1347        stream: true
1348      });
1349      let frameEnd = buffer.indexOf("\n\n");
1350      while (frameEnd !== -1) {
1351        const frame = buffer.slice(0, frameEnd);
1352        buffer = buffer.slice(frameEnd + 2);
1353        parseFrame(frame);
1354        frameEnd = buffer.indexOf("\n\n");
1355      }
1356    }
1357    buffer += decoder.decode();
1358    if (buffer.trim()) parseFrame(buffer);
1359  } finally {
1360    try {
1361      reader.releaseLock();
1362    } catch {
1363    }
1364  }
1365}
1366const RETRYABLE_AGENT_ERROR_TYPES = /* @__PURE__ */ new Set(["api_error", "stream_parse_error"]);
1367const AUTH_REQUIRED_MESSAGE = "Authentication required. Please refresh the page.";
1368function useAgentSSE(options) {
1369  const {
1370    publicId,
1371    websiteId,
1372    getToken,
1373    onFinish,
1374    onError,
1375    onSessionWarning,
1376    onSessionExpired,
1377    onChatReset,
1378    onNavigate,
1379    onShowView
1380  } = options;
1381  const [messages, setMessages] = reactExports.useState([]);
1382  const [status, setStatusRaw] = reactExports.useState("idle");
1383  const MESSAGE_FLUSH_MS = 80;
1384  const pendingMessageUpdatesRef = reactExports.useRef([]);
1385  const messageFlushTimerRef = reactExports.useRef(null);
1386  const flushMessagesNow = reactExports.useCallback(() => {
1387    if (messageFlushTimerRef.current !== null) {
1388      clearTimeout(messageFlushTimerRef.current);
1389      messageFlushTimerRef.current = null;
1390    }
1391    const updates = pendingMessageUpdatesRef.current;
1392    if (updates.length === 0) return;
1393    pendingMessageUpdatesRef.current = [];
1394    setMessages((prev) => updates.reduce((acc, u) => u(acc), prev));
1395  }, []);
1396  const queueMessagesUpdate = reactExports.useCallback((update) => {
1397    pendingMessageUpdatesRef.current.push(typeof update === "function" ? update : () => update);
1398    if (messageFlushTimerRef.current === null) {
1399      messageFlushTimerRef.current = setTimeout(() => {
1400        messageFlushTimerRef.current = null;
1401        flushMessagesNow();
1402      }, MESSAGE_FLUSH_MS);
1403    }
1404  }, [flushMessagesNow]);
1405  const setStatus = reactExports.useCallback((s) => {
1406    if (s === "idle" || s === "error") flushMessagesNow();
1407    setStatusRaw(s);
1408  }, [flushMessagesNow]);
1409  const setMessagesOrdered = reactExports.useCallback((update) => {
1410    queueMessagesUpdate(update);
1411    flushMessagesNow();
1412  }, [queueMessagesUpdate, flushMessagesNow]);
1413  reactExports.useEffect(() => {
1414    return () => {
1415      if (messageFlushTimerRef.current !== null) {
1416        clearTimeout(messageFlushTimerRef.current);
1417        messageFlushTimerRef.current = null;
1418      }
1419      pendingMessageUpdatesRef.current = [];
1420    };
1421  }, []);
1422  const prevStatusRef = reactExports.useRef(status);
1423  reactExports.useEffect(() => {
1424    const prev = prevStatusRef.current;
1425    prevStatusRef.current = status;
1426    const turnEnded = (prev === "streaming" || prev === "connecting") && status !== "streaming" && status !== "connecting";
1427    if (!turnEnded) return;
1428    setMessagesOrdered((prevMsgs) => {
1429      let lastAssistantIdx = -1;
1430      for (let i = prevMsgs.length - 1; i >= 0; i--) {
1431        if (prevMsgs[i].role === "assistant") {
1432          lastAssistantIdx = i;
1433          break;
1434        }
1435      }
1436      if (lastAssistantIdx === -1) return prevMsgs;
1437      const m = prevMsgs[lastAssistantIdx];
1438      let msgChanged = false;
1439      const parts = m.parts.map((p) => {
1440        if (isToolPart(p) && p.type !== "tool-Agent" && !p.parentToolUseId && (p.state === "input-available" || p.state === "input-streaming")) {
1441          msgChanged = true;
1442          return {
1443            ...p,
1444            state: "output-available",
1445            output: p.output ?? ""
1446          };
1447        }
1448        return p;
1449      });
1450      if (!msgChanged) return prevMsgs;
1451      const next = [...prevMsgs];
1452      next[lastAssistantIdx] = {
1453        ...m,
1454        parts
1455      };
1456      return next;
1457    });
1458  }, [status]);
1459  const [thinking, setThinking] = reactExports.useState(null);
1460  const [pendingApproval, setPendingApproval] = reactExports.useState(null);
1461  const [maxTurnsHit, setMaxTurnsHit] = reactExports.useState(false);
1462  const [approvalSubmitting, setApprovalSubmitting] = reactExports.useState(null);
1463  const [pendingQuestion, setPendingQuestion] = reactExports.useState(null);
1464  const [historyLoading, setHistoryLoading] = reactExports.useState(true);
1465  const [historyError, setHistoryError] = reactExports.useState(null);
1466  const [historyLoadAttempt, setHistoryLoadAttempt] = reactExports.useState(0);
1467  const posthogRef = reactExports.useRef(usePostHog());
1468  const abortRef = reactExports.useRef(null);
1469  const currentTurnIdRef = reactExports.useRef(null);
1470  const sessionIdRef = reactExports.useRef(null);
1471  const pendingAdmissionRef = reactExports.useRef(null);
1472  const pendingResetIdRef = reactExports.useRef(null);
1473  const lastEventIdRef = reactExports.useRef(-1);
1474  const lastResetAtRef = reactExports.useRef(0);
1475  const pageMountTimeRef = reactExports.useRef(Date.now());
1476  const historyAppliedRef = reactExports.useRef(false);
1477  const pendingResumeTurnIdRef = reactExports.useRef(null);
1478  const previewDomain = "landingsite.dev";
1479  const baseUrl = `https://${publicId}.${previewDomain}`;
1480  const gatewayUrl = `${baseUrl}/__agent/chat`;
1481  const resumeStreamUrl = `${baseUrl}/__agent/resume-stream`;
1482  const activeTurnUrl = `${baseUrl}/__agent/active-turn`;
1483  const notificationStreamUrl = `${baseUrl}/__agent/events`;
1484  const notificationLastEventIdRef = reactExports.useRef(-1);
1485  const lastShowViewRef = reactExports.useRef({
1486    nseq: -1,
1487    emittedAt: 0
1488  });
1489  const loadHistoryFromSandbox = reactExports.useCallback(async () => {
1490    const token = await getToken();
1491    if (!token) return null;
1492    try {
1493      const res = await fetch(`${baseUrl}/__agent/history`, {
1494        headers: {
1495          Authorization: `Bearer ${token}`
1496        }
1497      });
1498      if (!res.ok) {
1499        console.warn("[useAgentSSE] /__agent/history non-OK:", res.status);
1500        return null;
1501      }
1502      const body = await res.json();
1503      return {
1504        messages: body.messages ?? [],
1505        sessionId: body.sessionId ?? null,
1506        source: body.source ?? "unknown"
1507      };
1508    } catch (err) {
1509      console.warn("[useAgentSSE] /__agent/history failed:", err);
1510      return null;
1511    }
1512  }, [baseUrl, getToken]);
1513  const openResumeStream = reactExports.useCallback(async (turnId, startingLastEventId = -1) => {
1514    var _a;
1515    if (currentTurnIdRef.current === turnId) {
1516      return;
1517    }
1518    (_a = abortRef.current) == null ? void 0 : _a.abort();
1519    currentTurnIdRef.current = turnId;
1520    setStatus("connecting");
1521    let token = null;
1522    try {
1523      token = await getToken();
1524    } catch (err) {
1525      sseWarn(0, "openResumeStream getToken threw:", err.message);
1526    }
1527    if (!token) {
1528      onError == null ? void 0 : onError(new Error("No auth token available"));
1529      setStatus("idle");
1530      currentTurnIdRef.current = null;
1531      return;
1532    }
1533    const ctx = createTurnContext();
1534    turnStartTimes.set(ctx.seq, Date.now());
1535    ctx.lastEventId = startingLastEventId;
1536    sseLog(ctx.seq, "openResumeStream", {
1537      turnId,
1538      startingLastEventId
1539    });
1540    const controller = new AbortController();
1541    abortRef.current = controller;
1542    setStatus("streaming");
1543    const MAX_ATTEMPTS = 6;
1544    const BACKOFFS_MS = [500, 1e3, 2e3, 4e3, 8e3, 15e3];
1545    let attempt = 0;
1546    while (attempt < MAX_ATTEMPTS) {
1547      if (controller.signal.aborted) break;
1548      try {
1549        const url = `${resumeStreamUrl}?turnId=${encodeURIComponent(turnId)}&lastEventId=${encodeURIComponent(ctx.lastEventId)}`;
1550        sseLog(ctx.seq, `resume connect attempt=${attempt} lastEventId=${ctx.lastEventId}`);
1551        const response = await fetch(url, {
1552          headers: {
1553            Authorization: `Bearer ${token}`
1554          },
1555          signal: controller.signal
1556        });
1557        if (response.status === 409) {
1558          sseLog(ctx.seq, "resume 409: turn ended or stale");
1559          break;
1560        }
1561        if (!response.ok) {
1562          throw new Error(`Resume request failed (${response.status})`);
1563        }
1564        if (!response.body) throw new Error("No response body");
1565        attempt = 0;
1566        await consumeSseStream(response.body, ctx, (type, data) => {
1567          sseLog(ctx.seq, `resume recv type=${type} turnId=${turnId} visibility=${typeof document !== "undefined" ? document.visibilityState : "n/a"}`);
1568          processEvent(type, data, ctx, {
1569            setMessages: queueMessagesUpdate,
1570            setPendingApproval,
1571            setPendingQuestion,
1572            setThinking,
1573            setMaxTurnsHit,
1574            setHistoryError,
1575            sessionIdRef,
1576            pageMountTimeMs: pageMountTimeRef.current,
1577            lastResetAtRef,
1578            onError,
1579            onSessionWarning,
1580            onSessionExpired,
1581            onChatReset,
1582            onShowView,
1583            lastShowViewRef
1584          });
1585        }, controller.signal);
1586        lastEventIdRef.current = ctx.lastEventId;
1587        sseLog(ctx.seq, "resume stream end (clean)");
1588        break;
1589      } catch (err) {
1590        if (err.name === "AbortError") {
1591          sseLog(ctx.seq, "resume aborted");
1592          break;
1593        }
1594        attempt++;
1595        if (attempt >= MAX_ATTEMPTS) {
1596          sseWarn(ctx.seq, "resume giving up after max attempts");
1597          setStatus("error");
1598          onError == null ? void 0 : onError(new Error("Lost connection to the agent. Refresh to reconnect."));
1599          return;
1600        }
1601        const delay = BACKOFFS_MS[Math.min(attempt - 1, BACKOFFS_MS.length - 1)];
1602        const jittered = delay + Math.floor(Math.random() * 250);
1603        sseWarn(ctx.seq, `resume error, retrying in ${jittered}ms (attempt ${attempt})`, err.message);
1604        await new Promise((resolve) => {
1605          const timer = setTimeout(resolve, jittered);
1606          const onAbort = () => {
1607            clearTimeout(timer);
1608            resolve();
1609          };
1610          controller.signal.addEventListener("abort", onAbort, {
1611            once: true
1612          });
1613        });
1614      }
1615    }
1616    if (!controller.signal.aborted) {
1617      setStatus("idle");
1618    }
1619    abortRef.current = null;
1620    if (currentTurnIdRef.current === turnId) {
1621      currentTurnIdRef.current = null;
1622    }
1623  }, [resumeStreamUrl, getToken, onError, onSessionWarning, onSessionExpired, onChatReset, onNavigate, onShowView]);
1624  const openNotificationStream = reactExports.useCallback(async (signal) => {
1625    var _a;
1626    const BACKOFFS_MS = [500, 1e3, 2e3, 4e3, 8e3, 15e3];
1627    const IDLE_POLL_MS = 3e4;
1628    let attempt = 0;
1629    while (!signal.aborted) {
1630      try {
1631        const token = await getToken();
1632        if (!token) {
1633          attempt++;
1634          const delay = BACKOFFS_MS[Math.min(attempt - 1, BACKOFFS_MS.length - 1)];
1635          const jittered = delay + Math.floor(Math.random() * 250);
1636          await new Promise((resolve) => {
1637            const timer = setTimeout(resolve, jittered);
1638            const onAbort = () => {
1639              clearTimeout(timer);
1640              resolve();
1641            };
1642            signal.addEventListener("abort", onAbort, {
1643              once: true
1644            });
1645          });
1646          continue;
1647        }
1648        const url = `${notificationStreamUrl}?lastEventId=${encodeURIComponent(notificationLastEventIdRef.current)}`;
1649        if (isDev) ;
1650        const response = await fetch(url, {
1651          headers: {
1652            Authorization: `Bearer ${token}`
1653          },
1654          signal
1655        });
1656        if (!response.ok) {
1657          if (response.status === 401 || response.status === 403) {
1658            console.warn("[useAgentSSE] Notification stream auth failed");
1659            return;
1660          }
1661          throw new Error(`Notification stream failed (${response.status})`);
1662        }
1663        if (response.status === 204 || response.headers.get("X-Sandbox-State") === "idle") {
1664          try {
1665            await ((_a = response.body) == null ? void 0 : _a.cancel());
1666          } catch {
1667          }
1668          attempt = 0;
1669          const jittered = IDLE_POLL_MS + Math.floor(Math.random() * 1e3);
1670          if (isDev) ;
1671          await new Promise((resolve) => {
1672            const timer = setTimeout(resolve, jittered);
1673            const onAbort = () => {
1674              clearTimeout(timer);
1675              resolve();
1676            };
1677            signal.addEventListener("abort", onAbort, {
1678              once: true
1679            });
1680          });
1681          continue;
1682        }
1683        if (!response.body) throw new Error("No response body");
1684        attempt = 0;
1685        const reader = response.body.getReader();
1686        const decoder = new TextDecoder();
1687        let buffer = "";
1688        const parseFrame = (frame) => {
1689          let eventType = "";
1690          const dataLines = [];
1691          for (const line of frame.split("\n")) {
1692            if (line.startsWith("event: ")) {
1693              eventType = line.slice(7).trim();
1694            } else if (line.startsWith("data: ")) {
1695              dataLines.push(line.slice(6));
1696            }
1697          }
1698          if (dataLines.length === 0) return;
1699          try {
1700            const parsed = JSON.parse(dataLines.join("\n"));
1701            console.log(`[useAgentSSE] notification recv type=${eventType} nseq=${(parsed == null ? void 0 : parsed.nseq) ?? "?"} visibility=${typeof document !== "undefined" ? document.visibilityState : "n/a"}`);
1702            handleNotificationEvent(eventType, parsed);
1703          } catch (e) {
1704            console.warn("[useAgentSSE] notification parse error:", e);
1705          }
1706        };
1707        while (!signal.aborted) {
1708          const {
1709            done,
1710            value
1711          } = await reader.read();
1712          if (done) break;
1713          console.log(`[useAgentSSE] notification chunk bytes=${(value == null ? void 0 : value.byteLength) ?? 0} visibility=${typeof document !== "undefined" ? document.visibilityState : "n/a"}`);
1714          buffer += decoder.decode(value, {
1715            stream: true
1716          });
1717          let frameEnd = buffer.indexOf("\n\n");
1718          while (frameEnd !== -1) {
1719            const frame = buffer.slice(0, frameEnd);
1720            buffer = buffer.slice(frameEnd + 2);
1721            parseFrame(frame);
1722            frameEnd = buffer.indexOf("\n\n");
1723          }
1724        }
1725        if (!signal.aborted) {
1726          if (isDev) ;
1727          continue;
1728        }
1729        return;
1730      } catch (err) {
1731        if (signal.aborted || err.name === "AbortError") {
1732          return;
1733        }
1734        attempt++;
1735        const delay = BACKOFFS_MS[Math.min(attempt - 1, BACKOFFS_MS.length - 1)];
1736        const jittered = delay + Math.floor(Math.random() * 250);
1737        await new Promise((resolve) => {
1738          const timer = setTimeout(resolve, jittered);
1739          const onAbort = () => {
1740            clearTimeout(timer);
1741            resolve();
1742          };
1743          signal.addEventListener("abort", onAbort, {
1744            once: true
1745          });
1746        });
1747      }
1748    }
1749  }, [notificationStreamUrl, getToken]);
1750  function handleNotificationEvent(type, data) {
1751    if (typeof data.nseq === "number") {
1752      notificationLastEventIdRef.current = data.nseq;
1753    }
1754    switch (type) {
1755      case "chat_reset":
1756        {
1757          const resetAt = typeof data.resetAt === "number" ? data.resetAt : 0;
1758          if (resetAt < pageMountTimeRef.current) {
1759            break;
1760          }
1761          if (resetAt <= lastResetAtRef.current) {
1762            break;
1763          }
1764          setMessagesOrdered([]);
1765          setPendingApproval(null);
1766          setPendingQuestion(null);
1767          setThinking(null);
1768          setMaxTurnsHit(false);
1769          setHistoryError(null);
1770          sessionIdRef.current = null;
1771          lastResetAtRef.current = resetAt;
1772          onChatReset == null ? void 0 : onChatReset();
1773        }
1774        break;
1775      case "turn_started":
1776        {
1777          const turnId = data.turnId;
1778          if (!turnId) break;
1779          const startedAt = data.startedAt;
1780          if (startedAt && new Date(startedAt).getTime() < pageMountTimeRef.current) {
1781            break;
1782          }
1783          if (abortRef.current !== null && currentTurnIdRef.current === null) {
1784            break;
1785          }
1786          if (!historyAppliedRef.current) {
1787            pendingResumeTurnIdRef.current = turnId;
1788            break;
1789          }
1790          void openResumeStream(turnId, -1);
1791        }
1792        break;
1793      case "turn_ended":
1794        break;
1795      case "session_upload_status": {
1796        const warning = sessionUploadWarning(data);
1797        if (warning && (!data.emittedAt || Number(data.emittedAt) >= pageMountTimeRef.current)) onSessionWarning == null ? void 0 : onSessionWarning(warning);
1798        break;
1799      }
1800      case "session_warning":
1801        {
1802          const emittedAt = typeof data.emittedAt === "number" ? data.emittedAt : 0;
1803          if (emittedAt && emittedAt < pageMountTimeRef.current) {
1804            break;
1805          }
1806          onSessionWarning == null ? void 0 : onSessionWarning({
1807            bytes: typeof data.bytes === "number" ? data.bytes : void 0,
1808            reason: typeof data.reason === "string" ? data.reason : void 0,
1809            message: typeof data.message === "string" ? data.message : void 0
1810          });
1811        }
1812        break;
1813      case "navigate":
1814        {
1815          const emittedAt = typeof data.emittedAt === "number" ? data.emittedAt : 0;
1816          if (!emittedAt || emittedAt < pageMountTimeRef.current) {
1817            break;
1818          }
1819          const target = typeof data.target === "string" ? data.target : void 0;
1820          if (target && target.length > 0 && target.startsWith("/") && !target.startsWith("//")) {
1821            onNavigate == null ? void 0 : onNavigate(target);
1822          } else {
1823            console.warn("[useAgentSSE] navigate event dropped — unsafe or missing target", {
1824              target
1825            });
1826          }
1827        }
1828        break;
1829      case "show_view":
1830        processShowViewEvent(data, pageMountTimeRef.current, lastShowViewRef, onShowView);
1831        break;
1832      case "error":
1833        console.warn("[useAgentSSE] notification stream error event:", data);
1834        if (data.type === "subscriber_too_late") {
1835          notificationLastEventIdRef.current = -1;
1836        } else if (data.type === "session_expired") {
1837          onSessionExpired == null ? void 0 : onSessionExpired(typeof data.message === "string" ? data.message : "");
1838        }
1839        break;
1840    }
1841  }
1842  reactExports.useEffect(() => {
1843    let cancelled = false;
1844    if (!websiteId || !publicId) return;
1845    async function loadAndResume() {
1846      var _a;
1847      setHistoryLoading(true);
1848      setHistoryError(null);
1849      historyAppliedRef.current = false;
1850      pendingResumeTurnIdRef.current = null;
1851      const token = await getToken();
1852      const activeTurnP = token ? fetch(activeTurnUrl, {
1853        headers: {
1854          Authorization: `Bearer ${token}`
1855        }
1856      }).then((r) => r.ok ? r.json() : null).catch(() => null) : Promise.resolve(null);
1857      const BACKOFFS_MS = [1e3, 1e3, 1e3, 1e3, 1e3, 1e3, 1e3, 1e3, 1e3, 1e3, 2e3, 4e3, 8e3];
1858      let historyData = null;
1859      const DEFINITIVE_HISTORY_SOURCES = /* @__PURE__ */ new Set(["sandbox-disk", "sandbox-restored", "sandbox-empty", "history-expired"]);
1860      const historyStartedAt = Date.now();
1861      let historyAttempts = 0;
1862      let lastHistorySource = "fetch-failed";
1863      for (let attempt = 0; attempt <= BACKOFFS_MS.length; attempt++) {
1864        if (cancelled) return;
1865        const r = await loadHistoryFromSandbox();
1866        if (cancelled) return;
1867        historyAttempts = attempt + 1;
1868        lastHistorySource = (r == null ? void 0 : r.source) ?? "fetch-failed";
1869        if (r && DEFINITIVE_HISTORY_SOURCES.has(r.source)) {
1870          historyData = r;
1871          break;
1872        }
1873        if (attempt === BACKOFFS_MS.length) break;
1874        console.log("[useAgentSSE] history transient, retrying", {
1875          attempt: attempt + 1,
1876          source: (r == null ? void 0 : r.source) ?? "fetch-failed",
1877          delayMs: BACKOFFS_MS[attempt]
1878        });
1879        await new Promise((resolve) => {
1880          setTimeout(resolve, BACKOFFS_MS[attempt]);
1881        });
1882      }
1883      if (cancelled) return;
1884      try {
1885        (_a = posthogRef.current) == null ? void 0 : _a.capture("preview_boot", {
1886          step: historyData ? "chat_history_loaded" : "chat_history_failed",
1887          websiteId,
1888          publicId,
1889          durationMs: Date.now() - historyStartedAt,
1890          attempts: historyAttempts,
1891          source: lastHistorySource,
1892          sinceNavigationMs: Math.round(performance.now())
1893        });
1894      } catch {
1895      }
1896      const rawHistory = (historyData == null ? void 0 : historyData.messages) ?? null;
1897      const historySource = (historyData == null ? void 0 : historyData.source) ?? "fetch-failed";
1898      const historySessionId = (historyData == null ? void 0 : historyData.sessionId) ?? null;
1899      if (!historyData) {
1900        console.warn("[useAgentSSE] sandbox /__agent/history failed after retries");
1901      }
1902      console.log("[useAgentSSE] history loaded", {
1903        source: historySource,
1904        sessionId: historySessionId,
1905        count: (rawHistory == null ? void 0 : rawHistory.length) ?? 0
1906      });
1907      if (rawHistory && rawHistory.length > 0) {
1908        const history = historyToChatMessages(rawHistory);
1909        console.log("[useAgentSSE] history adapted", {
1910          count: history.length
1911        });
1912        if (history.length > 0) {
1913          setMessagesOrdered((prev) => prev.length > 0 ? prev : history);
1914          if (historySessionId) {
1915            sessionIdRef.current = historySessionId;
1916          }
1917        }
1918      }
1919      if (!historyData) {
1920        setHistoryError("Couldn't load chat history. The preview server may be starting up.");
1921      }
1922      setHistoryLoading(false);
1923      historyAppliedRef.current = true;
1924      const activeTurn = await activeTurnP;
1925      if (cancelled) return;
1926      if (activeTurn && typeof activeTurn.lastResetAt === "number") {
1927        lastResetAtRef.current = activeTurn.lastResetAt;
1928      }
1929      if (activeTurn && activeTurn.active && activeTurn.turnId) {
1930        void openResumeStream(activeTurn.turnId, -1);
1931      }
1932      if (pendingResumeTurnIdRef.current) {
1933        const pendingTurnId = pendingResumeTurnIdRef.current;
1934        pendingResumeTurnIdRef.current = null;
1935        void openResumeStream(pendingTurnId, -1);
1936      }
1937    }
1938    void loadAndResume();
1939    return () => {
1940      cancelled = true;
1941    };
1942  }, [websiteId, publicId, historyLoadAttempt]);
1943  reactExports.useEffect(() => {
1944    if (!websiteId || !publicId) return;
1945    const controller = new AbortController();
1946    void openNotificationStream(controller.signal);
1947    const onVisibility = () => {
1948      console.log(`[useAgentSSE] visibility → ${document.visibilityState} at ${(/* @__PURE__ */ new Date()).toISOString()}`);
1949    };
1950    document.addEventListener("visibilitychange", onVisibility);
1951    return () => {
1952      controller.abort();
1953      document.removeEventListener("visibilitychange", onVisibility);
1954    };
1955  }, [websiteId, publicId]);
1956  const sendMessage = reactExports.useCallback(async (message) => {
1957    var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
1958    const ctx = createTurnContext();
1959    turnStartTimes.set(ctx.seq, Date.now());
1960    sseLog(ctx.seq, "sendMessage", {
1961      messageId: message.id
1962    });
1963    setMaxTurnsHit(false);
1964    setMessagesOrdered((prev) => [...prev, message]);
1965    setStatus("connecting");
1966    let token = null;
1967    try {
1968      token = await getToken();
1969    } catch (err) {
1970      sseWarn(ctx.seq, "getToken threw:", err.message);
1971    }
1972    if (!token) {
1973      onError == null ? void 0 : onError(new Error("No auth token available"));
1974      setStatus("idle");
1975      return "failed";
1976    }
1977    (_a = abortRef.current) == null ? void 0 : _a.abort();
1978    const controller = new AbortController();
1979    abortRef.current = controller;
1980    sseLog(ctx.seq, "connecting");
1981    let streamingBegan = false;
1982    try {
1983      const messageText = ((_b = message.parts) == null ? void 0 : _b.filter((p) => p.type === "text").map((p) => p.text).join("\n")) || "";
1984      const fileParts = ((_c = message.parts) == null ? void 0 : _c.flatMap((p) => {
1985        if (p.type !== "file") return [];
1986        const url = p.url;
1987        const mediaType = p.mediaType;
1988        if (typeof url !== "string" || typeof mediaType !== "string" || !url.startsWith("https://")) {
1989          return [];
1990        }
1991        return [{
1992          url,
1993          mediaType
1994        }];
1995      })) || [];
1996      sseLog(ctx.seq, "fetching", {
1997        url: gatewayUrl,
1998        fileParts: fileParts.length
1999      });
2000      const intent = JSON.stringify({
2001        websiteId,
2002        message: messageText,
2003        fileParts
2004      });
2005      if (((_d = pendingAdmissionRef.current) == null ? void 0 : _d.intent) !== intent) {
2006        pendingAdmissionRef.current = {
2007          intent,
2008          id: crypto.randomUUID()
2009        };
2010      }
2011      const response = await postSessionMessage(gatewayUrl, {
2012        message: messageText,
2013        sessionId: sessionIdRef.current,
2014        websiteId,
2015        admissionId: pendingAdmissionRef.current.id,
2016        fileParts: fileParts.length > 0 ? fileParts : void 0
2017      }, getToken, controller.signal);
2018      if (response.status === 409) {
2019        const errBody = await response.json().catch(() => ({}));
2020        if (["admission_not_activated", "admission_owner_changed", "stale_generation", "admission_ended"].includes(((_e = errBody.error) == null ? void 0 : _e.type) || "")) pendingAdmissionRef.current = null;
2021        if (!["turn_active", "turn_already_active"].includes(((_f = errBody.error) == null ? void 0 : _f.type) || "")) {
2022          throw new Error(((_g = errBody.error) == null ? void 0 : _g.message) || "Your message could not start yet. Please retry.");
2023        }
2024        pendingAdmissionRef.current = null;
2025        const existingTurnId = (_h = errBody.error) == null ? void 0 : _h.turnId;
2026        sseLog(ctx.seq, "turn already active; subscribing", {
2027          existingTurnId
2028        });
2029        setMessagesOrdered((prev) => prev.filter((m) => m.id !== message.id));
2030        setStatus("idle");
2031        if (existingTurnId) {
2032          void openResumeStream(existingTurnId, -1);
2033        }
2034        return "turn_active";
2035      }
2036      if (!response.ok) {
2037        const errorBody = await response.text();
2038        let errorMsg = `Chat request failed (${response.status})`;
2039        try {
2040          const parsed = JSON.parse(errorBody);
2041          if ((_i = parsed.error) == null ? void 0 : _i.message) errorMsg = parsed.error.message;
2042        } catch (e) {
2043          sseWarn(ctx.seq, "Failed to parse error response:", e);
2044        }
2045        if (response.status === 402) {
2046          errorMsg = "You have run out of chat credits.";
2047        }
2048        throw new Error(errorMsg);
2049      }
2050      if ((_j = response.headers.get("Content-Type")) == null ? void 0 : _j.includes("application/json")) {
2051        const replay = await response.json();
2052        if (!replay.alreadyActivated) throw new Error("Your message has not started yet. Please retry.");
2053        const recovered = await loadHistoryFromSandbox();
2054        if (controller.signal.aborted || abortRef.current !== controller) return "started";
2055        if (!recovered || !["sandbox-disk", "sandbox-restored", "sandbox-empty", "history-expired"].includes(recovered.source)) throw new Error("Your message finished, but its history is still loading. Please retry.");
2056        if (["sandbox-empty", "history-expired"].includes(recovered.source)) {
2057          setMessagesOrdered((prev) => prev.filter((m) => m.id !== message.id));
2058          sessionIdRef.current = null;
2059          onSessionWarning == null ? void 0 : onSessionWarning(sessionUploadWarning({
2060            status: "failed"
2061          }));
2062        } else {
2063          setMessagesOrdered(historyToChatMessages(recovered.messages));
2064          if (recovered.sessionId) sessionIdRef.current = recovered.sessionId;
2065        }
2066        pendingAdmissionRef.current = null;
2067        setStatus("idle");
2068        return "started";
2069      }
2070      if (!response.body) throw new Error("No response body");
2071      pendingAdmissionRef.current = null;
2072      sseLog(ctx.seq, "streaming started");
2073      setStatus("streaming");
2074      streamingBegan = true;
2075      await consumeSseStream(response.body, ctx, (type, data) => processEvent(type, data, ctx, {
2076        setMessages: queueMessagesUpdate,
2077        setPendingApproval,
2078        setPendingQuestion,
2079        setThinking,
2080        setMaxTurnsHit,
2081        setHistoryError,
2082        sessionIdRef,
2083        pageMountTimeMs: pageMountTimeRef.current,
2084        lastResetAtRef,
2085        onError,
2086        onSessionWarning,
2087        onSessionExpired,
2088        onChatReset,
2089        onShowView,
2090        lastShowViewRef
2091      }), controller.signal);
2092      lastEventIdRef.current = ctx.lastEventId;
2093      sseLog(ctx.seq, "stream end");
2094      try {
2095        const activeRes = await fetch(activeTurnUrl, {
2096          headers: {
2097            Authorization: `Bearer ${token}`
2098          },
2099          signal: controller.signal
2100        });
2101        if (activeRes.ok) {
2102          const activeBody = await activeRes.json();
2103          if (activeBody.active && activeBody.turnId) {
2104            sseLog(ctx.seq, "POST stream ended mid-turn; switching to resume", {
2105              turnId: activeBody.turnId,
2106              lastEventId: ctx.lastEventId
2107            });
2108            void openResumeStream(activeBody.turnId, ctx.lastEventId);
2109            return "started";
2110          }
2111        }
2112      } catch (err) {
2113        if (err.name !== "AbortError") {
2114          sseWarn(ctx.seq, "active-turn check failed:", err.message);
2115        }
2116      }
2117      setStatus("idle");
2118      setThinking(null);
2119      setMessagesOrdered((prev) => {
2120        const lastMsg = prev[prev.length - 1];
2121        if ((lastMsg == null ? void 0 : lastMsg.id) === ctx.assistantMsgId) {
2122          onFinish == null ? void 0 : onFinish({
2123            message: lastMsg
2124          });
2125        }
2126        return prev;
2127      });
2128      return "started";
2129    } catch (err) {
2130      if (err.name === "AbortError") {
2131        sseLog(ctx.seq, "aborted");
2132        setStatus("idle");
2133        return streamingBegan ? "started" : "failed";
2134      }
2135      if (streamingBegan) {
2136        try {
2137          const activeRes = await fetch(activeTurnUrl, {
2138            headers: {
2139              Authorization: `Bearer ${token}`
2140            }
2141          });
2142          if (activeRes.ok) {
2143            const activeBody = await activeRes.json();
2144            if (activeBody.active && activeBody.turnId) {
2145              sseLog(ctx.seq, "POST stream errored mid-turn; switching to resume", {
2146                turnId: activeBody.turnId,
2147                lastEventId: ctx.lastEventId,
2148                cause: err.message
2149              });
2150              void openResumeStream(activeBody.turnId, ctx.lastEventId);
2151              return "started";
2152            }
2153          }
2154        } catch (probeErr) {
2155          sseWarn(ctx.seq, "mid-turn active-turn probe failed:", probeErr.message);
2156        }
2157      }
2158      sseWarn(ctx.seq, "error:", err.message);
2159      setStatus("error");
2160      if (ctx.assistantCreated) {
2161        setMessagesOrdered((prev) => prev.filter((m) => m.id !== ctx.assistantMsgId));
2162      }
2163      onError == null ? void 0 : onError(err instanceof Error ? err : new Error(String(err)));
2164      return "failed";
2165    } finally {
2166      abortRef.current = null;
2167    }
2168  }, [gatewayUrl, activeTurnUrl, websiteId, getToken, loadHistoryFromSandbox, onFinish, onError, onSessionWarning, onSessionExpired, onChatReset, onNavigate, onShowView, openResumeStream]);
2169  const respondToApproval = reactExports.useCallback(async (approvalId, approved) => {
2170    const token = await getToken();
2171    if (!token) return;
2172    setApprovalSubmitting({
2173      approvalId,
2174      approved
2175    });
2176    try {
2177      const res = await fetch(`${baseUrl}/__agent/approve`, {
2178        method: "POST",
2179        headers: {
2180          "Content-Type": "application/json",
2181          Authorization: `Bearer ${token}`
2182        },
2183        body: JSON.stringify({
2184          approvalId,
2185          approved
2186        })
2187      });
2188      if (res.ok) {
2189        setPendingApproval(null);
2190      } else {
2191        onError == null ? void 0 : onError(new Error("Failed to send approval. Please try again."));
2192      }
2193    } catch (err) {
2194      onError == null ? void 0 : onError(new Error("Failed to send approval. Please try again."));
2195    } finally {
2196      setApprovalSubmitting(null);
2197    }
2198  }, [baseUrl, getToken, onError]);
2199  const respondToQuestion = reactExports.useCallback(async (interactionId, answers) => {
2200    const token = await getToken();
2201    if (!token) return;
2202    try {
2203      const res = await fetch(`${baseUrl}/__agent/answer-questions`, {
2204        method: "POST",
2205        headers: {
2206          "Content-Type": "application/json",
2207          Authorization: `Bearer ${token}`
2208        },
2209        body: JSON.stringify({
2210          interactionId,
2211          answers
2212        })
2213      });
2214      if (res.ok) {
2215        setPendingQuestion(null);
2216      } else if (res.status === 404) {
2217        setPendingQuestion(null);
2218      } else {
2219        onError == null ? void 0 : onError(new Error("Failed to send answers. Please try again."));
2220      }
2221    } catch (err) {
2222      onError == null ? void 0 : onError(new Error("Failed to send answers. Please try again."));
2223    }
2224  }, [baseUrl, getToken, onError]);
2225  const stop = reactExports.useCallback(() => {
2226    var _a;
2227    void (async () => {
2228      try {
2229        const token = await getToken();
2230        if (!token) return;
2231        await fetch(`${baseUrl}/__agent/stop`, {
2232          method: "POST",
2233          headers: {
2234            "Content-Type": "application/json",
2235            Authorization: `Bearer ${token}`
2236          },
2237          body: JSON.stringify({
2238            websiteId
2239          })
2240        });
2241      } catch {
2242      }
2243    })();
2244    (_a = abortRef.current) == null ? void 0 : _a.abort();
2245    setStatus("idle");
2246  }, [baseUrl, getToken, websiteId]);
2247  const clearHistory = reactExports.useCallback(async () => {
2248    var _a;
2249    (_a = abortRef.current) == null ? void 0 : _a.abort();
2250    abortRef.current = null;
2251    currentTurnIdRef.current = null;
2252    pendingResetIdRef.current || (pendingResetIdRef.current = crypto.randomUUID());
2253    try {
2254      const token = await getToken();
2255      if (!token) {
2256        throw new Error(AUTH_REQUIRED_MESSAGE);
2257      }
2258      const res = await fetch(`${baseUrl}/__agent/reset`, {
2259        method: "POST",
2260        headers: {
2261          "Content-Type": "application/json",
2262          Authorization: `Bearer ${token}`
2263        },
2264        body: JSON.stringify({
2265          websiteId,
2266          resetId: pendingResetIdRef.current
2267        })
2268      });
2269      if (!res.ok) throw new Error("Chat could not be reset. Please retry.");
2270      const body = await res.json();
2271      pendingResetIdRef.current = null;
2272      pendingAdmissionRef.current = null;
2273      setMessagesOrdered([]);
2274      setPendingApproval(null);
2275      setPendingQuestion(null);
2276      setThinking(null);
2277      setMaxTurnsHit(false);
2278      sessionIdRef.current = null;
2279      lastEventIdRef.current = -1;
2280      setHistoryError(null);
2281      if (typeof body.resetAt === "number") {
2282        lastResetAtRef.current = body.resetAt;
2283      }
2284    } catch (error) {
2285      onError == null ? void 0 : onError(error instanceof Error ? error : new Error("Chat could not be reset."));
2286      throw error;
2287    } finally {
2288      setStatus("idle");
2289    }
2290  }, [baseUrl, websiteId]);
2291  const retryHistory = reactExports.useCallback(() => {
2292    setHistoryError(null);
2293    setHistoryLoadAttempt((n) => n + 1);
2294  }, []);
2295  return {
2296    messages,
2297    sendMessage,
2298    stop,
2299    status,
2300    isLoading: status === "connecting" || status === "streaming",
2301    // Ordered wrapper (queue + flush) so external mutations (e.g. restore)
2302    // can never apply against a stale base while stream updates are queued.
2303    setMessages: setMessagesOrdered,
2304    clearHistory,
2305    pendingApproval,
2306    approvalSubmitting,
2307    respondToApproval,
2308    pendingQuestion,
2309    respondToQuestion,
2310    historyLoading,
2311    historyError,
2312    retryHistory,
2313    thinking,
2314    maxTurnsHit
2315  };
2316}
2317function getMessageStackPosition(messages, index) {
2318  var _a, _b, _c;
2319  const role = (_a = messages[index]) == null ? void 0 : _a.role;
2320  if (role !== "user" && role !== "assistant") return null;
2321  const prevRole = index > 0 ? (_b = messages[index - 1]) == null ? void 0 : _b.role : null;
2322  const nextRole = index < messages.length - 1 ? (_c = messages[index + 1]) == null ? void 0 : _c.role : null;
2323  const continuesPrev = prevRole === role;
2324  const continuesNext = nextRole === role;
2325  if (!continuesPrev && !continuesNext) return "solo";
2326  if (!continuesPrev && continuesNext) return "first";
2327  if (continuesPrev && continuesNext) return "middle";
2328  return "last";
2329}
2330function messageContinuesStack(messages, index) {
2331  var _a, _b;
2332  if (index <= 0) return false;
2333  return ((_a = messages[index]) == null ? void 0 : _a.role) === ((_b = messages[index - 1]) == null ? void 0 : _b.role);
2334}
2335function getChatBubbleRadiusClass(role, position) {
2336  switch (position) {
2337    case "solo":
2338      return "rounded-tl-[16px] rounded-tr-[4px] rounded-br-[16px] rounded-bl-[16px]";
2339    case "first":
2340      return "rounded-tl-[16px] rounded-tr-[4px] rounded-br-[4px] rounded-bl-[16px]";
2341    case "middle":
2342      return "rounded-tl-[16px] rounded-tr-[4px] rounded-br-[4px] rounded-bl-[16px]";
2343    case "last":
2344      return "rounded-tl-[16px] rounded-tr-[4px] rounded-br-[16px] rounded-bl-[16px]";
2345  }
2346}
2347const TAG_TO_NOUN = {
2348  // Interactive
2349  button: "button",
2350  a: "link",
2351  input: "input",
2352  textarea: "input",
2353  select: "dropdown",
2354  option: "option",
2355  form: "form",
2356  fieldset: "form group",
2357  label: "label",
2358  legend: "label",
2359  // Media
2360  img: "image",
2361  picture: "image",
2362  figure: "figure",
2363  figcaption: "caption",
2364  video: "video",
2365  audio: "audio",
2366  svg: "icon",
2367  iframe: "embed",
2368  // Headings & text
2369  h1: "heading",
2370  h2: "heading",
2371  h3: "heading",
2372  h4: "heading",
2373  h5: "heading",
2374  h6: "heading",
2375  p: "text",
2376  blockquote: "quote",
2377  span: "text",
2378  strong: "text",
2379  b: "text",
2380  em: "text",
2381  i: "text",
2382  small: "text",
2383  mark: "highlight",
2384  code: "code",
2385  pre: "code block",
2386  // Lists & tables
2387  ul: "list",
2388  ol: "list",
2389  li: "list item",
2390  dl: "list",
2391  dt: "list item",
2392  dd: "list item",
2393  table: "table",
2394  thead: "table",
2395  tbody: "table",
2396  tfoot: "table",
2397  tr: "table row",
2398  td: "table cell",
2399  th: "table cell",
2400  // Layout / structural
2401  nav: "navigation",
2402  header: "header",
2403  footer: "footer",
2404  main: "main content",
2405  aside: "sidebar",
2406  article: "article",
2407  section: "section",
2408  div: "section",
2409  // Misc
2410  details: "expandable",
2411  summary: "summary",
2412  hr: "divider",
2413  br: "line break"
2414};
2415function friendlyElementNoun(tag) {
2416  return TAG_TO_NOUN[tag.toLowerCase()] ?? "element";
2417}
2418function formatFriendlyLabel(tag, text) {
2419  const noun = friendlyElementNoun(tag);
2420  const trimmed = (text ?? "").trim();
2421  if (!trimmed) return noun;
2422  return `${noun} — "${trimmed}"`;
2423}
2424const TOOL_ICONS = {
2425  // ── file / code ──────────────────────────────────────────────────────────
2426  Read: BookOpen,
2427  Write: FilePen,
2428  // feather + paper
2429  Edit: FilePen,
2430  MultiEdit: FilePen,
2431  editPage: FilePen,
2432  Bash: SquareTerminal,
2433  // >_
2434  // ── search / lookup ──────────────────────────────────────────────────────
2435  Glob: Search,
2436  Grep: Search,
2437  WebSearch: Search,
2438  WebFetch: Search,
2439  websiteSemanticSearch: Search,
2440  pageGrepSearch: Search,
2441  "mcp__landingsite__website_semantic_search": Search,
2442  "mcp__landingsite__page_grep_search": Search,
2443  // ── docs ─────────────────────────────────────────────────────────────────
2444  "mcp__landingsite-docs__search_docs": Files,
2445  // multiple pages
2446  // ── structure / content ──────────────────────────────────────────────────
2447  addNewSection: AppWindow,
2448  // application window
2449  addNewPage: FilePlus2,
2450  // default — review in harness
2451  "mcp__landingsite__create_form": ClipboardList,
2452  // default
2453  // ── navigation ───────────────────────────────────────────────────────────
2454  navigateToPage: Compass,
2455  // default
2456  navigateToSettings: Settings,
2457  // default
2458  // ── info / status ────────────────────────────────────────────────────────
2459  "mcp__landingsite__get_publishing_status": Activity,
2460  // default
2461  "mcp__landingsite__get_website_info": Info,
2462  // default
2463  "mcp__landingsite__get_domain_info": Globe,
2464  // default
2465  "mcp__landingsite__list_user_websites_and_domains": LayoutGrid,
2466  // default
2467  // ── media ────────────────────────────────────────────────────────────────
2468  "mcp__landingsite__search_for_images": Image,
2469  // default
2470  "mcp__landingsite__screenshot_preview": Camera,
2471  // default
2472  // ── publish ──────────────────────────────────────────────────────────────
2473  "mcp__landingsite__publish_website": Rocket,
2474  // default
2475  "mcp__landingsite__unpublish_website": EyeOff,
2476  // default
2477  // ── business / merchant views ────────────────────────────────────────────
2478  "mcp__landingsite__show_view": Eye,
2479  // swaps a merchant view into the preview
2480  "mcp__landingsite__get_business_summary": Store,
2481  "mcp__landingsite__sales_summary": TrendingUp,
2482  "mcp__landingsite__list_orders": Package,
2483  "mcp__landingsite__get_order": Package,
2484  "mcp__landingsite__list_people": Users,
2485  "mcp__landingsite__get_person": User,
2486  "mcp__landingsite__get_next_payout": Banknote,
2487  "mcp__landingsite__mark_order_fulfilled": PackageCheck
2488};
2489function getToolIcon(toolName) {
2490  return TOOL_ICONS[toolName] ?? null;
2491}
2492const SANDBOX_ROOT = /^\/home\/user\/website\//;
2493function stripHome(path) {
2494  return asString(path).replace(SANDBOX_ROOT, "");
2495}
2496function truncate(str, max) {
2497  if (typeof str !== "string") return "";
2498  if (str.length <= max) return str;
2499  return str.slice(0, max) + "…";
2500}
2501function formatBytes(bytes) {
2502  if (bytes < 1024) return `${bytes}B`;
2503  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
2504  return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
2505}
2506function asString(v) {
2507  if (typeof v === "string") return v;
2508  if (v == null) return "";
2509  try {
2510    return JSON.stringify(v);
2511  } catch {
2512    return String(v);
2513  }
2514}
2515function countLines(str) {
2516  if (!str) return 0;
2517  const lines = str.split("\n");
2518  if (lines[lines.length - 1] === "") lines.pop();
2519  return lines.length;
2520}
2521function firstLine(str) {
2522  const idx = str.indexOf("\n");
2523  return idx === -1 ? str : str.slice(0, idx);
2524}
2525function DimLabel({
2526  children
2527}) {
2528  return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-gray-400", children });
2529}
2530function HeaderPath({
2531  path
2532}) {
2533  return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-gray-700", children: stripHome(path) });
2534}
2535function CountSummary({
2536  label,
2537  count: count2,
2538  bytes
2539}) {
2540  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[11px] text-gray-600", children: [
2541    label,
2542    " ",
2543    count2,
2544    " line",
2545    count2 === 1 ? "" : "s",
2546    bytes !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-400", children: [
2547      " (",
2548      formatBytes(bytes),
2549      ")"
2550    ] })
2551  ] });
2552}
2553function MiniPatch({
2554  before,
2555  after
2556}) {
2557  if (!before && !after) return null;
2558  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "max-h-96 overflow-auto rounded border border-gray-200 bg-white font-mono text-[11px]", children: [
2559    before !== void 0 && before !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "whitespace-pre border-b border-gray-100 bg-red-50 px-2 py-1 text-red-700", children: prefixLines(before, "− ") }),
2560    after !== void 0 && after !== "" && /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "whitespace-pre bg-green-50 px-2 py-1 text-green-700", children: prefixLines(after, "+ ") })
2561  ] });
2562}
2563function prefixLines(str, prefix) {
2564  const trimmed = str.endsWith("\n") ? str.slice(0, -1) : str;
2565  return trimmed.split("\n").map((line) => prefix + line).join("\n");
2566}
2567const ReadRenderer = {
2568  header: (input) => {
2569    const path = input == null ? void 0 : input.file_path;
2570    if (!path) return null;
2571    const offset2 = input == null ? void 0 : input.offset;
2572    const limit = input == null ? void 0 : input.limit;
2573    return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
2574      /* @__PURE__ */ jsxRuntimeExports.jsx(HeaderPath, { path }),
2575      offset2 != null && limit != null && /* @__PURE__ */ jsxRuntimeExports.jsxs(DimLabel, { children: [
2576        " ",
2577        "· lines ",
2578        offset2,
2579        "–",
2580        offset2 + limit
2581      ] })
2582    ] });
2583  },
2584  result: ({
2585    output,
2586    input
2587  }) => {
2588    var _a;
2589    const text = asString(output);
2590    if (!text) return null;
2591    const lines = countLines(text);
2592    const bytes = new Blob([text]).size;
2593    const path = asString(input == null ? void 0 : input.file_path);
2594    const ext = (_a = path.split(".").pop()) == null ? void 0 : _a.toLowerCase();
2595    const isImage = ext ? ["png", "jpg", "jpeg", "gif", "webp", "svg"].includes(ext) : false;
2596    if (isImage) return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[11px] text-gray-600", children: "Read image" });
2597    if (ext === "pdf") return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[11px] text-gray-600", children: "Read PDF" });
2598    return /* @__PURE__ */ jsxRuntimeExports.jsx(CountSummary, { label: "Read", count: lines, bytes });
2599  }
2600};
2601const WriteRenderer = {
2602  header: (input) => {
2603    const path = input == null ? void 0 : input.file_path;
2604    const content = input == null ? void 0 : input.content;
2605    if (!path) return null;
2606    const bytes = content ? new Blob([content]).size : void 0;
2607    return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
2608      /* @__PURE__ */ jsxRuntimeExports.jsx(HeaderPath, { path }),
2609      bytes !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(DimLabel, { children: [
2610        " · ",
2611        formatBytes(bytes)
2612      ] })
2613    ] });
2614  },
2615  result: ({
2616    input
2617  }) => {
2618    const content = input == null ? void 0 : input.content;
2619    if (!content) return null;
2620    const lines = countLines(content);
2621    return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1.5", children: [
2622      /* @__PURE__ */ jsxRuntimeExports.jsx(CountSummary, { label: "Wrote", count: lines }),
2623      /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "max-h-96 overflow-auto whitespace-pre rounded border border-gray-200 bg-white p-2 font-mono text-[11px] leading-relaxed text-gray-800", children: content })
2624    ] });
2625  }
2626};
2627const EditRenderer = {
2628  header: (input) => {
2629    const path = input == null ? void 0 : input.file_path;
2630    return path ? /* @__PURE__ */ jsxRuntimeExports.jsx(HeaderPath, { path }) : null;
2631  },
2632  result: ({
2633    input
2634  }) => {
2635    const before = input == null ? void 0 : input.old_string;
2636    const after = input == null ? void 0 : input.new_string;
2637    if (!before && !after) return null;
2638    return /* @__PURE__ */ jsxRuntimeExports.jsx(MiniPatch, { before, after });
2639  }
2640};
2641const MultiEditRenderer = {
2642  header: (input) => {
2643    const path = input == null ? void 0 : input.file_path;
2644    const edits = input == null ? void 0 : input.edits;
2645    const n = Array.isArray(edits) ? edits.length : 0;
2646    if (!path) return null;
2647    return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
2648      /* @__PURE__ */ jsxRuntimeExports.jsx(HeaderPath, { path }),
2649      n > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(DimLabel, { children: [
2650        " ",
2651        "· ",
2652        n,
2653        " edit",
2654        n === 1 ? "" : "s"
2655      ] })
2656    ] });
2657  },
2658  result: ({
2659    input
2660  }) => {
2661    const edits = input == null ? void 0 : input.edits;
2662    if (!Array.isArray(edits) || edits.length === 0) return null;
2663    return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1.5", children: [
2664      edits.slice(0, 3).map((edit, i) => /* @__PURE__ */ jsxRuntimeExports.jsx(MiniPatch, { before: edit.old_string, after: edit.new_string }, i)),
2665      edits.length > 3 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[11px] text-gray-500", children: [
2666        "+ ",
2667        edits.length - 3,
2668        " more edit",
2669        edits.length - 3 === 1 ? "" : "s"
2670      ] })
2671    ] });
2672  }
2673};
2674const GlobRenderer = {
2675  displayName: "Search",
2676  progressLabel: () => "Searching…",
2677  header: (input) => {
2678    const pattern = input == null ? void 0 : input.pattern;
2679    const path = input == null ? void 0 : input.path;
2680    return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-700", children: [
2681      pattern && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
2682        "pattern:",
2683        " ",
2684        /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-900", children: [
2685          '"',
2686          truncate(pattern, 40),
2687          '"'
2688        ] })
2689      ] }),
2690      path && /* @__PURE__ */ jsxRuntimeExports.jsxs(DimLabel, { children: [
2691        ' · path: "',
2692        stripHome(path),
2693        '"'
2694      ] })
2695    ] });
2696  },
2697  result: ({
2698    output
2699  }) => {
2700    const text = asString(output);
2701    if (!text) return null;
2702    const files = text.split("\n").filter(Boolean);
2703    if (files.length === 0) return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[11px] text-gray-500", children: "No matches" });
2704    return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[11px]", children: [
2705      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-1 text-gray-600", children: [
2706        "Found ",
2707        files.length,
2708        " file",
2709        files.length === 1 ? "" : "s"
2710      ] }),
2711      /* @__PURE__ */ jsxRuntimeExports.jsxs("ul", { className: "space-y-0.5 font-mono text-gray-700", children: [
2712        files.slice(0, 20).map((f, i) => /* @__PURE__ */ jsxRuntimeExports.jsx("li", { className: "truncate", children: stripHome(f) }, i)),
2713        files.length > 20 && /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { className: "text-gray-400", children: [
2714          "+ ",
2715          files.length - 20,
2716          " more"
2717        ] })
2718      ] })
2719    ] });
2720  }
2721};
2722const GrepRenderer = {
2723  displayName: "Search",
2724  progressLabel: () => "Searching…",
2725  header: (input) => {
2726    const pattern = input == null ? void 0 : input.pattern;
2727    const path = input == null ? void 0 : input.path;
2728    return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-700", children: [
2729      pattern && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
2730        "pattern:",
2731        " ",
2732        /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-900", children: [
2733          '"',
2734          truncate(pattern, 40),
2735          '"'
2736        ] })
2737      ] }),
2738      path && /* @__PURE__ */ jsxRuntimeExports.jsxs(DimLabel, { children: [
2739        ' · path: "',
2740        stripHome(path),
2741        '"'
2742      ] })
2743    ] });
2744  },
2745  result: ({
2746    output,
2747    input
2748  }) => {
2749    const mode = (input == null ? void 0 : input.output_mode) ?? "files_with_matches";
2750    const text = asString(output);
2751    if (!text) return null;
2752    const lines = text.split("\n").filter(Boolean);
2753    if (lines.length === 0) return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[11px] text-gray-500", children: "No matches" });
2754    if (mode === "count") {
2755      const total = lines.reduce((sum, l) => {
2756        const m = l.match(/:(\d+)$/);
2757        return sum + (m ? parseInt(m[1], 10) : 0);
2758      }, 0);
2759      return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[11px] text-gray-600", children: [
2760        total,
2761        " match",
2762        total === 1 ? "" : "es",
2763        " in ",
2764        lines.length,
2765        " file",
2766        lines.length === 1 ? "" : "s"
2767      ] });
2768    }
2769    if (mode === "content") {
2770      return /* @__PURE__ */ jsxRuntimeExports.jsxs("pre", { className: "max-h-48 overflow-auto whitespace-pre-wrap break-all rounded bg-white p-1.5 font-mono text-[11px] text-gray-800", children: [
2771        lines.slice(0, 30).join("\n"),
2772        lines.length > 30 && `
2773… + ${lines.length - 30} more`
2774      ] });
2775    }
2776    return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[11px]", children: [
2777      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-1 text-gray-600", children: [
2778        "Found matches in ",
2779        lines.length,
2780        " file",
2781        lines.length === 1 ? "" : "s"
2782      ] }),
2783      /* @__PURE__ */ jsxRuntimeExports.jsxs("ul", { className: "space-y-0.5 font-mono text-gray-700", children: [
2784        lines.slice(0, 20).map((f, i) => /* @__PURE__ */ jsxRuntimeExports.jsx("li", { className: "truncate", children: stripHome(f) }, i)),
2785        lines.length > 20 && /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { className: "text-gray-400", children: [
2786          "+ ",
2787          lines.length - 20,
2788          " more"
2789        ] })
2790      ] })
2791    ] });
2792  }
2793};
2794const BashRenderer = {
2795  // Once the command has streamed in, keep it in the header while it runs —
2796  // a long-running command (a polling loop) otherwise reads as an opaque
2797  // "Running…" with no way to see what it's waiting on.
2798  progressLabel: (input) => (input == null ? void 0 : input.command) ? null : "Running…",
2799  hideDefaultInput: true,
2800  header: (input) => {
2801    const cmd = input == null ? void 0 : input.command;
2802    if (!cmd) return null;
2803    return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "truncate font-mono text-gray-800", children: [
2804      "$ ",
2805      truncate(firstLine(cmd), 120)
2806    ] });
2807  },
2808  result: ({
2809    output,
2810    input
2811  }) => {
2812    const cmd = (input == null ? void 0 : input.command) ?? "";
2813    const text = asString(output);
2814    return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1.5", children: [
2815      cmd && /* @__PURE__ */ jsxRuntimeExports.jsxs("pre", { className: "whitespace-pre-wrap break-all rounded bg-gray-900 p-1.5 font-mono text-[11px] text-gray-100", children: [
2816        "$ ",
2817        cmd
2818      ] }),
2819      text && /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "max-h-64 overflow-auto whitespace-pre-wrap break-all rounded bg-white p-1.5 font-mono text-[11px] text-gray-800", children: text }),
2820      text && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[10px] text-gray-400", children: [
2821        countLines(text),
2822        " lines · ",
2823        formatBytes(new Blob([text]).size)
2824      ] })
2825    ] });
2826  }
2827};
2828const WebFetchRenderer = {
2829  progressLabel: () => "Fetching…",
2830  header: (input) => {
2831    const url = input == null ? void 0 : input.url;
2832    if (!url) return null;
2833    return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-700", children: [
2834      "url: ",
2835      /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-900", children: [
2836        '"',
2837        truncate(url, 60),
2838        '"'
2839      ] })
2840    ] });
2841  },
2842  result: ({
2843    output
2844  }) => {
2845    const text = asString(output);
2846    if (!text) return null;
2847    return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[11px] text-gray-600", children: [
2848      "Received",
2849      " ",
2850      /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-400", children: [
2851        "(",
2852        formatBytes(new Blob([text]).size),
2853        ")"
2854      ] })
2855    ] });
2856  }
2857};
2858const WebSearchRenderer = {
2859  progressLabel: () => "Searching…",
2860  header: (input) => {
2861    const query = input == null ? void 0 : input.query;
2862    if (!query) return null;
2863    return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-700", children: [
2864      "query: ",
2865      /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-900", children: [
2866        '"',
2867        truncate(query, 60),
2868        '"'
2869      ] })
2870    ] });
2871  },
2872  result: ({
2873    output
2874  }) => {
2875    const text = asString(output);
2876    if (!text) return null;
2877    const blocks = text.split(/\n{2,}/).filter(Boolean);
2878    return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[11px] text-gray-600", children: [
2879      "Found ",
2880      blocks.length,
2881      " result",
2882      blocks.length === 1 ? "" : "s"
2883    ] });
2884  }
2885};
2886const SearchDocsRenderer = {
2887  displayName: "Search Help Docs",
2888  progressLabel: () => "Searching help docs…",
2889  header: (input) => {
2890    const query = input == null ? void 0 : input.query;
2891    if (!query) return null;
2892    return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-700", children: [
2893      "query: ",
2894      /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-900", children: [
2895        '"',
2896        truncate(query, 60),
2897        '"'
2898      ] })
2899    ] });
2900  },
2901  result: ({
2902    output
2903  }) => {
2904    let raw = output;
2905    if (typeof raw === "string") {
2906      try {
2907        raw = JSON.parse(raw);
2908      } catch {
2909      }
2910    }
2911    if (Array.isArray(raw)) {
2912      const first = raw[0];
2913      if ((first == null ? void 0 : first.type) === "text" && typeof first.text === "string") {
2914        try {
2915          raw = JSON.parse(first.text);
2916        } catch {
2917        }
2918      }
2919    } else if (raw && typeof raw === "object" && "content" in raw) {
2920      const content = raw.content;
2921      const first = Array.isArray(content) ? content[0] : null;
2922      if ((first == null ? void 0 : first.type) === "text" && typeof first.text === "string") {
2923        try {
2924          raw = JSON.parse(first.text);
2925        } catch {
2926        }
2927      }
2928    }
2929    let hits = null;
2930    if (raw && typeof raw === "object" && "hits" in raw) {
2931      hits = raw.hits;
2932    }
2933    const count2 = Array.isArray(hits) ? hits.length : 0;
2934    if (count2 === 0) {
2935      return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[11px] text-gray-600", children: "No matching docs found." });
2936    }
2937    return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[11px] text-gray-600", children: [
2938      "Found ",
2939      count2,
2940      " doc",
2941      count2 === 1 ? "" : "s"
2942    ] });
2943  }
2944};
2945const AskUserQuestionRenderer = {
2946  displayName: "Question",
2947  progressLabel: () => "Waiting for your answer…",
2948  hideDefaultInput: true,
2949  header: (input) => {
2950    const raw = input == null ? void 0 : input.questions;
2951    const questions = (Array.isArray(raw) ? raw : []).filter((q) => !!q && typeof q === "object");
2952    if (questions.length === 0) return null;
2953    if (questions.length === 1) {
2954      const label = questions[0].question || questions[0].header || "";
2955      return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-gray-700", children: truncate(label, 60) });
2956    }
2957    return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-700", children: [
2958      questions.length,
2959      " question",
2960      questions.length === 1 ? "" : "s",
2961      /* @__PURE__ */ jsxRuntimeExports.jsxs(DimLabel, { children: [
2962        " ",
2963        "·",
2964        " ",
2965        questions.map((q) => q.header || "").filter(Boolean).join(", ")
2966      ] })
2967    ] });
2968  },
2969  result: ({
2970    output
2971  }) => {
2972    let parsed = null;
2973    if (output && typeof output === "object") {
2974      parsed = output;
2975    } else if (typeof output === "string") {
2976      try {
2977        parsed = JSON.parse(output);
2978      } catch {
2979      }
2980    }
2981    if ((parsed == null ? void 0 : parsed.questions) && (parsed == null ? void 0 : parsed.answers)) {
2982      const {
2983        questions,
2984        answers
2985      } = parsed;
2986      return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1 text-[11px]", children: questions.map((q, i) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
2987        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-gray-500", children: q.question }),
2988        " → ",
2989        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium text-green-700", children: answers[q.question] || "(skipped)" })
2990      ] }, i)) });
2991    }
2992    const text = asString(output);
2993    if (!text) return null;
2994    return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[11px] text-gray-600", children: truncate(text, 200) });
2995  }
2996};
2997function unwrapMcpJson(output) {
2998  let raw = output;
2999  if (typeof raw === "string") {
3000    try {
3001      raw = JSON.parse(raw);
3002    } catch {
3003      return output;
3004    }
3005  }
3006  if (Array.isArray(raw)) {
3007    const first = raw[0];
3008    if ((first == null ? void 0 : first.type) === "text" && typeof first.text === "string") {
3009      try {
3010        return JSON.parse(first.text);
3011      } catch {
3012        return first.text;
3013      }
3014    }
3015  } else if (raw && typeof raw === "object" && "content" in raw) {
3016    const content = raw.content;
3017    const first = Array.isArray(content) ? content[0] : null;
3018    if ((first == null ? void 0 : first.type) === "text" && typeof first.text === "string") {
3019      try {
3020        return JSON.parse(first.text);
3021      } catch {
3022        return first.text;
3023      }
3024    }
3025  }
3026  return raw;
3027}
3028const GetPublishingStatusRenderer = {
3029  displayName: "Publishing Status",
3030  progressLabel: () => "Checking publishing status…",
3031  hideDefaultInput: true,
3032  header: () => null,
3033  result: ({
3034    output
3035  }) => {
3036    const data = unwrapMcpJson(output);
3037    if (!data || typeof data === "string") {
3038      const text = asString(output);
3039      return text ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[11px] text-gray-600", children: truncate(text, 200) }) : null;
3040    }
3041    const status = data.publishingStatus || "Unknown";
3042    const statusColor = status === "Completed" ? "text-green-700" : status === "Failed" ? "text-red-700" : status === "In Progress" ? "text-blue-700" : "text-gray-700";
3043    return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-0.5 text-[11px] text-gray-700", children: [
3044      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
3045        "Status:",
3046        " ",
3047        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("font-medium", statusColor), children: status }),
3048        typeof data.publishingProgress === "number" && /* @__PURE__ */ jsxRuntimeExports.jsxs(DimLabel, { children: [
3049          " · ",
3050          data.publishingProgress,
3051          "%"
3052        ] })
3053      ] }),
3054      data.publishingStep && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
3055        /* @__PURE__ */ jsxRuntimeExports.jsx(DimLabel, { children: "Step:" }),
3056        " ",
3057        data.publishingStep
3058      ] }),
3059      data.publishingErrorMessage && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-red-700", children: [
3060        /* @__PURE__ */ jsxRuntimeExports.jsx(DimLabel, { children: "Error:" }),
3061        " ",
3062        truncate(data.publishingErrorMessage, 200)
3063      ] })
3064    ] });
3065  }
3066};
3067const GetWebsiteInfoRenderer = {
3068  displayName: "Website Info",
3069  progressLabel: () => "Looking up website…",
3070  header: (input) => {
3071    const websiteId = input == null ? void 0 : input.websiteId;
3072    if (!websiteId) {
3073      return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-gray-500", children: "current website" });
3074    }
3075    return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-700", children: [
3076      /* @__PURE__ */ jsxRuntimeExports.jsx(DimLabel, { children: "id:" }),
3077      " ",
3078      truncate(websiteId, 40)
3079    ] });
3080  },
3081  result: ({
3082    output
3083  }) => {
3084    var _a;
3085    const data = unwrapMcpJson(output);
3086    if (!data || typeof data === "string") {
3087      const text = asString(output);
3088      return text ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[11px] text-gray-600", children: truncate(text, 200) }) : null;
3089    }
3090    return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-0.5 text-[11px] text-gray-700", children: [
3091      data.name && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
3092        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium text-gray-900", children: data.name }),
3093        data.websiteType && /* @__PURE__ */ jsxRuntimeExports.jsxs(DimLabel, { children: [
3094          " · ",
3095          data.websiteType
3096        ] })
3097      ] }),
3098      data.previewUrl && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
3099        /* @__PURE__ */ jsxRuntimeExports.jsx(DimLabel, { children: "Preview:" }),
3100        " ",
3101        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono", children: data.previewUrl })
3102      ] }),
3103      ((_a = data.Domain) == null ? void 0 : _a.domainName) && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
3104        /* @__PURE__ */ jsxRuntimeExports.jsx(DimLabel, { children: "Linked domain:" }),
3105        " ",
3106        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono", children: data.Domain.domainName }),
3107        data.Domain.verificationStatus && /* @__PURE__ */ jsxRuntimeExports.jsxs(DimLabel, { children: [
3108          " · ",
3109          data.Domain.verificationStatus
3110        ] })
3111      ] }),
3112      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
3113        /* @__PURE__ */ jsxRuntimeExports.jsx(DimLabel, { children: "Plan:" }),
3114        " ",
3115        data.stripePlan || "Free",
3116        /* @__PURE__ */ jsxRuntimeExports.jsxs(DimLabel, { children: [
3117          " ",
3118          "· ",
3119          data.hasBeenPublished ? "published" : "not published",
3120          data.publishingStatus ? ` (${data.publishingStatus})` : ""
3121        ] })
3122      ] })
3123    ] });
3124  }
3125};
3126const GetDomainInfoRenderer = {
3127  displayName: "Domain Info",
3128  progressLabel: () => "Looking up domain…",
3129  header: (input) => {
3130    const name = input == null ? void 0 : input.domainName;
3131    const id = input == null ? void 0 : input.domainId;
3132    if (name) {
3133      return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-gray-900", children: name });
3134    }
3135    if (id) {
3136      return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-700", children: [
3137        /* @__PURE__ */ jsxRuntimeExports.jsx(DimLabel, { children: "id:" }),
3138        " ",
3139        truncate(id, 40)
3140      ] });
3141    }
3142    return null;
3143  },
3144  result: ({
3145    output
3146  }) => {
3147    var _a, _b;
3148    const data = unwrapMcpJson(output);
3149    if (!data || typeof data === "string") {
3150      const text = asString(output);
3151      return text ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[11px] text-gray-600", children: truncate(text, 200) }) : null;
3152    }
3153    const verification = data.verificationStatus || "Unknown";
3154    const verificationColor = verification === "Active" ? "text-green-700" : /failed/i.test(verification) ? "text-red-700" : "text-blue-700";
3155    return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-0.5 text-[11px] text-gray-700", children: [
3156      data.domainName && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "font-mono text-gray-900", children: [
3157        data.domainName,
3158        data.isSubdomain && /* @__PURE__ */ jsxRuntimeExports.jsx(DimLabel, { children: " · subdomain" })
3159      ] }),
3160      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
3161        /* @__PURE__ */ jsxRuntimeExports.jsx(DimLabel, { children: "Verification:" }),
3162        " ",
3163        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("font-medium", verificationColor), children: verification })
3164      ] }),
3165      data.purchaseStatus && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
3166        /* @__PURE__ */ jsxRuntimeExports.jsx(DimLabel, { children: "Purchase:" }),
3167        " ",
3168        data.purchaseStatus,
3169        data.purchasedThroughLandingsite && /* @__PURE__ */ jsxRuntimeExports.jsx(DimLabel, { children: " · via Landingsite" })
3170      ] }),
3171      data.nameserverStatus && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
3172        /* @__PURE__ */ jsxRuntimeExports.jsx(DimLabel, { children: "Nameservers:" }),
3173        " ",
3174        data.nameserverStatus,
3175        data.configurationMethod && /* @__PURE__ */ jsxRuntimeExports.jsxs(DimLabel, { children: [
3176          " · ",
3177          data.configurationMethod
3178        ] })
3179      ] }),
3180      data.domainExpireDate && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
3181        /* @__PURE__ */ jsxRuntimeExports.jsx(DimLabel, { children: "Expires:" }),
3182        " ",
3183        new Date(data.domainExpireDate).toLocaleDateString(),
3184        data.isRenewalActive === false && ((_a = data.lifecycle) == null ? void 0 : _a.stage) !== "renewal_scheduled" && /* @__PURE__ */ jsxRuntimeExports.jsx(DimLabel, { children: " · renewal off" })
3185      ] }),
3186      ((_b = data.website) == null ? void 0 : _b.name) && /* @__P
3186URE__ */ jsxRuntimeExports.jsxs("div", { children: [
3187        /* @__PURE__ */ jsxRuntimeExports.jsx(DimLabel, { children: "Linked website:" }),
3188        " ",
3189        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-gray-900", children: data.website.name })
3190      ] })
3191    ] });
3192  }
3193};
3194const CreateFormRenderer = {
3195  displayName: "Create Form",
3196  progressLabel: (input) => {
3197    const name = input == null ? void 0 : input.name;
3198    return name ? `Creating "${truncate(name, 40)}"…` : "Creating form…";
3199  },
3200  header: (input) => {
3201    const name = input == null ? void 0 : input.name;
3202    if (!name) return null;
3203    return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-900", children: [
3204      '"',
3205      truncate(name, 60),
3206      '"'
3207    ] });
3208  }
3209};
3210const ShowViewRenderer = {
3211  displayName: "Show View",
3212  progressLabel: (input) => {
3213    const view = input == null ? void 0 : input.view;
3214    return view ? `Opening the ${view} view…` : "Opening view…";
3215  },
3216  header: (input) => {
3217    const view = input == null ? void 0 : input.view;
3218    if (!view) return null;
3219    const orderId = input == null ? void 0 : input.order_id;
3220    return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-900", children: [
3221      view,
3222      orderId && /* @__PURE__ */ jsxRuntimeExports.jsxs(DimLabel, { children: [
3223        " · order ",
3224        truncate(orderId, 24)
3225      ] })
3226    ] });
3227  }
3228};
3229const SearchForImagesRenderer = {
3230  displayName: "Search Images",
3231  progressLabel: (input) => {
3232    const description = input == null ? void 0 : input.description;
3233    return description ? `Searching for "${truncate(description, 40)}"…` : "Searching for images…";
3234  },
3235  header: (input) => {
3236    const description = input == null ? void 0 : input.description;
3237    if (!description) return null;
3238    return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-900", children: [
3239      '"',
3240      truncate(description, 60),
3241      '"'
3242    ] });
3243  },
3244  result: ({
3245    output
3246  }) => {
3247    const data = unwrapMcpJson(output);
3248    if (!data) return null;
3249    if (typeof data === "string") {
3250      return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[11px] text-gray-600", children: truncate(data, 200) });
3251    }
3252    const images = Array.isArray(data) ? data : data.data || [];
3253    if (images.length === 0) {
3254      return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[11px] text-gray-500", children: "No images found." });
3255    }
3256    return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1.5 text-[11px] text-gray-700", children: [
3257      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-gray-500", children: [
3258        images.length,
3259        " image",
3260        images.length === 1 ? "" : "s",
3261        " found"
3262      ] }),
3263      /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid grid-cols-3 gap-1.5", children: images.slice(0, 6).map((img, i) => img.url ? /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: img.url, target: "_blank", rel: "noopener noreferrer", className: "block overflow-hidden rounded border border-gray-200 bg-white", children: /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: img.url, alt: img.altText || "", className: "aspect-video w-full object-cover", loading: "lazy" }) }, i) : null) })
3264    ] });
3265  }
3266};
3267const ScreenshotPreviewRenderer = {
3268  displayName: "Screenshot Preview",
3269  progressLabel: (input) => {
3270    const reason = input == null ? void 0 : input.reason;
3271    return reason ? `Capturing: ${truncate(reason, 40)}…` : "Capturing screenshot…";
3272  },
3273  header: (input) => {
3274    const path = (input == null ? void 0 : input.path) ?? "/";
3275    const viewport = (input == null ? void 0 : input.viewport) ?? "both";
3276    const viewportLabel = viewport === "both" ? "desktop + mobile" : viewport;
3277    return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-700", children: [
3278      path,
3279      /* @__PURE__ */ jsxRuntimeExports.jsxs(DimLabel, { children: [
3280        " · ",
3281        viewportLabel
3282      ] })
3283    ] });
3284  },
3285  result: ({
3286    output
3287  }) => {
3288    let parsed = output;
3289    if (typeof parsed === "string") {
3290      try {
3291        parsed = JSON.parse(parsed);
3292      } catch {
3293      }
3294    }
3295    const parts = Array.isArray(parsed) ? parsed : parsed && typeof parsed === "object" && "content" in parsed ? parsed.content : null;
3296    if (!Array.isArray(parts)) return null;
3297    const items = [];
3298    let pendingCaption = null;
3299    const resolveImageSrc = (p) => {
3300      const src = p.source;
3301      if ((src == null ? void 0 : src.type) === "url" && typeof src.url === "string") return src.url;
3302      if ((src == null ? void 0 : src.type) === "base64" && src.data && src.media_type) {
3303        return `data:${src.media_type};base64,${src.data}`;
3304      }
3305      const data = p.data;
3306      if (typeof data === "string") {
3307        const media = p.mediaType ?? p.media_type ?? "image/png";
3308        return `data:${media};base64,${data}`;
3309      }
3310      return null;
3311    };
3312    for (const p of parts) {
3313      if ((p == null ? void 0 : p.type) === "text" && typeof p.text === "string") {
3314        if (pendingCaption !== null) {
3315          items.push({
3316            kind: "caption-only",
3317            text: pendingCaption
3318          });
3319        }
3320        pendingCaption = p.text;
3321      } else if ((p == null ? void 0 : p.type) === "image") {
3322        const src = resolveImageSrc(p);
3323        if (src === null) continue;
3324        if (pendingCaption !== null) {
3325          items.push({
3326            kind: "pair",
3327            text: pendingCaption,
3328            src
3329          });
3330          pendingCaption = null;
3331        } else {
3332          items.push({
3333            kind: "image-only",
3334            src
3335          });
3336        }
3337      }
3338    }
3339    if (pendingCaption !== null) {
3340      items.push({
3341        kind: "caption-only",
3342        text: pendingCaption
3343      });
3344    }
3345    if (items.length === 0) return null;
3346    return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-2", children: items.map((item, i) => {
3347      if (item.kind === "caption-only") {
3348        return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[11px] text-gray-600", children: truncate(item.text, 240) }, i);
3349      }
3350      if (item.kind === "image-only") {
3351        return /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: item.src, alt: "Preview screenshot", className: "max-w-full rounded border border-gray-200" }, i);
3352      }
3353      return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1", children: [
3354        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[11px] text-gray-600", children: truncate(item.text, 240) }),
3355        /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: item.src, alt: "Preview screenshot", className: "max-w-full rounded border border-gray-200" })
3356      ] }, i);
3357    }) });
3358  }
3359};
3360const PublishWebsiteRenderer = {
3361  displayName: "Publish Website",
3362  progressLabel: () => "Publishing website…",
3363  hideDefaultInput: true,
3364  header: () => null
3365};
3366const UnpublishWebsiteRenderer = {
3367  displayName: "Unpublish Website",
3368  progressLabel: () => "Unpublishing website…",
3369  hideDefaultInput: true,
3370  header: () => null
3371};
3372const ListUserWebsitesAndDomainsRenderer = {
3373  displayName: "My Sites & Domains",
3374  progressLabel: () => "Listing your websites and domains…",
3375  hideDefaultInput: true,
3376  header: () => null,
3377  result: ({
3378    output
3379  }) => {
3380    const data = unwrapMcpJson(output);
3381    if (!data || typeof data === "string") {
3382      const text = asString(output);
3383      return text ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[11px] text-gray-600", children: truncate(text, 200) }) : null;
3384    }
3385    const owned = data.ownedWebsites || [];
3386    const member = data.memberWebsites || [];
3387    const domains = data.ownedDomains || [];
3388    const MAX = 5;
3389    const pluralize = (n, s) => `${n} ${s}${n === 1 ? "" : "s"}`;
3390    return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1 text-[11px] text-gray-700", children: [
3391      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-gray-500", children: [
3392        pluralize(owned.length, "owned website"),
3393        " · ",
3394        pluralize(member.length, "shared website"),
3395        " · ",
3396        pluralize(domains.length, "domain")
3397      ] }),
3398      owned.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-0.5", children: [
3399        /* @__PURE__ */ jsxRuntimeExports.jsx(DimLabel, { children: "Owned:" }),
3400        owned.slice(0, MAX).map((w, i) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "pl-2", children: [
3401          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-gray-900", children: w.name || "(unnamed)" }),
3402          w.previewUrl && /* @__PURE__ */ jsxRuntimeExports.jsxs(DimLabel, { children: [
3403            " · ",
3404            w.previewUrl
3405          ] })
3406        ] }, i)),
3407        owned.length > MAX && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pl-2", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(DimLabel, { children: [
3408          "…and ",
3409          owned.length - MAX,
3410          " more"
3411        ] }) })
3412      ] }),
3413      member.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-0.5", children: [
3414        /* @__PURE__ */ jsxRuntimeExports.jsx(DimLabel, { children: "Shared:" }),
3415        member.slice(0, MAX).map((w, i) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "pl-2", children: [
3416          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-gray-900", children: w.name || "(unnamed)" }),
3417          w.memberRole && /* @__PURE__ */ jsxRuntimeExports.jsxs(DimLabel, { children: [
3418            " · ",
3419            w.memberRole
3420          ] }),
3421          w.previewUrl && /* @__PURE__ */ jsxRuntimeExports.jsxs(DimLabel, { children: [
3422            " · ",
3423            w.previewUrl
3424          ] })
3425        ] }, i)),
3426        member.length > MAX && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pl-2", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(DimLabel, { children: [
3427          "…and ",
3428          member.length - MAX,
3429          " more"
3430        ] }) })
3431      ] }),
3432      domains.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-0.5", children: [
3433        /* @__PURE__ */ jsxRuntimeExports.jsx(DimLabel, { children: "Domains:" }),
3434        domains.slice(0, MAX).map((d, i) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "pl-2", children: [
3435          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-gray-900", children: d.domainName || "(unknown)" }),
3436          d.verificationStatus && /* @__PURE__ */ jsxRuntimeExports.jsxs(DimLabel, { children: [
3437            " · ",
3438            d.verificationStatus
3439          ] })
3440        ] }, i)),
3441        domains.length > MAX && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pl-2", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(DimLabel, { children: [
3442          "…and ",
3443          domains.length - MAX,
3444          " more"
3445        ] }) })
3446      ] })
3447    ] });
3448  }
3449};
3450const toolRenderers = {
3451  Read: ReadRenderer,
3452  Write: WriteRenderer,
3453  Edit: EditRenderer,
3454  MultiEdit: MultiEditRenderer,
3455  Glob: GlobRenderer,
3456  Grep: GrepRenderer,
3457  Bash: BashRenderer,
3458  WebFetch: WebFetchRenderer,
3459  WebSearch: WebSearchRenderer,
3460  AskUserQuestion: AskUserQuestionRenderer,
3461  "mcp__landingsite-docs__search_docs": SearchDocsRenderer,
3462  mcp__landingsite__get_publishing_status: GetPublishingStatusRenderer,
3463  mcp__landingsite__get_website_info: GetWebsiteInfoRenderer,
3464  mcp__landingsite__get_domain_info: GetDomainInfoRenderer,
3465  mcp__landingsite__list_user_websites_and_domains: ListUserWebsitesAndDomainsRenderer,
3466  mcp__landingsite__create_form: CreateFormRenderer,
3467  mcp__landingsite__show_view: ShowViewRenderer,
3468  mcp__landingsite__search_for_images: SearchForImagesRenderer,
3469  mcp__landingsite__screenshot_preview: ScreenshotPreviewRenderer,
3470  mcp__landingsite__publish_website: PublishWebsiteRenderer,
3471  mcp__landingsite__unpublish_website: UnpublishWebsiteRenderer
3472};
3473function getToolRenderer(name) {
3474  return toolRenderers[name];
3475}
3476const MIN_INFLIGHT_MS = 500;
3477const expandedToolCallIds = /* @__PURE__ */ new Set();
3478function getToolName$1(type) {
3479  return type.replace(/^tool-/, "");
3480}
3481const BUILT_IN_TOOL_NAMES = /* @__PURE__ */ new Set(["Read", "Write", "Edit", "MultiEdit", "Glob", "Grep", "Bash", "WebFetch", "WebSearch", "Task", "TodoWrite", "NotebookEdit", "BashOutput", "KillShell"]);
3482function humanizeToolName(name) {
3483  if (name.startsWith("mcp__")) {
3484    const segments = name.split("__");
3485    const toolPart = segments[segments.length - 1];
3486    return toolPart.split("_").filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
3487  }
3488  if (BUILT_IN_TOOL_NAMES.has(name)) return name;
3489  const spaced = name.replace(/([a-z0-9])([A-Z])/g, "$1 $2");
3490  return spaced.charAt(0).toUpperCase() + spaced.slice(1);
3491}
3492function formatOutput(output) {
3493  if (output === void 0 || output === null) return "";
3494  if (typeof output === "string") return output;
3495  try {
3496    return JSON.stringify(output, null, 2);
3497  } catch {
3498    return String(output);
3499  }
3500}
3501function cleanErrorText(text) {
3502  const match = text.match(/^<tool_use_error>([\s\S]*)<\/tool_use_error>$/);
3503  return match ? match[1].trim() : text;
3504}
3505function ToolRow({
3506  part
3507}) {
3508  var _a;
3509  const toolName = getToolName$1(part.type);
3510  const renderer = getToolRenderer(toolName);
3511  const displayName = (renderer == null ? void 0 : renderer.displayName) ?? humanizeToolName(toolName);
3512  const actuallyInFlight = part.state === "input-streaming" || part.state === "input-available";
3513  const isError = part.state === "output-error";
3514  const errorCandidate = part.errorText && part.errorText.trim() || formatOutput(part.output).trim();
3515  const rawErrorText = isError ? errorCandidate || `${displayName} failed but no error details were returned by the tool.` : null;
3516  const errorMessage = rawErrorText ? cleanErrorText(rawErrorText) : null;
3517  const [minDurationElapsed, setMinDurationElapsed] = reactExports.useState(false);
3518  reactExports.useEffect(() => {
3519    const t = setTimeout(() => setMinDurationElapsed(true), MIN_INFLIGHT_MS);
3520    return () => clearTimeout(t);
3521  }, []);
3522  const isInFlight = actuallyInFlight || !isError && !minDurationElapsed;
3523  const isSuccess = !isInFlight && part.state === "output-available";
3524  const [isExpanded, setIsExpandedState] = reactExports.useState(() => expandedToolCallIds.has(part.toolCallId));
3525  const setIsExpanded = (next) => {
3526    setIsExpandedState((prev) => {
3527      const value = typeof next === "function" ? next(prev) : next;
3528      if (value) expandedToolCallIds.add(part.toolCallId);
3529      else expandedToolCallIds.delete(part.toolCallId);
3530      return value;
3531    });
3532  };
3533  const ToolGlyph = getToolIcon(toolName);
3534  const icon = isInFlight ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "h-[15px] w-[15px] shrink-0 animate-spin text-blue-600" }) : isError ? /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-[15px] w-[15px] shrink-0 text-red-500" }) : ToolGlyph ? /* @__PURE__ */ jsxRuntimeExports.jsx(ToolGlyph, { className: "h-[15px] w-[15px] shrink-0 text-gray-400" }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex h-[15px] w-[15px] shrink-0 items-center justify-center", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "h-[5px] w-[5px] rounded-full bg-gray-300" }) });
3535  const header = (renderer == null ? void 0 : renderer.header(part.input)) ?? null;
3536  const progressLabel = isInFlight && ((_a = renderer == null ? void 0 : renderer.progressLabel) == null ? void 0 : _a.call(renderer, part.input));
3537  const rendererResult = isSuccess && (renderer == null ? void 0 : renderer.result) ? renderer.result({
3538    input: part.input,
3539    output: part.output
3540  }) : null;
3541  const hasRendererResult = rendererResult !== null && rendererResult !== void 0;
3542  const showDefaultOutput = !hasRendererResult && !isInFlight && (isError || part.output !== void 0 && part.output !== null);
3543  const showDefaultInput = part.input !== void 0 && part.input !== null && (!(renderer == null ? void 0 : renderer.hideDefaultInput) || !hasRendererResult);
3544  return (
3545    // Quiet activity-log row: no heavy border/box chrome. Error rows use
3546    // red text/hover so they stand out without a full red card.
3547    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cn("group relative text-[13.5px]", isError && "text-red-700"), children: [
3548      /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { type: "button", onClick: () => setIsExpanded((v) => !v), className: cn("flex w-full cursor-pointer items-center gap-[9px] rounded-md px-1.5 py-1 text-left font-mono", "hover:bg-[#f5f6f8] active:bg-gray-100", isError && "hover:bg-red-50/60"), children: [
3549        icon,
3550        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("font-semibold", isError ? "text-red-700" : "text-gray-600"), children: displayName }),
3551        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("min-w-0 flex-1 truncate", isError ? "text-red-500" : isInFlight ? "text-gray-500" : "text-gray-400"), children: progressLabel || header }),
3552        /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: cn("h-3.5 w-3.5 shrink-0 text-gray-300 transition-transform", isExpanded && "rotate-90 text-gray-400") })
3553      ] }),
3554      isExpanded && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-0.5 rounded bg-gray-50 px-2.5 py-1.5 text-xs", children: [
3555        hasRendererResult ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: rendererResult }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
3556          showDefaultInput && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-1.5", children: [
3557            /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-0.5 text-[10px] uppercase tracking-wide text-gray-400", children: "Input" }),
3558            /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "max-h-48 overflow-auto whitespace-pre-wrap break-all rounded bg-white p-1.5 font-mono text-[11px] text-gray-800", children: JSON.stringify(part.input, null, 2) })
3559          ] }),
3560          showDefaultOutput && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
3561            /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: cn("mb-0.5 text-[10px] uppercase tracking-wide", isError ? "text-red-500" : "text-gray-400"), children: isError ? "Error" : "Output" }),
3562            /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: cn("max-h-48 overflow-auto whitespace-pre-wrap break-all rounded p-1.5 font-mono text-[11px]", isError ? "bg-red-50 text-red-700" : "bg-white text-gray-800"), children: isError ? errorMessage : formatOutput(part.output) })
3563          ] })
3564        ] }),
3565        hasRendererResult && isError && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-1.5", children: [
3566          /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-0.5 text-[10px] uppercase tracking-wide text-red-500", children: "Error" }),
3567          /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "max-h-48 overflow-auto whitespace-pre-wrap break-all rounded bg-red-50 p-1.5 font-mono text-[11px] text-red-700", children: errorMessage })
3568        ] })
3569      ] })
3570    ] })
3571  );
3572}
3573function getToolName(type) {
3574  return type.replace(/^tool-/, "");
3575}
3576function partHint(part) {
3577  var _a, _b;
3578  const name = getToolName(part.type);
3579  if (name === "Read") {
3580    const p = (_a = part.input) == null ? void 0 : _a.file_path;
3581    return p ? stripHome(p) : null;
3582  }
3583  const pattern = (_b = part.input) == null ? void 0 : _b.pattern;
3584  return pattern ?? null;
3585}
3586function CollapsedReadSearchRow({
3587  parts
3588}) {
3589  const hasError = parts.length > 0 && parts.every((p) => p.state === "output-error");
3590  const anyInFlight = parts.some((p) => p.state === "input-streaming" || p.state === "input-available");
3591  const [isExpanded, setIsExpanded] = reactExports.useState(false);
3592  const reads = parts.filter((p) => p.type === "tool-Read").length;
3593  const searches = parts.length - reads;
3594  const RollupGlyph = reads > 0 && searches === 0 ? BookOpen : Search;
3595  const icon = hasError ? /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-[15px] w-[15px] shrink-0 text-red-500" }
3595) : anyInFlight ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "h-[15px] w-[15px] shrink-0 animate-spin text-blue-600" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(RollupGlyph, { className: "h-[15px] w-[15px] shrink-0 text-gray-400" });
3596  const label = reads > 0 && searches > 0 ? `Read ${reads} and searched ${searches}` : reads > 0 ? `Read ${reads} file${reads === 1 ? "" : "s"}` : `${searches} search${searches === 1 ? "" : "es"}`;
3597  const preview = parts.map(partHint).find((h) => !!h) ?? null;
3598  return (
3599    // Quiet rollup row — no border/box, matches ToolRow chrome.
3600    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cn("group relative text-[13.5px]", hasError && "text-red-700"), children: [
3601      /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { type: "button", onClick: () => setIsExpanded((v) => !v), className: cn("flex w-full cursor-pointer items-center gap-2 rounded-md px-1.5 py-1 text-left font-mono", "hover:bg-[#f5f6f8] active:bg-gray-100", hasError && "hover:bg-red-50/60"), children: [
3602        icon,
3603        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("font-semibold", hasError ? "text-red-700" : "text-gray-600"), children: label }),
3604        preview && !isExpanded && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 flex-1 truncate text-gray-400", children: preview }),
3605        /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: cn("ml-auto h-3.5 w-3.5 shrink-0 text-gray-300 transition-transform", isExpanded && "rotate-90 text-gray-400") })
3606      ] }),
3607      isExpanded && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-0.5 space-y-0 rounded bg-gray-50 px-2 py-1", children: parts.map((part, i) => /* @__PURE__ */ jsxRuntimeExports.jsx(ToolRow, { part: {
3608        type: part.type,
3609        toolCallId: part.toolCallId || `rollup-${i}`,
3610        state: part.state || "input-available",
3611        input: part.input,
3612        output: part.output,
3613        errorText: part.errorText
3614      } }, part.toolCallId || `rollup-${i}`)) })
3615    ] })
3616  );
3617}
3618const GROUPABLE = /* @__PURE__ */ new Set(["tool-Read", "tool-Glob", "tool-Grep"]);
3619const MIN_GROUP_SIZE = 2;
3620function groupReadSearchParts(parts) {
3621  const groups = [];
3622  let run = [];
3623  let runStart = 0;
3624  const flushRun = () => {
3625    if (run.length === 0) return;
3626    if (run.length >= MIN_GROUP_SIZE) {
3627      groups.push({
3628        kind: "collapsed",
3629        parts: run,
3630        startIndex: runStart
3631      });
3632    } else {
3633      run.forEach((part, i) => groups.push({
3634        kind: "single",
3635        part,
3636        index: runStart + i
3637      }));
3638    }
3639    run = [];
3640  };
3641  parts.forEach((part, i) => {
3642    if (part.type && GROUPABLE.has(part.type)) {
3643      if (run.length === 0) runStart = i;
3644      run.push(part);
3645    } else {
3646      flushRun();
3647      groups.push({
3648        kind: "single",
3649        part,
3650        index: i
3651      });
3652    }
3653  });
3654  flushRun();
3655  return groups;
3656}
3657function formatDuration$1(ms) {
3658  if (ms < 1e3) return `${ms}ms`;
3659  const secs = ms / 1e3;
3660  if (secs < 60) return `${secs.toFixed(1)}s`;
3661  const mins = Math.floor(secs / 60);
3662  const rem = Math.floor(secs % 60);
3663  return `${mins}m ${rem}s`;
3664}
3665function ThinkingRow({
3666  part
3667}) {
3668  const isInFlight = part.thinkingDurationMs === -1;
3669  const text = part.text ?? "";
3670  const [isExpanded, setIsExpanded] = reactExports.useState(false);
3671  if (isInFlight) return null;
3672  if (text.length === 0) return null;
3673  const label = part.thinkingDurationMs && part.thinkingDurationMs > 0 ? `Worked for ${formatDuration$1(part.thinkingDurationMs)}` : "Worked";
3674  return (
3675    // Quiet activity-log row matching ToolRow chrome — no border/box.
3676    // Resolved-state: text + chevron only, muted (gray-400), no leading icon
3677    // and no horizontal rule — the prototype's "Worked for Ns ›" treatment.
3678    // Tight spacing (py-0.5) so the collapsed header sits close to the prose
3679    // it precedes.
3680    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "group relative text-sm", children: [
3681      /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { type: "button", onClick: () => setIsExpanded((v) => !v), className: "flex w-full cursor-pointer items-center gap-1.5 rounded-md px-1.5 py-0.5 text-left hover:bg-[#f5f6f8] active:bg-gray-100", children: [
3682        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-gray-400", children: label }),
3683        /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: cn("ml-0.5 h-3.5 w-3.5 shrink-0 text-gray-300 transition-transform", isExpanded && "rotate-90 text-gray-400") })
3684      ] }),
3685      isExpanded && text.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-0.5 rounded bg-gray-50 px-3 py-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: cn("prose prose-sm prose-neutral max-w-none text-[12px]", "italic text-gray-600"), children: /* @__PURE__ */ jsxRuntimeExports.jsx(Markdown, { remarkPlugins: [remarkGfm], children: text }) }) })
3686    ] })
3687  );
3688}
3689function FaviconIcon({
3690  hostname
3691}) {
3692  const [status, setStatus] = reactExports.useState("loading");
3693  const src = `https://www.google.com/s2/favicons?domain=${hostname}&sz=64`;
3694  return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex shrink-0 items-center", style: {
3695    width: 14,
3696    height: 14
3697  }, children: [
3698    status !== "loaded" && /* @__PURE__ */ jsxRuntimeExports.jsx(Globe, { "aria-hidden": "true", className: "h-[14px] w-[14px] text-gray-500" }),
3699    status !== "error" && /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src, alt: "", referrerPolicy: "no-referrer", onLoad: () => setStatus("loaded"), onError: () => setStatus("error"), className: "rounded-[3px]", style: {
3700      width: 14,
3701      height: 14,
3702      display: status === "loaded" ? "inline-block" : "none"
3703    } })
3704  ] });
3705}
3706const markdownComponents = {
3707  // Absolute http(s) links: favicon-or-globe icon + blue link text, new tab.
3708  // Relative/anchor links (#…): rendered as plain inline text to avoid broken
3709  // navigation inside the chat panel.
3710  a({
3711    href,
3712    children
3713  }) {
3714    const isAbsolute = href && /^https?:\/\//i.test(href);
3715    if (!isAbsolute) {
3716      return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-blue-600", children });
3717    }
3718    let hostname = "";
3719    try {
3720      hostname = new URL(href).hostname;
3721    } catch {
3722    }
3723    return /* @__PURE__ */ jsxRuntimeExports.jsxs("a", { href, target: "_blank", rel: "noreferrer", className: "inline-flex items-baseline gap-1 font-medium text-blue-600 hover:underline", children: [
3724      hostname && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "inline-flex translate-y-[2px] items-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx(FaviconIcon, { hostname }) }),
3725      children
3726    ] });
3727  },
3728  // Inline code: light gray-100 chip with monospace font so tool/skill names
3729  // read as chips. react-markdown v9+ removed the `inline` prop, so we detect
3730  // inline vs. block ourselves: fenced blocks carry a `language-*` className,
3731  // and any block code spans newlines. Everything else is inline → chip.
3732  code({
3733    className,
3734    children,
3735    ...props
3736  }) {
3737    const isFenced = typeof className === "string" && /\blanguage-/.test(className);
3738    const hasNewline = /\n/.test(Array.isArray(children) ? children.join("") : String(children ?? ""));
3739    if (!isFenced && !hasNewline) {
3740      return /* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "rounded-[5px] bg-gray-100 px-1.5 py-px font-mono text-[0.85em] text-gray-700 before:content-none after:content-none", children });
3741    }
3742    return /* @__PURE__ */ jsxRuntimeExports.jsx("code", { className, ...props, children });
3743  },
3744  // Section headings — pinned to the prototype's flat treatment (15px / 700,
3745  // near-black, 16px top / 8px bottom margin) instead of riding the prose-sm
3746  // heading scale, which renders them too small and only semibold.
3747  h1: ({
3748    children
3749  }) => /* @__PURE__ */ jsxRuntimeExports.jsx("h1", { className: "mb-2 mt-4 text-[16px] font-bold text-gray-900", children }),
3750  h2: ({
3751    children
3752  }) => /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "mb-2 mt-4 text-[15px] font-bold text-gray-900", children }),
3753  h3: ({
3754    children
3755  }) => /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "mb-2 mt-4 text-[15px] font-bold text-gray-900", children }),
3756  h4: ({
3757    children
3758  }) => /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "mb-2 mt-4 text-[15px] font-bold text-gray-900", children })
3759};
3760function renderGroup(group, keyPrefix) {
3761  if (group.kind === "collapsed") {
3762    return /* @__PURE__ */ jsxRuntimeExports.jsx(CollapsedReadSearchRow, { parts: group.parts }, `${keyPrefix}rollup-${group.startIndex}`);
3763  }
3764  const part = group.part;
3765  const index = group.index;
3766  if (part.type === "text" && part.text) {
3767    return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "message-part-text", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Markdown, { remarkPlugins: [remarkGfm], components: markdownComponents, children: part.text }) }, `${keyPrefix}text-${index}`);
3768  }
3769  if (part.type === "thinking") {
3770    return /* @__PURE__ */ jsxRuntimeExports.jsx(ThinkingRow, { part: {
3771      type: "thinking",
3772      text: part.text,
3773      thinkingDurationMs: part.thinkingDurationMs
3774    } }, `${keyPrefix}thinking-${index}`);
3775  }
3776  if (typeof part.type === "string" && part.type.startsWith("tool-")) {
3777    return /* @__PURE__ */ jsxRuntimeExports.jsx(ToolRow, { part: {
3778      type: part.type,
3779      toolCallId: part.toolCallId || `${index}`,
3780      state: part.state || "input-available",
3781      input: part.input,
3782      output: part.output
3783    } }, `${keyPrefix}tool-${part.toolCallId || index}`);
3784  }
3785  return null;
3786}
3787function isActivityGroup(group) {
3788  if (group.kind === "collapsed") return true;
3789  const {
3790    part
3791  }
3791 = group;
3792  if (part.type === "thinking") return true;
3793  if (typeof part.type === "string" && part.type.startsWith("tool-")) return true;
3794  return false;
3795}
3796function renderSandboxPartsWithReadGrouping(parts, keyPrefix = "") {
3797  const renderGroups = groupReadSearchParts(parts);
3798  const segments = [];
3799  let currentRun = null;
3800  let currentRunStart = 0;
3801  const flushRun = () => {
3802    if (currentRun && currentRun.length > 0) {
3803      segments.push({
3804        kind: "activity-run",
3805        groups: currentRun,
3806        startIdx: currentRunStart
3807      });
3808      currentRun = null;
3809    }
3810  };
3811  renderGroups.forEach((group, i) => {
3812    if (isActivityGroup(group)) {
3813      if (!currentRun) {
3814        currentRun = [];
3815        currentRunStart = i;
3816      }
3817      currentRun.push(group);
3818    } else {
3819      flushRun();
3820      segments.push({
3821        kind: "text-group",
3822        group,
3823        idx: i
3824      });
3825    }
3826  });
3827  flushRun();
3828  return segments.map((segment) => {
3829    if (segment.kind === "text-group") {
3830      return renderGroup(segment.group, keyPrefix);
3831    }
3832    const runKey = `${keyPrefix}run-${segment.startIdx}`;
3833    return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "my-2", children: segment.groups.map((g) => renderGroup(g, keyPrefix)) }, runKey);
3834  });
3835}
3836const PREVIEW_COUNT = 3;
3837function deriveDescription(input) {
3838  if (!input) return "exploring";
3839  const desc = input.description;
3840  if (typeof desc === "string" && desc.trim().length > 0) return desc.trim();
3841  const prompt = input.prompt;
3842  if (typeof prompt === "string" && prompt.trim().length > 0) {
3843    const firstLine2 = prompt.trim().split("\n")[0] ?? "";
3844    if (firstLine2.length > 0) return firstLine2;
3845  }
3846  const sub = input.subagent_type;
3847  if (typeof sub === "string" && sub.trim().length > 0) return sub.trim();
3848  return "exploring";
3849}
3850function formatDuration(ms) {
3851  if (!ms || ms <= 0) return "";
3852  const totalSec = Math.round(ms / 1e3);
3853  if (totalSec < 60) return `${totalSec}s`;
3854  const min = Math.floor(totalSec / 60);
3855  const sec = totalSec % 60;
3856  return sec === 0 ? `${min}m` : `${min}m ${sec}s`;
3857}
3858function formatTokens(n) {
3859  if (!n || n <= 0) return "";
3860  if (n >= 1e3) {
3861    const k = (n / 1e3).toFixed(1).replace(/\.0$/, "");
3862    return `${k}k tokens`;
3863  }
3864  return `${n} tokens`;
3865}
3866function ExploreRow({
3867  agentPart,
3868  childParts
3869}) {
3870  const description = deriveDescription(agentPart.input);
3871  const agentOutput = agentPart.agentOutput;
3872  const isDone = agentPart.state === "output-available";
3873  const isCompleted = isDone && (agentOutput == null ? void 0 : agentOutput.status) === "completed";
3874  const isError = agentPart.state === "output-error";
3875  const isRunning = !isDone && !isError;
3876  const [isExpanded, setIsExpanded] = reactExports.useState(false);
3877  const toolChildren = childParts.filter((p) => typeof p.type === "string" && p.type.startsWith("tool-"));
3878  const totalToolCount = (agentOutput == null ? void 0 : agentOutput.totalToolUseCount) ?? toolChildren.length;
3879  const overflowCount = Math.max(0, toolChildren.length - PREVIEW_COUNT);
3880  const previewParts = toolChildren.slice(-3);
3881  const headerIcon = isError ? /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-[15px] w-[15px] text-red-500" }
3881) : isRunning ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "h-[15px] w-[15px] animate-spin text-blue-600" }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex h-[15px] w-[15px] items-center justify-center", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "h-[5px] w-[5px] rounded-full bg-gray-300" }) });
3882  const footerPieces = [];
3883  if (isDone && totalToolCount > 0) {
3884    footerPieces.push(`${totalToolCount} tool use${totalToolCount === 1 ? "" : "s"}`);
3885    if (agentOutput) {
3886      const tokensStr = formatTokens(agentOutput.totalTokens);
3887      if (tokensStr) footerPieces.push(tokensStr);
3888      const durStr = formatDuration(agentOutput.totalDurationMs);
3889      if (durStr) footerPieces.push(durStr);
3890    }
3891  }
3892  return (
3893    // Quiet Explore container — drop the heavy purple border/box chrome.
3894    // A subtle left rail is applied by the renderParts wrapper around the
3895    // whole activity run. The Explore group itself gets a faint left
3896    // accent to distinguish nested children from top-level rows.
3897    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cn("group relative text-[13.5px]", isError && "text-red-700"), "data-explore-row": true, "data-explore-state": isCompleted ? "done" : isError ? "error" : "running", children: [
3898      /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { type: "button", onClick: () => setIsExpanded((v) => !v), className: cn("flex w-full cursor-pointer items-center gap-2 rounded-md px-1.5 py-1 text-left font-mono", "hover:bg-[#f5f6f8] active:bg-gray-100", isError && "hover:bg-red-50/60"), children: [
3899        headerIcon,
3900        /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: cn("font-semibold", isError ? "text-red-700" : "text-gray-600"), children: [
3901          "Explore(",
3902          description,
3903          ")"
3904        ] }),
3905        /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: cn("ml-auto h-3.5 w-3.5 shrink-0 text-gray-300 transition-transform", isExpanded && "rotate-90 text-gray-400") })
3906      ] }),
3907      !isExpanded && !isError && previewParts.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ml-7 space-y-0", children: [
3908        renderSandboxPartsWithReadGrouping(previewParts, "explore-prev-"),
3909        overflowCount > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "py-0.5 pl-2 text-xs italic text-gray-400", children: [
3910          "+",
3911          overflowCount,
3912          " more tool use",
3913          overflowCount === 1 ? "" : "s"
3914        ] })
3915      ] }),
3916      isDone && !isExpanded && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pl-9 py-0.5 text-gray-400 italic", children: footerPieces.length > 0 ? `Done (${footerPieces.join(" · ")})` : "Done" }),
3917      isError && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pl-9 py-0.5 text-red-500 italic", children: "Explore failed" }),
3918      (isExpanded || isError) && childParts.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ml-7 space-y-0", children: renderSandboxPartsWithReadGrouping(childParts, "explore-full-") })
3919    ] })
3920  );
3921}
3922function groupByParentAgent(parts) {
3923  const out = [];
3924  const openAgents = /* @__PURE__ */ new Map();
3925  let topBuffer = [];
3926  const flushTop = () => {
3927    if (topBuffer.length === 0) return;
3928    out.push({
3929      kind: "top",
3930      parts: topBuffer
3931    });
3932    topBuffer = [];
3933  };
3934  for (const part of parts) {
3935    if (part.type === "tool-Agent" && part.toolCallId) {
3936      flushTop();
3937      out.push({
3938        kind: "agent",
3939        agentPart: part,
3940        children: []
3941      });
3942      openAgents.set(part.toolCallId, out.length - 1);
3943      continue;
3944    }
3945    const parent = part.parentToolUseId;
3946    if (parent) {
3947      const idx = openAgents.get(parent);
3948      if (idx !== void 0) {
3949        const group = out[idx];
3950        if (group.kind === "agent") {
3951          group.children.push(part);
3952          continue;
3953        }
3954      }
3955    }
3956    topBuffer.push(part);
3957  }
3958  flushTop();
3959  return out;
3960}
3961function settleStaleToolSpinners(parts) {
3962  let lastTextIdx = -1;
3963  for (let i = parts.length - 1; i >= 0; i--) {
3964    const p = parts[i];
3965    if (p.type === "text" && (p.text || "").trim().length > 0) {
3966      lastTextIdx = i;
3967      break;
3968    }
3969  }
3970  if (lastTextIdx <= 0) return parts;
3971  let changed = false;
3972  const next = parts.map((p, i) => {
3973    if (i < lastTextIdx && typeof p.type === "string" && p.type.startsWith("tool-") && p.type !== "tool-Agent" && !p.parentToolUseId && (p.state === "input-available" || p.state === "input-streaming")) {
3974      changed = true;
3975      return {
3976        ...p,
3977        state: "output-available"
3978      };
3979    }
3980    return p;
3981  });
3982  return changed ? next : parts;
3983}
3984function extractText(parts) {
3985  return parts.filter((p) => p.type === "text" && typeof p.text === "string").map((p) => p.text).join("");
3986}
3987function extractPickerSummary(rawText) {
3988  if (!rawText.includes("Selected element HTML:")) return null;
3989  const match = rawText.match(/Selected element HTML:\s*```[^\n]*\n([\s\S]*?)\n```/);
3990  if (!match) return null;
3991  const html = match[1].trim();
3992  const tagMatch = html.match(/^<([a-zA-Z][a-zA-Z0-9-]*)/);
3993  if (!tagMatch) return null;
3994  const tag = tagMatch[1].toLowerCase();
3995  const plain = html.replace(/<[^>]*>/g, " ").replace(/\s+/g, " ").trim();
3996  const preview = plain.length > 40 ? plain.slice(0, 40).trimEnd() + "…" : plain;
3997  return {
3998    tag,
3999    preview
4000  };
4001}
4002function UserMessage({
4003  message,
4004  stackPosition = "solo",
4005  onRestore,
4006  isRestoring,
4007  isAIResponding
4008}) {
4009  var _a, _b, _c, _d, _e;
4010  const preMessageCommitHash = (_a = message.metadata) == null ? void 0 : _a.preMessageCommitHash;
4011  const showRestoreButton = onRestore && preMessageCommitHash && !isAIResponding;
4012  const rawText = extractText(message.parts);
4013  const pickerSummary = extractPickerSummary(rawText);
4014  const displayText = rawText.replace(/<context for the AI>[\s\S]*?<\/context for the AI>\s*/g, "").trim();
4015  const attachedMedia = ((_b = message.metadata) == null ? void 0 : _b.userUploadedMedia) ?? [];
4016  const attachedMediaTypes = ((_c = message.metadata) == null ? void 0 : _c.galleryMediaTypes) ?? [];
4017  const attachedMediaPreviews = ((_d = message.metadata) == null ? void 0 : _d.userUploadedMediaPreviews) ?? [];
4018  const attachedMediaNames = ((_e = message.metadata) == null ? void 0 : _e.userUploadedMediaNames) ?? [];
4019  const hasAttachedContext = !!pickerSummary || attachedMedia.length > 0;
4020  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative flex w-fit min-w-0 max-w-full flex-col items-end gap-1.5", "data-role": "user", "data-message-id": message.id, children: [
4021    showRestoreButton && /* @__PURE__ */ jsxRuntimeExports.jsxs(Button, { variant: "outline", size: "sm", className: cn("absolute -bottom-3 right-2 z-10 h-6 rounded-full border-gray-200 bg-white px-3 text-xs shadow-sm hover:bg-gray-50", isRestoring && "cursor-not-allowed opacity-50"), onClick: () => !isRestoring && onRestore(message.id, preMessageCommitHash), disabled: isRestoring, children: [
4022      /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { className: "mr-1 h-3 w-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3 10h10a8 8 0 018 8v2M3 10l6 6m-6-6l6-6" }) }),
4023      "Restore"
4024    ] }),
4025    hasAttachedContext && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex w-fit max-w-full flex-col gap-2 rounded-[16px] border border-gray-300 bg-white px-3 py-2.5", children: [
4026      pickerSummary && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "inline-flex w-fit max-w-full items-center gap-1.5 text-xs font-medium text-gray-600", "aria-label": pickerSummary.preview ? `Attached element: ${friendlyElementNoun(pickerSummary.tag)} '${pickerSummary.preview}'` : `Attached element: ${friendlyElementNoun(pickerSummary.tag)}`, children: [
4027        /* @__PURE__ */ jsxRuntimeExports.jsx(MousePointerClick, { className: "h-3.5 w-3.5 shrink-0 text-gray-400", "aria-hidden": true }),
4028        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", children: formatFriendlyLabel(pickerSummary.tag, pickerSummary.preview) })
4029      ] }),
4030      attachedMedia.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-wrap gap-2", children: attachedMedia.map((src, idx) => {
4031        var _a2, _b2;
4032        const mediaType = attachedMediaTypes[idx];
4033        const isVideo = mediaType === "video" || mediaType === "lottie";
4034        const isPdf = src.endsWith(".pdf") || src.includes(".pdf?") || ((_a2 = attachedMediaNames[idx]) == null ? void 0 : _a2.toLowerCase().endsWith(".pdf"));
4035        const isModel = src.endsWith(".glb") || src.includes(".glb?") || ((_b2 = attachedMediaNames[idx]) == null ? void 0 : _b2.toLowerCase().endsWith(".glb"));
4036        if (isVideo) {
4037          return /* @__PURE__ */ jsxRuntimeExports.jsx("video", { src: attachedMediaPreviews[idx] || src, autoPlay: true, loop: true, muted: true, playsInline: true, className: "h-24 rounded border border-gray-200 bg-black/5" }, src + idx);
4038        }
4039        if (isPdf || isModel) {
4040          const Icon = isModel ? Box : FileText;
4041          return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex h-24 w-20 flex-col items-center justify-center rounded border border-gray-200 bg-muted px-2", children: [
4042            /* @__PURE__ */ jsxRuntimeExports.jsx(Icon, { className: "h-7 w-7 text-muted-foreground" }),
4043            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "mt-1 w-full truncate text-center text-[10px] text-muted-foreground", children: attachedMediaNames[idx] || (isModel ? "3D model" : "PDF") })
4044          ] }, src + idx);
4045        }
4046        return /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src, alt: `attachment ${idx + 1}`, className: "h-24 rounded border border-gray-200" }, src + idx);
4047      }) })
4048    ] }),
4049    displayText && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: cn("flex min-w-0 max-w-full flex-col overflow-x-auto bg-[#f1f1f3] px-[15px] py-[9px] text-[#2a2d31]", getChatBubbleRadiusClass("user", stackPosition), "prose prose-sm prose-neutral break-words text-[15px] dark:prose-invert"), children: /* @__PURE__ */ jsxRuntimeExports.jsx(Markdown, { remarkPlugins: [remarkGfm], children: displayText }) })
4050  ] });
4051}
4052function AssistantMessage({
4053  message
4054}) {
4055  if (!message.parts || message.parts.length === 0) {
4056    return null;
4057  }
4058  const visibleParts = settleStaleToolSpinners(message.parts.filter((p) => p.type !== "tool-TodoWrite"));
4059  if (visibleParts.length === 0) {
4060    return null;
4061  }
4062  const hasAnyContent = visibleParts.some((p) => {
4063    if (p.type === "text") return (p.text || "").length > 0;
4064    return true;
4065  });
4066  if (!hasAnyContent) {
4067    return null;
4068  }
4069  const outerGroups = groupByParentAgent(visibleParts);
4070  return (
4071    // Assistant turns render as document flow directly on the panel surface —
4072    // no bg-muted enclosure. Full width, left-aligned.
4073    /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex w-full flex-col", "data-role": "assistant", "data-message-id": message.id, children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "prose prose-sm prose-neutral max-w-none break-words px-1 py-1 text-pretty text-[15px] leading-[1.55] dark:prose-invert", children: outerGroups.map((group, groupIdx) => {
4074      if (group.kind === "agent") {
4075        return /* @__PURE__ */ jsxRuntimeExports.jsx(ExploreRow, { agentPart: group.agentPart, childParts: group.children }, `explore-${group.agentPart.toolCallId || groupIdx}`);
4076      }
4077      return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Fragment, { children: renderSandboxPartsWithReadGrouping(group.parts, `g${groupIdx}-`) }, `top-${groupIdx}`);
4078    }) }) })
4079  );
4080}
4081const SandboxChatMessage = reactExports.memo(function SandboxChatMessage2(props) {
4082  const {
4083    message
4084  } = props;
4085  if (message.role === "user") {
4086    return /* @__PURE__ */ jsxRuntimeExports.jsx(UserMessage, { ...props });
4087  }
4088  if (message.role === "assistant") {
4089    return /* @__PURE__ */ jsxRuntimeExports.jsx(AssistantMessage, { message });
4090  }
4091  return null;
4092});
4093function SandboxWaitingIndicator() {
4094  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex w-full flex-col", "data-role": "assistant", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center px-1 py-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-shimmer text-sm font-medium", children: "Thinking" }) }) });
4095}
4096const TICK_INTERVAL_MS = 250;
4097const ELAPSED_BADGE_MIN_MS = 2e3;
4098const CHARS_PER_TOKEN = 4;
4099function formatElapsed(ms) {
4100  if (ms < 1e3) return `${ms}ms`;
4101  const secs = ms / 1e3;
4102  if (secs < 60) return `${secs.toFixed(1)}s`;
4103  const mins = Math.floor(secs / 60);
4104  const remSecs = Math.floor(secs % 60);
4105  return `${mins}m ${remSecs}s`;
4106}
4107function ThinkingIndicator({
4108  thinking
4109}) {
4110  const [, setTick] = reactExports.useState(0);
4111  reactExports.useEffect(() => {
4112    if (!(thinking == null ? void 0 : thinking.active)) return;
4113    const id = setInterval(() => setTick((n) => n + 1), TICK_INTERVAL_MS);
4114    return () => clearInterval(id);
4115  }, [thinking == null ? void 0 : thinking.active]);
4116  if (!(thinking == null ? void 0 : thinking.active)) return null;
4117  const now = Date.now();
4118  const elapsedMs = now - thinking.startedAt;
4119  const showElapsed = elapsedMs >= ELAPSED_BADGE_MIN_MS;
4120  const tokens = Math.round(thinking.chars / CHARS_PER_TOKEN);
4121  const labelText = showElapsed ? `Working for ${formatElapsed(elapsedMs)}` : "Thinking…";
4122  return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
4123    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mx-4 flex items-center gap-2 px-1 py-1 text-xs", children: [
4124      /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-shimmer text-sm font-medium tabular-nums", children: labelText }),
4125      tokens > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "tabular-nums text-gray-400", children: [
4126        "· ~",
4127        tokens.toLocaleString(),
4128        " tokens"
4129      ] })
4130    ] }),
4131    /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mx-4 mb-3 mt-1 h-px bg-gray-200/70" })
4132  ] });
4133}
4134const RECENTLY_COMPLETED_TTL_MS = 3e4;
4135const MAX_VISIBLE_ROWS = 10;
4136function parseTodos(input) {
4137  const todos = input == null ? void 0 : input.todos;
4138  if (!Array.isArray(todos)) return null;
4139  const parsed = todos.filter((t) => typeof t === "object" && t !== null && typeof t.content === "string" && ["pending", "in_progress", "completed"].includes(t.status));
4140  return parsed.length > 0 ? parsed : null;
4141}
4142function getLatestTodos(messages) {
4143  let lastUserIdx = -1;
4144  for (let i = messages.length - 1; i >= 0; i--) {
4145    if (messages[i].role === "user") {
4146      lastUserIdx = i;
4147      break;
4148    }
4149  }
4150  for (let i = messages.length - 1; i > lastUserIdx; i--) {
4151    const msg = messages[i];
4152    if (msg.role !== "assistant" || !msg.parts) continue;
4153    for (let j = msg.parts.length - 1; j >= 0; j--) {
4154      const part = msg.parts[j];
4155      if ((part == null ? void 0 : part.type) === "tool-TodoWrite") {
4156        const todos = parseTodos(part.input);
4157        if (todos) return todos;
4158      }
4159    }
4160  }
4161  return null;
4162}
4163function useRecentlyCompleted(todos) {
4164  const completedAtRef = reactExports.useRef(/* @__PURE__ */ new Map());
4165  const initialSnapshotRef = reactExports.useRef(null);
4166  const [, forceRender] = reactExports.useState(0);
4167  const now = Date.now();
4168  const map = completedAtRef.current;
4169  if (todos) {
4170    if (initialSnapshotRef.current === null) {
4171      initialSnapshotRef.current = new Set(todos.filter((t) => t.status === "completed").map((t) => t.content));
4172    }
4173    const currentCompleted = new Set(todos.filter((t) => t.status === "completed").map((t) => t.content));
4174    for (const key of map.keys()) {
4175      if (!currentCompleted.has(key)) map.delete(key);
4176    }
4177    for (const key of currentCompleted) {
4178      if (!map.has(key) && !initialSnapshotRef.current.has(key)) {
4179        map.set(key, now);
4180      }
4181    }
4182  } else {
4183    map.clear();
4184    initialSnapshotRef.current = null;
4185  }
4186  let nextExpiry = Infinity;
4187  for (const ts of map.values()) {
4188    const expiresAt = ts + RECENTLY_COMPLETED_TTL_MS;
4189    if (expiresAt > now && expiresAt < nextExpiry) nextExpiry = expiresAt;
4190  }
4191  reactExports.useEffect(() => {
4192    if (nextExpiry === Infinity) return;
4193    const timeout = setTimeout(() => forceRender((n) => n + 1), Math.max(0, nextExpiry - Date.now()) + 50);
4194    return () => clearTimeout(timeout);
4195  }, [nextExpiry]);
4196  return (task) => {
4197    var _a;
4198    if (task.status !== "completed") return true;
4199    if ((_a = initialSnapshotRef.current) == null ? void 0 : _a.has(task.content)) return false;
4200    const completedAt = map.get(task.content);
4201    if (completedAt === void 0) return true;
4202    return now - completedAt < RECENTLY_COMPLETED_TTL_MS;
4203  };
4204}
4205function formatHeader(total, done, inProgress, open) {
4206  const parts = [`${done} done`, `${inProgress} in progress`, `${open} open`];
4207  return `${total} task${total === 1 ? "" : "s"} (${parts.join(", ")})`;
4208}
4209function TodoChecklist({
4210  messages
4211}) {
4212  const todos = getLatestTodos(messages);
4213  const isVisible = useRecentlyCompleted(todos);
4214  if (!todos) return null;
4215  const visible = todos.filter(isVisible).slice(0, MAX_VISIBLE_ROWS);
4216  if (visible.length === 0) return null;
4217  const done = todos.filter((t) => t.status === "completed").length;
4218  const inProgress = todos.filter((t) => t.status === "in_progress").length;
4219  const open = todos.filter((t) => t.status === "pending").length;
4220  return (
4221    // In-stream inline card: no shadow/backdrop-blur floating panel.
4222    // Subtle border + barely-there bg, consistent with the quiet activity-log
4223    // aesthetic from Phase 2 and the SystemCard family from Phase 3.
4224    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mx-4 mb-2 rounded-md border border-gray-100 bg-gray-50/60 px-3 py-2", children: [
4225      /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-1.5", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "tabular-nums text-[10px] font-semibold uppercase tracking-wide text-gray-400", children: formatHeader(todos.length, done, inProgress, open) }) }),
4226      /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { className: "space-y-1 text-[12px]", children: visible.map((todo, i) => {
4227        const isDone = todo.status === "completed";
4228        const isActive = todo.status === "in_progress";
4229        const label = isActive && todo.activeForm ? todo.activeForm : todo.content;
4230        return /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { className: "flex items-start gap-2 leading-snug", children: [
4231          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "mt-px flex h-3.5 w-3.5 shrink-0 items-center justify-center", "aria-hidden": true, children: isDone ? (
4232            // Done items recede — a muted check, no green.
4233            /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "h-3.5 w-3.5 text-gray-400", strokeWidth: 2.5 })
4234          ) : isActive ? (
4235            // The one live item keeps a restrained blue (the chat's
4236            // in-flight accent) — a small, subtle box, not the old sky.
4237            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "h-2 w-2 rounded-[2px] bg-blue-500" })
4238          ) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "h-2.5 w-2.5 rounded-[3px] border-[1.5px] border-gray-300" }) }),
4239          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("flex-1", isDone && "text-gray-400 line-through", isActive && "font-medium text-gray-900", !isDone && !isActive && "text-gray-600"), children: label })
4240        ] }, i);
4241      }) })
4242    ] })
4243  );
4244}
4245const cardContainerClasses = {
4246  info: "border-gray-200 bg-gray-50/70",
4247  "pending-action": "border-amber-200/80 bg-amber-50/40",
4248  success: "border-gray-200 bg-gray-50/70",
4249  warning: "border-amber-200/70 bg-amber-50/30",
4250  danger: "border-red-200/80 bg-red-50/40"
4251};
4252const iconClasses = {
4253  info: "text-gray-500",
4254  "pending-action": "text-amber-500",
4255  success: "text-emerald-500",
4256  warning: "text-amber-500",
4257  danger: "text-red-500"
4258};
4259const titleClasses = {
4260  info: "text-gray-900",
4261  "pending-action": "text-gray-900",
4262  success: "text-gray-900",
4263  warning: "text-gray-900",
4264  danger: "text-gray-900"
4265};
4266const bodyClasses = {
4267  info: "text-gray-600",
4268  "pending-action": "text-gray-600",
4269  success: "text-gray-600",
4270  warning: "text-gray-600",
4271  danger: "text-gray-600"
4272};
4273const lineContainerClasses = {
4274  info: "border-gray-200 bg-gray-50/70 text-gray-600",
4275  "pending-action": "border-amber-200/80 bg-amber-50/40 text-gray-700",
4276  success: "border-gray-200 bg-gray-50/70 text-gray-600",
4277  warning: "border-amber-200/70 bg-amber-50/30 text-gray-700",
4278  danger: "border-red-200/80 bg-red-50/40 text-gray-700"
4279};
4280const dismissClasses = {
4281  info: "text-gray-400 hover:text-gray-600",
4282  "pending-action": "text-gray-400 hover:text-gray-600",
4283  success: "text-gray-400 hover:text-gray-600",
4284  warning: "text-gray-400 hover:text-gray-600",
4285  danger: "text-gray-400 hover:text-gray-600"
4286};
4287function SystemCard({
4288  accent,
4289  icon,
4290  title,
4291  children,
4292  actions,
4293  className
4294}) {
4295  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: cn$1("mx-4 rounded-lg border p-4 state-card-fade", cardContainerClasses[accent], className), children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-3", children: [
4296    icon && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn$1("mt-0.5 flex-shrink-0", iconClasses[accent]), children: icon }),
4297    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1", children: [
4298      title && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: cn$1("text-sm font-medium", titleClasses[accent]), children: title }),
4299      children && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: cn$1("text-sm", title ? "mt-1" : "", bodyClasses[accent]), children }),
4300      actions && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-3", children: actions })
4301    ] })
4302  ] }) });
4303}
4304function SystemLine({
4305  accent,
4306  children,
4307  onDismiss,
4308  className
4309}) {
4310  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cn$1("mx-4 flex items-start gap-2 rounded-lg border p-2 text-sm state-card-fade", lineContainerClasses[accent], className), children: [
4311    /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1", children }),
4312    onDismiss && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", onClick: onDismiss, "aria-label": "Dismiss", className: cn$1("flex-shrink-0", dismissClasses[accent]), children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "h-4 w-4" }) })
4313  ] });
4314}
4315function AskUserQuestionCard({
4316  pendingQuestion,
4317  onSubmit
4318}) {
4319  const {
4320    questions,
4321    interactionId
4322  } = pendingQuestion;
4323  const [currentIdx, setCurrentIdx] = reactExports.useState(0);
4324  const [answers, setAnswers] = reactExports.useState({});
4325  const [multiSelections, setMultiSelections] = reactExports.useState({});
4326  const [otherText, setOtherText] = reactExports.useState({});
4327  const [showOtherInput, setShowOtherInput] = reactExports.useState({});
4328  const [isSubmitting, setIsSubmitting] = reactExports.useState(false);
4329  const question = questions[currentIdx];
4330  const isLast = currentIdx === questions.length - 1;
4331  const allAnswered = questions.every((q) => answers[q.question]);
4332  const handleSelect = reactExports.useCallback((q, label) => {
4333    if (q.multiSelect) {
4334      const current = new Set(multiSelections[q.question] || []);
4335      if (current.has(label)) {
4336        current.delete(label);
4337      } else {
4338        current.add(label);
4339      }
4340      setMultiSelections((prev) => ({
4341        ...prev,
4342        [q.question]: current
4343      }));
4344      if (current.size > 0) {
4345        setAnswers((prev) => ({
4346          ...prev,
4347          [q.question]: Array.from(current).join(", ")
4348        }));
4349      } else {
4350        setAnswers((prev) => {
4351          const copy = {
4352            ...prev
4353          };
4354          delete copy[q.question];
4355          return copy;
4356        });
4357      }
4358      setShowOtherInput((prev) => ({
4359        ...prev,
4360        [q.question]: false
4361      }));
4362    } else {
4363      setAnswers((prev) => ({
4364        ...prev,
4365        [q.question]: label
4366      }));
4367      setShowOtherInput((prev) => ({
4368        ...prev,
4369        [q.question]: false
4370      }));
4371      if (!isLast) {
4372        setTimeout(() => setCurrentIdx((i) => i + 1), 150);
4373      }
4374    }
4375  }, [isLast, multiSelections]);
4376  const handleOtherSubmit = reactExports.useCallback((q) => {
4377    const text = (otherText[q.question] || "").trim();
4378    if (!text) return;
4379    setAnswers((prev) => ({
4380      ...prev,
4381      [q.question]: text
4382    }));
4383    setShowOtherInput((prev) => ({
4384      ...prev,
4385      [q.question]: false
4386    }));
4387    if (!isLast) {
4388      setTimeout(() => setCurrentIdx((i) => i + 1), 150);
4389    }
4390  }, [otherText, isLast]);
4391  const handleSubmitAll = reactExports.useCallback(async () => {
4392    if (isSubmitting) return;
4393    setIsSubmitting(true);
4394    try {
4395      await onSubmit(interactionId, answers);
4396    } finally {
4397      setIsSubmitting(false);
4398    }
4399  }, [interactionId, answers, onSubmit, isSubmitting]);
4400  const selectedForCurrent = question.multiSelect ? multiSelections[question.question] || /* @__PURE__ */ new Set() : new Set(answers[question.question] ? [answers[question.question]] : []);
4401  return /* @__PURE__ */ jsxRuntimeExports.jsxs(SystemCard, { accent: "info", children: [
4402    questions.length >
4402 1 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-3 flex items-center gap-1", children: questions.map((q, i) => /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { type: "button", onClick: () => setCurrentIdx(i), className: cn$1("flex items-center gap-1 rounded-full px-2.5 py-1 text-xs font-medium transition-colors", i === currentIdx ? "bg-blue-600 text-white" : answers[q.question] ? "bg-blue-200 text-blue-800" : "bg-white text-gray-600 hover:bg-gray-100"), children: [
4403      answers[q.question] && i !== currentIdx && /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "h-3 w-3" }),
4404      q.header || `Q${i + 1}`
4405    ] }, i)) }),
4406    /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mb-3 text-sm font-medium text-gray-900", children: question.question }),
4407    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-3 space-y-2", children: [
4408      question.options.map((opt) => {
4409        const isSelected = selectedForCurrent.has(opt.label);
4410        return /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { type: "button", onClick: () => handleSelect(question, opt.label), className: cn$1("flex w-full items-start gap-3 rounded-lg border p-3 text-left transition-colors", isSelected ? "border-blue-400 bg-blue-100" : "border-gray-200 bg-white hover:border-blue-300 hover:bg-blue-50/50"), children: [
4411          /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: cn$1("mt-0.5 flex h-4 w-4 flex-shrink-0 items-center justify-center rounded border", question.multiSelect ? "rounded" : "rounded-full", isSelected ? "border-blue-600 bg-blue-600" : "border-gray-300"), children: isSelected && /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "h-3 w-3 text-white" }) }),
4412          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 flex-1", children: [
4413            /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-medium text-gray-900", children: opt.label }),
4414            opt.description && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-0.5 text-xs text-gray-500", children: opt.description })
4415          ] })
4416        ] }, opt.label);
4417      }),
4418      showOtherInput[question.question] ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-lg border border-gray-300 bg-white p-3", children: [
4419        /* @__PURE__ */ jsxRuntimeExports.jsx("input", { type: "text", className: "w-full rounded border border-gray-200 px-2 py-1.5 text-sm focus:border-blue-400 focus:outline-none", placeholder: "Type your answer…", value: otherText[question.question] || "", onChange: (e) => setOtherText((prev) => ({
4420          ...prev,
4421          [question.question]: e.target.value
4422        })), onKeyDown: (e) => {
4423          if (e.key === "Enter") handleOtherSubmit(question);
4424          if (e.key === "Escape") setShowOtherInput((prev) => ({
4425            ...prev,
4426            [question.question]: false
4427          }));
4428        }, autoFocus: true }),
4429        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2 flex gap-2", children: [
4430          /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { size: "sm", onClick: () => handleOtherSubmit(question), disabled: !(otherText[question.question] || "").trim(), children: "Confirm" }),
4431          /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { size: "sm", variant: "ghost", onClick: () => setShowOtherInput((prev) => ({
4432            ...prev,
4433            [question.question]: false
4434          })), children: "Cancel" })
4435        ] })
4436      ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { type: "button", onClick: () => setShowOtherInput((prev) => ({
4437        ...prev,
4438        [question.question]: true
4439      })), className: "flex w-full items-center gap-3 rounded-lg border border-dashed border-gray-200 p-3 text-left text-sm text-gray-500 transition-colors hover:border-blue-300 hover:text-gray-700", children: [
4440        /* @__PURE__ */ jsxRuntimeExports.jsx(MessageSquare, { className: "h-4 w-4 flex-shrink-0" }),
4441        "Other…"
4442      ] })
4443    ] }),
4444    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
4445      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
4446        currentIdx > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(Button, { size: "sm", variant: "ghost", onClick: () => setCurrentIdx((i) => i - 1), children: [
4447          /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronLeft, { className: "mr-1 h-3 w-3" }),
4448          "Back"
4449        ] }),
4450        !isLast && answers[question.question] && /* @__PURE__ */ jsxRuntimeExports.jsxs(Button, { size: "sm", variant: "ghost", onClick: () => setCurrentIdx((i) => i + 1), children: [
4451          "Next",
4452          /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "ml-1 h-3 w-3" })
4453        ] })
4454      ] }),
4455      (isLast || allAnswered) && /* @__PURE__ */ jsxRuntimeExports.jsxs(Button, { size: "sm", onClick: handleSubmitAll, disabled: !allAnswered || isSubmitting, children: [
4456        isSubmitting && /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "mr-1.5 h-3 w-3 animate-spin" }),
4457        isSubmitting ? "Sending…" : "Submit answers"
4458      ] })
4459    ] })
4460  ] });
4461}
4462function SelectedElementChip({
4463  selectedElement,
4464  onClear
4465}) {
4466  if (!selectedElement) {
4467    return null;
4468  }
4469  const {
4470    tag,
4471    textPreview
4472  } = selectedElement;
4473  const hasPreview = textPreview !== "";
4474  const noun = friendlyElementNoun(tag);
4475  const label = formatFriendlyLabel(tag, textPreview);
4476  const ariaLabel = hasPreview ? `Selected ${noun} '${textPreview}'` : `Selected ${noun}`;
4477  const handleKeyDown = (event) => {
4478    if (event.key === "Backspace" || event.key === "Delete") {
4479      event.preventDefault();
4480      onClear();
4481    }
4482  };
4483  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { role: "button", tabIndex: 0, "aria-label": ariaLabel, onKeyDown: handleKeyDown, className: cn$1(
4484    // White carded chip, min-height so very-narrow chips don't collapse;
4485    // hard max-width so long text previews truncate instead of spanning
4486    // the composer.
4487    "inline-flex min-h-[28px] max-w-[220px] items-center gap-1.5 rounded-[12px]",
4488    "border border-[#1B1A22]/[0.08] bg-white px-2.5 py-1 text-xs text-foreground",
4489    "shadow-[0_1px_2px_rgba(27,26,34,0.06)]",
4490    "focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1"
4491  ), children: [
4492    /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", children: label }),
4493    /* @__PURE__ */ jsxRuntimeExports.jsx(
4494      Button,
4495      {
4496        type: "button",
4497        size: "icon",
4498        variant: "ghost",
4499        "aria-label": "Remove selection",
4500        onClick: onClear,
4501        className: "h-6 w-6 shrink-0 rounded-full p-0 text-muted-foreground hover:bg-background hover:text-foreground",
4502        children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "h-3 w-3" })
4503      }
4504    )
4505  ] });
4506}
4507function ComposerAttachmentTray({
4508  selectedElement,
4509  images,
4510  onClearSelection,
4511  onRemoveImage
4512}) {
4513  const hasAttachments = Boolean(selectedElement) || images.length > 0;
4514  const rowRef = reactExports.useRef(null);
4515  const [areaHeight, setAreaHeight] = reactExports.useState(0);
4516  reactExports.useLayoutEffect(() => {
4517    if (!hasAttachments) {
4518      setAreaHeight(0);
4519      return;
4520    }
4521    const row = rowRef.current;
4522    if (!row) {
4523      return;
4524    }
4525    const measure = () => setAreaHeight(row.scrollHeight);
4526    measure();
4527    if (typeof ResizeObserver === "undefined") {
4528      return;
4529    }
4530    const ro = new ResizeObserver(measure);
4531    ro.observe(row);
4532    return () => ro.disconnect();
4533  }, [hasAttachments, images.length, selectedElement]);
4534  return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
4535    /* @__PURE__ */ jsxRuntimeExports.jsx("div", { "aria-hidden": true, className: cn("composer-tray-bg", hasAttachments && "is-expanded") }),
4536    /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: cn("composer-chip-area", hasAttachments && "is-open"), style: {
4537      height: areaHeight
4538    }, "aria-hidden": !hasAttachments, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { ref: rowRef, className: "composer-chip-row flex flex-col gap-2 px-2 pb-2 pt-1.5", children: [
4539      selectedElement && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-wrap items-start gap-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "composer-chip-enter", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectedElementChip, { selectedElement, onClear: onClearSelection }) }) }),
4540      images.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-wrap items-start gap-2", children: images.map((item) => {
4541        var _a, _b, _c, _d, _e, _f, _g, _h;
4542        const isGetty = item.galleryMediaSource === "iStock";
4543        return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "composer-chip-enter relative shrink-0", children: [
4544          item.galleryMediaType === "video" || item.galleryMediaType === "lottie" ? /* @__PURE__ */ jsxRuntimeExports.jsx("video", { src: item.imagePreview, className: "h-14 w-14 rounded-[12px] border border-[#1B1A22]/[0.08] object-cover shadow-[0_1px_2px_rgba(27,26,34,0.06)]", autoPlay: true, loop: true, muted: true, playsInline: true, onContextMenu: isGetty ? (e) => e.preventDefault() : void 0 }) : ((_a = item.imageFile) == null ? void 0 : _a.type) === "application/pdf" ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex h-14 w-14 flex-col items-center justify-center rounded-[12px] border border-[#1B1A22]/[0.08] bg-white px-1 shadow-[0_1px_2px_rgba(27,26,34,0.06)]", children: [
4545            /* @__PURE__ */ jsxRuntimeExports.jsx(FileText, { className: "h-5 w-5 text-muted-foreground" }),
4546            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "mt-0.5 w-full truncate text-center text-[10px] text-muted-foreground", children: ((_b = item.imageFile) == null ? void 0 : _b.name) || "PDF" })
4547          ] }) : ((_d = (_c = item.imageFile) == null ? void 0 : _c.name) == null ? void 0 : _d.toLowerCase().endsWith(".glb")) ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex h-14 w-14 flex-col items-center justify-center rounded-[12px] border border-[#1B1A22]/[0.08] bg-white px-1 shadow-[0_1px_2px_rgba(27,26,34,0.06)]", children: [
4548            /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { className: "h-5 w-5 text-muted-foreground" }),
4549            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "mt-0.5 w-full truncate text-center text-[10px] text-muted-foreground", children: ((_e = item.imageFile) == null ? void 0 : _e.name) || "3D model" })
4550          ] }) : ((_f = item.imageFile) == null ? void 0 : _f.type) === "image/heic" || ((_g = item.imageFile) == null ? void 0 : _g.type) === "image/heif" ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex h-14 w-14 flex-col items-center justify-center rounded-[12px] border border-[#1B1A22]/[0.08] bg-white px-1 shadow-[0_1px_2px_rgba(27,26,34,0.06)]", children: [
4551            /* @__PURE__ */ jsxRuntimeExports.jsx(Image, { className: "h-5 w-5 text-muted-foreground" }),
4552            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "mt-0.5 w-full truncate text-center text-[10px] text-muted-foreground", children: ((_h = item.imageFile) == null ? void 0 : _h.name) || "HEIC" })
4553          ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: item.imagePreview, alt: "Preview", className: "h-14 w-14 rounded-[12px] border border-[#1B1A22]/[0.08] object-cover shadow-[0_1px_2px_rgba(27,26,34,0.06)]", onContextMenu: isGetty ? (e) => e.preventDefault() : void 0 }),
4554          item.error && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
4555            /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "absolute inset-0 flex cursor-default flex-col items-center justify-center rounded-[12px] bg-red-900/60", children: [
4556              /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-4 w-4 text-red-200" }),
4557              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "mt-0.5 px-0.5 text-center text-[10px] font-medium text-red-100", children: item.isFlagged ? "Not allowed" : "Error" })
4558            ] }) }),
4559            /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "max-w-xs text-sm", children: item.error }) })
4560          ] }) }),
4561          item.uploading ? /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { type: "button", className: "group absolute -right-1.5 -top-1.5 flex h-5 w-5 items-center justify-center rounded-full border border-[#1B1A22]/[0.08] bg-white shadow-sm hover:bg-muted", onClick: () => onRemoveImage(item.index), children: [
4562            /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "h-3 w-3 animate-spin text-muted-foreground group-hover:hidden" }),
4563            /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "hidden h-3 w-3 group-hover:block" })
4564          ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { type: "button", size: "icon", variant: "ghost", className: "absolute -right-1.5 -top-1.5 h-5 w-5 rounded-full border border-[#1B1A22]/[0.08] bg-white p-0 shadow-sm hover:bg-muted", onClick: () => onRemoveImage(item.index), children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "h-3 w-3" }) })
4565        ] }, item.index);
4566      }) })
4567    ] }) })
4568  ] });
4569}
4570const trayShellClasses = {
4571  danger: "border-red-200/80 bg-red-50/80",
4572  warning: "border-amber-200/80 bg-amber-50/70",
4573  info: "border-gray-200/90 bg-slate-50/95"
4574};
4575const bubbleBorderClasses = {
4576  danger: "border-red-200/75 text-red-950",
4577  warning: "border-amber-200/75 text-amber-950",
4578  info: "border-gray-200/85 text-gray-800"
4579};
4580const actionClasses = {
4581  danger: "text-red-700 hover:text-red-800",
4582  warning: "text-amber-700 hover:text-amber-800",
4583  info: "text-gray-700 hover:text-gray-900"
4584};
4585function NoticeTray({
4586  notice,
4587  children
4588}) {
4589  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { role: "group", "aria-live": notice.severity === "info" ? "polite" : "assertive", className: cn("state-card-fade rounded-[14px] border shadow-[0_1px_2px_rgba(27,26,34,0.04),0_12px_30px_-20px_rgba(27,26,34,0.16)]", trayShellClasses[notice.severity]), children: [
4590    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-2.5 px-3 pb-2.5 pt-2", children: [
4591      /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "mt-px flex-shrink-0", children: notice.icon }),
4592      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 flex-1", children: [
4593        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-2", children: [
4594          /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "min-w-0 flex-1 text-[13px] font-medium leading-5 text-gray-900", children: notice.title }),
4595          (notice.onMinimize || notice.onDismiss) && // Both controls live here, not just minimize: a dismissible
4596          // notice whose body says "dismiss this" is a dead end without
4597          // an X, and the tray is where the body is actually read. The
4598          // shared wrapper carries the edge offsets so a notice offering
4599          // only one of them still sits flush with the corner.
4600          /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "-mr-1 -mt-0.5 flex flex-shrink-0 items-center", children: [
4601            notice.onMinimize && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", "aria-label": "Minimize", title: "Minimize", onClick: notice.onMinimize, className: "rounded p-1 text-gray-400 transition-colors hover:text-gray-600", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronUp, { className: "h-3.5 w-3.5" }) }),
4602            notice.onDismiss && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", "aria-label": "Dismiss", title: "Dismiss", onClick: notice.onDismiss, className: "rounded p-1 text-gray-400 transition-colors hover:text-gray-600", children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "h-3.5 w-3.5" }) })
4603          ] })
4604        ] }),
4605        notice.body && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-0.5 text-[13px] leading-5 text-gray-600", children: notice.body }),
4606        notice.action && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { size: "sm", variant: "outline", className: "h-7 px-3 text-xs", onClick: notice.action.onClick, disabled: notice.action.disabled, children: notice.action.label }) })
4607      ] })
4608    ] }),
4609    /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "relative -mx-px -mb-px", children })
4610  ] });
4611}
4612function NoticeBubble({
4613  notice,
4614  delayMs
4615}) {
4616  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: {
4617    animationDelay: `${delayMs}ms`
4618  }, className: cn("notice-bubble-enter flex items-center gap-2.5 rounded-[12px] border bg-white/95 px-3.5 py-2 text-[13px]", "shadow-[0_1px_2px_rgba(27,26,34,0.05),0_8px_20px_-14px_rgba(27,26,34,0.16)]", bubbleBorderClasses[notice.severity]), children: [
4619    /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex shrink-0 items-center", children: notice.icon }),
4620    notice.onRestore ? /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", onClick: notice.onRestore, "aria-label": "Show details", title: "Show details", className: "min-w-0 flex-1 truncate text-left hover:underline", children: notice.title }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 flex-1 truncate", children: notice.title }),
4621    notice.action && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", onClick: notice.action.onClick, disabled: notice.action.disabled, className: cn("shrink-0 font-medium hover:underline disabled:cursor-not-allowed disabled:text-gray-400 disabled:no-underline", actionClasses[notice.severity]), children: notice.action.label }),
4622    notice.onDismiss && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
4623      notice.action && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { "aria-hidden": true, className: "h-3.5 w-px shrink-0 bg-gray-200" }),
4624      /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", "aria-label": "Dismiss", onClick: notice.onDismiss, className: "shrink-0 text-gray-400 transition-colors hover:text-gray-600", children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "h-3.5 w-3.5" }) })
4625    ] })
4626  ] });
4627}
4628function ComposerNoticeStack({
4629  tray,
4630  bubbles,
4631  children
4632}) {
4633  const visualBubbles = [...bubbles].reverse();
4634  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2", children: [
4635    visualBubbles.map((notice, visualIndex) => /* @__PURE__ */ jsxRuntimeExports.jsx(NoticeBubble, { notice, delayMs: visualIndex * 60 }, notice.id)),
4636    tray ? /* @__PURE__ */ jsxRuntimeExports.jsx(NoticeTray, { notice: tray, children }) : children
4637  ] });
4638}
4639const SEVERITY_RANK = {
4640  danger: 3,
4641  warning: 2,
4642  info: 1
4643};
4644const seqFor = (map, id) => map.get(id) ?? 0;
4645function pickTrayAndBubbles(notices, minimizedIds) {
4646  if (notices.length === 0) return {
4647    tray: null,
4648    bubbles: []
4649  };
4650  const byActivation = (a, b) => b.activatedSeq - a.activatedSeq;
4651  const trayCandidates = minimizedIds && minimizedIds.size > 0 ? notices.filter((notice) => !minimizedIds.has(notice.id)) : notices;
4652  if (trayCandidates.length === 0) {
4653    return {
4654      tray: null,
4655      bubbles: [...notices].sort(byActivation)
4656    };
4657  }
4658  const sortedForTray = [...trayCandidates].sort((a, b) => {
4659    const severityDelta = SEVERITY_RANK[b.severity] - SEVERITY_RANK[a.severity];
4660    if (severityDelta !== 0) return severityDelta;
4661    return b.activatedSeq - a.activatedSeq;
4662  });
4663  const tray = sortedForTray[0];
4664  const bubbles = notices.filter((notice) => notice.id !== tray.id).sort(byActivation);
4665  return {
4666    tray,
4667    bubbles
4668  };
4669}
4670function getActiveComposerNoticeIds({
4671  isOutOfCredits,
4672  isSessionExpired,
4673  viteError,
4674  sessionLostNotice,
4675  needsPaymentsSetup,
4676  needsPaymentsUpgrade,
4677  paymentsDisabled,
4678  commerceSetup,
4679  postageUncharged,
4680  currencyRestated
4681}) {
4682  return [isOutOfCredits ? "out-of-credits" : null, isSessionExpired ? "session-expired" : null, viteError ? "vite-error" : null, sessionLostNotice ? "session-lost" : null, needsPaymentsSetup || needsPaymentsUpgrade || paymentsDisabled || (commerceSetup == null ? void 0 : commerceSetup.paymentState) === "ACTIVE" && commerceSetup.payoutState !== "ACTIVE" ? "payments-setup" : null, postageUncharged ? "postage-uncharged" : null, currencyRestated ? "currency-restated" : null].filter((id) => id !== null);
4683}
4684function currencyLabel(code) {
4685  const upper = code.toUpperCase();
4686  try {
4687    const name = new Intl.DisplayNames(["en"], {
4688      type: "currency"
4689    }).of(upper);
4690    return !name || name === upper ? upper : `${upper} (${name})`;
4691  } catch {
4692    return upper;
4693  }
4694}
4695function paymentsNoticeCopy(args) {
4696  const owner = args.canStartPaymentsOnboarding;
4697  if (owner && !args.needsPaymentsUpgrade && args.commerceSetup) {
4698    return commerceSetupCopy(args.commerceSetup);
4699  }
4700  if (args.paymentsDisabled) {
4701    return {
4702      title: args.paymentsForInvoicing ? "Invoices can’t be sent right now." : "Your store can’t take payments right now.",
4703      body: owner ? "Stripe has turned payments off for your account — usually a review or a missing document. Check your Str
4703ipe dashboard for what they need, or contact support if nothing is waiting there." : "Stripe has turned payments off for the site owner’s account. The owner needs to check their Stripe dashboard, or contact support."
4704    };
4705  }
4706  if (args.paymentsForInvoicing) {
4707    const title2 = "You can’t send invoices yet.";
4708    if (args.needsPaymentsUpgrade) {
4709      return {
4710        title: title2,
4711        body: owner ? "Invoicing is on the Pro plan. Upgrade and I can send the invoice you asked for." : "Invoicing is on the Pro plan — the site’s owner can upgrade to switch it on."
4712      };
4713    }
4714    if (!owner) {
4715      return {
4716        title: title2,
4717        body: "Invoices are paid into the site owner’s Stripe account, which isn’t set up yet. The owner needs to set up payments — or transfer the site to you if you’re the one who should be paid."
4718      };
4719    }
4720    return {
4721      title: title2,
4722      body: args.paymentsPending ? "Your Stripe setup isn’t finished yet. Pick up where you left off — once Stripe confirms your account, ask me again and I’ll send the invoice." : "Connect Stripe to send invoices. It takes about five minutes — you’ll add your details with Stripe, who handle the payments, and what your clients pay goes straight to your own bank."
4723    };
4724  }
4725  const title = "Your store can’t take payments yet.";
4726  if (args.needsPaymentsUpgrade) {
4727    return {
4728      title,
4729      body: owner ? "You’ve added something to sell, but taking payments (and publishing your site) needs a paid plan. Upgrade and you can switch the buy buttons on." : "There’s something to sell here, but taking payments needs a paid plan — the site’s owner can upgrade to switch the buy buttons on."
4730    };
4731  }
4732  if (!owner) {
4733    return {
4734      title,
4735      body: "There’s something to sell here, but the buy buttons stay switched off until the site’s owner sets up a payment account."
4736    };
4737  }
4738  return {
4739    title,
4740    body: args.paymentsPending ? "Your Stripe setup isn’t finished yet. Pick up where you left off — once Stripe confirms your account, the buy buttons switch on." : "You’ve added something to sell, but the buy buttons stay switched off until you set up your payment account. It only takes a few minutes — you’ll add your details with Stripe, who handle the payments, and money from sales goes straight to your own bank."
4741  };
4742}
4743function buildComposerNotices(args) {
4744  var _a, _b, _c;
4745  const notices = [];
4746  if (args.isOutOfCredits) {
4747    notices.push({
4748      id: "out-of-credits",
4749      severity: "danger",
4750      icon: /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-[15px] w-[15px] text-red-500" }),
4751      title: "You've run out of chat credits.",
4752      action: {
4753        label: "Add 200 edits for $10",
4754        onClick: args.onAddCredits
4755      },
4756      activatedSeq: seqFor(args.activatedSeqById, "out-of-credits")
4757    });
4758  }
4759  if (args.isSessionExpired) {
4760    notices.push({
4761      id: "session-expired",
4762      severity: "warning",
4763      icon: /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-[15px] w-[15px] text-amber-500" }),
4764      title: "Your session needs to refresh.",
4765      body: args.hasBufferedMessage ? "Send a new message or click Try Again to continue." : "Send a new message to continue.",
4766      action: args.hasBufferedMessage ? {
4767        label: "Try Again",
4768        onClick: args.onTryAgain,
4769        disabled: args.actionDisabled
4770      } : void 0,
4771      activatedSeq: seqFor(args.activatedSeqById, "session-expired")
4772    });
4773  }
4774  if (args.viteError) {
4775    notices.push({
4776      id: "vite-error",
4777      severity: "warning",
4778      icon: /* @__PURE__ */ jsxRuntimeExports.jsx(TriangleAlert, { className: "h-[15px] w-[15px] text-amber-500" }),
4779      title: "Your website preview has an error",
4780      body: "The preview won't show your latest changes until it's fixed. You don't need to fix it yourself - just click the button below.",
4781      action: {
4782        label: "Have AI fix this",
4783        onClick: args.onFixVite,
4784        disabled: args.actionDisabled
4785      },
4786      activatedSeq: seqFor(args.activatedSeqById, "vite-error")
4787    });
4788  }
4789  if (args.needsPaymentsSetup || args.needsPaymentsUpgrade || args.paymentsDisabled || ((_a = args.commerceSetup) == null ? void 0 : _a.paymentState) === "ACTIVE" && args.commerceSetup.payoutState !== "ACTIVE") {
4790    const upgrade = args.needsPaymentsUpgrade;
4791    const stripeCopy = !upgrade && args.canStartPaymentsOnboarding && args.commerceSetup ? commerceSetupCopy(args.commerceSetup) : null;
4792    const copy = paymentsNoticeCopy(args);
4793    const title = args.commerceSetupRefreshError && !upgrade ? "We couldn’t check your Str
4793ipe status" : copy.title;
4794    const body = args.commerceSetupRefreshError && !upgrade ? "The last status may be out of date. Check again to find out whether Stripe needs more information or your account is ready." : copy.body;
4795    let action;
4796    if (args.commerceSetupRefreshError && !upgrade && args.onRefreshCommerceSetup) {
4797      action = {
4798        label: args.commerceSetupRefreshing ? "Checking Stripe…" : "Check status",
4799        onClick: args.onRefreshCommerceSetup,
4800        disabled: args.commerceSetupRefreshing
4801      };
4802    } else if (stripeCopy) {
4803      const onClick = {
4804        continue: args.onSetUpPayments,
4805        dashboard: args.onOpenStripeDashboard,
4806        refresh: args.onRefreshCommerceSetup,
4807        none: void 0,
4808        website: openCommerceWebsiteSetup
4809      }[stripeCopy.action];
4810      if (onClick) {
4811        action = {
4812          label: stripeCopy.action === "refresh" && args.commerceSetupRefreshing ? "Checking Stripe…" : stripeCopy.actionLabel,
4813          onClick,
4814          disabled: args.paymentsActionDisabled || args.commerceSetupRefreshing
4815        };
4816      }
4817    } else if (!args.paymentsDisabled && args.canStartPaymentsOnboarding) {
4818      action = upgrade ? {
4819        label: "View upgrade options",
4820        onClick: args.onUpgradePlan
4821      } : {
4822        label: args.paymentsPending ? "Continue Stripe setup" : "Connect with Stripe",
4823        onClick: args.onSetUpPayments,
4824        disabled: args.paymentsActionDisabled
4825      };
4826    }
4827    notices.push({
4828      id: "payments-setup",
4829      severity: "info",
4830      icon: args.paymentsForInvoicing ? /* @__PURE__ */ jsxRuntimeExports.jsx(FileText, { className: "h-[15px] w-[15px] text-blue-500" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(CreditCard, { className: "h-[15px] w-[15px] text-blue-500" }),
4831      title,
4832      body: stripeCopy || args.canStartPaymentsOnboarding && !upgrade ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
4833        body,
4834        /* @__PURE__ */ jsxRuntimeExports.jsx(CommerceSetupCheckedAt, { checkedAt: (_b = args.commerceSetup) == null ? void 0 : _b.checkedAt, refreshing: !!args.commerceSetupRefreshing })
4835      ] }) : body,
4836      action,
4837      ...args.paymentsNoticeMinimized ? {
4838        onRestore: args.onToggleMinimizePayments
4839      } : {
4840        onMinimize: args.onToggleMinimizePayments
4841      },
4842      activatedSeq: seqFor(args.activatedSeqById, "payments-setup")
4843    });
4844  }
4845  if (args.postageUncharged) {
4846    notices.push({
4847      id: "postage-uncharged",
4848      severity: "info",
4849      icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Truck, { className: "h-[15px] w-[15px] text-blue-500" }),
4850      title: "Delivery is free on every order.",
4851      body: "Your checkout asks buyers for a delivery address but doesn’t charge them anything to ship — so postage comes out of your own pocket on every sale. Tell me in the chat what flat rate you want to charge for delivery and I’ll set it up. If free delivery is deliberate, dismiss this.",
4852      onDismiss: args.onDismissPostage,
4853      activatedSeq: seqFor(args.activatedSeqById, "postage-uncharged")
4854    });
4855  }
4856  if (args.currencyRestated) {
4857    const to = args.currencyRestated.to.toUpperCase();
4858    const from = ((_c = args.currencyRestated.from) == null ? void 0 : _c.toUpperCase()) ?? null;
4859    notices.push({
4860      id: "currency-restated",
4861      severity: "warning",
4862      icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Banknote, { className: "h-[15px] w-[15px] text-amber-500" }),
4863      title: `Your prices are now in ${to}.`,
4864      // No worked example on purpose. "89 became 89" holds for usd->mxn but
4865      // lies for a move across decimal classes (usd->jpy takes 8900 minor
4866      // units from $89.00 to JPY 8900), and this notice exists precisely
4867      // because prices are already hard to eyeball. Describe the mechanism,
4868      // let them read their own numbers.
4869      // "follows your Stripe account" rather than "connecting Stripe": the
4870      // same push also fires on a later account.updated (a merchant changing
4871      // their Stripe country), and a merchant who connected weeks ago would
4872      // read the narrower wording as being about someone else.
4873      body: `This store's selling currency follows your Stripe account, and it just moved${from ? ` from ${from}` : ""} to ${currencyLabel(args.currencyRestated.to)}. Your amounts were carried straight across instead of being converted at an exchange rate, so every price now means something different from when you set it. Check they are still what you mean to charge — tell me the right ones in the chat and I will update them. Worth doing now: once a real order comes in, the currency is locked for good.`,
4874      onDismiss: args.onDismissCurrency,
4875      activatedSeq: seqFor(args.activatedSeqById, "currency-restated")
4876    });
4877  }
4878  if (args.sessionLostNotice) {
4879    notices.push({
4880      id: "session-lost",
4881      severity: "info",
4882      icon: /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "h-[15px] w-[15px] text-gray-500" }),
4883      title: args.sessionLostNotice,
4884      onDismiss: args.onDismissSessionLost,
4885      activatedSeq: seqFor(args.activatedSeqById, "session-lost")
4886    });
4887  }
4888  return notices;
4889}
4890function buildPickerContextSection({
4891  outerHTML,
4892  path,
4893  sourceLoc
4894}) {
4895  const loc = sourceLoc ? `
4896Source location (file:line:col): ${sourceLoc}
4897` : "";
4898  return `
4899User is on page with path "${path}"
4900
4901Selected element HTML:
4902\`\`\`
4903${outerHTML}
4904\`\`\`
4905${loc}`;
4906}
4907const TRUNCATED_COMMENT = " truncated ";
4908function collectDescendantsReverseDepthFirst(root) {
4909  const result = [];
4910  const stack = [];
4911  for (let i = root.childNodes.length - 1; i >= 0; i--) {
4912    stack.push(root.childNodes[i]);
4913  }
4914  while (stack.length > 0) {
4915    const node = stack.pop();
4916    result.push(node);
4917    if (node.nodeType === 1) {
4918      const el = node;
4919      for (let i = el.childNodes.length - 1; i >= 0; i--) {
4920        stack.push(el.childNodes[i]);
4921      }
4922    }
4923  }
4924  return result.reverse();
4925}
4926const textEncoder = new TextEncoder();
4927const byteLength = (s) => textEncoder.encode(s).length;
4928function truncateOuterHtml(html, capBytes = 2e5) {
4929  if (byteLength(html) <= capBytes) {
4930    return {
4931      html,
4932      truncated: false,
4933      rejected: false
4934    };
4935  }
4936  const doc = new DOMParser().parseFromString(html, "text/html");
4937  const root = doc.body.firstElementChild;
4938  if (!root) {
4939    return {
4940      html: "",
4941      truncated: false,
4942      rejected: true
4943    };
4944  }
4945  const descendants = collectDescendantsReverseDepthFirst(root);
4946  let firstRemoval = true;
4947  let truncated = false;
4948  for (const node of descendants) {
4949    if (!node.parentNode) continue;
4950    if (firstRemoval) {
4951      const comment = doc.createComment(TRUNCATED_COMMENT);
4952      node.parentNode.replaceChild(comment, node);
4953      firstRemoval = false;
4954    } else {
4955      node.parentNode.removeChild(node);
4956    }
4957    truncated = true;
4958    if (byteLength(root.outerHTML) <= capBytes) {
4959      return {
4960        html: root.outerHTML,
4961        truncated: true,
4962        rejected: false
4963      };
4964    }
4965  }
4966  if (byteLength(root.outerHTML) > capBytes) {
4967    return {
4968      html: "",
4969      truncated: false,
4970      rejected: true
4971    };
4972  }
4973  return {
4974    html: root.outerHTML,
4975    truncated,
4976    rejected: false
4977  };
4978}
4979function buildAgentMessage(snapshot, context) {
4980  var _a;
4981  const {
4982    text: messageText,
4983    images,
4984    selectedElement,
4985    currentPath
4986  } = snapshot;
4987  const {
4988    websitePlan,
4989    isAgencyUser,
4990    website,
4991    currentUserId,
4992    tokenMinutesLeft,
4993    isInitialCreation,
4994    generateId: generateId$1 = generateId
4995  } = context;
4996  const validImages = images == null ? void 0 : images.filter((media) => media.cdnUrl && !media.error);
4997  let contextBlock = "<context for the AI>\n";
4998  if (isAgencyUser) {
4999    contextBlock += "User is on Agency plan: Yes\n";
5000  } else {
5001    contextBlock += `Website plan: ${websitePlan}
5002`;
5003  }
5004  contextBlock += `Current page (the page the user is viewing in the preview): ${currentPath}
5005`;
5006  const hasImages = validImages && validImages.length > 0;
5007  if (hasImages) {
5008    contextBlock += "\nUser uploaded media:\n\n";
5009    validImages.forEach((media, index) => {
5010      var _a2, _b, _c;
5011      if (media.cdnUrl) {
5012        const isModel = media.mimeType === "model/gltf-binary" || ((_b = (_a2 = media.imageFile) == null ? void 0 : _a2.name) == null ? void 0 : _b.toLowerCase().endsWith(".glb"));
5013        const mediaType = isModel ? "3D model" : media.galleryMediaType || "image";
5014        const isVideo = mediaType === "video" || mediaType === "lottie";
5015        contextBlock += `${media.isGalleryImage ? "Gallery" : "Uploaded"} ${mediaType} ${index + 1}:
5016`;
5017        if (isVideo) {
5018          contextBlock += `Video URL: ${media.cdnUrl}
5019`;
5020          if (media.posterUrl) {
5021            contextBlock += `Poster URL: ${media.posterUrl}
5022`;
5023          }
5024          contextBlock += `Type: Cloudflare Stream video — render with the LandingsiteVideo component (src = Video URL, poster = Poster URL). The video may still be encoding for a short time; LandingsiteVideo handles that.
5025`;
5026        } else if (isModel) {
5027          contextBlock += `Model URL: ${media.cdnUrl}
5028`;
5029          if (media.r2Key) {
5030            contextBlock += `r2Key: ${media.r2Key}
5031`;
5032          }
5033          contextBlock += `Type: glTF binary (.glb) 3D model. Show it in an interactive 3D viewer (e.g. Google's <model-viewer> web component with auto-rotate and camera-controls), loading the model from the Model URL above. It is not an image — never put it in <img> or LandingsiteImage.
5034`;
5035        } else {
5036          const baseUrl = media.cdnUrl.replace(/[?&]w=\d+/, "");
5037          contextBlock += `Image URL: ${baseUrl}
5038`;
5039        }
5040        if ((_c = media.imageFile) == null ? void 0 : _c.name) {
5041          contextBlock += `Filename: ${media.imageFile.name}
5042`;
5043        }
5044        if (media.description) {
5045          contextBlock += `Description: ${media.description}
5046`;
5047        }
5048        contextBlock += "\n";
5049      }
5050    });
5051    const hasImageMedia = validImages.some((m) => m.cdnUrl && !["video", "lottie"].includes(m.galleryMediaType || ""));
5052    if (hasImageMedia) {
5053      contextBlock += "When placing images on the website, append ?w= with the appropriate width for the layout context. Available widths: 160, 320, 480, 768, 1200, 1920. Choose based on the image's rendered size — e.g. ?w=1920 for full-width heroes, ?w=768 for content columns, ?w=480 for cards/thumbnails, ?w=320 for small icons/avatars.\n\n";
5054    }
5055    const hasUserUploads = validImages.some((m) => {
5056      var _a2, _b;
5057      return !m.isGalleryImage && m.cdnUrl && ((_b = (_a2 = m.imageFile) == null ? void 0 : _a2.type) == null ? void 0 : _b.startsWith("image/"));
5058    });
5059    if (hasUserUploads) {
5060      contextBlock += "When placing images on the website, use the Description provided above as the alt attribute. If no description is provided, write a descriptive alt attribute based on the image content and how it's being used on the site. Do not leave alt empty or use generic placeholders.\n\n";
5061    }
5062    const hasFilenames = validImages.some((m) => {
5063      var _a2;
5064      return (_a2 = m.imageFile) == null ? void 0 : _a2.name;
5065    });
5066    if (hasFilenames) {
5067      contextBlock += "The Filename shown for each upload is the name the user gave it and often signals where or what the image is meant for. Use it together with the Description as a hint for the image's intended placement and subject when deciding where each image goes.\n\n";
5068    }
5069  }
5070  const domain = website == null ? void 0 : website.Domain;
5071  if (website == null ? void 0 : website.analyticsId) {
5072    contextBlock += `
5073Website Analytics ID: ${website.analyticsId}
5074`;
5075  }
5076  if (domain) {
5077    contextBlock += "\nDomain Information:\n";
5078    contextBlock += `- Domain ID: ${domain.id}
5079`;
5080    contextBlock += `- Domain Name: ${domain.domainName}
5081`;
5082    contextBlock += `- Verification Status: ${domain.verificationStatus}
5083`;
5084    if (!((_a = domain.configurationMethod) == null ? void 0 : _a.startsWith("EXTERNAL_DNS"))) {
5085      contextBlock += `- Nameserver Status: ${domain.nameserverStatus}
5086`;
5087    }
5088    if (domain.configurationMethod) {
5089      const methodLabels = {
5090        LANDINGSITE_NAMESERVERS: "Using Landingsite nameservers",
5091        EXTERNAL_DNS_ROOT: "External DNS (root domain)",
5092        EXTERNAL_DNS_SUBDOMAIN: "External DNS (subdomain)"
5093      };
5094      contextBlock += `- Configuration Method: ${methodLabels[domain.configurationMethod] || domain.configurationMethod}
5095`;
5096    }
5097    if (domain.purchaseType) {
5098      contextBlock += `- Purchase Type: ${domain.purchaseType === "landingsite" ? "Purchased through Landingsite" : "External domain"}
5099`;
5100    }
5101  } else {
5102    contextBlock += "\nDomain: No custom domain connected\n";
5103  }
5104  let selectionShipped = false;
5105  let selectionRejected = false;
5106  if (selectedElement) {
5107    const truncated = truncateOuterHtml(selectedElement.outerHTML);
5108    if (truncated.rejected) {
5109      selectionRejected = true;
5110    } else {
5111      contextBlock += buildPickerContextSection({
5112        outerHTML: truncated.html,
5113        path: selectedElement.path,
5114        sourceLoc: selectedElement.sourceLoc
5115      });
5116      selectionShipped = true;
5117    }
5118  }
5119  contextBlock += "</context for the AI>\n\n";
5120  const fileParts = (validImages || []).filter((m) => {
5121    var _a2, _b, _c, _d;
5122    return !m.isGalleryImage && !m.error && m.cdnUrl && (((_b = (_a2 = m.imageFile) == null ? void 0 : _a2.type) == null ? void 0 : _b.startsWith("image/")) || ((_c = m.imageFile) == null ? void 0 : _c.type) === "application/pdf") && ((_d = m.imageFile) == null ? void 0 : _d.type) !== "image/svg+xml";
5123  }).map((m) => ({
5124    type: "file",
5125    mediaType: m.imageFile.type,
5126    url: m.cdnUrl
5127  }));
5128  const message = {
5129    role: "user",
5130    parts: [{
5131      type: "text",
5132      text: contextBlock + messageText
5133    }, ...fileParts],
5134    id: generateId$1(),
5135    metadata: {
5136      userIdForAnalyticsOnly: currentUserId,
5137      isPaidWebsite: websitePlan !== "Free",
5138      websitePlan,
5139      publicId: (website == null ? void 0 : website.publicId) || void 0,
5140      // For container API calls
5141      tokenMinutesLeft,
5142      userUploadedMedia: (validImages == null ? void 0 : validImages.map((media) => media.cdnUrl || media.imagePreview)) || [],
5143      userUploadedMediaNames: (validImages == null ? void 0 : validImages.map((media) => {
5144        var _a2;
5145        return ((_a2 = media.imageFile) == null ? void 0 : _a2.name) || "";
5146      })) || [],
5147      galleryMediaTypes: (validImages == null ? void 0 : validImages.map((media) => media.galleryMediaType || "image")) || [],
5148      // Raw (watermarked) preview URL, used to play the clip immediately
5149      // in the chat bubble — the live site still gets the clean version.
5150      userUploadedMediaPreviews: (validImages == null ? void 0 : validImages.map((media) => media.imagePreview || "")) || [],
5151      // Flag for the initial website creation message - can't restore to this
5152      ...isInitialCreation && {
5153        isInitialCreation: true
5154      }
5155    }
5156  };
5157  return {
5158    message,
5159    selectionShipped,
5160    selectionRejected
5161  };
5162}
5163function mergeAssistantRuns(messages, prevCache) {
5164  const nextCache = /* @__PURE__ */ new Map();
5165  const merged = [];
5166  let i = 0;
5167  while (i < messages.length) {
5168    const msg = messages[i];
5169    if (msg.role !== "assistant") {
5170      merged.push(msg);
5171      i++;
5172      continue;
5173    }
5174    let j = i + 1;
5175    while (j < messages.length && messages[j].role === "assistant") {
5176      j++;
5177    }
5178    const run = messages.slice(i, j);
5179    if (run.length === 1) {
5180      merged.push(msg);
5181    } else {
5182      const key = `${msg.id}:${i}`;
5183      const cached = prevCache.get(key);
5184      const unchanged = cached !== void 0 && cached.inputs.length === run.length && cached.inputs.every((m, k) => m === run[k]);
5185      if (unchanged) {
5186        nextCache.set(key, cached);
5187        merged.push(cached.output);
5188      } else {
5189        const output = {
5190          ...msg,
5191          parts: run.flatMap((m) => m.parts || []),
5192          metadata: run.reduce((md, m) => ({
5193            ...md,
5194            ...m.metadata || {}
5195          }), {})
5196        };
5197        nextCache.set(key, {
5198          inputs: run,
5199          output
5200        });
5201        merged.push(output);
5202      }
5203    }
5204    i = j;
5205  }
5206  return {
5207    merged,
5208    nextCache
5209  };
5210}
5211function emptyQueue() {
5212  return {
5213    items: [],
5214    generation: 0
5215  };
5216}
5217function snapshotImage(image) {
5218  const imagePreview = image.imagePreview.startsWith("blob:") && image.cdnUrl ? image.cdnUrl : image.imagePreview;
5219  return {
5220    index: image.index,
5221    imageFile: image.imageFile,
5222    imagePreview,
5223    s3Url: image.s3Url,
5224    cdnUrl: image.cdnUrl,
5225    r2Key: image.r2Key,
5226    mimeType: image.mimeType,
5227    assetId: image.assetId,
5228    isFlagged: image.isFlagged,
5229    isGalleryImage: image.isGalleryImage,
5230    galleryMediaId: image.galleryMediaId,
5231    galleryMediaSource: image.galleryMediaSource,
5232    galleryMediaType: image.galleryMediaType,
5233    posterUrl: image.posterUrl,
5234    description: image.description,
5235    uploading: false
5236  };
5237}
5238function enqueue(state, input) {
5239  const item = {
5240    id: generateId(),
5241    text: input.text,
5242    images: input.images.map(snapshotImage),
5243    selectedElement: input.selectedElement,
5244    currentPath: input.currentPath,
5245    queuedAt: input.now ?? Date.now()
5246  };
5247  return {
5248    ...state,
5249    items: [...state.items, item]
5250  };
5251}
5252function updateText(state, id, text) {
5253  if (text.trim().length === 0) return state;
5254  const index = state.items.findIndex((item) => item.id === id);
5255  if (index === -1) return state;
5256  const items = state.items.slice();
5257  items[index] = {
5258    ...items[index],
5259    text
5260  };
5261  return {
5262    ...state,
5263    items
5264  };
5265}
5266function removeItem(state, id) {
5267  const items = state.items.filter((item) => item.id !== id);
5268  if (items.length === state.items.length) return state;
5269  return {
5270    ...state,
5271    items
5272  };
5273}
5274function shiftHead(state) {
5275  if (state.items.length === 0) return {
5276    head: null,
5277    state
5278  };
5279  const [head, ...rest] = state.items;
5280  return {
5281    head,
5282    state: {
5283      ...state,
5284      items: rest
5285    }
5286  };
5287}
5288function unshift(state, item) {
5289  return {
5290    ...state,
5291    items: [item, ...state.items]
5292  };
5293}
5294function clearQueue(state) {
5295  return {
5296    items: [],
5297    generation: state.generation + 1
5298  };
5299}
5300function shouldRequeueAfterConflict(capturedGeneration, currentGeneration) {
5301  return capturedGeneration === currentGeneration;
5302}
5303function mergeQueueIntoComposer(items, draft) {
5304  const parts = items.map((item) => item.text);
5305  if (draft.text.trim().length > 0) parts.push(draft.text);
5306  const images = items.flatMap((item) => item.images);
5307  const selections = items.map((item) => item.selectedElement).filter((sel) => sel !== null);
5308  const selectedElement = draft.hasSelection ? null : selections[0] ?? null;
5309  const droppedSelections = selections.length - (selectedElement ? 1 : 0);
5310  return {
5311    text: items.length === 0 ? draft.text : parts.join("\n\n"),
5312    images,
5313    selectedElement,
5314    droppedSelections
5315  };
5316}
5317function mergeOut(state, draft) {
5318  return {
5319    merged: mergeQueueIntoComposer(state.items, draft),
5320    state: clearQueue(state)
5321  };
5322}
5323function composerMode(flags) {
5324  const locked = flags.chatLimitReached || flags.restoring || !flags.containerReady || !flags.canEdit || flags.pendingApproval || flags.pendingQuestion || flags.inlineEditInProgress;
5325  if (locked) return "locked";
5326  const busy = flags.status === "connecting" || flags.status === "streaming" || flags.submitting;
5327  return busy ? "busy" : "idle";
5328}
5329const DRAIN_PAUSED_REASONS = ["approval", "question", "editing", "max-turns", "error", "chat-limit", "no-access", "restoring", "container"];
5330function drainGate(inputs) {
5331  if (inputs.pendingApproval) return "approval";
5332  if (inputs.pendingQuestion) return "question";
5333  if (inputs.status === "connecting" || inputs.status === "streaming" || inputs.submitting || inputs.stopLatched) {
5334    return "wait";
5335  }
5336  if (inputs.editing) return "editing";
5337  if (inputs.maxTurnsHit) return "max-turns";
5338  if (inputs.panelError) return "error";
5339  if (inputs.chatLimitReached) return "chat-limit";
5340  if (!inputs.canEdit) return "no-access";
5341  if (inputs.restoring) return "restoring";
5342  if (!inputs.containerReady) return "container";
5343  return "drain";
5344}
5345function drainTransition(previous, current) {
5346  return current === "drain" && previous !== "drain";
5347}
5348const PAUSED_REASON_COPY = {
5349  approval: "Waiting for you to approve or deny the request above",
5350  question: "Waiting for you to answer the question above",
5351  editing: "Finish editing to send",
5352  "max-turns": "Paused — click Continue or Send now",
5353  error: "Paused until the error above is resolved",
5354  "chat-limit": "Paused — chat limit reached",
5355  restoring: "Paused while restoring",
5356  "no-access": "Paused — you no longer have edit access to this site",
5357  container: "Waiting for the preview server"
5358};
5359function QueuedMessageListImpl({
5360  items,
5361  mode,
5362  pausedReason,
5363  onUpdateText,
5364  onRemove,
5365  onSendNow,
5366  onEditingChange
5367}) {
5368  if (items.length === 0) return null;
5369  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative z-[1] flex flex-col gap-1.5 px-1.5 pb-1.5 pt-1.5", children: [
5370    /* @__PURE__ */ jsxRuntimeExports.jsx("div", { role: "list", "aria-label": "Queued messages", className: "flex max-h-[40vh] flex-col gap-1.5 overflow-y-auto", children: items.map((item, index) => /* @__PURE__ */ jsxRuntimeExports.jsx(QueuedMessageRow, { item, position: index + 1, canSendNow: mode === "idle", onUpdateText, onRemove, onSendNow, onEditingChange }, item.id)) }),
5371    pausedReason && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "px-1 text-[11px] leading-4 text-muted-foreground", children: PAUSED_REASON_COPY[pausedReason] })
5372  ] });
5373}
5374function QueuedMessageRowImpl({
5375  item,
5376  position,
5377  canSendNow,
5378  onUpdateText,
5379  onRemove,
5380  onSendNow,
5381  onEditingChange
5382}) {
5383  const [editing, setEditing] = reactExports.useState(false);
5384  const [draft, setDraft] = reactExports.useState(item.text);
5385  const editorRef = reactExports.useRef(null);
5386  const editingRef = reactExports.useRef(false);
5387  const onEditingChangeRef = reactExports.useRef(onEditingChange);
5388  onEditingChangeRef.current = onEditingChange;
5389  reactExports.useEffect(() => {
5390    if (!editing) return;
5391    const el = editorRef.current;
5392    if (!el) return;
5393    el.focus();
5394    el.setSelectionRange(el.value.length, el.value.length);
5395  }, [editing]);
5396  reactExports.useEffect(() => () => {
5397    var _a;
5398    if (editingRef.current) {
5399      editingRef.current = false;
5400      (_a = onEditingChangeRef.current) == null ? void 0 : _a.call(onEditingChangeRef, null);
5401    }
5402  }, []);
5403  const startEdit = () => {
5404    setDraft(item.text);
5405    editingRef.current = true;
5406    setEditing(true);
5407    onEditingChange == null ? void 0 : onEditingChange(item.id);
5408  };
5409  const cancelEdit = () => {
5410    setDraft(item.text);
5411    editingRef.current = false;
5412    setEditing(false);
5413    onEditingChange == null ? void 0 : onEditingChange(null);
5414  };
5415  const saveEdit = () => {
5416    if (!editingRef.current) return;
5417    editingRef.current = false;
5418    const next = draft;
5419    setEditing(false);
5420    onEditingChange == null ? void 0 : onEditingChange(null);
5421    if (next.trim().length === 0 || next === item.text) {
5422      setDraft(item.text);
5423      return;
5424    }
5425    onUpdateText(item.id, next);
5426  };
5427  const handleSendNow = () => {
5428    saveEdit();
5429    onSendNow(item.id);
5430  };
5431  const handleEditorKeyDown = (event) => {
5432    if (event.key === "Escape") {
5433      event.preventDefault();
5434      cancelEdit();
5435      return;
5436    }
5437    if (event.key === "Enter" && !event.shiftKey) {
5438      event.preventDefault();
5439      saveEdit();
5440    }
5441  };
5442  const elementLabel = item.selectedElement ? formatFriendlyLabel(item.selectedElement.tag, item.selectedElement.textPreview) : null;
5443  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { role: "listitem", "aria-label": `Queued message ${position}`, className: cn$1("flex flex-col gap-1.5 rounded-[12px] border border-[#1B1A22]/[0.08] bg-white px-2.5 py-2", "shadow-[0_1px_2px_rgba(27,26,34,0.06)]"), children: [
5444    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-2", children: [
5445      /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-w-0 flex-1", children: editing ? /* @__PURE__ */ jsxRuntimeExports.jsx(Textarea, { ref: editorRef, "aria-label": "Edit queued message text", value: draft, rows: 2, onChange: (event) => setDraft(event.target.value), onKeyDown: handleEditorKeyDown, onBlur: saveEdit, className: "min-h-[40px] resize-none rounded-[8px] border-[#1B1A22]/[0.08] px-2 py-1.5 text-sm focus-visible:ring-1 focus-visible:ring-offset-0" }) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "line-clamp-3 whitespace-pre-wrap break-words text-sm text-foreground", children: item.text }) }),
5446      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex shrink-0 items-center gap-0.5", children: [
5447        /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
5448          /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "inline-flex", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { type: "button", size: "icon", variant: "ghost", "aria-label": "Send now", disabled: !canSendNow, onClick: handleSendNow, className: "h-6 w-6 rounded-full p-0 text-muted-foreground hover:bg-background hover:text-foreground disabled:opacity-40", children: /* @__PURE__ */ jsxRuntimeExports.jsx(CornerDownLeft, { className: "h-3.5 w-3.5" }) }) }) }),
5449          /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { side: "top", align: "center", children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: canSendNow ? "Send now" : "Sends automatically when the AI finishes" }) })
5450        ] }) }),
5451        /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { type: "button", size: "icon", variant: "ghost", "aria-label": "Edit queued message", "aria-pressed": editing, onClick: editing ? cancelEdit : startEdit, className: "h-6 w-6 rounded-full p-0 text-muted-foreground hover:bg-background hover:text-foreground", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Pencil, { className: "h-3.5 w-3.5" }) }),
5452        /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { type: "button", size: "icon", variant: "ghost", "aria-label": "Remove queued message", onClick: () => onRemove(item.id), className: "h-6 w-6 rounded-full p-0 text-muted-foreground hover:bg-background hover:text-foreground", children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "h-3.5 w-3.5" }) })
5453      ] })
5454    ] }),
5455    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-1.5 text-[11px] leading-4 text-muted-foreground", children: [
5456      item.images.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-wrap items-center gap-1", children: item.images.map((image) => /* @__PURE__ */ jsxRuntimeExports.jsx(QueuedThumbnail, { image }, image.index)) }),
5457      elementLabel && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex max-w-[220px] items-center gap-1 rounded-[8px] border border-[#1B1A22]/[0.08] bg-white px-1.5 py-0.5", children: [
5458        /* @__PURE__ */ jsxRuntimeExports.jsx(MousePointerClick, { className: "h-3 w-3 shrink-0", "aria-hidden": true }),
5459        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", children: elementLabel })
5460      ] })
5461    ] })
5462  ] });
5463}
5464const THUMB_CLASS = "h-10 w-10 rounded-[8px] border border-[#1B1A22]/[0.08] object-cover";
5465const TILE_CLASS = "flex h-10 w-10 items-center justify-center rounded-[8px] border border-[#1B1A22]/[0.08] bg-white";
5466function QueuedThumbnail({
5467  image
5468}) {
5469  var _a, _b;
5470  const fileName = ((_a = image.imageFile) == null ? void 0 : _a.name) ?? "";
5471  const fileType = ((_b = image.imageFile) == null ? void 0 : _b.type) ?? "";
5472  if (image.galleryMediaType === "video" || image.galleryMediaType === "lottie") {
5473    return /* @__PURE__ */ jsxRuntimeExports.jsx("video", { src: image.imagePreview, poster: image.posterUrl, className: THUMB_CLASS, autoPlay: true, loop: true, muted: true, playsInline: true, "aria-label": "Queued video attachment" });
5474  }
5475  if (fileType === "application/pdf") {
5476    return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: TILE_CLASS, title: fileName || "PDF", "aria-label": "Queued PDF attachment", children: /* @__PURE__ */ jsxRuntimeExports.jsx(FileText, { className: "h-4 w-4 text-muted-foreground" }) });
5477  }
5478  if (fileName.toLowerCase().endsWith(".glb")) {
5479    return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: TILE_CLASS, title: fileName || "3D model", "aria-label": "Queued 3D model attachment", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { className: "h-4 w-4 text-muted-foreground" }) });
5480  }
5481  if (fileType === "image/heic" || fileType === "image/heif") {
5482    return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: TILE_CLASS, title: fileName || "HEIC", "aria-label": "Queued HEIC attachment", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Image, { className: "h-4 w-4 text-muted-foreground" }) });
5483  }
5484  return /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: image.imagePreview, alt: "Queued attachment", className: THUMB_CLASS });
5485}
5486const QueuedMessageRow = React.memo(QueuedMessageRowImpl);
5487const QueuedMessageList = React.memo(QueuedMessageListImpl);
5488const PAYMENTS_DATA_TOOLS = /* @__PURE__ */ new Set(["create_product", "update_product", "delete_product", "set_product_variants", "generate_variants", "update_variant", "set_variant_inventory", "set_product_subscription", "moderate_review", "reply_to_review", "update_review_settings"]);
5489const COMMERCE_INTENT_TOOLS = /* @__PURE__ */ new Set(["create_invoice", "create_retainer"]);
5490const BUSINESS_DATA_TOOLS = /* @__PURE__ */ new Set([
5491  "create_product",
5492  "update_product",
5493  "set_product_variants",
5494  "set_variant_inventory",
5495  "set_shipping_countries",
5496  "set_shipping_rates",
5497  "mark_order_fulfilled",
5498  // Subscriptions (U9/U11): cancel mutates rows the SubscriptionsView has
5499  // fetched; list/get land here too so a turn that merely inspected
5500  // subscriptions still re-renders the freshest mirror state in the view.
5501  "list_subscriptions",
5502  "get_subscription",
5503  "cancel_subscription",
5504  // Invoicing (landingsite-modal/agent/src/tools/invoices.ts + retainers.ts):
5505  // every mutation changes rows an open Invoices view has fetched. The view
5506  // polls nothing of its own, so without these a "send Bob another invoice"
5507  // while the view is open leaves it stale until the merchant reopens it.
5508  "create_invoice",
5509  "void_invoice",
5510  "resend_invoice",
5511  "remind_invoice",
5512  "snooze_invoice",
5513  "set_invoice_reminders",
5514  "mark_invoice_paid",
5515  "mark_invoice_uncollectible",
5516  "update_invoice_recipient",
5517  "update_customer",
5518  "update_invoice_settings",
5519  "create_retainer",
5520  "update_retainer",
5521  "skip_next_retainer_cycle",
5522  "pause_retainer",
5523  "resume_retainer",
5524  "cancel_retainer"
5525]);
5526function turnEndRefreshTargets(toolNames) {
5527  const out = {
5528    preview: false,
5529    commerceIntent: false,
5530    business: false
5531  };
5532  for (const name of toolNames) {
5533    if (PAYMENTS_DATA_TOOLS.has(name)) {
5534      out.preview = true;
5535      out.commerceIntent = true;
5536    }
5537    if (COMMERCE_INTENT_TOOLS.has(name)) out.commerceIntent = true;
5538    if (BUSINESS_DATA_TOOLS.has(name)) out.business = true;
5539  }
5540  return out;
5541}
5542function completedToolNamesInTurn(messages) {
5543  var _a;
5544  let start = 0;
5545  for (let i = messages.length - 1; i >= 0; i--) {
5546    if (messages[i].role === "user") {
5547      start = i + 1;
5548      break;
5549    }
5550  }
5551  const names = [];
5552  for (const m of messages.slice(start)) {
5553    if (m.role !== "assistant") continue;
5554    const parts = m.parts;
5555    for (const p of parts ?? []) {
5556      if (!((_a = p == null ? void 0 : p.type) == null ? void 0 : _a.startsWith("tool-"))) continue;
5557      if (p.state !== "output-available") continue;
5558      names.push(p.type.split("__").pop() ?? "");
5559    }
5560  }
5561  return names;
5562}
5563const RESTORE_TO_CHAT_MESSAGE = {
5564  "kind": "Document",
5565  "definitions": [{
5566    "kind": "OperationDefinition",
5567    "operation": "mutation",
5568    "name": {
5569      "kind": "Name",
5570      "value": "RestoreToChatMessageMutation"
5571    },
5572    "variableDefinitions": [{
5573      "kind": "VariableDefinition",
5574      "variable": {
5575        "kind": "Variable",
5576        "name": {
5577          "kind": "Name",
5578          "value": "websiteId"
5579        }
5580      },
5581      "type": {
5582        "kind": "NonNullType",
5583        "type": {
5584          "kind": "NamedType",
5585          "name": {
5586            "kind": "Name",
5587            "value": "String"
5588          }
5589        }
5590      },
5591      "directives": []
5592    }, {
5593      "kind": "VariableDefinition",
5594      "variable": {
5595        "kind": "Variable",
5596        "name": {
5597          "kind": "Name",
5598          "value": "messageId"
5599        }
5600      },
5601      "type": {
5602        "kind": "NonNullType",
5603        "type": {
5604          "kind": "NamedType",
5605          "name": {
5606            "kind": "Name",
5607            "value": "String"
5608          }
5609        }
5610      },
5611      "directives": []
5612    }, {
5613      "kind": "VariableDefinition",
5614      "variable": {
5615        "kind": "Variable",
5616        "name": {
5617          "kind": "Name",
5618          "value": "preMessageCommitHash"
5619        }
5620      },
5621      "type": {
5622        "kind": "NonNullType",
5623        "type": {
5624          "kind": "NamedType",
5625          "name": {
5626            "kind": "Name",
5627            "value": "String"
5628          }
5629        }
5630      },
5631      "directives": []
5632    }],
5633    "directives": [],
5634    "selectionSet": {
5635      "kind": "SelectionSet",
5636      "selections": [{
5637        "kind": "Field",
5638        "name": {
5639          "kind": "Name",
5640          "value": "restoreToChatMessage"
5641        },
5642        "arguments": [{
5643          "kind": "Argument",
5644          "name": {
5645            "kind": "Name",
5646            "value": "websiteId"
5647          },
5648          "value": {
5649            "kind": "Variable",
5650            "name": {
5651              "kind": "Name",
5652              "value": "websiteId"
5653            }
5654          }
5655        }, {
5656          "kind": "Argument",
5657          "name": {
5658            "kind": "Name",
5659            "value": "messageId"
5660          },
5661          "value": {
5662            "kind": "Variable",
5663            "name": {
5664              "kind": "Name",
5665              "value": "messageId"
5666            }
5667          }
5668        }, {
5669          "kind": "Argument",
5670          "name": {
5671            "kind": "Name",
5672            "value": "preMessageCommitHash"
5673          },
5674          "value": {
5675            "kind": "Variable",
5676            "name": {
5677              "kind": "Name",
5678              "value": "preMessageCommitHash"
5679            }
5680          }
5681        }],
5682        "directives": [],
5683        "selectionSet": {
5684          "kind": "SelectionSet",
5685          "selections": [{
5686            "kind": "Field",
5687            "name": {
5688              "kind": "Name",
5689              "value": "success"
5690            },
5691            "arguments": [],
5692            "directives": []
5693          }, {
5694            "kind": "Field",
5695            "name": {
5696              "kind": "Name",
5697              "value": "error"
5698            },
5699            "arguments": [],
5700            "directives": []
5701          }, {
5702            "kind": "Field",
5703            "name": {
5704              "kind": "Name",
5705              "value": "pending"
5706            },
5707            "arguments": [],
5708            "directives": []
5709          }, {
5710            "kind": "Field",
5711            "name": {
5712              "kind": "Name",
5713              "value": "admissionId"
5714            },
5715            "arguments": [],
5716            "directives": []
5717          }, {
5718            "kind": "Field",
5719            "name": {
5720              "kind": "Name",
5721              "value": "sourceSessionId"
5722            },
5723            "arguments": [],
5724            "directives": []
5725          }]
5726        }
5727      }]
5728    }
5729  }],
5730  "loc": {
5731    "start": 0,
5732    "end": 361,
5733    "source": {
5734      "body": "\n  mutation RestoreToChatMessageMutation(\n    $websiteId: String!\n    $messageId: String!\n    $preMessageCommitHash: String!\n  ) {\n    restoreToChatMessage(\n      websiteId: $websiteId\n      messageId: $messageId\n      preMessageCommitHash: $preMessageCommitHash\n    ) {\n      success\n      error\n      pending\n      admissionId\n      sourceSessionId\n    }\n  }\n",
5735      "name": "GraphQL request",
5736      "locationOffset": {
5737        "line": 1,
5738        "column": 1
5739      }
5740    }
5741  }
5742};
5743const CONTINUE_CHAT_RESTORE = {
5744  "kind": "Document",
5745  "definitions": [{
5746    "kind": "OperationDefinition",
5747    "operation": "mutation",
5748    "name": {
5749      "kind": "Name",
5750      "value": "ContinueChatRestoreMutation"
5751    },
5752    "variableDefinitions": [{
5753      "kind": "VariableDefinition",
5754      "variable": {
5755        "kind": "Variable",
5756        "name": {
5757          "kind": "Name",
5758          "value": "websiteId"
5759        }
5760      },
5761      "type": {
5762        "kind": "NonNullType",
5763        "type": {
5764          "kind": "NamedType",
5765          "name": {
5766            "kind": "Name",
5767            "value": "String"
5768          }
5769        }
5770      },
5771      "directives": []
5772    }, {
5773      "kind": "VariableDefinition",
5774      "variable": {
5775        "kind": "Variable",
5776        "name": {
5777          "kind": "Name",
5778          "value": "preMessageCommitHash"
5779        }
5780      },
5781      "type": {
5782        "kind": "NonNullType",
5783        "type": {
5784          "kind": "NamedType",
5785          "name": {
5786            "kind": "Name",
5787            "value": "String"
5788          }
5789        }
5790      },
5791      "directives": []
5792    }, {
5793      "kind": "VariableDefinition",
5794      "variable": {
5795        "kind": "Variable",
5796        "name": {
5797          "kind": "Name",
5798          "value": "admissionId"
5799        }
5800      },
5801      "type": {
5802        "kind": "NonNullType",
5803        "type": {
5804          "kind": "NamedType",
5805          "name": {
5806            "kind": "Name",
5807            "value": "String"
5808          }
5809        }
5810      },
5811      "directives": []
5812    }, {
5813      "kind": "VariableDefinition",
5814      "variable": {
5815        "kind": "Variable",
5816        "name": {
5817          "kind": "Name",
5818          "value": "sourceSessionId"
5819        }
5820      },
5821      "type": {
5822        "kind": "NonNullType",
5823        "type": {
5824          "kind": "NamedType",
5825          "name": {
5826            "kind": "Name",
5827            "value": "String"
5828          }
5829        }
5830      },
5831      "directives": []
5832    }],
5833    "directives": [],
5834    "selectionSet": {
5835      "kind": "SelectionSet",
5836      "selections": [{
5837        "kind": "Field",
5838        "name": {
5839          "kind": "Name",
5840          "value": "continueChatRestore"
5841        },
5842        "arguments": [{
5843          "kind": "Argument",
5844          "name": {
5845            "kind": "Name",
5846            "value": "websiteId"
5847          },
5848          "value": {
5849            "kind": "Variable",
5850            "name": {
5851              "kind": "Name",
5852              "value": "websiteId"
5853            }
5854          }
5855        }, {
5856          "kind": "Argument",
5857          "name": {
5858            "kind": "Name",
5859            "value": "preMessageCommitHash"
5860          },
5861          "value": {
5862            "kind": "Variable",
5863            "name": {
5864              "kind": "Name",
5865              "value": "preMessageCommitHash"
5866            }
5867          }
5868        }, {
5869          "kind": "Argument",
5870          "name": {
5871            "kind": "Name",
5872            "value": "admissionId"
5873          },
5874          "value": {
5875            "kind": "Variable",
5876            "name": {
5877              "kind": "Name",
5878              "value": "admissionId"
5879            }
5880          }
5881        }, {
5882          "kind": "Argument",
5883          "name": {
5884            "kind": "Name",
5885            "value": "sourceSessionId"
5886          },
5887          "value": {
5888            "kind": "Variable",
5889            "name": {
5890              "kind": "Name",
5891              "value": "sourceSessionId"
5892            }
5893          }
5894        }],
5895        "directives": [],
5896        "selectionSet": {
5897          "kind": "SelectionSet",
5898          "selections": [{
5899            "kind": "Field",
5900            "name": {
5901              "kind": "Name",
5902              "value": "success"
5903            },
5904            "arguments": [],
5905            "directives": []
5906          }, {
5907            "kind": "Field",
5908            "name": {
5909              "kind": "Name",
5910              "value": "error"
5911            },
5912            "arguments": [],
5913            "directives": []
5914          }, {
5915            "kind": "Field",
5916            "name": {
5917              "kind": "Name",
5918              "value": "pending"
5919            },
5920            "arguments": [],
5921            "directives": []
5922          }, {
5923            "kind": "Field",
5924            "name": {
5925              "kind": "Name",
5926              "value": "admissionId"
5927            },
5928            "arguments": [],
5929            "directives": []
5930          }, {
5931            "kind": "Field",
5932            "name": {
5933              "kind": "Name",
5934              "value": "sourceSessionId"
5935            },
5936            "arguments": [],
5937            "directives": []
5938          }]
5939        }
5940      }]
5941    }
5942  }],
5943  "loc": {
5944    "start": 0,
5945    "end": 435,
5946    "source": {
5947      "body": "\n  mutation ContinueChatRestoreMutation(\n    $websiteId: String!\n    $preMessageCommitHash: String!\n    $admissionId: String!\n    $sourceSessionId: String!\n  ) {\n    continueChatRestore(\n      websiteId: $websiteId\n      preMessageCommitHash: $preMessageCommitHash\n      admissionId: $admissionId\n      sourceSessionId: $sourceSessionId\n    ) {\n      success\n      error\n      pending\n      admissionId\n      sourceSessionId\n    }\n  }\n",
5948      "name": "GraphQL request",
5949      "locationOffset": {
5950        "line": 1,
5951        "column": 1
5952      }
5953    }
5954  }
5955};
5956const WEBSITE_COMMERCE_INTENT = {
5957  "kind": "Document",
5958  "definitions": [{
5959    "kind": "OperationDefinition",
5960    "operation": "query",
5961    "name": {
5962      "kind": "Name",
5963      "value": "ReactChatPanelWebsiteCommerceIntent"
5964    },
5965    "variableDefinitions": [{
5966      "kind": "VariableDefinition",
5967      "variable": {
5968        "kind": "Variable",
5969        "name": {
5970          "kind": "Name",
5971          "value": "websiteId"
5972        }
5973      },
5974      "type": {
5975        "kind": "NonNullType",
5976        "type": {
5977          "kind": "NamedType",
5978          "name": {
5979            "kind": "Name",
5980            "value": "String"
5981          }
5982        }
5983      },
5984      "directives": []
5985    }],
5986    "directives": [],
5987    "selectionSet": {
5988      "kind": "SelectionSet",
5989      "selections": [{
5990        "kind": "Field",
5991        "name": {
5992          "kind": "Name",
5993          "value": "websiteCommerceIntent"
5994        },
5995        "arguments": [{
5996          "kind": "Argument",
5997          "name": {
5998            "kind": "Name",
5999            "value": "websiteId"
6000          },
6001          "value": {
6002            "kind": "Variable",
6003            "name": {
6004              "kind": "Name",
6005              "value": "websiteId"
6006            }
6007          }
6008        }],
6009        "directives": [],
6010        "selectionSet": {
6011          "kind": "SelectionSet",
6012          "selections": [{
6013            "kind": "Field",
6014            "name": {
6015              "kind": "Name",
6016              "value": "needsPaymentsSetup"
6017            },
6018            "arguments": [],
6019            "directives": []
6020          }, {
6021            "kind": "Field",
6022            "name": {
6023              "kind": "Name",
6024              "value": "paymentsActive"
6025            },
6026            "arguments": [],
6027            "directives": []
6028          }, {
6029            "kind": "Field",
6030            "name": {
6031              "kind": "Name",
6032              "value": "commerceSetup"
6033            },
6034            "arguments": [],
6035            "directives": [],
6036            "selectionSet": {
6037              "kind": "SelectionSet",
6038              "selections": [{
6039                "kind": "Field",
6040                "name": {
6041                  "kind": "Name",
6042                  "value": "websiteReview"
6043                },
6044                "arguments": [],
6045                "directives": [],
6046                "selectionSet": {
6047                  "kind": "SelectionSet",
6048                  "selections": [{
6049                    "kind": "Field",
6050                    "name": {
6051                      "kind": "Name",
6052                      "value": "url"
6053                    },
6054                    "arguments": [],
6055                    "directives": []
6056                  }, {
6057                    "kind": "Field",
6058                    "name": {
6059                      "kind": "Name",
6060                      "value": "state"
6061                    },
6062                    "arguments": [],
6063                    "directives": []
6064                  }, {
6065                    "kind": "Field",
6066                    "name": {
6067                      "kind": "Name",
6068                      "value": "issues"
6069                    },
6070                    "arguments": [],
6071                    "directives": []
6072                  }]
6073                }
6074              }, {
6075                "kind": "Field",
6076                "name": {
6077                  "kind": "Name",
6078                  "value": "paymentState"
6079                },
6080                "arguments": [],
6081                "directives": []
6082              }, {
6083                "kind": "Field",
6084                "name": {
6085                  "kind": "Name",
6086                  "value": "payoutState"
6087                },
6088                "arguments": [],
6089                "directives": []
6090              }, {
6091                "kind": "Field",
6092                "name": {
6093                  "kind": "Name",
6094                  "value": "detailsSubmitted"
6095                },
6096                "arguments": [],
6097                "directives": []
6098              }, {
6099                "kind": "Field",
6100                "name": {
6101                  "kind": "Name",
6102                  "value": "paymentRequirements"
6103                },
6104                "arguments": [],
6105                "directives": []
6106              }, {
6107                "kind": "Field",
6108                "name": {
6109                  "kind": "Name",
6110                  "value": "payoutRequirements"
6111                },
6112                "arguments": [],
6113                "directives": []
6114              }, {
6115                "kind": "Field",
6116                "name": {
6117                  "kind": "Name",
6118                  "value": "requirementsDeadline"
6119                },
6120                "arguments": [],
6121                "directives": []
6122              }, {
6123                "kind": "Field",
6124                "name": {
6125                  "kind": "Name",
6126                  "value": "checkedAt"
6127                },
6128                "arguments": [],
6129                "directives": []
6130              }]
6131            }
6132          }, {
6133            "kind": "Field",
6134            "name": {
6135              "kind": "Name",
6136              "value": "needsUpgrade"
6137            },
6138            "arguments": [],
6139            "directives": []
6140          }, {
6141            "kind": "Field",
6142            "name": {
6143              "kind": "Name",
6144              "value": "paymentsDisabled"
6145            },
6146            "arguments": [],
6147            "directives": []
6148          }, {
6149            "kind": "Field",
6150            "name": {
6151              "kind": "Name",
6152              "value": "hasProducts"
6153            },
6154            "arguments": [],
6155            "directives": []
6156          }, {
6157            "kind": "Field",
6158            "name": {
6159              "kind": "Name",
6160              "value": "invoiceIntent"
6161            },
6162            "arguments": [],
6163            "directives": []
6164          }, {
6165            "kind": "Field",
6166            "name": {
6167              "kind": "Name",
6168              "value": "paymentsPending"
6169            },
6170            "arguments": [],
6171            "directives": []
6172          }, {
6173            "kind": "Field",
6174            "name": {
6175              "kind": "Name",
6176              "value": "postageUncharged"
6177            },
6178            "arguments": [],
6179            "directives": []
6180          }, {
6181            "kind": "Field",
6182            "name": {
6183              "kind": "Name",
6184              "value": "currencyRestatedFrom"
6185            },
6186            "arguments": [],
6187            "directives": []
6188          }, {
6189            "kind": "Field",
6190            "name": {
6191              "kind": "Name",
6192              "value": "currencyRestatedTo"
6193            },
6194            "arguments": [],
6195            "directives": []
6196          }, {
6197            "kind": "Field",
6198            "name": {
6199              "kind": "Name",
6200              "value": "canStartOnboarding"
6201            },
6202            "arguments": [],
6203            "directives": []
6204          }]
6205        }
6206      }]
6207    }
6208  }],
6209  "loc": {
6210    "start": 0,
6211    "end": 656,
6212    "source": {
6213      "body": "\n  query ReactChatPanelWebsiteCommerceIntent($websiteId: String!) {\n    websiteCommerceIntent(websiteId: $websiteId) {\n      needsPaymentsSetup\n      paymentsActive\n      commerceSetup {\n        websiteReview {\n          url\n          state\n          issues\n        }\n        paymentState\n        payoutState\n        detailsSubmitted\n        paymentRequirements\n        payoutRequirements\n        requirementsDeadline\n        checkedAt\n      }\n      needsUpgrade\n      paymentsDisabled\n      hasProducts\n      invoiceIntent\n      paymentsPending\n      postageUncharged\n      currencyRestatedFrom\n      currencyRestatedTo\n      canStartOnboarding\n    }\n  }\n",
6214      "name": "GraphQL request",
6215      "locationOffset": {
6216        "line": 1,
6217        "column": 1
6218      }
6219    }
6220  }
6221};
6222const SYNC_STRIPE_CONNECT_STATUS_FROM_CHAT = {
6223  "kind": "Document",
6224  "definitions": [{
6225    "kind": "OperationDefinition",
6226    "operation": "mutation",
6227    "name": {
6228      "kind": "Name",
6229      "value": "SyncStripeConnectStatusFromChat"
6230    },
6231    "variableDefinitions": [{
6232      "kind": "VariableDefinition",
6233      "variable": {
6234        "kind": "Variable",
6235        "name": {
6236          "kind": "Name",
6237          "value": "polling"
6238        }
6239      },
6240      "type": {
6241        "kind": "NamedType",
6242        "name": {
6243          "kind": "Name",
6244          "value": "Boolean"
6245        }
6246      },
6247      "directives": []
6248    }],
6249    "directives": [],
6250    "selectionSet": {
6251      "kind": "SelectionSet",
6252      "selections": [{
6253        "kind": "Field",
6254        "name": {
6255          "kind": "Name",
6256          "value": "syncStripeConnectStatus"
6257        },
6258        "arguments": [{
6259          "kind": "Argument",
6260          "name": {
6261            "kind": "Name",
6262            "value": "polling"
6263          },
6264          "value": {
6265            "kind": "Variable",
6266            "name": {
6267              "kind": "Name",
6268              "value": "polling"
6269            }
6270          }
6271        }],
6272        "directives": [],
6273        "selectionSet": {
6274          "kind": "SelectionSet",
6275          "selections": [{
6276            "kind": "Field",
6277            "name": {
6278              "kind": "Name",
6279              "value": "hasAccount"
6280            },
6281            "arguments": [],
6282            "directives": []
6283          }, {
6284            "kind": "Field",
6285            "name": {
6286              "kind": "Name",
6287              "value": "chargesEnabled"
6288            },
6289            "arguments": [],
6290            "directives": []
6291          }, {
6292            "kind": "Field",
6293            "name": {
6294              "kind": "Name",
6295              "value": "detailsSubmitted"
6296            },
6297            "arguments": [],
6298            "directives": []
6299          }]
6300        }
6301      }]
6302    }
6303  }],
6304  "loc": {
6305    "start": 0,
6306    "end": 185,
6307    "source": {
6308      "body": "\n  mutation SyncStripeConnectStatusFromChat($polling: Boolean) {\n    syncStripeConnectStatus(polling: $polling) {\n      hasAccount\n      chargesEnabled\n      detailsSubmitted\n    }\n  }\n",
6309      "name": "GraphQL request",
6310      "locationOffset": {
6311        "line": 1,
6312        "column": 1
6313      }
6314    }
6315  }
6316};
6317const ENABLE_MERCHANT_PAYMENTS_FROM_CHAT = {
6318  "kind": "Document",
6319  "definitions": [{
6320    "kind": "OperationDefinition",
6321    "operation": "mutation",
6322    "name": {
6323      "kind": "Name",
6324      "value": "EnableMerchantPaymentsFromChat"
6325    },
6326    "variableDefinitions": [{
6327      "kind": "VariableDefinition",
6328      "variable": {
6329        "kind": "Variable",
6330        "name": {
6331          "kind": "Name",
6332          "value": "returnTo"
6333        }
6334      },
6335      "type": {
6336        "kind": "NamedType",
6337        "name": {
6338          "kind": "Name",
6339          "value": "String"
6340        }
6341      },
6342      "directives": []
6343    }, {
6344      "kind": "VariableDefinition",
6345      "variable": {
6346        "kind": "Variable",
6347        "name": {
6348          "kind": "Name",
6349          "value": "websiteId"
6350        }
6351      },
6352      "type": {
6353        "kind": "NamedType",
6354        "name": {
6355          "kind": "Name",
6356          "value": "String"
6357        }
6358      },
6359      "directives": []
6360    }],
6361    "directives": [],
6362    "selectionSet": {
6363      "kind": "SelectionSet",
6364      "selections": [{
6365        "kind": "Field",
6366        "name": {
6367          "kind": "Name",
6368          "value": "enableMerchantPayments"
6369        },
6370        "arguments": [{
6371          "kind": "Argument",
6372          "name": {
6373            "kind": "Name",
6374            "value": "returnTo"
6375          },
6376          "value": {
6377            "kind": "Variable",
6378            "name": {
6379              "kind": "Name",
6380              "value": "returnTo"
6381            }
6382          }
6383        }, {
6384          "kind": "Argument",
6385          "name": {
6386            "kind": "Name",
6387            "value": "websiteId"
6388          },
6389          "value": {
6390            "kind": "Variable",
6391            "name": {
6392              "kind": "Name",
6393              "value": "websiteId"
6394            }
6395          }
6396        }],
6397        "directives": [],
6398        "selectionSet": {
6399          "kind": "SelectionSet",
6400          "selections": [{
6401            "kind": "Field",
6402            "name": {
6403              "kind": "Name",
6404              "value": "url"
6405            },
6406            "arguments": [],
6407            "directives": []
6408          }]
6409        }
6410      }]
6411    }
6412  }],
6413  "loc": {
6414    "start": 0,
6415    "end": 188,
6416    "source": {
6417      "body": "\n  mutation EnableMerchantPaymentsFromChat(\n    $returnTo: String\n    $websiteId: String\n  ) {\n    enableMerchantPayments(returnTo: $returnTo, websiteId: $websiteId) {\n      url\n    }\n  }\n",
6418      "name": "GraphQL request",
6419      "locationOffset": {
6420        "line": 1,
6421        "column": 1
6422      }
6423    }
6424  }
6425};
6426const FILE_TOOL_VERBS = {
6427  Edit: "Editing",
6428  MultiEdit: "Editing",
6429  Write: "Editing",
6430  Read: "Reading"
6431};
6432const ReactChatPanel = reactExports.forwardRef(({
6433  websiteId,
6434  isContainerReady = true,
6435  website,
6436  expanded = true,
6437  onToggleChatPanel,
6438  onRefetchWebsite,
6439  myWebsiteAccess,
6440  isHiddenForLoading,
6441  onAIRespondingChange,
6442  localAgencyCreditsDelta = 0,
6443  onAgencyCreditUsed,
6444  localAiChatMessagesDelta = 0,
6445  onAiChatMessageUsed,
6446  onCommitHashChange,
6447  onAgentBusyChange,
6448  onPaymentsDataChanged,
6449  onBusinessDataChanged,
6450  onShowView,
6451  inlineEditInProgress = false,
6452  pickModeActive = false,
6453  selectedElement = null,
6454  currentPath = "/",
6455  onTogglePickMode,
6456  onClearSelection,
6457  onRestoreSelection,
6458  isPickerAvailable = false,
6459  isSelectorReady = false,
6460  viteError = null
6461}, ref) => {
6462  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
6463  const [loading, setLoading] = reactExports.useState(false);
6464  const [messagesLoaded, setMessagesLoaded] = reactExports.useState(false);
6465  const shouldReloadMessagesRef = reactExports.useRef(false);
6466  const {
6467    getToken,
6468    isAuthenticated,
6469    currentUser,
6470    hasRole
6471  } = useAuth();
6472  const isAdmin = hasRole(["support"]);
6473  const posthog = usePostHog();
6474  const [isExpanded, setIsExpanded] = reactExports.useState(expanded);
6475  const [userInitiatedAnyTurn, setUserInitiatedAnyTurn] = reactExports.useState(false);
6476  const [isSubmitting, setIsSubmitting] = reactExports.useState(false);
6477  const [dispatchInFlight, setDispatchInFlight] = reactExports.useState(false);
6478  const [queue, setQueue] = reactExports.useState(emptyQueue);
6479  const queueRef = reactExports.useRef(queue);
6480  reactExports.useEffect(() => {
6481    queueRef.current = queue;
6482  }, [queue]);
6483  const [editingQueuedId, setEditingQueuedId] = reactExports.useState(null);
6484  const discardQueue = reactExports.useCallback(() => {
6485    const hadItems = queueRef.current.items.length > 0;
6486    queueRef.current = clearQueue(queueRef.current);
6487    setQueue(clearQueue);
6488    setEditingQueuedId(null);
6489    if (hadItems) _t("Queued messages discarded");
6490  }, []);
6491  const [stopLatched, setStopLatched] = reactExports.useState(false);
6492  const submitSafetyTimerRef = reactExports.useRef(null);
6493  const releaseSubmitFlag = reactExports.useCallback(() => {
6494    setIsSubmitting(false);
6495    if (submitSafetyTimerRef.current) {
6496      clearTimeout(submitSafetyTimerRef.current);
6497      submitSafetyTimerRef.current = null;
6498    }
6499  }, []);
6500  const [maxStepsReached, setMaxStepsReached] = reactExports.useState(false);
6501  const [chatSessionInProgress, setChatSessionInProgress] = reactExports.useState(false);
6502  const [showResetSuggestion, setShowResetSuggestion] = reactExports.useState(false);
6503  const [sessionLostNotice, setSessionLostNotice] = reactExports.useState(null);
6504  const [chatErrorMessage, setChatErrorMessage] = reactExports.useState("");
6505  const [isOverloadedError, setIsOverloadedError] = reactExports.useState(false);
6506  const [isOutOfCredits, setIsOutOfCredits] = reactExports.useState(false);
6507  const [isSessionExpired, setIsSessionExpired] = reactExports.useState(false);
6508  const lastUserMessageRef = reactExports.useRef("");
6509  const lastDispatchedSnapshotRef = reactExports.useRef(null);
6510  const hasSetSpecificErrorRef = reactExports.useRef(false);
6511  const [isSummarizing, setIsSummarizing] = reactExports.useState(false);
6512  const [inputValue, setInputValue] = reactExports.useState("");
6513  const [isRestoring, setIsRestoring] = reactExports.useState(false);
6514  const pendingChatRestoreRef = reactExports.useRef(null);
6515  const [chatStopped, setChatStopped] = reactExports.useState(false);
6516  const [isDragActive, setIsDragActive] = reactExports.useState(false);
6517  const [restoreMutation] = useMutation(RESTORE_TO_CHAT_MESSAGE);
6518  const [continueRestoreMutation] = useMutation(CONTINUE_CHAT_RESTORE);
6519  const {
6520    data: commerceIntentData,
6521    refetch: refetchCommerceIntent
6522  } = useQuery(WEBSITE_COMMERCE_INTENT, {
6523    variables: {
6524      websiteId
6525    },
6526    skip: !websiteId,
6527    pollInterval: 6e4,
6528    fetchPolicy: "cache-and-network"
6529  });
6530  const needsPaymentsSetup = Boolean((_a = commerceIntentData == null ? void 0 : commerceIntentData.websiteCommerceIntent) == null ? void 0 : _a.needsPaymentsSetup);
6531  const needsPaymentsUpgrade = Boolean((_b = commerceIntentData == null ? void 0 : commerceIntentData.websiteCommerceIntent) == null ? void 0 : _b.needsUpgrade);
6532  const canStartPaymentsOnboarding = Boolean((_c = commerceIntentData == null ? void 0 : commerceIntentData.websiteCommerceIntent) == null ? void 0 : _c.canStartOnboarding);
6533  const paymentsForInvoicing = Boolean((_d = commerceIntentData == null ? void 0 : commerceIntentData.websiteCommerceIntent) == null ? void 0 : _d.invoiceIntent) && !((_e = commerceIntentData == null ? void 0 : commerceIntentData.websiteCommerceIntent) == null ? void 0 : _e.hasProducts);
6534  const paymentsPending = Boolean((_f = commerceIntentData == null ? void 0 : commerceIntentData.websiteCommerceIntent) == null ? void 0 : _f.paymentsPending);
6535  const paymentsDisabled = Boolean((_g = commerceIntentData == null ? void 0 : commerceIntentData.websiteCommerceIntent) == null ? void 0 : _g.paymentsDisabled);
6536  const postageUnchargedFromServer = Boolean((_h = commerceIntentData == null ? void 0 : commerceIntentData.websiteCommerceIntent) == null ? void 0 : _h.postageUncharged);
6537  const currencyRestatedTo = ((_i = commerceIntentData == null ? void 0 : commerceIntentData.websiteCommerceIntent) == null ? void 0 : _i.currencyRestatedTo) ?? null;
6538  const currencyRestatedFrom = ((_j = commerceIntentData == null ? void 0 : commerceIntentData.websiteCommerceIntent) == null ? void 0 : _j.currencyRestatedFrom) ?? null;
6539  const [enablePaymentsFromChat] = useMutation(ENABLE_MERCHANT_PAYMENTS_FROM_CHAT);
6540  const [syncStripeConnectFromChat] = useMutation(SYNC_STRIPE_CONNECT_STATUS_FROM_CHAT);
6541  const [isStartingPaymentsSetup, setIsStartingPaymentsSetup] = reactExports.useState(false);
6542  const startingPaymentsRef = reactExports.useRef(false);
6543  const commerceSetup = (_k = commerceIntentData == null ? void 0 : commerceIntentData.websiteCommerceIntent) == null ? void 0 : _k.commerceSetup;
6544  const hasCommerceIntent = Boolean(((_l = commerceIntentData == null ? void 0 : commerceIntentData.websiteCommerceIntent) == null ? void 0 : _l.hasProducts) || ((_m = commerceIntentData == null ? void 0 : commerceIntentData.websiteCommerceIntent) == null ? void 0 : _m.invoiceIntent));
6545  const setupRefresh = useCommerceSetupRefresh({
6546    scopeKey: websiteId,
6547    enabled: canStartPaymentsOnboarding && hasCommerceIntent && (paymentsPending || paymentsDisabled || !!commerceSetup || !!((_n = commerceIntentData == null ? void 0 : commerceIntentData.websiteCommerceIntent) == null ? void 0 : _n.paymentsActive)),
6548    needsPolling: commerceSetupNeedsPolling(commerceSetup),
6549    load: async ({
6550      polling
6551    }) => {
6552      await syncStripeConnectFromChat({
6553        variables: {
6554          polling
6555        }
6556      });
6557      await refetchCommerceIntent();
6558    }
6559  });
6560  const visibleCommerceSetup = hasCommerceIntent && canStartPaymentsOnboarding ? commerceSetup : null;
6561  reactExports.useEffect(() => {
6562    const onPageShow = (e) => {
6563      if (e.persisted) {
6564        startingPaymentsRef.current = false;
6565        setIsStartingPaymentsSetup(false);
6566      }
6567    };
6568    window.addEventListener("pageshow", onPageShow);
6569    return () => window.removeEventListener("pageshow", onPageShow);
6570  }, []);
6571  const handleSetUpPayments = reactExports.useCallback(async () => {
6572    var _a2;
6573    if (startingPaymentsRef.current) return;
6574    startingPaymentsRef.current = true;
6575    setIsStartingPaymentsSetup(true);
6576    try {
6577      const {
6578        data
6579      } = await enablePaymentsFromChat({
6580        variables: {
6581          websiteId,
6582          returnTo: window.location.href
6583        }
6584      });
6585      const url = (_a2 = data == null ? void 0 : data.enableMerchantPayments) == null ? void 0 : _a2.url;
6586      if (url) {
6587        window.location.href = url;
6588        return;
6589      }
6590      _t.error("Could not start payment setup. Please try again.");
6591      startingPaymentsRef.current = false;
6592      setIsStartingPaymentsSetup(false);
6593    } catch (err) {
6594      _t.error(err instanceof Error ? err.message : "Could not start payment setup. Please try again.");
6595      startingPaymentsRef.current = false;
6596      setIsStartingPaymentsSetup(false);
6597    }
6598  }, [enablePaymentsFromChat, websiteId]);
6599  const messagesEndRef = reactExports.useRef(null);
6600  const messagesContainerRef = reactExports.useRef(null);
6601  const textareaRef = reactExports.useRef(null);
6602  const fileInputRef = reactExports.useRef(null);
6603  const [isGalleryOpen, setIsGalleryOpen] = reactExports.useState(false);
6604  const {
6605    images,
6606    isUploading: isUploadingImages,
6607    handleFileChange,
6608    handleGalleryMediaSelection,
6609    handleRemoveImage,
6610    handleClearImages,
6611    handleRestoreImages
6612  } = useUploadImage(websiteId, (rejectedFiles, message) => {
6613    if (message) {
6614      _t.error(message);
6615    } else {
6616      const fileTypes = rejectedFiles.map((f) => f.type).join(", ");
6617      _t.error(`${rejectedFiles.length} file(s) rejected. Only images and PDFs are allowed. Rejected types: ${fileTypes}`);
6618    }
6619  }, (error, _fileName) => {
6620    _t.error(error.message || "Failed to publish image");
6621  }, {
6622    processGalleryVideos: true
6623  });
6624  const handleInternalGalleryMediaSelection = (media) => {
6625    setIsGalleryOpen(false);
6626    const mediaData = JSON.stringify({
6627      id: media.id,
6628      src: media.src,
6629      type: media.type
6630    });
6631    handleGalleryMediaSelection({
6632      ...media,
6633      dataMedia: mediaData
6634    });
6635  };
6636  const adjustTextareaHeight = reactExports.useCallback(() => {
6637    if (textareaRef.current) {
6638      textareaRef.current.style.height = "44px";
6639      const scrollHeight = textareaRef.current.scrollHeight;
6640      const maxHeight = 120;
6641      const newHeight = Math.min(scrollHeight, maxHeight);
6642      textareaRef.current.style.height = `${newHeight}px`;
6643    }
6644  }, []);
6645  reactExports.useEffect(() => {
6646    adjustTextareaHeight();
6647  }, [inputValue, adjustTextareaHeight]);
6648  const [pickerLiveMessage, setPickerLiveMessage] = reactExports.useState("");
6649  const prevPickModeActiveRef = reactExports.useRef(pickModeActive);
6650  reactExports.useEffect(() => {
6651    const prev = prevPickModeActiveRef.current;
6652    if (!prev && pickModeActive) {
6653      setPickerLiveMessage("Element picker active");
6654    } else if (prev && !pickModeActive) {
6655      setPickerLiveMessage("Element picker cancelled");
6656    }
6657    prevPickModeActiveRef.current = pickModeActive;
6658  }, [pickModeActive]);
6659  const prevSelectedElementRef = reactExports.useRef(selectedElement);
6660  reactExports.useEffect(() => {
6661    const prev = prevSelectedElementRef.current;
6662    if (!prev && selectedElement) {
6663      posthog == null ? void 0 : posthog.capture("picker_element_selected", {
6664        tag: selectedElement.tag
6665      });
6666    }
6667    prevSelectedElementRef.current = selectedElement;
6668  }, [selectedElement, posthog]);
6669  const pickerButtonHidden = !isPickerAvailable;
6670  const pickerButtonDisabled = !isSelectorReady;
6671  const pickerButtonTooltip = pickerButtonDisabled ? "Preview loading — try again in a moment" : "Pick an element";
6672  const handlePickerButtonClick = reactExports.useCallback(() => {
6673    if (pickerButtonDisabled || !onTogglePickMode) return;
6674    const next = !pickModeActive;
6675    posthog == null ? void 0 : posthog.capture("picker_button_clicked", {
6676      pick_mode_active: next
6677    });
6678    onTogglePickMode();
6679  }, [pickerButtonDisabled, onTogglePickMode, pickModeActive, posthog]);
6680  const handleChipClear = reactExports.useCallback(() => {
6681    onClearSelection == null ? void 0 : onClearSelection();
6682    requestAnimationFrame(() => {
6683      var _a2;
6684      (_a2 = textareaRef.current) == null ? void 0 : _a2.focus();
6685    });
6686  }, [onClearSelection]);
6687  const autoScrollActiveRef = reactExports.useRef(false);
6688  const userInteractedRef = reactExports.useRef(false);
6689  const rafIdRef = reactExports.useRef(null);
6690  const isPinnedToBottomRef = reactExports.useRef(true);
6691  const [showScrollToBottom, setShowScrollToBottom] = reactExports.useState(false);
6692  const FREE_PLAN_CHAT_LIMIT = 10;
6693  const websitePlan = (website == null ? void 0 : website.stripePlan) || "Free";
6694  const aiChatMessagesUsed = ((website == null ? void 0 : website.aiChatMessagesUsed) || 0) + localAiChatMessagesDelta;
6695  const monthlyUsed = (website == null ? void 0 : website.chatMonthlyUsed) || 0;
6696  const monthlyAllotment = (website == null ? void 0 : website.chatMonthlyAllotment) || 0;
6697  const purchasedCredits = (website == null ? void 0 : website.chatPurchasedCredits) || 0;
6698  const isAgencyUser = ((_o = website == null ? void 0 : website.user) == null ? void 0 : _o.isAgencyPlan) === true;
6699  const agencyTotalCredits = (((_p = website == null ? void 0 : website.user) == null ? void 0 : _p.agencyTotalCredits) || 0) + localAgencyCreditsDelta;
6700  const isFree = websitePlan === "Free";
6701  const websiteCreditsRemaining = Math.max(0, monthlyAllotment + purchasedCredits - monthlyUsed);
6702  let remainingChats;
6703  if (isAgencyUser) {
6704    if (!isFree && websiteCreditsRemaining > 0) {
6705      remainingChats = websiteCreditsRemaining;
6706    } else {
6707      remainingChats = agencyTotalCredits;
6708    }
6709  } else {
6710    remainingChats = isFree ? Math.max(0, FREE_PLAN_CHAT_LIMIT - aiChatMessagesUsed) + purchasedCredits : Math.max(0, monthlyAllotment + purchasedCredits - monthlyUsed);
6711  }
6712  const isChatLimitReached = isFree && !isAgencyUser && !isAdmin && aiChatMessagesUsed >= FREE_PLAN_CHAT_LIMIT && purchasedCredits <= 0;
6713  const sseChat = useAgentSSE({
6714    publicId: (website == null ? void 0 : website.publicId) || "",
6715    websiteId,
6716    getToken: async () => {
6717      const token = await getToken();
6718      return token || null;
6719    },
6720    onError: (error) => {
6721      console.error("[SSE Agent] Error:", error.message);
6722      setChatErrorMessage(error.message);
6723      const type = error.type;
6724      setIsOverloadedError(!!type && RETRYABLE_AGENT_ERROR_TYPES.has(type));
6725      if (error.message.toLowerCase().includes("credits") || error.message.toLowerCase().includes("out of")) {
6726        setIsOutOfCredits(true);
6727      }
6728    },
6729    onSessionWarning: ({
6730      reason,
6731      message
6732    }) => {
6733      if (reason === "session_lost" || reason === "session_upload") {
6734        setSessionLostNotice(message || "Previous chat history couldn't be restored. The assistant won't remember earlier turns in this conversation.");
6735      } else {
6736        setShowResetSuggestion(true);
6737      }
6738    },
6739    onSessionExpired: (message) => {
6740      setIsSessionExpired(true);
6741      const fallback = lastUserMessageRef.current ? "Your session needs to refresh — send a new message or click Try Again to continue." : "Your session needs to refresh — send a new message to continue.";
6742      setChatErrorMessage(message || fallback);
6743    },
6744    onChatReset: () => {
6745      setShowResetSuggestion(false);
6746      setSessionLostNotice(null);
6747      setChatErrorMessage("");
6748      setIsOverloadedError(false);
6749      setIsSessionExpired(false);
6750      discardQueue();
6751    },
6752    onNavigate: (target) => {
6753      navigate(target);
6754    },
6755    // The page coordinator owns the merchant-view swap; forward the
6756    // page-stable callback as-is (the hook dedups + staleness-filters).
6757    onShowView
6758  });
6759  const agentMessages = sseChat.messages;
6760  const agentMessagesRef = reactExports.useRef(agentMessages);
6761  reactExports.useEffect(() => {
6762    agentMessagesRef.current = agentMessages;
6763  }, [agentMessages]);
6764  const sendAgentMessage = sseChat.sendMessage;
6765  const stopAgentChat = sseChat.stop;
6766  const agentChatStatus = sseChat.status;
6767  const agentIsLoading = sseChat.isLoading;
6768  const agentBusy = agentChatStatus === "connecting" || agentChatStatus === "streaming";
6769  reactExports.useEffect(() => {
6770    onAgentBusyChange == null ? void 0 : onAgentBusyChange(agentBusy);
6771  }, [agentBusy, onAgentBusyChange]);
6772  const prevAgentBusyRef = reactExports.useRef(false);
6773  reactExports.useEffect(() => {
6774    const prev = prevAgentBusyRef.current;
6775    prevAgentBusyRef.current = agentBusy;
6776    if (!(prev && !agentBusy)) return;
6777    const targets = turnEndRefreshTargets(completedToolNamesInTurn(agentMessagesRef.current));
6778    if (targets.preview) onPaymentsDataChanged == null ? void 0 : onPaymentsDataChanged();
6779    if (targets.commerceIntent) refetchCommerceIntent();
6780  }, [agentBusy, onPaymentsDataChanged, refetchCommerceIntent]);
6781  const prevAgentBusyForBusinessRef = reactExports.useRef(false);
6782  reactExports.useEffect(() => {
6783    const prev = prevAgentBusyForBusinessRef.current;
6784    prevAgentBusyForBusinessRef.current = agentBusy;
6785    if (!(prev && !agentBusy)) return;
6786    const targets = turnEndRefreshTargets(completedToolNamesInTurn(agentMessagesRef.current));
6787    if (targets.business) onBusinessDataChanged == null ? void 0 : onBusinessDataChanged();
6788  }, [agentBusy, onBusinessDataChanged]);
6789  const setAgentMessages = sseChat.setMessages;
6790  const clearAgentHistory = sseChat.clearHistory;
6791  const pendingApproval = sseChat.pendingApproval;
6792  const approvalSubmitting = sseChat.approvalSubmitting;
6793  const respondToApproval = sseChat.respondToApproval;
6794  const pendingQuestion = sseChat.pendingQuestion;
6795  const respondToQuestion = sseChat.respondToQuestion;
6796  const thinking = sseChat.thinking;
6797  const maxTurnsHit = sseChat.maxTurnsHit;
6798  const mergedRunCacheRef = reactExports.useRef(/* @__PURE__ */ new Map());
6799  const displayMessages = reactExports.useMemo(() => {
6800    const {
6801      merged,
6802      nextCache
6803    } = mergeAssistantRuns(agentMessages, mergedRunCacheRef.current);
6804    mergedRunCacheRef.current = nextCache;
6805    return merged;
6806  }, [agentMessages]);
6807  const isAIResponding = sseChat.status === "streaming";
6808  reactExports.useEffect(() => {
6809    if (isAIResponding && isSubmitting) {
6810      setIsSubmitting(false);
6811      if (submitSafetyTimerRef.current) {
6812        clearTimeout(submitSafetyTimerRef.current);
6813        submitSafetyTimerRef.current = null;
6814      }
6815    }
6816  }, [isAIResponding, isSubmitting]);
6817  reactExports.useEffect(() => {
6818    return () => {
6819      if (submitSafetyTimerRef.current) {
6820        clearTimeout(submitSafetyTimerRef.current);
6821      }
6822    };
6823  }, []);
6824  const isFirstGenerationInProgress = (website == null ? void 0 : website.websiteType) === "react" && !(website == null ? void 0 : website.homepageGeneratedAt) && !userInitiatedAnyTurn;
6825  reactExports.useEffect(() => {
6826    onAIRespondingChange == null ? void 0 : onAIRespondingChange(isAIResponding);
6827  }, [isAIResponding, onAIRespondingChange]);
6828  const wasAIRespondingRef = reactExports.useRef(isAIResponding);
6829  reactExports.useEffect(() => {
6830    const wasResponding = wasAIRespondingRef.current;
6831    wasAIRespondingRef.current = isAIResponding;
6832    if (!wasResponding || isAIResponding) return;
6833    const active = document.activeElement;
6834    const focusable = !active || active === document.body || active === textareaRef.current;
6835    if (!focusable) return;
6836    requestAnimationFrame(() => {
6837      var _a2;
6838      (_a2 = textareaRef.current) == null ? void 0 : _a2.focus();
6839    });
6840  }, [isAIResponding]);
6841  reactExports.useEffect(() => {
6842    if (!websiteId) return;
6843    setLoading(sseChat.historyLoading);
6844    if (!sseChat.historyLoading) {
6845      setMessagesLoaded(true);
6846    }
6847  }, [websiteId, sseChat.historyLoading]);
6848  const lastReportedCommitHashRef = reactExports.useRef(null);
6849  reactExports.useEffect(() => {
6850    var _a2;
6851    if (!onCommitHashChange || agentMessages.length === 0) return;
6852    for (let i = agentMessages.length - 1; i >= 0; i--) {
6853      const msg = agentMessages[i];
6854      if (msg.role === "assistant" && ((_a2 = msg.metadata) == null ? void 0 : _a2.commitHash)) {
6855        const hash = msg.metadata.commitHash;
6856        if (hash !== lastReportedCommitHashRef.current) {
6857          lastReportedCommitHashRef.current = hash;
6858          onCommitHashChange(hash);
6859        }
6860        break;
6861      }
6862    }
6863  }, [agentMessages, onCommitHashChange]);
6864  const scrollToBottom = reactExports.useCallback((delay = 50) => {
6865    setTimeout(() => {
6866      var _a2;
6867      (_a2 = messagesEndRef.current) == null ? void 0 : _a2.scrollIntoView({
6868        behavior: "smooth"
6869      });
6870    }, delay);
6871  }, []);
6872  const stopAlignLastUserAutoScroll = reactExports.useCallback(() => {
6873    if (rafIdRef.current) {
6874      cancelAnimationFrame(rafIdRef.current);
6875      rafIdRef.current = null;
6876    }
6877    autoScrollActiveRef.current = false;
6878  }, []);
6879  const alignLastUserAutoScrollStep = reactExports.useCallback(() => {
6880    const container = messagesContainerRef.current;
6881    if (!container || !autoScrollActiveRef.current) {
6882      stopAlignLastUserAutoScroll();
6883      return;
6884    }
6885    if (userInteractedRef.current) {
6886      stopAlignLastUserAutoScroll();
6887      return;
6888    }
6889    const userMessages = container.querySelectorAll('[data-role="user"]');
6890    const lastUserMessage = userMessages[userMessages.length - 1];
6891    if (!lastUserMessage) {
6892      stopAlignLastUserAutoScroll();
6893      return;
6894    }
6895    const lastUserRect = lastUserMessage.getBoundingClientRect();
6896    const containerRect = container.getBoundingClientRect();
6897    const targetTop = containerRect.top + 5;
6898    const currentUserTop = lastUserRect.top;
6899    if (currentUserTop <= targetTop) {
6900      stopAlignLastUserAutoScroll();
6901      return;
6902    }
6903    const scrollDelta = Math.min(24, currentUserTop - targetTop);
6904    container.scrollTop += scrollDelta;
6905    rafIdRef.current = requestAnimationFrame(alignLastUserAutoScrollStep);
6906  }, [stopAlignLastUserAutoScroll]);
6907  const startAlignLastUserAutoScroll = reactExports.useCallback(() => {
6908    const container = messagesContainerRef.current;
6909    if (!container) return;
6910    const userMessages = container.querySelectorAll('[data-role="user"]');
6911    const lastUserMessage = userMessages[userMessages.length - 1];
6912    if (!lastUserMessage) {
6913      scrollToBottom(50);
6914      return;
6915    }
6916    const lastUserRect = lastUserMessage.getBoundingClientRect();
6917    const containerRect = container.getBoundingClientRect();
6918    const targetTop = containerRect.top + 5;
6919    if (lastUserRect.top <= targetTop) {
6920      return;
6921    }
6922    userInteractedRef.current = false;
6923    autoScrollActiveRef.current = true;
6924    rafIdRef.current = requestAnimationFrame(alignLastUserAutoScrollStep);
6925  }, [alignLastUserAutoScrollStep, scrollToBottom]);
6926  const checkScrollPosition = reactExports.useCallback(() => {
6927    const container = messagesContainerRef.current;
6928    if (!container) return;
6929    const {
6930      scrollTop,
6931      scrollHeight,
6932      clientHeight
6933    } = container;
6934    const isAtBottom = scrollTop + clientHeight >= scrollHeight - 10;
6935    const shouldShow = !isAtBottom && agentMessages.length > 0;
6936    isPinnedToBottomRef.current = isAtBottom;
6937    setShowScrollToBottom(shouldShow);
6938  }, [agentMessages.length]);
6939  reactExports.useEffect(() => {
6940    const timeoutId = setTimeout(() => {
6941      checkScrollPosition();
6942    }, 200);
6943    return () => clearTimeout(timeoutId);
6944  }, [agentMessages, checkScrollPosition]);
6945  reactExports.useLayoutEffect(() => {
6946    if (!isPinnedToBottomRef.current) return;
6947    const container = messagesContainerRef.current;
6948    if (!container) return;
6949    container.scrollTop = container.scrollHeight;
6950  }, [agentMessages]);
6951  reactExports.useEffect(() => {
6952    const container = messagesContainerRef.current;
6953    if (!container) return;
6954    const handleUserInteraction = () => {
6955      userInteractedRef.current = true;
6956      stopAlignLastUserAutoScroll();
6957    };
6958    container.addEventListener("wheel", handleUserInteraction, {
6959      passive: true
6960    });
6961    container.addEventListener("touchstart", handleUserInteraction, {
6962      passive: true
6963    });
6964    container.addEventListener("mousedown", handleUserInteraction);
6965    return () => {
6966      container.removeEventListener("wheel", handleUserInteraction);
6967      container.removeEventListener("touchstart", handleUserInteraction);
6968      container.removeEventListener("mousedown", handleUserInteraction);
6969      stopAlignLastUserAutoScroll();
6970    };
6971  }, [stopAlignLastUserAutoScroll]);
6972  const sendMessageWithAuth = reactExports.useCallback(async (message) => {
6973    setChatStopped(false);
6974    return await sendAgentMessage(message);
6975  }, [sendAgentMessage]);
6976  const dispatchSnapshot = reactExports.useCallback(async (snapshot, options) => {
6977    const messageText = snapshot.text;
6978    if (!messageText.trim()) return;
6979    if (!isContainerReady) {
6980      console.warn("Cannot submit while container is starting");
6981      return;
6982    }
6983    if (agentChatStatus === "streaming") {
6984      console.warn("Cannot submit while AI is already responding");
6985      return;
6986    }
6987    setIsSubmitting(true);
6988    if (submitSafetyTimerRef.current) {
6989      clearTimeout(submitSafetyTimerRef.current);
6990    }
6991    submitSafetyTimerRef.current = setTimeout(() => {
6992      setIsSubmitting(false);
6993      submitSafetyTimerRef.current = null;
6994    }, 15e3);
6995    setDispatchInFlight(true);
6996    try {
6997      if (!(options == null ? void 0 : options.isInitialCreation)) {
6998        setUserInitiatedAnyTurn(true);
6999      }
7000      setTimeout(() => {
7001        scrollToBottom(100);
7002      }, 100);
7003      setTimeout(() => {
7004        startAlignLastUserAutoScroll();
7005      }, 50);
7006      setMaxStepsReached(false);
7007      setIsOutOfCredits(false);
7008      setChatSessionInProgress(false);
7009      setChatErrorMessage("");
7010      setIsOverloadedError(false);
7011      setIsSessionExpired(false);
7012      const previousLastUserMessage = lastUserMessageRef.current;
7013      const previousLastSnapshot = lastDispatchedSnapshotRef.current;
7014      lastUserMessageRef.current = messageText;
7015      lastDispatchedSnapshotRef.current = snapshot;
7016      let token = null;
7017      try {
7018        token = await getFreshToken(getToken, 5);
7019      } catch (error) {
7020        console.error("[ReactChatPanel] Token refresh failed:", error);
7021      }
7022      if (!token) {
7023        lastUserMessageRef.current = previousLastUserMessage;
7024        lastDispatchedSnapshotRef.current = previousLastSnapshot;
7025        setChatErrorMessage(AUTH_REQUIRED_MESSAGE);
7026        releaseSubmitFlag();
7027        return void 0;
7028      }
7029      if ((options == null ? void 0 : options.generation) !== void 0 && options.generation !== queueRef.current.generation) {
7030        lastUserMessageRef.current = previousLastUserMessage;
7031        lastDispatchedSnapshotRef.current = previousLastSnapshot;
7032        releaseSubmitFlag();
7033        return "cancelled";
7034      }
7035      const tokenInfo = getTokenExpirationInfo(token);
7036      const tokenMinutesLeft = tokenInfo.valid ? tokenInfo.minutesUntilExpiration : -1;
7037      const {
7038        message,
7039        selectionShipped,
7040        selectionRejected
7041      } = buildAgentMessage(snapshot, {
7042        websitePlan,
7043        isAgencyUser,
7044        website: {
7045          publicId: website == null ? void 0 : website.publicId,
7046          analyticsId: website == null ? void 0 : website.analyticsId,
7047          Domain: website == null ? void 0 : website.Domain
7048        },
7049        currentUserId: currentUser == null ? void 0 : currentUser.id,
7050        tokenMinutesLeft,
7051        isInitialCreation: options == null ? void 0 : options.isInitialCreation
7052      });
7053      if (selectionRejected) {
7054        _t.error("Selected element is too large to attach — try picking a smaller element");
7055        setPickerLiveMessage("Selected element is too large to attach — try picking a smaller element");
7056      }
7057      try {
7058        const result = await sendMessageWithAuth(message);
7059        releaseSubmitFlag();
7060        if (result === "turn_active") {
7061          lastUserMessageRef.current = previousLastUserMessage;
7062          lastDispatchedSnapshotRef.current = previousLastSnapshot;
7063          return result;
7064        }
7065        if (result === "failed") {
7066          return result;
7067        }
7068        if (selectionShipped) {
7069          posthog == null ? void 0 : posthog.capture("picker_message_sent", {
7070            tag: snapshot.selectedElement.tag
7071          });
7072        }
7073        if (isAgencyUser && onAgencyCreditUsed) {
7074          if (isFree || websiteCreditsRemaining <= 0) {
7075            onAgencyCreditUsed();
7076          }
7077        }
7078        onAiChatMessageUsed == null ? void 0 : onAiChatMessageUsed();
7079        return result;
7080      } catch (error) {
7081        console.error("Error sending message:", error);
7082        setChatErrorMessage(error instanceof Error ? error.message : String(error));
7083        releaseSubmitFlag();
7084        return "failed";
7085      }
7086    } finally {
7087      setDispatchInFlight(false);
7088    }
7089  }, [websitePlan, currentUser, getToken, sendMessageWithAuth, startAlignLastUserAutoScroll, scrollToBottom, agentChatStatus, website == null ? void 0 : website.publicId, website == null ? void 0 : website.analyticsId, website == null ? void 0 : website.Domain, isAgencyUser, isFree, websiteCreditsRemaining, onAgencyCreditUsed, onAiChatMessageUsed, posthog, releaseSubmitFlag]);
7090  const selectedElementRef = reactExports.useRef(selectedElement);
7091  selectedElementRef.current = selectedElement;
7092  const submitMessage = reactExports.useCallback(async (messageText, options) => {
7093    if (!messageText.trim()) return;
7094    const snapshot = {
7095      text: messageText,
7096      images,
7097      selectedElement,
7098      currentPath
7099    };
7100    if (snapshot.selectedElement) {
7101      onClearSelection == null ? void 0 : onClearSelection();
7102    }
7103    handleClearImages();
7104    const result = await dispatchSnapshot(snapshot, options);
7105    if (result === void 0) {
7106      const settled = (snapshot.images ?? []).filter((image) => !image.uploading && !image.error);
7107      if (settled.length > 0) {
7108        handleRestoreImages(settled.map(snapshotImage));
7109      }
7110      if (snapshot.selectedElement && !selectedElementRef.current) {
7111        onRestoreSelection == null ? void 0 : onRestoreSelection(snapshot.selectedElement);
7112      }
7113    }
7114    return result;
7115  }, [images, selectedElement, currentPath, onClearSelection, onRestoreSelection, handleClearImages, handleRestoreImages, dispatchSnapshot]);
7116  const enqueueText = reactExports.useCallback((text) => {
7117    if (!text.trim()) return;
7118    const hasSelection = !!selectedElement;
7119    const snapshotImages = images.filter((image) => !image.error && !image.uploading);
7120    setQueue((state) => enqueue(state, {
7121      text,
7122      images: snapshotImages,
7123      selectedElement: selectedElement ?? null,
7124      currentPath
7125    }));
7126    if (hasSelection) {
7127      onClearSelection == null ? void 0 : onClearSelection();
7128    }
7129    if (images.some((image) => image.uploading)) {
7130      images.filter((image) => !image.uploading).forEach((image) => handleRemoveImage(image.index));
7131    } else {
7132      handleClearImages();
7133    }
7134    setPickerLiveMessage("Message queued — it will send when the AI finishes");
7135    posthog == null ? void 0 : posthog.capture("chat_message_queued", {
7136      queue_length: queueRef.current.items.length + 1,
7137      has_images: snapshotImages.length > 0,
7138      has_selection: hasSelection
7139    });
7140  }, [images, selectedElement, currentPath, onClearSelection, handleClearImages, handleRemoveImage, posthog]);
7141  const submitOrQueue = reactExports.useCallback((text, options) => {
7142    const busy = agentChatStatus === "connecting" || agentChatStatus === "streaming" || isSubmitting || dispatchInFlight;
7143    if (busy) {
7144      enqueueText(text);
7145      return;
7146    }
7147    void submitMessage(text, options);
7148  }, [agentChatStatus, isSubmitting, dispatchInFlight, enqueueText, submitMessage]);
7149  const sendQueued = reactExports.useCallback(async (item, state, via) => {
7150    const outcome = await dispatchSnapshot({
7151      text: item.text,
7152      images: [...item.images],
7153      selectedElement: item.selectedElement,
7154      currentPath: item.currentPath
7155    }, {
7156      generation: state.generation
7157    });
7158    if (outcome === "started") {
7159      posthog == null ? void 0 : posthog.capture("chat_queued_message_sent", {
7160        queue_length_remaining: state.items.length,
7161        has_images: item.images.length > 0,
7162        has_selection: !!item.selectedElement,
7163        via
7164      });
7165      return;
7166    }
7167    if (outcome === "turn_active" || outcome === void 0) {
7168      setQueue((current) => shouldRequeueAfterConflict(state.generation, current.generation) ? unshift(current, item) : current);
7169    }
7170  }, [dispatchSnapshot, posthog]);
7171  const handleContinueAfterMaxTurns = reactExports.useCallback(async () => {
7172    if (agentIsLoading) return;
7173    const message = {
7174      role: "user",
7175      parts: [{
7176        type: "text",
7177        text: "Continue"
7178      }],
7179      id: generateId(),
7180      metadata: {
7181        userIdForAnalyticsOnly: currentUser == null ? void 0 : currentUser.id,
7182        isPaidWebsite: websitePlan !== "Free",
7183        websitePlan,
7184        publicId: (website == null ? void 0 : website.publicId) || void 0
7185      }
7186    };
7187    setDispatchInFlight(true);
7188    try {
7189      await sendMessageWithAuth(message);
7190    } catch (err) {
7191      console.error("[ReactChatPanel] Continue failed:", err);
7192    } finally {
7193      setDispatchInFlight(false);
7194    }
7195  }, [agentIsLoading, currentUser == null ? void 0 : currentUser.id, websitePlan, website == null ? void 0 : website.publicId, sendMessageWithAuth]);
7196  reactExports.useImperativeHandle(ref, () => ({
7197    sendUserMessage: (message, options) => {
7198      submitOrQueue(message, options);
7199    },
7200    reloadMessages: () => {
7201      shouldReloadMessagesRef.current = true;
7202      setMessagesLoaded(false);
7203    }
7204  }), [submitOrQueue]);
7205  reactExports.useEffect(() => {
7206    setIsExpanded(expanded);
7207  }, [expanded]);
7208  reactExports.useEffect(() => {
7209    onToggleChatPanel == null ? void 0 : onToggleChatPanel(isExpanded);
7210  }, [isExpanded, onToggleChatPanel]);
7211  const handleClearAgentHistory = async () => {
7212    let token = null;
7213    try {
7214      token = await getToken();
7215    } catch (error) {
7216      console.error("[ReactChatPanel] Token lookup for reset failed:", error);
7217    }
7218    if (!token) {
7219      setChatErrorMessage(AUTH_REQUIRED_MESSAGE);
7220      return;
7221    }
7222    discardQueue();
7223    try {
7224      await clearAgentHistory();
7225    } catch {
7226      return;
7227    }
7228    setShowResetSuggestion(false);
7229    setSessionLostNotice(null);
7230    setChatErrorMessage("");
7231    setIsOverloadedError(false);
7232    setIsSessionExpired(false);
7233    hasSetSpecificErrorRef.current = false;
7234    lastUserMessageRef.current = "";
7235    lastDispatchedSnapshotRef.current = null;
7236  };
7237  const handleRetryLastMessage = reactExports.useCallback(async () => {
7238    if (!lastUserMessageRef.current) return;
7239    setChatErrorMessage("");
7240    setIsOverloadedError(false);
7241    setIsSessionExpired(false);
7242    if (agentMessages.length > 0 && setAgentMessages) {
7243      const lastMessage = agentMessages[agentMessages.length - 1];
7244      if (lastMessage.role === "user") {
7245        const updatedMessages = agentMessages.slice(0, -1);
7246        setAgentMessages(updatedMessages);
7247      }
7248    }
7249    const snapshot = lastDispatchedSnapshotRef.current;
7250    if (snapshot && snapshot.text === lastUserMessageRef.current) {
7251      await dispatchSnapshot(snapshot);
7252      return;
7253    }
7254    await submitMessage(lastUserMessageRef.current);
7255  }, [agentMessages, setAgentMessages, submitMessage, dispatchSnapshot]);
7256  const handleFixViteError = reactExports.useCallback(async () => {
7257    if (!viteError) return;
7258    if (isAIResponding || isRestoring || isChatLimitReached || !isContainerReady || !(myWebsiteAccess == null ? void 0 : myWebsiteAccess.canEdit)) {
7259      return;
7260    }
7261    const lines = ["Please fix the build error in my website preview so it can show my latest changes.", ""];
7262    if (viteError.file) lines.push(`File: ${viteError.file}`);
7263    if (viteError.message) lines.push(`Error: ${viteError.message}`);
7264    if (viteError.path) lines.push(`Page where this happened: ${viteError.path}`);
7265    if (viteError.frame) {
7266      lines.push("", "Code frame from the build tool:", "```", viteError.frame, "```");
7267    }
7268    await submitMessage(lines.join("\n"));
7269  }, [viteError, isAIResponding, isRestoring, isChatLimitReached, isContainerReady, myWebsiteAccess == null ? void 0 : myWebsiteAccess.canEdit, submitMessage]);
7270  const mode = composerMode({
7271    status: agentChatStatus,
7272    submitting: isSubmitting || dispatchInFlight,
7273    chatLimitReached: isChatLimitReached,
7274    restoring: isRestoring,
7275    containerReady: isContainerReady,
7276    canEdit: !!(myWebsiteAccess == null ? void 0 : myWebsiteAccess.canEdit),
7277    pendingApproval: !!pendingApproval,
7278    pendingQuestion: !!pendingQuestion,
7279    inlineEditInProgress
7280  });
7281  const composerLocked = mode === "locked";
7282  const panelError = !!chatErrorMessage || isSessionExpired || isOutOfCredits;
7283  const canResetFromError = !isOverloadedError;
7284  const drainDecision = drainGate({
7285    status: agentChatStatus,
7286    pendingApproval: !!pendingApproval,
7287    pendingQuestion: !!pendingQuestion,
7288    maxTurnsHit,
7289    panelError,
7290    chatLimitReached: isChatLimitReached,
7291    canEdit: !!(myWebsiteAccess == null ? void 0 : myWebsiteAccess.canEdit),
7292    restoring: isRestoring,
7293    containerReady: isContainerReady,
7294    submitting: isSubmitting || dispatchInFlight,
7295    stopLatched,
7296    // A queued row being edited, or the user editing text directly in the
7297    // preview: either way the queued AI edit must wait for them to finish.
7298    editing: editingQueuedId !== null || inlineEditInProgress
7299  });
7300  const pausedReason = queue.items.length > 0 && DRAIN_PAUSED_REASONS.includes(drainDecision) ? drainDecision : null;
7301  reactExports.useEffect(() => {
7302    if (stopLatched && agentChatStatus === "idle") setStopLatched(false);
7303  }, [stopLatched, agentChatStatus]);
7304  const prevDecisionRef = reactExports.useRef(null);
7305  reactExports.useEffect(() => {
7306    const prev = prevDecisionRef.current;
7307    prevDecisionRef.current = drainDecision;
7308    if (!drainTransition(prev, drainDecision)) return;
7309    const {
7310      head,
7311      state
7312    } = shiftHead(queueRef.current);
7313    if (!head) return;
7314    queueRef.current = state;
7315    setQueue(state);
7316    void sendQueued(head, state, "drain");
7317  }, [drainDecision, sendQueued]);
7318  const enqueueComposer = () => {
7319    const text = inputValue.trim();
7320    if (!text) return;
7321    enqueueText(text);
7322    setInputValue("");
7323    if (textareaRef.current) {
7324      textareaRef.current.style.height = "44px";
7325    }
7326  };
7327  const handleFormSubmit = async (e) => {
7328    e.preventDefault();
7329    if (!inputValue.trim()) return;
7330    if (composerLocked) return;
7331    if (mode === "busy" && isUploadingImages) return;
7332    if (pickModeActive && !selectedElement) {
7333      onTogglePickMode == null ? void 0 : onTogglePickMode();
7334      _t(mode === "busy" ? "Pick mode cancelled — message queued without selection" : "Pick mode cancelled — message sent without selection");
7335    }
7336    if (mode === "busy") {
7337      enqueueComposer();
7338      return;
7339    }
7340    const message = inputValue.trim();
7341    setInputValue("");
7342    if (textareaRef.current) {
7343      textareaRef.current.style.height = "44px";
7344    }
7345    await submitMessage(message);
7346  };
7347  const handleKeyDown = (e) => {
7348    if (e.key === "Enter" && !e.shiftKey) {
7349      e.preventDefault();
7350      if (!inputValue.trim() || composerLocked) {
7351        return;
7352      }
7353      handleFormSubmit(e);
7354    }
7355  };
7356  const handleUpdateQueuedText = reactExports.useCallback((id, text) => {
7357    const state = updateText(queueRef.current, id, text);
7358    if (state === queueRef.current) return;
7359    queueRef.current = state;
7360    setQueue(state);
7361  }, []);
7362  const handleRemoveQueued = reactExports.useCallback((id) => setQueue((state) => removeItem(state, id)), []);
7363  const handleSendQueuedNow = reactExports.useCallback((id) => {
7364    const current = queueRef.current;
7365    const item = current.items.find((entry) => entry.id === id);
7366    if (!item) return;
7367    const state = removeItem(current, id);
7368    queueRef.current = state;
7369    setQueue(state);
7370    void sendQueued(item, state, "send_now");
7371  }, [sendQueued]);
7372  const handleStopAgentChat = async () => {
7373    try {
7374      setChatStopped(true);
7375      setStopLatched(true);
7376      const queuedCount = queueRef.current.items.length;
7377      const {
7378        merged,
7379        state: emptied
7380      } = mergeOut(queueRef.current, {
7381        text: inputValue,
7382        hasSelection: !!selectedElement
7383      });
7384      queueRef.current = emptied;
7385      setQueue(emptied);
7386      setEditingQueuedId(null);
7387      if (queuedCount > 0) {
7388        setInputValue(merged.text);
7389        if (merged.images.length > 0) {
7390          handleRestoreImages(merged.images);
7391        }
7392        if (merged.selectedElement) {
7393          onRestoreSelection == null ? void 0 : onRestoreSelection(merged.selectedElement);
7394        }
7395        if (merged.droppedSelections > 0) {
7396          _t(merged.droppedSelections === 1 ? "A queued element selection was dropped — only one can be attached" : `${merged.droppedSelections} queued element selections were dropped — only one can be attached`);
7397        }
7398        posthog == null ? void 0 : posthog.capture("chat_queue_returned_on_
7398stop", {
7399          queue_length: queuedCount,
7400          has_images: merged.images.length > 0,
7401          has_selection: !!merged.selectedElement
7402        });
7403      }
7404      stopAgentChat();
7405      if (agentMessages.length > 0 && setAgentMessages) {
7406        const lastMessage = agentMessages[agentMessages.length - 1];
7407        if (lastMessage.role === "assistant") {
7408          const updatedMessages = [...agentMessages];
7409          updatedMessages[updatedMessages.length - 1] = {
7410            ...lastMessage,
7411            metadata: {
7412              ...lastMessage.metadata,
7413              aborted: true,
7414              abortedAt: (/* @__PURE__ */ new Date()).toISOString()
7415            }
7416          };
7417          setAgentMessages(updatedMessages);
7418        }
7419      }
7420      setTimeout(() => {
7421        setChatSessionInProgress(false);
7422      }, 500);
7423    } catch (error) {
7424      console.error("Error stopping agent chat:", error);
7425      setChatSessionInProgress(false);
7426    }
7427  };
7428  const handleRestore = reactExports.useCallback(async (messageId, preMessageCommitHash) => {
7429    const messagesNow = agentMessagesRef.current;
7430    const messageIndex = messagesNow.findIndex((m) => m.id === messageId);
7431    if (messageIndex === -1) {
7432      _t.error("Message not found");
7433      return;
7434    }
7435    const restoredMessage = messagesNow[messageIndex];
7436    const confirmed = window.confirm(`Restore ${siteIdentityText({
7437      id: websiteId,
7438      name: website == null ? void 0 : website.name,
7439      publicId: website == null ? void 0 : website.publicId
7440    })} to this point?
7441
7442This will:
7443• Roll back your code to this version
7444• Remove this message and all after it
7445• Let you edit and re-submit this message
7446
7447Any uncommitted changes will be lost.`);
7448    if (!confirmed) return;
7449    setIsRestoring(true);
7450    discardQueue();
7451    try {
7452      const restore = await resumeChatRestore({
7453        websiteId,
7454        preMessageCommitHash,
7455        pending: pendingChatRestoreRef.current,
7456        remember: (pending) => {
7457          pendingChatRestoreRef.current = pending;
7458        },
7459        start: async () => {
7460          var _a2;
7461          return (_a2 = (await restoreMutation({
7462            variables: {
7463              websiteId,
7464              messageId,
7465              preMessageCommitHash
7466            }
7467          })).data) == null ? void 0 : _a2.restoreToChatMessage;
7468        },
7469        advance: async (variables) => {
7470          var _a2;
7471          return (_a2 = (await continueRestoreMutation({
7472            variables
7473          })).data) == null ? void 0 : _a2.continueChatRestore;
7474        }
7475      });
7476      if (restore == null ? void 0 : restore.success) {
7477        let messageText = "";
7478        if (restoredMessage.parts) {
7479          for (const part of restoredMessage.parts) {
7480            if (part.type === "text" && part.text) {
7481              messageText = part.text;
7482              const contextMatch = messageText.match(/<context for the AI>[\s\S]*?<\/context for the AI>\s*/);
7483              if (contextMatch) {
7484                messageText = messageText.replace(contextMatch[0], "").trim();
7485              }
7486              break;
7487            }
7488          }
7489        }
7490        const remainingMessages = messagesNow.slice(0, messageIndex);
7491        setAgentMessages(remainingMessages);
7492        setInputValue(messageText);
7493        await new Promise((resolve) => setTimeout(resolve, 500));
7494        setTimeout(() => {
7495          var _a2;
7496          (_a2 = textareaRef.current) == null ? void 0 : _a2.focus();
7497        }, 100);
7498        _t.success("Restored! Edit your message below and re-submit when ready.");
7499      } else {
7500        _t.error((restore == null ? void 0 : restore.pending) ? "Conversation restore is still saving. Please retry shortly." : (restore == null ? void 0 : restore.error) || "Failed to restore");
7501      }
7502    } catch (error) {
7503      console.error("Restore error:", error);
7504      _t.error(error instanceof Error ? error.message : "Failed to restore");
7505    } finally {
7506      setIsRestoring(false);
7507    }
7508  }, [restoreMutation, continueRestoreMutation, websiteId, setAgentMessages, discardQueue]);
7509  const pinnedStatusText = reactExports.useMemo(() => {
7510    var _a2;
7511    if (!agentIsLoading) return null;
7512    const lastMsg = agentMessages[agentMessages.length - 1];
7513    if ((lastMsg == null ? void 0 : lastMsg.role) === "assistant" && lastMsg.parts) {
7514      const parts = lastMsg.parts;
7515      for (let i = parts.length - 1; i >= 0; i--) {
7516        const p = parts[i];
7517        if (!((_a2 = p == null ? void 0 : p.type) == null ? void 0 : _a2.startsWith("tool-"))) continue;
7518        const state = p.state;
7519        if (state !== "input-streaming" && state !== "input-available") continue;
7520        const toolName = p.type.replace(/^tool-/, "");
7521        const input = p.input ?? {};
7522        const fileVerb = FILE_TOOL_VERBS[toolName];
7523        if (fileVerb) {
7524          const filePath = input.file_path ?? input.path;
7525          const target = filePath ? stripHome(filePath) : "file";
7526          return `${fileVerb} ${target}`;
7527        }
7528        const renderer = getToolRenderer(toolName);
7529        if (renderer == null ? void 0 : renderer.progressLabel) {
7530          const label = renderer.progressLabel(input);
7531          if (label) return label;
7532        }
7533        if (renderer == null ? void 0 : renderer.displayName) return renderer.displayName;
7534        return humanizeToolName(toolName) || toolName;
7535      }
7536    }
7537    if (thinking == null ? void 0 : thinking.active) return null;
7538    return "Working…";
7539  }, [agentMessages, agentIsLoading, thinking == null ? void 0 : thinking.active]);
7540  const composerNoticeSeqRef = reactExports.useRef(0);
7541  const composerNoticeSeqByIdRef = reactExports.useRef(/* @__PURE__ */ new Map());
7542  const stuckViteError = agentIsLoading ? null : viteError;
7543  const postageNoticeDismissedKey = `ls_postage_notice_dismissed_${websiteId}`;
7544  const [postageNoticeDismissed, setPostageNoticeDismissed] = reactExports.useState(() => {
7545    try {
7546      return localStorage.getItem(postageNoticeDismissedKey) === "1";
7547    } catch {
7548      return false;
7549    }
7550  });
7551  const handleDismissPostage = reactExports.useCallback(() => {
7552    setPostageNoticeDismissed(true);
7553    try {
7554      localStorage.setItem(postageNoticeDismissedKey, "1");
7555    } catch {
7556    }
7557  }, [postageNoticeDismissedKey]);
7558  const postageUncharged = postageUnchargedFromServer && !postageNoticeDismissed;
7559  const currencyNoticeKey = `ls_currency_notice_dismissed_${websiteId}_${currencyRestatedFrom ?? ""}_${currencyRestatedTo ?? ""}`;
7560  const dismissedCurrencyKeysRef = reactExports.useRef(/* @__PURE__ */ new Set());
7561  const [currencyDismissNonce, setCurrencyDismissNonce] = reactExports.useState(0);
7562  const handleDismissCurrency = reactExports.useCallback(() => {
7563    dismissedCurrencyKeysRef.current.add(currencyNoticeKey);
7564    try {
7565      localStorage.setItem(currencyNoticeKey, "1");
7566    } catch {
7567    }
7568    setCurrencyDismissNonce((n) => n + 1);
7569  }, [currencyNoticeKey]);
7570  const currencyRestated = reactExports.useMemo(() => {
7571    if (!currencyRestatedTo) return null;
7572    if (dismissedCurrencyKeysRef.current.has(currencyNoticeKey)) return null;
7573    try {
7574      if (localStorage.getItem(currencyNoticeKey) === "1") return null;
7575    } catch {
7576    }
7577    return {
7578      from: currencyRestatedFrom,
7579      to: currencyRestatedTo
7580    };
7581  }, [currencyNoticeKey, currencyRestatedTo, currencyRestatedFrom, currencyDismissNonce]);
7582  const activeComposerNoticeIds = reactExports.useMemo(() => getActiveComposerNoticeIds({
7583    isOutOfCredits,
7584    isSessionExpired,
7585    viteError: stuckViteError,
7586    sessionLostNotice,
7587    needsPaymentsSetup,
7588    commerceSetup: visibleCommerceSetup,
7589    needsPaymentsUpgrade,
7590    paymentsDisabled,
7591    postageUncharged,
7592    currencyRestated
7593  }), [isOutOfCredits, isSessionExpired, stuckViteError, sessionLostNotice, visibleCommerceSetup, needsPaymentsSetup, needsPaymentsUpgrade, paymentsDisabled, postageUncharged, currencyRestated]);
7594  const composerNoticeSeqById = reactExports.useMemo(() => {
7595    const active = new Set(activeComposerNoticeIds);
7596    for (const id of active) {
7597      if (!composerNoticeSeqByIdRef.current.has(id)) {
7598        composerNoticeSeqRef.current += 1;
7599        composerNoticeSeqByIdRef.current.set(id, composerNoticeSeqRef.current);
7600      }
7601    }
7602    for (const id of composerNoticeSeqByIdRef.current.keys()) {
7603      if (!active.has(id)) composerNoticeSeqByIdRef.current.delete(id);
7604    }
7605    return new Map(composerNoticeSeqByIdRef.current);
7606  }, [activeComposerNoticeIds]);
7607  const paymentsNoticeMinimizedKey = `ls_payments_notice_min_${websiteId}`;
7608  const [paymentsNoticeMinimized, setPaymentsNoticeMinimized] = reactExports.useState(() => {
7609    try {
7610      return localStorage.getItem(paymentsNoticeMinimizedKey) === "1";
7611    } catch {
7612      return false;
7613    }
7614  });
7615  const handleToggleMinimizePayments = reactExports.useCallback(() => {
7616    setPaymentsNoticeMinimized((prev) => {
7617      const next = !prev;
7618      try {
7619        if (next) localStorage.setItem(paymentsNoticeMinimizedKey, "1");
7620        else localStorage.removeItem(paymentsNoticeMinimizedKey);
7621      } catch {
7622      }
7623      return next;
7624    });
7625  }, [paymentsNoticeMinimizedKey]);
7626  const minimizedNoticeIds = reactExports.useMemo(() => new Set(paymentsNoticeMinimized ? ["payments-setup"] : []), [paymentsNoticeMinimized]);
7627  const composerNotices = reactExports.useMemo(() => buildComposerNotices({
7628    isOutOfCredits,
7629    isSessionExpired,
7630    hasBufferedMessage: Boolean(lastUserMessageRef.current),
7631    viteError: stuckViteError,
7632    sessionLostNotice,
7633    needsPaymentsSetup,
7634    needsPaymentsUpgrade,
7635    canStartPaymentsOnboarding,
7636    paymentsForInvoicing,
7637    paymentsPending,
7638    paymentsDisabled,
7639    commerceSetup: visibleCommerceSetup,
7640    commerceSetupRefreshing: setupRefresh.refreshing,
7641    commerceSetupRefreshError: setupRefresh.refreshError,
7642    onRefreshCommerceSetup: setupRefresh.refresh,
7643    onOpenStripeDashboard: openCommerceStripeDashboard,
7644    activatedSeqById: composerNoticeSeqById,
7645    onAddCredits: () => navigate(namedRoutes.reactWebsiteChatSettingsTab({
7646      id: websiteId,
7647      tab: "plan"
7648    })),
7649    onTryAgain: handleRetryLastMessage,
7650    onFixVite: handleFixViteError,
7651    onDismissSessionLost: () => setSessionLostNotice(null),
7652    onSetUpPayments: handleSetUpPayments,
7653    onToggleMinimizePayments: handleToggleMinimizePayments,
7654    paymentsNoticeMinimized,
7655    postageUncharged,
7656    onDismissPostage: handleDismissPostage,
7657    currencyRestated,
7658    onDismissCurrency: handleDismissCurrency,
7659    onUpgradePlan: () => navigate(namedRoutes.reactWebsiteChatSettingsTab({
7660      id: websiteId,
7661      tab: "plan"
7662    })),
7663    paymentsActionDisabled: isStartingPaymentsSetup,
7664    actionDisabled: isAIResponding || isRestoring || isChatLimitReached || !isContainerReady || !(myWebsiteAccess == null ? void 0 : myWebsiteAccess.canEdit)
7665  }), [isOutOfCredits, isSessionExpired, stuckViteError, sessionLostNotice, needsPaymentsSetup, needsPaymentsUpgrade, canStartPaymentsOnboarding, paymentsForInvoicing, paymentsPending, paymentsDisabled, visibleCommerceSetup, setupRefresh.refreshing, setupRefresh.refreshError, setupRefresh.refresh, postageUncharged, handleDismissPostage, currencyRestated, handleDismissCurrency, handleSetUpPayments, handleToggleMinimizePayments, paymentsNoticeMinimized, isStartingPaymentsSetup, composerNoticeSeqById, websiteId, handleRetryLastMessage, handleFixViteError, isAIResponding, isRestoring, isChatLimitReached, isContainerReady, myWebsiteAccess == null ? void 0 : myWebsiteAccess.canEdit]);
7666  const {
7667    tray: composerNoticeTray,
7668    bubbles: composerNoticeBubbles
7669  } = reactExports.useMemo(() => pickTrayAndBubbles(composerNotices, minimizedNoticeIds), [composerNotices, minimizedNoticeIds]);
7670  const handleChatAreaDrop = (e) => {
7671    e.preventDefault();
7672    e.stopPropagation();
7673    setIsDragActive(false);
7674    if (composerLocked) return;
7675    const files = e.dataTransfer.files;
7676    if ((files == null ? void 0 : files.length) > 0) {
7677      handleFileChange(files);
7678    }
7679  };
7680  const handleChatAreaDragOver = (e) => {
7681    e.preventDefault();
7682    e.stopPropagation();
7683    if (!composerLocked) setIsDragActive(true);
7684  };
7685  const handleChatAreaDragEnter = (e) => {
7686    e.preventDefault();
7687    e.stopPropagation();
7688    if (!composerLocked) setIsDragActive(true);
7689  };
7690  const handleChatAreaDragLeave = (e) => {
7691    e.preventDefault();
7692    e.stopPropagation();
7693    if (!e.currentTarget.contains(e.relatedTarget)) {
7694      setIsDragActive(false);
7695    }
7696  };
7697  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cn$1("h-full overflow-hidden", isHiddenForLoading ? "w-0" : "w-full"), children: [
7698    /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { className: cn$1("relative flex h-full w-full flex-col rounded-none border-0 bg-white shadow-none", !isExpanded && "border-0 bg-transparent shadow-none"), onDrop: handleChatAreaDrop, onDragOver: handleChatAreaDragOver, onDragEnter: handleChatAreaDragEnter, onDragLeave: handleChatAreaDragLeave, children: [
7699      isDragActive && !composerLocked && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pointer-events-none absolute inset-0 z-40 overflow-hidden bg-gradient-to-br from-blue-50/95 to-indigo-50/95 p-3 backdrop-blur-md", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex h-full w-full items-center justify-center rounded-[14px] border-2 border-dashed border-blue-300/70 bg-white/95 px-4 py-3 shadow-lg animate-in fade-in-0 zoom-in-95 duration-200", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
7700        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-gradient-to-br from-blue-500 to-indigo-600 shadow-md", children: /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { className: "h-5 w-5 text-white", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" }) }) }),
7701        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 text-left", children: [
7702          /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-semibold leading-tight text-gray-900", children: "Drop files here" }),
7703          /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs leading-snug text-gray-600", children: "Add images or documents to your conversation" })
7704        ] })
7705      ] }) }) }),
7706      isRestoring && isExpanded && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute inset-0 z-50 flex items-center justify-center rounded-lg bg-white/95 backdrop-blur-sm", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "max-w-sm rounded-lg border bg-white p-6 text-center shadow-lg", children: [
7707        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "mx-auto h-12 w-12 animate-spin text-primary" }) }),
7708        /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "mb-2 text-lg font-semibold", children: "Restoring..." }),
7709        /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-gray-600", children: "Rolling back code and chat history. This may take a few seconds." })
7710      ] }) }),
7711      isChatLimitReached && isExpanded && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute inset-0 z-50 flex items-center justify-center rounded-lg bg-white/95 backdrop-blur-sm", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "max-w-sm rounded-lg border bg-white p-6 text-center shadow-lg", children: [
7712        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsxRuntimeExports.jsx(MessageSquare, { className: "mx-auto h-12 w-12 text-gray-400" }) }),
7713        /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "mb-2 text-lg font-semibold", children: "Chat Limit Reached" }),
7714        /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "mb-4 text-sm text-gray-600", children: [
7715          "You've used all ",
7716          FREE_PLAN_CHAT_LIMIT,
7717          " free chats. Upgrade to get more AI conversations."
7718        ] }),
7719        /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { onClick: () => {
7720          navigate(namedRoutes.reactWebsiteChatSettingsTab({
7721            id: websiteId,
7722            tab: "plan"
7723          }));
7724        }, className: "w-full", children: "Upgrade Plan" })
7725      ] }) }),
7726      isExpanded && /* @__PURE__ */ jsxRuntimeExports.jsxs(React.Fragment, { children: [
7727        /* @__PURE__ */ jsxRuntimeExports.jsx(CardContent, { ref: messagesContainerRef, className: "relative flex-grow overflow-y-auto p-0 pt-2", onScroll: checkScrollPosition, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col px-4 py-1", children: [
7728          loading && !agentIsLoading && /* @__PURE__ */ jsxRuntimeExports.jsx(SandboxWaitingIndicator, {}),
7729          !loading && sseChat.historyError && /* @__PURE__ */ jsxRuntimeExports.jsx(SystemCard, { accent: "warning", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-5 w-5" }), title: "Couldn't load chat history", className: "my-6", actions: (
7730            // Reset Chat too: ResetChatWidget only renders with
7731            // messages, so a session whose history never loads
7732            // would otherwise have no way to start over.
7733            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
7734              /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { size: "sm", variant: "outline", onClick: () => sseChat.retryHistory(), children: "Try again" }),
7735              /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { size: "sm", variant: "outline", onClick: handleClearAgentHistory, children: "Reset Chat" }),
7736              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-gray-500", children: "Your website changes are saved" })
7737            ] })
7738          ), children: sseChat.historyError }),
7739          !loading && !sseChat.historyError && agentMessages.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center justify-center py-12 text-center", children: [
7740            /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-4 rounded-full bg-gray-50 p-4", children: /* @__PURE__ */ jsxRuntimeExports.jsx(MessageSquare, { className: "h-8 w-8 text-gray-300" }) }),
7741            /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "mb-2 text-lg font-medium text-gray-400", children: "Start a conversation" }),
7742            /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "max-w-xs text-sm text-gray-300", children: "Ask me to edit your website, add components, or make any changes you'd like" })
7743          ] }),
7744          displayMessages.map((message, index) => {
7745            const stackPosition = getMessageStackPosition(displayMessages, index) ?? "solo";
7746            const continuesStack = messageContinuesStack(displayMessages, index);
7747            const staggerStep = Math.min(index, 4);
7748            const staggerDelay = `${staggerStep * 20}ms`;
7749            return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: cn$1("msg-row-enter flex w-full min-w-0", message.role === "user" && "justify-end", index > 0 && (continuesStack ? "mt-1" : "mt-4")), style: {
7750              animationDelay: staggerDelay
7751            }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(SandboxChatMessage, { message, stackPosition, onRestore: (myWebsiteAccess == null ? void 0 : myWebsiteAccess.canEdit) ? handleRestore : void 0, isRestoring, isAIResponding }) }, `${message.id}-${index}`);
7752          }),
7753          /* @__PURE__ */ jsxRuntimeExports.jsx(TodoChecklist, { messages: agentMessages }),
7754          /* @__PURE__ */ jsxRuntimeExports.jsx(ThinkingIndicator, { thinking }),
7755          pendingApproval && /* @__PURE__ */ jsxRuntimeExports.jsx(SystemCard, { accent: "pending-action", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(ShieldCheck, { className: "h-5 w-5" }), title: "Approval required", actions: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
7756            /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { size: "sm", disabled: !!approvalSubmitting, onClick: () => respondToApproval(pendingApproval.approvalId, true), children: (approvalSubmitting == null ? void 0 : approvalSubmitting.approved) === true ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
7757              /* @__PURE__ */ jsxRuntimeExports.jsx("i", { className: "fa-solid fa-spinner fa-spin mr-2" }),
7758              "Approving…"
7759            ] }) : "Approve" }),
7760            /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { size: "sm", variant: "outline", disabled: !!approvalSubmitting, onClick: () => respondToApproval(pendingApproval.approvalId, false), children: (approvalSubmitting == null ? void 0 : approvalSubmitting.approved) === false ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
7761              /* @__PURE__ */ jsxRuntimeExports.jsx("i", { className: "fa-solid fa-spinner fa-spin mr-2" }),
7762              "Denying…"
7763            ] }) : "Deny" })
7764          ] }), children: pendingApproval.description }),
7765          pendingQuestion && /* @__PURE__ */ jsxRuntimeExports.jsx(AskUserQuestionCard, { pendingQuestion, onSubmit: respondToQuestion }),
7766          maxTurnsHit && !agentIsLoading && !pendingApproval && !pendingQuestion && /* @__PURE__ */ jsxRuntimeExports.jsx(SystemCard, { accent: "info", actions: /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { size: "sm", onClick: handleContinueAfterMaxTurns, children: "Continue" }), children: "The assistant paused after a long run. Continue if it was on the right track, or send a new message to redirect." }),
7767          !chatStopped && agentIsLoading && // The pinned live-status line (above the composer) and the
7768          // in-stream ThinkingIndicator already surface the working /
7769          // thinking state. Suppress this message-list placeholder
7770          // whenever either is showing, so two shimmers never stack
7771          // (e.g. "Thinking" over "Working…").
7772          !(pinnedStatusText && isExpanded) && !(thinking == null ? void 0 : thinking.active) && // Show the waiting indicator until the current turn's
7773          // assistant message actually has content. It's hidden
7774          // once the first text/tool arrives — at that point the
7775          // assistant bubble renders its own progress (spinner
7776          // icons on in-flight tool rows).
7777          (() => {
7778            const last = agentMessages[agentMessages.length - 1];
7779            if ((last == null ? void 0 : last.role) !== "assistant") return /* @__PURE__ */ jsxRuntimeExports.jsx(SandboxWaitingIndicator, {});
7780            const hasContent = (last.parts || []).some((p) => {
7781              if (p.type === "text") return (p.text || "").length > 0;
7782              return true;
7783            });
7784            return hasContent ? null : /* @__PURE__ */ jsxRuntimeExports.jsx(SandboxWaitingIndicator, {});
7785          })(),
7786          isSummarizing && /* @__PURE__ */ jsxRuntimeExports.jsx(SystemCard, { accent: "info", icon: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-5 w-5 animate-spin rounded-full border-2 border-blue-500 border-t-transparent" }), title: "Summarizing conversation...", children: "This usually takes a few seconds" }),
7787          maxStepsReached && /* @__PURE__ */ jsxRuntimeExports.jsx(SystemLine, { accent: "warning", children: "The AI has reached its maximum number of steps. Please try rephrasing your request or breaking it into smaller tasks." }),
7788          showResetSuggestion && /* @__PURE__ */ jsxRuntimeExports.jsx(SystemLine, { accent: "warning", children: "The chat history is getting too long. Please reset the chat soon for the best performance." }),
7789          chatSessionInProgress && /* @__PURE__ */ jsxRuntimeExports.jsx(SystemLine, { accent: "info", children: "Please wait for the current chat response to complete before sending another message." }),
7790          chatErrorMessage && !isSessionExpired && !isOutOfCredits && /* @__PURE__ */ jsxRuntimeExports.jsx(SystemCard, { accent: "danger", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-4 w-4" }), title: chatErrorMessage, actions: canResetFromError || lastUserMessageRef.current ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2", children: [
7791            canResetFromError && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
7792              /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { size: "sm", variant: "outline", className: "h-7 border-red-300 bg-white px-3 text-xs text-red-700 hover:bg-red-100", onClick: handleClearAgentHistory, children: "Reset Chat" }),
7793              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-red-600", children: "Your website changes are saved" })
7794            ] }),
7795            isOverloadedError && lastUserMessageRef.current && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
7796              /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { size: "sm", variant: "outline", className: "h-7 border-red-300 bg-white px-3 text-xs text-red-700 hover:bg-red-100", onClick: handleRetryLastMessage, children: "Try again" }),
7797              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-red-600", children: "The AI service may be temporarily busy" })
7798            ] })
7799          ] }) : void 0 }),
7800          agentMessages.length > 0 && !isAIResponding && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-end px-1 py-0.5", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ResetButton, { onReset: handleClearAgentHistory }) }),
7801          /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: messagesEndRef })
7802        ] }) }),
7803        showScrollToBottom && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pointer-events-none sticky bottom-0 z-10 flex justify-end pb-2 pr-4", style: {
7804          marginTop: "-3rem"
7805        }, children: /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => scrollToBottom(), className: "pointer-events-auto flex h-10 w-10 items-center justify-center rounded-full bg-primary text-primary-foreground shadow-lg transition-all hover:bg-primary/90 hover:shadow-xl", "aria-label": "Scroll to bottom", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ArrowDown, { className: "h-5 w-5" }) }) })
7806      ] }),
7807      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white pb-2", children: [
7808        pinnedStatusText && isExpanded && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "state-card-fade flex items-center px-4 py-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-shimmer text-xs font-medium", children: pinnedStatusText }) }),
7809        !isExpanded && isChatLimitReached && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between border-b border-red-200 bg-red-50 px-4 py-3", children: [
7810          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
7811            /* @__PURE__ */ jsxRuntimeExports.jsx(MessageSquare, { className: "h-4 w-4 text-red-500" }),
7812            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm font-medium text-red-700", children: "Chat limit reached" })
7813          ] }),
7814          /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { size: "sm", onClick: () => {
7815            navigate(namedRoutes.reactWebsiteChatSettingsTab({
7816              id: websiteId,
7817              tab: "plan"
7818            }));
7819          }, className: "h-7 px-3 text-xs", children: "Upgrade" })
7820        ] }),
7821        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2", children: [
7822          !isChatLimitReached && isFree && !isAgencyUser && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-2 flex items-center justify-between px-4 text-xs text-gray-500", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
7823            remainingChats,
7824            " free chat",
7825            remainingChats !== 1 ? "s" : "",
7826            " remaining"
7827          ] }) }),
7828          /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-2 flex justify-end px-4 lg:hidden", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { variant: "ghost", size: "icon", onClick: () => setIsExpanded(!isExpanded), className: "h-6 w-6 text-gray-400 hover:text-gray-600", children: isExpanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronsDown, { className: "h-4 w-4" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronsUp, { className: "h-4 w-4" }) }) }),
7829          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative mx-2 flex flex-col space-y-2", children: [
7830            !isContainerReady && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 rounded-md bg-gray-50 px-3 py-2 text-sm text-gray-500", children: [
7831              /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-3 w-3 animate-spin rounded-full border-2 border-gray-400 border-t-transparent" }),
7832              "Preparing preview server..."
7833            ] }),
7834            /* @__PURE__ */ jsxRuntimeExports.jsx("div", { "aria-live": "polite", "aria-atomic": "true", className: "sr-only", children: pickerLiveMessage }),
7835            /* @__PURE__ */ jsxRuntimeExports.jsx(ComposerNoticeStack, { tray: composerNoticeTray, bubbles: composerNoticeBubbles, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative flex flex-col", children: [
7836              /* @__PURE__ */ jsxRuntimeExports.jsx(QueuedMessageList, { items: queue.items, mode, pausedReason, onUpdateText: handleUpdateQueuedText, onRemove: handleRemoveQueued, onSendNow: handleSendQueuedNow, onEditingChange: setEditingQueuedId }),
7837              /* @__PURE__ */ jsxRuntimeExports.jsx(ComposerAttachmentTray, { selectedElement, images, onClearSelection: handleChipClear, onRemoveImage: handleRemoveImage }),
7838              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cn$1("relative z-[1] rounded-[14px] border border-[#1B1A22]/[0.07] bg-white shadow-[inset_0_1px_0_rgba(255,255,255,0.9),0_1px_2px_rgba(27,26,34,0.03),0_2px_6px_-2px_rgba(27,26,34,0.04),0_10px_24px_-16px_rgba(27,26,34,0.10)] transition-all", composerLocked && "bg-muted"), children: [
7839                inlineEditInProgress && /* @__P
7839URE__ */ jsxRuntimeExports.jsx("div", { className: "absolute inset-0 z-10 flex items-center justify-center rounded-[14px] bg-background/80 backdrop-blur-[1px]", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "px-4 text-center text-sm font-medium text-muted-foreground", children: "Finish your edits in the preview to chat" }) }),
7840                /* @__PURE__ */ jsxRuntimeExports.jsx(Textarea, { ref: textareaRef, className: cn$1("min-h-[44px] w-full resize-none overflow-y-auto rounded-t-md border-0 px-3 py-3 text-[16px] sm:text-sm", "bg-transparent placeholder:text-muted-foreground", "focus-visible:ring-0 focus-visible:ring-offset-0"), placeholder: !isContainerReady ? "Waiting for preview server..." : pendingApproval ? "Waiting for you to approve or deny the request above…" : pendingQuestion ? "Waiting for you to answer the question above…" : isChatLimitReached || isRestoring || !(myWebsiteAccess == null ? void 0 : myWebsiteAccess.canEdit) ? "" : mode === "busy" ? "Queue your next message…" : "What would you like to change...", disabled: composerLocked, rows: 1, value: inputValue, onChange: (e) => {
7841                  setInputValue(e.target.value);
7842                }, onKeyDown: handleKeyDown, onFocus: () => setIsExpanded(true), onPaste: (e) => {
7843                  var _a2, _b2;
7844                  const items = Array.from(((_a2 = e.clipboardData) == null ? void 0 : _a2.items) ?? []);
7845                  const imageFiles = items.filter((it) => it.kind === "file" && it.type.startsWith("image/")).map((it) => it.getAsFile()).filter((f) => !!f);
7846                  if (imageFiles.length === 0) return;
7847                  e.preventDefault();
7848                  const text = ((_b2 = e.clipboardData) == null ? void 0 : _b2.getData("text/plain")) ?? "";
7849                  if (text) document.execCommand("insertText", false, text);
7850                  const extForMime = {
7851                    jpeg: "jpg",
7852                    "svg+xml": "svg",
7853                    "vnd.microsoft.icon": "ico"
7854                  };
7855                  const dt = new DataTransfer();
7856                  imageFiles.forEach((f) => {
7857                    const subtype = f.type.split("/")[1] || "png";
7858                    const ext = extForMime[subtype] ?? subtype;
7859                    const named = f.name && f.name !== "image.png" ? f : new File([f], `pasted-${Date.now()}.${ext}`, {
7860                      type: f.type
7861                    });
7862                    dt.items.add(named);
7863                  });
7864                  handleFileChange(dt.files);
7865                } }),
7866                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between px-3 py-2", children: [
7867                  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1", children: [
7868                    /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
7869                      /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { size: "icon", variant: "ghost", type: "button", "aria-label": "Upload images", className: "h-8 w-8 text-muted-foreground hover:text-foreground disabled:opacity-50", disabled: composerLocked, onClick: () => {
7870                        var _a2;
7871                        return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
7872                      }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Paperclip, { className: "h-5 w-5" }) }) }),
7873                      /* @__P
7873URE__ */ jsxRuntimeExports.jsx(TooltipContent, { side: "top", align: "center", children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Upload images" }) })
7874                    ] }) }),
7875                    /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
7876                      /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { size: "icon", variant: "ghost", type: "button", "aria-label": "Open gallery", className: "h-8 w-8 text-muted-foreground hover:text-foreground disabled:opacity-50", disabled: composerLocked, onClick: () => setIsGalleryOpen(true), children: /* @__PURE__ */ jsxRuntimeExports.jsx(Images, { className: "h-5 w-5" }) }) }),
7877                      /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { side: "top", align: "center", children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Open gallery" }) })
7878                    ] }) }),
7879                    !pickerButtonHidden && /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
7880                      /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { size: "icon", variant: "ghost", type: "button", "aria-pressed": pickModeActive, "aria-label": pickerButtonTooltip, onClick: handlePickerButtonClick, disabled: pickerButtonDisabled, className: cn$1(
7881                        "h-8 w-8 text-muted-foreground hover:text-foreground disabled:opacity-50",
7882                        // Active-state via color only — no motion
7883                        // (avoids prefers-reduced-motion carve-outs).
7884                        pickModeActive && "hover:bg-primary/15 bg-primary/10 text-primary hover:text-primary"
7885                      ), children: /* @__PURE__ */ jsxRuntimeExports.jsx(MousePointerClick, { className: "h-5 w-5" }) }) }),
7886                      /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { side: "top", align: "center", children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: pickerButtonTooltip }) })
7887                    ] }) })
7888                  ] }),
7889                  isAIResponding || isSubmitting ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1", children: [
7890                    isAIResponding && isFirstGenerationInProgress ? /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
7891                      /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "inline-flex", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { size: "icon", variant: "ghost", type: "button", "aria-label": "Building your website…", disabled: true, className: "h-8 w-8 rounded-full text-gray-400 disabled:opacity-100", style: {
7892                        background: "linear-gradient(180deg, #F3F4F6 0%, #E5E7EB 100%)",
7893                        boxShadow: "inset 0 0 0 1px rgba(0,0,0,0.06)"
7894                      }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Square, { className: "h-3.5 w-3.5", fill: "currentColor", strokeWidth: 0 }) }) }) }),
7895                      /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { side: "top", align: "center", children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Hang tight — your website is still building." }) })
7896                    ] }) }) : isAIResponding ? (
7897                      // Stop is a secondary action — keep it quiet
7898                      // (muted gray, not a glowing primary button).
7899                      /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { size: "icon", variant: "ghost", type: "button", "aria-label": "Stop", onClick: handleStopAgentChat, className: "h-8 w-8 rounded-full border border-gray-200 bg-white text-gray-500 hover:bg-gray-100 hover:text-gray-700 active:scale-[0.96]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Square, { className: "h-3 w-3", fill: "currentColor", strokeWidth: 0 }) })
7900                    ) : (
7901                      // Sent, waiting for the turn to start streaming
7902                      // — a working spinner so the composer reads as
7903                      // busy; the message cannot be re-submitted, but
7904                      // the next one can be queued beside it.
7905                      /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { size: "icon", variant: "ghost", type: "button", "aria-label": "Sending…", disabled: true, className: "h-8 w-8 rounded-full text-muted-foreground disabled:opacity-100", children: /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" }) })
7906                    ),
7907                    /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
7908                      /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "inline-flex", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
7909                        Button,
7910                        {
7911                          size: "icon",
7912                          variant: "ghost",
7913                          type: "button",
7914                          "aria-label": "Queue message",
7915                          className: "h-8 w-8 text-muted-foreground hover:text-foreground disabled:opacity-50",
7916                          disabled: mode !== "busy" || isUploadingImages || !inputValue.trim(),
7917                          onClick: handleFormSubmit,
7918                          children: /* @__PURE__ */ jsxRuntimeExports.jsx(ArrowUp, { className: "h-5 w-5" })
7919                        }
7920                      ) }) }),
7921                      /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { side: "top", align: "center", children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Queue message — sends when the AI finishes" }) })
7922                    ] }) })
7923                  ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { size: "icon", variant: "ghost", className: "h-8 w-8 text-muted-foreground hover:text-foreground disabled:opacity-50", disabled: isUploadingImages || isRestoring || !inputValue.trim() && images.length === 0 || isChatLimitReached || !(myWebsiteAccess == null ? void 0 : myWebsiteAccess.canEdit) || !!pendingApproval || !!pendingQuestion, onClick: handleFormSubmit, children: /* @__PURE__ */ jsxRuntimeExports.jsx(ArrowUp, { className: "h-5 w-5" }) })
7924                ] })
7925              ] })
7926            ] }) }),
7927            /* @__PURE__ */ jsxRuntimeExports.jsx("input", { ref: fileInputRef, type: "file", accept: ".jpg,.jpeg,.png,.gif,.webp,.bmp,.svg,.heic,.heif,.pdf,.glb", className: "hidden", multiple: true, onChange: (e) => {
7928              if (e.target.files) {
7929                handleFileChange(e.target.files);
7930              }
7931            } })
7932          ] }),
7933          /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "whitespace-nowrap px-4 pt-2 text-center text-[10px] text-gray-500 sm:whitespace-normal sm:text-xs sm:[text-wrap:balance]", children: "AI can make mistakes. Changes may not always apply as expected." })
7934        ] })
7935      ] })
7936    ] }),
7937    /* @__PURE__ */ jsxRuntimeExports.jsx(Dialog, { open: isGalleryOpen && !!website, onOpenChange: (open) => {
7938      if (!open) setIsGalleryOpen(false);
7939    }, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogContent, { "aria-describedby": void 0, className: "h-[min(90vh,900px)] w-[min(95vw,1280px)] max-w-none overflow-y-auto p-6 [&>button.absolute]:hidden", children: [
7940      /* @__PURE__ */ jsxRuntimeExports.jsx(DialogTitle, { className: "sr-only", children: "Gallery" }),
7941      website && /* @__PURE__ */ jsxRuntimeExports.jsx(Gallery, { websiteId: website.id, publicId: website.publicId || void 0, initialGalleryType: "images", initialKeyword: website.businessName || website.name || "", existingMedia: [], onClose: () => setIsGalleryOpen(false), onMediaSelected: handleInternalGalleryMediaSelection })
7942    ] }) })
7943  ] });
7944});
7945ReactChatPanel.displayName = "ReactChatPanel";
7946const ReactChatPanel$1 = React.memo(ReactChatPanel);
7947const PublishWhileAgentBusyModal = ({
7948  open,
7949  onPublish,
7950  onWait
7951}) => {
7952  if (!open) return null;
7953  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4", role: "dialog", "aria-modal": "true", "aria-labelledby": "publish-while-busy-title", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full max-w-md rounded-2xl bg-white p-8 shadow-2xl", children: [
7954    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-6", children: [
7955      /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-blue-50", children: /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "h-6 w-6 animate-spin text-blue-600" }) }),
7956      /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { id: "publish-while-busy-title", className: "mb-2 text-xl font-bold text-gray-900", children: "The AI is still working" }),
7957      /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm leading-relaxed text-gray-600", children: "If you publish now, the changes the AI is making right now won't be on your live site. We recommend waiting until it finishes, then publishing." })
7958    ] }),
7959    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-3", children: [
7960      /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: onWait, className: "w-full rounded-lg bg-gradient-to-r from-blue-600 to-indigo-600 px-6 py-3 font-semibold text-white shadow-md transition-all hover:from-blue-700 hover:to-indigo-700 hover:shadow-lg", children: "Wait" }),
7961      /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: onPublish, className: "w-full rounded-lg border border-gray-300 px-6 py-3 font-medium text-gray-700 transition-colors hover:bg-gray-50", children: "Publish anyway" })
7962    ] })
7963  ] }) });
7964};
7965// @__NO_SIDE_EFFECTS__
7966function createSlot(ownerName) {
7967  const SlotClone = /* @__PURE__ */ createSlotClone(ownerName);
7968  const Slot2 = reactExports.forwardRef((props, forwardedRef) => {
7969    const { children, ...slotProps } = props;
7970    const childrenArray = reactExports.Children.toArray(children);
7971    const slottable = childrenArray.find(isSlottable);
7972    if (slottable) {
7973      const newElement = slottable.props.children;
7974      const newChildren = childrenArray.map((child) => {
7975        if (child === slottable) {
7976          if (reactExports.Children.count(newElement) > 1) return reactExports.Children.only(null);
7977          return reactExports.isValidElement(newElement) ? newElement.props.children : null;
7978        } else {
7979          return child;
7980        }
7981      });
7982      return /* @__PURE__ */ jsxRuntimeExports.jsx(SlotClone, { ...slotProps, ref: forwardedRef, children: reactExports.isValidElement(newElement) ? reactExports.cloneElement(newElement, void 0, newChildren) : null });
7983    }
7984    return /* @__PURE__ */ jsxRuntimeExports.jsx(SlotClone, { ...slotProps, ref: forwardedRef, children });
7985  });
7986  Slot2.displayName = `${ownerName}.Slot`;
7987  return Slot2;
7988}
7989// @__NO_SIDE_EFFECTS__
7990function createSlotClone(ownerName) {
7991  const SlotClone = reactExports.forwardRef((props, forwardedRef) => {
7992    const { children, ...slotProps } = props;
7993    const childrenRef = reactExports.isValidElement(children) ? getElementRef$1(children) : void 0;
7994    const ref = useComposedRefs(childrenRef, forwardedRef);
7995    if (reactExports.isValidElement(children)) {
7996      const props2 = mergeProps(slotProps, children.props);
7997      if (children.type !== reactExports.Fragment) {
7998        props2.ref = ref;
7999      }
8000      return reactExports.cloneElement(children, props2);
8001    }
8002    return reactExports.Children.count(children) > 1 ? reactExports.Children.only(null) : null;
8003  });
8004  SlotClone.displayName = `${ownerName}.SlotClone`;
8005  return SlotClone;
8006}
8007var SLOTTABLE_IDENTIFIER = Symbol("radix.slottable");
8008function isSlottable(child) {
8009  return reactExports.isValidElement(child) && typeof child.type === "function" && "__radixId" in child.type && child.type.__radixId === SLOTTABLE_IDENTIFIER;
8010}
8011function mergeProps(slotProps, childProps) {
8012  const overrideProps = { ...childProps };
8013  for (const propName in childProps) {
8014    const slotPropValue = slotProps[propName];
8015    const childPropValue = childProps[propName];
8016    const isHandler = /^on[A-Z]/.test(propName);
8017    if (isHandler) {
8018      if (slotPropValue && childPropValue) {
8019        overrideProps[propName] = (...args) => {
8020          const result = childPropValue(...args);
8021          slotPropValue(...args);
8022          return result;
8023        };
8024      } else if (slotPropValue) {
8025        overrideProps[propName] = slotPropValue;
8026      }
8027    } else if (propName === "style") {
8028      overrideProps[propName] = { ...slotPropValue, ...childPropValue };
8029    } else if (propName === "className") {
8030      overrideProps[propName] = [slotPropValue, childPropValue].filter(Boolean).join(" ");
8031    }
8032  }
8033  return { ...slotProps, ...overrideProps };
8034}
8035function getElementRef$1(element) {
8036  var _a, _b;
8037  let getter = (_a = Object.getOwnPropertyDescriptor(element.props, "ref")) == null ? void 0 : _a.get;
8038  let mayWarn = getter && "isReactWarning" in getter && getter.isReactWarning;
8039  if (mayWarn) {
8040    return element.ref;
8041  }
8042  getter = (_b = Object.getOwnPropertyDescriptor(element, "ref")) == null ? void 0 : _b.get;
8043  mayWarn = getter && "isReactWarning" in getter && getter.isReactWarning;
8044  if (mayWarn) {
8045    return element.props.ref;
8046  }
8047  return element.props.ref || element.ref;
8048}
8049var NODES = [
8050  "a",
8051  "button",
8052  "div",
8053  "form",
8054  "h2",
8055  "h3",
8056  "img",
8057  "input",
8058  "label",
8059  "li",
8060  "nav",
8061  "ol",
8062  "p",
8063  "select",
8064  "span",
8065  "svg",
8066  "ul"
8067];
8068var Primitive = NODES.reduce((primitive, node) => {
8069  const Slot2 = /* @__PURE__ */ createSlot(`Primitive.${node}`);
8070  const Node = reactExports.forwardRef((props, forwardedRef) => {
8071    const { asChild, ...primitiveProps } = props;
8072    const Comp = asChild ? Slot2 : node;
8073    if (typeof window !== "undefined") {
8074      window[Symbol.for("radix-ui")] = true;
8075    }
8076    return /* @__PURE__ */ jsxRuntimeExports.jsx(Comp, { ...primitiveProps, ref: forwardedRef });
8077  });
8078  Node.displayName = `Primitive.${node}`;
8079  return { ...primitive, [node]: Node };
8080}, {});
8081function dispatchDiscreteCustomEvent(target, event) {
8082  if (target) reactDomExports.flushSync(() => target.dispatchEvent(event));
8083}
8084function useCallbackRef(callback) {
8085  const callbackRef = reactExports.useRef(callback);
8086  reactExports.useEffect(() => {
8087    callbackRef.current = callback;
8088  });
8089  return reactExports.useMemo(() => (...args) => {
8090    var _a;
8091    return (_a = callbackRef.current) == null ? void 0 : _a.call(callbackRef, ...args);
8092  }, []);
8093}
8094var DISMISSABLE_LAYER_NAME = "DismissableLayer";
8095var CONTEXT_UPDATE = "dismissableLayer.update";
8096var POINTER_DOWN_OUTSIDE = "dismissableLayer.pointerDownOutside";
8097var FOCUS_OUTSIDE = "dismissableLayer.focusOutside";
8098var originalBodyPointerEvents;
8099var DismissableLayerContext = reactExports.createContext({
8100  layers: /* @__PURE__ */ new Set(),
8101  layersWithOutsidePointerEventsDisabled: /* @__PURE__ */ new Set(),
8102  branches: /* @__PURE__ */ new Set()
8103});
8104var DismissableLayer = reactExports.forwardRef(
8105  (props, forwardedRef) => {
8106    const {
8107      disableOutsidePointerEvents = false,
8108      onEscapeKeyDown,
8109      onPointerDownOutside,
8110      onFocusOutside,
8111      onInteractOutside,
8112      onDismiss,
8113      ...layerProps
8114    } = props;
8115    const context = reactExports.useContext(DismissableLayerContext);
8116    const [node, setNode] = reactExports.useState(null);
8117    const ownerDocument = (node == null ? void 0 : node.ownerDocument) ?? (globalThis == null ? void 0 : globalThis.document);
8118    const [, force] = reactExports.useState({});
vendor: 5,804 bytes, lines 8119-8245
8119    const composedRefs = useComposedRefs(forwardedRef, (node2) => setNode(node2));
8120    const layers = Array.from(context.layers);
8121    const [highestLayerWithOutsidePointerEventsDisabled] = [...context.layersWithOutsidePointerEventsDisabled].slice(-1);
8122    const highestLayerWithOutsidePointerEventsDisabledIndex = layers.indexOf(highestLayerWithOutsidePointerEventsDisabled);
8123    const index = node ? layers.indexOf(node) : -1;
8124    const isBodyPointerEventsDisabled = context.layersWithOutsidePointerEventsDisabled.size > 0;
8125    const isPointerEventsEnabled = index >= highestLayerWithOutsidePointerEventsDisabledIndex;
8126    const pointerDownOutside = usePointerDownOutside((event) => {
8127      const target = event.target;
8128      const isPointerDownOnBranch = [...context.branches].some((branch) => branch.contains(target));
8129      if (!isPointerEventsEnabled || isPointerDownOnBranch) return;
8130      onPointerDownOutside == null ? void 0 : onPointerDownOutside(event);
8131      onInteractOutside == null ? void 0 : onInteractOutside(event);
8132      if (!event.defaultPrevented) onDismiss == null ? void 0 : onDismiss();
8133    }, ownerDocument);
8134    const focusOutside = useFocusOutside((event) => {
8135      const target = event.target;
8136      const isFocusInBranch = [...context.branches].some((branch) => branch.contains(target));
8137      if (isFocusInBranch) return;
8138      onFocusOutside == null ? void 0 : onFocusOutside(event);
8139      onInteractOutside == null ? void 0 : onInteractOutside(event);
8140      if (!event.defaultPrevented) onDismiss == null ? void 0 : onDismiss();
8141    }, ownerDocument);
8142    useEscapeKeydown((event) => {
8143      const isHighestLayer = index === context.layers.size - 1;
8144      if (!isHighestLayer) return;
8145      onEscapeKeyDown == null ? void 0 : onEscapeKeyDown(event);
8146      if (!event.defaultPrevented && onDismiss) {
8147        event.preventDefault();
8148        onDismiss();
8149      }
8150    }, ownerDocument);
8151    reactExports.useEffect(() => {
8152      if (!node) return;
8153      if (disableOutsidePointerEvents) {
8154        if (context.layersWithOutsidePointerEventsDisabled.size === 0) {
8155          originalBodyPointerEvents = ownerDocument.body.style.pointerEvents;
8156          ownerDocument.body.style.pointerEvents = "none";
8157        }
8158        context.layersWithOutsidePointerEventsDisabled.add(node);
8159      }
8160      context.layers.add(node);
8161      dispatchUpdate();
8162      return () => {
8163        if (disableOutsidePointerEvents && context.layersWithOutsidePointerEventsDisabled.size === 1) {
8164          ownerDocument.body.style.pointerEvents = originalBodyPointerEvents;
8165        }
8166      };
8167    }, [node, ownerDocument, disableOutsidePointerEvents, context]);
8168    reactExports.useEffect(() => {
8169      return () => {
8170        if (!node) return;
8171        context.layers.delete(node);
8172        context.layersWithOutsidePointerEventsDisabled.delete(node);
8173        dispatchUpdate();
8174      };
8175    }, [node, context]);
8176    reactExports.useEffect(() => {
8177      const handleUpdate = () => force({});
8178      document.addEventListener(CONTEXT_UPDATE, handleUpdate);
8179      return () => document.removeEventListener(CONTEXT_UPDATE, handleUpdate);
8180    }, []);
8181    return /* @__PURE__ */ jsxRuntimeExports.jsx(
8182      Primitive.div,
8183      {
8184        ...layerProps,
8185        ref: composedRefs,
8186        style: {
8187          pointerEvents: isBodyPointerEventsDisabled ? isPointerEventsEnabled ? "auto" : "none" : void 0,
8188          ...props.style
8189        },
8190        onFocusCapture: composeEventHandlers(props.onFocusCapture, focusOutside.onFocusCapture),
8191        onBlurCapture: composeEventHandlers(props.onBlurCapture, focusOutside.onBlurCapture),
8192        onPointerDownCapture: composeEventHandlers(
8193          props.onPointerDownCapture,
8194          pointerDownOutside.onPointerDownCapture
8195        )
8196      }
8197    );
8198  }
8199);
8200DismissableLayer.displayName = DISMISSABLE_LAYER_NAME;
8201var BRANCH_NAME = "DismissableLayerBranch";
8202var DismissableLayerBranch = reactExports.forwardRef((props, forwardedRef) => {
8203  const context = reactExports.useContext(DismissableLayerContext);
8204  const ref = reactExports.useRef(null);
8205  const composedRefs = useComposedRefs(forwardedRef, ref);
8206  reactExports.useEffect(() => {
8207    const node = ref.current;
8208    if (node) {
8209      context.branches.add(node);
8210      return () => {
8211        context.branches.delete(node);
8212      };
8213    }
8214  }, [context.branches]);
8215  return /* @__PURE__ */ jsxRuntimeExports.jsx(Primitive.div, { ...props, ref: composedRefs });
8216});
8217DismissableLayerBranch.displayName = BRANCH_NAME;
8218function usePointerDownOutside(onPointerDownOutside, ownerDocument = globalThis == null ? void 0 : globalThis.document) {
8219  const handlePointerDownOutside = useCallbackRef(onPointerDownOutside);
8220  const isPointerInsideReactTreeRef = reactExports.useRef(false);
8221  const handleClickRef = reactExports.useRef(() => {
8222  });
8223  reactExports.useEffect(() => {
8224    const handlePointerDown = (event) => {
8225      if (event.target && !isPointerInsideReactTreeRef.current) {
8226        let handleAndDispatchPointerDownOutsideEvent2 = function() {
8227          handleAndDispatchCustomEvent(
8228            POINTER_DOWN_OUTSIDE,
8229            handlePointerDownOutside,
8230            eventDetail,
8231            { discrete: true }
8232          );
8233        };
8234        const eventDetail = { originalEvent: event };
8235        if (event.pointerType === "touch") {
8236          ownerDocument.removeEventListener("click", handleClickRef.current);
8237          handleClickRef.current = handleAndDispatchPointerDownOutsideEvent2;
8238          ownerDocument.addEventListener("click", handleClickRef.current, { once: true });
8239        } else {
8240          handleAndDispatchPointerDownOutsideEvent2();
8241        }
8242      } else {
8243        ownerDocument.removeEventListener("click", handleClickRef.current);
8244      }
8245      isPointerInsideReactTreeRef.current = false;
vendor: 9,270 bytes, lines 8246-8473
8246    };
8247    const timerId = window.setTimeout(() => {
8248      ownerDocument.addEventListener("pointerdown", handlePointerDown);
8249    }, 0);
8250    return () => {
8251      window.clearTimeout(timerId);
8252      ownerDocument.removeEventListener("pointerdown", handlePointerDown);
8253      ownerDocument.removeEventListener("click", handleClickRef.current);
8254    };
8255  }, [ownerDocument, handlePointerDownOutside]);
8256  return {
8257    // ensures we check React component tree (not just DOM tree)
8258    onPointerDownCapture: () => isPointerInsideReactTreeRef.current = true
8259  };
8260}
8261function useFocusOutside(onFocusOutside, ownerDocument = globalThis == null ? void 0 : globalThis.document) {
8262  const handleFocusOutside = useCallbackRef(onFocusOutside);
8263  const isFocusInsideReactTreeRef = reactExports.useRef(false);
8264  reactExports.useEffect(() => {
8265    const handleFocus = (event) => {
8266      if (event.target && !isFocusInsideReactTreeRef.current) {
8267        const eventDetail = { originalEvent: event };
8268        handleAndDispatchCustomEvent(FOCUS_OUTSIDE, handleFocusOutside, eventDetail, {
8269          discrete: false
8270        });
8271      }
8272    };
8273    ownerDocument.addEventListener("focusin", handleFocus);
8274    return () => ownerDocument.removeEventListener("focusin", handleFocus);
8275  }, [ownerDocument, handleFocusOutside]);
8276  return {
8277    onFocusCapture: () => isFocusInsideReactTreeRef.current = true,
8278    onBlurCapture: () => isFocusInsideReactTreeRef.current = false
8279  };
8280}
8281function dispatchUpdate() {
8282  const event = new CustomEvent(CONTEXT_UPDATE);
8283  document.dispatchEvent(event);
8284}
8285function handleAndDispatchCustomEvent(name, handler, detail, { discrete }) {
8286  const target = detail.originalEvent.target;
8287  const event = new CustomEvent(name, { bubbles: false, cancelable: true, detail });
8288  if (handler) target.addEventListener(name, handler, { once: true });
8289  if (discrete) {
8290    dispatchDiscreteCustomEvent(target, event);
8291  } else {
8292    target.dispatchEvent(event);
8293  }
8294}
8295var count = 0;
8296function useFocusGuards() {
8297  reactExports.useEffect(() => {
8298    const edgeGuards = document.querySelectorAll("[data-radix-focus-guard]");
8299    document.body.insertAdjacentElement("afterbegin", edgeGuards[0] ?? createFocusGuard());
8300    document.body.insertAdjacentElement("beforeend", edgeGuards[1] ?? createFocusGuard());
8301    count++;
8302    return () => {
8303      if (count === 1) {
8304        document.querySelectorAll("[data-radix-focus-guard]").forEach((node) => node.remove());
8305      }
8306      count--;
8307    };
8308  }, []);
8309}
8310function createFocusGuard() {
8311  const element = document.createElement("span");
8312  element.setAttribute("data-radix-focus-guard", "");
8313  element.tabIndex = 0;
8314  element.style.outline = "none";
8315  element.style.opacity = "0";
8316  element.style.position = "fixed";
8317  element.style.pointerEvents = "none";
8318  return element;
8319}
8320var AUTOFOCUS_ON_MOUNT = "focusScope.autoFocusOnMount";
8321var AUTOFOCUS_ON_UNMOUNT = "focusScope.autoFocusOnUnmount";
8322var EVENT_OPTIONS = { bubbles: false, cancelable: true };
8323var FOCUS_SCOPE_NAME = "FocusScope";
8324var FocusScope = reactExports.forwardRef((props, forwardedRef) => {
8325  const {
8326    loop = false,
8327    trapped = false,
8328    onMountAutoFocus: onMountAutoFocusProp,
8329    onUnmountAutoFocus: onUnmountAutoFocusProp,
8330    ...scopeProps
8331  } = props;
8332  const [container, setContainer] = reactExports.useState(null);
8333  const onMountAutoFocus = useCallbackRef(onMountAutoFocusProp);
8334  const onUnmountAutoFocus = useCallbackRef(onUnmountAutoFocusProp);
8335  const lastFocusedElementRef = reactExports.useRef(null);
8336  const composedRefs = useComposedRefs(forwardedRef, (node) => setContainer(node));
8337  const focusScope = reactExports.useRef({
8338    paused: false,
8339    pause() {
8340      this.paused = true;
8341    },
8342    resume() {
8343      this.paused = false;
8344    }
8345  }).current;
8346  reactExports.useEffect(() => {
8347    if (trapped) {
8348      let handleFocusIn2 = function(event) {
8349        if (focusScope.paused || !container) return;
8350        const target = event.target;
8351        if (container.contains(target)) {
8352          lastFocusedElementRef.current = target;
8353        } else {
8354          focus(lastFocusedElementRef.current, { select: true });
8355        }
8356      }, handleFocusOut2 = function(event) {
8357        if (focusScope.paused || !container) return;
8358        const relatedTarget = event.relatedTarget;
8359        if (relatedTarget === null) return;
8360        if (!container.contains(relatedTarget)) {
8361          focus(lastFocusedElementRef.current, { select: true });
8362        }
8363      }, handleMutations2 = function(mutations) {
8364        const focusedElement = document.activeElement;
8365        if (focusedElement !== document.body) return;
8366        for (const mutation of mutations) {
8367          if (mutation.removedNodes.length > 0) focus(container);
8368        }
8369      };
8370      document.addEventListener("focusin", handleFocusIn2);
8371      document.addEventListener("focusout", handleFocusOut2);
8372      const mutationObserver = new MutationObserver(handleMutations2);
8373      if (container) mutationObserver.observe(container, { childList: true, subtree: true });
8374      return () => {
8375        document.removeEventListener("focusin", handleFocusIn2);
8376        document.removeEventListener("focusout", handleFocusOut2);
8377        mutationObserver.disconnect();
8378      };
8379    }
8380  }, [trapped, container, focusScope.paused]);
8381  reactExports.useEffect(() => {
8382    if (container) {
8383      focusScopesStack.add(focusScope);
8384      const previouslyFocusedElement = document.activeElement;
8385      const hasFocusedCandidate = container.contains(previouslyFocusedElement);
8386      if (!hasFocusedCandidate) {
8387        const mountEvent = new CustomEvent(AUTOFOCUS_ON_MOUNT, EVENT_OPTIONS);
8388        container.addEventListener(AUTOFOCUS_ON_MOUNT, onMountAutoFocus);
8389        container.dispatchEvent(mountEvent);
8390        if (!mountEvent.defaultPrevented) {
8391          focusFirst(removeLinks(getTabbableCandidates(container)), { select: true });
8392          if (document.activeElement === previouslyFocusedElement) {
8393            focus(container);
8394          }
8395        }
8396      }
8397      return () => {
8398        container.removeEventListener(AUTOFOCUS_ON_MOUNT, onMountAutoFocus);
8399        setTimeout(() => {
8400          const unmountEvent = new CustomEvent(AUTOFOCUS_ON_UNMOUNT, EVENT_OPTIONS);
8401          container.addEventListener(AUTOFOCUS_ON_UNMOUNT, onUnmountAutoFocus);
8402          container.dispatchEvent(unmountEvent);
8403          if (!unmountEvent.defaultPrevented) {
8404            focus(previouslyFocusedElement ?? document.body, { select: true });
8405          }
8406          container.removeEventListener(AUTOFOCUS_ON_UNMOUNT, onUnmountAutoFocus);
8407          focusScopesStack.remove(focusScope);
8408        }, 0);
8409      };
8410    }
8411  }, [container, onMountAutoFocus, onUnmountAutoFocus, focusScope]);
8412  const handleKeyDown = reactExports.useCallback(
8413    (event) => {
8414      if (!loop && !trapped) return;
8415      if (focusScope.paused) return;
8416      const isTabKey = event.key === "Tab" && !event.altKey && !event.ctrlKey && !event.metaKey;
8417      const focusedElement = document.activeElement;
8418      if (isTabKey && focusedElement) {
8419        const container2 = event.currentTarget;
8420        const [first, last] = getTabbableEdges(container2);
8421        const hasTabbableElementsInside = first && last;
8422        if (!hasTabbableElementsInside) {
8423          if (focusedElement === container2) event.preventDefault();
8424        } else {
8425          if (!event.shiftKey && focusedElement === last) {
8426            event.preventDefault();
8427            if (loop) focus(first, { select: true });
8428          } else if (event.shiftKey && focusedElement === first) {
8429            event.preventDefault();
8430            if (loop) focus(last, { select: true });
8431          }
8432        }
8433      }
8434    },
8435    [loop, trapped, focusScope.paused]
8436  );
8437  return /* @__PURE__ */ jsxRuntimeExports.jsx(Primitive.div, { tabIndex: -1, ...scopeProps, ref: composedRefs, onKeyDown: handleKeyDown });
8438});
8439FocusScope.displayName = FOCUS_SCOPE_NAME;
8440function focusFirst(candidates, { select = false } = {}) {
8441  const previouslyFocusedElement = document.activeElement;
8442  for (const candidate of candidates) {
8443    focus(candidate, { select });
8444    if (document.activeElement !== previouslyFocusedElement) return;
8445  }
8446}
8447function getTabbableEdges(container) {
8448  const candidates = getTabbableCandidates(container);
8449  const first = findVisible(candidates, container);
8450  const last = findVisible(candidates.reverse(), container);
8451  return [first, last];
8452}
8453function getTabbableCandidates(container) {
8454  const nodes = [];
8455  const walker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, {
8456    acceptNode: (node) => {
8457      const isHiddenInput = node.tagName === "INPUT" && node.type === "hidden";
8458      if (node.disabled || node.hidden || isHiddenInput) return NodeFilter.FILTER_SKIP;
8459      return node.tabIndex >= 0 ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
8460    }
8461  });
8462  while (walker.nextNode()) nodes.push(walker.currentNode);
8463  return nodes;
8464}
8465function findVisible(elements, container) {
8466  for (const element of elements) {
8467    if (!isHidden(element, { upTo: container })) return element;
8468  }
8469}
8470function isHidden(node, { upTo }) {
8471  if (getComputedStyle(node).visibility === "hidden") return true;
8472  while (node) {
8473    if (upTo !== void 0 && node === upTo) return false;
vendor: 5,482 bytes, lines 8474-8615
8474    if (getComputedStyle(node).display === "none") return true;
8475    node = node.parentElement;
8476  }
8477  return false;
8478}
8479function isSelectableInput(element) {
8480  return element instanceof HTMLInputElement && "select" in element;
8481}
8482function focus(element, { select = false } = {}) {
8483  if (element && element.focus) {
8484    const previouslyFocusedElement = document.activeElement;
8485    element.focus({ preventScroll: true });
8486    if (element !== previouslyFocusedElement && isSelectableInput(element) && select)
8487      element.select();
8488  }
8489}
8490var focusScopesStack = createFocusScopesStack();
8491function createFocusScopesStack() {
8492  let stack = [];
8493  return {
8494    add(focusScope) {
8495      const activeFocusScope = stack[0];
8496      if (focusScope !== activeFocusScope) {
8497        activeFocusScope == null ? void 0 : activeFocusScope.pause();
8498      }
8499      stack = arrayRemove(stack, focusScope);
8500      stack.unshift(focusScope);
8501    },
8502    remove(focusScope) {
8503      var _a;
8504      stack = arrayRemove(stack, focusScope);
8505      (_a = stack[0]) == null ? void 0 : _a.resume();
8506    }
8507  };
8508}
8509function arrayRemove(array, item) {
8510  const updatedArray = [...array];
8511  const index = updatedArray.indexOf(item);
8512  if (index !== -1) {
8513    updatedArray.splice(index, 1);
8514  }
8515  return updatedArray;
8516}
8517function removeLinks(items) {
8518  return items.filter((item) => item.tagName !== "A");
8519}
8520var NAME = "Arrow";
8521var Arrow$1 = reactExports.forwardRef((props, forwardedRef) => {
8522  const { children, width = 10, height = 5, ...arrowProps } = props;
8523  return /* @__PURE__ */ jsxRuntimeExports.jsx(
8524    Primitive.svg,
8525    {
8526      ...arrowProps,
8527      ref: forwardedRef,
8528      width,
8529      height,
8530      viewBox: "0 0 30 10",
8531      preserveAspectRatio: "none",
8532      children: props.asChild ? children : /* @__PURE__ */ jsxRuntimeExports.jsx("polygon", { points: "0,0 30,0 15,10" })
8533    }
8534  );
8535});
8536Arrow$1.displayName = NAME;
8537var Root = Arrow$1;
8538var POPPER_NAME = "Popper";
8539var [createPopperContext, createPopperScope] = createContextScope(POPPER_NAME);
8540var [PopperProvider, usePopperContext] = createPopperContext(POPPER_NAME);
8541var Popper = (props) => {
8542  const { __scopePopper, children } = props;
8543  const [anchor, setAnchor] = reactExports.useState(null);
8544  return /* @__PURE__ */ jsxRuntimeExports.jsx(PopperProvider, { scope: __scopePopper, anchor, onAnchorChange: setAnchor, children });
8545};
8546Popper.displayName = POPPER_NAME;
8547var ANCHOR_NAME$1 = "PopperAnchor";
8548var PopperAnchor = reactExports.forwardRef(
8549  (props, forwardedRef) => {
8550    const { __scopePopper, virtualRef, ...anchorProps } = props;
8551    const context = usePopperContext(ANCHOR_NAME$1, __scopePopper);
8552    const ref = reactExports.useRef(null);
8553    const composedRefs = useComposedRefs(forwardedRef, ref);
8554    reactExports.useEffect(() => {
8555      context.onAnchorChange((virtualRef == null ? void 0 : virtualRef.current) || ref.current);
8556    });
8557    return virtualRef ? null : /* @__PURE__ */ jsxRuntimeExports.jsx(Primitive.div, { ...anchorProps, ref: composedRefs });
8558  }
8559);
8560PopperAnchor.displayName = ANCHOR_NAME$1;
8561var CONTENT_NAME$1 = "PopperContent";
8562var [PopperContentProvider, useContentContext] = createPopperContext(CONTENT_NAME$1);
8563var PopperContent = reactExports.forwardRef(
8564  (props, forwardedRef) => {
8565    var _a, _b, _c, _d, _e, _f;
8566    const {
8567      __scopePopper,
8568      side = "bottom",
8569      sideOffset = 0,
8570      align = "center",
8571      alignOffset = 0,
8572      arrowPadding = 0,
8573      avoidCollisions = true,
8574      collisionBoundary = [],
8575      collisionPadding: collisionPaddingProp = 0,
8576      sticky = "partial",
8577      hideWhenDetached = false,
8578      updatePositionStrategy = "optimized",
8579      onPlaced,
8580      ...contentProps
8581    } = props;
8582    const context = usePopperContext(CONTENT_NAME$1, __scopePopper);
8583    const [content, setContent] = reactExports.useState(null);
8584    const composedRefs = useComposedRefs(forwardedRef, (node) => setContent(node));
8585    const [arrow$1, setArrow] = reactExports.useState(null);
8586    const arrowSize = useSize(arrow$1);
8587    const arrowWidth = (arrowSize == null ? void 0 : arrowSize.width) ?? 0;
8588    const arrowHeight = (arrowSize == null ? void 0 : arrowSize.height) ?? 0;
8589    const desiredPlacement = side + (align !== "center" ? "-" + align : "");
8590    const collisionPadding = typeof collisionPaddingProp === "number" ? collisionPaddingProp : { top: 0, right: 0, bottom: 0, left: 0, ...collisionPaddingProp };
8591    const boundary = Array.isArray(collisionBoundary) ? collisionBoundary : [collisionBoundary];
8592    const hasExplicitBoundaries = boundary.length > 0;
8593    const detectOverflowOptions = {
8594      padding: collisionPadding,
8595      boundary: boundary.filter(isNotNull),
8596      // with `strategy: 'fixed'`, this is the only way to get it to respect boundaries
8597      altBoundary: hasExplicitBoundaries
8598    };
8599    const { refs, floatingStyles, placement, isPositioned, middlewareData } = useFloating({
8600      // default to `fixed` strategy so users don't have to pick and we also avoid focus scroll issues
8601      strategy: "fixed",
8602      placement: desiredPlacement,
8603      whileElementsMounted: (...args) => {
8604        const cleanup = autoUpdate(...args, {
8605          animationFrame: updatePositionStrategy === "always"
8606        });
8607        return cleanup;
8608      },
8609      elements: {
8610        reference: context.anchor
8611      },
8612      middleware: [
8613        offset({ mainAxis: sideOffset + arrowHeight, alignmentAxis: alignOffset }),
8614        avoidCollisions && shift({
8615          mainAxis: true,
8616          crossAxis: false,
8617          limiter: sticky === "partial" ? limitShift() : void 0,
8618          ...detectOverflowOptions
8619        }),
8620        avoidCollisions && flip({ ...detectOverflowOptions }),
8621        size({
8622          ...detectOverflowOptions,
8623          apply: ({ elements, rects, availableWidth, availableHeight }) => {
8624            const { width: anchorWidth, height: anchorHeight } = rects.reference;
8625            const contentStyle = elements.floating.style;
8626            contentStyle.setProperty("--radix-popper-available-width", `${availableWidth}px`);
8627            contentStyle.setProperty("--radix-popper-available-height", `${availableHeight}px`);
8628            contentStyle.setProperty("--radix-popper-anchor-width", `${anchorWidth}px`);
8629            contentStyle.setProperty("--radix-popper-anchor-height", `${anchorHeight}px`);
8630          }
8631        }),
8632        arrow$1 && arrow({ element: arrow$1, padding: arrowPadding }),
8633        transformOrigin({ arrowWidth, arrowHeight }),
8634        hideWhenDetached && hide({ strategy: "referenceHidden", ...detectOverflowOptions })
8635      ]
8636    });
8637    const [placedSide, placedAlign] = getSideAndAlignFromPlacement(placement);
8638    const handlePlaced = useCallbackRef(onPlaced);
8639    useLayoutEffect2(() => {
8640      if (isPositioned) {
8641        handlePlaced == null ? void 0 : handlePlaced();
8642      }
8643    }, [isPositioned, handlePlaced]);
8644    const arrowX = (_a = middlewareData.arrow) == null ? void 0 : _a.x;
8645    const arrowY = (_b = middlewareData.arrow) == null ? void 0 : _b.y;
8646    const cannotCenterArrow = ((_c = middlewareData.arrow) == null ? void 0 : _c.centerOffset) !== 0;
8647    const [contentZIndex, setContentZIndex] = reactExports.useState();
8648    useLayoutEffect2(() => {
8649      if (content) setContentZIndex(window.getComputedStyle(content).zIndex);
8650    }, [content]);
8651    return /* @__PURE__ */ jsxRuntimeExports.jsx(
8652      "div",
8653      {
8654        ref: refs.setFloating,
8655        "data-radix-popper-content-wrapper": "",
8656        style: {
8657          ...floatingStyles,
8658          transform: isPositioned ? floatingStyles.transform : "translate(0, -200%)",
8659          // keep off the page when measuring
8660          minWidth: "max-content",
8661          zIndex: contentZIndex,
8662          ["--radix-popper-transform-origin"]: [
8663            (_d = middlewareData.transformOrigin) == null ? void 0 : _d.x,
8664            (_e = middlewareData.transformOrigin) == null ? void 0 : _e.y
8665          ].join(" "),
8666          // hide the content if using the hide middleware and should be hidden
8667          // set visibility to hidden and disable pointer events so the UI behaves
8668          // as if the PopperContent isn't there at all
8669          ...((_f = middlewareData.hide) == null ? void 0 : _f.referenceHidden) && {
8670            visibility: "hidden",
8671            pointerEvents: "none"
8672          }
8673        },
8674        dir: props.dir,
8675        children: /* @__PURE__ */ jsxRuntimeExports.jsx(
8676          PopperContentProvider,
8677          {
8678            scope: __scopePopper,
8679            placedSide,
8680            onArrowChange: setArrow,
8681            arrowX,
8682            arrowY,
8683            shouldHideArrow: cannotCenterArrow,
8684            children: /* @__PURE__ */ jsxRuntimeExports.jsx(
8685              Primitive.div,
8686              {
8687                "data-side": placedSide,
8688                "data-align": placedAlign,
8689                ...contentProps,
8690                ref: composedRefs,
8691                style: {
8692                  ...contentProps.style,
8693                  // if the PopperContent hasn't been placed yet (not all measurements done)
8694                  // we prevent animations so that users's animation don't kick in too early referring wrong sides
8695                  animation: !isPositioned ? "none" : void 0
8696                }
8697              }
8698            )
8699          }
8700        )
8701      }
8702    );
8703  }
8704);
8705PopperContent.displayName = CONTENT_NAME$1;
8706var ARROW_NAME$1 = "PopperArrow";
8707var OPPOSITE_SIDE = {
8708  top: "bottom",
8709  right: "left",
8710  bottom: "top",
8711  left: "right"
8712};
8713var PopperArrow = reactExports.forwardRef(function PopperArrow2(props, forwardedRef) {
8714  const { __scopePopper, ...arrowProps } = props;
8715  const contentContext = useContentContext(ARROW_NAME$1, __scopePopper);
8716  const baseSide = OPPOSITE_SIDE[contentContext.placedSide];
8717  return (
8718    // we have to use an extra wrapper because `ResizeObserver` (used by `useSize`)
8719    // doesn't report size as we'd expect on SVG elements.
8720    // it reports their bounding box which is effectively the largest path inside the SVG.
vendor: 12,509 bytes, lines 8721-9034
8721    /* @__PURE__ */ jsxRuntimeExports.jsx(
8722      "span",
8723      {
8724        ref: contentContext.onArrowChange,
8725        style: {
8726          position: "absolute",
8727          left: contentContext.arrowX,
8728          top: contentContext.arrowY,
8729          [baseSide]: 0,
8730          transformOrigin: {
8731            top: "",
8732            right: "0 0",
8733            bottom: "center 0",
8734            left: "100% 0"
8735          }[contentContext.placedSide],
8736          transform: {
8737            top: "translateY(100%)",
8738            right: "translateY(50%) rotate(90deg) translateX(-50%)",
8739            bottom: `rotate(180deg)`,
8740            left: "translateY(50%) rotate(-90deg) translateX(50%)"
8741          }[contentContext.placedSide],
8742          visibility: contentContext.shouldHideArrow ? "hidden" : void 0
8743        },
8744        children: /* @__PURE__ */ jsxRuntimeExports.jsx(
8745          Root,
8746          {
8747            ...arrowProps,
8748            ref: forwardedRef,
8749            style: {
8750              ...arrowProps.style,
8751              // ensures the element can be measured correctly (mostly for if SVG)
8752              display: "block"
8753            }
8754          }
8755        )
8756      }
8757    )
8758  );
8759});
8760PopperArrow.displayName = ARROW_NAME$1;
8761function isNotNull(value) {
8762  return value !== null;
8763}
8764var transformOrigin = (options) => ({
8765  name: "transformOrigin",
8766  options,
8767  fn(data) {
8768    var _a, _b, _c;
8769    const { placement, rects, middlewareData } = data;
8770    const cannotCenterArrow = ((_a = middlewareData.arrow) == null ? void 0 : _a.centerOffset) !== 0;
8771    const isArrowHidden = cannotCenterArrow;
8772    const arrowWidth = isArrowHidden ? 0 : options.arrowWidth;
8773    const arrowHeight = isArrowHidden ? 0 : options.arrowHeight;
8774    const [placedSide, placedAlign] = getSideAndAlignFromPlacement(placement);
8775    const noArrowAlign = { start: "0%", center: "50%", end: "100%" }[placedAlign];
8776    const arrowXCenter = (((_b = middlewareData.arrow) == null ? void 0 : _b.x) ?? 0) + arrowWidth / 2;
8777    const arrowYCenter = (((_c = middlewareData.arrow) == null ? void 0 : _c.y) ?? 0) + arrowHeight / 2;
8778    let x = "";
8779    let y = "";
8780    if (placedSide === "bottom") {
8781      x = isArrowHidden ? noArrowAlign : `${arrowXCenter}px`;
8782      y = `${-arrowHeight}px`;
8783    } else if (placedSide === "top") {
8784      x = isArrowHidden ? noArrowAlign : `${arrowXCenter}px`;
8785      y = `${rects.floating.height + arrowHeight}px`;
8786    } else if (placedSide === "right") {
8787      x = `${-arrowHeight}px`;
8788      y = isArrowHidden ? noArrowAlign : `${arrowYCenter}px`;
8789    } else if (placedSide === "left") {
8790      x = `${rects.floating.width + arrowHeight}px`;
8791      y = isArrowHidden ? noArrowAlign : `${arrowYCenter}px`;
8792    }
8793    return { data: { x, y } };
8794  }
8795});
8796function getSideAndAlignFromPlacement(placement) {
8797  const [side, align = "center"] = placement.split("-");
8798  return [side, align];
8799}
8800var Root2$1 = Popper;
8801var Anchor = PopperAnchor;
8802var Content = PopperContent;
8803var Arrow = PopperArrow;
8804var PORTAL_NAME$1 = "Portal";
8805var Portal$1 = reactExports.forwardRef((props, forwardedRef) => {
8806  var _a;
8807  const { container: containerProp, ...portalProps } = props;
8808  const [mounted, setMounted] = reactExports.useState(false);
8809  useLayoutEffect2(() => setMounted(true), []);
8810  const container = containerProp || mounted && ((_a = globalThis == null ? void 0 : globalThis.document) == null ? void 0 : _a.body);
8811  return container ? ReactDOM.createPortal(/* @__PURE__ */ jsxRuntimeExports.jsx(Primitive.div, { ...portalProps, ref: forwardedRef }), container) : null;
8812});
8813Portal$1.displayName = PORTAL_NAME$1;
8814function useStateMachine(initialState, machine) {
8815  return reactExports.useReducer((state, event) => {
8816    const nextState = machine[state][event];
8817    return nextState ?? state;
8818  }, initialState);
8819}
8820var Presence = (props) => {
8821  const { present, children } = props;
8822  const presence = usePresence(present);
8823  const child = typeof children === "function" ? children({ present: presence.isPresent }) : reactExports.Children.only(children);
8824  const ref = useComposedRefs(presence.ref, getElementRef(child));
8825  const forceMount = typeof children === "function";
8826  return forceMount || presence.isPresent ? reactExports.cloneElement(child, { ref }) : null;
8827};
8828Presence.displayName = "Presence";
8829function usePresence(present) {
8830  const [node, setNode] = reactExports.useState();
8831  const stylesRef = reactExports.useRef(null);
8832  const prevPresentRef = reactExports.useRef(present);
8833  const prevAnimationNameRef = reactExports.useRef("none");
8834  const initialState = present ? "mounted" : "unmounted";
8835  const [state, send] = useStateMachine(initialState, {
8836    mounted: {
8837      UNMOUNT: "unmounted",
8838      ANIMATION_OUT: "unmountSuspended"
8839    },
8840    unmountSuspended: {
8841      MOUNT: "mounted",
8842      ANIMATION_END: "unmounted"
8843    },
8844    unmounted: {
8845      MOUNT: "mounted"
8846    }
8847  });
8848  reactExports.useEffect(() => {
8849    const currentAnimationName = getAnimationName(stylesRef.current);
8850    prevAnimationNameRef.current = state === "mounted" ? currentAnimationName : "none";
8851  }, [state]);
8852  useLayoutEffect2(() => {
8853    const styles = stylesRef.current;
8854    const wasPresent = prevPresentRef.current;
8855    const hasPresentChanged = wasPresent !== present;
8856    if (hasPresentChanged) {
8857      const prevAnimationName = prevAnimationNameRef.current;
8858      const currentAnimationName = getAnimationName(styles);
8859      if (present) {
8860        send("MOUNT");
8861      } else if (currentAnimationName === "none" || (styles == null ? void 0 : styles.display) === "none") {
8862        send("UNMOUNT");
8863      } else {
8864        const isAnimating = prevAnimationName !== currentAnimationName;
8865        if (wasPresent && isAnimating) {
8866          send("ANIMATION_OUT");
8867        } else {
8868          send("UNMOUNT");
8869        }
8870      }
8871      prevPresentRef.current = present;
8872    }
8873  }, [present, send]);
8874  useLayoutEffect2(() => {
8875    if (node) {
8876      let timeoutId;
8877      const ownerWindow = node.ownerDocument.defaultView ?? window;
8878      const handleAnimationEnd = (event) => {
8879        const currentAnimationName = getAnimationName(stylesRef.current);
8880        const isCurrentAnimation = currentAnimationName.includes(event.animationName);
8881        if (event.target === node && isCurrentAnimation) {
8882          send("ANIMATION_END");
8883          if (!prevPresentRef.current) {
8884            const currentFillMode = node.style.animationFillMode;
8885            node.style.animationFillMode = "forwards";
8886            timeoutId = ownerWindow.setTimeout(() => {
8887              if (node.style.animationFillMode === "forwards") {
8888                node.style.animationFillMode = currentFillMode;
8889              }
8890            });
8891          }
8892        }
8893      };
8894      const handleAnimationStart = (event) => {
8895        if (event.target === node) {
8896          prevAnimationNameRef.current = getAnimationName(stylesRef.current);
8897        }
8898      };
8899      node.addEventListener("animationstart", handleAnimationStart);
8900      node.addEventListener("animationcancel", handleAnimationEnd);
8901      node.addEventListener("animationend", handleAnimationEnd);
8902      return () => {
8903        ownerWindow.clearTimeout(timeoutId);
8904        node.removeEventListener("animationstart", handleAnimationStart);
8905        node.removeEventListener("animationcancel", handleAnimationEnd);
8906        node.removeEventListener("animationend", handleAnimationEnd);
8907      };
8908    } else {
8909      send("ANIMATION_END");
8910    }
8911  }, [node, send]);
8912  return {
8913    isPresent: ["mounted", "unmountSuspended"].includes(state),
8914    ref: reactExports.useCallback((node2) => {
8915      stylesRef.current = node2 ? getComputedStyle(node2) : null;
8916      setNode(node2);
8917    }, [])
8918  };
8919}
8920function getAnimationName(styles) {
8921  return (styles == null ? void 0 : styles.animationName) || "none";
8922}
8923function getElementRef(element) {
8924  var _a, _b;
8925  let getter = (_a = Object.getOwnPropertyDescriptor(element.props, "ref")) == null ? void 0 : _a.get;
8926  let mayWarn = getter && "isReactWarning" in getter && getter.isReactWarning;
8927  if (mayWarn) {
8928    return element.ref;
8929  }
8930  getter = (_b = Object.getOwnPropertyDescriptor(element, "ref")) == null ? void 0 : _b.get;
8931  mayWarn = getter && "isReactWarning" in getter && getter.isReactWarning;
8932  if (mayWarn) {
8933    return element.props.ref;
8934  }
8935  return element.props.ref || element.ref;
8936}
8937var POPOVER_NAME = "Popover";
8938var [createPopoverContext, createPopoverScope] = createContextScope(POPOVER_NAME, [
8939  createPopperScope
8940]);
8941var usePopperScope = createPopperScope();
8942var [PopoverProvider, usePopoverContext] = createPopoverContext(POPOVER_NAME);
8943var Popover$1 = (props) => {
8944  const {
8945    __scopePopover,
8946    children,
8947    open: openProp,
8948    defaultOpen,
8949    onOpenChange,
8950    modal = false
8951  } = props;
8952  const popperScope = usePopperScope(__scopePopover);
8953  const triggerRef = reactExports.useRef(null);
8954  const [hasCustomAnchor, setHasCustomAnchor] = reactExports.useState(false);
8955  const [open, setOpen] = useControllableState({
8956    prop: openProp,
8957    defaultProp: defaultOpen ?? false,
8958    onChange: onOpenChange,
8959    caller: POPOVER_NAME
8960  });
8961  return /* @__PURE__ */ jsxRuntimeExports.jsx(Root2$1, { ...popperScope, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
8962    PopoverProvider,
8963    {
8964      scope: __scopePopover,
8965      contentId: useId(),
8966      triggerRef,
8967      open,
8968      onOpenChange: setOpen,
8969      onOpenToggle: reactExports.useCallback(() => setOpen((prevOpen) => !prevOpen), [setOpen]),
8970      hasCustomAnchor,
8971      onCustomAnchorAdd: reactExports.useCallback(() => setHasCustomAnchor(true), []),
8972      onCustomAnchorRemove: reactExports.useCallback(() => setHasCustomAnchor(false), []),
8973      modal,
8974      children
8975    }
8976  ) });
8977};
8978Popover$1.displayName = POPOVER_NAME;
8979var ANCHOR_NAME = "PopoverAnchor";
8980var PopoverAnchor$1 = reactExports.forwardRef(
8981  (props, forwardedRef) => {
8982    const { __scopePopover, ...anchorProps } = props;
8983    const context = usePopoverContext(ANCHOR_NAME, __scopePopover);
8984    const popperScope = usePopperScope(__scopePopover);
8985    const { onCustomAnchorAdd, onCustomAnchorRemove } = context;
8986    reactExports.useEffect(() => {
8987      onCustomAnchorAdd();
8988      return () => onCustomAnchorRemove();
8989    }, [onCustomAnchorAdd, onCustomAnchorRemove]);
8990    return /* @__PURE__ */ jsxRuntimeExports.jsx(Anchor, { ...popperScope, ...anchorProps, ref: forwardedRef });
8991  }
8992);
8993PopoverAnchor$1.displayName = ANCHOR_NAME;
8994var TRIGGER_NAME = "PopoverTrigger";
8995var PopoverTrigger = reactExports.forwardRef(
8996  (props, forwardedRef) => {
8997    const { __scopePopover, ...triggerProps } = props;
8998    const context = usePopoverContext(TRIGGER_NAME, __scopePopover);
8999    const popperScope = usePopperScope(__scopePopover);
9000    const composedTriggerRef = useComposedRefs(forwardedRef, context.triggerRef);
9001    const trigger = /* @__PURE__ */ jsxRuntimeExports.jsx(
9002      Primitive.button,
9003      {
9004        type: "button",
9005        "aria-haspopup": "dialog",
9006        "aria-expanded": context.open,
9007        "aria-controls": context.contentId,
9008        "data-state": getState(context.open),
9009        ...triggerProps,
9010        ref: composedTriggerRef,
9011        onClick: composeEventHandlers(props.onClick, context.onOpenToggle)
9012      }
9013    );
9014    return context.hasCustomAnchor ? trigger : /* @__PURE__ */ jsxRuntimeExports.jsx(Anchor, { asChild: true, ...popperScope, children: trigger });
9015  }
9016);
9017PopoverTrigger.displayName = TRIGGER_NAME;
9018var PORTAL_NAME = "PopoverPortal";
9019var [PortalProvider, usePortalContext] = createPopoverContext(PORTAL_NAME, {
9020  forceMount: void 0
9021});
9022var PopoverPortal = (props) => {
9023  const { __scopePopover, forceMount, children, container } = props;
9024  const context = usePopoverContext(PORTAL_NAME, __scopePopover);
9025  return /* @__PURE__ */ jsxRuntimeExports.jsx(PortalProvider, { scope: __scopePopover, forceMount, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Presence, { present: forceMount || context.open, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Portal$1, { asChild: true, container, children }) }) });
9026};
9027PopoverPortal.displayName = PORTAL_NAME;
9028var CONTENT_NAME = "PopoverContent";
9029var PopoverContent$1 = reactExports.forwardRef(
9030  (props, forwardedRef) => {
9031    const portalContext = usePortalContext(CONTENT_NAME, props.__scopePopover);
9032    const { forceMount = portalContext.forceMount, ...contentProps } = props;
9033    const context = usePopoverContext(CONTENT_NAME, props.__scopePopover);
9034    return /* @__PURE__ */ jsxRuntimeExports.jsx(Presence, { present: forceMount || context.open, children: context.modal ? /* @__P
9034URE__ */ jsxRuntimeExports.jsx(PopoverContentModal, { ...contentProps, ref: forwardedRef }) : /* @__PURE__ */ jsxRuntimeExports.jsx(PopoverContentNonModal, { ...contentProps, ref: forwardedRef }) });
9035  }
9036);
9037PopoverContent$1.displayName = CONTENT_NAME;
9038var Slot = /* @__PURE__ */ createSlot("PopoverContent.RemoveScroll");
9039var PopoverContentModal = reactExports.forwardRef(
9040  (props, forwardedRef) => {
9041    const context = usePopoverContext(CONTENT_NAME, props.__scopePopover);
9042    const contentRef = reactExports.useRef(null);
9043    const composedRefs = useComposedRefs(forwardedRef, contentRef);
9044    const isRightClickOutsideRef = reactExports.useRef(false);
9045    reactExports.useEffect(() => {
9046      const content = contentRef.current;
9047      if (content) return hideOthers(content);
9048    }, []);
9049    return /* @__PURE__ */ jsxRuntimeExports.jsx(ReactRemoveScroll, { as: Slot, allowPinchZoom: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
9050      PopoverContentImpl,
9051      {
9052        ...props,
9053        ref: composedRefs,
9054        trapFocus: context.open,
9055        disableOutsidePointerEvents: true,
9056        onCloseAutoFocus: composeEventHandlers(props.onCloseAutoFocus, (event) => {
9057          var _a;
9058          event.preventDefault();
9059          if (!isRightClickOutsideRef.current) (_a = context.triggerRef.current) == null ? void 0 : _a.focus();
9060        }),
9061        onPointerDownOutside: composeEventHandlers(
9062          props.onPointerDownOutside,
9063          (event) => {
9064            const originalEvent = event.detail.originalEvent;
9065            const ctrlLeftClick = originalEvent.button === 0 && originalEvent.ctrlKey === true;
9066            const isRightClick = originalEvent.button === 2 || ctrlLeftClick;
9067            isRightClickOutsideRef.current = isRightClick;
9068          },
9069          { checkForDefaultPrevented: false }
9070        ),
9071        onFocusOutside: composeEventHandlers(
9072          props.onFocusOutside,
9073          (event) => event.preventDefault(),
9074          { checkForDefaultPrevented: false }
9075        )
9076      }
9077    ) });
9078  }
9079);
9080var PopoverContentNonModal = reactExports.forwardRef(
9081  (props, forwardedRef) => {
9082    const context = usePopoverContext(CONTENT_NAME, props.__scopePopover);
9083    const hasInteractedOutsideRef = reactExports.useRef(false);
9084    const hasPointerDownOutsideRef = reactExports.useRef(false);
9085    return /* @__PURE__ */ jsxRuntimeExports.jsx(
9086      PopoverContentImpl,
9087      {
9088        ...props,
9089        ref: forwardedRef,
9090        trapFocus: false,
9091        disableOutsidePointerEvents: false,
9092        onCloseAutoFocus: (event) => {
9093          var _a, _b;
9094          (_a = props.onCloseAutoFocus) == null ? void 0 : _a.call(props, event);
9095          if (!event.defaultPrevented) {
9096            if (!hasInteractedOutsideRef.current) (_b = context.triggerRef.current) == null ? void 0 : _b.focus();
9097            event.preventDefault();
9098          }
9099          hasInteractedOutsideRef.current = false;
9100          hasPointerDownOutsideRef.current = false;
9101        },
9102        onInteractOutside: (event) => {
9103          var _a, _b;
9104          (_a = props.onInteractOutside) == null ? void 0 : _a.call(props, event);
9105          if (!event.defaultPrevented) {
9106            hasInteractedOutsideRef.current = true;
9107            if (event.detail.originalEvent.type === "pointerdown") {
9108              hasPointerDownOutsideRef.current = true;
9109            }
9110          }
9111          const target = event.target;
9112          const targetIsTrigger = (_b = context.triggerRef.current) == null ? void 0 : _b.contains(target);
9113          if (targetIsTrigger) event.preventDefault();
9114          if (event.detail.originalEvent.type === "focusin" && hasPointerDownOutsideRef.current) {
9115            event.preventDefault();
9116          }
9117        }
9118      }
9119    );
9120  }
9121);
9122var PopoverContentImpl = reactExports.forwardRef(
9123  (props, forwardedRef) => {
9124    const {
9125      __scopePopover,
9126      trapFocus,
9127      onOpenAutoFocus,
9128      onCloseAutoFocus,
9129      disableOutsidePointerEvents,
9130      onEscapeKeyDown,
9131      onPointerDownOutside,
9132      onFocusOutside,
9133      onInteractOutside,
9134      ...contentProps
9135    } = props;
9136    const context = usePopoverContext(CONTENT_NAME, __scopePopover);
9137    const popperScope = usePopperScope(__scopePopover);
9138    useFocusGuards();
9139    return /* @__PURE__ */ jsxRuntimeExports.jsx(
9140      FocusScope,
9141      {
9142        asChild: true,
9143        loop: true,
9144        trapped: trapFocus,
9145        onMountAutoFocus: onOpenAutoFocus,
9146        onUnmountAutoFocus: onCloseAutoFocus,
9147        children: /* @__PURE__ */ jsxRuntimeExports.jsx(
9148          DismissableLayer,
9149          {
9150            asChild: true,
9151            disableOutsidePointerEvents,
9152            onInteractOutside,
9153            onEscapeKeyDown,
9154            onPointerDownOutside,
9155            onFocusOutside,
9156            onDismiss: () => context.onOpenChange(false),
9157            children: /* @__PURE__ */ jsxRuntimeExports.jsx(
9158              Content,
9159              {
9160                "data-state": getState(context.open),
9161                role: "dialog",
9162                id: context.contentId,
9163                ...popperScope,
9164                ...contentProps,
9165                ref: forwardedRef,
9166                style: {
9167                  ...contentProps.style,
9168                  // re-namespace exposed content custom properties
9169                  ...{
9170                    "--radix-popover-content-transform-origin": "var(--radix-popper-transform-origin)",
9171                    "--radix-popover-content-available-width": "var(--radix-popper-available-width)",
9172                    "--radix-popover-content-available-height": "var(--radix-popper-available-height)",
9173                    "--radix-popover-trigger-width": "var(--radix-popper-anchor-width)",
9174                    "--radix-popover-trigger-height": "var(--radix-popper-anchor-height)"
9175                  }
9176                }
9177              }
9178            )
9179          }
9180        )
9181      }
9182    );
9183  }
9184);
9185var CLOSE_NAME = "PopoverClose";
9186var PopoverClose = reactExports.forwardRef(
9187  (props, forwardedRef) => {
9188    const { __scopePopover, ...closeProps } = props;
9189    const context = usePopoverContext(CLOSE_NAME, __scopePopover);
9190    return /* @__PURE__ */ jsxRuntimeExports.jsx(
9191      Primitive.button,
9192      {
9193        type: "button",
9194        ...closeProps,
9195        ref: forwardedRef,
9196        onClick: composeEventHandlers(props.onClick, () => context.onOpenChange(false))
9197      }
9198    );
9199  }
9200);
9201PopoverClose.displayName = CLOSE_NAME;
9202var ARROW_NAME = "PopoverArrow";
9203var PopoverArrow = reactExports.forwardRef(
9204  (props, forwardedRef) => {
9205    const { __scopePopover, ...arrowProps } = props;
9206    const popperScope = usePopperScope(__scopePopover);
9207    return /* @__PURE__ */ jsxRuntimeExports.jsx(Arrow, { ...popperScope, ...arrowProps, ref: forwardedRef });
9208  }
9209);
9210PopoverArrow.displayName = ARROW_NAME;
9211function getState(open) {
9212  return open ? "open" : "closed";
9213}
9214var Root2 = Popover$1;
9215var Anchor2 = PopoverAnchor$1;
9216var Portal = PopoverPortal;
9217var Content2 = PopoverContent$1;
9218const Popover = Root2;
9219const PopoverAnchor = Anchor2;
9220const PopoverContent = reactExports.forwardRef(({
9221  className,
9222  align = "center",
9223  sideOffset = 4,
9224  ...props
9225}, ref) => /* @__PURE__ */ jsxRuntimeExports.jsx(Portal, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(Content2, { ref, align, sideOffset, className: cn$1("z-50 w-72 origin-[--radix-popover-content-transform-origin] rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none 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-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:sli
9225de-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", className), ...props }) }));
9226PopoverContent.displayName = Content2.displayName;
9227function pickerAllowedOrigin({
9228  previewUrl,
9229  hoverPointer,
9230  previewBaseDomain
9231}) {
9232  if (!hoverPointer) {
9233    return {
9234      allowed: false,
9235      reason: "touch"
9236    };
9237  }
9238  if (!previewUrl) {
9239    return {
9240      allowed: false,
9241      reason: "unknown"
9242    };
9243  }
9244  let host;
9245  try {
9246    host = new URL(previewUrl).hostname.toLowerCase();
9247  } catch {
9248    return {
9249      allowed: false,
9250      reason: "unknown"
9251    };
9252  }
9253  if (host === "history.landingsite.dev" || host.endsWith(".history.landingsite.dev")) {
9254    return {
9255      allowed: false,
9256      reason: "history"
9257    };
9258  }
9259  if (host === "agncy.dev" || host.endsWith(".agncy.dev")) {
9260    return {
9261      allowed: false,
9262      reason: "agncy"
9263    };
9264  }
9265  if (host === "landingsite.dev" || host.endsWith(".landingsite.dev")) {
9266    return {
9267      allowed: true
9268    };
9269  }
9270  if (host === "agcy.dev" || host.endsWith(".agcy.dev")) {
9271    return {
9272      allowed: true
9273    };
9274  }
9275  if (host === "localhost" || host === "127.0.0.1") {
9276    try {
9277      const port = new URL(previewUrl).port;
9278      if (port === "8792") return {
9279        allowed: true
9280      };
9281    } catch {
9282    }
9283  }
9284  return {
9285    allowed: false,
9286    reason: "unknown"
9287  };
9288}
9289function validateTextEdits(raw, requireLoc) {
9290  if (!Array.isArray(raw)) return [];
9291  const enc = new TextEncoder();
9292  const out = [];
9293  for (const e of raw.slice(0, 500)) {
9294    if (!e || typeof e !== "object") continue;
9295    const ed = e;
9296    if (typeof ed.sourceLoc !== "string" || typeof ed.oldText !== "string" || typeof ed.newText !== "string") {
9297      continue;
9298    }
9299    const hasValidLoc = /^.+:\d+:\d+$/.test(ed.sourceLoc) && enc.encode(ed.sourceLoc).length <= 512;
9300    if (requireLoc && !hasValidLoc) continue;
9301    if (enc.encode(ed.oldText).length > 64 * 1024) continue;
9302    if (enc.encode(ed.newText).length > 64 * 1024) continue;
9303    out.push({
9304      sourceLoc: hasValidLoc ? ed.sourceLoc : "",
9305      oldText: ed.oldText,
9306      newText: ed.newText,
9307      tag: typeof ed.tag === "string" ? ed.tag.toLowerCase().slice(0, 64) : "",
9308      path: typeof ed.path === "string" ? ed.path.slice(0, 512) : ""
9309    });
9310  }
9311  return out;
9312}
9313function parsePickerMessage(data) {
9314  if (!data || typeof data !== "object") return null;
9315  const raw = data;
9316  if (typeof raw.type !== "string") return null;
9317  switch (raw.type) {
9318    case "selector-probe":
9319    case "enter-select":
9320    case "cancel-select":
9321    case "selector-ready":
9322    case "enter-select-ack":
9323    case "enter-edit-text-ack":
9324    case "cancel-select-request":
9325      return {
9326        type: raw.type
9327      };
9328    case "edit-queue-count": {
9329      const r = raw;
9330      const count2 = typeof r.count === "number" ? r.count : 0;
9331      const persistable = typeof r.persistable === "number" ? r.persistable : 0;
9332      return {
9333        type: "edit-queue-count",
9334        count: Math.max(0, Math.floor(count2)),
9335        persistable: Math.max(0, Math.floor(persistable))
9336      };
9337    }
9338    case "text-edit-batch": {
9339      const r = raw;
9340      if (!Array.isArray(r.edits)) return null;
9341      const forEditId = typeof r.forEditId === "number" && Number.isFinite(r.forEditId) && r.forEditId >= 0 ? Math.floor(r.forEditId) : void 0;
9342      return {
9343        type: "text-edit-batch",
9344        edits: validateTextEdits(r.edits, true),
9345        agentEdits: validateTextEdits(r.agentEdits, false),
9346        ...forEditId !== void 0 ? {
9347          forEditId
9348        } : {}
9349      };
9350    }
9351    case "active-edit-element": {
9352      const r = raw;
9353      if (typeof r.editId !== "number" || !Number.isFinite(r.editId) || r.editId < 0 || !r.rect || typeof r.rect !== "object" || typeof r.sourceLoc !== "string" || typeof r.hasSourceLoc !== "boolean" || typeof r.isDirty !== "boolean") {
9354        return null;
9355      }
9356      const rectRaw = r.rect;
9357      if (typeof rectRaw.top !== "number" || typeof rectRaw.left !== "number" || typeof rectRaw.width !== "number" || typeof rectRaw.height !== "number" || !Number.isFinite(rectRaw.top) || !Number.isFinite(rectRaw.left) || !Number.isFinite(rectRaw.width) || !Number.isFinite(rectRaw.height)) {
9358        return null;
9359      }
9360      const encActive = new TextEncoder();
9361      const validLoc = r.sourceLoc.length > 0 && encActive.encode(r.sourceLoc).length <= 512 && /^.+:\d+:\d+$/.test(r.sourceLoc);
9362      return {
9363        type: "active-edit-element",
9364        editId: Math.floor(r.editId),
9365        rect: {
9366          top: rectRaw.top,
9367          left: rectRaw.left,
9368          width: Math.max(0, rectRaw.width),
9369          height: Math.max(0, rectRaw.height)
9370        },
9371        sourceLoc: validLoc ? r.sourceLoc : "",
9372        hasSourceLoc: validLoc ? r.hasSourceLoc : false,
9373        isDirty: r.isDirty
9374      };
9375    }
9376    case "request-focus-change": {
9377      const r = raw;
9378      if (typeof r.fromEditId !== "number" || !Number.isFinite(r.fromEditId) || r.fromEditId < 0 || typeof r.toEditId !== "number" || !Number.isFinite(r.toEditId) || r.toEditId < -1 || typeof r.dirtyPreview !== "string") {
9379        return null;
9380      }
9381      return {
9382        type: "request-focus-change",
9383        fromEditId: Math.floor(r.fromEditId),
9384        toEditId: Math.floor(r.toEditId),
9385        dirtyPreview: r.dirtyPreview.slice(0, 120)
9386      };
9387    }
9388    case "selected": {
9389      const r = raw;
9390      if (typeof r.outerHTML !== "string" || typeof r.tag !== "string" || typeof r.textPreview !== "string" || typeof r.path !== "string") {
9391        return null;
9392      }
9393      if (!/^[a-zA-Z][a-zA-Z0-9-]{0,63}$/.test(r.tag)) return null;
9394      const enc = new TextEncoder();
9395      if (enc.encode(r.outerHTML).length > 200 * 1024) return null;
9396      if (enc.encode(r.textPreview).length > 1024) return null;
9397      if (enc.encode(r.path).length > 512) return null;
9398      let sourceLoc;
9399      if (typeof r.sourceLoc === "string") {
9400        if (enc.encode(r.sourceLoc).length <= 512 && /^.+:\d+:\d+$/.test(r.sourceLoc)) {
9401          sourceLoc = r.sourceLoc;
9402        }
9403      }
9404      return {
9405        type: "selected",
9406        outerHTML: r.outerHTML,
9407        tag: r.tag,
9408        textPreview: r.textPreview,
9409        path: r.path,
9410        ...sourceLoc !== void 0 ? {
9411          sourceLoc
9412        } : {}
9413      };
9414    }
9415    default:
9416      return null;
9417  }
9418}
9419const COUNTRY_FORMS = {
9420  GB: {
9421    city: "Town or city",
9422    state: "County (optional)",
9423    postal: "Postcode"
9424  },
9425  US: {
9426    city: "City",
9427    state: "State",
9428    postal: "ZIP code"
9429  },
9430  CA: {
9431    city: "City",
9432    state: "Province",
9433    postal: "Postal code"
9434  },
9435  IE: {
9436    city: "Town or city",
9437    state: "County",
9438    postal: "Eircode (optional)"
9439  },
9440  AU: {
9441    city: "Suburb",
9442    state: "State",
9443    postal: "Postcode"
9444  },
9445  NZ: {
9446    city: "Town or city",
9447    state: null,
9448    postal: "Postcode"
9449  },
9450  DE: {
9451    city: "City",
9452    state: null,
9453    postal: "Postal code"
9454  },
9455  FR: {
9456    city: "City",
9457    state: null,
9458    postal: "Postal code"
9459  },
9460  NL: {
9461    city: "City",
9462    state: null,
9463    postal: "Postal code"
9464  },
9465  ES: {
9466    city: "City",
9467    state: "Province",
9468    postal: "Postal code"
9469  },
9470  IT: {
9471    city: "City",
9472    state: "Province",
9473    postal: "Postal code"
9474  },
9475  HK: {
9476    city: "District",
9477    state: "Region",
9478    postal: false
9479  },
9480  AE: {
9481    city: "City",
9482    state: "Emirate",
9483    postal: false
9484  },
9485  SG: {
9486    city: "City",
9487    state: null,
9488    postal: "Postal code"
9489  },
9490  JP: {
9491    city: "City / ward",
9492    state: "Prefecture",
9493    postal: "Postal code"
9494  }
9495};
9496const DEFAULT_FORM = {
9497  city: "Town or city",
9498  state: "State, province or region (optional)",
9499  postal: "Postal code"
9500};
9501const COUNTRY_NAMES = {
9502  GB: "United Kingdom",
9503  US: "United States",
9504  CA: "Canada",
9505  IE: "Ireland",
9506  AU: "Australia",
9507  NZ: "New Zealand",
9508  DE: "Germany",
9509  FR: "France",
9510  NL: "Netherlands",
9511  ES: "Spain",
9512  IT: "Italy",
9513  HK: "Hong Kong",
9514  AE: "United Arab Emirates",
9515  SG: "Singapore",
9516  JP: "Japan"
9517};
9518const CURRENCY_HOME = {
9519  gbp: "GB",
9520  usd: "US",
9521  cad: "CA",
9522  eur: "IE",
9523  aud: "AU",
9524  nzd: "NZ",
9525  sgd: "SG",
9526  hkd: "HK",
9527  aed: "AE",
9528  jpy: "JP"
9529};
9530const money = (minor, currency) => {
9531  try {
9532    return new Intl.NumberFormat(void 0, {
9533      style: "currency",
9534      currency: currency.toUpperCase()
9535    }).format(minor / 100);
9536  } catch {
9537    return `${(minor / 100).toFixed(2)} ${currency.toUpperCase()}`;
9538  }
9539};
9540const intervalPhrase = (plan) => plan.intervalCount === 1 ? plan.interval : `${plan.intervalCount} ${plan.interval}s`;
9541const TestCheckoutSheet = ({
9542  open,
9543  storeName,
9544  ownerEmail,
9545  collectsShippingAddress,
9546  shippingCountries,
9547  currency,
9548  lines,
9549  subtotal,
9550  shippingRates,
9551  freeShippingOver,
9552  stripeTaxEnabled,
9553  taxBehavior,
9554  subscription,
9555  submitting,
9556  onSubmit,
9557  onCancel
9558}) => {
9559  const countries = reactExports.useMemo(() => {
9560    if (shippingCountries && shippingCountries.length > 0) {
9561      return shippingCountries.map((c) => c.toUpperCase());
9562    }
9563    const home = CURRENCY_HOME[currency == null ? void 0 : currency.toLowerCase()] ?? "US";
9564    const rest = Object.keys(COUNTRY_NAMES).filter((c) => c !== home);
9565    return [home, ...rest];
9566  }, [shippingCountries, currency]);
9567  const [name, setName] = reactExports.useState("");
9568  const [line1, setLine1] = reactExports.useState("");
9569  const [line2, setLine2] = reactExports.useState("");
9570  const [city, setCity] = reactExports.useState("");
9571  const [stateRegion, setStateRegion] = reactExports.useState("");
9572  const [postalCode, setPostalCode] = reactExports.useState("");
9573  const [country, setCountry] = reactExports.useState(countries[0] ?? "US");
9574  const [touched, setTouched] = reactExports.useState(false);
9575  const [shippingLabel, setShippingLabel] = reactExports.useState(null);
9576  reactExports.useEffect(() => {
9577    if (!open) return;
9578    setName("");
9579    setLine1("");
9580    setLine2("");
9581    setCity("");
9582    setStateRegion("");
9583    setPostalCode("");
9584    setCountry(countries[0] ?? "US");
9585    setTouched(false);
9586    setShippingLabel(null);
9587  }, [open, countries]);
9588  const form = COUNTRY_FORMS[country] ?? DEFAULT_FORM;
9589  const shippableSubtotal = reactExports.useMemo(() => lines.reduce((sum, l) => l.shippable ? sum + l.unitAmount * l.quantity : sum, 0), [lines]);
9590  const freeShippingApplies = freeShippingOver !== null && shippableSubtotal >= freeShippingOver;
9591  const rateOptions = reactExports.useMemo(() => {
9592    let cheapest = 0;
9593    for (let i = 1; i < shippingRates.length; i++) {
9594      if (shippingRates[i].amount < shippingRates[cheapest].amount) cheapest = i;
9595    }
9596    return shippingRates.map((rate, i) => ({
9597      label: rate.label,
9598      amount: freeShippingApplies && i === cheapest ? 0 : rate.amount,
9599      // What it would have cost — shown struck through, so the merchant sees
9600      // the discount happen instead of a bare "Free" with no evidence.
9601      listAmount: rate.amount,
9602      waived: freeShippingApplies && i === cheapest && rate.amount > 0
9603    }));
9604  }, [shippingRates, freeShippingApplies]);
9605  const selectedRate = rateOptions.find((r) => r.label === shippingLabel) ?? rateOptions[0] ?? null;
9606  const deliveryAmount = collectsShippingAddress && !subscription ? (selectedRate == null ? void 0 : selectedRate.amount) ?? 0 : 0;
9607  const chargeSubtotal = subscription ? subscription.amount : subtotal;
9608  const total = chargeSubtotal + deliveryAmount;
9609  const addressOk = !collectsShippingAddress || line1.trim().length > 0;
9610  const canSubmit = addressOk && !submitting;
9611  const submit = () => {
9612    setTouched(true);
9613    if (!canSubmit) return;
9614    onSubmit({
9615      shippingAddress: collectsShippingAddress ? {
9616        name: name.trim() || void 0,
9617        line1: line1.trim(),
9618        line2: line2.trim() || void 0,
9619        city: city.trim() || void 0,
9620        state: stateRegion.trim() || void 0,
9621        postalCode: postalCode.trim() || void 0,
9622        country
9623      } : null,
9624      shippingOption: collectsShippingAddress && !subscription && selectedRate ? selectedRate.label : null
9625    });
9626  };
9627  return /* @__PURE__ */ jsxRuntimeExports.jsx(Dialog, { open, onOpenChange: (next) => !next && onCancel(), children: /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogContent, { className: "max-h-[90vh] gap-0 overflow-y-auto p-0 sm:max-w-[760px]", children: [
9628    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-b border-amber-200 bg-amber-50 px-5 py-3", children: [
9629      /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] font-bold uppercase tracking-wider text-amber-800", children: "Test checkout" }),
9630      /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-0.5 text-[13px] leading-snug text-amber-800/90", children: "A rehearsal of your checkout. No payment is taken, and no card can be entered here." })
9631    ] }),
9632    /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogHeader, { className: "space-y-1 px-5 pb-1 pt-5 text-left", children: [
9633      /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogTitle, { className: "text-base font-semibold", children: [
9634        "What ",
9635        storeName,
9636        " asks buyers for"
9637      ] }),
9638      /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[13px] text-muted-foreground", children: "Stripe collects these on your real checkout page. Fill them in and they'll appear on your test order and its email, exactly as a real sale's would." })
9639    ] }),
9640    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid gap-0 md:grid-cols-[minmax(0,260px)_minmax(0,1fr)]", children: [
9641      /* @__PURE__ */ jsxRuntimeExports.jsxs("aside", { className: "flex flex-col gap-4 border-b bg-muted/40 px-5 py-5 md:border-b-0 md:border-r", children: [
9642        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
9643          /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[12px] text-muted-foreground", children: subscription ? `Subscribe to ${storeName}` : `Pay ${storeName}` }),
9644          /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-2xl font-semibold tabular-nums", children: [
9645            money(total, currency),
9646            subscription && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-sm font-normal text-muted-foreground", children: [
9647              " ",
9648              "/ ",
9649              intervalPhrase(subscription)
9650            ] })
9651          ] })
9652        ] }),
9653        /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { className: "flex list-none flex-col gap-3 p-0", children: lines.map((line, i) => /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { className: "flex items-start gap-3", children: [
9654          line.imageUrl ? /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: line.imageUrl, alt: "", className: "h-10 w-10 shrink-0 rounded border object-cover" }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "h-10 w-10 shrink-0 rounded border bg-background" }),
9655          /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "min-w-0 flex-1", children: [
9656            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "block truncate text-[13px] font-medium", children: line.name }),
9657            /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "block text-[12px] text-muted-foreground", children: [
9658              line.variantTitle ? `${line.variantTitle} · ` : "",
9659              "Qty ",
9660              line.quantity
9661            ] })
9662          ] }),
9663          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0 text-[13px] tabular-nums", children: money(line.unitAmount * line.quantity, currency) })
9664        ] }, i)) }),
9665        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1.5 border-t pt-3 text-[13px]", children: [
9666          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-muted-foreground", children: [
9667            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Subtotal" }),
9668            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "tabular-nums", children: money(chargeSubtotal, currency) })
9669          ] }),
9670          collectsShippingAddress && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-muted-foreground", children: [
9671            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Delivery" }),
9672            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "tabular-nums", children: subscription ? "Included" : (selectedRate == null ? void 0 : selectedRate.waived) ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
9673              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "mr-1.5 line-through opacity-60", children: money(selectedRate.listAmount, currency) }),
9674              "Free"
9675            ] }) : money(deliveryAmount, currency) })
9676          ] }),
9677          stripeTaxEnabled && taxBehavior === "exclusive" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-muted-foreground", children: [
9678            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Tax" }),
9679            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Added at checkout" })
9680          ] }),
9681          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between border-t pt-1.5 font-semibold text-foreground", children: [
9682            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Total" }),
9683            /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "tabular-nums", children: [
9684              money(total, currency),
9685              subscription ? ` / ${intervalPhrase(subscription)}` : ""
9686            ] })
9687          ] })
9688        ] })
9689      ] }),
9690      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-5 px-5 pb-5 pt-4", children: [
9691        subscription && /* A signup is a different promise from a purchase, and the
9692        merchant needs to see WHICH they are rehearsing. Terms only —
9693        renewal, cancel and reactivate are deliberately not simulated,
9694        so this screen must not imply it exercised them. */
9695        /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "rounded-md border border-violet-200 bg-violet-50 px-3 py-2.5 text-[12.5px] leading-snug text-violet-900", children: [
9696          /* @__PURE__ */ jsxRuntimeExports.jsxs("strong", { className: "font-semibold", children: [
9697            subscription.title ?? "Subscription",
9698            " — recurring"
9699          ] }),
9700          " ",
9701          "Your buyer is charged ",
9702          money(subscription.amount, currency),
9703          " ",
9704          "every ",
9705          intervalPhrase(subscription),
9706          " until they cancel. This rehearsal creates the signup and its first order; it does not run a renewal."
9707        ] }),
9708        /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "flex flex-col gap-2", children: [
9709          /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-semibold", children: "Contact" }),
9710          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "overflow-hidden rounded-md border border-input", children: [
9711            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3 px-3 py-2.5", children: [
9712              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 truncate text-sm", children: ownerEmail }),
9713              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "rounded-full bg-violet-100 px-2 py-0.5 text-[10px] font-bold uppercase tracking-wide text-violet-700", children: "You" })
9714            ] }),
9715            /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "border-t border-dashed border-input px-3 py-2 text-[12px] leading-snug text-muted-foreground", children: "Stripe collects your buyer's email here on every order. This test uses yours, so the receipt reaches you." })
9716          ] })
9717        ] }),
9718        collectsShippingAddress && /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "flex flex-col gap-3", children: [
9719          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
9720            /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-semibold", children: "Delivery address" }),
9721            /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[12px] text-muted-foreground", children: "Collected because this order contains something you deliver." })
9722          ] }),
9723          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1.5", children: [
9724            /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "tc-name", className: "text-xs", children: "Full name" }),
9725            /* @__PURE__ */ jsxRuntimeExports.jsx(Input, { id: "tc-name", autoComplete: "off", value: name, onChange: (e) => setName(e.target.value) })
9726          ] }),
9727          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1.5", children: [
9728            /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "tc-line1", className: "text-xs", children: "Address" }),
9729            /* @__PURE__ */ jsxRuntimeExports.jsx(Input, { id: "tc-line1", autoComplete: "off", value: line1, onChange: (e) => setLine1(e.target.value) }),
9730            touched && !addressOk && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[12px] text-destructive", children: "Enter a street address." })
9731          ] }),
9732          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1.5", children: [
9733            /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "tc-line2", className: "text-xs", children: "Apartment, suite, etc. (optional)" }),
9734            /* @__PURE__ */ jsxRuntimeExports.jsx(Input, { id: "tc-line2", autoComplete: "off", value: line2, onChange: (e) => setLine2(e.target.value) })
9735          ] }),
9736          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-3", children: [
9737            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1.5", children: [
9738              /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "tc-city", className: "text-xs", children: form.city }),
9739              /* @__PURE__ */ jsxRuntimeExports.jsx(Input, { id: "tc-city", autoComplete: "off", value: city, onChange: (e) => setCity(e.target.value) })
9740            ] }),
9741            form.postal !== false && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1.5", children: [
9742              /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "tc-postal", className: "text-xs", children: form.postal }),
9743              /* @__PURE__ */ jsxRuntimeExports.jsx(Input, { id: "tc-postal", autoComplete: "off", value: postalCode, onChange: (e) => setPostalCode(e.target.value) })
9744            ] })
9745          ] }),
9746          form.state !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1.5", children: [
9747            /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "tc-state", className: "text-xs", children: form.state }),
9748            /* @__PURE__ */ jsxRuntimeExports.jsx(Input, { id: "tc-state", autoComplete: "off", value: stateRegion, onChange: (e) => setStateRegion(e.target.value) })
9749          ] }),
9750          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1.5", children: [
9751            /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "tc-country", className: "text-xs", children: "Country" }),
9752            /* @__PURE__ */ jsxRuntimeExports.jsx("select", { id: "tc-country", className: "h-9 rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", value: country, onChange: (e) => setCountry(e.target.value), children: countries.map((code) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: code, children: COUNTRY_NAMES[code] ?? code }, code)) }),
9753            /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[12px] text-muted-foreground", children: shippingCountries && shippingCountries.length > 0 ? "Buyers outside this list cannot check out." : "Your store delivers anywhere Stripe serves." })
9754          ] })
9755        ] }),
9756        collectsShippingAddress && !subscription && /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "flex flex-col gap-2", children: [
9757          /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-semibold", children: "Delivery method" }),
9758          shippingRates.length === 0 ? (
9759            /*
9760             * An empty rate list is the single most valuable thing this
9761             * screen can surface. Collecting a delivery address while
9762             * charging nothing for postage is the expensive mistake in
9763             * this feature — the merchant posts the order and eats the
9764             * cost — and it is invisible everywhere else until the first
9765             * real sale.
9766             */
9767            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-md border border-amber-200 bg-amber-50 px-3 py-2.5 text-[12.5px] leading-snug text-amber-900", children: [
9768              /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { className: "font-semibold", children: "Your store charges nothing for delivery." }),
9769              " ",
9770              "Buyers pay ",
9771              money(0, currency),
9772              " postage because no delivery rates are set. Ask the assistant to set them if you charge for delivery."
9773            ] })
9774          ) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1.5", children: [
9775            rateOptions.map((rate) => {
9776              const checked = (selectedRate == null ? void 0 : selectedRate.label) === rate.label;
9777              return /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: `flex cursor-pointer items-center justify-between rounded-md border px-3 py-2 text-[13px] ${checked ? "border-violet-400 bg-violet-50/60 ring-1 ring-violet-200" : "hover:bg-muted/50"}`, children: [
9778                /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-2.5", children: [
9779                  /* @__PURE__ */ jsxRuntimeExports.jsx("input", { type: "radio", name: "test-checkout-delivery", className: "accent-violet-600", checked, onChange: () => setShippingLabel(rate.label) }),
9780                  rate.label
9781                ] }),
9782                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "tabular-nums", children: rate.waived ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
9783                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "mr-1.5 line-through opacity-60", children: money(rate.listAmount, currency) }),
9784                  "Free"
9785                ] }) : money(rate.amount, currency) })
9786              ] }, rate.label);
9787            }),
9788            freeShippingOver !== null && !freeShippingApplies && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-[12px] text-muted-foreground", children: [
9789              "Cheapest option is free over",
9790              " ",
9791              money(freeShippingOver, currency),
9792              "."
9793            ] }),
9794            freeShippingApplies && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-[12px] text-muted-foreground", children: [
9795              "Free delivery applied — this basket is over",
9796              " ",
9797              money(freeShippingOver, currency),
9798              "."
9799            ] })
9800          ] })
9801        ] }),
9802        /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "flex flex-col gap-2", children: [
9803          /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-semibold", children: "Payment" }),
9804          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "overflow-hidden rounded-md border border-input", children: [
9805            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3 px-3 py-2.5", children: [
9806              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "grid h-6 w-9 shrink-0 place-items-center rounded bg-slate-800 text-[8px] font-bold tracking-wide text-white", children: "TEST" }),
9807              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 font-mono text-sm tracking-wide", children: "•••• •••• •••• 4242" }),
9808              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "rounded-full bg-violet-100 px-2 py-0.5 text-[10px] font-bold uppercase tracking-wide text-violet-700", children: "Simulated" })
9809            ] }),
9810            /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "border-t border-dashed border-input px-3 py-2 text-[12px] leading-snug text-muted-foreground", children: "Your buyers enter their own card on Stripe's secure page — never on your site." })
9811          ] })
9812        ] }),
9813        /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "flex flex-col gap-2", children: [
9814          /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-semibold", children: "What happens on the real checkout" }),
9815          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1.5 rounded-md border border-dashed px-3 py-2.5", children: [
9816            /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-[12.5px] leading-snug text-muted-foreground", children: [
9817              /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { className: "font-medium text-foreground", children: "Stripe hosts the real page" }),
9818              " ",
9819              "under your business name and branding, at checkout.stripe.com."
9820            ] }),
9821            /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[12.5px] leading-snug text-muted-foreground", children: stripeTaxEnabled ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
9822              /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { className: "font-medium text-foreground", children: "Stripe Tax is on." }),
9823              " ",
9824              taxBehavior === "inclusive" ? "Your prices include tax, and Stripe itemises it on the receipt." : "Stripe adds tax on its page once the buyer enters their address."
9825            ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
9826              /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { className: "font-medium text-foreground", children: "Tax is off for this store." }),
9827              " ",
9828              "Turn on Stripe Tax in your Stripe Dashboard and it applies here automatically."
9829            ] }) }),
9830            collectsShippingAddress && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-[12.5px] leading-snug text-muted-foreground", children: [
9831              /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { className: "font-medium text-foreground", children: shippingCountries && shippingCountries.length > 0 ? `You deliver to ${shippingCountries.length} ${shippingCountries.length === 1 ? "country" : "countries"}.` : "Buyers can order from anywhere Stripe serves." }),
9832              " ",
9833              shippingCountries && shippingCountries.length > 0 ? "Stripe refuses any other delivery address on its own page." : "You haven't limited delivery countries."
9834            ] })
9835          ] })
9836        ] })
9837      ] })
9838    ] }),
9839    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-end gap-2 border-t bg-muted/30 px-5 py-3", children: [
9840      /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { variant: "ghost", onClick: onCancel, disabled: submitting, children: "Cancel" }),
9841      /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { onClick: submit, disabled: !canSubmit, children: submitting ? "Creating…" : subscription ? "Create test subscription" : "Place test order" })
9842    ] })
9843  ] }) });
9844};
9845const VITE_ERROR_CAPS = {
9846  message: 1024,
9847  file: 1024,
9848  frame: 4 * 1024,
9849  stack: 8 * 1024,
9850  path: 512
9851};
9852function parseViteErrorMessage(data) {
9853  if (!data || typeof data !== "object") return null;
9854  const raw = data;
9855  if (raw.type === "vite-error-cleared") {
9856    return {
9857      type: "vite-error-cleared"
9858    };
9859  }
9860  if (raw.type !== "vite-error") return null;
9861  const r = raw;
9862  if (typeof r.message !== "string" || typeof r.file !== "string" || typeof r.frame !== "string" || typeof r.stack !== "string" || typeof r.path !== "string") {
9863    return null;
9864  }
9865  const enc = new TextEncoder();
9866  const cap = (s, max) => {
9867    const bytes = enc.encode(s);
9868    return bytes.length > max ? null : s;
9869  };
9870  const message = cap(r.message, VITE_ERROR_CAPS.message);
9871  const file = cap(r.file, VITE_ERROR_CAPS.file);
9872  const frame = cap(r.frame, VITE_ERROR_CAPS.frame);
9873  const stack = cap(r.stack, VITE_ERROR_CAPS.stack);
9874  const path = cap(r.path, VITE_ERROR_CAPS.path);
9875  if (message === null || file === null || frame === null || stack === null || path === null) {
9876    return null;
9877  }
9878  if (!message && !file && !frame) return null;
9879  return {
9880    type: "vite-error",
9881    message,
9882    file,
9883    frame,
9884    stack,
9885    path
9886  };
9887}
9888function fnv1a(str) {
9889  let hash = 2166136261;
9890  for (let i = 0; i < str.length; i++) {
9891    hash ^= str.charCodeAt(i);
9892    hash = Math.imul(hash, 16777619);
9893  }
9894  return (hash >>> 0).toString(16);
9895}
9896function viteErrorSignature(payload) {
9897  return fnv1a(`${payload.file}|${payload.message}`);
9898}
9899const DiscardEditsConfirmModal = ({
9900  open,
9901  dirtyPreview = "",
9902  onConfirm,
9903  onCancel
9904}) => {
9905  const truncated = dirtyPreview.length > 80 ? `${dirtyPreview.slice(0, 80)}…` : dirtyPreview;
9906  return /* @__PURE__ */ jsxRuntimeExports.jsx(AlertDialog, { open, onOpenChange: (next) => {
9907    if (!next) onCancel();
9908  }, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(AlertDialogContent, { className: "max-w-sm", children: [
9909    /* @__PURE__ */ jsxRuntimeExports.jsxs(AlertDialogHeader, { children: [
9910      /* @__PURE__ */ jsxRuntimeExports.jsx(AlertDialogTitle, { children: "Discard your edits?" }),
9911      /* @__PURE__ */ jsxRuntimeExports.jsx(AlertDialogDescription, { children: truncated ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
9912        "You'll lose your changes to",
9913        " ",
9914        /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-medium text-[#1B1A22]", children: [
9915          "“",
9916          truncated,
9917          "”"
9918        ] }),
9919        ". This can't be undone."
9920      ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: "You'll lose your unsaved changes. This can't be undone." }) })
9921    ] }),
9922    /* @__PURE__ */ jsxRuntimeExports.jsxs(AlertDialogFooter, { children: [
9923      /* @__PURE__ */ jsxRuntimeExports.jsx(AlertDialogCancel, { onClick: onCancel, children: "Keep editing" }),
9924      /* @__PURE__ */ jsxRuntimeExports.jsx(AlertDialogAction, { onClick: onConfirm, className: "bg-red-600 text-white hover:bg-red-700", children: "Discard" })
9925    ] })
9926  ] }) });
9927};
9928function byHomepageThenPath(a, b) {
9929  if (a.isHomepage !== b.isHomepage) return a.isHomepage ? -1 : 1;
9930  return a.path.localeCompare(b.path);
9931}
9932function filterPages(pages, query) {
9933  const normalized = query.trim().toLowerCase();
9934  if (normalized === "") {
9935    return [...pages].sort(byHomepageThenPath);
9936  }
9937  const matches = pages.filter((page) => page.path.toLowerCase().includes(normalized) || page.name.toLowerCase().includes(normalized));
9938  return matches.sort((a, b) => {
9939    const aExact = a.path.toLowerCase() === normalized;
9940    const bExact = b.path.toLowerCase() === normalized;
9941    if (aExact !== bExact) return aExact ? -1 : 1;
9942    return byHomepageThenPath(a, b);
9943  });
9944}
9945function nextActiveIndex(current, length, direction) {
9946  if (length <= 0) return null;
9947  let safeCurrent;
9948  if (current === null || current < 0 || current >= length) {
9949    safeCurrent = direction === "up" ? length : -1;
9950  } else {
9951    safeCurrent = current;
9952  }
9953  switch (direction) {
9954    case "down":
9955      return (safeCurrent + 1) % length;
9956    case "up":
9957      return (safeCurrent - 1 + length) % length;
9958    case "home":
9959      return 0;
9960    case "end":
9961      return length - 1;
9962  }
9963}
9964const LISTBOX_ID = "pages-typeahead-listbox";
9965const OPTION_ID_PREFIX = "pages-typeahead-option";
9966function formatPageLabel(page) {
9967  var _a;
9968  const raw = ((_a = page.name) == null ? void 0 : _a.trim()) || page.path.replace(/^\/+/, "") || (page.isHomepage ? "home" : "");
9969  if (!raw) return "";
9970  return raw.charAt(0).toUpperCase() + raw.slice(1);
9971}
9972const PagesTypeahead = reactExports.forwardRef(function PagesTypeahead2(props, ref) {
9973  const {
9974    pages,
9975    query,
9976    currentPath,
9977    anchorRef,
9978    onSelect,
9979    onClose,
9980    onPointerDownInside,
9981    websiteId,
9982    hasCustomDomain = false,
9983    domainName
9984  } = props;
9985  const posthog = usePostHog();
9986  const filtered = reactExports.useMemo(() => filterPages(pages, query), [pages, query]);
9987  const rowRefs = reactExports.useRef([]);
9988  const [active, setActive] = reactExports.useState(() => {
9989    if (filtered.length === 0) return {
9990      index: null,
9991      source: "init"
9992    };
9993    const match = filtered.findIndex((p) => p.path === currentPath);
9994    return {
9995      index: match >= 0 ? match : 0,
9996      source: "init"
9997    };
9998  });
9999  const hasInitializedRef = reactExports.useRef(false);
10000  reactExports.useEffect(() => {
10001    if (!hasInitializedRef.current) {
10002      hasInitializedRef.current = true;
10003      return;
10004    }
10005    setActive((prev) => {
10006      if (filtered.length === 0) return {
10007        index: null,
10008        source: "init"
10009      };
10010      if (prev.index !== null && prev.index < filtered.length) return prev;
10011      const match = filtered.findIndex((p) => p.path === currentPath);
10012      return {
10013        index: match >= 0 ? match : 0,
10014        source: "init"
10015      };
10016    });
10017  }, [filtered, currentPath]);
10018  reactExports.useEffect(() => {
10019    if (active.source !== "keyboard" || active.index === null) return;
10020    const el = rowRefs.current[active.index];
10021    el == null ? void 0 : el.scrollIntoView({
10022      block: "nearest",
10023      behavior: "smooth"
10024    });
10025  }, [active]);
10026  reactExports.useImperativeHandle(ref, () => ({
10027    moveActive: (direction) => {
10028      setActive((prev) => ({
10029        index: nextActiveIndex(prev.index, filtered.length, direction),
10030        source: "keyboard"
10031      }));
10032    },
10033    selectActive: () => {
10034      if (active.index === null) return null;
10035      const page = filtered[active.index];
10036      return page ? page.path : null;
10037    }
10038  }), [filtered, active.index]);
10039  const liveRegionMessage = filtered.length === 0 ? "No matching pages" : `${filtered.length} page${filtered.length === 1 ? "" : "s"} available`;
10040  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
10041    PopoverContent,
10042    {
10043      id: LISTBOX_ID,
10044      align: "start",
10045      side: "bottom",
10046      sideOffset: 8,
10047      style: {
10048        width: "var(--radix-popover-trigger-width)",
10049        // Round 5 — white body to match the URL bar in both states.
10050        background: "#FFFFFF",
10051        border: "1px solid rgba(27,26,34,0.06)",
10052        boxShadow: "0 1px 2px rgba(27,26,34,0.04), 0 16px 40px -12px rgba(27,26,34,0.16)",
10053        // Drives the scale direction. The panel scales out from its top
10054        // edge (the direction of the URL bar above) rather than from
10055        // center.
10056        transformOrigin: "top center"
10057      },
10058      className: cn$1(
10059        "flex flex-col p-0",
10060        "max-h-[min(360px,var(--radix-popover-content-available-height,360px))] overflow-hidden",
10061        // Round 5 — separate rounded card, 16px on all corners. [&]: bumps
10062        // specificity to beat shadcn PopoverContent's default `rounded-md`.
10063        "[&]:rounded-[16px]",
10064        // Emil Kowalski-style layered animation: scaleX + scaleY + translateY
10065        // + opacity. Smooth confident settle on open (cubic-bezier(0.32,0.72,0,1)),
10066        // snappier asymmetric exit (cubic-bezier(0.4,0,1,1)).
10067        "motion-safe:data-[state=open]:animate-[pages-typeahead-rise_280ms_cubic-bezier(0.32,0.72,0,1)]",
10068        "motion-safe:data-[state=closed]:animate-[pages-typeahead-fall_160ms_cubic-bezier(0.4,0,1,1)]"
10069      ),
10070      onOpenAutoFocus: (event) => event.preventDefault(),
10071      onPointerDownOutside: (event) => {
10072        var _a;
10073        if ((_a = anchorRef.current) == null ? void 0 : _a.contains(event.target)) {
10074          event.preventDefault();
10075        }
10076      },
10077      onInteractOutside: (event) => {
10078        var _a;
10079        const target = event.target;
10080        if (target && ((_a = anchorRef.current) == null ? void 0 : _a.contains(target))) {
10081          event.preventDefault();
10082        }
10083      },
10084      onEscapeKeyDown: () => onClose(),
10085      onPointerDownCapture: () => onPointerDownInside == null ? void 0 : onPointerDownInside(),
10086      children: [
10087        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { role: "status", "aria-live": "polite", className: "sr-only", children: liveRegionMessage }),
10088        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: cn$1("min-h-0 flex-1 overflow-y-auto p-1", "[mask-image:linear-gradient(to_bottom,black_calc(100%-24px),transparent)]", "[scrollbar-width:none] [&::-webkit-scrollbar]:hidden"), children: filtered.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-3 py-2 text-sm text-muted-foreground", "data-testid": "pages-typeahead-empty", children: query.trim() === "" ? "No pages yet" : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
10089          "No matching pages — Enter navigates to",
10090          " ",
10091          /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-medium text-[#1B1A22]", children: [
10092            "/",
10093            query.trim().replace(/^\/+/, "")
10094          ] })
10095        ] }) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { role: "listbox", "aria-label": "Site pages", className: "flex flex-col gap-0.5", children: filtered.map((page, index) => {
10096          const isActive = active.index === index;
10097          const isCurrent = page.path === currentPath;
10098          const Icon = page.isHomepage ? House : FileText;
10099          const optionId = `${OPTION_ID_PREFIX}-${page.id}`;
10100          return /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { ref: (el) => {
10101            rowRefs.current[index] = el;
10102          }, id: optionId, role: "option", "aria-selected": isActive, "aria-current": isCurrent ? "page" : void 0, className: cn$1(
10103            "relative flex cursor-pointer items-center gap-2.5 rounded-[8px] px-2.5 py-1.5 text-sm text-[#1B1A22]",
10104            "transition-colors duration-100 ease-out",
10105            // Hover (keyboard-active OR mouse-over) is a soft wash,
10106            // not a nested glass pill. Granola's hover is a brushed
10107            // full-width tint, no inset highlights, no inner light.
10108            isActive && "bg-[#1B1A22]/[0.035]"
10109          ), onMouseEnter: () => setActive({
10110            index,
10111            source: "hover"
10112          }), onMouseDown: (event) => {
10113            event.preventDefault();
10114            onSelect(page.path);
10115          }, children: [
10116            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { "aria-hidden": "true", className: cn$1("flex h-[22px] w-[22px] flex-shrink-0 items-center justify-center rounded-[8px]", "transition-colors duration-100 ease-out", isCurrent ? "bg-[#1B1A22] text-white" : "bg-[#1B1A22]/[0.06] text-[#1B1A22]/70"), children: /* @__PURE__ */ jsxRuntimeExports.jsx(Icon, { className: "h-3.5 w-3.5", "aria-hidden": "true" }) }),
10117            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn$1("flex-1 truncate text-[13px]", isCurrent ? "font-semibold" : "font-medium"), children: formatPageLabel(page) }),
10118            (isActive || isCurrent) && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { "aria-hidden": "true", className: "flex-shrink-0 truncate font-mono text-[11.5px] text-[#1B1A22]/40", children: [
10119              domainName || "yourdomain.com",
10120              page.path
10121            ] }),
10122            isCurrent && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { "aria-hidden": "true", className: "flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full bg-[#1B1A22] text-white", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "h-3 w-3", strokeWidth: 3 }) })
10123          ] }, page.id);
10124        }) }) }),
10125        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-shrink-0 items-center justify-between gap-2 border-t border-[#1B1A22]/[0.06] px-1 py-1.5 pr-3", children: [
10126          !hasCustomDomain && websiteId ? /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { type: "button", onMouseDown: (event) => {
10127            event.preventDefault();
10128            posthog == null ? void 0 : posthog.capture("Set Up Domain Clicked", {
10129              websiteId,
10130              source: "pages_typeahead",
10131              websiteType: "react"
10132            });
10133            navigate(namedRoutes.reactWebsiteChatSettingsTab({
10134              id: websiteId,
10135              tab: "domain"
10136            }));
10137          }, className: cn$1(
10138            // Pill shape (matches URL-bar globe button). Padding stays
10139            // horizontally aligned with the list rows so the globe sits
10140            // directly under the page icons above; vertical padding is
10141            // tight (py-1) for a slim pill.
10142            "group inline-flex items-center gap-2.5 rounded-full px-2.5 py-1 text-xs font-medium",
10143            "text-[#1B1A22]/40 hover:text-green-500 hover:bg-[#d6e9db]",
10144            "transition-colors duration-150 ease-out"
10145          ), children: [
10146            /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "relative flex h-[22px] w-[22px] flex-none items-center justify-center", children: [
10147              /* @__PURE__ */ jsxRuntimeExports.jsx(Globe, { className: "h-3.5 w-3.5 [filter:drop-shadow(0_0.5px_0_rgba(255,255,255,0.7))]", strokeWidth: 2.25 }),
10148              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { "aria-hidden": "true", className: cn$1("pointer-events-none absolute right-[2px] top-[2px] h-1.5 w-1.5 rounded-full", "bg-gradient-to-b from-[#FCD34D] to-[#EAB308]", "shadow-[inset_0_0.5px_0_rgba(255,255,255,0.55),0_0.5px_1px_rgba(146,64,14,0.18),0_0_0_2px_#FFFFFF]", "transition-opacity duration-150 ease-out", "group-hover:opacity-0 group-focus-visible:opacity-0") })
10149            ] }),
10150            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "whitespace-nowrap leading-5", children: "Set up your domain" })
10151          ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", {}),
10152          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { "aria-hidden": "true", className: "flex items-center gap-2 font-mono text-[10.5px] text-[#1B1A22]/45", children: [
10153            /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1", children: [
10154              /* @__PURE__ */ jsxRuntimeExports.jsx("kbd", { className: "inline-flex h-4 items-center justify-center rounded-[4px] bg-[#1B1A22]/[0.06] px-1 text-[#1B1A22]/60", children: "↵" }),
10155              "Go"
10156            ] }),
10157            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[#1B1A22]/25", children: "·" }),
10158            /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1", children: [
10159              /* @__PURE__ */ jsxRuntimeExports.jsx("kbd", { className: "inline-flex h-4 items-center justify-center rounded-[4px] bg-[#1B1A22]/[0.06] px-1 text-[#1B1A22]/60", children: "esc" }),
10160              "Cancel"
10161            ] })
10162          ] })
10163        ] })
10164      ]
10165    }
10166  );
10167});
10168const VIEWPORT_ORDER = ["desktop", "tablet", "mobile"];
10169const VIEWPORT_TILE_STEP = 28;
10170function viewportIndicatorOffset(size2) {
10171  const index = VIEWPORT_ORDER.indexOf(size2);
10172  return (index < 0 ? 0 : index) * VIEWPORT_TILE_STEP;
10173}
10174function bootFields(boot) {
10175  if (!boot) return {};
10176  return {
10177    bootPath: boot.path,
10178    bootDurationMs: boot.durationMs,
10179    bootPhases: boot.phases,
10180    bootViteReady: boot.viteReady,
10181    bootCreatedAt: boot.createdAt
10182  };
10183}
10184function newBootId() {
10185  return Math.random().toString(36).slice(2, 10);
10186}
10187const stripInternalParams = (path) => {
10188  if (!path.includes("?")) return path;
10189  try {
10190    const url = new URL(path, "http://dummy");
10191    url.searchParams.delete("_r");
10192    const search = url.searchParams.toString();
10193    return url.pathname + (search ? `?${search}` : "") + url.hash;
10194  } catch {
10195    return path.replace(/[?&]_r=[^&]*/, "").replace(/\?$/, "");
10196  }
10197};
10198const buildPreviewUrl = (baseUrl, path = "/") => {
10199  const normalizedBase = baseUrl.replace(/\/$/, "");
10200  const normalizedPath = path.startsWith("/") ? path : `/${path}`;
10201  return `${normalizedBase}${normalizedPath}`;
10202};
10203const CREATE_TEST_ORDER_MUTATION = gql`
10204  mutation CreateTestOrderFromPreview(
10205    $websiteId: String!
10206    $productId: String
10207    $variantId: String
10208    $quantity: Int
10209    $amount: Int
10210    $items: [TestOrderItemInput!]
10211    $metadata: JSON
10212    $shippingAddress: TestShippingAddressInput
10213    $shippingOption: String
10214  ) {
10215    createTestOrder(
10216      websiteId: $websiteId
10217      productId: $productId
10218      variantId: $variantId
10219      quantity: $quantity
10220      amount: $amount
10221      items: $items
10222      metadata: $metadata
10223      shippingAddress: $shippingAddress
10224      shippingOption: $shippingOption
10225    ) {
10226      orderId
10227      sessionId
10228    }
10229  }
10230`;
10231const CREATE_TEST_SUBSCRIPTION_MUTATION = gql`
10232  mutation CreateTestSubscriptionFromPreview(
10233    $websiteId: String!
10234    $productId: String!
10235    $variantId: String
10236    $planId: String
10237    $metadata: JSON
10238    $shippingAddress: TestShippingAddressInput
10239  ) {
10240    createTestSubscription(
10241      websiteId: $websiteId
10242      productId: $productId
10243      variantId: $variantId
10244      planId: $planId
10245      metadata: $metadata
10246      shippingAddress: $shippingAddress
10247    ) {
10248      orderId
10249      sessionId
10250      subscriptionId
10251    }
10252  }
10253`;
10254const TEST_CHECKOUT_CONTEXT_QUERY = gql`
10255  query TestCheckoutContextForPreview(
10256    $websiteId: String!
10257    $productId: String
10258    $variantId: String
10259    $quantity: Int
10260    $amount: Int
10261    $items: [TestOrderItemInput!]
10262    $planId: String
10263  ) {
10264    testCheckoutContext(
10265      websiteId: $websiteId
10266      productId: $productId
10267      variantId: $variantId
10268      quantity: $quantity
10269      amount: $amount
10270      items: $items
10271      planId: $planId
10272    ) {
10273      subscription {
10274        planId
10275        title
10276        interval
10277        intervalCount
10278        amount
10279      }
10280      collectsShippingAddress
10281      shippingCountries
10282      currency
10283      subtotal
10284      freeShippingOver
10285      stripeTaxEnabled
10286      taxBehavior
10287      lines {
10288        name
10289        variantTitle
10290        quantity
10291        unitAmount
10292        imageUrl
10293        shippable
10294      }
10295      shippingRates {
10296        label
10297        amount
10298      }
10299    }
10300  }
10301`;
10302const TEST_ORDER_PAYMENTS_STATE_QUERY = gql`
10303  query ReactPreviewPanelTestOrderPaymentsState($websiteId: String!) {
10304    websiteCommerceIntent(websiteId: $websiteId) {
10305      paymentsActive
10306    }
10307  }
10308`;
10309const MINT_PREVIEW_SESSION_MUTATION = gql`
10310  mutation MintAifeaturesPreviewSessionFromPreview(
10311    $websiteId: String!
10312    $email: String!
10313  ) {
10314    mintAifeaturesPreviewSession(websiteId: $websiteId, email: $email) {
10315      token
10316      expiresAt
10317    }
10318  }
10319`;
10320const parseTestOrderItems = (raw) => {
10321  if (!Array.isArray(raw) || raw.length < 1 || raw.length > 20) return null;
10322  const items = [];
10323  for (const entry of raw) {
10324    if (typeof entry !== "object" || entry === null) return null;
10325    const {
10326      productId,
10327      variantId,
10328      quantity
10329    } = entry;
10330    if (typeof productId !== "string") return null;
10331    if (variantId !== void 0 && typeof variantId !== "string") return null;
10332    if (quantity !== void 0 && (typeof quantity !== "number" || !Number.isInteger(quantity) || quantity < 1)) return null;
10333    items.push({
10334      productId,
10335      ...typeof variantId === "string" ? {
10336        variantId
10337      } : {},
10338      ...typeof quantity === "number" ? {
10339        quantity
10340      } : {}
10341    });
10342  }
10343  return items;
10344};
10345const parseTestOrderMetadata = (raw) => {
10346  if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return null;
10347  const out = {};
10348  for (const [key, value] of Object.entries(raw)) {
10349    if (typeof value !== "string") return null;
10350    out[key] = value;
10351  }
10352  return Object.keys(out).length > 0 ? out : null;
10353};
10354const GLASS_PILL = "bg-[linear-gradient(180deg,rgba(247,247,250,0.97)_0%,rgba(241,241,245,0.94)_100%)] shadow-[inset_0_1px_0_rgba(255,255,255,0.95),inset_0_2px_5px_-1px_rgba(255,255,255,0.55),inset_0_-2px_5px_-3px_rgba(27,26,34,0.08),inset_0_0_0_0.5px_rgba(255,255,255,0.45),inset_0_0_0_1px_rgba(27,26,34,0.07),0_0_4px_rgba(27,26,34,0.04),0_0_13px_-2px_rgba(27,26,34,0.045),0_0_20px_-5px_rgba(27,26,34,0.05)]";
10355const TOOLBAR_CAPSULE = `flex items-center gap-0 rounded-full p-0.5 ${GLASS_PILL}`;
10356const TOOLBAR_BTN = "flex h-7 w-7 items-center justify-center rounded-full bg-transparent text-[#1B1A22]";
10357const TOOLBAR_BTN_STYLE = {
10358  transition: "background-color 120ms ease-out, box-shadow 120ms ease-out, transform 90ms ease-out"
10359};
10360const TOOLBAR_BTN_HAPTIC = "disabled:cursor-not-allowed disabled:opacity-50 enabled:hover:bg-[rgba(27,26,34,0.055)] enabled:hover:shadow-[inset_0_0.5px_0_rgba(255,255,255,0.7),inset_0_0_0_0.5px_rgba(27,26,34,0.04)] enabled:active:scale-[0.94] enabled:active:bg-[rgba(27,26,34,0.10)]";
10361const composeAgentEditPrompt = (edits) => {
10362  const lines = edits.map((e, i) => {
10363    const where = e.tag ? `in the <${e.tag}>` : "on this page";
10364    const loc = e.sourceLoc ? ` (source: ${e.sourceLoc})` : "";
10365    return `${i + 1}. ${where}, change "${e.oldText.trim()}" to "${e.newText.trim()}"${loc}`;
10366  });
10367  return "Please make these exact text changes on the current page and nothing else:\n" + lines.join("\n");
10368};
10369const ReactPreviewPanel = ({
10370  previewUrl,
10371  containerStatus: initialContainerStatus,
10372  containerError: initialContainerError,
10373  pickModeActive = false,
10374  onPicked,
10375  onPickModeExit,
10376  onIframeReload,
10377  onSelectorReadyChange,
10378  onPickerAvailabilityChange,
10379  onCurrentPathChange,
10380  onViteError,
10381  onViteErrorCleared,
10382  editTextModeActive = false,
10383  onToggleEditTextMode,
10384  onEditTextModeExit,
10385  onApplyWithAI,
10386  isAgentResponding = false,
10387  onEditBusyChange,
10388  pages = [],
10389  websiteId,
10390  hasCustomDomain = false,
10391  domainName,
10392  refreshSignal
10393}) => {
10394  const {
10395    getToken,
10396    currentUser
10397  } = useAuth();
10398  const posthog = usePostHog();
10399  const iframeRef = reactExports.useRef(null);
10400  const containerRef = reactExports.useRef(null);
10401  const [isLoading, setIsLoading] = reactExports.useState(true);
10402  const [hasError, setHasError] = reactExports.useState(false);
10403  const [viewportSize, setViewportSize] = reactExports.useState("desktop");
10404  const [currentPath, setCurrentPath] = reactExports.useState("/");
10405  const [urlInputValue, setUrlInputValue] = reactExports.useState("/");
10406  const [historyStack, setHistoryStack] = reactExports.useState(["/"]);
10407  const [historyIndex, setHistoryIndex] = reactExports.useState(0);
10408  const [isTypeaheadOpen, setIsTypeaheadOpen] = reactExports.useState(false);
10409  const [isDomainCtaHovered, setIsDomainCtaHovered] = reactExports.useState(false);
10410  const [isDesktop, setIsDesktop] = reactExports.useState(() => {
10411    if (typeof window === "undefined" || !window.matchMedia) return true;
10412    return window.matchMedia("(min-width: 1024px)").matches;
10413  });
10414  const formRef = reactExports.useRef(null);
10415  const inputRef = reactExports.useRef(null);
10416  const typeaheadRef = reactExports.useRef(null);
10417  const blurTimerRef = reactExports.useRef(null);
10418  const [iframePages, setIframePages] = reactExports.useState([]);
10419  const [containerSize, setContainerSize] = reactExports.useState({
10420    width: 0,
10421    height: 0
10422  });
10423  const [editPersistableCount, setEditPersistableCount] = reactExports.useState(0);
10424  const [editNeedsAgentCount, setEditNeedsAgentCount] = reactExports.useState(0);
10425  const [isSavingEdits, setIsSavingEdits] = reactExports.useState(false);
10426  const [isApplyingWithAI, setIsApplyingWithAI] = reactExports.useState(false);
10427  const aiTurnStartedRef = reactExports.useRef(false);
10428  const pendingFlushResolveRef = reactExports.useRef(null);
10429  const [pendingExitConfirm, setPendingExitConfirm] = reactExports.useState(false);
10430  const [bannerRendered, setBannerRendered] = reactExports.useState(false);
10431  const [bannerExiting, setBannerExiting] = reactExports.useState(false);
10432  const [isNavigating, setIsNavigating] = reactExports.useState(false);
10433  const ignoreNextNavMessage = reactExports.useRef(false);
10434  const [liveContainerStatus, setLiveContainerStatus] = reactExports.useState(null);
10435  const [isContainerStarting, setIsContainerStarting] = reactExports.useState(false);
10436  const loadingStartTimeRef = reactExports.useRef(null);
10437  const [wasEverReady, setWasEverReady] = reactExports.useState(false);
10438  const isContainerStartingRef = reactExports.useRef(false);
10439  const wasEverReadyRef = reactExports.useRef(false);
10440  const containerTimingRef = reactExports.useRef({
10441    bootId: newBootId(),
10442    pageLoadTime: Date.now(),
10443    iframeLoadStartTime: null,
10444    firstStatusCheckTime: null,
10445    containerReadyTime: null,
10446    iframeLoadCompleteTime: null
10447  });
10448  const websiteIdRef = reactExports.useRef(websiteId);
10449  websiteIdRef.current = websiteId;
10450  const lastStatusCaptureRef = reactExports.useRef(null);
10451  const shouldCaptureStatus = reactExports.useCallback((outcome, hasBoot) => {
10452    const bootId = containerTimingRef.current.bootId;
10453    const last = lastStatusCaptureRef.current;
10454    const sameLoad = (last == null ? void 0 : last.bootId) === bootId;
10455    const capture = !sameLoad || last.outcome !== outcome || hasBoot && !last.hadB
10455oot;
10456    if (capture) {
10457      lastStatusCaptureRef.current = {
10458        bootId,
10459        outcome,
10460        hadBoot: hasBoot || sameLoad && last.hadBoot
10461      };
10462    }
10463    return capture;
10464  }, []);
10465  const oneShotStepsRef = reactExports.useRef({
10466    bootId: "",
10467    steps: /* @__PURE__ */ new Set()
10468  });
10469  const logContainerTiming = reactExports.useCallback(
10470    (event, extra, opts) => {
10471      const now = Date.now();
10472      const timing = containerTimingRef.current;
10473      const sincePageLoad = now - timing.pageLoadTime;
10474      const sinceIframeStart = timing.iframeLoadStartTime ? now - timing.iframeLoadStartTime : null;
10475      const payload = {
10476        timestamp: new Date(now).toISOString(),
10477        sincePageLoadMs: sincePageLoad,
10478        sinceIframeStartMs: sinceIframeStart,
10479        ...extra
10480      };
10481      console.log(`[ContainerTiming] ${event}`, payload);
10482      if ((opts == null ? void 0 : opts.capture) === false) return;
10483      try {
10484        posthog == null ? void 0 : posthog.capture("preview_boot", {
10485          step: event,
10486          bootId: timing.bootId,
10487          websiteId: websiteIdRef.current,
10488          sinceNavigationMs: Math.round(performance.now()),
10489          ...payload
10490        });
10491      } catch {
10492      }
10493    },
10494    [posthog]
10495    // posthog is the provider singleton; everything else is a ref
10496  );
10497  const logOncePerLoad = reactExports.useCallback((step, extra) => {
10498    const bootId = containerTimingRef.current.bootId;
10499    if (oneShotStepsRef.current.bootId !== bootId) {
10500      oneShotStepsRef.current = {
10501        bootId,
10502        steps: /* @__PURE__ */ new Set()
10503      };
10504    }
10505    if (oneShotStepsRef.current.steps.has(step)) return;
10506    oneShotStepsRef.current.steps.add(step);
10507    logContainerTiming(step, extra);
10508  }, [logContainerTiming]);
10509  const containerStatus = liveContainerStatus || initialContainerStatus;
10510  const containerError = initialContainerError;
10511  const checkContainerStatus = reactExports.useCallback(async () => {
10512    if (!previewUrl) return null;
10513    const checkStartTime = Date.now();
10514    const requestBootId = containerTimingRef.current.bootId;
10515    if (!containerTimingRef.current.firstStatusCheckTime) {
10516      containerTimingRef.current.firstStatusCheckTime = checkStartTime;
10517      logContainerTiming("first_status_check_start");
10518    }
10519    try {
10520      const token = await getToken();
10521      const statusUrl = `${previewUrl.replace(/\/$/, "")}/__container/status`;
10522      const headers = {};
10523      if (token) {
10524        headers["Authorization"] = `Bearer ${token}`;
10525      }
10526      const response = await fetch(statusUrl, {
10527        headers
10528      });
10529      if (!response.ok) {
10530        console.error("[ReactPreviewPanel] Status check failed:", response.status);
10531        logContainerTiming("status_check_failed", {
10532          statusCode: response.status,
10533          durationMs: Date.now() - checkStartTime
10534        }, {
10535          capture: shouldCaptureStatus(`failed_${response.status}`, false)
10536        });
10537        return null;
10538      }
10539      const data = await response.json();
10540      const capture = shouldCaptureStatus(`ok_${data.status}`, !!data.boot);
10541      logContainerTiming("status_check_complete", {
10542        status: data.status,
10543        durationMs: Date.now() - checkStartTime,
10544        ...bootFields(data.boot)
10545      }, {
10546        capture
10547      });
10548      if (["running", "healthy", "warm"].includes(data.status) && containerTimingRef.current.bootId === requestBootId) {
10549        logOncePerLoad("container_first_ready", {
10550          status: data.status,
10551          ...bootFields(data.boot)
10552        });
10553      }
10554      return data;
10555    } catch (error) {
10556      console.error("[ReactPreviewPanel] Status check error:", error);
10557      logContainerTiming("status_check_error", {
10558        error: error instanceof Error ? error.message : String(error),
10559        durationMs: Date.now() - checkStartTime
10560      }, {
10561        capture: shouldCaptureStatus("error", false)
10562      });
10563      return null;
10564    }
10565  }, [previewUrl, getToken, logContainerTiming, shouldCaptureStatus, logOncePerLoad]);
10566  reactExports.useEffect(() => {
10567    if (!isLoading || !previewUrl) {
10568      loadingStartTimeRef.current = null;
10569      return;
10570    }
10571    if (!loadingStartTimeRef.current) {
10572      loadingStartTimeRef.current = Date.now();
10573    }
10574    let pollInterval = null;
10575    let isCancelled = false;
10576    const pollStatus = async () => {
10577      const loadingDuration = Date.now() - (loadingStartTimeRef.current || 0);
10578      if (loadingDuration < 3e3) return;
10579      const status = await checkContainerStatus();
10580      if (isCancelled) return;
10581      if (status) {
10582        setLiveContainerStatus(status.status);
10583        if (["running", "healthy", "warm"].includes(status.status)) {
10584          if (!wasEverReadyRef.current) {
10585            containerTimingRef.current.containerReadyTime = Date.now();
10586            wasEverReadyRef.current = true;
10587            setWasEverReady(true);
10588          }
10589        }
10590        const isStarting = !["running", "healthy", "warm"].includes(status.status);
10591        const wasStarting = isContainerStartingRef.current;
10592        isContainerStartingRef.current = isStarting;
10593        setIsContainerStarting(isStarting);
10594        if (["running", "healthy", "warm"].includes(status.status) && wasStarting) {
10595          logContainerTiming("container_became_ready_reloading_iframe", {
10596            status: status.status
10597          });
10598          isCancelled = true;
10599          if (pollInterval) clearInterval(pollInterval);
10600          if (iframeRef.current) {
10601            setTimeout(() => {
10602              if (iframeRef.current) {
10603                const currentSrc = iframeRef.current.src;
10604                const url = new URL(currentSrc);
10605                url.searchParams.set("_r", Date.now().toString());
10606                iframeRef.current.src = url.toString();
10607                logContainerTiming("iframe_reload_triggered");
10608              }
10609            }, 500);
10610          }
10611        }
10612      }
10613    };
10614    const initialTimeout = setTimeout(pollStatus, 3e3);
10615    pollInterval = setInterval(pollStatus, 2e3);
10616    return () => {
10617      isCancelled = true;
10618      clearTimeout(initialTimeout);
10619      if (pollInterval) clearInterval(pollInterval);
10620    };
10621  }, [isLoading, previewUrl, checkContainerStatus, logContainerTiming]);
10622  const viewportConfig = {
10623    mobile: {
10624      width: 393,
10625      height: 852
10626    },
10627    // iPhone 15/16 effective resolution
10628    tablet: {
10629      width: 768,
10630      height: 1024
10631    },
10632    desktop: {
10633      width: 1512,
10634      height: 982
10635    }
10636    // MacBook Pro 14" effective resolution
10637  };
10638  const config = viewportConfig[viewportSize];
10639  reactExports.useEffect(() => {
10640    if (editTextModeActive) return;
10641    setPendingExitConfirm(false);
10642  }, [editTextModeActive]);
10643  reactExports.useEffect(() => {
10644    if (editTextModeActive) {
10645      setBannerRendered(true);
10646      setBannerExiting(false);
10647      return;
10648    }
10649    if (!bannerRendered) return;
10650    setBannerExiting(true);
10651    const t = window.setTimeout(() => {
10652      setBannerRendered(false);
10653      setBannerExiting(false);
10654    }, 320);
10655    return () => window.clearTimeout(t);
10656  }, [editTextModeActive, bannerRendered]);
10657  reactExports.useEffect(() => {
10658    const container = containerRef.current;
10659    if (!container) return;
10660    const resizeObserver = new ResizeObserver((entries) => {
10661      const entry = entries[0];
10662      if (entry) {
10663        setContainerSize({
10664          width: entry.contentRect.width,
10665          height: entry.contentRect.height
10666        });
10667      }
10668    });
10669    resizeObserver.observe(container);
10670    return () => resizeObserver.disconnect();
10671  }, []);
10672  reactExports.useEffect(() => {
10673    if (typeof window === "undefined" || !window.matchMedia) return;
10674    const mql = window.matchMedia("(min-width: 1024px)");
10675    const onChange = (event) => setIsDesktop(event.matches);
10676    setIsDesktop(mql.matches);
10677    if (mql.addEventListener) {
10678      mql.addEventListener("change", onChange);
10679      return () => mql.removeEventListener("change", onChange);
10680    }
10681    mql.addListener(onChange);
10682    return () => mql.removeListener(onChange);
10683  }, []);
10684  reactExports.useEffect(() => {
10685    const handleRoutesMessage = (event) => {
10686      var _a;
10687      if (((_a = event.data) == null ? void 0 : _a.type) !== "routes-manifest") return;
10688      const routes2 = event.data.routes;
10689      if (!Array.isArray(routes2)) return;
10690      const sanitized = routes2.filter((r) => !!r && typeof r === "object" && typeof r.id === "string" && typeof r.path === "string" && typeof r.name === "string" && typeof r.isHomepage === "boolean").map((r) => ({
10691        id: r.id,
10692        name: r.name,
10693        path: r.path,
10694        isHomepage: r.isHomepage
10695      }));
10696      setIframePages(sanitized);
10697    };
10698    window.addEventListener("message", handleRoutesMessage);
10699    const requestManifest = () => {
10700      const iframe = iframeRef.current;
10701      if (!(iframe == null ? void 0 : iframe.contentWindow)) return;
10702      try {
10703        iframe.contentWindow.postMessage({
10704          type: "request-routes-manifest"
10705        }, "*");
10706      } catch {
10707      }
10708    };
10709    const t1 = window.setTimeout(requestManifest, 500);
10710    const t2 = window.setTimeout(requestManifest, 1500);
10711    const t3 = window.setTimeout(requestManifest, 3500);
10712    return () => {
10713      window.removeEventListener("message", handleRoutesMessage);
10714      window.clearTimeout(t1);
10715      window.clearTimeout(t2);
10716      window.clearTimeout(t3);
10717    };
10718  }, [previewUrl]);
10719  const effectivePages = iframePages.length > 0 ? iframePages : pages;
10720  const isPreviewLoading = isLoading || isNavigating || effectivePages.length === 0;
10721  const getScaleAndDimensions = () => {
10722    const targetWidth = typeof config.width === "number" ? config.width : 0;
10723    const targetHeight = typeof config.height === "number" ? config.height : 0;
10724    if (containerSize.width > 0 && containerSize.height > 0) {
10725      if (viewportSize === "desktop") {
10726        const scale3 = containerSize.width / targetWidth;
10727        const scaledHeight = containerSize.height / scale3;
10728        return {
10729          width: targetWidth,
10730          // 1280px - content renders at desktop width
10731          height: scaledHeight,
10732          // calculated to fill container when scaled
10733          scale: scale3,
10734          needsScaling: true
10735          // always scale for desktop to ensure consistent rendering
10736        };
10737      }
10738      const padding = 32;
10739      const availableWidth = containerSize.width - padding;
10740      const scale2 = Math.min(availableWidth / targetWidth, 1);
10741      return {
10742        width: targetWidth,
10743        height: targetHeight,
10744        scale: scale2,
10745        needsScaling: scale2 < 1
10746      };
10747    }
10748    return {
10749      width: targetWidth,
10750      height: targetHeight,
10751      scale: 1,
10752      needsScaling: false
10753    };
10754  };
10755  const {
10756    width: iframeWidth,
10757    height: iframeHeight,
10758    scale,
10759    needsScaling
10760  } = getScaleAndDimensions();
10761  reactExports.useEffect(() => {
10762    setUrlInputValue(currentPath);
10763  }, [currentPath]);
10764  reactExports.useEffect(() => {
10765    if (previewUrl && !containerTimingRef.current.iframeLoadStartTime) {
10766      containerTimingRef.current.iframeLoadStartTime = Date.now();
10767      checkContainerStatus().then((statusResponse) => {
10768        if (statusResponse) {
10769          setLiveContainerStatus(statusResponse.status);
10770        }
10771        logContainerTiming("iframe_initial_load_start", {
10772          previewUrl: previewUrl.replace(/token=[^&]+/, "token=***"),
10773          initialStatus: (statusResponse == null ? void 0 : statusResponse.status) ?? "fetch_failed"
10774        });
10775      });
10776    }
10777  }, [previewUrl, logContainerTiming, checkContainerStatus]);
10778  reactExports.useEffect(() => {
10779    const handleMessage = (event) => {
10780      var _a, _b;
10781      if (!previewUrl) return;
10782      if (((_a = event.data) == null ? void 0 : _a.type) !== "navigation" || !((_b = event.data) == null ? void 0 : _b.path)) return;
10783      const newPath = stripInternalParams(event.data.path);
10784      const navState = event.data.state;
10785      const isInFlight = navState !== void 0 && navState !== "idle";
10786      setIsNavigating(isInFlight);
10787      if (isInFlight) {
10788        setUrlInputValue(newPath);
10789        return;
10790      }
10791      if (ignoreNextNavMessage.current) {
10792        ignoreNextNavMessage.current = false;
10793        setCurrentPath(newPath);
10794        return;
10795      }
10796      if (newPath !== currentPath) {
10797        setCurrentPath(newPath);
10798        setHistoryStack((prev) => [...prev.slice(0, historyIndex + 1), newPath]);
10799        setHistoryIndex((prev) => prev + 1);
10800      }
10801    };
10802    window.addEventListener("message", handleMessage);
10803    return () => window.removeEventListener("message", handleMessage);
10804  }, [previewUrl, currentPath, historyIndex]);
10805  const testOrderInFlight = reactExports.useRef(false);
10806  const [createTestOrderMutation] = useMutation$1(CREATE_TEST_ORDER_MUTATION);
10807  const [createTestSubscriptionMutation] = useMutation$1(CREATE_TEST_SUBSCRIPTION_MUTATION);
10808  const [loadTestCheckoutContext] = useLazyQuery(TEST_CHECKOUT_CONTEXT_QUERY, {
10809    fetchPolicy: "network-only"
10810  });
10811  const [loadPaymentsState] = useLazyQuery(TEST_ORDER_PAYMENTS_STATE_QUERY, {
10812    // Payments can go live mid-session (the merchant finishes Stripe in
10813    // another tab) — a cached "not active" would pitch an upgrade to someone
10814    // who just did it.
10815    fetchPolicy: "network-only"
10816  });
10817  const [testCheckout, setTestCheckout] = reactExports.useState(null);
10818  const [testCheckoutSubmitting, setTestCheckoutSubmitting] = reactExports.useState(false);
10819  const testCheckoutReplyRef = reactExports.useRef(null);
10820  const closeTestCheckout = reactExports.useCallback(() => {
10821    setTestCheckout(null);
10822    setTestCheckoutSubmitting(false);
10823    testCheckoutReplyRef.current = null;
10824    testOrderInFlight.current = false;
10825  }, []);
10826  const cancelTestCheckout = reactExports.useCallback(() => {
10827    var _a;
10828    (_a = testCheckoutReplyRef.current) == null ? void 0 : _a.call(testCheckoutReplyRef, "failed", "Test purchase cancelled");
10829    closeTestCheckout();
10830  }, [closeTestCheckout]);
10831  const submitTestCheckout = reactExports.useCallback(async (submission) => {
10832    var _a, _b, _c, _d;
10833    if (!testCheckout) return;
10834    setTestCheckoutSubmitting(true);
10835    const paymentsStatePromise = websiteId ? loadPaymentsState({
10836      variables: {
10837        websiteId
10838      }
10839    }).then(({
10840      data: stateData
10841    }) => {
10842      var _a2;
10843      return ((_a2 = stateData == null ? void 0 : stateData.websiteCommerceIntent) == null ? void 0 : _a2.paymentsActive) !== false;
10844    }).catch(() => true) : Promise.resolve(true);
10845    try {
10846      let sessionId;
10847      if (testCheckout.planId) {
10848        const {
10849          data: result
10850        } = await createTestSubscriptionMutation({
10851          variables: {
10852            websiteId: testCheckout.variables.websiteId,
10853            productId: testCheckout.variables.productId,
10854            variantId: testCheckout.variables.variantId ?? null,
10855            planId: testCheckout.planId,
10856            metadata: testCheckout.metadata,
10857            shippingAddress: submission.shippingAddress
10858          }
10859        });
10860        sessionId = (_a = result == null ? void 0 : result.createTestSubscription) == null ? void 0 : _a.sessionId;
10861      } else {
10862        const {
10863          data: result
10864        } = await createTestOrderMutation({
10865          variables: {
10866            ...testCheckout.variables,
10867            metadata: testCheckout.metadata,
10868            shippingAddress: submission.shippingAddress,
10869            shippingOption: submission.shippingOption
10870          }
10871        });
10872        sessionId = (_b = result == null ? void 0 : result.createTestOrder) == null ? void 0 : _b.sessionId;
10873      }
10874      if (sessionId && iframeRef.current && previewUrl) {
10875        const paymentsActive = await paymentsStatePromise;
10876        const testNoun = testCheckout.planId ? "signup" : "purchase";
10877        if (paymentsActive) {
10878          _t.success(`Test ${testNoun} created — no payment was collected. Test orders only happen here in the editor; on your published site this is a real charge.`, {
10879            duration: 8e3
10880          });
10881        } else {
10882          _t.success(`Test ${testNoun} created — no payment was collected. Test orders only happen here in the editor — on your published site the button reads "Payments not set up" until you upgrade to Pro and connect Stripe.`, {
10883            duration: 8e3
10884          });
10885        }
10886        iframeRef.current.src = buildPreviewUrl(previewUrl, `/order/confirmation?session_id=${encodeURIComponent(sessionId)}`);
10887        closeTestCheckout();
10888      } else {
10889        (_c = testCheckoutReplyRef.current) == null ? void 0 : _c.call(testCheckoutReplyRef, "failed", "Could not create the test purchase");
10890        _t.error("Could not create the test purchase");
10891        closeTestCheckout();
10892      }
10893    } catch (err) {
10894      const message = err instanceof Error ? err.message : "Could not create the test purchase";
10895      (_d = testCheckoutReplyRef.current) == null ? void 0 : _d.call(testCheckoutReplyRef, "failed", message);
10896      _t.error(message);
10897      closeTestCheckout();
10898    }
10899  }, [testCheckout, createTestOrderMutation, createTestSubscriptionMutation, previewUrl, closeTestCheckout, websiteId, loadPaymentsState]);
10900  reactExports.useEffect(() => {
10901    const handleTestCheckout = async (event) => {
10902      var _a, _b;
10903      if (!iframeRef.current || event.source !== iframeRef.current.contentWindow) {
10904        return;
10905      }
10906      if (!previewUrl) return;
10907      try {
10908        if (event.origin !== new URL(previewUrl).origin) return;
10909      } catch {
10910        return;
10911      }
10912      const data = event.data;
10913      if ((data == null ? void 0 : data.type) !== "aifeatures:test-checkout") return;
10914      if (!websiteId) return;
10915      const cartItems = "items" in data ? parseTestOrderItems(data.items) : null;
10916      if ("items" in data && cartItems === null) return;
10917      if (cartItems === null && typeof data.productId !== "string") return;
10918      const previewOrigin = new URL(previewUrl).origin;
10919      const requestId = typeof data.requestId === "string" ? data.requestId : void 0;
10920      const reply = (status, error) => {
10921        var _a2;
10922        try {
10923          ;
10924          (_a2 = event.source) == null ? void 0 : _a2.postMessage({
10925            type: "aifeatures:test-checkout-ack",
10926            status,
10927            error,
10928            ...requestId !== void 0 ? {
10929              requestId
10930            } : {}
10931          }, previewOrigin);
10932        } catch {
10933        }
10934      };
10935      if (testOrderInFlight.current) {
10936        reply("accepted");
10937        return;
10938      }
10939      testOrderInFlight.current = true;
10940      reply("accepted");
10941      testCheckoutReplyRef.current = reply;
10942      const planId = !cartItems && typeof data.planId === "string" ? data.planId : null;
10943      const variables = cartItems ? {
10944        websiteId,
10945        items: cartItems
10946      } : {
10947        websiteId,
10948        productId: data.productId,
10949        variantId: typeof data.variantId === "string" ? data.variantId : null,
10950        quantity: typeof data.quantity === "number" ? data.quantity : null,
10951        amount: typeof data.amount === "number" ? data.amount : null
10952      };
10953      let ctx = {
10954        collectsShippingAddress: false,
10955        shippingCountries: null,
10956        currency: "usd",
10957        lines: [],
10958        subtotal: 0,
10959        shippingRates: [],
10960        freeShippingOver: null,
10961        stripeTaxEnabled: false,
10962        taxBehavior: null,
10963        subscription: null
10964      };
10965      try {
10966        const {
10967          data: ctxData
10968        } = await loadTestCheckoutContext({
10969          variables: cartItems ? {
10970            websiteId,
10971            items: cartItems
10972          } : {
10973            websiteId,
10974            productId: data.productId,
10975            variantId: typeof data.variantId === "string" ? data.variantId : null,
10976            quantity: typeof data.quantity === "number" ? data.quantity : null,
10977            amount: typeof data.amount === "number" ? data.amount : null,
10978            planId
10979          }
10980        });
10981        if (planId && ((_b = (_a = ctxData == null ? void 0 : ctxData.testCheckoutContext) == null ? void 0 : _a.subscription) == null ? void 0 : _b.planId) !== planId) {
10982          throw new Error("Could not load this subscription plan. Please try again.");
10983        }
10984        if (ctxData == null ? void 0 : ctxData.testCheckoutContext) ctx = ctxData.testCheckoutContext;
10985      } catch (err) {
10986        if (planId) {
10987          const message = err instanceof Error ? err.message : "Could not load this subscription plan. Please try again.";
10988          reply("failed", message);
10989          _t.error(message);
10990          closeTestCheckout();
10991          return;
10992        }
10993      }
10994      setTestCheckout({
10995        variables,
10996        metadata: parseTestOrderMetadata(data.metadata),
10997        context: ctx,
10998        planId
10999      });
11000    };
11001    window.addEventListener("message", handleTestCheckout);
11002    return () => window.removeEventListener("message", handleTestCheckout);
11003  }, [websiteId, previewUrl, loadTestCheckoutContext, closeTestCheckout]);
11004  const [mintPreviewSessionMutation] = useMutation$1(MINT_PREVIEW_SESSION_MUTATION);
11005  reactExports.useEffect(() => {
11006    const handlePreviewSession = async (event) => {
11007      var _a;
11008      if (!iframeRef.current || event.source !== iframeRef.current.contentWindow) {
11009        return;
11010      }
11011      if (!previewUrl) return;
11012      try {
11013        if (event.origin !== new URL(previewUrl).origin) return;
11014      } catch {
11015        return;
11016      }
11017      const data = event.data;
11018      if ((data == null ? void 0 : data.type) !== "aifeatures:preview-session") return;
11019      if (!websiteId) return;
11020      if (typeof data.requestId !== "string" || !data.requestId) return;
11021      if (typeof data.email !== "string" || !data.email) return;
11022      const previewOrigin = new URL(previewUrl).origin;
11023      const requestId = data.requestId;
11024      const reply = (payload) => {
11025        var _a2;
11026        try {
11027          ;
11028          (_a2 = event.source) == null ? void 0 : _a2.postMessage({
11029            type: "aifeatures:preview-session-ack",
11030            requestId,
11031            ...payload
11032          }, previewOrigin);
11033        } catch {
11034        }
11035      };
11036      try {
11037        const {
11038          data: result
11039        } = await mintPreviewSessionMutation({
11040          variables: {
11041            websiteId,
11042            email: data.email
11043          }
11044        });
11045        const token = (_a = result == null ? void 0 : result.mintAifeaturesPreviewSession) == null ? void 0 : _a.token;
11046        if (typeof token === "string" && token) {
11047          reply({
11048            token
11049          });
11050        } else {
11051          reply({
11052            error: "The preview sign-in could not be created."
11053          });
11054        }
11055      } catch (err) {
11056        reply({
11057          error: err instanceof Error && err.message ? err.message : "The preview sign-in could not be created."
11058        });
11059      }
11060    };
11061    window.addEventListener("message", handlePreviewSession);
11062    return () => window.removeEventListener("message", handlePreviewSession);
11063  }, [websiteId, previewUrl, mintPreviewSessionMutation]);
11064  const [isSelectorReady, setIsSelectorReady] = reactExports.useState(false);
11065  const onPickedRef = reactExports.useRef(onPicked);
11066  const onPickModeExitRef = reactExports.useRef(onPickModeExit);
11067  const onEditTextModeExitRef = reactExports.useRef(onEditTextModeExit);
11068  const onApplyWithAIRef = reactExports.useRef(onApplyWithAI);
11069  const onIframeReloadRef = reactExports.useRef(onIframeReload);
11070  const onSelectorReadyChangeRef = reactExports.useRef(onSelectorReadyChange);
11071  const onPickerAvailabilityChangeRef = reactExports.useRef(onPickerAvailabilityChange);
11072  const onCurrentPathChangeRef = reactExports.useRef(onCurrentPathChange);
11073  const pickModeActiveRef = reactExports.useRef(pickModeActive);
11074  reactExports.useEffect(() => {
11075    onPickedRef.current = onPicked;
11076  }, [onPicked]);
11077  reactExports.useEffect(() => {
11078    onPickModeExitRef.current = onPickModeExit;
11079  }, [onPickModeExit]);
11080  reactExports.useEffect(() => {
11081    onEditTextModeExitRef.current = onEditTextModeExit;
11082  }, [onEditTextModeExit]);
11083  reactExports.useEffect(() => {
11084    onApplyWithAIRef.current = onApplyWithAI;
11085  }, [onApplyWithAI]);
11086  reactExports.useEffect(() => {
11087    onIframeReloadRef.current = onIframeReload;
11088  }, [onIframeReload]);
11089  reactExports.useEffect(() => {
11090    onSelectorReadyChangeRef.current = onSelectorReadyChange;
11091  }, [onSelectorReadyChange]);
11092  reactExports.useEffect(() => {
11093    onPickerAvailabilityChangeRef.current = onPickerAvailabilityChange;
11094  }, [onPickerAvailabilityChange]);
11095  reactExports.useEffect(() => {
11096    onCurrentPathChangeRef.current = onCurrentPathChange;
11097  }, [onCurrentPathChange]);
11098  reactExports.useEffect(() => {
11099    pickModeActiveRef.current = pickModeActive;
11100  }, [pickModeActive]);
11101  reactExports.useEffect(() => {
11102    var _a;
11103    (_a = onCurrentPathChangeRef.current) == null ? void 0 : _a.call(onCurrentPathChangeRef, currentPath);
11104  }, [currentPath]);
11105  const iframeOrigin = React.useMemo(() => {
11106    if (!previewUrl) return null;
11107    try {
11108      return new URL(previewUrl).origin;
11109    } catch {
11110      return null;
11111    }
11112  }, [previewUrl]);
11113  const isPickerOriginAllowed = reactExports.useCallback((origin) => {
11114    let url;
11115    try {
11116      url = new URL(origin);
11117    } catch {
11118      return false;
11119    }
11120    const host = url.hostname.toLowerCase();
11121    if (host === "landingsite.dev" || host.endsWith(".landingsite.dev")) {
11122      return true;
11123    }
11124    if (host === "agcy.dev" || host.endsWith(".agcy.dev")) {
11125      return true;
11126    }
11127    if ((host === "localhost" || host === "127.0.0.1") && url.port === "8792") {
11128      return true;
11129    }
11130    return false;
11131  }, []);
11132  const parsePickerMessage$1 = reactExports.useCallback((data) => parsePickerMessage(data), []);
11133  reactExports.useEffect(() => {
11134    var _a;
11135    (_a = onSelectorReadyChangeRef.current) == null ? void 0 : _a.call(onSelectorReadyChangeRef, isSelectorReady);
11136  }, [isSelectorReady]);
11137  reactExports.useEffect(() => {
11138    const handlePickerMessage = (event) => {
11139      var _a, _b, _c, _d, _e, _f;
11140      if (!isPickerOriginAllowed(event.origin)) return;
11141      if (!iframeRef.current || event.source !== iframeRef.current.contentWindow) {
11142        return;
11143      }
11144      const msg = parsePickerMessage$1(event.data);
11145      if (!msg) {
11146        const t = (_a = event.data) == null ? void 0 : _a.type;
11147        if (typeof t === "string" && ["selector-probe", "enter-select", "cancel-select", "selector-ready", "enter-select-ack", "enter-edit-text-ack", "selected", "cancel-select-request", "edit-queue-count", "text-edit-batch"].includes(t)) {
11148          console.warn("[ReactPreviewPanel] Rejected picker message: payload validation failed", {
11149            type: t
11150          });
11151        }
11152        return;
11153      }
11154      switch (msg.type) {
11155        case "selector-ready": {
11156          setIsSelectorReady(true);
11157          if (selectorProbeTimerRef.current !== null) {
11158            clearTimeout(selectorProbeTimerRef.current);
11159            selectorProbeTimerRef.current = null;
11160          }
11161          break;
11162        }
11163        case "enter-select-ack": {
11164          if (enterSelectAckTimerRef.current !== null) {
11165            clearTimeout(enterSelectAckTimerRef.current);
11166            enterSelectAckTimerRef.current = null;
11167          }
11168          break;
11169        }
11170        case "enter-edit-text-ack": {
11171          if (enterEditTextAckTimerRef.current !== null) {
11172            clearTimeout(enterEditTextAckTimerRef.current);
11173            enterEditTextAckTimerRef.current = null;
11174          }
11175          break;
11176        }
11177        case "selected": {
11178          if (!pickModeActiveRef.current) {
11179            (_c = (_b = iframeRef.current) == null ? void 0 : _b.contentWindow) == null ? void 0 : _c.postMessage({
11180              type: "cancel-select"
11181            }, event.origin);
11182            return;
11183          }
11184          if (enterSelectAckTimerRef.current !== null) {
11185            clearTimeout(enterSelectAckTimerRef.current);
11186            enterSelectAckTimerRef.current = null;
11187          }
11188          const {
11189            outerHTML,
11190            tag,
11191            textPreview,
11192            path,
11193            sourceLoc
11194          } = msg;
11195          (_d = onPickedRef.current) == null ? void 0 : _d.call(onPickedRef, {
11196            outerHTML,
11197            tag,
11198            textPreview,
11199            path,
11200            sourceLoc
11201          });
11202          break;
11203        }
11204        case "cancel-select-request": {
11205          if (enterSelectAckTimerRef.current !== null) {
11206            clearTimeout(enterSelectAckTimerRef.current);
11207            enterSelectAckTimerRef.current = null;
11208          }
11209          (_e = onPickModeExitRef.current) == null ? void 0 : _e.call(onPickModeExitRef);
11210          break;
11211        }
11212        case "edit-queue-count": {
11213          setEditPersistableCount(msg.persistable);
11214          setEditNeedsAgentCount(Math.max(0, msg.count - msg.persistable));
11215          break;
11216        }
11217        case "text-edit-batch": {
11218          (_f = pendingFlushResolveRef.current) == null ? void 0 : _f.call(pendingFlushResolveRef, {
11219            edits: msg.edits,
11220            agentEdits: msg.agentEdits
11221          });
11222          pendingFlushResolveRef.current = null;
11223          break;
11224        }
11225      }
11226    };
11227    window.addEventListener("message", handlePickerMessage);
11228    return () => window.removeEventListener("message", handlePickerMessage);
11229  }, [isPickerOriginAllowed, parsePickerMessage$1]);
11230  const onViteErrorRef = reactExports.useRef(onViteError);
11231  const onViteErrorClearedRef = reactExports.useRef(onViteErrorCleared);
11232  reactExports.useEffect(() => {
11233    onViteErrorRef.current = onViteError;
11234  }, [onViteError]);
11235  reactExports.useEffect(() => {
11236    onViteErrorClearedRef.current = onViteErrorCleared;
11237  }, [onViteErrorCleared]);
11238  reactExports.useEffect(() => {
11239    const handleViteErrorMessage = (event) => {
11240      var _a, _b, _c;
11241      if (!isPickerOriginAllowed(event.origin)) return;
11242      if (!iframeRef.current || event.source !== iframeRef.current.contentWindow) {
11243        return;
11244      }
11245      const msg = parseViteErrorMessage(event.data);
11246      if (!msg) {
11247        if (event.data && typeof event.data === "object" && (event.data.type === "vite-error" || event.data.type === "vite-error-cleared")) {
11248          console.log("[ls:preview] vite-error msg dropped by parser", {
11249            origin: event.origin,
11250            data: event.data
11251          });
11252        }
11253        return;
11254      }
11255      if (msg.type === "vite-error") {
11256        const {
11257          type: _t2,
11258          ...payload
11259        } = msg;
11260        livePreviewErrorRef.current = true;
11261        setHasPreviewError(true);
11262        console.log("[ls:preview] vite-error received", {
11263          origin: event.origin,
11264          message: (_a = payload.message) == null ? void 0 : _a.slice(0, 80),
11265          file: payload.file
11266        });
11267        (_b = onViteErrorRef.current) == null ? void 0 : _b.call(onViteErrorRef, payload);
11268      } else {
11269        livePreviewErrorRef.current = false;
11270        setHasPreviewError(false);
11271        console.log("[ls:preview] vite-error-cleared received", {
11272          origin: event.origin
11273        });
11274        (_c = onViteErrorClearedRef.current) == null ? void 0 : _c.call(onViteErrorClearedRef);
11275      }
11276    };
11277    window.addEventListener("message", handleViteErrorMessage);
11278    return () => window.removeEventListener("message", handleViteErrorMessage);
11279  }, [isPickerOriginAllowed]);
11280  reactExports.useEffect(() => {
11281    const handlePreviewDocMessage = (event) => {
11282      if (!iframeRef.current || event.source !== iframeRef.current.contentWindow) {
11283        return;
11284      }
11285      const data = event.data;
11286      if (!data || typeof data !== "object" || data.type !== "ls-preview-doc") {
11287        return;
11288      }
11289      logOncePerLoad(data.healthy === true ? "iframe_content_rendered" : "iframe_error_rendered");
11290    };
11291    const PERF_FIELDS = ["ttfbMs", "domContentLoadedMs", "loadMs", "fcpMs", "resourceCount", "scriptCount", "styleCount", "transferKB", "lastResourceEndMs", "slowestResourceMs"];
11292    const handlePreviewPerfMessage = (event) => {
11293      if (!iframeRef.current || event.source !== iframeRef.current.contentWindow) {
11294        return;
11295      }
11296      const data = event.data;
11297      if (!data || typeof data !== "object" || data.type !== "ls-preview-perf") {
11298        return;
11299      }
11300      const props = {};
11301      for (const field of PERF_FIELDS) {
11302        const value = data[field];
11303        if (typeof value === "number" && Number.isFinite(value)) {
11304          props[field] = value;
11305        }
11306      }
11307      logOncePerLoad("iframe_page_timing", props);
11308    };
11309    window.addEventListener("message", handlePreviewDocMessage);
11310    window.addEventListener("message", handlePreviewPerfMessage);
11311    return () => {
11312      window.removeEventListener("message", handlePreviewDocMessage);
11313      window.removeEventListener("message", handlePreviewPerfMessage);
11314    };
11315  }, [logOncePerLoad]);
11316  const lastStartupErrorRef = reactExports.useRef(void 0);
11317  const hasStartupErrorRef = reactExports.useRef(false);
11318  const livePreviewErrorRef = reactExports.useRef(false);
11319  const [hasPreviewError, setHasPreviewError] = reactExports.useState(false);
11320  const currentPathRef = reactExports.useRef(currentPath);
11321  reactExports.useEffect(() => {
11322    currentPathRef.current = currentPath;
11323  }, [currentPath]);
11324  reactExports.useEffect(() => {
11325    if (!previewUrl) return;
11326    let cancelled = false;
11327    const tick = async () => {
11328      var _a, _b;
11329      if (typeof document !== "undefined" && document.visibilityState === "hidden") {
11330        return;
11331      }
11332      const status = await checkContainerStatus();
11333      if (cancelled || !status) return;
11334      const next = (status.startupError ?? "").trim() || null;
11335      const prev = lastStartupErrorRef.current;
11336      if (next === prev) return;
11337      lastStartupErrorRef.current = next;
11338      hasStartupErrorRef.current = next !== null;
11339      if (next !== null) {
11340        const frame = next.slice(0, 4 * 1024);
11341        setHasPreviewError(true);
11342        (_a = onViteErrorRef.current) == null ? void 0 : _a.call(onViteErrorRef, {
11343          message: "Vite preview server failed to start",
11344          file: "",
11345          frame,
11346          stack: "",
11347          path: currentPathRef.current
11348        });
11349      } else {
11350        if (typeof prev === "string" || !livePreviewErrorRef.current) {
11351          setHasPreviewError(false);
11352          (_b = onViteErrorClearedRef.current) == null ? void 0 : _b.call(onViteErrorClearedRef);
11353        }
11354        if (typeof prev === "string" && iframeRef.current) {
11355          const recoverUrl = new URL(buildPreviewUrl(previewUrl, currentPathRef.current));
11356          recoverUrl.searchParams.set("_r", Date.now().toString());
11357          iframeRef.current.src = recoverUrl.toString();
11358        }
11359      }
11360    };
11361    const initialTimeout = setTimeout(tick, 4e3);
11362    const interval = setInterval(tick, 15e3);
11363    const onVisible = () => {
11364      if (document.visibilityState === "visible") void tick();
11365    };
11366    document.addEventListener("visibilitychange", onVisible);
11367    return () => {
11368      cancelled = true;
11369      clearTimeout(initialTimeout);
11370      clearInterval(interval);
11371      document.removeEventListener("visibilitychange", onVisible);
11372    };
11373  }, [previewUrl, checkContainerStatus]);
11374  const selectorProbeTimerRef = reactExports.useRef(null);
11375  const enterSelectAckTimerRef = reactExports.useRef(null);
11376  const enterEditTextAckTimerRef = reactExports.useRef(null);
11377  reactExports.useEffect(() => {
11378    var _a;
11379    const targetWindow = (_a = iframeRef.current) == null ? void 0 : _a.contentWindow;
11380    if (!targetWindow || !iframeOrigin) return;
11381    if (pickModeActive) {
11382      if (!isSelectorReady) {
11383        return;
11384      }
11385      targetWindow.postMessage({
11386        type: "enter-select"
11387      }, iframeOrigin);
11388      if (enterSelectAckTimerRef.current !== null) {
11389        clearTimeout(enterSelectAckTimerRef.current);
11390      }
11391      enterSelectAckTimerRef.current = setTimeout(() => {
11392        var _a2;
11393        enterSelectAckTimerRef.current = null;
11394        (_a2 = onPickModeExitRef.current) == null ? void 0 : _a2.call(onPickModeExitRef);
11395        _t("Preview isn't ready yet");
11396      }, 500);
11397    } else {
11398      targetWindow.postMessage({
11399        type: "cancel-select"
11400      }, iframeOrigin);
11401      if (enterSelectAckTimerRef.current !== null) {
11402        clearTimeout(enterSelectAckTimerRef.current);
11403        enterSelectAckTimerRef.current = null;
11404      }
11405    }
11406    return () => {
11407    };
11408  }, [pickModeActive, isSelectorReady, iframeOrigin]);
11409  reactExports.useEffect(() => {
11410    var _a;
11411    const targetWindow = (_a = iframeRef.current) == null ? void 0 : _a.contentWindow;
11412    if (!targetWindow || !iframeOrigin) return;
11413    if (editTextModeActive) {
11414      if (!isSelectorReady) return;
11415      targetWindow.postMessage({
11416        type: "enter-edit-text"
11417      }, iframeOrigin);
11418      if (enterEditTextAckTimerRef.current !== null) {
11419        clearTimeout(enterEditTextAckTimerRef.current);
11420      }
11421      enterEditTextAckTimerRef.current = setTimeout(() => {
11422        var _a2;
11423        enterEditTextAckTimerRef.current = null;
11424        (_a2 = onEditTextModeExitRef.current) == null ? void 0 : _a2.call(onEditTextModeExitRef);
11425        _t("Preview isn't ready yet");
11426      }, 500);
11427    } else {
11428      targetWindow.postMessage({
11429        type: "exit-edit-text"
11430      }, iframeOrigin);
11431      if (enterEditTextAckTimerRef.current !== null) {
11432        clearTimeout(enterEditTextAckTimerRef.current);
11433        enterEditTextAckTimerRef.current = null;
11434      }
11435      setEditPersistableCount(0);
11436      setEditNeedsAgentCount(0);
11437    }
11438  }, [editTextModeActive, isSelectorReady, iframeOrigin]);
11439  reactExports.useEffect(() => {
11440    if (!isApplyingWithAI) {
11441      aiTurnStartedRef.current = false;
11442      return;
11443    }
11444    if (isAgentResponding) {
11445      aiTurnStartedRef.current = true;
11446    } else if (aiTurnStartedRef.current) {
11447      setIsApplyingWithAI(false);
11448      return;
11449    }
11450    const safety = setTimeout(() => setIsApplyingWithAI(false), 12e4);
11451    return () => clearTimeout(safety);
11452  }, [isApplyingWithAI, isAgentResponding]);
11453  reactExports.useEffect(() => {
11454    onEditBusyChange == null ? void 0 : onEditBusyChange(isSavingEdits || isApplyingWithAI);
11455  }, [isSavingEdits, isApplyingWithAI, onEditBusyChange]);
11456  const persistEditBatch = reactExports.useCallback(async (edits) => {
11457    if (!previewUrl) throw new Error("No preview URL");
11458    const token = await getToken();
11459    const url = `${previewUrl.replace(/\/$/, "")}/__agent/edit-batch`;
11460    const res = await fetch(url, {
11461      method: "POST",
11462      headers: {
11463        "Content-Type": "application/json",
11464        ...token ? {
11465          Authorization: `Bearer ${token}`
11466        } : {}
11467      },
11468      body: JSON.stringify({
11469        edits
11470      })
11471    });
11472    if (!res.ok) {
11473      throw new Error(`edit-batch failed: ${res.status}`);
11474    }
11475    return res.json().catch(() => ({}));
11476  }, [previewUrl, getToken]);
11477  const requestEditFlush = reactExports.useCallback(() => {
11478    const empty = {
11479      edits: [],
11480      agentEdits: []
11481    };
11482    return new Promise((resolve) => {
11483      var _a;
11484      const target = (_a = iframeRef.current) == null ? void 0 : _a.contentWindow;
11485      if (!target || !iframeOrigin) return resolve(empty);
11486      const timer = setTimeout(() => {
11487        if (pendingFlushResolveRef.current) {
11488          pendingFlushResolveRef.current = null;
11489          resolve(empty);
11490        }
11491      }, 3e3);
11492      pendingFlushResolveRef.current = (batch) => {
11493        clearTimeout(timer);
11494        resolve(batch);
11495      };
11496      target.postMessage({
11497        type: "flush-edits"
11498      }, iframeOrigin);
11499    });
11500  }, [iframeOrigin]);
11501  const handleSaveEdits = reactExports.useCallback(async () => {
11502    var _a, _b;
11503    if (isSavingEdits) return;
11504    setIsSavingEdits(true);
11505    try {
11506      const {
11507        edits,
11508        agentEdits
11509      } = await requestEditFlush();
11510      let appliedCount = 0;
11511      let skippedEdits = [];
11512      if (edits.length > 0) {
11513        const result = await persistEditBatch(edits);
11514        appliedCount = typeof (result == null ? void 0 : result.applied) === "
11514number" ? result.applied : edits.length;
11515        const skips = Array.isArray(result == null ? void 0 : result.skipped) ? result.skipped : [];
11516        const skippedLocs = new Set(skips.map((s) => s == null ? void 0 : s.sourceLoc).filter(Boolean));
11517        skippedEdits = edits.filter((e) => skippedLocs.has(e.sourceLoc));
11518        if (skips.length > 0) {
11519          const byLoc = new Map(edits.map((e) => [e.sourceLoc, e]));
11520          for (const s of skips) {
11521            const e = (s == null ? void 0 : s.sourceLoc) ? byLoc.get(s.sourceLoc) : void 0;
11522            console.warn(`[inline-edit] punted to AI — reason=${(s == null ? void 0 : s.reason) ?? "unknown"} loc=${(s == null ? void 0 : s.sourceLoc) ?? "?"} old=${JSON.stringify(((e == null ? void 0 : e.oldText) ?? "").slice(0, 60))} new=${JSON.stringify(((e == null ? void 0 : e.newText) ?? "").slice(0, 60))}`);
11523          }
11524        }
11525      }
11526      if (agentEdits.length > 0) {
11527        console.warn(`[inline-edit] ${agentEdits.length} edit(s) routed to AI by the iframe (structural change or no resolvable source location) — see the preview-frame console for per-edit detail.`);
11528      }
11529      (_a = onEditTextModeExitRef.current) == null ? void 0 : _a.call(onEditTextModeExitRef);
11530      const aiEdits = [...agentEdits, ...skippedEdits];
11531      posthog == null ? void 0 : posthog.capture("inline_edit_saved", {
11532        direct_applied: appliedCount,
11533        ai_routed: aiEdits.length
11534      });
11535      if (aiEdits.length > 0 && onApplyWithAIRef.current) {
11536        const target = (_b = iframeRef.current) == null ? void 0 : _b.contentWindow;
11537        if (target && iframeOrigin) {
11538          target.postMessage({
11539            type: "discard-edits"
11540          }, iframeOrigin);
11541        }
11542        setIsApplyingWithAI(true);
11543        onApplyWithAIRef.current(composeAgentEditPrompt(aiEdits));
11544        _t((appliedCount > 0 ? `Saved ${appliedCount} change${appliedCount > 1 ? "s" : ""}. ` : "") + `Applying ${aiEdits.length} change${aiEdits.length > 1 ? "s" : ""} with AI…`, {
11545          duration: 6e3
11546        });
11547      } else if (aiEdits.length > 0) {
11548        _t(`${aiEdits.length} edit${aiEdits.length > 1 ? "s" : ""} couldn't be applied automatically.`, {
11549          duration: 6e3
11550        });
11551      } else {
11552        _t.success(appliedCount > 0 ? `Saved ${appliedCount} change${appliedCount > 1 ? "s" : ""}` : "No changes to save");
11553      }
11554    } catch {
11555      _t.error("Couldn't save your edits — please try again.");
11556    } finally {
11557      setIsSavingEdits(false);
11558    }
11559  }, [isSavingEdits, requestEditFlush, persistEditBatch, iframeOrigin, posthog]);
11560  const handleCancelEdits = reactExports.useCallback(() => {
11561    var _a, _b;
11562    if (isSavingEdits) return;
11563    posthog == null ? void 0 : posthog.capture("inline_edit_cancelled");
11564    const target = (_a = iframeRef.current) == null ? void 0 : _a.contentWindow;
11565    if (target && iframeOrigin) {
11566      target.postMessage({
11567        type: "discard-edits"
11568      }, iframeOrigin);
11569    }
11570    (_b = onEditTextModeExitRef.current) == null ? void 0 : _b.call(onEditTextModeExitRef);
11571  }, [isSavingEdits, iframeOrigin, posthog]);
11572  const handleDiscardConfirm = reactExports.useCallback(() => {
11573    var _a, _b;
11574    setPendingExitConfirm(false);
11575    const target = (_a = iframeRef.current) == null ? void 0 : _a.contentWindow;
11576    if (target && iframeOrigin) {
11577      target.postMessage({
11578        type: "discard-edits"
11579      }, iframeOrigin);
11580    }
11581    (_b = onEditTextModeExitRef.current) == null ? void 0 : _b.call(onEditTextModeExitRef);
11582  }, [iframeOrigin]);
11583  const handleDiscardCancel = reactExports.useCallback(() => {
11584    setPendingExitConfirm(false);
11585  }, []);
11586  const handleEditTextToggle = reactExports.useCallback(() => {
11587    posthog == null ? void 0 : posthog.capture("inline_edit_button_clicked", {
11588      inline_edit_active: !editTextModeActive,
11589      websiteId
11590    });
11591    if (!editTextModeActive) {
11592      onToggleEditTextMode == null ? void 0 : onToggleEditTextMode();
11593      return;
11594    }
11595    if (editPersistableCount + editNeedsAgentCount > 0) {
11596      setPendingExitConfirm(true);
11597      return;
11598    }
11599    onToggleEditTextMode == null ? void 0 : onToggleEditTextMode();
11600  }, [editTextModeActive, onToggleEditTextMode, posthog, editPersistableCount, editNeedsAgentCount, websiteId]);
11601  const editSaving = isSavingEdits || isApplyingWithAI;
11602  const editTotalCount = editPersistableCount + editNeedsAgentCount;
11603  const editSaveLabel = editPersistableCount === 0 && editNeedsAgentCount > 0 ? "Apply with AI" : "Save";
11604  reactExports.useEffect(() => {
11605    var _a;
11606    let hoverPointer = true;
11607    if (typeof window !== "undefined" && typeof window.matchMedia === "function") {
11608      hoverPointer = window.matchMedia("(hover: hover) and (pointer: fine)").matches;
11609    }
11610    const result = pickerAllowedOrigin({
11611      previewUrl,
11612      hoverPointer,
11613      // Dev/staging preview base domain — passed so the helper can allow
11614      // hosts under e.g. `thoop.dev` without hardcoding dev domains.
11615      previewBaseDomain: void 0
11616    });
11617    (_a = onPickerAvailabilityChangeRef.current) == null ? void 0 : _a.call(onPickerAvailabilityChangeRef, result.allowed);
11618  }, [previewUrl]);
11619  reactExports.useEffect(() => {
11620    return () => {
11621      var _a;
11622      if (selectorProbeTimerRef.current !== null) {
11623        clearTimeout(selectorProbeTimerRef.current);
11624        selectorProbeTimerRef.current = null;
11625      }
11626      if (enterSelectAckTimerRef.current !== null) {
11627        clearTimeout(enterSelectAckTimerRef.current);
11628        enterSelectAckTimerRef.current = null;
11629      }
11630      if (enterEditTextAckTimerRef.current !== null) {
11631        clearTimeout(enterEditTextAckTimerRef.current);
11632        enterEditTextAckTimerRef.current = null;
11633      }
11634      (_a = onPickModeExitRef.current) == null ? void 0 : _a.call(onPickModeExitRef);
11635    };
11636  }, []);
11637  reactExports.useEffect(() => {
11638    const handleFlush = () => {
11639      var _a, _b;
11640      (_b = (_a = iframeRef.current) == null ? void 0 : _a.contentWindow) == null ? void 0 : _b.postMessage({
11641        type: "flush-console-logs"
11642      }, "*");
11643    };
11644    window.addEventListener("flush-browser-logs", handleFlush);
11645    return () => window.removeEventListener("flush-browser-logs", handleFlush);
11646  }, []);
11647  const handleIframeLoad = () => {
11648    var _a, _b, _c;
11649    containerTimingRef.current.iframeLoadCompleteTime = Date.now();
11650    logContainerTiming("iframe_load_complete", {
11651      totalLoadTimeMs: containerTimingRef.current.iframeLoadStartTime ? Date.now() - containerTimingRef.current.iframeLoadStartTime : null
11652    });
11653    setIsLoading(false);
11654    setHasError(false);
11655    setIsSelectorReady(false);
11656    (_a = onIframeReloadRef.current) == null ? void 0 : _a.call(onIframeReloadRef);
11657    const willClear = !hasStartupErrorRef.current && !livePreviewErrorRef.current;
11658    console.log("[ls:preview] iframe-load", {
11659      hasStartupErrorRef: hasStartupErrorRef.current,
11660      livePreviewErrorRef: livePreviewErrorRef.current,
11661      willClearViteError: willClear
11662    });
11663    if (willClear) {
11664      setHasPreviewError(false);
11665      (_b = onViteErrorClearedRef.current) == null ? void 0 : _b.call(onViteErrorClearedRef);
11666    }
11667    if (selectorProbeTimerRef.current !== null) {
11668      clearTimeout(selectorProbeTimerRef.current);
11669      selectorProbeTimerRef.current = null;
11670    }
11671    const targetWindow = (_c = iframeRef.current) == null ? void 0 : _c.contentWindow;
11672    if (targetWindow && iframeOrigin) {
11673      targetWindow.postMessage({
11674        type: "selector-probe"
11675      }, iframeOrigin);
11676      selectorProbeTimerRef.current = setTimeout(() => {
11677        selectorProbeTimerRef.current = null;
11678      }, 5e3);
11679    }
11680  };
11681  const handleIframeError = () => {
11682    logContainerTiming("iframe_load_error");
11683    setIsLoading(false);
11684    setHasError(true);
11685  };
11686  const handleRefresh = () => {
11687    if (iframeRef.current && previewUrl) {
11688      logContainerTiming("manual_refresh_triggered");
11689      containerTimingRef.current.iframeLoadStartTime = Date.now();
11690      setIsLoading(true);
11691      setHasError(false);
11692      const refreshUrl = buildPreviewUrl(previewUrl, currentPath);
11693      const url = new URL(refreshUrl);
11694      url.searchParams.set("_r", Date.now().toString());
11695      iframeRef.current.src = url.toString();
11696    }
11697  };
11698  const lastRefreshSignalRef = reactExports.useRef(refreshSignal);
11699  reactExports.useEffect(() => {
11700    if (refreshSignal === void 0) return;
11701    if (lastRefreshSignalRef.current === refreshSignal) return;
11702    lastRefreshSignalRef.current = refreshSignal;
11703    handleRefresh();
11704  }, [refreshSignal]);
11705  const handleWakeAndRefresh = () => {
11706    containerTimingRef.current.bootId = newBootId();
11707    containerTimingRef.current.pageLoadTime = Date.now();
11708    containerTimingRef.current.iframeLoadStartTime = Date.now();
11709    containerTimingRef.current.firstStatusCheckTime = null;
11710    containerTimingRef.current.containerReadyTime = null;
11711    containerTimingRef.current.iframeLoadCompleteTime = null;
11712    logContainerTiming("wake_and_refresh_triggered");
11713    setIsLoading(true);
11714    setHasError(false);
11715    setIsContainerStarting(true);
11716    isContainerStartingRef.current = true;
11717    setLiveContainerStatus(null);
11718    loadingStartTimeRef.current = Date.now();
11719    if (iframeRef.current && previewUrl) {
11720      const refreshUrl = buildPreviewUrl(previewUrl, currentPath);
11721      const url = new URL(refreshUrl);
11722      url.searchParams.set("_r", Date.now().toString());
11723      iframeRef.current.src = url.toString();
11724    }
11725  };
11726  const navigateToPath = reactExports.useCallback((path, addToHistory = true) => {
11727    if (!previewUrl) return;
11728    const normalizedPath = path.startsWith("/") ? path : `/${path}`;
11729    setCurrentPath(normalizedPath);
11730    setIsLoading(true);
11731    setHasError(false);
11732    if (addToHistory) {
11733      setHistoryStack((prev) => [...prev.slice(0, historyIndex + 1), normalizedPath]);
11734      setHistoryIndex((prev) => prev + 1);
11735    }
11736    if (iframeRef.current) {
11737      iframeRef.current.src = buildPreviewUrl(previewUrl, normalizedPath);
11738    }
11739  }, [previewUrl, historyIndex]);
11740  const handleBack = reactExports.useCallback(() => {
11741    var _a;
11742    if (historyIndex > 0 && ((_a = iframeRef.current) == null ? void 0 : _a.contentWindow)) {
11743      const newIndex = historyIndex - 1;
11744      const targetPath = historyStack[newIndex];
11745      console.log("[ReactPreviewPanel] handleBack - sending navigate-to-path:", targetPath);
11746      ignoreNextNavMessage.current = true;
11747      iframeRef.current.contentWindow.postMessage({
11748        type: "navigate-to-path",
11749        path: targetPath
11750      }, "*");
11751      setHistoryIndex(newIndex);
11752      setCurrentPath(targetPath);
11753    }
11754  }, [historyIndex, historyStack]);
11755  const handleForward = reactExports.useCallback(() => {
11756    var _a;
11757    if (historyIndex < historyStack.length - 1 && ((_a = iframeRef.current) == null ? void 0 : _a.contentWindow)) {
11758      const newIndex = historyIndex + 1;
11759      const targetPath = historyStack[newIndex];
11760      ignoreNextNavMessage.current = true;
11761      iframeRef.current.contentWindow.postMessage({
11762        type: "navigate-to-path",
11763        path: targetPath
11764      }, "*");
11765      setHistoryIndex(newIndex);
11766      setCurrentPath(targetPath);
11767    }
11768  }, [historyIndex, historyStack]);
11769  const handleUrlSubmit = (e) => {
11770    e.preventDefault();
11771    if (urlInputValue.trim() === "") return;
11772    navigateToPath(urlInputValue);
11773  };
11774  const handleUrlKeyDown = (e) => {
11775    var _a, _b, _c, _d, _e;
11776    if (!isTypeaheadOpen) {
11777      if (e.key === "ArrowDown" && isDesktop && effectivePages.length > 0) {
11778        e.preventDefault();
11779        setIsTypeaheadOpen(true);
11780        return;
11781      }
11782      if (e.key === "Enter") {
11783        e.preventDefault();
11784        if (urlInputValue.trim() !== "") navigateToPath(urlInputValue);
11785      }
11786      return;
11787    }
11788    switch (e.key) {
11789      case "ArrowDown":
11790        e.preventDefault();
11791        (_a = typeaheadRef.current) == null ? void 0 : _a.moveActive("down");
11792        break;
11793      case "ArrowUp":
11794        e.preventDefault();
11795        (_b = typeaheadRef.current) == null ? void 0 : _b.moveActive("up");
11796        break;
11797      case "Home":
11798        e.preventDefault();
11799        (_c = typeaheadRef.current) == null ? void 0 : _c.moveActive("home");
11800        break;
11801      case "End":
11802        e.preventDefault();
11803        (_d = typeaheadRef.current) == null ? void 0 : _d.moveActive("end");
11804        break;
11805      case "Enter": {
11806        const activePath = ((_e = typeaheadRef.current) == null ? void 0 : _e.selectActive()) ?? null;
11807        e.preventDefault();
11808        if (activePath) {
11809          navigateToPath(activePath);
11810          setIsTypeaheadOpen(false);
11811        } else if (urlInputValue.trim() !== "") {
11812          navigateToPath(urlInputValue);
11813          setIsTypeaheadOpen(false);
11814        } else {
11815          setIsTypeaheadOpen(false);
11816        }
11817        break;
11818      }
11819      case "Escape":
11820        setIsTypeaheadOpen(false);
11821        break;
11822    }
11823  };
11824  const handleUrlBlur = () => {
11825    if (blurTimerRef.current !== null) {
11826      window.clearTimeout(blurTimerRef.current);
11827    }
11828    blurTimerRef.current = window.setTimeout(() => {
11829      setIsTypeaheadOpen(false);
11830      blurTimerRef.current = null;
11831    }, 150);
11832  };
11833  reactExports.useEffect(() => {
11834    return () => {
11835      if (blurTimerRef.current !== null) {
11836        window.clearTimeout(blurTimerRef.current);
11837      }
11838    };
11839  }, []);
11840  const handleTypeaheadSelect = (path) => {
11841    var _a;
11842    navigateToPath(path);
11843    setIsTypeaheadOpen(false);
11844    if (blurTimerRef.current !== null) {
11845      window.clearTimeout(blurTimerRef.current);
11846      blurTimerRef.current = null;
11847    }
11848    (_a = inputRef.current) == null ? void 0 : _a.blur();
11849  };
11850  const handleTypeaheadPointerDownInside = () => {
11851    if (blurTimerRef.current !== null) {
11852      window.clearTimeout(blurTimerRef.current);
11853      blurTimerRef.current = null;
11854    }
11855  };
11856  const canGoBack = historyIndex > 0;
11857  const canGoForward = historyIndex < historyStack.length - 1;
11858  const browserToolbar = /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex h-16 flex-shrink-0 items-center gap-2 border-b border-[#1B1A22]/[0.06] bg-white px-3.5", children: [
11859    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: TOOLBAR_CAPSULE, children: [
11860      /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: handleBack, disabled: !canGoBack, className: clsx(TOOLBAR_BTN, TOOLBAR_BTN_HAPTIC), style: TOOLBAR_BTN_STYLE, title: "Go back", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronLeft, { className: "h-4 w-4" }) }),
11861      /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: handleForward, disabled: !canGoForward, className: clsx(TOOLBAR_BTN, TOOLBAR_BTN_HAPTIC), style: TOOLBAR_BTN_STYLE, title: "Go forward", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "h-4 w-4" }) }),
11862      /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: handleRefresh, disabled: isLoading, className: clsx(TOOLBAR_BTN, TOOLBAR_BTN_HAPTIC), style: TOOLBAR_BTN_STYLE, title: "Refresh", children: /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: clsx("h-3.5 w-3.5", (isLoading || isNavigating) && "animate-spin") }) })
11863    ] }),
11864    /* @__PURE__ */ jsxRuntimeExports.jsxs(Popover, { open: isTypeaheadOpen, onOpenChange: setIsTypeaheadOpen, children: [
11865      /* @__PURE__ */ jsxRuntimeExports.jsx(PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("form", { ref: formRef, onSubmit: (e) => {
11866        handleUrlSubmit(e);
11867        setIsTypeaheadOpen(false);
11868      }, className: "relative mx-auto flex-[0_1_360px] focus-within:basis-[480px]", style: {
11869        transition: "flex-basis 240ms cubic-bezier(0.4, 0, 0.2, 1)"
11870      }, children: [
11871        /* @__PURE__ */ jsxRuntimeExports.jsx(Search, { "aria-hidden": "true", className: "text-[#1B1A22]/45 pointer-events-none absolute left-[19px] top-1/2 h-3.5 w-3.5 -translate-y-1/2", style: {
11872          opacity: isTypeaheadOpen ? 1 : 0,
11873          transition: "opacity 240ms ease-out"
11874        } }),
11875        /* @__PURE__ */ jsxRuntimeExports.jsx(
11876          "input",
11877          {
11878            ref: inputRef,
11879            type: "text",
11880            value: urlInputValue,
11881            onChange: (e) => setUrlInputValue(e.target.value),
11882            onKeyDown: handleUrlKeyDown,
11883            onClick: () => {
11884              if (!isDesktop || effectivePages.length === 0) return;
11885              setIsTypeaheadOpen(true);
11886            },
11887            onFocus: () => {
11888              setUrlInputValue("");
11889            },
11890            onBlur: handleUrlBlur,
11891            role: "combobox",
11892            "aria-expanded": isTypeaheadOpen,
11893            "aria-controls": "pages-typeahead-listbox",
11894            className: clsx(!isTypeaheadOpen && GLASS_PILL, "h-7 w-full rounded-full border-0 pr-3 text-left text-sm font-medium leading-7 placeholder-gray-400 placeholder:font-normal focus:outline-none", isTypeaheadOpen ? "text-[#1B1A22]" : "text-transparent"),
11895            style: {
11896              transition: "box-shadow 240ms ease-out, background 240ms ease-out, padding-left 280ms cubic-bezier(0.32, 0.72, 0, 1)",
11897              paddingLeft: isTypeaheadOpen ? "47px" : "45%",
11898              ...isTypeaheadOpen ? {
11899                background: "#FFFFFF",
11900                boxShadow: "inset 0 1px 0 rgba(255,255,255,1), inset 0 -1px 0 rgba(27,26,34,0.04), 0 1px 3px rgba(27,26,34,0.06), 0 8px 24px -6px rgba(27,26,34,0.10)"
11901              } : {}
11902            },
11903            placeholder: isTypeaheadOpen ? "Search pages or type a path" : ""
11904          }
11905        ),
11906        !isTypeaheadOpen && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 flex items-center justify-center gap-2 px-3", style: {
11907          WebkitMaskImage: isDomainCtaHovered ? "linear-gradient(to right, black 0%, black 25%, transparent 70%)" : "linear-gradient(to right, black 0%, black 100%, transparent 100%)",
11908          maskImage: isDomainCtaHovered ? "linear-gradient(to right, black 0%, black 25%, transparent 70%)" : "linear-gradient(to right, black 0%, black 100%, transparent 100%)",
11909          transition: "mask-image 240ms ease-out, -webkit-mask-image 240ms ease-out"
11910        }, children: [
11911          isPreviewLoading && /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "h-3.5 w-3.5 flex-none animate-spin text-[#1B1A22]/40", strokeWidth: 2.25 }),
11912          /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "truncate text-sm font-medium leading-7", children: [
11913            /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[#1B1A22]/40", children: [
11914              domainName || "yourdomain.com",
11915              "/"
11916            ] }),
11917            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[#1B1A22]", children: currentPath.replace(/^\/+/, "") })
11918          ] })
11919        ] }),
11920        !isTypeaheadOpen && !hasCustomDomain && websiteId && /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { type: "button", onClick: () => {
11921          posthog == null ? void 0 : posthog.capture("Set Up Domain Clicked", {
11922            websiteId,
11923            source: "preview_url_bar",
11924            websiteType: "react"
11925          });
11926          navigate(namedRoutes.reactWebsiteChatSettingsTab({
11927            id: websiteId,
11928            tab: "domain"
11929          }));
11930        }, onMouseEnter: () => setIsDomainCtaHovered(true), onMouseLeave: () => setIsDomainCtaHovered(false), onFocus: () => setIsDomainCtaHovered(true), onBlur: () => setIsDomainCtaHovered(false), "aria-label": "Set up your domain", className: clsx("group absolute inset-y-[2px] right-[2px] z-10 flex items-center", "overflow-hidden rounded-full bg-transparent text-[#1B1A22]/40", "hover:bg-[#d6e9db] hover:text-green-500", "max-w-[24px] hover:max-w-[180px]", "duration-[200ms] ease-[cubic-bezier(0.4,0,1,1)] transition-[max-width,background-color,color]", "hover:duration-[280ms] hover:ease-[cubic-bezier(0.32,0.72,0,1)]"), children: [
11931          /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "relative flex h-6 w-6 flex-none items-center justify-center", children: [
11932            /* @__PURE__ */ jsxRuntimeExports.jsx(Globe, { className: "h-3.5 w-3.5 [filter:drop-shadow(0_0.5px_0_rgba(255,255,255,0.7))]", strokeWidth: 2.25 }),
11933            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { "aria-hidden": "true", className: clsx("pointer-events-none absolute right-[3px] top-[3px] h-1.5 w-1.5 rounded-full", "bg-gradient-to-b from-[#FCD34D] to-[#EAB308]", "shadow-[inset_0_0.5px_0_rgba(255,255,255,0.55),0_0.5px_1px_rgba(146,64,14,0.18),0_0_0_2px_#F4F4F7]", "transition-opacity duration-150 ease-out", "group-hover:opacity-0 group-focus-visible:opacity-0") })
11934          ] }),
11935          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: clsx("whitespace-nowrap pr-3 text-xs font-medium leading-6", "opacity-0 transition-opacity duration-150 ease-out", "group-hover:opacity-100 group-hover:delay-100"), children: "Set up your domain" })
11936        ] })
11937      ] }) }),
11938      /* @__PURE__ */ jsxRuntimeExports.jsx(PagesTypeahead, { ref: typeaheadRef, pages: effectivePages, query: urlInputValue, currentPath, anchorRef: formRef, onSelect: handleTypeaheadSelect, onClose: () => setIsTypeaheadOpen(false), onPointerDownInside: handleTypeaheadPointerDownInside, websiteId, hasCustomDomain, domainName })
11939    ] }),
11940    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: clsx(TOOLBAR_CAPSULE, "group relative"), children: [
11941      /* @__PURE__ */ jsxRuntimeExports.jsx("div", { "aria-hidden": true, className: "pointer-events-none absolute left-0.5 top-0.5 z-0 h-7 w-7 scale-100 rounded-full bg-[linear-gradient(180deg,#ffffff_0%,#f6f6f8_100%)] shadow-[inset_0_1px_0_rgba(255,255,255,1),inset_0_2px_4px_rgba(255,255,255,0.5),inset_0_-2px_4px_-2px_rgba(27,26,34,0.08),inset_0_0_0_0.5px_rgba(27,26,34,0.14),0_0_4px_rgba(27,26,34,0.055),0_0_13px_-2px_rgba(27,26,34,0.06),0_0_24px_-5px_rgba(27,26,34,0.07)] group-active:scale-[1.16]", style: {
11942        translate: `${viewportIndicatorOffset(viewportSize)}px 0`,
11943        transition: "translate 280ms cubic-bezier(0.4,0,0.2,1), transform 260ms cubic-bezier(0.34,1.56,0.64,1)"
11944      } }),
11945      /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => setViewportSize("desktop"), className: clsx(TOOLBAR_BTN, "relative z-[1]", viewportSize !== "desktop" && TOOLBAR_BTN_HAPTIC), style: TOOLBAR_BTN_STYLE, title: "Desktop view", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Monitor, { className: "h-4 w-4" }) }),
11946      /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => setViewportSize("tablet"), className: clsx(TOOLBAR_BTN, "relative z-[1]", viewportSize !== "tablet" && TOOLBAR_BTN_HAPTIC), style: TOOLBAR_BTN_STYLE, title: "Tablet view", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Tablet, { className: "h-4 w-4" }) }),
11947      /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => setViewportSize("mobile"), className: clsx(TOOLBAR_BTN, "relative z-[1]", viewportSize !== "mobile" && TOOLBAR_BTN_HAPTIC), style: TOOLBAR_BTN_STYLE, title: "Mobile view", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Smartphone, { className: "h-4 w-4" }) })
11948    ] }),
11949    /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: TOOLBAR_CAPSULE, children: /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipProvider, { delayDuration: 250, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tooltip, { children: [
11950      /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: handleEditTextToggle, disabled: !isSelectorReady || hasPreviewError && !editTextModeActive, "aria-pressed": editTextModeActive, "aria-label": editTextModeActive ? "Exit Edit text mode" : "Edit text directly in the preview", className: clsx(editTextModeActive ? clsx(
11951        // Active glass-button shell: positioned + clipped to
11952        // round so the specular ::before stays inside the
11953        // circle. Class hook `ls-glass-active` lets the
11954        // reduced-motion media query in index.css cancel the
11955        // pulse + drift while leaving the static layering
11956        // untouched.
11957        "ls-glass-active relative flex h-7 w-7 items-center justify-center overflow-hidden rounded-full text-white",
11958        "active:scale-[0.94]",
11959        // Specular drift ::before — radial highlight whose
11960        // background-position transitions on hover so the
11961        // bright spot drifts diagonally. Constrained to the
11962        // button's circle by `overflow-hidden` above.
11963        "before:absolute before:inset-0 before:rounded-full before:content-['']",
11964        "before:bg-[radial-gradient(circle_at_30%_25%,rgba(255,255,255,0.55)_0%,transparent_45%)]",
11965        "before:duration-[280ms] before:transition-[background-position]",
11966        "before:ease-[cubic-bezier(0.32,0.72,0,1)]",
11967        "hover:before:[background-position:60%_50%]",
11968        // Keep the icon glyph above the specular layer.
11969        "[&>svg]:relative [&>svg]:z-[1]"
11970      ) : clsx(TOOLBAR_BTN, TOOLBAR_BTN_HAPTIC)), style: editTextModeActive ? {
11971        // Active state: flat indigo gradient. Formerly a
11972        // backdrop-filter chain (SVG displacement lens + blur
11973        // + saturate) with an infinite halo pulse — dropped
11974        // with the rest of the editor's backdrop filters
11975        // (HS #16453): the lens re-filtered the backdrop
11976        // every frame, the costliest effect per pixel in the
11977        // editor, for a button that reads nearly the same
11978        // painted. The specular ::before in the className
11979        // keeps the glassy highlight without filter cost.
11980        background: "linear-gradient(180deg, #818cf8 0%, #6366f1 50%, #4338ca 100%)",
11981        transition: "transform 110ms ease-out, background 240ms ease-out"
11982      } : TOOLBAR_BTN_STYLE, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Type, { className: "h-4 w-4" }) }) }),
11983      /* @__PURE__ */ jsxRuntimeExports.jsx(TooltipContent, { sideOffset: 6, children: hasPreviewError && !editTextModeActive ? "Fix the preview error before editing text" : "Edit text" })
11984    ] }) }) })
11985  ] });
11986  if (containerStatus === "starting") {
11987    return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex h-full flex-col bg-white", children: [
11988      browserToolbar,
11989      /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-1 items-center justify-center bg-gray-100", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center", children: [
11990        /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "mx-auto h-12 w-12 animate-spin text-blue-600" }),
11991        /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "mt-4 text-lg font-medium text-gray-900", children: "Starting Preview Server..." }),
11992        /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-2 text-sm text-gray-500", children: "This may take a few moments" })
11993      ] }) })
11994    ] });
11995  }
11996  if (wasEverReady && (containerStatus === "stopped" || containerStatus === "stopped_with_code")) {
11997    return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex h-full flex-col bg-white", children: [
11998      browserToolbar,
11999      /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-1 items-center justify-center bg-gray-100", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "max-w-md text-center", children: [
12000        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-amber-100", children: /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-8 w-8 text-amber-600" }) }),
12001        /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-lg font-medium text-gray-900", children: "Preview Server Stopped" }),
12002        /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-2 text-sm text-gray-500", children: "The preview server has stopped. Click below to restart it." }),
12003        /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { onClick: handleWakeAndRefresh, className: "mt-4 inline-flex items-center gap-2 rounded-md bg-blue-600 px-4 py-2 text-sm font-medium text-white hover:bg-blue-700", children: [
12004          /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "h-4 w-4" }),
12005          "Start Preview Server"
12006        ] }),
12007        /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "mt-4 text-xs text-gray-400", children: [
12008          "If this keeps happening, contact",
12009          " ",
12010          /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "mailto:[email protected]", className: "text-blue-600 hover:underline", children: "[email protected]" })
12011        ] })
12012      ] }) })
12013    ] });
12014  }
12015  if (containerStatus === "error" || containerError) {
12016    return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex h-full flex-col bg-white", children: [
12017      browserToolbar,
12018      /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-1 items-center justify-center bg-gray-100", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "max-w-md text-center", children: [
12019        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-red-100", children: /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-8 w-8 text-red-600" }) }),
12020        /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-lg font-medium text-gray-900", children: "Preview Unavailable" }),
12021        /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-2 text-sm text-gray-500", children: containerError || "Unable to start the preview server. Please try again." }),
12022        /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { onClick: handleWakeAndRefresh, className: "mt-4 inline-flex items-center gap-2 rounded-md bg-blue-600 px-4 py-2 text-sm font-medium text-white hover:bg-blue-700", children: [
12023          /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "h-4 w-4" }),
12024          "Retry"
12025        ] }),
12026        /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "mt-4 text-xs text-gray-400", children: [
12027          "If this keeps happening, contact",
12028          " ",
12029          /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "mailto:[email protected]", className: "text-blue-600 hover:underline", children: "[email protected]" })
12030        ] })
12031      ] }) })
12032    ] });
12033  }
12034  if (!previewUrl) {
12035    return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex h-full flex-col bg-white", children: [
12036      browserToolbar,
12037      /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-1 items-center justify-center bg-gray-100", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "max-w-sm text-center", children: [
12038        /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "mx-auto h-12 w-12 animate-spin text-blue-600" }),
12039        /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "mt-4 text-lg font-medium text-gray-900", children: "Initializing Preview..." }),
12040        /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-2 text-sm text-gray-500", children: "Setting up your development environment" }),
12041        /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "mt-4 text-xs text-gray-400", children: [
12042          "Taking too long? Try refreshing the page or contact",
12043          " ",
12044          /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "mailto:[email protected]", className: "text-blue-600 hover:underline", children: "[email protected]" })
12045        ] })
12046      ] }) })
12047    ] });
12048  }
12049  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex h-full flex-col bg-white", children: [
12050    bannerRendered && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { role: "status", "aria-live": "polite", className: "relative flex h-8 flex-shrink-0 items-center justify-center gap-2 overflow-hidden rounded-t-[16px] border-b border-[#1B1A22]/[0.08] px-4 text-xs font-medium text-indigo-950", style: {
12051      // Solid pale-indigo base + a faint 1px-on/9px-off diagonal stripe
12052      // overlay (so the stripe pattern reads as texture without
12053      // fighting the text for legibility).
12054      backgroundColor: "rgba(165, 180, 252, 0.32)",
12055      backgroundImage: "repeating-linear-gradient(45deg, rgba(67,56,202,0.06) 0px, rgba(67,56,202,0.06) 1px, transparent 1px, transparent 10px)",
12056      // Emerge / retreat keyframes drive max-height + opacity so the
12057      // banner unfurls downward from inside the EditorLayout's
12058      // rounded-[16px] top edge and tucks back up the same way on
12059      // exit. Asymmetric easing: slower confident settle on emerge,
12060      // snappier exit on retreat. See @keyframes in index.css.
12061      animation: bannerExiting ? "edit-text-banner-retreat 320ms cubic-bezier(0.4,0,1,1) both" : "edit-text-banner-emerge 320ms cubic-bezier(0.32,0.72,0,1) both"
12062    }, children: [
12063      /* @__PURE__ */ jsxRuntimeExports.jsx(Type, { className: "h-3.5 w-3.5 text-indigo-700" }),
12064      /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: editTotalCount > 0 ? `Editing text · ${editTotalCount} change${editTotalCount === 1 ? "" : "s"}` : "Editing text" }),
12065      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "absolute right-2 flex items-center gap-1", children: [
12066        editTotalCount > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
12067          /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", onClick: handleCancelEdits, disabled: editSaving, className: "flex h-6 items-center rounded-[7px] px-2 text-[11px] font-medium text-indigo-900/70 transition-colors hover:bg-indigo-900/10 hover:text-indigo-900 focus:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500/50 disabled:cursor-not-allowed disabled:opacity-50", children: "Discard" }),
12068          /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", onClick: handleSaveEdits, disabled: editSaving, className: "flex h-6 items-center whitespace-nowrap rounded-[7px] bg-indigo-600 px-2.5 text-[11px] font-semibold text-white transition-colors hover:bg-indigo-700 focus:outline-none focus-visible:ring-2 focus-visible:ring-indigo-300 disabled:cursor-not-allowed disabled:opacity-70", children: editSaving ? "Saving…" : editSaveLabel })
12069        ] }),
12070        /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", onClick: handleEditTextToggle, disabled: editSaving, "aria-label": "Exit text editing", title: "Exit text editing", className: "flex h-5 w-5 items-center justify-center rounded-full text-indigo-700/80 transition-colors hover:bg-indigo-900/10 hover:text-indigo-900 focus:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500/50 disabled:cursor-not-allowed disabled:opacity-50", children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "h-3.5 w-3.5" }) })
12071      ] })
12072    ] }),
12073    browserToolbar,
12074    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { ref: containerRef, className: "relative flex flex-1 items-center justify-center overflow-hidden rounded-b-[16px] bg-gray-100", children: [
12075      (isSavingEdits || isApplyingWithAI) && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: clsx("absolute inset-0 z-20 flex items-center justify-center backdrop-blur-[1px]", isApplyingWithAI ? "bg-white/90" : "bg-white/60"), children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 rounded-md bg-white px-4 py-2 text-sm font-medium text-gray-700 shadow", children: [
12076        /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "h-4 w-4 animate-spin text-indigo-600" }),
12077        isApplyingWithAI ? "Applying with AI…" : "Saving your edits…"
12078      ] }) }),
12079      isLoading && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute inset-0 z-10 flex items-center justify-center bg-gray-100", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center", children: [
12080        /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "mx-auto h-8 w-8 animate-spin text-blue-600" }),
12081        isContainerStarting ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
12082          /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "mt-4 text-lg font-medium text-gray-900", children: "Starting Preview Server..." }),
12083          /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-2 text-sm text-gray-500", children: "The container is waking up. This may take 30-60 seconds." }),
12084          /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "mt-1 text-xs text-gray-400", children: [
12085            "Status: ",
12086            liveContainerStatus || "checking..."
12087          ] })
12088        ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-2 text-sm text-gray-500", children: "Loading preview..." })
12089      ] }) }),
12090      hasError && !isLoading && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute inset-0 z-10 flex items-center justify-center bg-gray-100", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "max-w-sm text-center", children: [
12091        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-amber-100", children: /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-8 w-8 text-amber-600" }) }),
12092        /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-lg font-medium text-gray-900", children: "Preview Connection Lost" }),
12093        /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-2 text-sm text-gray-500", children: "The preview server may have timed out or stopped." }),
12094        liveContainerStatus && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "mt-1 text-xs text-gray-400", children: [
12095          "Container status: ",
12096          liveContainerStatus
12097        ] }),
12098        /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { onClick: handleWakeAndRefresh, className: "mt-4 inline-flex items-center gap-2 rounded-md bg-blue-600 px-4 py-2 text-sm font-medium text-white hover:bg-blue-700", children: [
12099          /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "h-4 w-4" }),
12100          "Restart Preview"
12101        ] }),
12102        /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "mt-4 text-xs text-gray-400", children: [
12103          "If this keeps happening, contact",
12104          " ",
12105          /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "mailto:[email protected]", className: "text-blue-600 hover:underline", children: "[email protected]" })
12106        ] })
12107      ] }) }),
12108      /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: clsx(
12109        "relative overflow-hidden bg-white transition-all duration-300",
12110        // For mobile/tablet, always show device frame styling
12111        viewportSize !== "desktop" && "rounded-xl border border-gray-200 shadow-lg"
12112      ), style: {
12113        // Desktop: fill the container entirely
12114        // Mobile/Tablet: use fixed dimensions (scaled if needed), capped to container height
12115        width: viewportSize === "desktop" ? "100%" : needsScaling ? `${iframeWidth * scale}px` : `${iframeWidth}px`,
12116        height: viewportSize === "desktop" ? "100%" : `${Math.min(iframeHeight * scale, containerSize.height - 32)}px`,
12117        maxHeight: viewportSize !== "desktop" ? `${containerSize.height - 32}px` : void 0
12118      }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
12119        "iframe",
12120        {
12121          ref: iframeRef,
12122          src: buildPreviewUrl(previewUrl),
12123          className: "bg-white",
12124          style: {
12125            // The iframe is at target dimensions (e.g., 1512px for desktop)
12126            // This makes the content INSIDE the iframe render at desktop width
12127            width: `${iframeWidth}px`,
12128            height: `${iframeHeight}px`,
12129            // Scale down to fit the wrapper visually
12130            transform: `scale(${scale})`,
12131            transformOrigin: "top left"
12132          },
12133          onLoad: handleIframeLoad,
12134          onError: handleIframeError,
12135          title: "Website Preview",
12136          sandbox: "allow-scripts allow-same-origin allow-forms allow-popups allow-downloads allow-popups-to-escape-sandbox"
12137        }
12138      ) })
12139    ] }),
12140    /* @__PURE__ */ jsxRuntimeExports.jsx(DiscardEditsConfirmModal, { open: pendingExitConfirm, onConfirm: handleDiscardConfirm, onCancel: handleDiscardCancel }),
12141    testCheckout && /* @__PURE__ */ jsxRuntimeExports.jsx(TestCheckoutSheet, { open: true, storeName: domainName || "your store", ownerEmail: (currentUser == null ? void 0 : currentUser.email) ?? "you", collectsShippingAddress: testCheckout.context.collectsShippingAddress, shippingCountries: testCheckout.context.shippingCountries, currency: testCheckout.context.currency, lines: testCheckout.context.lines, subtotal: testCheckout.context.subtotal, shippingRates: testCheckout.context.shippingRates, freeShippingOver: testCheckout.context.freeShippingOver, stripeTaxEnabled: testCheckout.context.stripeTaxEnabled, taxBehavior: testCheckout.context.taxBehavior, subscription: testCheckout.context.subscription, submitting: testCheckoutSubmitting, onSubmit: submitTestCheckout, onCancel: cancelTestCheckout })
12142  ] });
12143};
12144const ReactPreviewPanel$1 = React.memo(ReactPreviewPanel);
12145const STORAGE_KEY = "ls_hdyhau_done_v1";
12146const THANKS_MS = 2e3;
12147const OPTIONS = [{
12148  value: "tiktok",
12149  label: "TikTok"
12150}, {
12151  value: "instagram",
12152  label: "Instagram"
12153}, {
12154  value: "youtube",
12155  label: "YouTube"
12156}, {
12157  value: "facebook",
12158  label: "Facebook"
12159}, {
12160  value: "chatgpt",
12161  label: "ChatGPT"
12162}, {
12163  value: "google",
12164  label: "Google"
12165}, {
12166  value: "friend",
12167  label: "A friend"
12168}, {
12169  value: "other",
12170  label: "Other"
12171}];
12172const HdyhauSurveyCard = () => {
12173  const {
12174    isAuthenticated
12175  } = useAuth();
12176  const [recordAcquisition] = useMutation$1(RECORD_ACQUISITION);
12177  const [phase, setPhase] = reactExports.useState(() => {
12178    try {
12179      return localStorage.getItem(STORAGE_KEY) ? "hidden" : "ask";
12180    } catch {
12181      return "ask";
12182    }
12183  });
12184  const [detail, setDetail] = reactExports.useState("");
12185  const thanksTimer = reactExports.useRef(void 0);
12186  reactExports.useEffect(() => {
12187    return () => {
12188      if (thanksTimer.current) clearTimeout(thanksTimer.current);
12189    };
12190  }, []);
12191  const setGuard = () => {
12192    try {
12193      localStorage.setItem(STORAGE_KEY, "1");
12194    } catch {
12195    }
12196  };
12197  const send = (source, detailText) => {
12198    if (isAuthenticated) {
12199      recordAcquisition({
12200        variables: {
12201          surveySource: source,
12202          surveyDetail: detailText ?? null
12203        }
12204      }).catch(() => {
12205      });
12206    } else {
12207      stashSurveyAnswer(source, detailText);
12208    }
12209  };
12210  const showThanks = () => {
12211    setPhase("thanks");
12212    thanksTimer.current = setTimeout(() => setPhase("hidden"), THANKS_MS);
12213  };
12214  const onPick = (source) => {
12215    send(source);
12216    setGuard();
12217    if (source === "other") {
12218      setPhase("detail");
12219    } else {
12220      showThanks();
12221    }
12222  };
12223  const onDetailSubmit = () => {
12224    const trimmed = detail.trim();
12225    if (trimmed) send("other", trimmed);
12226    showThanks();
12227  };
12228  const onSkip = () => {
12229    setGuard();
12230    setPhase("hidden");
12231  };
12232  if (phase === "hidden") return null;
12233  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-10 w-full max-w-md rounded-lg border border-gray-200 bg-white p-4 text-left shadow-sm", children: phase === "thanks" ? /* @__P
12233URE__ */ jsxRuntimeExports.jsx("p", { className: "text-center text-sm text-gray-600", children: "Thanks — that helps us a lot! 🙌" }) : phase === "detail" ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
12234    /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "mb-2 text-sm font-medium text-gray-700", children: [
12235      "Where was that? ",
12236      /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-gray-400", children: "(optional)" })
12237    ] }),
12238    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
12239      /* @__PURE__ */ jsxRuntimeExports.jsx("input", { type: "text", value: detail, onChange: (e) => setDetail(e.target.value), onKeyDown: (e) => e.key === "Enter" && onDetailSubmit(), maxLength: 500, placeholder: "e.g. a podcast, a friend's website…", className: "min-w-0 flex-1 rounded-md border border-gray-300 px-3 py-1.5 text-sm focus:border-blue-500 focus:outline-none" }),
12240      /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", onClick: onDetailSubmit, className: "rounded-md bg-blue-600 px-3 py-1.5 text-sm font-medium text-white hover:bg-blue-700", children: "Send" })
12241    ] })
12242  ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
12243    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-3 flex items-start justify-between gap-2", children: [
12244      /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium text-gray-700", children: "While you wait — where did you hear about us?" }),
12245      /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", onClick: onSkip, className: "-mr-1 -mt-1 shrink-0 rounded px-1 text-xs text-gray-400 hover:text-gray-600", children: "Skip" })
12246    ] }),
12247    /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-wrap gap-2", children: OPTIONS.map((option) => /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", onClick: () => onPick(option.value), className: "rounded-full border border-gray-300 bg-white px-3 py-1.5 text-sm text-gray-700 transition-colors hover:border-blue-500 hover:bg-blue-50 hover:text-blue-700", children: option.label }, option.value)) })
12248  ] }) });
12249};
12250var module = {};
12251(function main(global, module2, isWorker, workerSize) {
12252  var canUseWorker = !!(global.Worker && global.Blob && global.Promise && global.OffscreenCanvas && global.OffscreenCanvasRenderingContext2D && global.HTMLCanvasElement && global.HTMLCanvasElement.prototype.transferControlToOffscreen && global.URL && global.URL.createObjectURL);
12253  var canUsePaths = typeof Path2D === "function" && typeof DOMMatrix === "function";
12254  var canDrawBitmap = function() {
12255    if (!global.OffscreenCanvas) {
12256      return false;
12257    }
12258    var canvas = new OffscreenCanvas(1, 1);
12259    var ctx = canvas.getContext("2d");
12260    ctx.fillRect(0, 0, 1, 1);
12261    var bitmap = canvas.transferToImageBitmap();
12262    try {
12263      ctx.createPattern(bitmap, "no-repeat");
12264    } catch (e) {
12265      return false;
12266    }
12267    return true;
12268  }();
12269  function noop() {
12270  }
12271  function promise(func) {
12272    var ModulePromise = module2.exports.Promise;
12273    var Prom = ModulePromise !== void 0 ? ModulePromise : global.Promise;
12274    if (typeof Prom === "function") {
12275      return new Prom(func);
12276    }
12277    func(noop, noop);
12278    return null;
12279  }
12280  var bitmapMapper = /* @__PURE__ */ function(skipTransform, map) {
12281    return {
12282      transform: function(bitmap) {
12283        if (skipTransform) {
12284          return bitmap;
12285        }
12286        if (map.has(bitmap)) {
12287          return map.get(bitmap);
12288        }
12289        var canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
12290        var ctx = canvas.getContext("2d");
12291        ctx.drawImage(bitmap, 0, 0);
12292        map.set(bitmap, canvas);
12293        return canvas;
12294      },
12295      clear: function() {
12296        map.clear();
12297      }
12298    };
12299  }(canDrawBitmap, /* @__PURE__ */ new Map());
12300  var raf = function() {
12301    var TIME = Math.floor(1e3 / 60);
12302    var frame, cancel;
12303    var frames = {};
12304    var lastFrameTime = 0;
12305    if (typeof requestAnimationFrame === "function" && typeof cancelAnimationFrame === "function") {
12306      frame = function(cb) {
12307        var id = Math.random();
12308        frames[id] = requestAnimationFrame(function onFrame(time) {
12309          if (lastFrameTime === time || lastFrameTime + TIME - 1 < time) {
12310            lastFrameTime = time;
12311            delete frames[id];
12312            cb();
12313          } else {
12314            frames[id] = requestAnimationFrame(onFrame);
12315          }
12316        });
12317        return id;
12318      };
12319      cancel = function(id) {
12320        if (frames[id]) {
12321          cancelAnimationFrame(frames[id]);
12322        }
12323      };
12324    } else {
12325      frame = function(cb) {
12326        return setTimeout(cb, TIME);
12327      };
12328      cancel = function(timer) {
12329        return clearTimeout(timer);
12330      };
12331    }
12332    return { frame, cancel };
12333  }();
12334  var getWorker = /* @__PURE__ */ function() {
12335    var worker;
12336    var prom;
12337    var resolves = {};
12338    function decorate(worker2) {
12339      function execute(options, callback) {
12340        worker2.postMessage({ options: options || {}, callback });
12341      }
12342      worker2.init = function initWorker(canvas) {
12343        var offscreen = canvas.transferControlToOffscreen();
12344        worker2.postMessage({ canvas: offscreen }, [offscreen]);
12345      };
12346      worker2.fire = function fireWorker(options, size2, done) {
12347        if (prom) {
12348          execute(options, null);
12349          return prom;
12350        }
12351        var id = Math.random().toString(36).slice(2);
12352        prom = promise(function(resolve) {
12353          function workerDone(msg) {
12354            if (msg.data.callback !== id) {
12355              return;
12356            }
12357            delete resolves[id];
12358            worker2.removeEventListener("message", workerDone);
12359            prom = null;
12360            bitmapMapper.clear();
12361            done();
12362            resolve();
12363          }
12364          worker2.addEventListener("message", workerDone);
12365          execute(options, id);
12366          resolves[id] = workerDone.bind(null, { data: { callback: id } });
12367        });
12368        return prom;
12369      };
12370      worker2.reset = function resetWorker() {
12371        worker2.postMessage({ reset: true });
12372        for (var id in resolves) {
12373          resolves[id]();
12374          delete resolves[id];
12375        }
12376      };
12377    }
12378    return function() {
12379      if (worker) {
12380        return worker;
12381      }
12382      if (!isWorker && canUseWorker) {
12383        var code = [
12384          "var CONFETTI, SIZE = {}, module = {};",
12385          "(" + main.toString() + ")(this, module, true, SIZE);",
12386          "onmessage = function(msg) {",
12387          "  if (msg.data.options) {",
12388          "    CONFETTI(msg.data.options).then(function () {",
12389          "      if (msg.data.callback) {",
12390          "        postMessage({ callback: msg.data.callback });",
12391          "      }",
12392          "    });",
12393          "  } else if (msg.data.reset) {",
12394          "    CONFETTI && CONFETTI.reset();",
12395          "  } else if (msg.data.resize) {",
12396          "    SIZE.width = msg.data.resize.width;",
12397          "    SIZE.height = msg.data.resize.height;",
12398          "  } else if (msg.data.canvas) {",
12399          "    SIZE.width = msg.data.canvas.width;",
12400          "    SIZE.height = msg.data.canvas.height;",
12401          "    CONFETTI = module.exports.create(msg.data.canvas);",
12402          "  }",
12403          "}"
12404        ].join("\n");
12405        try {
12406          worker = new Worker(URL.createObjectURL(new Blob([code])));
12407        } catch (e) {
12408          typeof console !== void 0 && typeof console.warn === "function" ? console.warn("🎊 Could not load worker", e) : null;
12409          return null;
12410        }
12411        decorate(worker);
12412      }
12413      return worker;
12414    };
12415  }();
12416  var defaults = {
12417    particleCount: 50,
12418    angle: 90,
12419    spread: 45,
12420    startVelocity: 45,
12421    decay: 0.9,
12422    gravity: 1,
12423    drift: 0,
12424    ticks: 200,
12425    x: 0.5,
12426    y: 0.5,
12427    shapes: ["square", "circle"],
12428    zIndex: 100,
12429    colors: [
12430      "#26ccff",
12431      "#a25afd",
12432      "#ff5e7e",
12433      "#88ff5a",
12434      "#fcff42",
12435      "#ffa62d",
12436      "#ff36ff"
12437    ],
12438    // probably should be true, but back-compat
12439    disableForReducedMotion: false,
12440    scalar: 1
12441  };
12442  function convert(val, transform) {
12443    return transform ? transform(val) : val;
12444  }
12445  function isOk(val) {
12446    return !(val === null || val === void 0);
12447  }
12448  function prop(options, name, transform) {
12449    return convert(
12450      options && isOk(options[name]) ? options[name] : defaults[name],
12451      transform
12452    );
12453  }
12454  function onlyPositiveInt(number) {
12455    return number < 0 ? 0 : Math.floor(number);
12456  }
12457  function randomInt(min, max) {
12458    return Math.floor(Math.random() * (max - min)) + min;
12459  }
12460  function toDecimal(str) {
12461    return parseInt(str, 16);
12462  }
12463  function colorsToRgb(colors) {
12464    return colors.map(hexToRgb);
12465  }
12466  function hexToRgb(str) {
12467    var val = String(str).replace(/[^0-9a-f]/gi, "");
12468    if (val.length < 6) {
12469      val = val[0] + val[0] + val[1] + val[1] + val[2] + val[2];
12470    }
12471    return {
12472      r: toDecimal(val.substring(0, 2)),
12473      g: toDecimal(val.substring(2, 4)),
12474      b: toDecimal(val.substring(4, 6))
12475    };
12476  }
12477  function getOrigin(options) {
12478    var origin = prop(options, "origin", Object);
12479    origin.x = prop(origin, "x", Number);
12480    origin.y = prop(origin, "y", Number);
12481    return origin;
12482  }
12483  function setCanvasWindowSize(canvas) {
12484    canvas.width = document.documentElement.clientWidth;
12485    canvas.height = document.documentElement.clientHeight;
12486  }
12487  function setCanvasRectSize(canvas) {
12488    var rect = canvas.getBoundingClientRect();
12489    canvas.width = rect.width;
12490    canvas.height = rect.height;
12491  }
12492  function getCanvas(zIndex) {
12493    var canvas = document.createElement("canvas");
12494    canvas.style.position = "fixed";
12495    canvas.style.top = "0px";
12496    canvas.style.left = "0px";
12497    canvas.style.pointerEvents = "none";
12498    canvas.style.zIndex = zIndex;
12499    return canvas;
12500  }
12501  function ellipse(context, x, y, radiusX, radiusY, rotation, startAngle, endAngle, antiClockwise) {
12502    context.save();
12503    context.translate(x, y);
12504    context.rotate(rotation);
12505    context.scale(radiusX, radiusY);
12506    context.arc(0, 0, 1, startAngle, endAngle, antiClockwise);
12507    context.restore();
12508  }
12509  function randomPhysics(opts) {
12510    var radAngle = opts.angle * (Math.PI / 180);
12511    var radSpread = opts.spread * (Math.PI / 180);
12512    return {
12513      x: opts.x,
12514      y: opts.y,
12515      wobble: Math.random() * 10,
12516      wobbleSpeed: Math.min(0.11, Math.random() * 0.1 + 0.05),
12517      velocity: opts.startVelocity * 0.5 + Math.random() * opts.startVelocity,
12518      angle2D: -radAngle + (0.5 * radSpread - Math.random() * radSpread),
12519      tiltAngle: (Math.random() * (0.75 - 0.25) + 0.25) * Math.PI,
12520      color: opts.color,
12521      shape: opts.shape,
12522      tick: 0,
12523      totalTicks: opts.ticks,
12524      decay: opts.decay,
12525      drift: opts.drift,
12526      random: Math.random() + 2,
12527      tiltSin: 0,
12528      tiltCos: 0,
12529      wobbleX: 0,
12530      wobbleY: 0,
12531      gravity: opts.gravity * 3,
12532      ovalScalar: 0.6,
12533      scalar: opts.scalar,
12534      flat: opts.flat
12535    };
12536  }
12537  function updateFetti(context, fetti) {
12538    fetti.x += Math.cos(fetti.angle2D) * fetti.velocity + fetti.drift;
12539    fetti.y += Math.sin(fetti.angle2D) * fetti.velocity + fetti.gravity;
12540    fetti.velocity *= fetti.decay;
12541    if (fetti.flat) {
12542      fetti.wobble = 0;
12543      fetti.wobbleX = fetti.x + 10 * fetti.scalar;
12544      fetti.wobbleY = fetti.y + 10 * fetti.scalar;
12545      fetti.tiltSin = 0;
12546      fetti.tiltCos = 0;
12547      fetti.random = 1;
12548    } else {
12549      fetti.wobble += fetti.wobbleSpeed;
12550      fetti.wobbleX = fetti.x + 10 * fetti.scalar * Math.cos(fetti.wobble);
12551      fetti.wobbleY = fetti.y + 10 * fetti.scalar * Math.sin(fetti.wobble);
12552      fetti.tiltAngle += 0.1;
12553      fetti.tiltSin = Math.sin(fetti.tiltAngle);
12554      fetti.tiltCos = Math.cos(fetti.tiltAngle);
12555      fetti.random = Math.random() + 2;
12556    }
12557    var progress = fetti.tick++ / fetti.totalTicks;
12558    var x1 = fetti.x + fetti.random * fetti.tiltCos;
12559    var y1 = fetti.y + fetti.random * fetti.tiltSin;
12560    var x2 = fetti.wobbleX + fetti.random * fetti.tiltCos;
12561    var y2 = fetti.wobbleY + fetti.random * fetti.tiltSin;
12562    context.fillStyle = "rgba(" + fetti.color.r + ", " + fetti.color.g + ", " + fetti.color.b + ", " + (1 - progress) + ")";
12563    context.beginPath();
12564    if (canUsePaths && fetti.shape.type === "path" && typeof fetti.shape.path === "string" && Array.isArray(fetti.shape.matrix)) {
12565      context.fill(transformPath2D(
12566        fetti.shape.path,
12567        fetti.shape.matrix,
12568        fetti.x,
12569        fetti.y,
12570        Math.abs(x2 - x1) * 0.1,
12571        Math.abs(y2 - y1) * 0.1,
12572        Math.PI / 10 * fetti.wobble
12573      ));
12574    } else if (fetti.shape.type === "bitmap") {
12575      var rotation = Math.PI / 10 * fetti.wobble;
12576      var scaleX = Math.abs(x2 - x1) * 0.1;
12577      var scaleY = Math.abs(y2 - y1) * 0.1;
12578      var width = fetti.shape.bitmap.width * fetti.scalar;
12579      var height = fetti.shape.bitmap.height * fetti.scalar;
12580      var matrix = new DOMMatrix([
vendor: 8,449 bytes, lines 12581-12830
12581        Math.cos(rotation) * scaleX,
12582        Math.sin(rotation) * scaleX,
12583        -Math.sin(rotation) * scaleY,
12584        Math.cos(rotation) * scaleY,
12585        fetti.x,
12586        fetti.y
12587      ]);
12588      matrix.multiplySelf(new DOMMatrix(fetti.shape.matrix));
12589      var pattern = context.createPattern(bitmapMapper.transform(fetti.shape.bitmap), "no-repeat");
12590      pattern.setTransform(matrix);
12591      context.globalAlpha = 1 - progress;
12592      context.fillStyle = pattern;
12593      context.fillRect(
12594        fetti.x - width / 2,
12595        fetti.y - height / 2,
12596        width,
12597        height
12598      );
12599      context.globalAlpha = 1;
12600    } else if (fetti.shape === "circle") {
12601      context.ellipse ? context.ellipse(fetti.x, fetti.y, Math.abs(x2 - x1) * fetti.ovalScalar, Math.abs(y2 - y1) * fetti.ovalScalar, Math.PI / 10 * fetti.wobble, 0, 2 * Math.PI) : ellipse(context, fetti.x, fetti.y, Math.abs(x2 - x1) * fetti.ovalScalar, Math.abs(y2 - y1) * fetti.ovalScalar, Math.PI / 10 * fetti.wobble, 0, 2 * Math.PI);
12602    } else if (fetti.shape === "star") {
12603      var rot = Math.PI / 2 * 3;
12604      var innerRadius = 4 * fetti.scalar;
12605      var outerRadius = 8 * fetti.scalar;
12606      var x = fetti.x;
12607      var y = fetti.y;
12608      var spikes = 5;
12609      var step = Math.PI / spikes;
12610      while (spikes--) {
12611        x = fetti.x + Math.cos(rot) * outerRadius;
12612        y = fetti.y + Math.sin(rot) * outerRadius;
12613        context.lineTo(x, y);
12614        rot += step;
12615        x = fetti.x + Math.cos(rot) * innerRadius;
12616        y = fetti.y + Math.sin(rot) * innerRadius;
12617        context.lineTo(x, y);
12618        rot += step;
12619      }
12620    } else {
12621      context.moveTo(Math.floor(fetti.x), Math.floor(fetti.y));
12622      context.lineTo(Math.floor(fetti.wobbleX), Math.floor(y1));
12623      context.lineTo(Math.floor(x2), Math.floor(y2));
12624      context.lineTo(Math.floor(x1), Math.floor(fetti.wobbleY));
12625    }
12626    context.closePath();
12627    context.fill();
12628    return fetti.tick < fetti.totalTicks;
12629  }
12630  function animate(canvas, fettis, resizer, size2, done) {
12631    var animatingFettis = fettis.slice();
12632    var context = canvas.getContext("2d");
12633    var animationFrame;
12634    var destroy;
12635    var prom = promise(function(resolve) {
12636      function onDone() {
12637        animationFrame = destroy = null;
12638        context.clearRect(0, 0, size2.width, size2.height);
12639        bitmapMapper.clear();
12640        done();
12641        resolve();
12642      }
12643      function update() {
12644        if (isWorker && !(size2.width === workerSize.width && size2.height === workerSize.height)) {
12645          size2.width = canvas.width = workerSize.width;
12646          size2.height = canvas.height = workerSize.height;
12647        }
12648        if (!size2.width && !size2.height) {
12649          resizer(canvas);
12650          size2.width = canvas.width;
12651          size2.height = canvas.height;
12652        }
12653        context.clearRect(0, 0, size2.width, size2.height);
12654        animatingFettis = animatingFettis.filter(function(fetti) {
12655          return updateFetti(context, fetti);
12656        });
12657        if (animatingFettis.length) {
12658          animationFrame = raf.frame(update);
12659        } else {
12660          onDone();
12661        }
12662      }
12663      animationFrame = raf.frame(update);
12664      destroy = onDone;
12665    });
12666    return {
12667      addFettis: function(fettis2) {
12668        animatingFettis = animatingFettis.concat(fettis2);
12669        return prom;
12670      },
12671      canvas,
12672      promise: prom,
12673      reset: function() {
12674        if (animationFrame) {
12675          raf.cancel(animationFrame);
12676        }
12677        if (destroy) {
12678          destroy();
12679        }
12680      }
12681    };
12682  }
12683  function confettiCannon(canvas, globalOpts) {
12684    var isLibCanvas = !canvas;
12685    var allowResize = !!prop(globalOpts || {}, "resize");
12686    var hasResizeEventRegistered = false;
12687    var globalDisableForReducedMotion = prop(globalOpts, "disableForReducedMotion", Boolean);
12688    var shouldUseWorker = canUseWorker && !!prop(globalOpts || {}, "useWorker");
12689    var worker = shouldUseWorker ? getWorker() : null;
12690    var resizer = isLibCanvas ? setCanvasWindowSize : setCanvasRectSize;
12691    var initialized = canvas && worker ? !!canvas.__confetti_initialized : false;
12692    var preferLessMotion = typeof matchMedia === "function" && matchMedia("(prefers-reduced-motion)").matches;
12693    var animationObj;
12694    function fireLocal(options, size2, done) {
12695      var particleCount = prop(options, "particleCount", onlyPositiveInt);
12696      var angle = prop(options, "angle", Number);
12697      var spread = prop(options, "spread", Number);
12698      var startVelocity = prop(options, "startVelocity", Number);
12699      var decay = prop(options, "decay", Number);
12700      var gravity = prop(options, "gravity", Number);
12701      var drift = prop(options, "drift", Number);
12702      var colors = prop(options, "colors", colorsToRgb);
12703      var ticks = prop(options, "ticks", Number);
12704      var shapes = prop(options, "shapes");
12705      var scalar = prop(options, "scalar");
12706      var flat = !!prop(options, "flat");
12707      var origin = getOrigin(options);
12708      var temp = particleCount;
12709      var fettis = [];
12710      var startX = canvas.width * origin.x;
12711      var startY = canvas.height * origin.y;
12712      while (temp--) {
12713        fettis.push(
12714          randomPhysics({
12715            x: startX,
12716            y: startY,
12717            angle,
12718            spread,
12719            startVelocity,
12720            color: colors[temp % colors.length],
12721            shape: shapes[randomInt(0, shapes.length)],
12722            ticks,
12723            decay,
12724            gravity,
12725            drift,
12726            scalar,
12727            flat
12728          })
12729        );
12730      }
12731      if (animationObj) {
12732        return animationObj.addFettis(fettis);
12733      }
12734      animationObj = animate(canvas, fettis, resizer, size2, done);
12735      return animationObj.promise;
12736    }
12737    function fire(options) {
12738      var disableForReducedMotion = globalDisableForReducedMotion || prop(options, "disableForReducedMotion", Boolean);
12739      var zIndex = prop(options, "zIndex", Number);
12740      if (disableForReducedMotion && preferLessMotion) {
12741        return promise(function(resolve) {
12742          resolve();
12743        });
12744      }
12745      if (isLibCanvas && animationObj) {
12746        canvas = animationObj.canvas;
12747      } else if (isLibCanvas && !canvas) {
12748        canvas = getCanvas(zIndex);
12749        document.body.appendChild(canvas);
12750      }
12751      if (allowResize && !initialized) {
12752        resizer(canvas);
12753      }
12754      var size2 = {
12755        width: canvas.width,
12756        height: canvas.height
12757      };
12758      if (worker && !initialized) {
12759        worker.init(canvas);
12760      }
12761      initialized = true;
12762      if (worker) {
12763        canvas.__confetti_initialized = true;
12764      }
12765      function onResize() {
12766        if (worker) {
12767          var obj = {
12768            getBoundingClientRect: function() {
12769              if (!isLibCanvas) {
12770                return canvas.getBoundingClientRect();
12771              }
12772            }
12773          };
12774          resizer(obj);
12775          worker.postMessage({
12776            resize: {
12777              width: obj.width,
12778              height: obj.height
12779            }
12780          });
12781          return;
12782        }
12783        size2.width = size2.height = null;
12784      }
12785      function done() {
12786        animationObj = null;
12787        if (allowResize) {
12788          hasResizeEventRegistered = false;
12789          global.removeEventListener("resize", onResize);
12790        }
12791        if (isLibCanvas && canvas) {
12792          if (document.body.contains(canvas)) {
12793            document.body.removeChild(canvas);
12794          }
12795          canvas = null;
12796          initialized = false;
12797        }
12798      }
12799      if (allowResize && !hasResizeEventRegistered) {
12800        hasResizeEventRegistered = true;
12801        global.addEventListener("resize", onResize, false);
12802      }
12803      if (worker) {
12804        return worker.fire(options, size2, done);
12805      }
12806      return fireLocal(options, size2, done);
12807    }
12808    fire.reset = function() {
12809      if (worker) {
12810        worker.reset();
12811      }
12812      if (animationObj) {
12813        animationObj.reset();
12814      }
12815    };
12816    return fire;
12817  }
12818  var defaultFire;
12819  function getDefaultFire() {
12820    if (!defaultFire) {
12821      defaultFire = confettiCannon(null, { useWorker: true, resize: true });
12822    }
12823    return defaultFire;
12824  }
12825  function transformPath2D(pathString, pathMatrix, x, y, scaleX, scaleY, rotation) {
12826    var path2d = new Path2D(pathString);
12827    var t1 = new Path2D();
12828    t1.addPath(path2d, new DOMMatrix(pathMatrix));
12829    var t2 = new Path2D();
12830    t2.addPath(t1, new DOMMatrix([
12831      Math.cos(rotation) * scaleX,
12832      Math.sin(rotation) * scaleX,
12833      -Math.sin(rotation) * scaleY,
12834      Math.cos(rotation) * scaleY,
12835      x,
12836      y
12837    ]));
12838    return t2;
12839  }
12840  function shapeFromPath(pathData) {
12841    if (!canUsePaths) {
12842      throw new Error("path confetti are not supported in this browser");
12843    }
12844    var path, matrix;
12845    if (typeof pathData === "string") {
12846      path = pathData;
12847    } else {
12848      path = pathData.path;
12849      matrix = pathData.matrix;
12850    }
12851    var path2d = new Path2D(path);
12852    var tempCanvas = document.createElement("canvas");
12853    var tempCtx = tempCanvas.getContext("2d");
12854    if (!matrix) {
12855      var maxSize = 1e3;
12856      var minX = maxSize;
12857      var minY = maxSize;
12858      var maxX = 0;
12859      var maxY = 0;
12860      var width, height;
12861      for (var x = 0; x < maxSize; x += 2) {
12862        for (var y = 0; y < maxSize; y += 2) {
12863          if (tempCtx.isPointInPath(path2d, x, y, "nonzero")) {
12864            minX = Math.min(minX, x);
12865            minY = Math.min(minY, y);
12866            maxX = Math.max(maxX, x);
12867            maxY = Math.max(maxY, y);
12868          }
12869        }
12870      }
12871      width = maxX - minX;
12872      height = maxY - minY;
12873      var maxDesiredSize = 10;
12874      var scale = Math.min(maxDesiredSize / width, maxDesiredSize / height);
12875      matrix = [
12876        scale,
12877        0,
12878        0,
12879        scale,
12880        -Math.round(width / 2 + minX) * scale,
12881        -Math.round(height / 2 + minY) * scale
12882      ];
12883    }
12884    return {
12885      type: "path",
12886      path,
12887      matrix
12888    };
12889  }
12890  function shapeFromText(textData) {
12891    var text, scalar = 1, color = "#000000", fontFamily = '"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji", "EmojiOne Color", "Android Emoji", "Twemoji Mozilla", "system emoji", sans-serif';
12892    if (typeof textData === "string") {
12893      text = textData;
12894    } else {
12895      text = textData.text;
12896      scalar = "scalar" in textData ? textData.scalar : scalar;
12897      fontFamily = "fontFamily" in textData ? textData.fontFamily : fontFamily;
12898      color = "color" in textData ? textData.color : color;
12899    }
12900    var fontSize = 10 * scalar;
12901    var font = "" + fontSize + "px " + fontFamily;
12902    var canvas = new OffscreenCanvas(fontSize, fontSize);
12903    var ctx = canvas.getContext("2d");
12904    ctx.font = font;
12905    var size2 = ctx.measureText(text);
12906    var width = Math.ceil(size2.actualBoundingBoxRight + size2.actualBoundingBoxLeft);
12907    var height = Math.ceil(size2.actualBoundingBoxAscent + size2.actualBoundingBoxDescent);
12908    var padding = 2;
12909    var x = size2.actualBoundingBoxLeft + padding;
12910    var y = size2.actualBoundingBoxAscent + padding;
12911    width += padding + padding;
12912    height += padding + padding;
12913    canvas = new OffscreenCanvas(width, height);
12914    ctx = canvas.getContext("2d");
12915    ctx.font = font;
12916    ctx.fillStyle = color;
12917    ctx.fillText(text, x, y);
12918    var scale = 1 / scalar;
12919    return {
12920      type: "bitmap",
12921      // TODO these probably need to be transfered for workers
12922      bitmap: canvas.transferToImageBitmap(),
12923      matrix: [scale, 0, 0, scale, -width * scale / 2, -height * scale / 2]
12924    };
12925  }
12926  module2.exports = function() {
12927    return getDefaultFire().apply(this, arguments);
12928  };
12929  module2.exports.reset = function() {
12930    getDefaultFire().reset();
12931  };
12932  module2.exports.create = confettiCannon;
12933  module2.exports.shapeFromPath = shapeFromPath;
12934  module2.exports.shapeFromText = shapeFromText;
12935})(function() {
12936  if (typeof window !== "undefined") {
12937    return window;
12938  }
12939  if (typeof self !== "undefined") {
12940    return self;
12941  }
12942  return this || {};
12943}(), module, false);
12944const confetti = module.exports;
12945module.exports.create;
12946const FIRST_PUBLISH_CELEBRATION_STATUS = gql`
12947  query FirstPublishCelebrationStatus {
12948    firstPublishCelebrationStatus {
12949      shouldShow
12950      websiteId
12951      liveUrl
12952    }
12953  }
12954`;
12955const MARK_TRUSTPILOT_REVIEW_PROMPT_SEEN = gql`
12956  mutation MarkTrustpilotReviewPromptSeen {
12957    markTrustpilotReviewPromptSeen
12958  }
12959`;
12960const TRUSTPILOT_REVIEW_URL = "https://www.trustpilot.com/evaluate/landingsite.ai";
12961const ANALYTICS_PROPS = {
12962  trigger: "first_publish"
12963};
12964const FirstPublishCelebration = ({
12965  websiteId,
12966  publishCompletedSignal
12967}) => {
12968  const posthog = usePostHog();
12969  const [open, setOpen] = reactExports.useState(false);
12970  const armedRef = reactExports.useRef(false);
12971  const clickedRef = reactExports.useRef(false);
12972  const dismissedRef = reactExports.useRef(false);
12973  const prevSignalRef = reactExports.useRef(publishCompletedSignal);
12974  const [markSeen] = useMutation$1(MARK_TRUSTPILOT_REVIEW_PROMPT_SEEN);
12975  const {
12976    data,
12977    refetch
12978  }
12978 = useQuery$1(FIRST_PUBLISH_CELEBRATION_STATUS, {
12979    fetchPolicy: "network-only"
12980  });
12981  reactExports.useEffect(() => {
12982    if (publishCompletedSignal !== void 0 && publishCompletedSignal !== prevSignalRef.current) {
12983      prevSignalRef.current = publishCompletedSignal;
12984      refetch().catch(() => {
12985      });
12986    }
12987  }, [publishCompletedSignal, refetch]);
12988  const status = data == null ? void 0 : data.firstPublishCelebrationStatus;
12989  reactExports.useEffect(() => {
12990    var _a;
12991    if ((status == null ? void 0 : status.shouldShow) !== true) return;
12992    if (status.websiteId !== websiteId) return;
12993    if (armedRef.current) return;
12994    armedRef.current = true;
12995    setOpen(true);
12996    try {
12997      const prefersReducedMotion = typeof window !== "undefined" && ((_a = window.matchMedia) == null ? void 0 : _a.call(window, "(prefers-reduced-motion: reduce)").matches);
12998      if (!prefersReducedMotion) {
12999        confetti({
13000          particleCount: 150,
13001          spread: 90,
13002          origin: {
13003            y: 0.6
13004          },
13005          zIndex: 100
13006        });
13007      }
13008    } catch {
13009    }
13010    markSeen().then((result) => {
13011      var _a2;
13012      if (((_a2 = result == null ? void 0 : result.data) == null ? void 0 : _a2.markTrustpilotReviewPromptSeen) === true) {
13013        posthog == null ? void 0 : posthog.capture("Trustpilot Prompt Shown", ANALYTICS_PROPS);
13014      }
13015    }).catch(() => {
13016    });
13017  }, [status, websiteId, markSeen, posthog]);
13018  const handleDismiss = () => {
13019    if (!clickedRef.current && !dismissedRef.current) {
13020      dismissedRef.current = true;
13021      posthog == null ? void 0 : posthog.capture("Trustpilot Prompt Dismissed", ANALYTICS_PROPS);
13022    }
13023    setOpen(false);
13024  };
13025  const handleOpenChange = (nextOpen) => {
13026    if (!nextOpen) handleDismiss();
13027  };
13028  if (!open) return null;
13029  const liveUrl = (status == null ? void 0 : status.liveUrl) ?? null;
13030  return /* @__PURE__ */ jsxRuntimeExports.jsx(Dialog, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogContent, { className: "max-w-md", children: [
13031    /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogHeader, { children: [
13032      /* @__PURE__ */ jsxRuntimeExports.jsx(DialogTitle, { className: "text-center text-2xl", children: "🎉 Your site is live!" }),
13033      liveUrl && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "pt-2 text-center text-sm text-muted-foreground", children: [
13034        "Check it out at",
13035        " ",
13036        /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: liveUrl, target: "_blank", rel: "noopener noreferrer", className: "font-medium text-primary underline underline-offset-4 hover:opacity-80", children: liveUrl.replace(/^https?:\/\//, "") })
13037      ] }),
13038      /* @__PURE__ */ jsxRuntimeExports.jsx(DialogDescription, { className: "pt-2 text-center", children: "Did you have fun building it? We'd love it if you shared your experience on Trustpilot — it helps other small businesses find us." })
13039    ] }),
13040    /* @__PURE__ */ jsxRuntimeExports.jsxs(DialogFooter, { className: "gap-2 sm:justify-center", children: [
13041      /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { variant: "outline", onClick: handleDismiss, children: "Not now" }),
13042      /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: TRUSTPILOT_REVIEW_URL, target: "_blank", rel: "noopener noreferrer", onClick: () => {
13043        if (!clickedRef.current) {
13044          clickedRef.current = true;
13045          posthog == null ? void 0 : posthog.capture("Trustpilot Prompt Clicked", ANALYTICS_PROPS);
13046        }
13047      }, children: "Leave a review" }) })
13048    ] })
13049  ] }) });
13050};
13051const buildPreWarmUrl = (baseUrl) => {
13052  return baseUrl.replace(/\/$/, "");
13053};
13054const BUILD_STEPS = [{
13055  label: "Designing your logo",
13056  icon: Palette,
13057  startAt: 0
13058}, {
13059  label: "Choosing your colors & fonts",
13060  icon: Type,
13061  startAt: 8
13062}, {
13063  label: "Finding the perfect images",
13064  icon: Image,
13065  startAt: 18
13066}, {
13067  label: "Planning your pages",
13068  icon: LayoutTemplate,
13069  startAt: 30
13070}, {
13071  label: "Preparing your site",
13072  icon: Sparkles,
13073  startAt: 42
13074}];
13075const SpinnerIcon = () => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative mx-auto h-20 w-20", children: [
13076  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute inset-0 rounded-full border-4 border-gray-200" }),
13077  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute inset-0 animate-spin rounded-full border-4 border-transparent border-t-blue-500" }),
13078  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute inset-2 animate-spin rounded-full border-4 border-transparent border-b-purple-500", style: {
13079    animationDirection: "reverse",
13080    animationDuration: "1.5s"
13081  } }),
13082  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { className: "h-8 w-8 text-blue-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" }) }) })
13083] });
13084const StepIndicator = ({
13085  steps,
13086  activeIndex
13087}) => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-10 w-full max-w-sm space-y-3", children: steps.map((step, i) => {
13088  const isCompleted = i < activeIndex;
13089  const isActive = i === activeIndex;
13090  const isPending = i > activeIndex;
13091  const Icon = step.icon;
13092  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `flex items-center gap-3 transition-all duration-500 ${isPending ? "opacity-40" : "opacity-100"}`, children: [
13093    /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full transition-all duration-500 ${isCompleted ? "bg-green-100 text-green-600" : isActive ? "bg-blue-100 text-blue-600" : "bg-gray-100 text-gray-400"}`, children: isCompleted ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "h-4 w-4" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Icon, { className: `h-4 w-4 ${isActive ? "animate-pulse" : ""}` }) }),
13094    /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: `text-sm transition-all duration-500 ${isCompleted ? "text-green-700" : isActive ? "font-medium text-gray-900" : "text-gray-400"}`, children: [
13095      step.label,
13096      isActive && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ml-1 inline-flex", children: [
13097        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "animate-bounce text-gray-400", style: {
13098          animationDelay: "0ms"
13099        }, children: "." }),
13100        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "animate-bounce text-gray-400", style: {
13101          animationDelay: "150ms"
13102        }, children: "." }),
13103        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "animate-bounce text-gray-400", style: {
13104          animationDelay: "300ms"
13105        }, children: "." })
13106      ] })
13107    ] })
13108  ] }, step.label);
13109}) });
13110const ReactWebsiteLoadingScreen = ({
13111  businessName,
13112  previewUrl,
13113  containerStatus,
13114  footer
13115}) => {
13116  const isWaitingForContainer = typeof containerStatus === "string" && containerStatus.length > 0;
13117  const [elapsedSeconds, setElapsedSeconds] = reactExports.useState(0);
13118  const preWarmAttemptedRef = reactExports.useRef(false);
13119  const mountTimeRef = reactExports.useRef(Date.now());
13120  reactExports.useEffect(() => {
13121    if (!previewUrl || preWarmAttemptedRef.current) return;
13122    preWarmAttemptedRef.current = true;
13123    const preWarmUrl = buildPreWarmUrl(previewUrl);
13124    const MAX_RETRIES = 3;
13125    const RETRY_DELAY_MS = 2e3;
13126    let cancelled = false;
13127    const attempt = async (retryCount) => {
13128      const sinceMountMs = Date.now() - mountTimeRef.current;
13129      console.log("[PreWarm] Starting container pre-warm", {
13130        timestamp: (/* @__PURE__ */ new Date()).toISOString(),
13131        localTime: (/* @__PURE__ */ new Date()).toLocaleTimeString(),
13132        sinceMountMs,
13133        previewUrl,
13134        attempt: retryCount + 1
13135      });
13136      try {
13137        const response = await fetch(preWarmUrl);
13138        const elapsed = Date.now() - mountTimeRef.current;
13139        console.log("[PreWarm] Container pre-warm response received", {
13140          timestamp: (/* @__PURE__ */ new Date()).toISOString(),
13141          localTime: (/* @__PURE__ */ new Date()).toLocaleTimeString(),
13142          sinceMountMs: elapsed,
13143          status: response.status,
13144          statusText: response.statusText,
13145          attempt: retryCount + 1
13146        });
13147        if (response.status >= 500 && retryCount < MAX_RETRIES && !cancelled) {
13148          console.log(`[PreWarm] Got ${response.status}, retrying in ${RETRY_DELAY_MS}ms...`);
13149          await new Promise((r) => setTimeout(r, RETRY_DELAY_MS));
13150          if (!cancelled) await attempt(retryCount + 1);
13151        }
13152      } catch (error) {
13153        const elapsed = Date.now() - mountTimeRef.current;
13154        console.log("[PreWarm] Container pre-warm request failed (may be CORS)", {
13155          timestamp: (/* @__PURE__ */ new Date()).toISOString(),
13156          localTime: (/* @__PURE__ */ new Date()).toLocaleTimeString(),
13157          sinceMountMs: elapsed,
13158          error: error instanceof Error ? error.message : String(error),
13159          attempt: retryCount + 1
13160        });
13161        if (retryCount < MAX_RETRIES && !cancelled) {
13162          console.log(`[PreWarm] Retrying in ${RETRY_DELAY_MS}ms...`);
13163          await new Promise((r) => setTimeout(r, RETRY_DELAY_MS));
13164          if (!cancelled) await attempt(retryCount + 1);
13165        }
13166      }
13167    };
13168    attempt(0);
13169    return () => {
13170      cancelled = true;
13171    };
13172  }, [previewUrl]);
13173  reactExports.useEffect(() => {
13174    const interval = setInterval(() => {
13175      setElapsedSeconds((prev) => prev + 1);
13176    }, 1e3);
13177    return () => clearInterval(interval);
13178  }, []);
13179  const activeStepIndex = BUILD_STEPS.reduce((idx, step, i) => {
13180    return elapsedSeconds >= step.startAt ? i : idx;
13181  }, 0);
13182  const displayStepIndex = isWaitingForContainer && activeStepIndex >= BUILD_STEPS.length - 1 ? BUILD_STEPS.length : activeStepIndex;
13183  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex min-h-screen w-full flex-col items-center justify-center bg-gray-50", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center px-6 text-center", children: [
13184    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-8 flex items-center gap-2", children: [
13185      /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: "/logo-paper-plane.png", alt: "Landingsite", className: "h-5 w-auto" }),
13186      /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xl font-semibold tracking-tight text-gray-800", children: "Landingsite" })
13187    ] }),
13188    /* @__PURE__ */ jsxRuntimeExports.jsx(SpinnerIcon, {}),
13189    /* @__PURE__ */ jsxRuntimeExports.jsx("h1", { className: "mt-8 text-center text-2xl font-bold text-gray-900 sm:text-3xl", children: businessName ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
13190      "Building",
13191      " ",
13192      /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-blue-600", children: businessName })
13193    ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: "Building Your Website" }) }),
13194    /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mx-auto mt-3 max-w-md text-gray-500", children: isWaitingForContainer ? "Putting it all together..." : "Our AI is crafting your custom website. This will only take a moment." }),
13195    /* @__PURE__ */ jsxRuntimeExports.jsx(StepIndicator, { steps: BUILD_STEPS, activeIndex: displayStepIndex }),
13196    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-8 flex justify-center gap-2", children: [
13197      /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "h-2 w-2 animate-bounce rounded-full bg-blue-500", style: {
13198        animationDelay: "0ms"
13199      } }),
13200      /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "h-2 w-2 animate-bounce rounded-full bg-purple-500", style: {
13201        animationDelay: "150ms"
13202      } }),
13203      /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "h-2 w-2 animate-bounce rounded-full bg-blue-500", style: {
13204        animationDelay: "300ms"
13205      } })
13206    ] }),
13207    footer
13208  ] }) });
13209};
13210const LONG_FRAME_MIN_MS = 200;
13211const MAX_EVENTS_PER_PAGE = 20;
13212const MIN_GAP_MS = 3e3;
13213function summarizeLongFrame(entry, mountedAt) {
13214  const allScripts = entry.scripts || [];
13215  const scripts = allScripts.filter((s) => (s.duration ?? 0) >= 5).sort((a, b) => (b.duration ?? 0) - (a.duration ?? 0)).slice(0, 3);
13216  return {
13217    frame_ms: Math.round(entry.duration),
13218    blocking_ms: Math.round(entry.blockingDuration ?? 0),
13219    style_layout_ms: Math.round(entry.styleAndLayoutDuration ?? 0),
13220    // Aggregates over ALL browser-reported scripts (vs the top-3 list
13221    // below). Note the LoAF API itself only reports scripts >5ms — the spec
13222    // (§3.2.2) appends a script entry only "if the duration ... is greater
13223    // than 5 milliseconds" — so these aggregates distinguish frames with
13224    // many moderate (>5ms) scripts beyond the top-3 list from frames with
13225    // genuinely zero reported scripts (GPU/presentation wait). Limitation:
13226    // a frame full of sub-5ms callbacks (e.g. rrweb per-mutation work) is
13227    // indistinguishable from a script-free frame in LoAF data; classifying
13228    // those needs a different instrument (an in-page profiling probe or an
13229    // on/off experiment).
13230    script_count: allScripts.length,
13231    script_total_ms: Math.round(allScripts.reduce((sum, s) => sum + (s.duration ?? 0), 0)),
13232    editor_age_ms: Math.max(0, Math.round(entry.startTime - mountedAt)),
13233    scripts: scripts.map((s) => ({
13234      src: (s.sourceURL || s.name || "unknown").slice(-120),
13235      fn: (s.sourceFunctionName || "").slice(0, 80),
13236      invoker: (s.invoker || "").slice(-120),
13237      invoker_type: s.invokerType || "",
13238      dur_ms: Math.round(s.duration ?? 0),
13239      forced_layout_ms: Math.round(s.forcedStyleAndLayoutDuration ?? 0)
13240    }))
13241  };
13242}
13243function pageContext() {
13244  try {
13245    return {
13246      chat_bubbles: document.querySelectorAll(".msg-row-enter").length,
13247      dom_nodes: document.getElementsByTagName("*").length
13248    };
13249  } catch {
13250    return {};
13251  }
13252}
13253function startLongFrameTelemetry(capture, websiteId) {
13254  const mountedAt = performance.now();
13255  let sent = 0;
13256  let lastSentAt = -Infinity;
13257  let observer = null;
13258  try {
13259    observer = new PerformanceObserver((list) => {
13260      const longEntries = list.getEntries().filter((e) => e.duration >= LONG_FRAME_MIN_MS);
13261      if (longEntries.length === 0) return;
13262      const now = performance.now();
13263      if (sent >= MAX_EVENTS_PER_PAGE || now - lastSentAt < MIN_GAP_MS) {
13264        return;
13265      }
13266      const worst = longEntries.reduce((a, b) => b.duration > a.duration ? b : a);
13267      sent++;
13268      lastSentAt = now;
13269      capture("editor_long_frame", {
13270        websiteId,
13271        ...summarizeLongFrame(worst, mountedAt),
13272        ...pageContext()
13273      });
13274      if (sent >= MAX_EVENTS_PER_PAGE) {
13275        observer == null ? void 0 : observer.disconnect();
13276        observer = null;
13277      }
13278    });
13279    observer.observe({
13280      type: "long-animation-frame",
13281      buffered: true
13282    });
13283  } catch {
13284    observer = null;
13285  }
13286  return () => observer == null ? void 0 : observer.disconnect();
13287}
13288const DOCK_MIN = 320;
13289const DOCK_MAX = 720;
13290const DOCK_DEFAULT = 396;
13291const EditorLayout = ({
13292  navbar,
13293  chat,
13294  preview,
13295  merchantView,
13296  viewSwitcher,
13297  banner,
13298  websiteName,
13299  chatExpanded = true
13300}) => {
13301  const isDesktop = useBreakpoint("lg");
13302  const [dockWidth, setDockWidth] = reactExports.useState(DOCK_DEFAULT);
13303  const [dragging, setDragging] = reactExports.useState(false);
13304  const dragRef = reactExports.useRef(null);
13305  const handlePointerDown = (e) => {
13306    e.currentTarget.setPointerCapture(e.pointerId);
13307    dragRef.current = {
13308      startX: e.clientX,
13309      startWidth: dockWidth
13310    };
13311    setDragging(true);
13312  };
13313  const handlePointerMove = (e) => {
13314    const drag = dragRef.current;
13315    if (!drag) return;
13316    const dx = e.clientX - drag.startX;
13317    const next = drag.startWidth - dx;
13318    setDockWidth(Math.max(DOCK_MIN, Math.min(DOCK_MAX, next)));
13319  };
13320  const handlePointerUp = (e) => {
13321    if (e.currentTarget.hasPointerCapture(e.pointerId)) {
13322      e.currentTarget.releasePointerCapture(e.pointerId);
13323    }
13324    dragRef.current = null;
13325    setDragging(false);
13326  };
13327  const handleDoubleClick = () => setDockWidth(DOCK_DEFAULT);
13328  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex h-screen flex-col text-[#1B1A22]", style: {
13329    background: "radial-gradient(120% 90% at 82% -8%, #F3F1FB 0%, transparent 46%), radial-gradient(110% 80% at 6% 110%, #FDF1EC 0%, transparent 44%), #FBFAF8"
13330  }, children: [
13331    banner,
13332    /* @__PURE__ */ jsxRuntimeExports.jsx("header", { className: "z-20 px-4 py-1.5", children: navbar }),
13333    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative flex min-h-0 flex-1 flex-row-reverse items-stretch", children: [
13334      /* @__PURE__ */ jsxRuntimeExports.jsx("aside", { className: isDesktop ? "relative z-10 flex h-full flex-shrink-0 pb-3 pr-3" : `absolute inset-x-0 bottom-0 z-20 flex px-3 pb-3 ${chatExpanded ? "h-[75svh]" : "h-auto"}`, style: isDesktop ? {
13335        width: dockWidth
13336      } : void 0, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `flex h-full w-full flex-col overflow-hidden rounded-[16px] animate-in fade-in-0 duration-500 ease-out fill-mode-both ${isDesktop ? "border border-[#1B1A22]/[0.08] bg-white shadow-[0_28px_70px_-40px_rgba(27,26,34,0.40)] slide-in-from-right-4" : chatExpanded ? "border border-[#1B1A22]/[0.08] bg-white shadow-[0_-18px_50px_-30px_rgba(27,26,34,0.45)] slide-in-from-bottom-4" : "slide-in-from-bottom-4"}`, children: [
13337        isDesktop && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3 border-b border-[#1B1A22]/[0.06] px-5 py-4", children: [
13338          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "grid h-8 w-8 flex-shrink-0 place-items-center rounded-[12px] bg-[linear-gradient(135deg,#F4674E,#6E56CF)] text-white shadow-[0_6px_16px_-6px_rgba(110,86,207,0.6)]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Sparkles, { size: 15, strokeWidth: 2.25 }) }),
13339          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 flex-1 leading-tight", children: [
13340            /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "truncate text-[13.5px] font-semibold tracking-[-0.012em]", children: "Build with AI" }),
13341            /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "truncate text-[11.5px] text-[#6B6878]", children: [
13342              "Editing ",
13343              websiteName
13344            ] })
13345          ] }),
13346          viewSwitcher ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-shrink-0", children: viewSwitcher }) : null
13347        ] }),
13348        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-h-0 flex-1", children: chat })
13349      ] }) }),
13350      isDesktop && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "group flex w-3 flex-shrink-0 cursor-col-resize touch-none select-none items-center justify-center pb-3", role: "separator", "aria-orientation": "vertical", "aria-label": "Resize chat dock", "aria-valuenow": Math.round(dockWidth), "aria-valuemin": DOCK_MIN, "aria-valuemax": DOCK_MAX, onPointerDown: handlePointerDown, onPointerMove: handlePointerMove, onPointerUp: handlePointerUp, onPointerCancel: handlePointerUp, onDoubleClick: handleDoubleClick, children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `h-10 w-1 rounded-full transition-colors ${dragging ? "bg-[#1B1A22]/60" : "bg-[#1B1A22]/30 group-hover:bg-[#1B1A22]/50"}` }) }),
13351      /* @__PURE__ */ jsxRuntimeExports.jsxs("main", { className: `relative flex h-full min-w-0 flex-1 items-stretch justify-start ${isDesktop ? "pb-3 pl-3" : "px-3 pb-3"}`, children: [
13352        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { "aria-hidden": true, className: "pointer-events-none absolute inset-x-28 top-2 h-48 rounded-[100%] blur-[64px]", style: {
13353          background: "radial-gradient(closest-side, rgba(110,86,207,0.22), transparent)"
13354        } }),
13355        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative flex h-full w-full flex-col overflow-hidden rounded-[16px] border border-[#1B1A22]/[0.08] bg-white shadow-[0_40px_100px_-48px_rgba(27,26,34,0.46)] animate-in fade-in-0 zoom-in-95 duration-700 ease-out fill-mode-both", children: [
13356          /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-h-0 flex-1", style: merchantView ? {
13357            visibility: "hidden",
13358            pointerEvents: "none"
13359          } : void 0, children: preview }),
13360          merchantView && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute inset-0 overflow-y-auto bg-white", children: merchantView })
13361        ] })
13362      ] })
13363    ] })
13364  ] });
13365};
13366const GET_REACT_WEBSITE = {
13367  "kind": "Document",
13368  "definitions": [{
13369    "kind": "OperationDefinition",
13370    "operation": "query",
13371    "name": {
13372      "kind": "Name",
13373      "value": "GetReactWebsite"
13374    },
13375    "variableDefinitions": [{
13376      "kind": "VariableDefinition",
13377      "variable": {
13378        "kind": "Variable",
13379        "name": {
13380          "kind": "Name",
13381          "value": "id"
13382        }
13383      },
13384      "type": {
13385        "kind": "NonNullType",
13386        "type": {
13387          "kind": "NamedType",
13388          "name": {
13389            "kind": "Name",
13390            "value": "String"
13391          }
13392        }
13393      },
13394      "directives": []
13395    }],
13396    "directives": [],
13397    "selectionSet": {
13398      "kind": "SelectionSet",
13399      "selections": [{
13400        "kind": "Field",
13401        "name": {
13402          "kind": "Name",
13403          "value": "website"
13404        },
13405        "arguments": [{
13406          "kind": "Argument",
13407          "name": {
13408            "kind": "Name",
13409            "value": "id"
13410          },
13411          "value": {
13412            "kind": "Variable",
13413            "name": {
13414              "kind": "Name",
13415              "value": "id"
13416            }
13417          }
13418        }],
13419        "directives": [],
13420        "selectionSet": {
13421          "kind": "SelectionSet",
13422          "selections": [{
13423            "kind": "Field",
13424            "name": {
13425              "kind": "Name",
13426              "value": "__typename"
13427            },
13428            "arguments": [],
13429            "directives": []
13430          }, {
13431            "kind": "Field",
13432            "name": {
13433              "kind": "Name",
13434              "value": "id"
13435            },
13436            "arguments": [],
13437            "directives": []
13438          }, {
13439            "kind": "Field",
13440            "name": {
13441              "kind": "Name",
13442              "value": "name"
13443            },
13444            "arguments": [],
13445            "directives": []
13446          }, {
13447            "kind": "Field",
13448            "name": {
13449              "kind": "Name",
13450              "value": "url"
13451            },
13452            "arguments": [],
13453            "directives": []
13454          }, {
13455            "kind": "Field",
13456            "name": {
13457              "kind": "Name",
13458              "value": "publicId"
13459            },
13460            "arguments": [],
13461            "directives": []
13462          }, {
13463            "kind": "Field",
13464            "name": {
13465              "kind": "Name",
13466              "value": "businessName"
13467            },
13468            "arguments": [],
13469            "directives": []
13470          }, {
13471            "kind": "Field",
13472            "name": {
13473              "kind": "Name",
13474              "value": "businessAbout"
13475            },
13476            "arguments": [],
13477            "directives": []
13478          }, {
13479            "kind": "Field",
13480            "name": {
13481              "kind": "Name",
13482              "value": "websiteType"
13483            },
13484            "arguments": [],
13485            "directives": []
13486          }, {
13487            "kind": "Field",
13488            "name": {
13489              "kind": "Name",
13490              "value": "isFirstWebsite"
13491            },
13492            "arguments": [],
13493            "directives": []
13494          }, {
13495            "kind": "Field",
13496            "name": {
13497              "kind": "Name",
13498              "value": "createdAt"
13499            },
13500            "arguments": [],
13501            "directives": []
13502          }, {
13503            "kind": "Field",
13504            "name": {
13505              "kind": "Name",
13506              "value": "stripePlan"
13507            },
13508            "arguments": [],
13509            "directives": []
13510          }, {
13511            "kind": "Field",
13512            "name": {
13513              "kind": "Name",
13514              "value": "stripeIsAnnualPlan"
13515            },
13516            "arguments": [],
13517            "directives": []
13518          }, {
13519            "kind": "Field",
13520            "name": {
13521              "kind": "Name",
13522              "value": "paymentPastDue"
13523            },
13524            "arguments": [],
13525            "directives": []
13526          }, {
13527            "kind": "Field",
13528            "name": {
13529              "kind": "Name",
13530              "value": "pastDueInvoiceUrl"
13531            },
13532            "arguments": [],
13533            "directives": []
13534          }, {
13535            "kind": "Field",
13536            "name": {
13537              "kind": "Name",
13538              "value": "underReview"
13539            },
13540            "arguments": [],
13541            "directives": []
13542          }, {
13543            "kind": "Field",
13544            "name": {
13545              "kind": "Name",
13546              "value": "siteCaseNotice"
13547            },
13548            "arguments": [],
13549            "directives": [],
13550            "selectionSet": {
13551              "kind": "SelectionSet",
13552              "selections": [{
13553                "kind": "Field",
13554                "name": {
13555                  "kind": "Name",
13556                  "value": "type"
13557                },
13558                "arguments": [],
13559                "directives": []
13560              }, {
13561                "kind": "Field",
13562                "name": {
13563                  "kind": "Name",
13564                  "value": "brand"
13565                },
13566                "arguments": [],
13567                "directives": []
13568              }, {
13569                "kind": "Field",
13570                "name": {
13571                  "kind": "Name",
13572                  "value": "deadlineAt"
13573                },
13574                "arguments": [],
13575                "directives": []
13576              }, {
13577                "kind": "Field",
13578                "name": {
13579                  "kind": "Name",
13580                  "value": "paused"
13581                },
13582                "arguments": [],
13583                "directives": []
13584              }]
13585            }
13586          }, {
13587            "kind": "Field",
13588            "name": {
13589              "kind": "Name",
13590              "value": "analyticsId"
13591            },
13592            "arguments": [],
13593            "directives": []
13594          }, {
13595            "kind": "Field",
13596            "name": {
13597              "kind": "Name",
13598              "value": "updatedAt"
13599            },
13600            "arguments": [],
13601            "directives": []
13602          }, {
13603            "kind": "Field",
13604            "name": {
13605              "kind": "Name",
13606              "value": "publishingStatus"
13607            },
13608            "arguments": [],
13609            "directives": []
13610          }, {
13611            "kind": "Field",
13612            "name": {
13613              "kind": "Name",
13614              "value": "publishingStep"
13615            },
13616            "arguments": [],
13617            "directives": []
13618          }, {
13619            "kind": "Field",
13620            "name": {
13621              "kind": "Name",
13622              "value": "publishingProgress"
13623            },
13624            "arguments": [],
13625            "directives": []
13626          }, {
13627            "kind": "Field",
13628            "name": {
13629              "kind": "Name",
13630              "value": "startedPublishingAt"
13631            },
13632            "arguments": [],
13633            "directives": []
13634          }, {
13635            "kind": "Field",
13636            "name": {
13637              "kind": "Name",
13638              "value": "finishedPublishingAt"
13639            },
13640            "arguments": [],
13641            "directives": []
13642          }, {
13643            "kind": "Field",
13644            "name": {
13645              "kind": "Name",
13646              "value": "proPublishedAt"
13647            },
13648            "arguments": [],
13649            "directives": []
13650          }, {
13651            "kind": "Field",
13652            "name": {
13653              "kind": "Name",
13654              "value": "lastPublishedCheckpoint"
13655            },
13656            "arguments": [],
13657            "directives": []
13658          }, {
13659            "kind": "Field",
13660            "name": {
13661              "kind": "Name",
13662              "value": "lastPublishedCommitHash"
13663            },
13664            "arguments": [],
13665            "directives": []
13666          }, {
13667            "kind": "Field",
13668            "name": {
13669              "kind": "Name",
13670              "value": "aiChatMessagesUsed"
13671            },
13672            "arguments": [],
13673            "directives": []
13674          }, {
13675            "kind": "Field",
13676            "name": {
13677              "kind": "Name",
13678              "value": "chatMonthlyAllotment"
13679            },
13680            "arguments": [],
13681            "directives": []
13682          }, {
13683            "kind": "Field",
13684            "name": {
13685              "kind": "Name",
13686              "value": "chatMonthlyUsed"
13687            },
13688            "arguments": [],
13689            "directives": []
13690          }, {
13691            "kind": "Field",
13692            "name": {
13693              "kind": "Name",
13694              "value": "chatPurchasedCredits"
13695            },
13696            "arguments": [],
13697            "directives": []
13698          }, {
13699            "kind": "Field",
13700            "name": {
13701              "kind": "Name",
13702              "value": "chatQuotaCurrentPeriodStartAt"
13703            },
13704            "arguments": [],
13705            "directives": []
13706          }, {
13707            "kind": "Field",
13708            "name": {
13709              "kind": "Name",
13710              "value": "chatQuotaCurrentPeriodEndAt"
13711            },
13712            "arguments": [],
13713            "directives": []
13714          }, {
13715            "kind": "Field",
13716            "name": {
13717              "kind": "Name",
13718              "value": "relaceRepoId"
13719            },
13720            "arguments": [],
13721            "directives": []
13722          }, {
13723            "kind": "Field",
13724            "name": {
13725              "kind": "Name",
13726              "value": "cloudflareContainerUrl"
13727            },
13728            "arguments": [],
13729            "directives": []
13730          }, {
13731            "kind": "Field",
13732            "name": {
13733              "kind": "Name",
13734              "value": "aiHomepageCreationPrompt"
13735            },
13736            "arguments": [],
13737            "directives": []
13738          }, {
13739            "kind": "Field",
13740            "name": {
13741              "kind": "Name",
13742              "value": "hasSubmittedHomepageCreationMessage"
13743            },
13744            "arguments": [],
13745            "directives": []
13746          }, {
13747            "kind": "Field",
13748            "name": {
13749              "kind": "Name",
13750              "value": "startedGeneratingAt"
13751            },
13752            "arguments": [],
13753            "directives": []
13754          }, {
13755            "kind": "Field",
13756            "name": {
13757              "kind": "Name",
13758              "value": "finishedGeneratingAt"
13759            },
13760            "arguments": [],
13761            "directives": []
13762          }, {
13763            "kind": "Field",
13764            "name": {
13765              "kind": "Name",
13766              "value": "freePublishedAt"
13767            },
13768            "arguments": [],
13769            "directives": []
13770          }, {
13771            "kind": "Field",
13772            "name": {
13773              "kind": "Name",
13774              "value": "cloneStatus"
13775            },
13776            "arguments": [],
13777            "directives": []
13778          }, {
13779            "kind": "Field",
13780            "name": {
13781              "kind": "Name",
13782              "value": "homepageGeneratedAt"
13783            },
13784            "arguments": [],
13785            "directives": []
13786          }, {
13787            "kind": "Field",
13788            "name": {
13789              "kind": "Name",
13790              "value": "aifeaturesSiteToken"
13791            },
13792            "arguments": [],
13793            "directives": []
13794          }, {
13795            "kind": "Field",
13796            "name": {
13797              "kind": "Name",
13798              "value": "user"
13799            },
13800            "arguments": [],
13801            "directives": [],
13802            "selectionSet": {
13803              "kind": "SelectionSet",
13804              "selections": [{
13805                "kind": "Field",
13806                "name": {
13807                  "kind": "Name",
13808                  "value": "id"
13809                },
13810                "arguments": [],
13811                "directives": []
13812              }, {
13813                "kind": "Field",
13814                "name": {
13815                  "kind": "Name",
13816                  "value": "email"
13817                },
13818                "arguments": [],
13819                "directives": []
13820              }, {
13821                "kind": "Field",
13822                "name": {
13823                  "kind": "Name",
13824                  "value": "isAgencyPlan"
13825                },
13826                "arguments": [],
13827                "directives": []
13828              }, {
13829                "kind": "Field",
13830                "name": {
13831                  "kind": "Name",
13832                  "value": "agencyMonthlyCredits"
13833                },
13834                "arguments": [],
13835                "directives": []
13836              }, {
13837                "kind": "Field",
13838                "name": {
13839                  "kind": "Name",
13840                  "value": "agencyPaidCredits"
13841                },
13842                "arguments": [],
13843                "directives": []
13844              }, {
13845                "kind": "Field",
13846                "name": {
13847                  "kind": "Name",
13848                  "value": "agencyTotalCredits"
13849                },
13850                "arguments": [],
13851                "directives": []
13852              }, {
13853                "kind": "Field",
13854                "name": {
13855                  "kind": "Name",
13856                  "value": "merchantPaymentsBetaEnabled"
13857                },
13858                "arguments": [],
13859                "directives": []
13860              }]
13861            }
13862          }, {
13863            "kind": "Field",
13864            "name": {
13865              "kind": "Name",
13866              "value": "Domain"
13867            },
13868            "arguments": [],
13869            "directives": [],
13870            "selectionSet": {
13871              "kind": "SelectionSet",
13872              "selections": [{
13873                "kind": "Field",
13874                "name": {
13875                  "kind": "Name",
13876                  "value": "id"
13877                },
13878                "arguments": [],
13879                "directives": []
13880              }, {
13881                "kind": "Field",
13882                "name": {
13883                  "kind": "Name",
13884                  "value": "domainName"
13885                },
13886                "arguments": [],
13887                "directives": []
13888              }, {
13889                "kind": "Field",
13890                "name": {
13891                  "kind": "Name",
13892                  "value": "nameserverStatus"
13893                },
13894                "arguments": [],
13895                "directives": []
13896              }, {
13897                "kind": "Field",
13898                "name": {
13899                  "kind": "Name",
13900                  "value": "verificationStatus"
13901                },
13902                "arguments": [],
13903                "directives": []
13904              }, {
13905                "kind": "Field",
13906                "name": {
13907                  "kind": "Name",
13908                  "value": "configurationMethod"
13909                },
13910                "arguments": [],
13911                "directives": []
13912              }, {
13913                "kind": "Field",
13914                "name": {
13915                  "kind": "Name",
13916                  "value": "purchaseType"
13917                },
13918                "arguments": [],
13919                "directives": []
13920              }]
13921            }
13922          }, {
13923            "kind": "Field",
13924            "name": {
13925              "kind": "Name",
13926              "value": "reactWebsiteConfig"
13927            },
13928            "arguments": [],
13929            "directives": [],
13930            "selectionSet": {
13931              "kind": "SelectionSet",
13932              "selections": [{
13933                "kind": "Field",
13934                "name": {
13935                  "kind": "Name",
13936                  "value": "containerStatus"
13937                },
13938                "arguments": [],
13939                "directives": []
13940              }, {
13941                "kind": "Field",
13942                "name": {
13943                  "kind": "Name",
13944                  "value": "containerLastActive"
13945                },
13946                "arguments": [],
13947                "directives": []
13948              }, {
13949                "kind": "Field",
13950                "name": {
13951                  "kind": "Name",
13952                  "value": "containerErrorMessage"
13953                },
13954                "arguments": [],
13955                "directives": []
13956              }]
13957            }
13958          }]
13959        }
13960      }, {
13961        "kind": "Field",
13962        "name": {
13963          "kind": "Name",
13964          "value": "myWebsiteAccess"
13965        },
13966        "arguments": [{
13967          "kind": "Argument",
13968          "name": {
13969            "kind": "Name",
13970            "value": "websiteId"
13971          },
13972          "value": {
13973            "kind": "Variable",
13974            "name": {
13975              "kind": "Name",
13976              "value": "id"
13977            }
13978          }
13979        }],
13980        "directives": [],
13981        "selectionSet": {
13982          "kind": "SelectionSet",
13983          "selections": [{
13984            "kind": "Field",
13985            "name": {
13986              "kind": "Name",
13987              "value": "role"
13988            },
13989            "arguments": [],
13990            "directives": []
13991          }, {
13992            "kind": "Field",
13993            "name": {
13994              "kind": "Name",
13995              "value": "canEdit"
13996            },
13997            "arguments": [],
13998            "directives": []
13999          }]
14000        }
14001      }, {
14002        "kind": "Field",
14003        "alias": {
14004          "kind": "Name",
14005          "value": "pagesForToolbar"
14006        },
14007        "name": {
14008          "kind": "Name",
14009          "value": "pages"
14010        },
14011        "arguments": [{
14012          "kind": "Argument",
14013          "name": {
14014            "kind": "Name",
14015            "value": "websiteId"
14016          },
14017          "value": {
14018            "kind": "Variable",
14019            "name": {
14020              "kind": "Name",
14021              "value": "id"
14022            }
14023          }
14024        }],
14025        "directives": [],
14026        "selectionSet": {
14027          "kind": "SelectionSet",
14028          "selections": [{
14029            "kind": "Field",
14030            "name": {
14031              "kind": "Name",
14032              "value": "id"
14033            },
14034            "arguments": [],
14035            "directives": []
14036          }, {
14037            "kind": "Field",
14038            "name": {
14039              "kind": "Name",
14040              "value": "name"
14041            },
14042            "arguments": [],
14043            "directives": []
14044          }, {
14045            "kind": "Field",
14046            "name": {
14047              "kind": "Name",
14048              "value": "path"
14049            },
14050            "arguments": [],
14051            "directives": []
14052          }, {
14053            "kind": "Field",
14054            "name": {
14055              "kind": "Name",
14056              "value": "isHomepage"
14057            },
14058            "arguments": [],
14059            "directives": []
14060          }]
14061        }
14062      }]
14063    }
14064  }],
14065  "loc": {
14066    "start": 0,
14067    "end": 2339,
14068    "source": {
14069      "body": `
14070  query GetReactWebsite($id: String!) {
14071    website(id: $id) {
14072      __typename
14073      id
14074      name
14075      url
14076      publicId
14077      businessName
14078      businessAbout
14079      websiteType
14080      isFirstWebsite
14081      createdAt
14082      stripePlan
14083      stripeIsAnnualPlan
14084      paymentPastDue
14085      pastDueInvoiceUrl
14086      underReview
14087      siteCaseNotice {
14088        type
14089        brand
14090        deadlineAt
14091        paused
14092      }
14093      analyticsId
14094      updatedAt
14095      publishingStatus
14096      publishingStep
14097      publishingProgress
14098      startedPublishingAt
14099      finishedPublishingAt
14100      proPublishedAt
14101      lastPublishedCheckpoint
14102      lastPublishedCommitHash
14103      aiChatMessagesUsed
14104      chatMonthlyAllotment
14105      chatMonthlyUsed
14106      chatPurchasedCredits
14107      chatQuotaCurrentPeriodStartAt
14108      chatQuotaCurrentPeriodEndAt
14109      relaceRepoId
14110      cloudflareContainerUrl
14111      aiHomepageCreationPrompt
14112      hasSubmittedHomepageCreationMessage
14113      startedGeneratingAt
14114      finishedGeneratingAt
14115      # U3/R6. Read by the header's site picker, which falls back to this row
14116      # whenever the landingSites query does not contain this site (a support
14117      # session, or a deep link past the row cap). Without them the picker
14118      # reads a legacy free-published site as a Draft, and a clone in flight
14119      # as "Setting up" instead of "Copying".
14120      freePublishedAt
14121      cloneStatus
14122      homepageGeneratedAt
14123      aifeaturesSiteToken
14124      user {
14125        id
14126        email
14127        isAgencyPlan
14128        agencyMonthlyCredits
14129        agencyPaidCredits
14130        agencyTotalCredits
14131        # The website OWNER's beta flag — merchant views gate on the
14132        # owner's enrollment regardless of who is editing (the same fact
14133        # the sandbox preflight's businessToolsEnabled evaluates, so tool
14134        # gate and view gate stay coupled).
14135        merchantPaymentsBetaEnabled
14136      }
14137      Domain {
14138        id
14139        domainName
14140        nameserverStatus
14141        verificationStatus
14142        configurationMethod
14143        purchaseType
14144      }
14145      reactWebsiteConfig {
14146        containerStatus
14147        containerLastActive
14148        containerErrorMessage
14149      }
14150    }
14151    myWebsiteAccess(websiteId: $id) {
14152      role
14153      canEdit
14154    }
14155    pagesForToolbar: pages(websiteId: $id) {
14156      id
14157      name
14158      path
14159      isHomepage
14160    }
14161  }
14162`,
14163      "name": "GraphQL request",
14164      "locationOffset": {
14165        "line": 1,
14166        "column": 1
14167      }
14168    }
14169  }
14170};
14171const CLAIM_WEBSITE = {
14172  "kind": "Document",
14173  "definitions": [{
14174    "kind": "OperationDefinition",
14175    "operation": "mutation",
14176    "name": {
14177      "kind": "Name",
14178      "value": "ReactWebsiteChatPageClaimWebsiteMutation"
14179    },
14180    "variableDefinitions": [{
14181      "kind": "VariableDefinition",
14182      "variable": {
14183        "kind": "Variable",
14184        "name": {
14185          "kind": "Name",
14186          "value": "id"
14187        }
14188      },
14189      "type": {
14190        "kind": "NonNullType",
14191        "type": {
14192          "kind": "NamedType",
14193          "name": {
14194            "kind": "Name",
14195            "value": "String"
14196          }
14197        }
14198      },
14199      "directives": []
14200    }],
14201    "directives": [],
14202    "selectionSet": {
14203      "kind": "SelectionSet",
14204      "selections": [{
14205        "kind": "Field",
14206        "name": {
14207          "kind": "Name",
14208          "value": "claimWebsite"
14209        },
14210        "arguments": [{
14211          "kind": "Argument",
14212          "name": {
14213            "kind": "Name",
14214            "value": "id"
14215          },
14216          "value": {
14217            "kind": "Variable",
14218            "name": {
14219              "kind": "Name",
14220              "value": "id"
14221            }
14222          }
14223        }],
14224        "directives": [],
14225        "selectionSet": {
14226          "kind": "SelectionSet",
14227          "selections": [{
14228            "kind": "Field",
14229            "name": {
14230              "kind": "Name",
14231              "value": "id"
14232            },
14233            "arguments": [],
14234            "directives": []
14235          }]
14236        }
14237      }]
14238    }
14239  }],
14240  "loc": {
14241    "start": 0,
14242    "end": 116,
14243    "source": {
14244      "body": "\n  mutation ReactWebsiteChatPageClaimWebsiteMutation($id: String!) {\n    claimWebsite(id: $id) {\n      id\n    }\n  }\n",
14245      "name": "GraphQL request",
14246      "locationOffset": {
14247        "line": 1,
14248        "column": 1
14249      }
14250    }
14251  }
14252};
14253const ENSURE_HOMEPAGE_GENERATION = {
14254  "kind": "Document",
14255  "definitions": [{
14256    "kind": "OperationDefinition",
14257    "operation": "mutation",
14258    "name": {
14259      "kind": "Name",
14260      "value": "EnsureHomepageGenerationMutation"
14261    },
14262    "variableDefinitions": [{
14263      "kind": "VariableDefinition",
14264      "variable": {
14265        "kind": "Variable",
14266        "name": {
14267          "kind": "Name",
14268          "value": "id"
14269        }
14270      },
14271      "type": {
14272        "kind": "NonNullType",
14273        "type": {
14274          "kind": "NamedType",
14275          "name": {
14276            "kind": "Name",
14277            "value": "String"
14278          }
14279        }
14280      },
14281      "directives": []
14282    }],
14283    "directives": [],
14284    "selectionSet": {
14285      "kind": "SelectionSet",
14286      "selections": [{
14287        "kind": "Field",
14288        "name": {
14289          "kind": "Name",
14290          "value": "ensureHomepageGeneration"
14291        },
14292        "arguments": [{
14293          "kind": "Argument",
14294          "name": {
14295            "kind": "Name",
14296            "value": "id"
14297          },
14298          "value": {
14299            "kind": "Variable",
14300            "name": {
14301              "kind": "Name",
14302              "value": "id"
14303            }
14304          }
14305        }],
14306        "directives": [],
14307        "selectionSet": {
14308          "kind": "SelectionSet",
14309          "selections": [{
14310            "kind": "Field",
14311            "name": {
14312              "kind": "Name",
14313              "value": "id"
14314            },
14315            "arguments": [],
14316            "directives": []
14317          }, {
14318            "kind": "Field",
14319            "name": {
14320              "kind": "Name",
14321              "value": "startedGeneratingAt"
14322            },
14323            "arguments": [],
14324            "directives": []
14325          }, {
14326            "kind": "Field",
14327            "name": {
14328              "kind": "Name",
14329              "value": "finishedGeneratingAt"
14330            },
14331            "arguments": [],
14332            "directives": []
14333          }, {
14334            "kind": "Field",
14335            "name": {
14336              "kind": "Name",
14337              "value": "hasSubmittedHomepageCreationMessage"
14338            },
14339            "arguments": [],
14340            "directives": []
14341          }, {
14342            "kind": "Field",
14343            "name": {
14344              "kind": "Name",
14345              "value": "homepageGeneratedAt"
14346            },
14347            "arguments": [],
14348            "directives": []
14349          }]
14350        }
14351      }]
14352    }
14353  }],
14354  "loc": {
14355    "start": 0,
14356    "end": 241,
14357    "source": {
14358      "body": "\n  mutation EnsureHomepageGenerationMutation($id: String!) {\n    ensureHomepageGeneration(id: $id) {\n      id\n      startedGeneratingAt\n      finishedGeneratingAt\n      hasSubmittedHomepageCreationMessage\n      homepageGeneratedAt\n    }\n  }\n",
14359      "name": "GraphQL request",
14360      "locationOffset": {
14361        "line": 1,
14362        "column": 1
14363      }
14364    }
14365  }
14366};
14367const PUBLISH_REACT_WEBSITE = {
14368  "kind": "Document",
14369  "definitions": [{
14370    "kind": "OperationDefinition",
14371    "operation": "mutation",
14372    "name": {
14373      "kind": "Name",
14374      "value": "PublishReactWebsiteMutation"
14375    },
14376    "variableDefinitions": [{
14377      "kind": "VariableDefinition",
14378      "variable": {
14379        "kind": "Variable",
14380        "name": {
14381          "kind": "Name",
14382          "value": "id"
14383        }
14384      },
14385      "type": {
14386        "kind": "NonNullType",
14387        "type": {
14388          "kind": "NamedType",
14389          "name": {
14390            "kind": "Name",
14391            "value": "String"
14392          }
14393        }
14394      },
14395      "directives": []
14396    }],
14397    "directives": [],
14398    "selectionSet": {
14399      "kind": "SelectionSet",
14400      "selections": [{
14401        "kind": "Field",
14402        "name": {
14403          "kind": "Name",
14404          "value": "publishReactWebsite"
14405        },
14406        "arguments": [{
14407          "kind": "Argument",
14408          "name": {
14409            "kind": "Name",
14410            "value": "id"
14411          },
14412          "value": {
14413            "kind": "Variable",
14414            "name": {
14415              "kind": "Name",
14416              "value": "id"
14417            }
14418          }
14419        }],
14420        "directives": [],
14421        "selectionSet": {
14422          "kind": "SelectionSet",
14423          "selections": [{
14424            "kind": "Field",
14425            "name": {
14426              "kind": "Name",
14427              "value": "success"
14428            },
14429            "arguments": [],
14430            "directives": []
14431          }, {
14432            "kind": "Field",
14433            "name": {
14434              "kind": "Name",
14435              "value": "error"
14436            },
14437            "arguments": [],
14438            "directives": []
14439          }, {
14440            "kind": "Field",
14441            "name": {
14442              "kind": "Name",
14443              "value": "errorCode"
14444            },
14445            "arguments": [],
14446            "directives": []
14447          }, {
14448            "kind": "Field",
14449            "name": {
14450              "kind": "Name",
14451              "value": "blockers"
14452            },
14453            "arguments": [],
14454            "directives": [],
14455            "selectionSet": {
14456              "kind": "SelectionSet",
14457              "selections": [{
14458                "kind": "Field",
14459                "name": {
14460                  "kind": "Name",
14461                  "value": "code"
14462                },
14463                "arguments": [],
14464                "directives": []
14465              }, {
14466                "kind": "Field",
14467                "name": {
14468                  "kind": "Name",
14469                  "value": "message"
14470                },
14471                "arguments": [],
14472                "directives": []
14473              }]
14474            }
14475          }, {
14476            "kind": "Field",
14477            "name": {
14478              "kind": "Name",
14479              "value": "website"
14480            },
14481            "arguments": [],
14482            "directives": [],
14483            "selectionSet": {
14484              "kind": "SelectionSet",
14485              "selections": [{
14486                "kind": "Field",
14487                "name": {
14488                  "kind": "Name",
14489                  "value": "__typename"
14490                },
14491                "arguments": [],
14492                "directives": []
14493              }, {
14494                "kind": "Field",
14495                "name": {
14496                  "kind": "Name",
14497                  "value": "id"
14498                },
14499                "arguments": [],
14500                "directives": []
14501              }, {
14502                "kind": "Field",
14503                "name": {
14504                  "kind": "Name",
14505                  "value": "publishingStatus"
14506                },
14507                "arguments": [],
14508                "directives": []
14509              }, {
14510                "kind": "Field",
14511                "name": {
14512                  "kind": "Name",
14513                  "value": "finishedPublishingAt"
14514                },
14515                "arguments": [],
14516                "directives": []
14517              }, {
14518                "kind": "Field",
14519                "name": {
14520                  "kind": "Name",
14521                  "value": "proPublishedAt"
14522                },
14523                "arguments": [],
14524                "directives": []
14525              }, {
14526                "kind": "Field",
14527                "name": {
14528                  "kind": "Name",
14529                  "value": "lastPublishedCheckpoint"
14530                },
14531                "arguments": [],
14532                "directives": []
14533              }]
14534            }
14535          }]
14536        }
14537      }]
14538    }
14539  }],
14540  "loc": {
14541    "start": 0,
14542    "end": 360,
14543    "source": {
14544      "body": "\n  mutation PublishReactWebsiteMutation($id: String!) {\n    publishReactWebsite(id: $id) {\n      success\n      error\n      errorCode\n      blockers {\n        code\n        message\n      }\n      website {\n        __typename\n        id\n        publishingStatus\n        finishedPublishingAt\n        proPublishedAt\n        lastPublishedCheckpoint\n      }\n    }\n  }\n",
14545      "name": "GraphQL request",
14546      "locationOffset": {
14547        "line": 1,
14548        "column": 1
14549      }
14550    }
14551  }
14552};
14553const GET_LATEST_REACT_VERSION = {
14554  "kind": "Document",
14555  "definitions": [{
14556    "kind": "OperationDefinition",
14557    "operation": "query",
14558    "name": {
14559      "kind": "Name",
14560      "value": "GetLatestReactVersion"
14561    },
14562    "variableDefinitions": [{
14563      "kind": "VariableDefinition",
14564      "variable": {
14565        "kind": "Variable",
14566        "name": {
14567          "kind": "Name",
14568          "value": "websiteId"
14569        }
14570      },
14571      "type": {
14572        "kind": "NonNullType",
14573        "type": {
14574          "kind": "NamedType",
14575          "name": {
14576            "kind": "Name",
14577            "value": "String"
14578          }
14579        }
14580      },
14581      "directives": []
14582    }],
14583    "directives": [],
14584    "selectionSet": {
14585      "kind": "SelectionSet",
14586      "selections": [{
14587        "kind": "Field",
14588        "name": {
14589          "kind": "Name",
14590          "value": "reactWebsiteVersions"
14591        },
14592        "arguments": [{
14593          "kind": "Argument",
14594          "name": {
14595            "kind": "Name",
14596            "value": "websiteId"
14597          },
14598          "value": {
14599            "kind": "Variable",
14600            "name": {
14601              "kind": "Name",
14602              "value": "websiteId"
14603            }
14604          }
14605        }, {
14606          "kind": "Argument",
14607          "name": {
14608            "kind": "Name",
14609            "value": "take"
14610          },
14611          "value": {
14612            "kind": "IntValue",
14613            "value": "1"
14614          }
14615        }],
14616        "directives": [],
14617        "selectionSet": {
14618          "kind": "SelectionSet",
14619          "selections": [{
14620            "kind": "Field",
14621            "name": {
14622              "kind": "Name",
14623              "value": "commitHash"
14624            },
14625            "arguments": [],
14626            "directives": []
14627          }]
14628        }
14629      }]
14630    }
14631  }],
14632  "loc": {
14633    "start": 0,
14634    "end": 140,
14635    "source": {
14636      "body": "\n  query GetLatestReactVersion($websiteId: String!) {\n    reactWebsiteVersions(websiteId: $websiteId, take: 1) {\n      commitHash\n    }\n  }\n",
14637      "name": "GraphQL request",
14638      "locationOffset": {
14639        "line": 1,
14640        "column": 1
14641      }
14642    }
14643  }
14644};
14645const REFUND_ORDER = {
14646  "kind": "Document",
14647  "definitions": [{
14648    "kind": "OperationDefinition",
14649    "operation": "mutation",
14650    "name": {
14651      "kind": "Name",
14652      "value": "ReactWebsiteChatPageRefundOrderMutation"
14653    },
14654    "variableDefinitions": [{
14655      "kind": "VariableDefinition",
14656      "variable": {
14657        "kind": "Variable",
14658        "name": {
14659          "kind": "Name",
14660          "value": "websiteId"
14661        }
14662      },
14663      "type": {
14664        "kind": "NonNullType",
14665        "type": {
14666          "kind": "NamedType",
14667          "name": {
14668            "kind": "Name",
14669            "value": "String"
14670          }
14671        }
14672      },
14673      "directives": []
14674    }, {
14675      "kind": "VariableDefinition",
14676      "variable": {
14677        "kind": "Variable",
14678        "name": {
14679          "kind": "Name",
14680          "value": "orderId"
14681        }
14682      },
14683      "type": {
14684        "kind": "NonNullType",
14685        "type": {
14686          "kind": "NamedType",
14687          "name": {
14688            "kind": "Name",
14689            "value": "String"
14690          }
14691        }
14692      },
14693      "directives": []
14694    }, {
14695      "kind": "VariableDefinition",
14696      "variable": {
14697        "kind": "Variable",
14698        "name": {
14699          "kind": "Name",
14700          "value": "amount"
14701        }
14702      },
14703      "type": {
14704        "kind": "NamedType",
14705        "name": {
14706          "kind": "Name",
14707          "value": "Int"
14708        }
14709      },
14710      "directives": []
14711    }],
14712    "directives": [],
14713    "selectionSet": {
14714      "kind": "SelectionSet",
14715      "selections": [{
14716        "kind": "Field",
14717        "name": {
14718          "kind": "Name",
14719          "value": "refundOrder"
14720        },
14721        "arguments": [{
14722          "kind": "Argument",
14723          "name": {
14724            "kind": "Name",
14725            "value": "websiteId"
14726          },
14727          "value": {
14728            "kind": "Variable",
14729            "name": {
14730              "kind": "Name",
14731              "value": "websiteId"
14732            }
14733          }
14734        }, {
14735          "kind": "Argument",
14736          "name": {
14737            "kind": "Name",
14738            "value": "orderId"
14739          },
14740          "value": {
14741            "kind": "Variable",
14742            "name": {
14743              "kind": "Name",
14744              "value": "orderId"
14745            }
14746          }
14747        }, {
14748          "kind": "Argument",
14749          "name": {
14750            "kind": "Name",
14751            "value": "amount"
14752          },
14753          "value": {
14754            "kind": "Variable",
14755            "name": {
14756              "kind": "Name",
14757              "value": "amount"
14758            }
14759          }
14760        }],
14761        "directives": [],
14762        "selectionSet": {
14763          "kind": "SelectionSet",
14764          "selections": [{
14765            "kind": "Field",
14766            "name": {
14767              "kind": "Name",
14768              "value": "status"
14769            },
14770            "arguments": [],
14771            "directives": []
14772          }, {
14773            "kind": "Field",
14774            "name": {
14775              "kind": "Name",
14776              "value": "amountRefunded"
14777            },
14778            "arguments": [],
14779            "directives": []
14780          }]
14781        }
14782      }]
14783    }
14784  }],
14785  "loc": {
14786    "start": 0,
14787    "end": 243,
14788    "source": {
14789      "body": "\n  mutation ReactWebsiteChatPageRefundOrderMutation(\n    $websiteId: String!\n    $orderId: String!\n    $amount: Int\n  ) {\n    refundOrder(websiteId: $websiteId, orderId: $orderId, amount: $amount) {\n      status\n      amountRefunded\n    }\n  }\n",
14790      "name": "GraphQL request",
14791      "locationOffset": {
14792        "line": 1,
14793        "column": 1
14794      }
14795    }
14796  }
14797};
14798const SiteViews = reactExports.lazy(() => __vitePreload(() => import("./SiteViews-DrsHYaEK.js"), true ? __vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12]) : void 0));
14799const LoadingSpinner = () => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex h-screen items-center justify-center bg-white", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-8 w-8 animate-spin rounded-full border-2 border-gray-300 border-t-black" }) });
14800const ErrorContent = ({
14801  error
14802}) => {
14803  var _a;
14804  const isNotFound = (error == null ? void 0 : error.message) === "user does not have access to this website" || ((_a = error == null ? void 0 : error.message) == null ? void 0 : _a.includes("not found"));
14805  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-1 items-center justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center", children: [
14806    /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-xl font-semibold text-gray-900", children: isNotFound ? "Website not found" : "Unable to load website" }),
14807    /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-2 text-gray-600", children: isNotFound ? "This website doesn't exist or you don't have access to it." : (error == null ? void 0 : error.message) || "Please try again later." }),
14808    /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "/sites", className: "mt-4 inline-block text-sm text-blue-600 hover:text-blue-800", children: "Go back to dashboard" })
14809  ] }) });
14810};
14811const ReactWebsiteChatEditor = ({
14812  id
14813}) => {
14814  var _a, _b, _c, _d, _e;
14815  const {
14816    currentUser,
14817    isAuthenticated,
14818    loading: authLoading,
14819    getToken
14820  } = useAuth();
14821  useRecordLastViewedWebsite(id);
14822  const {
14823    search
14824  } = useLocation();
14825  const chatPanelRef = reactExports.useRef(null);
14826  const [isChatPanelExpanded, setIsChatPanelExpanded] = reactExports.useState(true);
14827  const [previewKey, setPreviewKey] = reactExports.useState(0);
14828  const [isClaiming, setIsClaiming] = reactExports.useState(false);
14829  const [isPublishing, setIsPublishing] = reactExports.useState(false);
14830  const [publishCompletedSignal, setPublishCompletedSignal] = reactExports.useState(0);
14831  const prevPublishingStatusRef = reactExports.useRef(void 0);
14832  const [publishBlockers, setPublishBlockers] = reactExports.useState([]);
14833  const [showUpgradeModal, setShowUpgradeModal] = reactExports.useState(false);
14834  const [upgradeError, _setUpgradeError] = reactExports.useState(null);
14835  const [isPreparationComplete, setIsPreparationComplete] = reactExports.useState(false);
14836  const [isContainerReady, setIsContainerReady] = reactExports.useState(false);
14837  const [containerStatus, setContainerStatus] = reactExports.useState(null);
14838  const [localAgencyCreditsDelta, setLocalAgencyCreditsDelta] = reactExports.useState(0);
14839  const [localAiChatMessagesDelta, setLocalAiChatMessagesDelta] = reactExports.useState(0);
14840  const [pickModeActive, setPickModeActive] = reactExports.useState(false);
14841  const [selectedElement, setSelectedElement] = reactExports.useState(null);
14842  const [isSelectorReady, setIsSelectorReady] = reactExports.useState(false);
14843  const [isPickerAvailable, setIsPickerAvailable] = reactExports.useState(false);
14844  const [currentPath, setCurrentPath] = reactExports.useState("/");
14845  const [editTextModeActive, setEditTextModeActive] = reactExports.useState(false);
14846  const [isAgentResponding, setIsAgentResponding] = reactExports.useState(false);
14847  const handleAgentBusyChange = reactExports.useCallback((busy) => {
14848    setIsAgentResponding(busy);
14849  }, []);
14850  const [showPublishWhileBusy, setShowPublishWhileBusy] = reactExports.useState(false);
14851  const [previewRefreshSignal, setPreviewRefreshSignal] = reactExports.useState(0);
14852  const handlePaymentsDataChanged = reactExports.useCallback(() => {
14853    setPreviewRefreshSignal((n) => n + 1);
14854  }, []);
14855  const [activeView, setActiveView] = reactExports.useState("website");
14856  const [showViewNonce, setShowViewNonce] = reactExports.useState(0);
14857  const [viewRefreshSignal, setViewRefreshSignal] = reactExports.useState(0);
14858  const [orderDetailId, setOrderDetailId] = reactExports.useState(void 0);
14859  const [invoiceDetailId, setInvoiceDetailId] = reactExports.useState(void 0);
14860  const isDesktop = useBreakpoint("lg");
14861  const handleBusinessDataChanged = reactExports.useCallback(() => {
14862    setViewRefreshSignal((n) => n + 1);
14863  }, []);
14864  const handleBackToWebsite = reactExports.useCallback(() => {
14865    setActiveView("website");
14866    setOrderDetailId(void 0);
14867    setInvoiceDetailId(void 0);
14868  }, []);
14869  reactExports.useEffect(() => {
14870    if (activeView !== "website") {
14871      __vitePreload(() => Promise.resolve({}), true ? __vite__mapDeps([13]) : void 0);
14872    }
14873  }, [activeView]);
14874  const [isEditBusy, setIsEditBusy] = reactExports.useState(false);
14875  const handleEditBusyChange = reactExports.useCallback((busy) => {
14876    setIsEditBusy(busy);
14877  }, []);
14878  const [viteError, setViteError] = reactExports.useState(null);
14879  const viteErrorCaptureTimer = reactExports.useRef(null);
14880  const currentViteErrorSig = reactExports.useRef(null);
14881  const viteErrorClearedSinceSeen = reactExports.useRef(false);
14882  const handleViteErrorCleared = reactExports.useCallback(() => {
14883    setViteError(null);
14884    if (viteErrorCaptureTimer.current) {
14885      clearTimeout(viteErrorCaptureTimer.current);
14886      viteErrorCaptureTimer.current = null;
14887    }
14888    viteErrorClearedSinceSeen.current = true;
14889  }, []);
14890  const handleTogglePickMode = reactExports.useCallback(() => {
14891    setPickModeActive((prev) => {
14892      const next = !prev;
14893      if (next) setEditTextModeActive(false);
14894      return next;
14895    });
14896  }, []);
14897  const handleToggleEditTextMode = reactExports.useCallback(() => {
14898    setEditTextModeActive((prev) => {
14899      const next = !prev;
14900      if (next) setPickModeActive(false);
14901      return next;
14902    });
14903  }, []);
14904  const handleEditTextModeExit = reactExports.useCallback(() => {
14905    setEditTextModeActive(false);
14906  }, []);
14907  const handleApplyEditsWithAI = reactExports.useCallback((prompt) => {
14908    var _a2;
14909    (_a2 = chatPanelRef.current) == null ? void 0 : _a2.sendUserMessage(prompt);
14910  }, []);
14911  const handleClearSelection = reactExports.useCallback(() => {
14912    setSelectedElement(null);
14913  }, []);
14914  const handlePicked = reactExports.useCallback((payload) => {
14915    setSelectedElement(payload);
14916    setPickModeActive(false);
14917  }, []);
14918  const handlePickModeExit = reactExports.useCallback(() => {
14919    setPickModeActive(false);
14920  }, []);
14921  const handleIframeReload = reactExports.useCallback(() => {
14922    setPickModeActive(false);
14923    setSelectedElement(null);
14924    setEditTextModeActive(false);
14925  }, []);
14926  const handleSelectorReadyChange = reactExports.useCallback((ready) => {
14927    setIsSelectorReady(ready);
14928  }, []);
14929  const handlePickerAvailabilityChange = reactExports.useCallback((available) => {
14930    setIsPickerAvailable(available);
14931  }, []);
14932  const handleCurrentPathChange = reactExports.useCallback((path) => {
14933    setCurrentPath(path);
14934  }, []);
14935  reactExports.useEffect(() => {
14936    if (!pickModeActive) return;
14937    const handleKeyDown = (e) => {
14938      if (e.key === "Escape") {
14939        e.preventDefault();
14940        handlePickModeExit();
14941      }
14942    };
14943    window.addEventListener("keydown", handleKeyDown);
14944    return () => {
14945      window.removeEventListener("keydown", handleKeyDown);
14946    };
14947  }, [pickModeActive, handlePickModeExit]);
14948  const lastKnownCommitHashRef = reactExports.useRef(null);
14949  const isAIRespondingRef = reactExports.useRef(false);
14950  const {
14951    data,
14952    loading,
14953    error,
14954    refetch,
14955    startPolling,
14956    stopPolling
14957  } = useQuery$1(GET_REACT_WEBSITE, {
14958    variables: {
14959      id
14960    },
14961    skip: !isAuthenticated,
14962    // Don't query until authenticated
14963    fetchPolicy: "network-only",
14964    // Always fetch fresh data (credits, publishing status, etc.)
14965    // Don't poll while the tab is in the background — the user can't see
14966    // the result, and the visibility-change handler below does a fresh
14967    // refetch the moment the tab is visible again.
14968    skipPollAttempt: () => document.hidden
14969  });
14970  reactExports.useEffect(() => {
14971    if (!authLoading && !isAuthenticated) {
14972      const urlParams = new URLSearchParams(search);
14973      const screenHint = urlParams.get("screen_hint");
14974      urlParams.delete("screen_hint");
14975      const cleanSearch = urlParams.toString();
14976      const cleanPath = window.location.pathname + (cleanSearch ? `?${cleanSearch}` : "");
14977      const encodedRedirect = encodeURIComponent(cleanPath);
14978      if (screenHint === "signup") {
14979        navigate(namedRoutes.signup({
14980          redirectTo: encodedRedirect
14981        }));
14982      } else {
14983        navigate(namedRoutes.login({
14984          redirectTo: encodedRedirect
14985        }));
14986      }
14987    }
14988    if (isAuthenticated) {
14989      const urlParams = new URLSearchParams(search);
14990      const hasScreenHint = urlParams.has("screen_hint");
14991      if (hasScreenHint) {
14992        urlParams.delete("screen_hint");
14993        const newSearch = urlParams.toString();
14994        const newPath = window.location.pathname + (newSearch ? `?${newSearch}` : "");
14995        navigate(newPath, {
14996          replace: true
14997        });
14998      }
14999    }
15000  }, [authLoading, isAuthenticated, search]);
15001  const [publishReactWebsite] = useMutation$1(PUBLISH_REACT_WEBSITE);
15002  const [claimWebsite] = useMutation$1(CLAIM_WEBSITE);
15003  const [ensureHomepageGeneration] = useMutation$1(ENSURE_HOMEPAGE_GENERATION);
15004  const [refundOrder] = useMutation$1(REFUND_ORDER);
15005  const refundInFlight = reactExports.useRef(false);
15006  const posthog = usePostHog();
15007  const hasFiredFirstViewRef = reactExports.useRef(false);
15008  const hasAttemptedClaimRef = reactExports.useRef(false);
15009  const hasAttemptedEnsureRef = reactExports.useRef(false);
15010  reactExports.useEffect(() => {
15011    if (!posthog) return;
15012    return posthog.onFeatureFlags(() => {
15013      if (posthog.isFeatureEnabled("disable-editor-session-recording")) {
15014        posthog.stopSessionRecording();
15015        return;
15016      }
15017      posthog.startSessionRecording();
15018    });
15019  }, [posthog]);
15020  reactExports.useEffect(() => {
15021    if (!posthog) return;
15022    return startLongFrameTelemetry((event, properties) => posthog.capture(event, properties), id);
15023  }, [posthog, id]);
15024  const handleViteError = reactExports.useCallback((payload) => {
15025    setViteError(payload);
15026    try {
15027      const signatureHash = viteErrorSignature(payload);
15028      const dedupKey = `ls_react_err_${id}_${signatureHash}`;
15029      if (localStorage.getItem(dedupKey)) return;
15030      const capture = () => {
15031        var _a2;
15032        viteErrorCaptureTimer.current = null;
15033        if (localStorage.getItem(dedupKey)) return;
15034        localStorage.setItem(dedupKey, "1");
15035        posthog == null ? void 0 : posthog.capture("react_website_error_detected", {
15036          websiteId: id,
15037          source: "frontend_overlay",
15038          message: (_a2 = payload.message) == null ? void 0 : _a2.slice(0, 500),
15039          file: payload.file,
15040          path: payload.path,
15041          signatureHash,
15042          websiteType: "react"
15043        });
15044      };
15045      if (signatureHash === currentViteErrorSig.current && viteErrorClearedSinceSeen.current) {
15046        if (viteErrorCaptureTimer.current) {
15047          clearTimeout(viteErrorCaptureTimer.current);
15048        }
15049        capture();
15050        return;
15051      }
15052      if (signatureHash !== currentViteErrorSig.current) {
15053        currentViteErrorSig.current = signatureHash;
15054        viteErrorClearedSinceSeen.current = false;
15055        if (viteErrorCaptureTimer.current) {
15056          clearTimeout(viteErrorCaptureTimer.current);
15057        }
15058        viteErrorCaptureTimer.current = setTimeout(capture, 1500);
15059      }
15060    } catch {
15061    }
15062  }, [id, posthog]);
15063  const website = data == null ? void 0 : data.website;
15064  const myWebsiteAccess = data == null ? void 0 : data.myWebsiteAccess;
15065  const hasSeededFirstViewRef = reactExports.useRef(false);
15066  const prevHomepageGeneratedAtRef = reactExports.useRef(null);
15067  reactExports.useEffect(() => {
15068    var _a2;
15069    if (!website) return;
15070    const prev = prevHomepageGeneratedAtRef.current;
15071    prevHomepageGeneratedAtRef.current = website.homepageGeneratedAt ?? null;
15072    if (!hasSeededFirstViewRef.current) {
15073      hasSeededFirstViewRef.current = true;
15074      return;
15075    }
15076    if (prev !== null || !website.homepageGeneratedAt) return;
15077    if (!(currentUser == null ? void 0 : currentUser.id) || ((_a2 = website.user) == null ? void 0 : _a2.id) !== currentUser.id) return;
15078    if (hasFiredFirstViewRef.current) return;
15079    hasFiredFirstViewRef.current = true;
15080    posthog == null ? void 0 : posthog.capture("Website First View After Build");
15081  }, [website, currentUser == null ? void 0 : currentUser.id, posthog]);
15082  const hasFiredViewedRef = reactExports.useRef(false);
15083  const generatedAtMountRef = reactExports.useRef(null);
15084  reactExports.useEffect(() => {
15085    var _a2;
15086    if (!website) return;
15087    if (generatedAtMountRef.current === null) {
15088      generatedAtMountRef.current = !!website.homepageGeneratedAt;
15089    }
15090    if (hasFiredViewedRef.current) return;
15091    if (!website.homepageGeneratedAt) return;
15092    if (!(currentUser == null ? void 0 : currentUser.id) || ((_a2 = website.user) == null ? void 0 : _a2.id) !== currentUser.id) return;
15093    hasFiredViewedRef.current = true;
15094    posthog == null ? void 0 : posthog.capture("Generated Website Viewed", {
15095      websiteId: website.id,
15096      viewMode: generatedAtMountRef.current ? "returned" : "live"
15097    });
15098  }, [website, currentUser == null ? void 0 : currentUser.id, posthog]);
15099  reactExports.useEffect(() => {
15100    var _a2;
15101    if (website && !website.user && isAuthenticated && !hasAttemptedClaimRef.current) {
15102      const isAdmin = (_a2 = currentUser == null ? void 0 : currentUser.roles) == null ? void 0 : _a2.includes("support");
15103      if (!isAdmin) {
15104        hasAttemptedClaimRef.current = true;
15105        setIsClaiming(true);
15106        claimWebsite({
15107          variables: {
15108            id: website.id
15109          }
15110        }).then(() => refetch()).then(() => setIsClaiming(false)).catch(async (error2) => {
15111          var _a3, _b2, _c2;
15112          const message = (error2 == null ? void 0 : error2.message) || "Failed to claim this website.";
15113          if (message.includes("already claimed")) {
15114            try {
15115              const result = await refetch();
15116              if (((_c2 = (_b2 = (_a3 = result == null ? void 0 : result.data) == null ? void 0 : _a3.website) == null ? void 0 : _b2.user) == null ? void 0 : _c2.id) === (currentUser == null ? void 0 : currentUser.id)) {
15117                setIsClaiming(false);
15118                return;
15119              }
15120            } catch {
15121            }
15122          }
15123          console.error("Failed to claim website:", error2);
15124          navigate(namedRoutes.sites() + `?error=${encodeURIComponent(message)}`);
15125        });
15126      }
15127    }
15128  }, [website, isAuthenticated, currentUser]);
15129  reactExports.useEffect(() => {
15130    var _a2;
15131    if (hasAttemptedEnsureRef.current) return;
15132    if (!website || website.websiteType !== "react") return;
15133    if (!(currentUser == null ? void 0 : currentUser.id) || ((_a2 = website.user) == null ? void 0 : _a2.id) !== currentUser.id) return;
15134    if (website.homepageGeneratedAt) return;
15135    const prepStalled = website.startedGeneratingAt && !website.finishedGeneratingAt;
15136    const turnUndispatched = website.finishedGeneratingAt && !website.hasSubmittedHomepageCreationMessage;
15137    if (!prepStalled && !turnUndispatched) return;
15138    hasAttemptedEnsureRef.current = true;
15139    ensureHomepageGeneration({
15140      variables: {
15141        id: website.id
15142      }
15143    }).catch((err) => {
15144      console.error("Failed to ensure homepage generation:", err);
15145    });
15146  }, [website, currentUser == null ? void 0 : currentUser.id, ensureHomepageGeneration]);
15147  const isBeingPrepared = (website == null ? void 0 : website.websiteType) === "react" && !(website == null ? void 0 : website.finishedGeneratingAt);
15148  reactExports.useEffect(() => {
15149    if (!isBeingPrepared && (website == null ? void 0 : website.finishedGeneratingAt) && !isPreparationComplete) {
15150      setIsPreparationComplete(true);
15151    }
15152  }, [isBeingPrepared, isPreparationComplete, website == null ? void 0 : website.finishedGeneratingAt]);
15153  reactExports.useEffect(() => {
15154    setIsPublishing((website == null ? void 0 : website.publishingStatus) === "In Progress");
15155  }, [website == null ? void 0 : website.publishingStatus]);
15156  reactExports.useEffect(() => {
15157    const current = website == null ? void 0 : website.publishingStatus;
15158    if (current === void 0) return;
15159    const previous = prevPublishingStatusRef.current;
15160    prevPublishingStatusRef.current = current;
15161    if (previous !== void 0 && previous !== "Completed" && current === "Completed") {
15162      setPublishCompletedSignal((n) => n + 1);
15163    }
15164  }, [website == null ? void 0 : website.publishingStatus]);
15165  reactExports.useEffect(() => {
15166    setLocalAiChatMessagesDelta(0);
15167    setLocalAgencyCreditsDelta(0);
15168  }, [website == null ? void 0 : website.aiChatMessagesUsed, (_a = website == null ? void 0 : website.user) == null ? void 0 : _a.agencyTotalCredits]);
15169  const idlePollInterval = isBeingPrepared && !isPreparationComplete ? 2e3 : 15e3;
15170  reactExports.useEffect(() => {
15171    startPolling((website == null ? void 0 : website.publishingStatus) === "In Progress" ? 2e3 : idlePollInterval);
15172    return () => stopPolling();
15173  }, [idlePollInterval, website == null ? void 0 : website.publishingStatus, startPolling, stopPolling]);
15174  reactExports.useEffect(() => {
15175    if ((website == null ? void 0 : website.websiteType) === "html" || (website == null ? void 0 : website.websiteType) === null) {
15176      navigate(namedRoutes.websiteChat({
15177        id
15178      }));
15179    }
15180  }, [website == null ? void 0 : website.websiteType, id]);
15181  const previewBaseDomain = "landingsite.dev";
15182  const previewUrl = (website == null ? void 0 : website.relaceRepoId) && (website == null ? void 0 : website.publicId) ? `https://${website.publicId}.${previewBaseDomain}` : null;
15183  reactExports.useEffect(() => {
15184    if ((website == null ? void 0 : website.hasSubmittedHomepageCreationMessage) && !isContainerReady) {
15185      setIsContainerReady(true);
15186      return;
15187    }
15188    if (!(website == null ? void 0 : website.finishedGeneratingAt) || !previewUrl || isContainerReady) {
15189      return;
15190    }
15191    let isCancelled = false;
15192    let pollInterval = null;
15193    const checkStatus = async () => {
15194      try {
15195        const token = await getToken();
15196        const statusUrl = `${previewUrl}/__container/status`;
15197        const headers = {};
15198        if (token) {
15199          headers["Authorization"] = `Bearer ${token}`;
15200        }
15201        const response = await fetch(statusUrl, {
15202          headers
15203        });
15204        if (!response.ok || isCancelled) return;
15205        const data2 = await response.json();
15206        setContainerStatus(data2.status);
15207        if (data2.ready === true) {
15208          setIsContainerReady(true);
15209          if (pollInterval) clearInterval(pollInterval);
15210        }
15211      } catch {
15212      }
15213    };
15214    checkStatus();
15215    pollInterval = setInterval(checkStatus, 2e3);
15216    return () => {
15217      isCancelled = true;
15218      if (pollInterval) clearInterval(pollInterval);
15219    };
15220  }, [website == null ? void 0 : website.finishedGeneratingAt, website == null ? void 0 : website.hasSubmittedHomepageCreationMessage, previewUrl, isContainerReady, getToken]);
15221  const apolloClient = useApolloClient();
15222  const handleCommitHashChange = reactExports.useCallback((hash) => {
15223    const prevHash = lastKnownCommitHashRef.current;
15224    lastKnownCommitHashRef.current = hash;
15225    const shouldBump = !!(prevHash && prevHash !== hash && viteError);
15226    console.log("[ls:preview] commit-hash-change", {
15227      prevHash: (prevHash == null ? void 0 : prevHash.slice(0, 7)) ?? null,
15228      newHash: hash.slice(0, 7),
15229      hashChanged: prevHash !== hash,
15230      hasViteError: !!viteError,
15231      viteErrorMessage: (viteError == null ? void 0 : viteError.message) ?? null,
15232      bumpingPreviewKey: shouldBump
15233    });
15234    if (shouldBump) {
15235      setPreviewKey((prev) => prev + 1);
15236    }
15237  }, [viteError]);
15238  reactExports.useEffect(() => {
15239    if (!(website == null ? void 0 : website.id) || !isContainerReady) return;
15240    const handleVisibilityChange = async () => {
15241      var _a2, _b2, _c2, _d2, _e2;
15242      if (document.visibilityState !== "visible") return;
15243      if (isAIRespondingRef.current) return;
15244      refetch();
15245      setLocalAgencyCreditsDelta(0);
15246      setLocalAiChatMessagesDelta(0);
15247      try {
15248        const result = await apolloClient.query({
15249          query: GET_LATEST_REACT_VERSION,
15250          variables: {
15251            websiteId: website.id
15252          },
15253          fetchPolicy: "network-only"
15254        });
15255        const latestHash = ((_c2 = (_b2 = (_a2 = result.data) == null ? void 0 : _a2.reactWebsiteVersions) == null ? void 0 : _b2[0]) == null ? void 0 : _c2.commitHash) ?? null;
15256        if (latestHash && lastKnownCommitHashRef.current && latestHash !== lastKnownCommitHashRef.current) {
15257          console.log("[ReactWebsiteChatPage] External changes detected, refreshing preview and chat", {
15258            previous: (_d2 = lastKnownCommitHashRef.current) == null ? void 0 : _d2.substring(0, 7),
15259            latest: latestHash.substring(0, 7)
15260          });
15261          lastKnownCommitHashRef.current = latestHash;
15262          setPreviewKey((prev) => prev + 1);
15263          (_e2 = chatPanelRef.current) == null ? void 0 : _e2.reloadMessages();
15264        } else if (latestHash) {
15265          lastKnownCommitHashRef.current = latestHash;
15266        }
15267      } catch {
15268      }
15269    };
15270    document.addEventListener("visibilitychange", handleVisibilityChange);
15271    return () => {
15272      document.removeEventListener("visibilitychange", handleVisibilityChange);
15273    };
15274  }, [website == null ? void 0 : website.id, isContainerReady, apolloClient, refetch]);
15275  const handleRefreshPreview = reactExports.useCallback(() => {
15276    setPreviewKey((prev) => prev + 1);
15277  }, []);
15278  const handleRefetchWebsite = reactExports.useCallback(() => {
15279    refetch();
15280    setLocalAgencyCreditsDelta(0);
15281    setLocalAiChatMessagesDelta(0);
15282  }, [refetch]);
15283  const handleAgencyCreditUsed = reactExports.useCallback(() => {
15284    setLocalAgencyCreditsDelta((prev) => prev - 1);
15285  }, []);
15286  const handleAiChatMessageUsed = reactExports.useCallback(() => {
15287    setLocalAiChatMessagesDelta((prev) => prev + 1);
15288  }, []);
15289  const toolbarPages = reactExports.useMemo(() => (data == null ? void 0 : data.pagesForToolbar) ?? [], [data == null ? void 0 : data.pagesForToolbar]);
15290  const chatWebsite = reactExports.useMemo(() => website ? {
15291    id: website.id,
15292    publicId: website.publicId,
15293    analyticsId: website.analyticsId,
15294    name: website.name,
15295    businessName: website.businessName,
15296    websiteType: website.websiteType,
15297    homepageGeneratedAt: website.homepageGeneratedAt,
15298    stripePlan: website.stripePlan,
15299    aiChatMessagesUsed: website.aiChatMessagesUsed,
15300    chatMonthlyAllotment: website.chatMonthlyAllotment,
15301    chatMonthlyUsed: website.chatMonthlyUsed,
15302    chatPurchasedCredits: website.chatPurchasedCredits,
15303    user: website.user,
15304    Domain: website.Domain
15305  } : void 0, [website == null ? void 0 : website.id, website == null ? void 0 : website.publicId, website == null ? void 0 : website.analyticsId, website == null ? void 0 : website.name, website == null ? void 0 : website.businessName, website == null ? void 0 : website.websiteType, website == null ? void 0 : website.homepageGeneratedAt, website == null ? void 0 : website.stripePlan, website == null ? void 0 : website.aiChatMessagesUsed, website == null ? void 0 : website.chatMonthlyAllotment, website == null ? void 0 : website.chatMonthlyUsed, website == null ? void 0 : website.chatPurchasedCredits, website == null ? void 0 : website.user, website == null ? void 0 : website.Domain]);
15306  const handleAIRespondingChange = reactExports.useCallback((responding) => {
15307    isAIRespondingRef.current = responding;
15308  }, []);
15309  const canEditWebsite = !!(myWebsiteAccess == null ? void 0 : myWebsiteAccess.canEdit);
15310  const accessRole = myWebsiteAccess == null ? void 0 : myWebsiteAccess.role;
15311  const aifeaturesSiteToken = (website == null ? void 0 : website.aifeaturesSiteToken) ?? null;
15312  const ownerCommerceEnabled = !!((_b = website == null ? void 0 : website.user) == null ? void 0 : _b.merchantPaymentsBetaEnabled);
15313  const isSitePublished = Boolean(website == null ? void 0 : website.proPublishedAt);
15314  const surfaceFacts = reactExports.useMemo(() => ({
15315    isPublished: isSitePublished,
15316    /**
15317     * NOT QUERYABLE HERE YET. Nothing on the editor's website query answers
15318     * "does this site sell anything" — no product count, no connected
15319     * Stripe account. No surface rule reads this fact today, and
15320     * `siteSurfaces.test.ts` fails the moment one starts to, which is the
15321     * signal that this call site needs a real source before it can.
15322     */
15323    commerceRelevant: false,
15324    role: accessRole,
15325    canEdit: canEditWebsite,
15326    ownerCommerceEnabled
15327  }), [isSitePublished, accessRole, canEditWebsite, ownerCommerceEnabled]);
15328  const canOpenView = reactExports.useCallback((view) => canOpenSiteSurface(view, surfaceFacts, !!aifeaturesSiteToken), [surfaceFacts, aifeaturesSiteToken]);
15329  const handleShowView = reactExports.useCallback(
15330    (view, params, source = "agent") => {
15331      if (view === "website") {
15332        setActiveView("website");
15333        setOrderDetailId(void 0);
15334        setInvoiceDetailId(void 0);
15335        return;
15336      }
15337      if (!canOpenView(view)) return;
15338      posthog == null ? void 0 : posthog.capture("merchant_view_opened", {
15339        view,
15340        deep_open: Boolean((params == null ? void 0 : params.orderId) || (params == null ? void 0 : params.invoiceId)),
15341        source,
15342        websiteId: id
15343      });
15344      setActiveView(view);
15345      setOrderDetailId(view === "orders" ? params == null ? void 0 : params.orderId : void 0);
15346      setInvoiceDetailId(view === "invoices" ? params == null ? void 0 : params.invoiceId : void 0);
15347      setShowViewNonce((n) => n + 1);
15348      if (!isDesktop) {
15349        setIsChatPanelExpanded(false);
15350      }
15351    },
15352    // The gate rules live in `canOpenView`; this only needs the callback plus
15353    // what it uses for instrumentation and layout.
15354    [canOpenView, isDesktop, posthog, id]
15355  );
15356  const handleMerchantViewRefund = reactExports.useCallback(async (order, amount) => {
15357    if (refundInFlight.current) {
15358      throw new Error("A refund is already in progress.");
15359    }
15360    refundInFlight.current = true;
15361    try {
15362      await refundOrder({
15363        variables: {
15364          websiteId: id,
15365          orderId: order.id,
15366          amount
15367        }
15368      });
15369      _t.success("Refund issued");
15370      setViewRefreshSignal((n) => n + 1);
15371    } finally {
15372      refundInFlight.current = false;
15373    }
15374  }, [refundOrder, id]);
15375  const isOwnerSide = accessRole === "OWNER" || accessRole === "ADMIN";
15376  const merchantViewAllowed = activeView !== "website" && canOpenView(activeView);
15377  const merchantViewEl = reactExports.useMemo(() => {
15378    if (!merchantViewAllowed || !aifeaturesSiteToken) return null;
15379    return (
15380      // NO FALLBACK UI. The chunk is fetched on the same interaction that
15381      // opens the view, and a spinner that flashes for one frame on a warm
15382      // cache reads as jank rather than as progress. The dock already shows
15383      // the switch happening.
15384      /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
15385        SiteViews,
15386        {
15387          view: activeView,
15388          viewKey: `${activeView}:${showViewNonce}`,
15389          siteToken: aifeaturesSiteToken,
15390          apiUrl: void 0,
15391          refreshKey: viewRefreshSignal,
15392          initialOrderId: orderDetailId,
15393          initialInvoiceId: invoiceDetailId,
15394          isOwner: isOwnerSide,
15395          needsPaidPlan: (website == null ? void 0 : website.stripePlan) !== "Pro",
15396          published: Boolean(website == null ? void 0 : website.proPublishedAt),
15397          lastPublishedAt: (website == null ? void 0 : website.proPublishedAt) ?? null,
15398          onRefund: handleMerchantViewRefund,
15399          onBackToWebsite: handleBackToWebsite,
15400          onUpgradePlan: () => navigate(namedRoutes.reactWebsiteChatSettingsTab({
15401            id,
15402            tab: "plan"
15403          })),
15404          onConnectStripe: () => navigate(namedRoutes.settingsTab({
15405            tab: "payments"
15406          }))
15407        }
15408      ) })
15409    );
15410  }, [merchantViewAllowed, activeView, showViewNonce, viewRefreshSignal, orderDetailId, invoiceDetailId, aifeaturesSiteToken, isOwnerSide, handleMerchantViewRefund, handleBackToWebsite, website == null ? void 0 : website.stripePlan, website == null ? void 0 : website.proPublishedAt, id]);
15411  reactExports.useEffect(() => {
15412    if (activeView !== "website" && !merchantViewAllowed) {
15413      setActiveView("website");
15414      setOrderDetailId(void 0);
15415      setInvoiceDetailId(void 0);
15416    }
15417  }, [activeView, merchantViewAllowed]);
15418  const viewSwitcherEl = reactExports.useMemo(() => {
15419    const options = editorSiteSurfaces(surfaceFacts, !!aifeaturesSiteToken);
15420    if (options.length < 2) return null;
15421    const active = options.find((o) => o.surface === activeView) ?? options[0];
15422    const ActiveIcon = active.icon;
15423    return /* @__PURE__ */ jsxRuntimeExports.jsxs(Root2$2, { children: [
15424      /* @__PURE__ */ jsxRuntimeExports.jsx(Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { type: "button", "aria-label": `Current view: ${active.label}. Switch view`, className: "group flex items-center gap-1.5 rounded-[9px] border border-[#1B1A22]/[0.08] bg-white px-2 py-1.5 text-[11.5px] font-medium text-[#1B1A22] shadow-[0_1px_2px_rgba(27,26,34,0.05)] transition-colors hover:border-[#1B1A22]/[0.16] data-[state=open]:border-[#1B1A22]/[0.16] data-[state=open]:bg-[#1B1A22]/[0.03]", children: [
15425        /* @__PURE__ */ jsxRuntimeExports.jsx(ActiveIcon, { size: 13, strokeWidth: 2, className: "flex-shrink-0 text-[#6B6878]" }),
15426        active.label,
15427        /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { size: 12, strokeWidth: 2.5, className: "flex-shrink-0 text-[#9995A6] transition-transform duration-150 group-data-[state=open]:rotate-180" })
15428      ] }) }),
15429      /* @__PURE__ */ jsxRuntimeExports.jsx(Portal2, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(Content2$1, { align: "end", sideOffset: 6, className: "z-50 min-w-[212px] rounded-[12px] border border-[#1B1A22]/[0.08] bg-white p-1 shadow-[0_20px_48px_-18px_rgba(27,26,34,0.32)] data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95", children: options.map((option) => {
15430        const isActive = option.surface === activeView;
15431        const OptionIcon = option.icon;
15432        return /* @__PURE__ */ jsxRuntimeExports.jsxs(Item2, { onSelect: () => handleShowView(option.surface, void 0, "user"), className: "flex cursor-pointer select-none items-center gap-2.5 rounded-[8px] px-2 py-1.5 outline-none data-[highlighted]:bg-[#1B1A22]/[0.045]", children: [
15433          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `grid h-6 w-6 flex-shrink-0 place-items-center rounded-[7px] ${isActive ? "bg-[#6E56CF]/[0.10] text-[#6E56CF]" : "bg-[#1B1A22]/[0.045] text-[#6B6878]"}`, children: /* @__PURE__ */ jsxRuntimeExports.jsx(OptionIcon, { size: 13, strokeWidth: 2 }) }),
15434          /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "min-w-0 leading-tight", children: [
15435            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "block text-[12.5px] font-medium text-[#1B1A22]", children: option.label }),
15436            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "block truncate text-[10.5px] text-[#9995A6]", children: option.hint })
15437          ] }),
15438          isActive && /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { size: 13, strokeWidth: 2.75, className: "ml-auto flex-shrink-0 text-[#6E56CF]" })
15439        ] }, option.surface);
15440      }) }) })
15441    ] });
15442  }, [surfaceFacts, aifeaturesSiteToken, activeView, handleShowView]);
15443  const handlePublish = reactExports.useCallback(async () => {
15444    var _a2, _b2, _c2;
15445    if (!website) return;
15446    setPublishBlockers([]);
15447    setIsPublishing(true);
15448    startPolling(1e3);
15449    try {
15450      const {
15451        data: publishData
15452      } = await publishReactWebsite({
15453        variables: {
15454          id: website.id
15455        }
15456      });
15457      const result = publishData == null ? void 0 : publishData.publishReactWebsite;
15458      if (result && !result.success) {
15459        startPolling(idlePollInterval);
15460        setIsPublishing(false);
15461        setPublishBlockers(((_a2 = result.blockers) == null ? void 0 : _a2.length) ? result.blockers : result.error ? [{
15462          code: result.errorCode ?? "publish_failed",
15463          message: result.error
15464        }] : []);
15465      }
15466    } catch (err) {
15467      console.error("Publish mutation failed:", err);
15468      let claimed = false;
15469      let reachable = true;
15470      let freshStatus;
15471      try {
15472        const fresh = (_c2 = (_b2 = await refetch()) == null ? void 0 : _b2.data) == null ? void 0 : _c2.website;
15473        freshStatus = fresh == null ? void 0 : fresh.publishingStatus;
15474        claimed = freshStatus === "In Progress" || (fresh == null ? void 0 : fresh.startedPublishingAt) != null && fresh.startedPublishingAt !== website.startedPublishingAt;
15475      } catch {
15476        reachable = false;
15477      }
15478      if (claimed) {
15479        if (freshStatus !== "In Progress") {
15480          startPolling(idlePollInterval);
15481          setIsPublishing(false);
15482        }
15483        return;
15484      }
15485      startPolling(idlePollInterval);
15486      setIsPublishing(false);
15487      _t.error(reachable ? "Publishing failed to start. Please try again." : "Could not reach the server to start publishing. Check your connection and try again; if it did start, the status will update shortly.");
15488    }
15489  }, [website, refetch, idlePollInterval, startPolling, publishReactWebsite]);
15490  const handlePublishClicked = reactExports.useCallback(() => {
15491    if (isAgentResponding) {
15492      setShowPublishWhileBusy(true);
15493      return;
15494    }
15495    handlePublish();
15496  }, [isAgentResponding, handlePublish]);
15497  if (authLoading || loading && !website) return /* @__PURE__ */ jsxRuntimeExports.jsx(LoadingSpinner, {});
15498  if (error || !website) return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex h-screen flex-col bg-gray-50", children: [
15499    /* @__PURE__ */ jsxRuntimeExports.jsx("header", { className: "px-4 py-1.5", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ReactNavbar, {}) }),
15500    /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorContent, { error })
15501  ] });
15502  if (website.websiteType === "html" || website.websiteType === null) {
15503    return /* @__PURE__ */ jsxRuntimeExports.jsx(LoadingSpinner, {});
15504  }
15505  if (isBeingPrepared) {
15506    return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
15507      /* @__PURE__ */ jsxRuntimeExports.jsx(Metadata, { title: `Preparing ${website.name || "Website"}` }),
15508      /* @__PURE__ */ jsxRuntimeExports.jsx(ReactWebsiteLoadingScreen, { businessName: website.businessName || website.name, previewUrl, containerStatus, footer: (
15509        // Only ask "where did you hear about us?" while the user's first
15510        // website generates. Fail open: show unless we definitively know
15511        // this isn't their first (isFirstWebsite === false).
15512        website.isFirstWebsite === false ? void 0 : /* @__PURE__ */ jsxRuntimeExports.jsx(HdyhauSurveyCard, {})
15513      ) })
15514    ] });
15515  }
15516  const navbarEl = /* @__PURE__ */ jsxRuntimeExports.jsx(ReactNavbar, { website, onPublishClicked: handlePublishClicked, isPublishing, publishingProgress: website.publishingProgress, publishingStep: website.publishingStep, publishingStatus: website.publishingStatus });
15517  const chatEl = /* @__PURE__ */ jsxRuntimeExports.jsx(ChatErrorBoundary, { websiteId: id, resetUrl: previewUrl ? `${previewUrl}/__agent/reset` : void 0, children: /* @__PURE__ */ jsxRuntimeExports.jsx(ReactChatPanel$1, { ref: chatPanelRef, websiteId: id, isContainerReady, website: chatWebsite, expanded: isChatPanelExpanded, onToggleChatPanel: setIsChatPanelExpanded, onRefetchWebsite: handleRefetchWebsite, onRefreshPreview: handleRefreshPreview, myWebsiteAccess, onAIRespondingChange: handleAIRespondingChange, onCommitHashChange: handleCommitHashChange, localAgencyCreditsDelta, onAgencyCreditUsed: handleAgencyCreditUsed, localAiChatMessagesDelta, onAiChatMessageUsed: handleAiChatMessageUsed, onAgentBusyChange: handleAgentBusyChange, onPaymentsDataChanged: handlePaymentsDataChanged, onBusinessDataChanged: handleBusinessDataChanged, onShowView: handleShowView, inlineEditInProgress: editTextModeActive || isEditBusy, pickModeActive, selectedElement, currentPath, onTogglePickMode: handleTogglePickMode, onClearSelection: handleClearSelection, onRestoreSelection: setSelectedElement, isPickerAvailable, isSelectorReady, viteError }) });
15518  const previewEl = /* @__PURE__ */ jsxRuntimeExports.jsx(ReactPreviewPanel$1, { previewUrl, containerStatus: (_c = website.reactWebsiteConfig) == null ? void 0 : _c.containerStatus, containerError: (_d = website.reactWebsiteConfig) == null ? void 0 : _d.containerErrorMessage, pages: toolbarPages, websiteId: website.id, hasCustomDomain: Boolean(website.Domain), domainName: ((_e = website.Domain) == null ? void 0 : _e.domainName) ?? void 0, pickModeActive, onPicked: handlePicked, onPickModeExit: handlePickModeExit, onIframeReload: handleIframeReload, onSelectorReadyChange: handleSelectorReadyChange, onPickerAvailabilityChange: handlePickerAvailabilityChange, onCurrentPathChange: handleCurrentPathChange, onViteError: handleViteError, onViteErrorCleared: handleViteErrorCleared, editTextModeActive, onToggleEditTextMode: handleToggleEditTextMode, onEditTextModeExit: handleEditTextModeExit, onApplyWithAI: handleApplyEditsWithAI, isAgentResponding, onEditBusyChange: handleEditBusyChange, refreshSignal: previewRefreshSignal }, previewKey);
15519  return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
15520    /* @__PURE__ */ jsxRuntimeExports.jsx(Metadata, { title: website.name }),
15521    isClaiming && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-white", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center gap-3", children: [
15522      /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-8 w-8 animate-spin rounded-full border-2 border-gray-300 border-t-black" }),
15523      /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-gray-700", children: "Setting up your website..." })
15524    ] }) }),
15525    /* @__PURE__ */ jsxRuntimeExports.jsx(EditorLayout, { navbar: navbarEl, chat: chatEl, preview: previewEl, merchantView: merchantViewEl, viewSwitcher: viewSwitcherEl, banner: (
15526      // Owner-only: the past-due banner carries the owner's Stripe pay
15527      // link, and the under-review notice is for the owner to act on, so
15528      // neither shows to shared-access collaborators. Under-review first:
15529      // a hidden site is the more urgent of the two.
15530      (myWebsiteAccess == null ? void 0 : myWebsiteAccess.role) === "OWNER" ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
15531        /* @__PURE__ */ jsxRuntimeExports.jsx(ImpersonationReviewBanner, { underReview: website.underReview }),
15532        !website.underReview && /* @__PURE__ */ jsxRuntimeExports.jsx(SiteCaseNoticeBanner, { notice: website.siteCaseNotice }),
15533        /* @__PURE__ */ jsxRuntimeExports.jsx(PaymentPastDueBanner, { paymentPastDue: website.paymentPastDue, pastDueInvoiceUrl: website.pastDueInvoiceUrl, fallbackHref: namedRoutes.reactWebsiteChatSettingsTab({
15534          id: website.id,
15535          tab: "plan"
15536        }) })
15537      ] }) : void 0
15538    ), websiteName: website.name ?? "", chatExpanded: isChatPanelExpanded }),
15539    /* @__PURE__ */ jsxRuntimeExports.jsx(FirstPublishCelebration, { websiteId: id, publishCompletedSignal }),
15540    /* @__PURE__ */ jsxRuntimeExports.jsx(PublishWhileAgentBusyModal, { open: showPublishWhileBusy, onPublish: () => {
15541      setShowPublishWhileBusy(false);
15542      handlePublish();
15543    }, onWait: () => setShowPublishWhileBusy(false) }),
15544    /* @__PURE__ */ jsxRuntimeExports.jsx(PublishBlockedModal, { blockers: publishBlockers, websiteId: website.id, onClose: () => setPublishBlockers([]) }),
15545    showUpgradeModal && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mx-4 max-w-md rounded-2xl bg-white p-8 shadow-2xl", children: [
15546      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-6 text-center", children: [
15547        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-gradient-to-br from-amber-400 to-orange-500 shadow-lg", children: /* @__PURE__ */ jsxRuntimeExports.jsx("i", { className: "fa-solid fa-rocket text-2xl text-white" }) }),
15548        /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "mb-2 text-2xl font-bold text-gray-900", children: "Upgrade to Pro" }),
15549        /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "leading-relaxed text-gray-600", children: upgradeError || "Your website has multiple pages. Upgrade to Pro to publish multi-page websites." })
15550      ] }),
15551      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-3", children: [
15552        /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => {
15553          setShowUpgradeModal(false);
15554          navigate(namedRoutes.reactWebsiteChatSettingsTab({
15555            id: website.id,
15556            tab: "plan"
15557          }));
15558        }, className: "w-full rounded-lg bg-gradient-to-r from-blue-600 to-indigo-600 px-6 py-3 font-semibold text-white shadow-md transition-all hover:from-blue-700 hover:to-indigo-700 hover:shadow-lg", children: "View Upgrade Options" }),
15559        /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => setShowUpgradeModal(false), className: "w-full rounded-lg border border-gray-300 px-6 py-3 font-medium text-gray-700 transition-colors hover:bg-gray-50", children: "Maybe Later" })
15560      ] })
15561    ] }) })
15562  ] });
15563};
15564const ReactWebsiteChatPage = (props) => /* @__PURE__ */ jsxRuntimeExports.jsx(ReactWebsiteChatEditor, { ...props }, props.id);
15565export {
15566  ReactWebsiteChatPage as default
15567};
15568//# sourceMappingURL=ReactWebsiteChatPage-DmjgzGss.js.map
15569
15570//# debugId=ea5d659a-f734-5a99-962b-fd02b29dfbea

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.