@burdenoff/website-sdk 2026.1024.1 → 2026.1027.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/README.md +77 -1
  2. package/dist/components/explore-cta.d.mts +10 -1
  3. package/dist/components/explore-cta.d.ts +10 -1
  4. package/dist/components/explore-cta.js +82 -74
  5. package/dist/components/explore-cta.js.map +1 -1
  6. package/dist/components/explore-cta.mjs +83 -75
  7. package/dist/components/explore-cta.mjs.map +1 -1
  8. package/dist/components/explore.d.mts +2 -2
  9. package/dist/components/explore.d.ts +2 -2
  10. package/dist/components/explore.js +876 -510
  11. package/dist/components/explore.js.map +1 -1
  12. package/dist/components/explore.mjs +877 -511
  13. package/dist/components/explore.mjs.map +1 -1
  14. package/dist/{explore-POqE7J8r.d.mts → explore-BEgq1_0O.d.mts} +65 -3
  15. package/dist/{explore-D6kon7uz.d.ts → explore-CHiP9u-4.d.ts} +65 -3
  16. package/dist/{explore-types-BB8HNFzX.d.mts → explore-types-_9UJu6EA.d.mts} +1 -1
  17. package/dist/{explore-types-BB8HNFzX.d.ts → explore-types-_9UJu6EA.d.ts} +1 -1
  18. package/dist/hooks/index.d.mts +2 -2
  19. package/dist/hooks/index.d.ts +2 -2
  20. package/dist/hooks/index.js +15 -9
  21. package/dist/hooks/index.js.map +1 -1
  22. package/dist/hooks/index.mjs +15 -9
  23. package/dist/hooks/index.mjs.map +1 -1
  24. package/dist/index.d.mts +177 -6
  25. package/dist/index.d.ts +177 -6
  26. package/dist/index.js +1236 -152
  27. package/dist/index.js.map +1 -1
  28. package/dist/index.mjs +1236 -155
  29. package/dist/index.mjs.map +1 -1
  30. package/dist/{use-progressive-reveal-Kr6DwGXG.d.mts → use-progressive-reveal-BFPWbEXy.d.mts} +25 -2
  31. package/dist/{use-progressive-reveal-BVJn9NIr.d.ts → use-progressive-reveal-C0hkdu_i.d.ts} +25 -2
  32. package/package.json +1 -1
@@ -48,10 +48,26 @@ var RTL_LOCALES = /* @__PURE__ */ new Set(["ar"]);
48
48
  function isRtlLocale(locale) {
49
49
  return RTL_LOCALES.has(locale);
50
50
  }
51
+ var PORTFOLIO_PROMPT = {
52
+ en: "Which of your products fits a problem like mine?",
53
+ zh: "\u54EA\u4E2A\u4EA7\u54C1\u9002\u5408\u6211\u8FD9\u6837\u7684\u95EE\u9898\uFF1F",
54
+ hi: "\u092E\u0947\u0930\u0940 \u091C\u0948\u0938\u0940 \u0938\u092E\u0938\u094D\u092F\u093E \u0915\u0947 \u0932\u093F\u090F \u0915\u094C\u0928 \u0938\u093E \u0909\u0924\u094D\u092A\u093E\u0926 \u0938\u0939\u0940 \u0939\u0948?",
55
+ es: "\xBFQu\xE9 producto encaja con un problema como el m\xEDo?",
56
+ ar: "\u0623\u064A \u0645\u0646\u062A\u062C \u064A\u0646\u0627\u0633\u0628 \u0645\u0634\u0643\u0644\u0629 \u0645\u062B\u0644 \u0645\u0634\u0643\u0644\u062A\u064A\u061F",
57
+ ta: "\u0B8E\u0BA9\u0BCD \u0BAA\u0BBF\u0BB0\u0B9A\u0BCD\u0B9A\u0BBF\u0BA9\u0BC8\u0B95\u0BCD\u0B95\u0BC1 \u0B8E\u0BA8\u0BCD\u0BA4\u0BA4\u0BCD \u0BA4\u0BAF\u0BBE\u0BB0\u0BBF\u0BAA\u0BCD\u0BAA\u0BC1 \u0BAA\u0BCA\u0BB0\u0BC1\u0BA8\u0BCD\u0BA4\u0BC1\u0BAE\u0BCD?"
58
+ };
59
+ var PORTFOLIO_PROMPTS = new Set(
60
+ Object.values(PORTFOLIO_PROMPT)
61
+ );
62
+ function isPortfolioPrompt(prompt) {
63
+ return PORTFOLIO_PROMPTS.has(prompt);
64
+ }
51
65
  var EN = {
52
66
  badge: "AI answers, grounded in our documentation",
53
67
  welcomeTitle: "What problem are you trying to solve?",
54
68
  welcomeBody: "Describe the problem, in your own words. You can also ask about a specific product or compare a few. Every answer comes straight from our documentation.",
69
+ welcomeBodyProduct: "Describe the problem in your own words, or ask what {product} does. Every answer comes straight from our documentation.",
70
+ welcomeBodyScoped: "Describe the problem in your own words. Every answer comes straight from our documentation.",
55
71
  tryAsking: "Try asking",
56
72
  focusProduct: "Focus on a product",
57
73
  allProducts: "All products",
@@ -61,6 +77,7 @@ var EN = {
61
77
  nextYouCouldAsk: "Next you could ask",
62
78
  placeholder: "Describe the problem\u2026",
63
79
  placeholderProduct: "Describe a problem, or ask about {product}\u2026",
80
+ placeholderScoped: "Ask about {product}\u2026",
64
81
  send: "Send",
65
82
  stop: "Stop",
66
83
  newChat: "New chat",
@@ -82,6 +99,7 @@ var EN = {
82
99
  attachmentTooMany: "Only {{max}} files can be attached, so {{name}} was skipped.",
83
100
  noAnswer: "I couldn't find this in our documentation, so the answer below is not grounded in a source. Try rephrasing, or",
84
101
  answerDidNotArrive: "That answer didn't come through. Try asking again.",
102
+ toolBudgetScoped: "That question covers more than I can look through in one go. Try asking about one part of it.",
85
103
  askHuman: "ask a human",
86
104
  // An offer, not a demand: this row sits under every answer on 38 marketing sites, so the
87
105
  // wording has to be shruggable. "Was this helpful?" invites; "Please rate this answer"
@@ -135,6 +153,15 @@ var EN = {
135
153
  closeVideo: "Close video",
136
154
  enterFullScreen: "Full screen",
137
155
  exitFullScreen: "Exit full screen",
156
+ panelTitle: "AI assistant",
157
+ panelTitleProduct: "{product} assistant",
158
+ panelViews: "Assistant views",
159
+ tabChat: "Chat",
160
+ tabAvatar: "Avatar",
161
+ closePanel: "Close",
162
+ liveAvatar: "Live avatar",
163
+ avatarComingSoon: "Live avatar coming soon",
164
+ continueInChat: "Continue in Chat",
138
165
  videoUnavailable: "This video can't be played right now.",
139
166
  groundedIn: "What this answer is based on",
140
167
  sourceCountOne: "1 source",
@@ -147,6 +174,7 @@ var EN = {
147
174
  seoTitle: "Describe a problem, get an answer",
148
175
  seoDescription: "Describe the problem in your own words and get an answer drawn from our product documentation, with links to the exact pages it came from.",
149
176
  seoDescriptionProduct: "Describe the problem in your own words and get an answer drawn from {product}'s documentation \u2014 and every other product we build \u2014 with links to the exact pages it came from.",
177
+ seoDescriptionScoped: "Answers about {product}, drawn from {product}'s documentation, with links to the exact pages they came from.",
150
178
  capabilities: [
151
179
  "Grounded in our own docs",
152
180
  "Compare across the ecosystem",
@@ -156,13 +184,15 @@ var EN = {
156
184
  "Every course we run lives in a different spreadsheet.",
157
185
  "We only hear a machine is down after the line has stopped.",
158
186
  "Members quietly stop showing up and we never know why.",
159
- "Which of your products fits a problem like mine?"
187
+ PORTFOLIO_PROMPT.en
160
188
  ]
161
189
  };
162
190
  var ZH = {
163
191
  badge: "\u57FA\u4E8E\u6211\u4EEC\u6587\u6863\u7684 AI \u56DE\u7B54",
164
192
  welcomeTitle: "\u4F60\u60F3\u89E3\u51B3\u4EC0\u4E48\u95EE\u9898\uFF1F",
165
193
  welcomeBody: "\u7528\u4F60\u81EA\u5DF1\u7684\u8BDD\u63CF\u8FF0\u95EE\u9898\u3002\u4F60\u4E5F\u53EF\u4EE5\u8BE2\u95EE\u67D0\u4E00\u6B3E\u4EA7\u54C1\uFF0C\u6216\u6BD4\u8F83\u51E0\u6B3E\u4EA7\u54C1\u3002\u6240\u6709\u56DE\u7B54\u90FD\u76F4\u63A5\u6765\u81EA\u6211\u4EEC\u7684\u6587\u6863\u3002",
194
+ welcomeBodyProduct: "\u7528\u4F60\u81EA\u5DF1\u7684\u8BDD\u63CF\u8FF0\u95EE\u9898\uFF0C\u6216\u8005\u95EE\u95EE {product} \u662F\u505A\u4EC0\u4E48\u7684\u3002\u6240\u6709\u56DE\u7B54\u90FD\u76F4\u63A5\u6765\u81EA\u6211\u4EEC\u7684\u6587\u6863\u3002",
195
+ welcomeBodyScoped: "\u7528\u4F60\u81EA\u5DF1\u7684\u8BDD\u63CF\u8FF0\u95EE\u9898\u3002\u6240\u6709\u56DE\u7B54\u90FD\u76F4\u63A5\u6765\u81EA\u6211\u4EEC\u7684\u6587\u6863\u3002",
166
196
  tryAsking: "\u8BD5\u7740\u95EE",
167
197
  focusProduct: "\u805A\u7126\u67D0\u4E2A\u4EA7\u54C1",
168
198
  allProducts: "\u5168\u90E8\u4EA7\u54C1",
@@ -172,6 +202,7 @@ var ZH = {
172
202
  nextYouCouldAsk: "\u4F60\u8FD8\u53EF\u4EE5\u95EE",
173
203
  placeholder: "\u63CF\u8FF0\u4F60\u7684\u95EE\u9898\u2026",
174
204
  placeholderProduct: "\u63CF\u8FF0\u95EE\u9898\uFF0C\u6216\u8BE2\u95EE {product}\u2026",
205
+ placeholderScoped: "\u5C31 {product} \u63D0\u95EE\u2026",
175
206
  send: "\u53D1\u9001",
176
207
  stop: "\u505C\u6B62",
177
208
  newChat: "\u65B0\u5BF9\u8BDD",
@@ -193,6 +224,7 @@ var ZH = {
193
224
  attachmentTooMany: "\u6700\u591A\u53EA\u80FD\u6DFB\u52A0 {{max}} \u4E2A\u6587\u4EF6\uFF0C\u5DF2\u8DF3\u8FC7 {{name}}\u3002",
194
225
  noAnswer: "\u6211\u5728\u6587\u6863\u4E2D\u6CA1\u6709\u627E\u5230\u76F8\u5173\u5185\u5BB9\uFF0C\u4E0B\u9762\u7684\u56DE\u7B54\u6CA1\u6709\u6765\u6E90\u652F\u6301\u3002\u8BF7\u6362\u4E2A\u8BF4\u6CD5\uFF0C\u6216",
195
226
  answerDidNotArrive: "\u8FD9\u6761\u56DE\u7B54\u6CA1\u6709\u8FD4\u56DE\u3002\u8BF7\u518D\u95EE\u4E00\u6B21\u3002",
227
+ toolBudgetScoped: "\u8FD9\u4E2A\u95EE\u9898\u6D89\u53CA\u7684\u5185\u5BB9\u592A\u591A\uFF0C\u6211\u6CA1\u6CD5\u4E00\u6B21\u67E5\u5B8C\u3002\u8BD5\u7740\u53EA\u95EE\u5176\u4E2D\u7684\u4E00\u90E8\u5206\u3002",
196
228
  askHuman: "\u8054\u7CFB\u6211\u4EEC",
197
229
  feedbackPrompt: "\u8FD9\u4E2A\u56DE\u7B54\u6709\u5E2E\u52A9\u5417\uFF1F",
198
230
  feedbackHelpful: "\u6709\u5E2E\u52A9",
@@ -243,6 +275,15 @@ var ZH = {
243
275
  closeVideo: "\u5173\u95ED\u89C6\u9891",
244
276
  enterFullScreen: "\u5168\u5C4F",
245
277
  exitFullScreen: "\u9000\u51FA\u5168\u5C4F",
278
+ panelTitle: "AI \u52A9\u624B",
279
+ panelTitleProduct: "{product} \u52A9\u624B",
280
+ panelViews: "\u52A9\u624B\u89C6\u56FE",
281
+ tabChat: "\u804A\u5929",
282
+ tabAvatar: "\u865A\u62DF\u5F62\u8C61",
283
+ closePanel: "\u5173\u95ED",
284
+ liveAvatar: "\u5B9E\u65F6\u865A\u62DF\u5F62\u8C61",
285
+ avatarComingSoon: "\u5B9E\u65F6\u865A\u62DF\u5F62\u8C61\u5373\u5C06\u63A8\u51FA",
286
+ continueInChat: "\u5728\u804A\u5929\u4E2D\u7EE7\u7EED",
246
287
  videoUnavailable: "\u6682\u65F6\u65E0\u6CD5\u64AD\u653E\u6B64\u89C6\u9891\u3002",
247
288
  groundedIn: "\u8FD9\u4E2A\u56DE\u7B54\u7684\u4F9D\u636E",
248
289
  sourceCountOne: "1 \u4E2A\u6765\u6E90",
@@ -255,18 +296,21 @@ var ZH = {
255
296
  seoTitle: "\u63CF\u8FF0\u95EE\u9898\uFF0C\u83B7\u5F97\u7B54\u6848",
256
297
  seoDescription: "\u7528\u4F60\u81EA\u5DF1\u7684\u8BDD\u63CF\u8FF0\u95EE\u9898\uFF0C\u5373\u53EF\u83B7\u5F97\u6765\u81EA\u6211\u4EEC\u4EA7\u54C1\u6587\u6863\u7684\u56DE\u7B54\uFF0C\u5E76\u9644\u4E0A\u7B54\u6848\u51FA\u5904\u7684\u9875\u9762\u94FE\u63A5\u3002",
257
298
  seoDescriptionProduct: "\u7528\u4F60\u81EA\u5DF1\u7684\u8BDD\u63CF\u8FF0\u95EE\u9898\uFF0C\u5373\u53EF\u83B7\u5F97\u6765\u81EA {product} \u53CA\u6211\u4EEC\u5176\u4ED6\u4EA7\u54C1\u6587\u6863\u7684\u56DE\u7B54\uFF0C\u5E76\u9644\u4E0A\u7B54\u6848\u51FA\u5904\u7684\u9875\u9762\u94FE\u63A5\u3002",
299
+ seoDescriptionScoped: "\u6709\u5173 {product} \u7684\u56DE\u7B54\uFF0C\u5747\u6765\u81EA {product} \u7684\u6587\u6863\uFF0C\u5E76\u9644\u4E0A\u7B54\u6848\u51FA\u5904\u7684\u9875\u9762\u94FE\u63A5\u3002",
258
300
  capabilities: ["\u57FA\u4E8E\u6211\u4EEC\u81EA\u5DF1\u7684\u6587\u6863", "\u8DE8\u4EA7\u54C1\u5BF9\u6BD4", "\u76F4\u8FBE\u6B63\u786E\u7684\u9875\u9762"],
259
301
  prompts: [
260
302
  "\u6BCF\u95E8\u8BFE\u7A0B\u90FD\u8BB0\u5728\u4E0D\u540C\u7684\u8868\u683C\u91CC\u3002",
261
303
  "\u673A\u5668\u505C\u4E86\uFF0C\u8981\u7B49\u6574\u6761\u7EBF\u505C\u4E0B\u6765\u624D\u77E5\u9053\u3002",
262
304
  "\u4F1A\u5458\u6162\u6162\u5C31\u4E0D\u6765\u4E86\uFF0C\u6211\u4EEC\u4E5F\u4E0D\u77E5\u9053\u4E3A\u4EC0\u4E48\u3002",
263
- "\u54EA\u4E2A\u4EA7\u54C1\u9002\u5408\u6211\u8FD9\u6837\u7684\u95EE\u9898\uFF1F"
305
+ PORTFOLIO_PROMPT.zh
264
306
  ]
265
307
  };
266
308
  var HI = {
267
309
  badge: "\u0939\u092E\u093E\u0930\u0947 \u0926\u0938\u094D\u0924\u093E\u0935\u0947\u091C\u093C\u094B\u0902 \u092A\u0930 \u0906\u0927\u093E\u0930\u093F\u0924 AI \u0909\u0924\u094D\u0924\u0930",
268
310
  welcomeTitle: "\u0906\u092A \u0915\u094C\u0928 \u0938\u0940 \u0938\u092E\u0938\u094D\u092F\u093E \u0939\u0932 \u0915\u0930\u0928\u093E \u091A\u093E\u0939\u0924\u0947 \u0939\u0948\u0902?",
269
311
  welcomeBody: "\u0905\u092A\u0928\u0940 \u0938\u092E\u0938\u094D\u092F\u093E \u0905\u092A\u0928\u0947 \u0936\u092C\u094D\u0926\u094B\u0902 \u092E\u0947\u0902 \u092C\u0924\u093E\u090F\u0902\u0964 \u0906\u092A \u0915\u093F\u0938\u0940 \u090F\u0915 \u0909\u0924\u094D\u092A\u093E\u0926 \u0915\u0947 \u092C\u093E\u0930\u0947 \u092E\u0947\u0902 \u092D\u0940 \u092A\u0942\u091B \u0938\u0915\u0924\u0947 \u0939\u0948\u0902 \u092F\u093E \u0915\u0941\u091B \u0915\u0940 \u0924\u0941\u0932\u0928\u093E \u0915\u0930 \u0938\u0915\u0924\u0947 \u0939\u0948\u0902\u0964 \u0939\u0930 \u0909\u0924\u094D\u0924\u0930 \u0938\u0940\u0927\u0947 \u0939\u092E\u093E\u0930\u0947 \u0926\u0938\u094D\u0924\u093E\u0935\u0947\u091C\u093C \u0938\u0947 \u0906\u0924\u093E \u0939\u0948\u0964",
312
+ welcomeBodyProduct: "\u0905\u092A\u0928\u0940 \u0938\u092E\u0938\u094D\u092F\u093E \u0905\u092A\u0928\u0947 \u0936\u092C\u094D\u0926\u094B\u0902 \u092E\u0947\u0902 \u092C\u0924\u093E\u090F\u0902, \u092F\u093E \u092A\u0942\u091B\u0947\u0902 \u0915\u093F {product} \u0915\u094D\u092F\u093E \u0915\u0930\u0924\u093E \u0939\u0948\u0964 \u0939\u0930 \u0909\u0924\u094D\u0924\u0930 \u0938\u0940\u0927\u0947 \u0939\u092E\u093E\u0930\u0947 \u0926\u0938\u094D\u0924\u093E\u0935\u0947\u091C\u093C \u0938\u0947 \u0906\u0924\u093E \u0939\u0948\u0964",
313
+ welcomeBodyScoped: "\u0905\u092A\u0928\u0940 \u0938\u092E\u0938\u094D\u092F\u093E \u0905\u092A\u0928\u0947 \u0936\u092C\u094D\u0926\u094B\u0902 \u092E\u0947\u0902 \u092C\u0924\u093E\u090F\u0902\u0964 \u0939\u0930 \u0909\u0924\u094D\u0924\u0930 \u0938\u0940\u0927\u0947 \u0939\u092E\u093E\u0930\u0947 \u0926\u0938\u094D\u0924\u093E\u0935\u0947\u091C\u093C \u0938\u0947 \u0906\u0924\u093E \u0939\u0948\u0964",
270
314
  tryAsking: "\u092F\u0939 \u092A\u0942\u091B\u0915\u0930 \u0926\u0947\u0916\u0947\u0902",
271
315
  focusProduct: "\u0915\u093F\u0938\u0940 \u0909\u0924\u094D\u092A\u093E\u0926 \u092A\u0930 \u0927\u094D\u092F\u093E\u0928 \u0926\u0947\u0902",
272
316
  allProducts: "\u0938\u092D\u0940 \u0909\u0924\u094D\u092A\u093E\u0926",
@@ -276,6 +320,7 @@ var HI = {
276
320
  nextYouCouldAsk: "\u0906\u0917\u0947 \u0906\u092A \u092A\u0942\u091B \u0938\u0915\u0924\u0947 \u0939\u0948\u0902",
277
321
  placeholder: "\u0905\u092A\u0928\u0940 \u0938\u092E\u0938\u094D\u092F\u093E \u092C\u0924\u093E\u090F\u0902\u2026",
278
322
  placeholderProduct: "\u0938\u092E\u0938\u094D\u092F\u093E \u092C\u0924\u093E\u090F\u0902, \u092F\u093E {product} \u0915\u0947 \u092C\u093E\u0930\u0947 \u092E\u0947\u0902 \u092A\u0942\u091B\u0947\u0902\u2026",
323
+ placeholderScoped: "{product} \u0915\u0947 \u092C\u093E\u0930\u0947 \u092E\u0947\u0902 \u092A\u0942\u091B\u0947\u0902\u2026",
279
324
  send: "\u092D\u0947\u091C\u0947\u0902",
280
325
  stop: "\u0930\u094B\u0915\u0947\u0902",
281
326
  newChat: "\u0928\u0908 \u092C\u093E\u0924\u091A\u0940\u0924",
@@ -297,6 +342,7 @@ var HI = {
297
342
  attachmentTooMany: "\u0915\u0947\u0935\u0932 {{max}} \u092B\u093C\u093E\u0907\u0932\u0947\u0902 \u091C\u094B\u0921\u093C\u0940 \u091C\u093E \u0938\u0915\u0924\u0940 \u0939\u0948\u0902, \u0907\u0938\u0932\u093F\u090F {{name}} \u091B\u094B\u0921\u093C \u0926\u0940 \u0917\u0908\u0964",
298
343
  noAnswer: "\u092F\u0939 \u092E\u0941\u091D\u0947 \u0939\u092E\u093E\u0930\u0947 \u0926\u0938\u094D\u0924\u093E\u0935\u0947\u091C\u093C\u094B\u0902 \u092E\u0947\u0902 \u0928\u0939\u0940\u0902 \u092E\u093F\u0932\u093E, \u0907\u0938\u0932\u093F\u090F \u0928\u0940\u091A\u0947 \u0926\u093F\u092F\u093E \u0909\u0924\u094D\u0924\u0930 \u0915\u093F\u0938\u0940 \u0938\u094D\u0930\u094B\u0924 \u092A\u0930 \u0906\u0927\u093E\u0930\u093F\u0924 \u0928\u0939\u0940\u0902 \u0939\u0948\u0964 \u0926\u0942\u0938\u0930\u0947 \u0936\u092C\u094D\u0926\u094B\u0902 \u092E\u0947\u0902 \u092A\u0942\u091B\u0947\u0902, \u092F\u093E",
299
344
  answerDidNotArrive: "\u0935\u0939 \u0909\u0924\u094D\u0924\u0930 \u0928\u0939\u0940\u0902 \u0906 \u0938\u0915\u093E\u0964 \u0915\u0943\u092A\u092F\u093E \u0926\u094B\u092C\u093E\u0930\u093E \u092A\u0942\u091B\u0947\u0902\u0964",
345
+ toolBudgetScoped: "\u0907\u0938 \u0938\u0935\u093E\u0932 \u092E\u0947\u0902 \u0907\u0924\u0928\u093E \u0915\u0941\u091B \u0939\u0948 \u0915\u093F \u090F\u0915 \u092C\u093E\u0930 \u092E\u0947\u0902 \u0938\u092C \u0928\u0939\u0940\u0902 \u0926\u0947\u0916\u093E \u091C\u093E \u0938\u0915\u0924\u093E\u0964 \u0907\u0938\u0915\u0947 \u0915\u093F\u0938\u0940 \u090F\u0915 \u0939\u093F\u0938\u094D\u0938\u0947 \u0915\u0947 \u092C\u093E\u0930\u0947 \u092E\u0947\u0902 \u092A\u0942\u091B\u0915\u0930 \u0926\u0947\u0916\u0947\u0902\u0964",
300
346
  askHuman: "\u0939\u092E\u0938\u0947 \u0938\u0902\u092A\u0930\u094D\u0915 \u0915\u0930\u0947\u0902",
301
347
  feedbackPrompt: "\u0915\u094D\u092F\u093E \u092F\u0939 \u0909\u0924\u094D\u0924\u0930 \u092E\u0926\u0926\u0917\u093E\u0930 \u0925\u093E?",
302
348
  feedbackHelpful: "\u092E\u0926\u0926\u0917\u093E\u0930",
@@ -347,6 +393,15 @@ var HI = {
347
393
  closeVideo: "\u0935\u0940\u0921\u093F\u092F\u094B \u092C\u0902\u0926 \u0915\u0930\u0947\u0902",
348
394
  enterFullScreen: "\u092A\u0942\u0930\u094D\u0923 \u0938\u094D\u0915\u094D\u0930\u0940\u0928",
349
395
  exitFullScreen: "\u092A\u0942\u0930\u094D\u0923 \u0938\u094D\u0915\u094D\u0930\u0940\u0928 \u0938\u0947 \u092C\u093E\u0939\u0930 \u0928\u093F\u0915\u0932\u0947\u0902",
396
+ panelTitle: "AI \u0938\u0939\u093E\u092F\u0915",
397
+ panelTitleProduct: "{product} \u0938\u0939\u093E\u092F\u0915",
398
+ panelViews: "\u0938\u0939\u093E\u092F\u0915 \u0926\u0943\u0936\u094D\u092F",
399
+ tabChat: "\u091A\u0948\u091F",
400
+ tabAvatar: "\u0905\u0935\u0924\u093E\u0930",
401
+ closePanel: "\u092C\u0902\u0926 \u0915\u0930\u0947\u0902",
402
+ liveAvatar: "\u0932\u093E\u0907\u0935 \u0905\u0935\u0924\u093E\u0930",
403
+ avatarComingSoon: "\u0932\u093E\u0907\u0935 \u0905\u0935\u0924\u093E\u0930 \u091C\u0932\u094D\u0926 \u0906 \u0930\u0939\u093E \u0939\u0948",
404
+ continueInChat: "\u091A\u0948\u091F \u092E\u0947\u0902 \u091C\u093E\u0930\u0940 \u0930\u0916\u0947\u0902",
350
405
  videoUnavailable: "\u092F\u0939 \u0935\u0940\u0921\u093F\u092F\u094B \u0905\u092D\u0940 \u0928\u0939\u0940\u0902 \u091A\u0932 \u0938\u0915\u0924\u093E\u0964",
351
406
  groundedIn: "\u092F\u0939 \u0909\u0924\u094D\u0924\u0930 \u0915\u093F\u0938 \u092A\u0930 \u0906\u0927\u093E\u0930\u093F\u0924 \u0939\u0948",
352
407
  sourceCountOne: "1 \u0938\u094D\u0930\u094B\u0924",
@@ -359,6 +414,7 @@ var HI = {
359
414
  seoTitle: "\u0938\u092E\u0938\u094D\u092F\u093E \u092C\u0924\u093E\u090F\u0902, \u091C\u0935\u093E\u092C \u092A\u093E\u090F\u0902",
360
415
  seoDescription: "\u0905\u092A\u0928\u0940 \u0938\u092E\u0938\u094D\u092F\u093E \u0905\u092A\u0928\u0947 \u0936\u092C\u094D\u0926\u094B\u0902 \u092E\u0947\u0902 \u092C\u0924\u093E\u090F\u0902 \u0914\u0930 \u0939\u092E\u093E\u0930\u0947 \u0909\u0924\u094D\u092A\u093E\u0926 \u0926\u0938\u094D\u0924\u093E\u0935\u0947\u091C\u093C\u094B\u0902 \u0938\u0947 \u0932\u093F\u092F\u093E \u0917\u092F\u093E \u091C\u0935\u093E\u092C \u092A\u093E\u090F\u0902, \u0938\u093E\u0925 \u092E\u0947\u0902 \u0909\u0928\u094D\u0939\u0940\u0902 \u092A\u0928\u094D\u0928\u094B\u0902 \u0915\u0947 \u0932\u093F\u0902\u0915 \u091C\u0939\u093E\u0901 \u0938\u0947 \u0935\u0939 \u0906\u092F\u093E \u0939\u0948\u0964",
361
416
  seoDescriptionProduct: "\u0905\u092A\u0928\u0940 \u0938\u092E\u0938\u094D\u092F\u093E \u0905\u092A\u0928\u0947 \u0936\u092C\u094D\u0926\u094B\u0902 \u092E\u0947\u0902 \u092C\u0924\u093E\u090F\u0902 \u0914\u0930 {product} \u0924\u0925\u093E \u0939\u092E\u093E\u0930\u0947 \u092C\u093E\u0915\u0940 \u0909\u0924\u094D\u092A\u093E\u0926\u094B\u0902 \u0915\u0947 \u0926\u0938\u094D\u0924\u093E\u0935\u0947\u091C\u093C\u094B\u0902 \u0938\u0947 \u0932\u093F\u092F\u093E \u0917\u092F\u093E \u091C\u0935\u093E\u092C \u092A\u093E\u090F\u0902, \u0938\u093E\u0925 \u092E\u0947\u0902 \u0909\u0928\u094D\u0939\u0940\u0902 \u092A\u0928\u094D\u0928\u094B\u0902 \u0915\u0947 \u0932\u093F\u0902\u0915 \u091C\u0939\u093E\u0901 \u0938\u0947 \u0935\u0939 \u0906\u092F\u093E \u0939\u0948\u0964",
417
+ seoDescriptionScoped: "{product} \u0915\u0947 \u092C\u093E\u0930\u0947 \u092E\u0947\u0902 \u091C\u0935\u093E\u092C \u092A\u093E\u090F\u0902, \u091C\u094B {product} \u0915\u0947 \u0926\u0938\u094D\u0924\u093E\u0935\u0947\u091C\u093C\u094B\u0902 \u0938\u0947 \u0932\u093F\u090F \u0917\u090F \u0939\u0948\u0902, \u0938\u093E\u0925 \u092E\u0947\u0902 \u0909\u0928\u094D\u0939\u0940\u0902 \u092A\u0928\u094D\u0928\u094B\u0902 \u0915\u0947 \u0932\u093F\u0902\u0915 \u091C\u0939\u093E\u0901 \u0938\u0947 \u0935\u0947 \u0906\u090F \u0939\u0948\u0902\u0964",
362
418
  capabilities: [
363
419
  "\u0939\u092E\u093E\u0930\u0947 \u0905\u092A\u0928\u0947 \u0926\u0938\u094D\u0924\u093E\u0935\u0947\u091C\u093C\u094B\u0902 \u092A\u0930 \u0906\u0927\u093E\u0930\u093F\u0924",
364
420
  "\u0938\u092D\u0940 \u0909\u0924\u094D\u092A\u093E\u0926\u094B\u0902 \u0915\u0940 \u0924\u0941\u0932\u0928\u093E \u0915\u0930\u0947\u0902",
@@ -368,13 +424,15 @@ var HI = {
368
424
  "\u0939\u0930 \u0915\u094B\u0930\u094D\u0938 \u0915\u093E \u0939\u093F\u0938\u093E\u092C \u0905\u0932\u0917 \u0936\u0940\u091F \u092E\u0947\u0902 \u0930\u0916\u093E \u091C\u093E\u0924\u093E \u0939\u0948\u0964",
369
425
  "\u092E\u0936\u0940\u0928 \u092C\u0902\u0926 \u0939\u094B\u0928\u0947 \u0915\u093E \u092A\u0924\u093E \u0924\u092D\u0940 \u091A\u0932\u0924\u093E \u0939\u0948 \u091C\u092C \u0932\u093E\u0907\u0928 \u0930\u0941\u0915 \u091C\u093E\u090F\u0964",
370
426
  "\u0938\u0926\u0938\u094D\u092F \u0927\u0940\u0930\u0947-\u0927\u0940\u0930\u0947 \u0906\u0928\u093E \u092C\u0902\u0926 \u0915\u0930 \u0926\u0947\u0924\u0947 \u0939\u0948\u0902, \u0935\u091C\u0939 \u092A\u0924\u093E \u0928\u0939\u0940\u0902 \u091A\u0932\u0924\u0940\u0964",
371
- "\u092E\u0947\u0930\u0940 \u091C\u0948\u0938\u0940 \u0938\u092E\u0938\u094D\u092F\u093E \u0915\u0947 \u0932\u093F\u090F \u0915\u094C\u0928 \u0938\u093E \u0909\u0924\u094D\u092A\u093E\u0926 \u0938\u0939\u0940 \u0939\u0948?"
427
+ PORTFOLIO_PROMPT.hi
372
428
  ]
373
429
  };
374
430
  var ES = {
375
431
  badge: "Respuestas de IA basadas en nuestra documentaci\xF3n",
376
432
  welcomeTitle: "\xBFQu\xE9 problema quieres resolver?",
377
433
  welcomeBody: "Describe el problema con tus propias palabras. Tambi\xE9n puedes preguntar por un producto concreto o comparar varios. Cada respuesta procede directamente de nuestra documentaci\xF3n.",
434
+ welcomeBodyProduct: "Describe el problema con tus propias palabras o pregunta qu\xE9 hace {product}. Cada respuesta procede directamente de nuestra documentaci\xF3n.",
435
+ welcomeBodyScoped: "Describe el problema con tus propias palabras. Cada respuesta procede directamente de nuestra documentaci\xF3n.",
378
436
  tryAsking: "Prueba a preguntar",
379
437
  focusProduct: "Centrarse en un producto",
380
438
  allProducts: "Todos los productos",
@@ -384,6 +442,7 @@ var ES = {
384
442
  nextYouCouldAsk: "Tambi\xE9n puedes preguntar",
385
443
  placeholder: "Describe el problema\u2026",
386
444
  placeholderProduct: "Describe un problema o pregunta por {product}\u2026",
445
+ placeholderScoped: "Pregunta sobre {product}\u2026",
387
446
  send: "Enviar",
388
447
  stop: "Detener",
389
448
  newChat: "Nueva conversaci\xF3n",
@@ -405,6 +464,7 @@ var ES = {
405
464
  attachmentTooMany: "Solo se pueden adjuntar {{max}} archivos, as\xED que se omiti\xF3 {{name}}.",
406
465
  noAnswer: "No he encontrado esto en nuestra documentaci\xF3n, as\xED que la respuesta de abajo no se apoya en ninguna fuente. Prueba a reformularla, o",
407
466
  answerDidNotArrive: "Esa respuesta no lleg\xF3. Int\xE9ntalo de nuevo.",
467
+ toolBudgetScoped: "Esa pregunta abarca m\xE1s de lo que puedo revisar de una vez. Prueba a preguntar por una parte de ella.",
408
468
  askHuman: "habla con una persona",
409
469
  feedbackPrompt: "\xBFTe ha servido?",
410
470
  feedbackHelpful: "Me sirve",
@@ -455,6 +515,15 @@ var ES = {
455
515
  closeVideo: "Cerrar v\xEDdeo",
456
516
  enterFullScreen: "Pantalla completa",
457
517
  exitFullScreen: "Salir de pantalla completa",
518
+ panelTitle: "Asistente de IA",
519
+ panelTitleProduct: "Asistente de {product}",
520
+ panelViews: "Vistas del asistente",
521
+ tabChat: "Chat",
522
+ tabAvatar: "Avatar",
523
+ closePanel: "Cerrar",
524
+ liveAvatar: "Avatar en vivo",
525
+ avatarComingSoon: "Avatar en vivo: pr\xF3ximamente",
526
+ continueInChat: "Continuar en el chat",
458
527
  videoUnavailable: "Ahora mismo no se puede reproducir este v\xEDdeo.",
459
528
  groundedIn: "En qu\xE9 se basa esta respuesta",
460
529
  sourceCountOne: "1 fuente",
@@ -467,6 +536,7 @@ var ES = {
467
536
  seoTitle: "Describe un problema y obt\xE9n una respuesta",
468
537
  seoDescription: "Describe el problema con tus palabras y recibe una respuesta extra\xEDda de la documentaci\xF3n de nuestros productos, con enlaces a las p\xE1ginas exactas de las que procede.",
469
538
  seoDescriptionProduct: "Describe el problema con tus palabras y recibe una respuesta extra\xEDda de la documentaci\xF3n de {product} y del resto de nuestros productos, con enlaces a las p\xE1ginas exactas de las que procede.",
539
+ seoDescriptionScoped: "Respuestas sobre {product}, extra\xEDdas de la documentaci\xF3n de {product}, con enlaces a las p\xE1ginas exactas de las que proceden.",
470
540
  capabilities: [
471
541
  "Basado en nuestra documentaci\xF3n",
472
542
  "Compara todo el ecosistema",
@@ -476,13 +546,15 @@ var ES = {
476
546
  "Cada curso que damos est\xE1 en una hoja de c\xE1lculo distinta.",
477
547
  "Nos enteramos de que una m\xE1quina falla cuando para la l\xEDnea.",
478
548
  "Los socios dejan de venir poco a poco y nunca sabemos por qu\xE9.",
479
- "\xBFQu\xE9 producto encaja con un problema como el m\xEDo?"
549
+ PORTFOLIO_PROMPT.es
480
550
  ]
481
551
  };
482
552
  var AR = {
483
553
  badge: "\u0625\u062C\u0627\u0628\u0627\u062A \u0630\u0643\u0627\u0621 \u0627\u0635\u0637\u0646\u0627\u0639\u064A \u0645\u0628\u0646\u064A\u0629 \u0639\u0644\u0649 \u0648\u062B\u0627\u0626\u0642\u0646\u0627",
484
554
  welcomeTitle: "\u0645\u0627 \u0627\u0644\u0645\u0634\u0643\u0644\u0629 \u0627\u0644\u062A\u064A \u062A\u062D\u0627\u0648\u0644 \u062D\u0644\u0647\u0627\u061F",
485
555
  welcomeBody: "\u0635\u0641 \u0627\u0644\u0645\u0634\u0643\u0644\u0629 \u0628\u0643\u0644\u0645\u0627\u062A\u0643 \u0623\u0646\u062A. \u064A\u0645\u0643\u0646\u0643 \u0623\u064A\u0636\u064B\u0627 \u0627\u0644\u0633\u0624\u0627\u0644 \u0639\u0646 \u0645\u0646\u062A\u062C \u0628\u0639\u064A\u0646\u0647 \u0623\u0648 \u0627\u0644\u0645\u0642\u0627\u0631\u0646\u0629 \u0628\u064A\u0646 \u0639\u062F\u0629 \u0645\u0646\u062A\u062C\u0627\u062A. \u062A\u0623\u062A\u064A \u0643\u0644 \u0625\u062C\u0627\u0628\u0629 \u0645\u0628\u0627\u0634\u0631\u0629 \u0645\u0646 \u0648\u062B\u0627\u0626\u0642\u0646\u0627.",
556
+ welcomeBodyProduct: "\u0635\u0641 \u0627\u0644\u0645\u0634\u0643\u0644\u0629 \u0628\u0643\u0644\u0645\u0627\u062A\u0643 \u0623\u0646\u062A\u060C \u0623\u0648 \u0627\u0633\u0623\u0644 \u0639\u0645\u0651\u0627 \u064A\u0641\u0639\u0644\u0647 {product}. \u062A\u0623\u062A\u064A \u0643\u0644 \u0625\u062C\u0627\u0628\u0629 \u0645\u0628\u0627\u0634\u0631\u0629 \u0645\u0646 \u0648\u062B\u0627\u0626\u0642\u0646\u0627.",
557
+ welcomeBodyScoped: "\u0635\u0641 \u0627\u0644\u0645\u0634\u0643\u0644\u0629 \u0628\u0643\u0644\u0645\u0627\u062A\u0643 \u0623\u0646\u062A. \u062A\u0623\u062A\u064A \u0643\u0644 \u0625\u062C\u0627\u0628\u0629 \u0645\u0628\u0627\u0634\u0631\u0629 \u0645\u0646 \u0648\u062B\u0627\u0626\u0642\u0646\u0627.",
486
558
  tryAsking: "\u062C\u0631\u0651\u0628 \u0623\u0646 \u062A\u0633\u0623\u0644",
487
559
  focusProduct: "\u0627\u0644\u062A\u0631\u0643\u064A\u0632 \u0639\u0644\u0649 \u0645\u0646\u062A\u062C",
488
560
  allProducts: "\u0643\u0644 \u0627\u0644\u0645\u0646\u062A\u062C\u0627\u062A",
@@ -492,6 +564,7 @@ var AR = {
492
564
  nextYouCouldAsk: "\u064A\u0645\u0643\u0646\u0643 \u0623\u0646 \u062A\u0633\u0623\u0644 \u0628\u0639\u062F \u0630\u0644\u0643",
493
565
  placeholder: "\u0635\u0641 \u0627\u0644\u0645\u0634\u0643\u0644\u0629\u2026",
494
566
  placeholderProduct: "\u0635\u0641 \u0645\u0634\u0643\u0644\u062A\u0643 \u0623\u0648 \u0627\u0633\u0623\u0644 \u0639\u0646 {product}\u2026",
567
+ placeholderScoped: "\u0627\u0633\u0623\u0644 \u0639\u0646 {product}\u2026",
495
568
  send: "\u0625\u0631\u0633\u0627\u0644",
496
569
  stop: "\u0625\u064A\u0642\u0627\u0641",
497
570
  newChat: "\u0645\u062D\u0627\u062F\u062B\u0629 \u062C\u062F\u064A\u062F\u0629",
@@ -513,6 +586,7 @@ var AR = {
513
586
  attachmentTooMany: "\u064A\u0645\u0643\u0646 \u0625\u0631\u0641\u0627\u0642 {{max}} \u0645\u0644\u0641\u0627\u062A \u0641\u0642\u0637\u060C \u0644\u0630\u0627 \u062A\u0645 \u062A\u062E\u0637\u064A {{name}}.",
514
587
  noAnswer: "\u0644\u0645 \u0623\u062C\u062F \u0647\u0630\u0627 \u0641\u064A \u0648\u062B\u0627\u0626\u0642\u0646\u0627\u060C \u0644\u0630\u0627 \u0641\u0627\u0644\u0625\u062C\u0627\u0628\u0629 \u0623\u062F\u0646\u0627\u0647 \u063A\u064A\u0631 \u0645\u0633\u062A\u0646\u062F\u0629 \u0625\u0644\u0649 \u0645\u0635\u062F\u0631. \u062D\u0627\u0648\u0644 \u0625\u0639\u0627\u062F\u0629 \u0627\u0644\u0635\u064A\u0627\u063A\u0629\u060C \u0623\u0648",
515
588
  answerDidNotArrive: "\u0644\u0645 \u062A\u0635\u0644 \u0647\u0630\u0647 \u0627\u0644\u0625\u062C\u0627\u0628\u0629. \u064A\u0631\u062C\u0649 \u0627\u0644\u0645\u062D\u0627\u0648\u0644\u0629 \u0645\u0631\u0629 \u0623\u062E\u0631\u0649.",
589
+ toolBudgetScoped: "\u0647\u0630\u0627 \u0627\u0644\u0633\u0624\u0627\u0644 \u064A\u0634\u0645\u0644 \u0623\u0643\u062B\u0631 \u0645\u0645\u0627 \u0623\u0633\u062A\u0637\u064A\u0639 \u0627\u0644\u0628\u062D\u062B \u0641\u064A\u0647 \u062F\u0641\u0639\u0629 \u0648\u0627\u062D\u062F\u0629. \u062C\u0631\u0651\u0628 \u0623\u0646 \u062A\u0633\u0623\u0644 \u0639\u0646 \u062C\u0632\u0621 \u0648\u0627\u062D\u062F \u0645\u0646\u0647.",
516
590
  askHuman: "\u062A\u062D\u062F\u0651\u062B \u0625\u0644\u0649 \u0634\u062E\u0635",
517
591
  feedbackPrompt: "\u0647\u0644 \u0643\u0627\u0646\u062A \u0647\u0630\u0647 \u0627\u0644\u0625\u062C\u0627\u0628\u0629 \u0645\u0641\u064A\u062F\u0629\u061F",
518
592
  feedbackHelpful: "\u0645\u0641\u064A\u062F\u0629",
@@ -563,6 +637,15 @@ var AR = {
563
637
  closeVideo: "\u0625\u063A\u0644\u0627\u0642 \u0627\u0644\u0641\u064A\u062F\u064A\u0648",
564
638
  enterFullScreen: "\u0645\u0644\u0621 \u0627\u0644\u0634\u0627\u0634\u0629",
565
639
  exitFullScreen: "\u0627\u0644\u062E\u0631\u0648\u062C \u0645\u0646 \u0645\u0644\u0621 \u0627\u0644\u0634\u0627\u0634\u0629",
640
+ panelTitle: "\u0645\u0633\u0627\u0639\u062F \u0627\u0644\u0630\u0643\u0627\u0621 \u0627\u0644\u0627\u0635\u0637\u0646\u0627\u0639\u064A",
641
+ panelTitleProduct: "\u0645\u0633\u0627\u0639\u062F {product}",
642
+ panelViews: "\u0637\u0631\u0642 \u0639\u0631\u0636 \u0627\u0644\u0645\u0633\u0627\u0639\u062F",
643
+ tabChat: "\u062F\u0631\u062F\u0634\u0629",
644
+ tabAvatar: "\u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631",
645
+ closePanel: "\u0625\u063A\u0644\u0627\u0642",
646
+ liveAvatar: "\u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631 \u0627\u0644\u0645\u0628\u0627\u0634\u0631",
647
+ avatarComingSoon: "\u0627\u0644\u0623\u0641\u0627\u062A\u0627\u0631 \u0627\u0644\u0645\u0628\u0627\u0634\u0631 \u0642\u0631\u064A\u0628\u064B\u0627",
648
+ continueInChat: "\u0627\u0644\u0645\u062A\u0627\u0628\u0639\u0629 \u0641\u064A \u0627\u0644\u062F\u0631\u062F\u0634\u0629",
566
649
  videoUnavailable: "\u062A\u0639\u0630\u0651\u0631 \u062A\u0634\u063A\u064A\u0644 \u0647\u0630\u0627 \u0627\u0644\u0641\u064A\u062F\u064A\u0648 \u0627\u0644\u0622\u0646.",
567
650
  groundedIn: "\u0639\u0644\u0649 \u0645\u0627\u0630\u0627 \u062A\u0633\u062A\u0646\u062F \u0647\u0630\u0647 \u0627\u0644\u0625\u062C\u0627\u0628\u0629",
568
651
  sourceCountOne: "\u0645\u0635\u062F\u0631 \u0648\u0627\u062D\u062F",
@@ -575,6 +658,7 @@ var AR = {
575
658
  seoTitle: "\u0635\u0641 \u0645\u0634\u0643\u0644\u062A\u0643 \u0648\u0627\u062D\u0635\u0644 \u0639\u0644\u0649 \u0625\u062C\u0627\u0628\u0629",
576
659
  seoDescription: "\u0635\u0641 \u0627\u0644\u0645\u0634\u0643\u0644\u0629 \u0628\u0643\u0644\u0645\u0627\u062A\u0643 \u0648\u0627\u062D\u0635\u0644 \u0639\u0644\u0649 \u0625\u062C\u0627\u0628\u0629 \u0645\u0633\u062A\u0645\u062F\u0629 \u0645\u0646 \u0648\u062B\u0627\u0626\u0642 \u0645\u0646\u062A\u062C\u0627\u062A\u0646\u0627\u060C \u0645\u0639 \u0631\u0648\u0627\u0628\u0637 \u0625\u0644\u0649 \u0627\u0644\u0635\u0641\u062D\u0627\u062A \u0627\u0644\u062A\u064A \u062C\u0627\u0621\u062A \u0645\u0646\u0647\u0627.",
577
660
  seoDescriptionProduct: "\u0635\u0641 \u0627\u0644\u0645\u0634\u0643\u0644\u0629 \u0628\u0643\u0644\u0645\u0627\u062A\u0643 \u0648\u0627\u062D\u0635\u0644 \u0639\u0644\u0649 \u0625\u062C\u0627\u0628\u0629 \u0645\u0633\u062A\u0645\u062F\u0629 \u0645\u0646 \u0648\u062B\u0627\u0626\u0642 {product} \u0648\u0628\u0642\u064A\u0629 \u0645\u0646\u062A\u062C\u0627\u062A\u0646\u0627\u060C \u0645\u0639 \u0631\u0648\u0627\u0628\u0637 \u0625\u0644\u0649 \u0627\u0644\u0635\u0641\u062D\u0627\u062A \u0627\u0644\u062A\u064A \u062C\u0627\u0621\u062A \u0645\u0646\u0647\u0627.",
661
+ seoDescriptionScoped: "\u0625\u062C\u0627\u0628\u0627\u062A \u0639\u0646 {product} \u0645\u0633\u062A\u0645\u062F\u0629 \u0645\u0646 \u0648\u062B\u0627\u0626\u0642 {product}\u060C \u0645\u0639 \u0631\u0648\u0627\u0628\u0637 \u0625\u0644\u0649 \u0627\u0644\u0635\u0641\u062D\u0627\u062A \u0627\u0644\u062A\u064A \u062C\u0627\u0621\u062A \u0645\u0646\u0647\u0627.",
578
662
  capabilities: [
579
663
  "\u0645\u0628\u0646\u064A \u0639\u0644\u0649 \u0648\u062B\u0627\u0626\u0642\u0646\u0627",
580
664
  "\u0642\u0627\u0631\u0646 \u0639\u0628\u0631 \u0627\u0644\u0645\u0646\u0638\u0648\u0645\u0629",
@@ -584,13 +668,15 @@ var AR = {
584
668
  "\u0643\u0644 \u062F\u0648\u0631\u0629 \u062A\u062F\u0631\u064A\u0628\u064A\u0629 \u0644\u062F\u064A\u0646\u0627 \u0641\u064A \u062C\u062F\u0648\u0644 \u0628\u064A\u0627\u0646\u0627\u062A \u0645\u062E\u062A\u0644\u0641.",
585
669
  "\u0644\u0627 \u0646\u0639\u0644\u0645 \u0628\u062A\u0639\u0637\u0644 \u0627\u0644\u0645\u0627\u0643\u064A\u0646\u0629 \u0625\u0644\u0627 \u0628\u0639\u062F \u062A\u0648\u0642\u0641 \u062E\u0637 \u0627\u0644\u0625\u0646\u062A\u0627\u062C.",
586
670
  "\u0623\u0639\u0636\u0627\u0624\u0646\u0627 \u064A\u062A\u0648\u0642\u0641\u0648\u0646 \u0639\u0646 \u0627\u0644\u062D\u0636\u0648\u0631 \u062A\u062F\u0631\u064A\u062C\u064A\u064B\u0627 \u062F\u0648\u0646 \u0623\u0646 \u0646\u0639\u0631\u0641 \u0627\u0644\u0633\u0628\u0628.",
587
- "\u0623\u064A \u0645\u0646\u062A\u062C \u064A\u0646\u0627\u0633\u0628 \u0645\u0634\u0643\u0644\u0629 \u0645\u062B\u0644 \u0645\u0634\u0643\u0644\u062A\u064A\u061F"
671
+ PORTFOLIO_PROMPT.ar
588
672
  ]
589
673
  };
590
674
  var TA = {
591
675
  badge: "\u0B8E\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B86\u0BB5\u0BA3\u0B99\u0BCD\u0B95\u0BB3\u0BC8 \u0B85\u0B9F\u0BBF\u0BAA\u0BCD\u0BAA\u0B9F\u0BC8\u0BAF\u0BBE\u0B95\u0B95\u0BCD \u0B95\u0BCA\u0BA3\u0BCD\u0B9F AI \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD\u0B95\u0BB3\u0BCD",
592
676
  welcomeTitle: "\u0BA8\u0BC0\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B8E\u0BA8\u0BCD\u0BA4\u0B9A\u0BCD \u0B9A\u0BBF\u0B95\u0BCD\u0B95\u0BB2\u0BC8\u0BA4\u0BCD \u0BA4\u0BC0\u0BB0\u0BCD\u0B95\u0BCD\u0B95 \u0BAE\u0BC1\u0BAF\u0BB2\u0BCD\u0B95\u0BBF\u0BB1\u0BC0\u0BB0\u0BCD\u0B95\u0BB3\u0BCD?",
593
677
  welcomeBody: "\u0B9A\u0BBF\u0B95\u0BCD\u0B95\u0BB2\u0BC8 \u0B89\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B9A\u0BCA\u0BA8\u0BCD\u0BA4 \u0BB5\u0BBE\u0BB0\u0BCD\u0BA4\u0BCD\u0BA4\u0BC8\u0B95\u0BB3\u0BBF\u0BB2\u0BCD \u0BB5\u0BBF\u0BB5\u0BB0\u0BBF\u0BAF\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD. \u0B92\u0BB0\u0BC1 \u0B95\u0BC1\u0BB1\u0BBF\u0BAA\u0BCD\u0BAA\u0BBF\u0B9F\u0BCD\u0B9F \u0BA4\u0BAF\u0BBE\u0BB0\u0BBF\u0BAA\u0BCD\u0BAA\u0BC1 \u0BAA\u0BB1\u0BCD\u0BB1\u0BBF\u0BAF\u0BC1\u0BAE\u0BCD \u0B95\u0BC7\u0B9F\u0BCD\u0B95\u0BB2\u0BBE\u0BAE\u0BCD, \u0B9A\u0BBF\u0BB2\u0BB5\u0BB1\u0BCD\u0BB1\u0BC8 \u0B92\u0BAA\u0BCD\u0BAA\u0BBF\u0B9F\u0BB5\u0BC1\u0BAE\u0BCD \u0B9A\u0BC6\u0BAF\u0BCD\u0BAF\u0BB2\u0BBE\u0BAE\u0BCD. \u0B92\u0BB5\u0BCD\u0BB5\u0BCA\u0BB0\u0BC1 \u0BAA\u0BA4\u0BBF\u0BB2\u0BC1\u0BAE\u0BCD \u0B8E\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B86\u0BB5\u0BA3\u0BAA\u0BCD\u0BAA\u0B9F\u0BC1\u0BA4\u0BCD\u0BA4\u0BB2\u0BBF\u0BB2\u0BBF\u0BB0\u0BC1\u0BA8\u0BCD\u0BA4\u0BC1 \u0BA8\u0BC7\u0BB0\u0B9F\u0BBF\u0BAF\u0BBE\u0B95 \u0BB5\u0BB0\u0BC1\u0B95\u0BBF\u0BB1\u0BA4\u0BC1.",
678
+ welcomeBodyProduct: "\u0B9A\u0BBF\u0B95\u0BCD\u0B95\u0BB2\u0BC8 \u0B89\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B9A\u0BCA\u0BA8\u0BCD\u0BA4 \u0BB5\u0BBE\u0BB0\u0BCD\u0BA4\u0BCD\u0BA4\u0BC8\u0B95\u0BB3\u0BBF\u0BB2\u0BCD \u0BB5\u0BBF\u0BB5\u0BB0\u0BBF\u0BAF\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD, \u0B85\u0BB2\u0BCD\u0BB2\u0BA4\u0BC1 {product} \u0B8E\u0BA9\u0BCD\u0BA9 \u0B9A\u0BC6\u0BAF\u0BCD\u0B95\u0BBF\u0BB1\u0BA4\u0BC1 \u0B8E\u0BA9\u0BCD\u0BB1\u0BC1 \u0B95\u0BC7\u0BB3\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD. \u0B92\u0BB5\u0BCD\u0BB5\u0BCA\u0BB0\u0BC1 \u0BAA\u0BA4\u0BBF\u0BB2\u0BC1\u0BAE\u0BCD \u0B8E\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B86\u0BB5\u0BA3\u0BAA\u0BCD\u0BAA\u0B9F\u0BC1\u0BA4\u0BCD\u0BA4\u0BB2\u0BBF\u0BB2\u0BBF\u0BB0\u0BC1\u0BA8\u0BCD\u0BA4\u0BC1 \u0BA8\u0BC7\u0BB0\u0B9F\u0BBF\u0BAF\u0BBE\u0B95 \u0BB5\u0BB0\u0BC1\u0B95\u0BBF\u0BB1\u0BA4\u0BC1.",
679
+ welcomeBodyScoped: "\u0B9A\u0BBF\u0B95\u0BCD\u0B95\u0BB2\u0BC8 \u0B89\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B9A\u0BCA\u0BA8\u0BCD\u0BA4 \u0BB5\u0BBE\u0BB0\u0BCD\u0BA4\u0BCD\u0BA4\u0BC8\u0B95\u0BB3\u0BBF\u0BB2\u0BCD \u0BB5\u0BBF\u0BB5\u0BB0\u0BBF\u0BAF\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD. \u0B92\u0BB5\u0BCD\u0BB5\u0BCA\u0BB0\u0BC1 \u0BAA\u0BA4\u0BBF\u0BB2\u0BC1\u0BAE\u0BCD \u0B8E\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B86\u0BB5\u0BA3\u0BAA\u0BCD\u0BAA\u0B9F\u0BC1\u0BA4\u0BCD\u0BA4\u0BB2\u0BBF\u0BB2\u0BBF\u0BB0\u0BC1\u0BA8\u0BCD\u0BA4\u0BC1 \u0BA8\u0BC7\u0BB0\u0B9F\u0BBF\u0BAF\u0BBE\u0B95 \u0BB5\u0BB0\u0BC1\u0B95\u0BBF\u0BB1\u0BA4\u0BC1.",
594
680
  tryAsking: "\u0B87\u0BA4\u0BC8\u0B95\u0BCD \u0B95\u0BC7\u0B9F\u0BCD\u0B9F\u0BC1\u0BAA\u0BCD \u0BAA\u0BBE\u0BB0\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD",
595
681
  focusProduct: "\u0B92\u0BB0\u0BC1 \u0BA4\u0BAF\u0BBE\u0BB0\u0BBF\u0BAA\u0BCD\u0BAA\u0BBF\u0BB2\u0BCD \u0B95\u0BB5\u0BA9\u0BAE\u0BCD",
596
682
  allProducts: "\u0B85\u0BA9\u0BC8\u0BA4\u0BCD\u0BA4\u0BC1 \u0BA4\u0BAF\u0BBE\u0BB0\u0BBF\u0BAA\u0BCD\u0BAA\u0BC1\u0B95\u0BB3\u0BCD",
@@ -600,6 +686,7 @@ var TA = {
600
686
  nextYouCouldAsk: "\u0B85\u0B9F\u0BC1\u0BA4\u0BCD\u0BA4\u0BC1 \u0BA8\u0BC0\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B95\u0BC7\u0B9F\u0BCD\u0B95\u0BB2\u0BBE\u0BAE\u0BCD",
601
687
  placeholder: "\u0B9A\u0BBF\u0B95\u0BCD\u0B95\u0BB2\u0BC8 \u0BB5\u0BBF\u0BB5\u0BB0\u0BBF\u0BAF\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD\u2026",
602
688
  placeholderProduct: "\u0B9A\u0BBF\u0B95\u0BCD\u0B95\u0BB2\u0BC8 \u0BB5\u0BBF\u0BB5\u0BB0\u0BBF\u0BAF\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD, \u0B85\u0BB2\u0BCD\u0BB2\u0BA4\u0BC1 {product} \u0BAA\u0BB1\u0BCD\u0BB1\u0BBF\u0B95\u0BCD \u0B95\u0BC7\u0BB3\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD\u2026",
689
+ placeholderScoped: "{product} \u0BAA\u0BB1\u0BCD\u0BB1\u0BBF\u0B95\u0BCD \u0B95\u0BC7\u0BB3\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD\u2026",
603
690
  send: "\u0B85\u0BA9\u0BC1\u0BAA\u0BCD\u0BAA\u0BC1",
604
691
  stop: "\u0BA8\u0BBF\u0BB1\u0BC1\u0BA4\u0BCD\u0BA4\u0BC1",
605
692
  newChat: "\u0BAA\u0BC1\u0BA4\u0BBF\u0BAF \u0B89\u0BB0\u0BC8\u0BAF\u0BBE\u0B9F\u0BB2\u0BCD",
@@ -621,6 +708,7 @@ var TA = {
621
708
  attachmentTooMany: "{{max}} \u0B95\u0BCB\u0BAA\u0BCD\u0BAA\u0BC1\u0B95\u0BB3\u0BCD \u0BAE\u0B9F\u0BCD\u0B9F\u0BC1\u0BAE\u0BC7 \u0B87\u0BA3\u0BC8\u0B95\u0BCD\u0B95 \u0BAE\u0BC1\u0B9F\u0BBF\u0BAF\u0BC1\u0BAE\u0BCD, \u0B8E\u0BA9\u0BB5\u0BC7 {{name}} \u0BA4\u0BB5\u0BBF\u0BB0\u0BCD\u0B95\u0BCD\u0B95\u0BAA\u0BCD\u0BAA\u0B9F\u0BCD\u0B9F\u0BA4\u0BC1.",
622
709
  noAnswer: "\u0B87\u0BA4\u0BC1 \u0B8E\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B86\u0BB5\u0BA3\u0B99\u0BCD\u0B95\u0BB3\u0BBF\u0BB2\u0BCD \u0B95\u0BBF\u0B9F\u0BC8\u0B95\u0BCD\u0B95\u0BB5\u0BBF\u0BB2\u0BCD\u0BB2\u0BC8, \u0B8E\u0BA9\u0BB5\u0BC7 \u0B95\u0BC0\u0BB4\u0BC7 \u0B89\u0BB3\u0BCD\u0BB3 \u0BAA\u0BA4\u0BBF\u0BB2\u0BC1\u0B95\u0BCD\u0B95\u0BC1 \u0BAE\u0BC2\u0BB2\u0BAE\u0BCD \u0B87\u0BB2\u0BCD\u0BB2\u0BC8. \u0BB5\u0BC7\u0BB1\u0BC1 \u0BB5\u0B95\u0BC8\u0BAF\u0BBF\u0BB2\u0BCD \u0B95\u0BC7\u0BB3\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD, \u0B85\u0BB2\u0BCD\u0BB2\u0BA4\u0BC1",
623
710
  answerDidNotArrive: "\u0B85\u0BA8\u0BCD\u0BA4\u0BAA\u0BCD \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD \u0BB5\u0BB0\u0BB5\u0BBF\u0BB2\u0BCD\u0BB2\u0BC8. \u0BAE\u0BC0\u0BA3\u0BCD\u0B9F\u0BC1\u0BAE\u0BCD \u0B95\u0BC7\u0B9F\u0BCD\u0B9F\u0BC1\u0BAA\u0BCD \u0BAA\u0BBE\u0BB0\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD.",
711
+ toolBudgetScoped: "\u0B87\u0BA8\u0BCD\u0BA4\u0B95\u0BCD \u0B95\u0BC7\u0BB3\u0BCD\u0BB5\u0BBF\u0BAF\u0BBF\u0BB2\u0BCD \u0B92\u0BB0\u0BC7 \u0BAE\u0BC1\u0BB1\u0BC8\u0BAF\u0BBF\u0BB2\u0BCD \u0B8E\u0BA9\u0BCD\u0BA9\u0BBE\u0BB2\u0BCD \u0BAA\u0BBE\u0BB0\u0BCD\u0B95\u0BCD\u0B95 \u0BAE\u0BC1\u0B9F\u0BBF\u0BB5\u0BA4\u0BC8 \u0BB5\u0BBF\u0B9F \u0B85\u0BA4\u0BBF\u0B95\u0BAE\u0BCD \u0B89\u0BB3\u0BCD\u0BB3\u0BA4\u0BC1. \u0B85\u0BA4\u0BA9\u0BCD \u0B92\u0BB0\u0BC1 \u0BAA\u0B95\u0BC1\u0BA4\u0BBF\u0BAF\u0BC8\u0BAA\u0BCD \u0BAA\u0BB1\u0BCD\u0BB1\u0BBF\u0B95\u0BCD \u0B95\u0BC7\u0B9F\u0BCD\u0B9F\u0BC1\u0BAA\u0BCD \u0BAA\u0BBE\u0BB0\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD.",
624
712
  askHuman: "\u0B8E\u0B99\u0BCD\u0B95\u0BB3\u0BC8\u0BA4\u0BCD \u0BA4\u0BCA\u0B9F\u0BB0\u0BCD\u0BAA\u0BC1 \u0B95\u0BCA\u0BB3\u0BCD\u0BB3\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD",
625
713
  feedbackPrompt: "\u0B87\u0BA8\u0BCD\u0BA4\u0BAA\u0BCD \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD \u0BAA\u0BAF\u0BA9\u0BC1\u0BB3\u0BCD\u0BB3\u0BA4\u0BBE\u0B95 \u0B87\u0BB0\u0BC1\u0BA8\u0BCD\u0BA4\u0BA4\u0BBE?",
626
714
  feedbackHelpful: "\u0BAA\u0BAF\u0BA9\u0BC1\u0BB3\u0BCD\u0BB3\u0BA4\u0BC1",
@@ -671,6 +759,15 @@ var TA = {
671
759
  closeVideo: "\u0BB5\u0BC0\u0B9F\u0BBF\u0BAF\u0BCB\u0BB5\u0BC8 \u0BAE\u0BC2\u0B9F\u0BC1",
672
760
  enterFullScreen: "\u0BAE\u0BC1\u0BB4\u0BC1\u0BA4\u0BCD \u0BA4\u0BBF\u0BB0\u0BC8",
673
761
  exitFullScreen: "\u0BAE\u0BC1\u0BB4\u0BC1\u0BA4\u0BCD \u0BA4\u0BBF\u0BB0\u0BC8\u0BAF\u0BBF\u0BB2\u0BBF\u0BB0\u0BC1\u0BA8\u0BCD\u0BA4\u0BC1 \u0BB5\u0BC6\u0BB3\u0BBF\u0BAF\u0BC7\u0BB1\u0BC1",
762
+ panelTitle: "AI \u0B89\u0BA4\u0BB5\u0BBF\u0BAF\u0BBE\u0BB3\u0BB0\u0BCD",
763
+ panelTitleProduct: "{product} \u0B89\u0BA4\u0BB5\u0BBF\u0BAF\u0BBE\u0BB3\u0BB0\u0BCD",
764
+ panelViews: "\u0B89\u0BA4\u0BB5\u0BBF\u0BAF\u0BBE\u0BB3\u0BB0\u0BCD \u0B95\u0BBE\u0B9F\u0BCD\u0B9A\u0BBF\u0B95\u0BB3\u0BCD",
765
+ tabChat: "\u0B85\u0BB0\u0B9F\u0BCD\u0B9F\u0BC8",
766
+ tabAvatar: "\u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD",
767
+ closePanel: "\u0BAE\u0BC2\u0B9F\u0BC1",
768
+ liveAvatar: "\u0BA8\u0BC7\u0BB0\u0BB2\u0BC8 \u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD",
769
+ avatarComingSoon: "\u0BA8\u0BC7\u0BB0\u0BB2\u0BC8 \u0B85\u0BB5\u0BA4\u0BBE\u0BB0\u0BCD \u0BB5\u0BBF\u0BB0\u0BC8\u0BB5\u0BBF\u0BB2\u0BCD",
770
+ continueInChat: "\u0B85\u0BB0\u0B9F\u0BCD\u0B9F\u0BC8\u0BAF\u0BBF\u0BB2\u0BCD \u0BA4\u0BCA\u0B9F\u0BB0\u0BB5\u0BC1\u0BAE\u0BCD",
674
771
  videoUnavailable: "\u0B87\u0BA8\u0BCD\u0BA4 \u0BB5\u0BC0\u0B9F\u0BBF\u0BAF\u0BCB\u0BB5\u0BC8 \u0B87\u0BAA\u0BCD\u0BAA\u0BCB\u0BA4\u0BC1 \u0B87\u0BAF\u0B95\u0BCD\u0B95 \u0BAE\u0BC1\u0B9F\u0BBF\u0BAF\u0BB5\u0BBF\u0BB2\u0BCD\u0BB2\u0BC8.",
675
772
  groundedIn: "\u0B87\u0BA8\u0BCD\u0BA4\u0BAA\u0BCD \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD \u0B8E\u0BA4\u0BC8 \u0B85\u0B9F\u0BBF\u0BAA\u0BCD\u0BAA\u0B9F\u0BC8\u0BAF\u0BBE\u0B95\u0B95\u0BCD \u0B95\u0BCA\u0BA3\u0BCD\u0B9F\u0BA4\u0BC1",
676
773
  sourceCountOne: "1 \u0BAE\u0BC2\u0BB2\u0BAE\u0BCD",
@@ -683,6 +780,7 @@ var TA = {
683
780
  seoTitle: "\u0B9A\u0BBF\u0B95\u0BCD\u0B95\u0BB2\u0BC8 \u0BB5\u0BBF\u0BB5\u0BB0\u0BBF\u0BAF\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD, \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD \u0BAA\u0BC6\u0BB1\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD",
684
781
  seoDescription: "\u0B9A\u0BBF\u0B95\u0BCD\u0B95\u0BB2\u0BC8 \u0B89\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B9A\u0BCA\u0BA8\u0BCD\u0BA4 \u0BB5\u0BBE\u0BB0\u0BCD\u0BA4\u0BCD\u0BA4\u0BC8\u0B95\u0BB3\u0BBF\u0BB2\u0BCD \u0BB5\u0BBF\u0BB5\u0BB0\u0BBF\u0BAF\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD; \u0B8E\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0BA4\u0BAF\u0BBE\u0BB0\u0BBF\u0BAA\u0BCD\u0BAA\u0BC1 \u0B86\u0BB5\u0BA3\u0B99\u0BCD\u0B95\u0BB3\u0BBF\u0BB2\u0BBF\u0BB0\u0BC1\u0BA8\u0BCD\u0BA4\u0BC1 \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD \u0B95\u0BBF\u0B9F\u0BC8\u0B95\u0BCD\u0B95\u0BC1\u0BAE\u0BCD, \u0B85\u0BA4\u0BC1 \u0BB5\u0BA8\u0BCD\u0BA4 \u0BAA\u0B95\u0BCD\u0B95\u0B99\u0BCD\u0B95\u0BB3\u0BC1\u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0B87\u0BA3\u0BC8\u0BAA\u0BCD\u0BAA\u0BC1\u0B95\u0BB3\u0BC1\u0B9F\u0BA9\u0BCD.",
685
782
  seoDescriptionProduct: "{product} \u0BAE\u0BB1\u0BCD\u0BB1\u0BC1\u0BAE\u0BCD \u0B8E\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0BAA\u0BBF\u0BB1 \u0BA4\u0BAF\u0BBE\u0BB0\u0BBF\u0BAA\u0BCD\u0BAA\u0BC1\u0B95\u0BB3\u0BBF\u0BA9\u0BCD \u0B86\u0BB5\u0BA3\u0B99\u0BCD\u0B95\u0BB3\u0BBF\u0BB2\u0BBF\u0BB0\u0BC1\u0BA8\u0BCD\u0BA4\u0BC1 \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD \u0BAA\u0BC6\u0BB1, \u0B9A\u0BBF\u0B95\u0BCD\u0B95\u0BB2\u0BC8 \u0B89\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B9A\u0BCA\u0BA8\u0BCD\u0BA4 \u0BB5\u0BBE\u0BB0\u0BCD\u0BA4\u0BCD\u0BA4\u0BC8\u0B95\u0BB3\u0BBF\u0BB2\u0BCD \u0BB5\u0BBF\u0BB5\u0BB0\u0BBF\u0BAF\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u2014 \u0B85\u0BA4\u0BC1 \u0BB5\u0BA8\u0BCD\u0BA4 \u0BAA\u0B95\u0BCD\u0B95\u0B99\u0BCD\u0B95\u0BB3\u0BC1\u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0B87\u0BA3\u0BC8\u0BAA\u0BCD\u0BAA\u0BC1\u0B95\u0BB3\u0BC1\u0B9F\u0BA9\u0BCD.",
783
+ seoDescriptionScoped: "{product} \u0BAA\u0BB1\u0BCD\u0BB1\u0BBF\u0BAF \u0BAA\u0BA4\u0BBF\u0BB2\u0BCD\u0B95\u0BB3\u0BCD, {product} \u0B86\u0BB5\u0BA3\u0B99\u0BCD\u0B95\u0BB3\u0BBF\u0BB2\u0BBF\u0BB0\u0BC1\u0BA8\u0BCD\u0BA4\u0BC1, \u0B85\u0BB5\u0BC8 \u0BB5\u0BA8\u0BCD\u0BA4 \u0BAA\u0B95\u0BCD\u0B95\u0B99\u0BCD\u0B95\u0BB3\u0BC1\u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0B87\u0BA3\u0BC8\u0BAA\u0BCD\u0BAA\u0BC1\u0B95\u0BB3\u0BC1\u0B9F\u0BA9\u0BCD.",
686
784
  capabilities: [
687
785
  "\u0B8E\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B9A\u0BCA\u0BA8\u0BCD\u0BA4 \u0B86\u0BB5\u0BA3\u0B99\u0BCD\u0B95\u0BB3\u0BBF\u0BA9\u0BCD \u0B85\u0B9F\u0BBF\u0BAA\u0BCD\u0BAA\u0B9F\u0BC8\u0BAF\u0BBF\u0BB2\u0BCD",
688
786
  "\u0BA4\u0BAF\u0BBE\u0BB0\u0BBF\u0BAA\u0BCD\u0BAA\u0BC1\u0B95\u0BB3\u0BC8 \u0B92\u0BAA\u0BCD\u0BAA\u0BBF\u0B9F\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD",
@@ -692,7 +790,7 @@ var TA = {
692
790
  "\u0B92\u0BB5\u0BCD\u0BB5\u0BCA\u0BB0\u0BC1 \u0BAA\u0BAF\u0BBF\u0BB1\u0BCD\u0B9A\u0BBF \u0BB5\u0B95\u0BC1\u0BAA\u0BCD\u0BAA\u0BC1\u0BAE\u0BCD \u0BB5\u0BC6\u0BB5\u0BCD\u0BB5\u0BC7\u0BB1\u0BC1 \u0BB5\u0BBF\u0BB0\u0BBF\u0BA4\u0BBE\u0BB3\u0BBF\u0BB2\u0BCD \u0B89\u0BB3\u0BCD\u0BB3\u0BA4\u0BC1.",
693
791
  "\u0B87\u0BAF\u0BA8\u0BCD\u0BA4\u0BBF\u0BB0\u0BAE\u0BCD \u0BA8\u0BBF\u0BA9\u0BCD\u0BB1\u0BA4\u0BC1 \u0BB2\u0BC8\u0BA9\u0BCD \u0BA8\u0BBF\u0BB1\u0BCD\u0B95\u0BC1\u0BAE\u0BCD\u0BAA\u0BCB\u0BA4\u0BC1\u0BA4\u0BBE\u0BA9\u0BCD \u0BA4\u0BC6\u0BB0\u0BBF\u0BAF \u0BB5\u0BB0\u0BC1\u0B95\u0BBF\u0BB1\u0BA4\u0BC1.",
694
792
  "\u0B89\u0BB1\u0BC1\u0BAA\u0BCD\u0BAA\u0BBF\u0BA9\u0BB0\u0BCD\u0B95\u0BB3\u0BCD \u0BAE\u0BC6\u0BB2\u0BCD\u0BB2 \u0BB5\u0BB0\u0BC1\u0BB5\u0BA4\u0BC8 \u0BA8\u0BBF\u0BB1\u0BC1\u0BA4\u0BCD\u0BA4\u0BC1\u0B95\u0BBF\u0BB1\u0BBE\u0BB0\u0BCD\u0B95\u0BB3\u0BCD, \u0B95\u0BBE\u0BB0\u0BA3\u0BAE\u0BCD \u0BA4\u0BC6\u0BB0\u0BBF\u0BAF\u0BBE\u0BA4\u0BC1.",
695
- "\u0B8E\u0BA9\u0BCD \u0BAA\u0BBF\u0BB0\u0B9A\u0BCD\u0B9A\u0BBF\u0BA9\u0BC8\u0B95\u0BCD\u0B95\u0BC1 \u0B8E\u0BA8\u0BCD\u0BA4\u0BA4\u0BCD \u0BA4\u0BAF\u0BBE\u0BB0\u0BBF\u0BAA\u0BCD\u0BAA\u0BC1 \u0BAA\u0BCA\u0BB0\u0BC1\u0BA8\u0BCD\u0BA4\u0BC1\u0BAE\u0BCD?"
793
+ PORTFOLIO_PROMPT.ta
696
794
  ]
697
795
  };
698
796
  var STRINGS = {
@@ -1687,6 +1785,230 @@ function ExploreAnswerBody({
1687
1785
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("boff-prose boff-explore-body min-w-0", className), children: /* @__PURE__ */ jsxRuntime.jsx(AnswerScopeContext.Provider, { value: scope, children: /* @__PURE__ */ jsxRuntime.jsx(Markdown, { components: overrides, rehypePlugins, children }) }) });
1688
1786
  }
1689
1787
 
1788
+ // src/client/security.ts
1789
+ var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "::1"]);
1790
+ var RESERVED_HEADERS = /* @__PURE__ */ new Set([
1791
+ "authorization",
1792
+ "cookie",
1793
+ "x-actor-id",
1794
+ "x-actor-type",
1795
+ "x-consent-granted-by",
1796
+ "x-consent-scope",
1797
+ "x-consent-granted-at",
1798
+ "x-consent-expires-at"
1799
+ ]);
1800
+ function validateGatewayUrl(value) {
1801
+ let url;
1802
+ try {
1803
+ url = new URL(value);
1804
+ } catch {
1805
+ throw new Error("Gateway URL must be a valid absolute URL");
1806
+ }
1807
+ if (url.protocol === "https:") {
1808
+ return url.toString();
1809
+ }
1810
+ if (url.protocol === "http:" && LOOPBACK_HOSTS.has(url.hostname.toLowerCase())) {
1811
+ return url.toString();
1812
+ }
1813
+ throw new Error("Gateway URL must use HTTPS unless it targets localhost");
1814
+ }
1815
+ function sanitizeHeaders(headers) {
1816
+ if (!headers) return void 0;
1817
+ return Object.fromEntries(
1818
+ Object.entries(headers).filter(
1819
+ ([key]) => !RESERVED_HEADERS.has(key.toLowerCase())
1820
+ )
1821
+ );
1822
+ }
1823
+ var CF_ACCESS_GATED_HOSTS = /* @__PURE__ */ new Set([
1824
+ "alphagraphql.burdenoff.com",
1825
+ "alphagraphqlworkspaces.burdenoff.com"
1826
+ ]);
1827
+ function cfAccessHeaders(gatewayUrl, cfAccess) {
1828
+ const clientId = cfAccess?.clientId?.trim();
1829
+ const clientSecret = cfAccess?.clientSecret?.trim();
1830
+ if (!clientId || !clientSecret) return {};
1831
+ let host;
1832
+ try {
1833
+ host = new URL(gatewayUrl).hostname.toLowerCase();
1834
+ } catch {
1835
+ return {};
1836
+ }
1837
+ if (!CF_ACCESS_GATED_HOSTS.has(host)) return {};
1838
+ return {
1839
+ "CF-Access-Client-Id": clientId,
1840
+ "CF-Access-Client-Secret": clientSecret
1841
+ };
1842
+ }
1843
+
1844
+ // src/client/graphql-client.ts
1845
+ var _WebSDKClient = class _WebSDKClient {
1846
+ constructor(config) {
1847
+ __publicField(this, "config");
1848
+ __publicField(this, "queryCache", /* @__PURE__ */ new Map());
1849
+ __publicField(this, "inflight", /* @__PURE__ */ new Map());
1850
+ this.config = {
1851
+ ...config,
1852
+ gatewayUrl: validateGatewayUrl(config.gatewayUrl),
1853
+ headers: sanitizeHeaders(config.headers)
1854
+ };
1855
+ }
1856
+ getConfig() {
1857
+ return this.config;
1858
+ }
1859
+ /**
1860
+ * Execute a GraphQL query (with deduplication and caching).
1861
+ *
1862
+ * Pass `{ cache: false }` to bypass the cache entirely — required for poll
1863
+ * loops, where every tick must reach the network.
1864
+ */
1865
+ async query(query, variables, options) {
1866
+ if (options?.cache === false) {
1867
+ return this.request(query, variables, true, options.timeoutMs);
1868
+ }
1869
+ const cacheKey = JSON.stringify({ query, variables });
1870
+ const cached = this.queryCache.get(cacheKey);
1871
+ if (cached) {
1872
+ if (Date.now() - cached.ts < _WebSDKClient.CACHE_TTL) {
1873
+ return cached.data;
1874
+ }
1875
+ this.queryCache.delete(cacheKey);
1876
+ }
1877
+ const existing = this.inflight.get(cacheKey);
1878
+ if (existing) {
1879
+ return existing;
1880
+ }
1881
+ const promise = this.request(query, variables, true, options?.timeoutMs).then((result) => {
1882
+ if (result.data && !result.errors?.length) {
1883
+ if (this.queryCache.size >= _WebSDKClient.MAX_CACHE_ENTRIES) {
1884
+ const oldestEntry = this.queryCache.keys().next().value;
1885
+ if (oldestEntry) {
1886
+ this.queryCache.delete(oldestEntry);
1887
+ }
1888
+ }
1889
+ this.queryCache.set(cacheKey, { data: result, ts: Date.now() });
1890
+ }
1891
+ return result;
1892
+ }).finally(() => {
1893
+ this.inflight.delete(cacheKey);
1894
+ });
1895
+ this.inflight.set(cacheKey, promise);
1896
+ return promise;
1897
+ }
1898
+ /**
1899
+ * Execute a GraphQL mutation
1900
+ */
1901
+ async mutate(mutation, variables, options) {
1902
+ return this.request(mutation, variables, false, options?.timeoutMs);
1903
+ }
1904
+ /** HTTP statuses worth another attempt — transient server/edge conditions. */
1905
+ static isRetriableStatus(status) {
1906
+ return status === 429 || status === 408 || status >= 500 && status < 600;
1907
+ }
1908
+ static sleep(ms) {
1909
+ return new Promise((resolve) => setTimeout(resolve, ms));
1910
+ }
1911
+ /**
1912
+ * Perform the HTTP call with a hard timeout. Every outcome resolves to a
1913
+ * GraphQLResponse — callers never hang, so a UI's `loading` state always
1914
+ * settles into data or a renderable error.
1915
+ */
1916
+ async attempt(query, variables, timeoutMs) {
1917
+ const controller = new AbortController();
1918
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
1919
+ try {
1920
+ const response = await fetch(this.config.gatewayUrl, {
1921
+ method: "POST",
1922
+ headers: {
1923
+ "Content-Type": "application/json",
1924
+ "x-product-id": this.config.productId,
1925
+ ...this.config.headers,
1926
+ ...cfAccessHeaders(this.config.gatewayUrl, this.config.cfAccess)
1927
+ },
1928
+ body: JSON.stringify({ query, variables }),
1929
+ signal: controller.signal
1930
+ });
1931
+ if (!response.ok) {
1932
+ console.error(
1933
+ "[WebSDK] GraphQL request failed",
1934
+ response.status,
1935
+ response.statusText
1936
+ );
1937
+ return {
1938
+ res: {
1939
+ errors: [
1940
+ {
1941
+ message: `HTTP ${response.status}: ${response.statusText}`,
1942
+ extensions: { code: `HTTP_${response.status}` }
1943
+ }
1944
+ ]
1945
+ },
1946
+ retriable: _WebSDKClient.isRetriableStatus(response.status)
1947
+ };
1948
+ }
1949
+ return {
1950
+ res: await response.json(),
1951
+ retriable: false
1952
+ };
1953
+ } catch (error) {
1954
+ const aborted = error instanceof Error && (error.name === "AbortError" || controller.signal.aborted);
1955
+ const message = aborted ? `Request timed out after ${timeoutMs}ms` : error instanceof Error ? error.message : "Network error";
1956
+ console.error("[WebSDK] Network error", message);
1957
+ return {
1958
+ res: {
1959
+ errors: [
1960
+ {
1961
+ message,
1962
+ extensions: { code: aborted ? "TIMEOUT" : "NETWORK_ERROR" }
1963
+ }
1964
+ ]
1965
+ },
1966
+ // Transport-level failures are worth one more try; a genuine outage
1967
+ // just fails twice quickly and still renders an error state.
1968
+ retriable: true
1969
+ };
1970
+ } finally {
1971
+ clearTimeout(timer);
1972
+ }
1973
+ }
1974
+ async request(query, variables, retry = true, timeoutOverrideMs) {
1975
+ const timeoutMs = timeoutOverrideMs ?? this.config.timeoutMs ?? _WebSDKClient.DEFAULT_TIMEOUT_MS;
1976
+ const maxRetries = retry ? this.config.maxRetries ?? _WebSDKClient.DEFAULT_MAX_RETRIES : 0;
1977
+ let last;
1978
+ for (let i = 0; i <= maxRetries; i++) {
1979
+ const { res, retriable } = await this.attempt(
1980
+ query,
1981
+ variables,
1982
+ timeoutMs
1983
+ );
1984
+ if (!retriable || i === maxRetries) return res;
1985
+ last = res;
1986
+ await _WebSDKClient.sleep(
1987
+ _WebSDKClient.RETRY_BASE_DELAY_MS * (i + 1) + Math.random() * 200
1988
+ );
1989
+ }
1990
+ return last;
1991
+ }
1992
+ };
1993
+ __publicField(_WebSDKClient, "CACHE_TTL", 5 * 60 * 1e3);
1994
+ // 5 minutes
1995
+ __publicField(_WebSDKClient, "MAX_CACHE_ENTRIES", 100);
1996
+ __publicField(_WebSDKClient, "DEFAULT_TIMEOUT_MS", 12e3);
1997
+ __publicField(_WebSDKClient, "DEFAULT_MAX_RETRIES", 1);
1998
+ __publicField(_WebSDKClient, "RETRY_BASE_DELAY_MS", 400);
1999
+ var WebSDKContext = React.createContext(null);
2000
+ function useWebSDK() {
2001
+ const client = React.useContext(WebSDKContext);
2002
+ if (!client) {
2003
+ throw new Error("useWebSDK must be used within a WebSDKProvider");
2004
+ }
2005
+ return client;
2006
+ }
2007
+ function useWebSDKConfig() {
2008
+ const client = useWebSDK();
2009
+ return client.getConfig();
2010
+ }
2011
+
1690
2012
  // src/components/explore-types.ts
1691
2013
  var EXPLORE_FEEDBACK_REASONS = [
1692
2014
  "INACCURATE",
@@ -1896,420 +2218,20 @@ var EXPLORE_SHARED_CONVERSATION_QUERY = (
1896
2218
  }
1897
2219
  `
1898
2220
  );
1899
- var PROSE_CSS = `
1900
- .boff-prose {
1901
- max-width: none;
1902
- }
1903
2221
 
1904
- .boff-prose h1 {
1905
- font-size: 2.25rem;
1906
- font-weight: 800;
1907
- line-height: 1.2;
1908
- margin-top: 0;
1909
- margin-bottom: 1rem;
1910
- color: hsl(var(--foreground));
1911
- }
1912
-
1913
- .boff-prose h2 {
1914
- font-size: 1.75rem;
1915
- font-weight: 700;
1916
- line-height: 1.3;
1917
- margin-top: 2rem;
1918
- margin-bottom: 1rem;
1919
- color: hsl(var(--foreground));
1920
- }
1921
-
1922
- .boff-prose h3 {
1923
- font-size: 1.5rem;
1924
- font-weight: 600;
1925
- line-height: 1.4;
1926
- margin-top: 1.5rem;
1927
- margin-bottom: 0.75rem;
1928
- color: hsl(var(--foreground));
1929
- }
1930
-
1931
- .boff-prose h4 {
1932
- font-size: 1.25rem;
1933
- font-weight: 600;
1934
- line-height: 1.5;
1935
- margin-top: 1.25rem;
1936
- margin-bottom: 0.5rem;
1937
- color: hsl(var(--foreground));
1938
- }
1939
-
1940
- .boff-prose p {
1941
- margin-bottom: 1rem;
1942
- line-height: 1.75;
1943
- color: hsl(var(--foreground));
1944
- }
1945
-
1946
- .boff-prose ul,
1947
- .boff-prose ol {
1948
- margin-bottom: 1rem;
1949
- padding-left: 1.5rem;
1950
- }
1951
-
1952
- .boff-prose ul {
1953
- list-style-type: disc;
1954
- }
1955
-
1956
- .boff-prose ol {
1957
- list-style-type: decimal;
1958
- }
1959
-
1960
- .boff-prose li {
1961
- margin-bottom: 0.25rem;
1962
- line-height: 1.75;
1963
- color: hsl(var(--foreground));
1964
- }
1965
-
1966
- .boff-prose li > ul,
1967
- .boff-prose li > ol {
1968
- margin-top: 0.25rem;
1969
- margin-bottom: 0.25rem;
1970
- }
1971
-
1972
- .boff-prose a {
1973
- color: hsl(var(--primary));
1974
- text-decoration: underline;
1975
- text-underline-offset: 2px;
1976
- }
1977
-
1978
- .boff-prose a:hover {
1979
- opacity: 0.8;
1980
- }
1981
-
1982
- .boff-prose hr {
1983
- border: none;
1984
- height: 1px;
1985
- background-color: hsl(var(--border));
1986
- margin: 2rem 0;
1987
- }
1988
-
1989
- .boff-prose blockquote {
1990
- border-left: 4px solid hsl(var(--border));
1991
- padding-left: 1rem;
1992
- margin: 1.5rem 0;
1993
- font-style: italic;
1994
- color: hsl(var(--muted-foreground));
1995
- }
1996
-
1997
- .boff-prose strong {
1998
- font-weight: 700;
1999
- color: hsl(var(--foreground));
2000
- }
2001
-
2002
- .boff-prose code {
2003
- background-color: hsl(var(--muted));
2004
- padding: 0.125rem 0.25rem;
2005
- border-radius: 0.25rem;
2006
- font-size: 0.875em;
2007
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
2008
- }
2009
-
2010
- .boff-prose pre {
2011
- background-color: hsl(var(--muted));
2012
- padding: 1rem;
2013
- border-radius: 0.5rem;
2014
- overflow-x: auto;
2015
- margin-bottom: 1rem;
2016
- }
2017
-
2018
- .boff-prose pre code {
2019
- background-color: transparent;
2020
- padding: 0;
2021
- }
2022
-
2023
- .boff-prose img {
2024
- max-width: 100%;
2025
- height: auto;
2026
- }
2027
-
2028
- .boff-prose table {
2029
- width: 100%;
2030
- border-collapse: collapse;
2031
- margin-bottom: 1rem;
2032
- }
2033
-
2034
- .boff-prose th,
2035
- .boff-prose td {
2036
- border: 1px solid hsl(var(--border));
2037
- padding: 0.5rem;
2038
- text-align: left;
2039
- }
2040
-
2041
- .boff-prose th {
2042
- font-weight: 600;
2043
- background-color: hsl(var(--muted));
2044
- }
2045
-
2046
- /* Smaller variant used inside cards and compact panels */
2047
- .boff-prose-sm {
2048
- font-size: 0.875rem;
2049
- }
2050
-
2051
- .boff-prose-sm h1 {
2052
- font-size: 1.75rem;
2053
- }
2054
-
2055
- .boff-prose-sm h2 {
2056
- font-size: 1.5rem;
2057
- }
2058
-
2059
- .boff-prose-sm h3 {
2060
- font-size: 1.25rem;
2061
- }
2062
-
2063
- .boff-prose-sm h4 {
2064
- font-size: 1.125rem;
2065
- }
2066
-
2067
- .boff-prose-sm p,
2068
- .boff-prose-sm li {
2069
- line-height: 1.625;
2070
- }
2071
- `;
2072
- function ProseStyles() {
2073
- return /* @__PURE__ */ jsxRuntime.jsx("style", { dangerouslySetInnerHTML: { __html: PROSE_CSS } });
2074
- }
2075
-
2076
- // src/client/security.ts
2077
- var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "::1"]);
2078
- var RESERVED_HEADERS = /* @__PURE__ */ new Set([
2079
- "authorization",
2080
- "cookie",
2081
- "x-actor-id",
2082
- "x-actor-type",
2083
- "x-consent-granted-by",
2084
- "x-consent-scope",
2085
- "x-consent-granted-at",
2086
- "x-consent-expires-at"
2087
- ]);
2088
- function validateGatewayUrl(value) {
2089
- let url;
2090
- try {
2091
- url = new URL(value);
2092
- } catch {
2093
- throw new Error("Gateway URL must be a valid absolute URL");
2094
- }
2095
- if (url.protocol === "https:") {
2096
- return url.toString();
2097
- }
2098
- if (url.protocol === "http:" && LOOPBACK_HOSTS.has(url.hostname.toLowerCase())) {
2099
- return url.toString();
2100
- }
2101
- throw new Error("Gateway URL must use HTTPS unless it targets localhost");
2102
- }
2103
- function sanitizeHeaders(headers) {
2104
- if (!headers) return void 0;
2105
- return Object.fromEntries(
2106
- Object.entries(headers).filter(
2107
- ([key]) => !RESERVED_HEADERS.has(key.toLowerCase())
2108
- )
2109
- );
2110
- }
2111
- var CF_ACCESS_GATED_HOSTS = /* @__PURE__ */ new Set([
2112
- "alphagraphql.burdenoff.com",
2113
- "alphagraphqlworkspaces.burdenoff.com"
2114
- ]);
2115
- function cfAccessHeaders(gatewayUrl, cfAccess) {
2116
- const clientId = cfAccess?.clientId?.trim();
2117
- const clientSecret = cfAccess?.clientSecret?.trim();
2118
- if (!clientId || !clientSecret) return {};
2119
- let host;
2120
- try {
2121
- host = new URL(gatewayUrl).hostname.toLowerCase();
2122
- } catch {
2123
- return {};
2124
- }
2125
- if (!CF_ACCESS_GATED_HOSTS.has(host)) return {};
2126
- return {
2127
- "CF-Access-Client-Id": clientId,
2128
- "CF-Access-Client-Secret": clientSecret
2129
- };
2130
- }
2131
-
2132
- // src/client/graphql-client.ts
2133
- var _WebSDKClient = class _WebSDKClient {
2134
- constructor(config) {
2135
- __publicField(this, "config");
2136
- __publicField(this, "queryCache", /* @__PURE__ */ new Map());
2137
- __publicField(this, "inflight", /* @__PURE__ */ new Map());
2138
- this.config = {
2139
- ...config,
2140
- gatewayUrl: validateGatewayUrl(config.gatewayUrl),
2141
- headers: sanitizeHeaders(config.headers)
2142
- };
2143
- }
2144
- getConfig() {
2145
- return this.config;
2146
- }
2147
- /**
2148
- * Execute a GraphQL query (with deduplication and caching).
2149
- *
2150
- * Pass `{ cache: false }` to bypass the cache entirely — required for poll
2151
- * loops, where every tick must reach the network.
2152
- */
2153
- async query(query, variables, options) {
2154
- if (options?.cache === false) {
2155
- return this.request(query, variables, true, options.timeoutMs);
2156
- }
2157
- const cacheKey = JSON.stringify({ query, variables });
2158
- const cached = this.queryCache.get(cacheKey);
2159
- if (cached) {
2160
- if (Date.now() - cached.ts < _WebSDKClient.CACHE_TTL) {
2161
- return cached.data;
2162
- }
2163
- this.queryCache.delete(cacheKey);
2164
- }
2165
- const existing = this.inflight.get(cacheKey);
2166
- if (existing) {
2167
- return existing;
2168
- }
2169
- const promise = this.request(query, variables, true, options?.timeoutMs).then((result) => {
2170
- if (result.data && !result.errors?.length) {
2171
- if (this.queryCache.size >= _WebSDKClient.MAX_CACHE_ENTRIES) {
2172
- const oldestEntry = this.queryCache.keys().next().value;
2173
- if (oldestEntry) {
2174
- this.queryCache.delete(oldestEntry);
2175
- }
2176
- }
2177
- this.queryCache.set(cacheKey, { data: result, ts: Date.now() });
2178
- }
2179
- return result;
2180
- }).finally(() => {
2181
- this.inflight.delete(cacheKey);
2182
- });
2183
- this.inflight.set(cacheKey, promise);
2184
- return promise;
2185
- }
2186
- /**
2187
- * Execute a GraphQL mutation
2188
- */
2189
- async mutate(mutation, variables, options) {
2190
- return this.request(mutation, variables, false, options?.timeoutMs);
2191
- }
2192
- /** HTTP statuses worth another attempt — transient server/edge conditions. */
2193
- static isRetriableStatus(status) {
2194
- return status === 429 || status === 408 || status >= 500 && status < 600;
2195
- }
2196
- static sleep(ms) {
2197
- return new Promise((resolve) => setTimeout(resolve, ms));
2198
- }
2199
- /**
2200
- * Perform the HTTP call with a hard timeout. Every outcome resolves to a
2201
- * GraphQLResponse — callers never hang, so a UI's `loading` state always
2202
- * settles into data or a renderable error.
2203
- */
2204
- async attempt(query, variables, timeoutMs) {
2205
- const controller = new AbortController();
2206
- const timer = setTimeout(() => controller.abort(), timeoutMs);
2207
- try {
2208
- const response = await fetch(this.config.gatewayUrl, {
2209
- method: "POST",
2210
- headers: {
2211
- "Content-Type": "application/json",
2212
- "x-product-id": this.config.productId,
2213
- ...this.config.headers,
2214
- ...cfAccessHeaders(this.config.gatewayUrl, this.config.cfAccess)
2215
- },
2216
- body: JSON.stringify({ query, variables }),
2217
- signal: controller.signal
2218
- });
2219
- if (!response.ok) {
2220
- console.error(
2221
- "[WebSDK] GraphQL request failed",
2222
- response.status,
2223
- response.statusText
2224
- );
2225
- return {
2226
- res: {
2227
- errors: [
2228
- {
2229
- message: `HTTP ${response.status}: ${response.statusText}`,
2230
- extensions: { code: `HTTP_${response.status}` }
2231
- }
2232
- ]
2233
- },
2234
- retriable: _WebSDKClient.isRetriableStatus(response.status)
2235
- };
2236
- }
2237
- return {
2238
- res: await response.json(),
2239
- retriable: false
2240
- };
2241
- } catch (error) {
2242
- const aborted = error instanceof Error && (error.name === "AbortError" || controller.signal.aborted);
2243
- const message = aborted ? `Request timed out after ${timeoutMs}ms` : error instanceof Error ? error.message : "Network error";
2244
- console.error("[WebSDK] Network error", message);
2245
- return {
2246
- res: {
2247
- errors: [
2248
- {
2249
- message,
2250
- extensions: { code: aborted ? "TIMEOUT" : "NETWORK_ERROR" }
2251
- }
2252
- ]
2253
- },
2254
- // Transport-level failures are worth one more try; a genuine outage
2255
- // just fails twice quickly and still renders an error state.
2256
- retriable: true
2257
- };
2258
- } finally {
2259
- clearTimeout(timer);
2260
- }
2261
- }
2262
- async request(query, variables, retry = true, timeoutOverrideMs) {
2263
- const timeoutMs = timeoutOverrideMs ?? this.config.timeoutMs ?? _WebSDKClient.DEFAULT_TIMEOUT_MS;
2264
- const maxRetries = retry ? this.config.maxRetries ?? _WebSDKClient.DEFAULT_MAX_RETRIES : 0;
2265
- let last;
2266
- for (let i = 0; i <= maxRetries; i++) {
2267
- const { res, retriable } = await this.attempt(
2268
- query,
2269
- variables,
2270
- timeoutMs
2271
- );
2272
- if (!retriable || i === maxRetries) return res;
2273
- last = res;
2274
- await _WebSDKClient.sleep(
2275
- _WebSDKClient.RETRY_BASE_DELAY_MS * (i + 1) + Math.random() * 200
2276
- );
2277
- }
2278
- return last;
2279
- }
2280
- };
2281
- __publicField(_WebSDKClient, "CACHE_TTL", 5 * 60 * 1e3);
2282
- // 5 minutes
2283
- __publicField(_WebSDKClient, "MAX_CACHE_ENTRIES", 100);
2284
- __publicField(_WebSDKClient, "DEFAULT_TIMEOUT_MS", 12e3);
2285
- __publicField(_WebSDKClient, "DEFAULT_MAX_RETRIES", 1);
2286
- __publicField(_WebSDKClient, "RETRY_BASE_DELAY_MS", 400);
2287
- var WebSDKContext = React.createContext(null);
2288
- function useWebSDK() {
2289
- const client = React.useContext(WebSDKContext);
2290
- if (!client) {
2291
- throw new Error("useWebSDK must be used within a WebSDKProvider");
2292
- }
2293
- return client;
2294
- }
2295
- function useWebSDKConfig() {
2296
- const client = useWebSDK();
2297
- return client.getConfig();
2298
- }
2299
-
2300
- // src/utils/product-slug.ts
2301
- var PRODUCT_SLUG_RENAMES = Object.freeze(
2302
- [Object.freeze({ legacy: "botlit", current: "botmanor" })]
2303
- );
2304
- Object.freeze(
2305
- Object.fromEntries(PRODUCT_SLUG_RENAMES.map((r) => [r.legacy, r.current]))
2306
- );
2307
- var PRODUCT_SLUG_EMIT = Object.freeze({ productSlug: "current" });
2308
- function findRename(slug) {
2309
- const wanted = slug.toLowerCase();
2310
- return PRODUCT_SLUG_RENAMES.find(
2311
- (r) => r.legacy === wanted || r.current === wanted
2312
- );
2222
+ // src/utils/product-slug.ts
2223
+ var PRODUCT_SLUG_RENAMES = Object.freeze(
2224
+ [Object.freeze({ legacy: "botlit", current: "botmanor" })]
2225
+ );
2226
+ Object.freeze(
2227
+ Object.fromEntries(PRODUCT_SLUG_RENAMES.map((r) => [r.legacy, r.current]))
2228
+ );
2229
+ var PRODUCT_SLUG_EMIT = Object.freeze({ productSlug: "current" });
2230
+ function findRename(slug) {
2231
+ const wanted = slug.toLowerCase();
2232
+ return PRODUCT_SLUG_RENAMES.find(
2233
+ (r) => r.legacy === wanted || r.current === wanted
2234
+ );
2313
2235
  }
2314
2236
  function normalizeProductSlug(slug) {
2315
2237
  if (slug == null) return slug;
@@ -2318,6 +2240,11 @@ function normalizeProductSlug(slug) {
2318
2240
  function legacyProductSlug(slug) {
2319
2241
  return findRename(slug)?.legacy ?? slug;
2320
2242
  }
2243
+ function productSlugVariants(slug) {
2244
+ return [
2245
+ .../* @__PURE__ */ new Set([slug, normalizeProductSlug(slug), legacyProductSlug(slug)])
2246
+ ];
2247
+ }
2321
2248
  function isSameProductSlug(a, b) {
2322
2249
  if (a == null || b == null) return a === b;
2323
2250
  return a === b || normalizeProductSlug(a) === normalizeProductSlug(b);
@@ -2898,7 +2825,9 @@ function useExploreChat(options = {}) {
2898
2825
  pollTimeoutMs = DEFAULT_POLL_TIMEOUT_MS,
2899
2826
  storageKey = DEFAULT_STORAGE_KEY,
2900
2827
  persist = true,
2901
- onSend
2828
+ onSend,
2829
+ enabled = true,
2830
+ shareToken: shareTokenOption
2902
2831
  } = options;
2903
2832
  const client = useWebSDK();
2904
2833
  const { productId } = useWebSDKConfig();
@@ -2936,7 +2865,7 @@ function useExploreChat(options = {}) {
2936
2865
  const [hasConversation, setHasConversation] = React.useState(false);
2937
2866
  const shareTokenRef = React.useRef(void 0);
2938
2867
  if (shareTokenRef.current === void 0) {
2939
- shareTokenRef.current = readShareToken();
2868
+ shareTokenRef.current = shareTokenOption === void 0 ? readShareToken() : shareTokenOption;
2940
2869
  }
2941
2870
  const isSharedView = shareTokenRef.current !== null;
2942
2871
  const catalogRef = React.useRef(catalog);
@@ -2974,6 +2903,7 @@ function useExploreChat(options = {}) {
2974
2903
  };
2975
2904
  }, []);
2976
2905
  React.useEffect(() => {
2906
+ if (!enabled) return;
2977
2907
  const shareToken = shareTokenRef.current;
2978
2908
  if (!shareToken) return;
2979
2909
  let cancelled = false;
@@ -3008,8 +2938,9 @@ function useExploreChat(options = {}) {
3008
2938
  return () => {
3009
2939
  cancelled = true;
3010
2940
  };
3011
- }, [client]);
2941
+ }, [client, enabled]);
3012
2942
  React.useEffect(() => {
2943
+ if (!enabled) return;
3013
2944
  if (shareTokenRef.current !== null) return;
3014
2945
  if (!persist) {
3015
2946
  setHydrated(true);
@@ -3034,9 +2965,10 @@ function useExploreChat(options = {}) {
3034
2965
  setTurnCount(turns);
3035
2966
  }
3036
2967
  setHydrated(true);
3037
- }, [persist, rememberConversationToken, storageKey]);
2968
+ }, [persist, rememberConversationToken, storageKey, enabled]);
3038
2969
  React.useEffect(() => {
3039
- if (!persist || !hydrated || typeof window === "undefined") return;
2970
+ if (!persist || !hydrated || isSharedView || typeof window === "undefined")
2971
+ return;
3040
2972
  try {
3041
2973
  const payload = {
3042
2974
  conversationToken: conversationTokenRef.current,
@@ -3050,10 +2982,10 @@ function useExploreChat(options = {}) {
3050
2982
  window.localStorage.setItem(storageKey, JSON.stringify(payload));
3051
2983
  } catch {
3052
2984
  }
3053
- }, [persist, hydrated, storageKey, messages, focusProduct]);
2985
+ }, [persist, hydrated, isSharedView, storageKey, messages, focusProduct]);
3054
2986
  React.useEffect(() => {
3055
2987
  messagesRef.current = messages;
3056
- if (!persist || !hydrated) return;
2988
+ if (!persist || !hydrated || isSharedView) return;
3057
2989
  const settled = messages.some(
3058
2990
  (m) => m.role === "ASSISTANT" && (m.status === "COMPLETED" || m.status === "FAILED")
3059
2991
  );
@@ -3065,8 +2997,9 @@ function useExploreChat(options = {}) {
3065
2997
  focusProduct: focusProductRef.current
3066
2998
  })
3067
2999
  );
3068
- }, [messages, persist, hydrated, storageKey]);
3000
+ }, [messages, persist, hydrated, isSharedView, storageKey]);
3069
3001
  React.useEffect(() => {
3002
+ if (!enabled) return;
3070
3003
  let cancelled = false;
3071
3004
  const load = async () => {
3072
3005
  const variables = { productSlug: productSlug ?? null };
@@ -3107,7 +3040,7 @@ function useExploreChat(options = {}) {
3107
3040
  return () => {
3108
3041
  cancelled = true;
3109
3042
  };
3110
- }, [client, productSlug, fallbackCatalog, bakedRaw]);
3043
+ }, [client, productSlug, fallbackCatalog, bakedRaw, enabled]);
3111
3044
  const startPolling = React.useCallback(
3112
3045
  (conversationToken, messageId) => {
3113
3046
  pollGenerationRef.current += 1;
@@ -3599,10 +3532,326 @@ function useExploreChat(options = {}) {
3599
3532
  isSharedView
3600
3533
  };
3601
3534
  }
3602
- var optimisticCounter = 0;
3603
- function makeOptimisticId() {
3604
- optimisticCounter += 1;
3605
- return `boff-explore-local-${Date.now()}-${optimisticCounter}`;
3535
+ var optimisticCounter = 0;
3536
+ function makeOptimisticId() {
3537
+ optimisticCounter += 1;
3538
+ return `boff-explore-local-${Date.now()}-${optimisticCounter}`;
3539
+ }
3540
+ var ExploreConversationContext = React.createContext(null);
3541
+ React.createContext(null);
3542
+ function useExploreConversation(options = {}) {
3543
+ const {
3544
+ productSlug,
3545
+ locale,
3546
+ examplePrompts,
3547
+ onSend,
3548
+ pageUrl,
3549
+ enabled,
3550
+ shareToken
3551
+ } = options;
3552
+ const urlAtMount = React.useMemo(
3553
+ () => typeof window === "undefined" ? void 0 : window.location.href,
3554
+ []
3555
+ );
3556
+ const T = React.useMemo(
3557
+ () => exploreStrings(resolveExploreLocale(locale)),
3558
+ [locale]
3559
+ );
3560
+ const chat = useExploreChat({
3561
+ productSlug,
3562
+ pageUrl: pageUrl ?? urlAtMount,
3563
+ onSend,
3564
+ // Locale-aware, so a catalog outage degrades to a translated welcome rather than an English one.
3565
+ examplePrompts: examplePrompts ?? T.prompts,
3566
+ fallbackWelcome: { title: T.welcomeTitle, body: T.welcomeBody },
3567
+ ...enabled === void 0 ? {} : { enabled },
3568
+ ...shareToken === void 0 ? {} : { shareToken }
3569
+ });
3570
+ const [draft, setDraft] = React.useState("");
3571
+ const [staged, setStaged] = React.useState([]);
3572
+ return React.useMemo(
3573
+ () => ({ ...chat, draft, setDraft, staged, setStaged }),
3574
+ [chat, draft, staged]
3575
+ );
3576
+ }
3577
+
3578
+ // src/components/explore-scope.ts
3579
+ function pinnedProductSlug(scope, productSlug) {
3580
+ if (scope !== "product" || productSlug === void 0) return null;
3581
+ return productSlug.trim() === "" ? null : productSlug;
3582
+ }
3583
+ function productNameFor(products, slug, given) {
3584
+ const own = given?.trim();
3585
+ if (own) return own;
3586
+ return products.find((product) => isSameProductSlug(product.slug, slug))?.name ?? null;
3587
+ }
3588
+ var NAME_CHARACTER = /[a-z0-9]/;
3589
+ var MIN_SPELLING_LENGTH = 3;
3590
+ function siteNameOf(website) {
3591
+ if (!website) return "";
3592
+ try {
3593
+ const labels = new URL(website).hostname.split(".");
3594
+ return labels.length >= 2 ? labels[labels.length - 2] ?? "" : "";
3595
+ } catch {
3596
+ return "";
3597
+ }
3598
+ }
3599
+ function spellingsOf(product) {
3600
+ const spellings = [
3601
+ product.name,
3602
+ product.name.replace(/\s+/g, ""),
3603
+ ...productSlugVariants(product.slug),
3604
+ siteNameOf(product.website)
3605
+ ].map((spelling) => spelling.trim().toLowerCase()).filter((spelling) => spelling.length >= MIN_SPELLING_LENGTH);
3606
+ return [...new Set(spellings)];
3607
+ }
3608
+ function wordAt(text, spelling, from = 0) {
3609
+ for (let at = text.indexOf(spelling, from); at !== -1; at = text.indexOf(spelling, at + 1)) {
3610
+ const before = text[at - 1];
3611
+ const after = text[at + spelling.length];
3612
+ const bounded = (before === void 0 || !NAME_CHARACTER.test(before)) && (after === void 0 || !NAME_CHARACTER.test(after));
3613
+ if (bounded) return at;
3614
+ }
3615
+ return -1;
3616
+ }
3617
+ function withoutWord(text, spelling) {
3618
+ let result = text;
3619
+ for (let at = wordAt(result, spelling); at !== -1; at = wordAt(result, spelling, at + spelling.length)) {
3620
+ result = `${result.slice(0, at)}${" ".repeat(spelling.length)}${result.slice(at + spelling.length)}`;
3621
+ }
3622
+ return result;
3623
+ }
3624
+ function anotherProductMatcher(products, pinnedSlug) {
3625
+ const own = productSlugVariants(pinnedSlug).map((slug) => slug.toLowerCase());
3626
+ const others = [];
3627
+ for (const product of products) {
3628
+ if (isSameProductSlug(product.slug, pinnedSlug)) {
3629
+ own.push(...spellingsOf(product));
3630
+ } else {
3631
+ others.push(...spellingsOf(product));
3632
+ }
3633
+ }
3634
+ const ownSpellings = [...new Set(own)].sort((a, b) => b.length - a.length);
3635
+ const otherSpellings = [...new Set(others)].filter(
3636
+ (spelling) => !ownSpellings.includes(spelling)
3637
+ );
3638
+ return (text) => {
3639
+ let rest = text.toLowerCase();
3640
+ for (const spelling of ownSpellings) rest = withoutWord(rest, spelling);
3641
+ return otherSpellings.some((spelling) => wordAt(rest, spelling) !== -1);
3642
+ };
3643
+ }
3644
+ function distinctPrompts(prompts) {
3645
+ return [...new Set(prompts.filter((prompt) => prompt.trim() !== ""))];
3646
+ }
3647
+ function productScopedPrompts(hostPrompts, catalogPrompts, namesAnotherProduct) {
3648
+ const own = distinctPrompts(hostPrompts ?? []);
3649
+ if (own.length > 0) return own;
3650
+ return distinctPrompts(
3651
+ catalogPrompts.filter(
3652
+ (prompt) => !isPortfolioPrompt(prompt) && !namesAnotherProduct(prompt)
3653
+ )
3654
+ );
3655
+ }
3656
+ function productScopedHighlights(highlights, pinnedSlug, namesAnotherProduct) {
3657
+ return highlights.filter(
3658
+ (highlight) => isSameProductSlug(highlight.product, pinnedSlug) && !namesAnotherProduct(`${highlight.title}
3659
+ ${highlight.alt}`)
3660
+ );
3661
+ }
3662
+ function productScopedError(error, toolBudgetMessage) {
3663
+ return error.code === "TOOL_BUDGET" ? { ...error, message: toolBudgetMessage } : error;
3664
+ }
3665
+ function isDevelopmentBuild() {
3666
+ try {
3667
+ return process.env.NODE_ENV !== "production";
3668
+ } catch {
3669
+ return false;
3670
+ }
3671
+ }
3672
+ var warnedWithoutSlug = false;
3673
+ function warnProductScopeWithoutSlug() {
3674
+ if (warnedWithoutSlug || !isDevelopmentBuild()) return;
3675
+ warnedWithoutSlug = true;
3676
+ console.warn(
3677
+ `[WebSDK] Explore scope="product" needs a productSlug. Without one the assistant stays the portfolio's: every product, and a product picker.`
3678
+ );
3679
+ }
3680
+ var PROSE_CSS = `
3681
+ .boff-prose {
3682
+ max-width: none;
3683
+ }
3684
+
3685
+ .boff-prose h1 {
3686
+ font-size: 2.25rem;
3687
+ font-weight: 800;
3688
+ line-height: 1.2;
3689
+ margin-top: 0;
3690
+ margin-bottom: 1rem;
3691
+ color: hsl(var(--foreground));
3692
+ }
3693
+
3694
+ .boff-prose h2 {
3695
+ font-size: 1.75rem;
3696
+ font-weight: 700;
3697
+ line-height: 1.3;
3698
+ margin-top: 2rem;
3699
+ margin-bottom: 1rem;
3700
+ color: hsl(var(--foreground));
3701
+ }
3702
+
3703
+ .boff-prose h3 {
3704
+ font-size: 1.5rem;
3705
+ font-weight: 600;
3706
+ line-height: 1.4;
3707
+ margin-top: 1.5rem;
3708
+ margin-bottom: 0.75rem;
3709
+ color: hsl(var(--foreground));
3710
+ }
3711
+
3712
+ .boff-prose h4 {
3713
+ font-size: 1.25rem;
3714
+ font-weight: 600;
3715
+ line-height: 1.5;
3716
+ margin-top: 1.25rem;
3717
+ margin-bottom: 0.5rem;
3718
+ color: hsl(var(--foreground));
3719
+ }
3720
+
3721
+ .boff-prose p {
3722
+ margin-bottom: 1rem;
3723
+ line-height: 1.75;
3724
+ color: hsl(var(--foreground));
3725
+ }
3726
+
3727
+ .boff-prose ul,
3728
+ .boff-prose ol {
3729
+ margin-bottom: 1rem;
3730
+ padding-left: 1.5rem;
3731
+ }
3732
+
3733
+ .boff-prose ul {
3734
+ list-style-type: disc;
3735
+ }
3736
+
3737
+ .boff-prose ol {
3738
+ list-style-type: decimal;
3739
+ }
3740
+
3741
+ .boff-prose li {
3742
+ margin-bottom: 0.25rem;
3743
+ line-height: 1.75;
3744
+ color: hsl(var(--foreground));
3745
+ }
3746
+
3747
+ .boff-prose li > ul,
3748
+ .boff-prose li > ol {
3749
+ margin-top: 0.25rem;
3750
+ margin-bottom: 0.25rem;
3751
+ }
3752
+
3753
+ .boff-prose a {
3754
+ color: hsl(var(--primary));
3755
+ text-decoration: underline;
3756
+ text-underline-offset: 2px;
3757
+ }
3758
+
3759
+ .boff-prose a:hover {
3760
+ opacity: 0.8;
3761
+ }
3762
+
3763
+ .boff-prose hr {
3764
+ border: none;
3765
+ height: 1px;
3766
+ background-color: hsl(var(--border));
3767
+ margin: 2rem 0;
3768
+ }
3769
+
3770
+ .boff-prose blockquote {
3771
+ border-left: 4px solid hsl(var(--border));
3772
+ padding-left: 1rem;
3773
+ margin: 1.5rem 0;
3774
+ font-style: italic;
3775
+ color: hsl(var(--muted-foreground));
3776
+ }
3777
+
3778
+ .boff-prose strong {
3779
+ font-weight: 700;
3780
+ color: hsl(var(--foreground));
3781
+ }
3782
+
3783
+ .boff-prose code {
3784
+ background-color: hsl(var(--muted));
3785
+ padding: 0.125rem 0.25rem;
3786
+ border-radius: 0.25rem;
3787
+ font-size: 0.875em;
3788
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
3789
+ }
3790
+
3791
+ .boff-prose pre {
3792
+ background-color: hsl(var(--muted));
3793
+ padding: 1rem;
3794
+ border-radius: 0.5rem;
3795
+ overflow-x: auto;
3796
+ margin-bottom: 1rem;
3797
+ }
3798
+
3799
+ .boff-prose pre code {
3800
+ background-color: transparent;
3801
+ padding: 0;
3802
+ }
3803
+
3804
+ .boff-prose img {
3805
+ max-width: 100%;
3806
+ height: auto;
3807
+ }
3808
+
3809
+ .boff-prose table {
3810
+ width: 100%;
3811
+ border-collapse: collapse;
3812
+ margin-bottom: 1rem;
3813
+ }
3814
+
3815
+ .boff-prose th,
3816
+ .boff-prose td {
3817
+ border: 1px solid hsl(var(--border));
3818
+ padding: 0.5rem;
3819
+ text-align: left;
3820
+ }
3821
+
3822
+ .boff-prose th {
3823
+ font-weight: 600;
3824
+ background-color: hsl(var(--muted));
3825
+ }
3826
+
3827
+ /* Smaller variant used inside cards and compact panels */
3828
+ .boff-prose-sm {
3829
+ font-size: 0.875rem;
3830
+ }
3831
+
3832
+ .boff-prose-sm h1 {
3833
+ font-size: 1.75rem;
3834
+ }
3835
+
3836
+ .boff-prose-sm h2 {
3837
+ font-size: 1.5rem;
3838
+ }
3839
+
3840
+ .boff-prose-sm h3 {
3841
+ font-size: 1.25rem;
3842
+ }
3843
+
3844
+ .boff-prose-sm h4 {
3845
+ font-size: 1.125rem;
3846
+ }
3847
+
3848
+ .boff-prose-sm p,
3849
+ .boff-prose-sm li {
3850
+ line-height: 1.625;
3851
+ }
3852
+ `;
3853
+ function ProseStyles() {
3854
+ return /* @__PURE__ */ jsxRuntime.jsx("style", { dangerouslySetInnerHTML: { __html: PROSE_CSS } });
3606
3855
  }
3607
3856
  var DRAIN_TARGET_MS = 1200;
3608
3857
  var MIN_CHARS_PER_SECOND = 90;
@@ -4811,21 +5060,25 @@ var CAPABILITIES = [
4811
5060
  {
4812
5061
  icon: lucideReact.BookOpenText,
4813
5062
  title: "Grounded in our own docs",
4814
- body: "Every answer comes from published product pages and documentation \u2014 never invented."
5063
+ body: "Every answer comes from published product pages and documentation \u2014 never invented.",
5064
+ invitesOtherProducts: false
4815
5065
  },
4816
5066
  {
4817
5067
  icon: lucideReact.Layers,
4818
5068
  title: "Compare across the ecosystem",
4819
- body: "Ask which product fits your team, or how two of them work together."
5069
+ body: "Ask which product fits your team, or how two of them work together.",
5070
+ invitesOtherProducts: true
4820
5071
  },
4821
5072
  {
4822
5073
  icon: lucideReact.Link2,
4823
5074
  title: "Straight to the right page",
4824
- body: "Get the sources and next steps \u2014 pricing, docs, a demo \u2014 without hunting."
5075
+ body: "Get the sources and next steps \u2014 pricing, docs, a demo \u2014 without hunting.",
5076
+ invitesOtherProducts: false
4825
5077
  }
4826
5078
  ];
4827
5079
  var MIN_VISIBLE_FRACTION = 0.25;
4828
5080
  var SDK_OVERLAY_SELECTOR = "[data-boff-explore]";
5081
+ var NO_PRODUCTS = [];
4829
5082
  var CTA_VARIANTS = {
4830
5083
  CONTACT: "default",
4831
5084
  WAITLIST: "default",
@@ -6374,29 +6627,40 @@ function WelcomeState({
6374
6627
  focusProduct,
6375
6628
  onPrompt,
6376
6629
  onFocus,
6377
- disabled
6630
+ disabled,
6631
+ heading = "h1",
6632
+ productScoped = false
6378
6633
  }) {
6634
+ const Heading = heading;
6379
6635
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "boff-explore-aura mx-auto my-auto w-full max-w-3xl px-4 py-4 sm:py-5", children: [
6380
6636
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "boff-explore-rise text-center", children: [
6381
6637
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "boff-explore-hero-badge inline-flex items-center gap-1.5 rounded-full border border-border bg-muted px-3 py-1 text-xs font-medium text-muted-foreground", children: [
6382
6638
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "h-3.5 w-3.5" }),
6383
6639
  T.badge
6384
6640
  ] }),
6385
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "mt-2 text-balance break-words text-2xl font-bold tracking-tight sm:text-3xl", children: title }),
6641
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { className: "mt-2 text-balance break-words text-2xl font-bold tracking-tight sm:text-3xl", children: title }),
6386
6642
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mx-auto mt-2 max-w-2xl text-pretty text-sm leading-relaxed text-muted-foreground", children: body })
6387
6643
  ] }),
6388
- /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "boff-explore-capabilities boff-explore-rise boff-explore-rise-1 mt-4 grid grid-cols-3 gap-2 sm:gap-2.5", children: CAPABILITIES.map(({ icon: Icon, body: capBody }, i) => /* @__PURE__ */ jsxRuntime.jsxs(
6389
- "li",
6644
+ /* @__PURE__ */ jsxRuntime.jsx(
6645
+ "ul",
6390
6646
  {
6391
- className: "rounded-xl border border-border/70 bg-card/60 p-2.5 text-center transition-colors hover:border-border sm:p-2.5 sm:text-left",
6392
- children: [
6393
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mx-auto mb-1.5 flex h-7 w-7 items-center justify-center rounded-lg bg-primary/10 text-primary sm:mx-0 sm:mb-2 sm:h-8 sm:w-8", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-3.5 w-3.5 sm:h-4 sm:w-4" }) }),
6394
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] font-semibold leading-tight text-card-foreground sm:text-sm sm:leading-snug", children: T.capabilities[i] ?? "" }),
6395
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 hidden text-xs leading-snug text-muted-foreground lg:block", children: capBody })
6396
- ]
6397
- },
6398
- i
6399
- )) }),
6647
+ className: `boff-explore-capabilities boff-explore-rise boff-explore-rise-1 mt-4 grid ${productScoped ? "grid-cols-2" : "grid-cols-3"} gap-2 sm:gap-2.5`,
6648
+ children: CAPABILITIES.map(
6649
+ ({ icon: Icon, body: capBody, invitesOtherProducts }, i) => productScoped && invitesOtherProducts ? null : /* @__PURE__ */ jsxRuntime.jsxs(
6650
+ "li",
6651
+ {
6652
+ className: "rounded-xl border border-border/70 bg-card/60 p-2.5 text-center transition-colors hover:border-border sm:p-2.5 sm:text-left",
6653
+ children: [
6654
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mx-auto mb-1.5 flex h-7 w-7 items-center justify-center rounded-lg bg-primary/10 text-primary sm:mx-0 sm:mb-2 sm:h-8 sm:w-8", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-3.5 w-3.5 sm:h-4 sm:w-4" }) }),
6655
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] font-semibold leading-tight text-card-foreground sm:text-sm sm:leading-snug", children: T.capabilities[i] ?? "" }),
6656
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 hidden text-xs leading-snug text-muted-foreground lg:block", children: capBody })
6657
+ ]
6658
+ },
6659
+ i
6660
+ )
6661
+ )
6662
+ }
6663
+ ),
6400
6664
  prompts.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "boff-explore-rise boff-explore-rise-2 mt-4", children: /* @__PURE__ */ jsxRuntime.jsx(
6401
6665
  PromptCarousel,
6402
6666
  {
@@ -6437,19 +6701,39 @@ function exploreQuestionHref(question, base = "/explore") {
6437
6701
  const joiner = base.includes("?") ? "&" : "?";
6438
6702
  return `${base}${joiner}q=${encodeURIComponent(trimmed)}`;
6439
6703
  }
6440
- function ExplorePage({
6704
+ function ExplorePage(props) {
6705
+ const shared = React.useContext(ExploreConversationContext);
6706
+ return shared ? /* @__PURE__ */ jsxRuntime.jsx(ExploreView, { ...props, conversation: shared }) : /* @__PURE__ */ jsxRuntime.jsx(StandaloneExplorePage, { ...props });
6707
+ }
6708
+ function StandaloneExplorePage(props) {
6709
+ const conversation = useExploreConversation({
6710
+ productSlug: props.productSlug,
6711
+ locale: props.locale,
6712
+ examplePrompts: props.examplePrompts,
6713
+ onSend: props.onSend
6714
+ });
6715
+ return /* @__PURE__ */ jsxRuntime.jsx(ExploreView, { ...props, conversation });
6716
+ }
6717
+ function ExploreView({
6441
6718
  seo,
6442
6719
  productSlug,
6443
- examplePrompts,
6444
6720
  className,
6445
6721
  heightMode = "viewport",
6446
6722
  viewportOffset,
6447
6723
  onNavigate,
6448
- onSend,
6449
6724
  welcomeTitle,
6450
6725
  welcomeBody,
6451
- locale
6726
+ locale,
6727
+ presentation = "page",
6728
+ active = true,
6729
+ explorePath = "/explore",
6730
+ examplePrompts,
6731
+ scope,
6732
+ productName,
6733
+ conversation
6452
6734
  }) {
6735
+ const panel = presentation === "panel";
6736
+ const viewportPage = !panel && heightMode === "viewport";
6453
6737
  const pageUrl = React.useMemo(
6454
6738
  () => typeof window === "undefined" ? void 0 : window.location.href,
6455
6739
  []
@@ -6485,26 +6769,21 @@ function ExplorePage({
6485
6769
  escalate,
6486
6770
  canEscalate,
6487
6771
  createShareLink,
6488
- isSharedView
6489
- } = useExploreChat({
6490
- productSlug,
6491
- pageUrl,
6492
- onSend,
6493
- // Locale-aware, so a catalog outage degrades to a translated welcome rather than an
6494
- // English one. `T.prompts` seeds the chips the same way.
6495
- examplePrompts: examplePrompts ?? T.prompts,
6496
- fallbackWelcome: { title: T.welcomeTitle, body: T.welcomeBody }
6497
- });
6498
- const [draft, setDraft] = React.useState("");
6772
+ isSharedView,
6773
+ draft,
6774
+ setDraft,
6775
+ staged,
6776
+ setStaged
6777
+ } = conversation;
6499
6778
  const textareaRef = React.useRef(null);
6500
6779
  React.useEffect(() => {
6501
- if (typeof window === "undefined") return;
6780
+ if (typeof window === "undefined" || panel) return;
6502
6781
  const params = new URLSearchParams(window.location.search);
6503
6782
  if (params.has("c")) return;
6504
6783
  const question = params.get("q")?.trim();
6505
6784
  if (!question) return;
6506
6785
  setDraft(question.slice(0, EXPLORE_PREFILL_MAX_LENGTH));
6507
- }, []);
6786
+ }, [panel, setDraft]);
6508
6787
  const [historyOpen, setHistoryOpen] = React.useState(false);
6509
6788
  const speechStopRef = React.useRef(() => void 0);
6510
6789
  const stopDictation = React.useCallback(() => {
@@ -6520,8 +6799,12 @@ function ExplorePage({
6520
6799
  }
6521
6800
  });
6522
6801
  speechStopRef.current = speech.stop;
6802
+ React.useEffect(() => {
6803
+ if (active) return;
6804
+ stopDictation();
6805
+ stopSpeaking();
6806
+ }, [active, stopDictation]);
6523
6807
  const [disclaimerOpen, setDisclaimerOpen] = React.useState(false);
6524
- const [staged, setStaged] = React.useState([]);
6525
6808
  const [attachmentNotice, setAttachmentNotice] = React.useState(null);
6526
6809
  const fileInputRef = React.useRef(null);
6527
6810
  const stagedRef = React.useRef([]);
@@ -6541,16 +6824,47 @@ function ExplorePage({
6541
6824
  const maxLength = catalog.limits.maxMessageLength;
6542
6825
  const overLimit = draft.length > maxLength;
6543
6826
  const canSubmit = canSend && draft.trim().length > 0 && !overLimit && !busy;
6544
- const resolvedTitle = welcomeTitle ?? catalog.welcomeTitle;
6545
- const resolvedBody = welcomeBody ?? catalog.welcomeBody;
6546
- const prompts = catalog.examplePrompts;
6827
+ const pinnedSlug = pinnedProductSlug(scope, productSlug);
6828
+ React.useEffect(() => {
6829
+ if (scope === "product" && pinnedSlug === null) {
6830
+ warnProductScopeWithoutSlug();
6831
+ }
6832
+ }, [pinnedSlug, scope]);
6833
+ const pinnedName = React.useMemo(
6834
+ () => pinnedSlug === null ? null : productNameFor(catalog.products, pinnedSlug, productName),
6835
+ [catalog.products, pinnedSlug, productName]
6836
+ );
6837
+ const namesAnotherProduct = React.useMemo(
6838
+ () => pinnedSlug === null ? null : anotherProductMatcher(catalog.products, pinnedSlug),
6839
+ [catalog.products, pinnedSlug]
6840
+ );
6841
+ const resolvedTitle = welcomeTitle ?? (namesAnotherProduct?.(catalog.welcomeTitle) ? T.welcomeTitle : catalog.welcomeTitle);
6842
+ const resolvedBody = welcomeBody ?? (pinnedSlug === null ? catalog.welcomeBody : pinnedName === null ? T.welcomeBodyScoped : fill(T.welcomeBodyProduct, { product: pinnedName }));
6843
+ const prompts = React.useMemo(
6844
+ () => namesAnotherProduct === null ? catalog.examplePrompts : productScopedPrompts(
6845
+ examplePrompts,
6846
+ catalog.examplePrompts,
6847
+ namesAnotherProduct
6848
+ ),
6849
+ [catalog.examplePrompts, examplePrompts, namesAnotherProduct]
6850
+ );
6851
+ const conceptHighlights = React.useMemo(
6852
+ () => pinnedSlug === null || namesAnotherProduct === null ? catalog.conceptHighlights : productScopedHighlights(
6853
+ catalog.conceptHighlights,
6854
+ pinnedSlug,
6855
+ namesAnotherProduct
6856
+ ),
6857
+ [catalog.conceptHighlights, namesAnotherProduct, pinnedSlug]
6858
+ );
6547
6859
  const focusedProductName = React.useMemo(
6548
- () => catalog.products.find((p) => isSameProductSlug(p.slug, focusProduct))?.name ?? null,
6549
- [catalog.products, focusProduct]
6860
+ () => pinnedSlug !== null ? pinnedName : catalog.products.find((p) => isSameProductSlug(p.slug, focusProduct))?.name ?? null,
6861
+ [catalog.products, focusProduct, pinnedName, pinnedSlug]
6550
6862
  );
6551
6863
  const headProductName = React.useMemo(
6552
- () => productSlug ? catalog.products.find((p) => isSameProductSlug(p.slug, productSlug))?.name ?? null : null,
6553
- [catalog.products, productSlug]
6864
+ () => pinnedSlug !== null ? pinnedName : productSlug ? catalog.products.find(
6865
+ (p) => isSameProductSlug(p.slug, productSlug)
6866
+ )?.name ?? null : null,
6867
+ [catalog.products, pinnedName, pinnedSlug, productSlug]
6554
6868
  );
6555
6869
  const imageOrigins = React.useMemo(
6556
6870
  () => inlineImageOrigins(catalog.products),
@@ -6574,7 +6888,7 @@ function ExplorePage({
6574
6888
  const [bottomInset, setBottomInset] = React.useState(0);
6575
6889
  const paneOffsetRef = React.useRef(0);
6576
6890
  const measurePane = React.useCallback(() => {
6577
- if (heightMode !== "viewport") return;
6891
+ if (!viewportPage) return;
6578
6892
  const el = rootRef.current;
6579
6893
  if (!el) return;
6580
6894
  const layoutHeight = window.innerHeight;
@@ -6593,7 +6907,7 @@ function ExplorePage({
6593
6907
  paneOffsetRef.current = top;
6594
6908
  setPaneOffset((current) => current === top ? current : top);
6595
6909
  setBottomInset((current) => current === inset ? current : inset);
6596
- }, [heightMode]);
6910
+ }, [viewportPage]);
6597
6911
  const [chromeOverlap, setChromeOverlap] = React.useState(0);
6598
6912
  const measureChrome = React.useCallback(() => {
6599
6913
  const root = rootRef.current;
@@ -6618,7 +6932,7 @@ function ExplorePage({
6618
6932
  measureChrome();
6619
6933
  }, [measurePane, measureChrome]);
6620
6934
  React.useEffect(() => {
6621
- if (typeof window === "undefined") return;
6935
+ if (typeof window === "undefined" || panel) return;
6622
6936
  let frame = 0;
6623
6937
  const run = () => {
6624
6938
  frame = 0;
@@ -6656,12 +6970,12 @@ function ExplorePage({
6656
6970
  setBottomInset(0);
6657
6971
  setChromeOverlap(0);
6658
6972
  };
6659
- }, [remeasure]);
6973
+ }, [remeasure, panel]);
6660
6974
  React.useEffect(() => {
6661
6975
  measureChrome();
6662
6976
  }, [measureChrome, paneOffset, bottomInset]);
6663
6977
  React.useEffect(() => {
6664
- if (heightMode !== "viewport" || typeof window === "undefined") return;
6978
+ if (!viewportPage || typeof window === "undefined") return;
6665
6979
  const { history: browserHistory } = window;
6666
6980
  const previousRestoration = "scrollRestoration" in browserHistory ? browserHistory.scrollRestoration : null;
6667
6981
  if (previousRestoration !== null)
@@ -6729,14 +7043,14 @@ function ExplorePage({
6729
7043
  if (previousRestoration !== null)
6730
7044
  browserHistory.scrollRestoration = previousRestoration;
6731
7045
  };
6732
- }, [heightMode, remeasure]);
7046
+ }, [viewportPage, remeasure]);
6733
7047
  const handleScroll = React.useCallback(() => {
6734
7048
  const el = scrollRef.current;
6735
7049
  if (!el) return;
6736
7050
  stickToBottomRef.current = el.scrollHeight - el.scrollTop - el.clientHeight < 80;
6737
7051
  }, []);
6738
7052
  React.useEffect(() => {
6739
- if (typeof window === "undefined") return;
7053
+ if (typeof window === "undefined" || panel) return;
6740
7054
  let frame = 0;
6741
7055
  const run = () => {
6742
7056
  frame = 0;
@@ -6759,7 +7073,7 @@ function ExplorePage({
6759
7073
  if (frame) window.cancelAnimationFrame(frame);
6760
7074
  window.removeEventListener("scroll", schedule);
6761
7075
  };
6762
- }, []);
7076
+ }, [panel]);
6763
7077
  const latestAssistantId = React.useMemo(() => {
6764
7078
  for (let i = messages.length - 1; i >= 0; i -= 1) {
6765
7079
  const message = messages[i];
@@ -6775,7 +7089,7 @@ function ExplorePage({
6775
7089
  if (!stickToBottomRef.current) return;
6776
7090
  if (anchor.offsetHeight === 0) return;
6777
7091
  alignedForRef.current = latestAssistantId;
6778
- if (!pageOwnsScrolling(el)) {
7092
+ if (panel || !pageOwnsScrolling(el)) {
6779
7093
  const delta2 = anchor.getBoundingClientRect().top - el.getBoundingClientRect().top;
6780
7094
  el.scrollTop = Math.max(0, el.scrollTop + delta2 - 12);
6781
7095
  return;
@@ -6784,7 +7098,7 @@ function ExplorePage({
6784
7098
  anchor.getBoundingClientRect().top - paneOffsetRef.current - 12
6785
7099
  );
6786
7100
  if (delta !== 0) window.scrollBy({ top: delta, left: 0, behavior: "auto" });
6787
- }, [latestAssistantId, messages]);
7101
+ }, [latestAssistantId, messages, panel]);
6788
7102
  React.useEffect(() => {
6789
7103
  if (messages.length === 0) return;
6790
7104
  if (!stickToBottomRef.current) return;
@@ -6792,7 +7106,7 @@ function ExplorePage({
6792
7106
  return;
6793
7107
  const el = scrollRef.current;
6794
7108
  if (!el) return;
6795
- if (!pageOwnsScrolling(el)) {
7109
+ if (panel || !pageOwnsScrolling(el)) {
6796
7110
  el.scrollTop = el.scrollHeight;
6797
7111
  return;
6798
7112
  }
@@ -6801,7 +7115,7 @@ function ExplorePage({
6801
7115
  dock.getBoundingClientRect().bottom - visualViewportHeight()
6802
7116
  );
6803
7117
  if (delta > 0) window.scrollBy({ top: delta, left: 0, behavior: "auto" });
6804
- }, [activity, latestAssistantId, messages]);
7118
+ }, [activity, latestAssistantId, messages, panel]);
6805
7119
  const handleShare = React.useCallback(async () => {
6806
7120
  setShareLabel(T.copying);
6807
7121
  setShareUrl(null);
@@ -6811,7 +7125,7 @@ function ExplorePage({
6811
7125
  setTimeout(() => setShareLabel(T.share), 2500);
6812
7126
  return;
6813
7127
  }
6814
- const url = new URL(pageUrl ?? window.location.href);
7128
+ const url = panel ? new URL(explorePath, window.location.href) : new URL(pageUrl ?? window.location.href);
6815
7129
  url.search = "";
6816
7130
  url.hash = "";
6817
7131
  url.searchParams.set("c", token);
@@ -6827,6 +7141,8 @@ function ExplorePage({
6827
7141
  }, [
6828
7142
  createShareLink,
6829
7143
  pageUrl,
7144
+ panel,
7145
+ explorePath,
6830
7146
  T.copied,
6831
7147
  T.copying,
6832
7148
  T.share,
@@ -6855,12 +7171,26 @@ function ExplorePage({
6855
7171
  });
6856
7172
  return pickQueueRef.current;
6857
7173
  },
6858
- [T]
7174
+ [T, setStaged]
7175
+ );
7176
+ const removeAttachment = React.useCallback(
7177
+ (id) => {
7178
+ setStaged((prev) => prev.filter((entry) => entry.id !== id));
7179
+ setAttachmentNotice(null);
7180
+ },
7181
+ [setStaged]
7182
+ );
7183
+ const pinFocus = React.useCallback(() => {
7184
+ if (pinnedSlug !== null) setFocusProduct(pinnedSlug);
7185
+ }, [pinnedSlug, setFocusProduct]);
7186
+ const retryTurn = React.useCallback(() => {
7187
+ pinFocus();
7188
+ retry();
7189
+ }, [pinFocus, retry]);
7190
+ const shownError = React.useMemo(
7191
+ () => error !== null && pinnedSlug !== null ? productScopedError(error, T.toolBudgetScoped) : error,
7192
+ [T, error, pinnedSlug]
6859
7193
  );
6860
- const removeAttachment = React.useCallback((id) => {
6861
- setStaged((prev) => prev.filter((entry) => entry.id !== id));
6862
- setAttachmentNotice(null);
6863
- }, []);
6864
7194
  const submitDraft = React.useCallback(() => {
6865
7195
  const text = draft.trim();
6866
7196
  if (!text || overLimit || busy || !canSend) return;
@@ -6868,22 +7198,34 @@ function ExplorePage({
6868
7198
  stopSpeaking();
6869
7199
  setDraft("");
6870
7200
  stickToBottomRef.current = true;
7201
+ pinFocus();
6871
7202
  void send(text, toPayload(stagedRef.current));
6872
7203
  setStaged([]);
6873
7204
  setAttachmentNotice(null);
6874
7205
  textareaRef.current?.focus();
6875
- }, [busy, canSend, draft, overLimit, send, stopDictation]);
7206
+ }, [
7207
+ busy,
7208
+ canSend,
7209
+ draft,
7210
+ overLimit,
7211
+ pinFocus,
7212
+ send,
7213
+ setDraft,
7214
+ setStaged,
7215
+ stopDictation
7216
+ ]);
6876
7217
  const sendPrompt = React.useCallback(
6877
7218
  (prompt) => {
6878
7219
  if (!canSend || busy) return;
6879
7220
  stopSpeaking();
6880
7221
  setDraft("");
6881
7222
  stickToBottomRef.current = true;
7223
+ pinFocus();
6882
7224
  void send(prompt, toPayload(stagedRef.current));
6883
7225
  setStaged([]);
6884
7226
  setAttachmentNotice(null);
6885
7227
  },
6886
- [busy, canSend, send]
7228
+ [busy, canSend, pinFocus, send, setDraft, setStaged]
6887
7229
  );
6888
7230
  const handleKeyDown = React.useCallback(
6889
7231
  (event) => {
@@ -6905,7 +7247,7 @@ function ExplorePage({
6905
7247
  [serverCatalogRaw]
6906
7248
  );
6907
7249
  const rootStyle = {};
6908
- if (heightMode === "viewport") {
7250
+ if (viewportPage) {
6909
7251
  rootStyle["--boff-explore-offset"] = paneOffset === null ? normalizeOffset(viewportOffset) : `${paneOffset}px`;
6910
7252
  if (bottomInset > 0) {
6911
7253
  rootStyle["--boff-explore-inset"] = `${bottomInset}px`;
@@ -6918,23 +7260,29 @@ function ExplorePage({
6918
7260
  "div",
6919
7261
  {
6920
7262
  ref: rootRef,
6921
- "data-boff-explore": "page",
7263
+ "data-boff-explore": panel ? "panel" : "page",
6922
7264
  "data-phase": phase,
6923
7265
  "data-locale": activeLocale,
6924
7266
  dir: rtl ? "rtl" : void 0,
6925
7267
  className: cn(
6926
- "flex w-full min-w-0 flex-col overflow-x-hidden bg-background text-foreground",
6927
- heightMode === "viewport" && "boff-explore-viewport",
6928
- heightMode === "auto" && "min-h-[70vh]",
7268
+ panel ? "boff-explore-panel flex h-full min-h-0 w-full min-w-0 flex-col overflow-hidden bg-background text-foreground" : "flex w-full min-w-0 flex-col overflow-x-hidden bg-background text-foreground",
7269
+ viewportPage && "boff-explore-viewport",
7270
+ !panel && heightMode === "auto" && "min-h-[70vh]",
6929
7271
  className
6930
7272
  ),
6931
- style: rootStyle,
7273
+ style: panel ? void 0 : rootStyle,
6932
7274
  children: [
6933
- /* @__PURE__ */ jsxRuntime.jsx(
7275
+ panel ? null : /* @__PURE__ */ jsxRuntime.jsx(
6934
7276
  PageHead,
6935
7277
  {
6936
7278
  title: seo?.title ?? T.seoTitle,
6937
- description: seo?.description ?? (headProductName ? fill(T.seoDescriptionProduct, { product: headProductName }) : T.seoDescription),
7279
+ description: seo?.description ?? (headProductName ? fill(
7280
+ // BOFF-9796: one product's own page promises that product's answers alone, never "and every
7281
+ // other product we build". The title ("Describe a problem, get an answer | {product}") and the
7282
+ // site name already name this product only, and the og:/twitter: tags repeat these two.
7283
+ pinnedSlug === null ? T.seoDescriptionProduct : T.seoDescriptionScoped,
7284
+ { product: headProductName }
7285
+ ) : T.seoDescription),
6938
7286
  productName: seo?.title ? void 0 : headProductName ?? void 0,
6939
7287
  keywords: seo?.keywords,
6940
7288
  image: seo?.image,
@@ -6943,7 +7291,11 @@ function ExplorePage({
6943
7291
  ),
6944
7292
  /* @__PURE__ */ jsxRuntime.jsx(ProseStyles, {}),
6945
7293
  /* @__PURE__ */ jsxRuntime.jsx(ExploreStyles, {}),
6946
- bakedCatalogJson ? /* @__PURE__ */ jsxRuntime.jsx(
7294
+ panel ? /* @__PURE__ */ jsxRuntime.jsx("style", { children: `.boff-explore-panel .boff-explore-scroll { container: boff-explore-pane / size; }
7295
+ @container boff-explore-pane (width < ${toRem(WELCOME_FIT_MIN_WIDTH_PX)}) {
7296
+ .boff-explore-panel .boff-explore-scroll .boff-explore-capabilities { display: none; }
7297
+ }` }) : null,
7298
+ !panel && bakedCatalogJson ? /* @__PURE__ */ jsxRuntime.jsx(
6947
7299
  "script",
6948
7300
  {
6949
7301
  id: BAKED_CATALOG_ELEMENT_ID,
@@ -6963,7 +7315,7 @@ function ExplorePage({
6963
7315
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "h-4 w-4" })
6964
7316
  }
6965
7317
  ),
6966
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "truncate text-sm font-semibold", children: resolvedTitle }),
7318
+ panel ? /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "truncate text-sm font-semibold", children: resolvedTitle }) : /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "truncate text-sm font-semibold", children: resolvedTitle }),
6967
7319
  focusedProductName ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden shrink-0 rounded-full bg-secondary px-2 py-0.5 text-xs font-medium text-secondary-foreground sm:inline", children: focusedProductName }) : null,
6968
7320
  /* @__PURE__ */ jsxRuntime.jsxs(
6969
7321
  Button,
@@ -7107,16 +7459,18 @@ function ExplorePage({
7107
7459
  children: showWelcome ? /* @__PURE__ */ jsxRuntime.jsx(
7108
7460
  WelcomeState,
7109
7461
  {
7462
+ heading: panel ? "h2" : "h1",
7110
7463
  strings: T,
7111
7464
  title: resolvedTitle,
7112
7465
  body: resolvedBody,
7113
7466
  prompts,
7114
- products: catalog.products,
7115
- conceptHighlights: catalog.conceptHighlights,
7467
+ products: pinnedSlug === null ? catalog.products : NO_PRODUCTS,
7468
+ conceptHighlights,
7116
7469
  focusProduct,
7117
7470
  onPrompt: sendPrompt,
7118
7471
  onFocus: setFocusProduct,
7119
- disabled: !canSend || busy
7472
+ disabled: !canSend || busy,
7473
+ productScoped: pinnedSlug !== null
7120
7474
  }
7121
7475
  ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto w-full min-w-0 max-w-3xl space-y-6 px-4 py-6", children: messages.map(
7122
7476
  (message) => message.role === "USER" ? /* @__PURE__ */ jsxRuntime.jsx(UserBubble, { strings: T, message }, message.id) : /* @__PURE__ */ jsxRuntime.jsx(
@@ -7193,7 +7547,14 @@ function ExplorePage({
7193
7547
  submitDraft();
7194
7548
  },
7195
7549
  children: [
7196
- error ? /* @__PURE__ */ jsxRuntime.jsx(ErrorBanner, { error, onRetry: retry, onReset: reset }) : null,
7550
+ shownError ? /* @__PURE__ */ jsxRuntime.jsx(
7551
+ ErrorBanner,
7552
+ {
7553
+ error: shownError,
7554
+ onRetry: retryTurn,
7555
+ onReset: reset
7556
+ }
7557
+ ) : null,
7197
7558
  staged.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
7198
7559
  "ul",
7199
7560
  {
@@ -7279,9 +7640,14 @@ function ExplorePage({
7279
7640
  composingRef.current = false;
7280
7641
  },
7281
7642
  "aria-label": "Ask a question",
7282
- placeholder: composerDisabled ? phase === "limited" ? "Message limit reached \u2014 please try again later" : "Explore is unavailable right now" : focusedProductName ? fill(T.placeholderProduct, {
7283
- product: focusedProductName
7284
- }) : T.placeholder,
7643
+ placeholder: composerDisabled ? phase === "limited" ? "Message limit reached \u2014 please try again later" : "Explore is unavailable right now" : focusedProductName ? fill(
7644
+ // BOFF-9796: one product's own assistant keeps this field exactly as every site has it, its
7645
+ // classes and its fit to the draft alone; only its placeholder says less. On a phone the
7646
+ // field is one line tall and cuts off a placeholder that wraps: in English, "Ask about
7647
+ // {product}…" fits that line at 320px and wider.
7648
+ pinnedSlug === null ? T.placeholderProduct : T.placeholderScoped,
7649
+ { product: focusedProductName }
7650
+ ) : T.placeholder,
7285
7651
  className: "max-h-[200px] min-h-[44px] w-full min-w-0 flex-1 resize-none border-0 bg-transparent px-2 py-2.5 text-base shadow-none focus-visible:ring-0 sm:text-sm"
7286
7652
  }
7287
7653
  ),