@burdenoff/website-sdk 2026.921.1 → 2026.922.2

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.
@@ -49,8 +49,8 @@ function isRtlLocale(locale) {
49
49
  }
50
50
  var EN = {
51
51
  badge: "AI answers, grounded in our documentation",
52
- welcomeTitle: "Ask anything about our products",
53
- welcomeBody: "Describe what you are trying to do and I will point you at the product, the page and the next step.",
52
+ welcomeTitle: "What problem are you trying to solve?",
53
+ welcomeBody: "Describe the problem you're facing, in your own words. You can also ask about a specific product or compare a few. Every answer comes straight from our documentation.",
54
54
  tryAsking: "Try asking",
55
55
  focusProduct: "Focus on a product",
56
56
  allProducts: "All products",
@@ -58,8 +58,8 @@ var EN = {
58
58
  showLess: "Show less",
59
59
  sources: "Sources",
60
60
  nextYouCouldAsk: "Next you could ask",
61
- placeholder: "Ask anything about our products\u2026",
62
- placeholderProduct: "Ask about {product}\u2026",
61
+ placeholder: "Describe the problem you're facing\u2026",
62
+ placeholderProduct: "Describe a problem, or ask about {product}\u2026",
63
63
  send: "Send",
64
64
  stop: "Stop",
65
65
  newChat: "New chat",
@@ -92,16 +92,16 @@ var EN = {
92
92
  "Straight to the right page"
93
93
  ],
94
94
  prompts: [
95
- "What does this product actually do?",
96
- "Which product fits my team?",
97
- "How do I get started, step by step?",
98
- "How much does it cost?"
95
+ "Every course we run lives in a different spreadsheet.",
96
+ "We only hear a machine is down after the line has stopped.",
97
+ "Members quietly stop showing up and we never know why.",
98
+ "Which of your products fits a problem like mine?"
99
99
  ]
100
100
  };
101
101
  var ZH = {
102
102
  badge: "\u57FA\u4E8E\u6211\u4EEC\u6587\u6863\u7684 AI \u56DE\u7B54",
103
- welcomeTitle: "\u5173\u4E8E\u6211\u4EEC\u7684\u4EA7\u54C1\uFF0C\u968F\u4FBF\u95EE",
104
- welcomeBody: "\u63CF\u8FF0\u4F60\u60F3\u505A\u7684\u4E8B\uFF0C\u6211\u4F1A\u4E3A\u4F60\u6307\u51FA\u5BF9\u5E94\u7684\u4EA7\u54C1\u3001\u9875\u9762\u548C\u4E0B\u4E00\u6B65\u3002",
103
+ welcomeTitle: "\u4F60\u60F3\u89E3\u51B3\u4EC0\u4E48\u95EE\u9898\uFF1F",
104
+ welcomeBody: "\u7528\u4F60\u81EA\u5DF1\u7684\u8BDD\u63CF\u8FF0\u4F60\u9047\u5230\u7684\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",
105
105
  tryAsking: "\u8BD5\u7740\u95EE",
106
106
  focusProduct: "\u805A\u7126\u67D0\u4E2A\u4EA7\u54C1",
107
107
  allProducts: "\u5168\u90E8\u4EA7\u54C1",
@@ -109,8 +109,8 @@ var ZH = {
109
109
  showLess: "\u6536\u8D77",
110
110
  sources: "\u6765\u6E90",
111
111
  nextYouCouldAsk: "\u4F60\u8FD8\u53EF\u4EE5\u95EE",
112
- placeholder: "\u5173\u4E8E\u6211\u4EEC\u7684\u4EA7\u54C1\uFF0C\u968F\u4FBF\u95EE\u2026",
113
- placeholderProduct: "\u8BE2\u95EE\u5173\u4E8E {product} \u7684\u95EE\u9898\u2026",
112
+ placeholder: "\u63CF\u8FF0\u4F60\u9047\u5230\u7684\u95EE\u9898\u2026",
113
+ placeholderProduct: "\u63CF\u8FF0\u95EE\u9898\uFF0C\u6216\u8BE2\u95EE {product}\u2026",
114
114
  send: "\u53D1\u9001",
115
115
  stop: "\u505C\u6B62",
116
116
  newChat: "\u65B0\u5BF9\u8BDD",
@@ -139,16 +139,16 @@ var ZH = {
139
139
  opensInNewTab: "\u5728\u65B0\u6807\u7B7E\u9875\u4E2D\u6253\u5F00",
140
140
  capabilities: ["\u57FA\u4E8E\u6211\u4EEC\u81EA\u5DF1\u7684\u6587\u6863", "\u8DE8\u4EA7\u54C1\u5BF9\u6BD4", "\u76F4\u8FBE\u6B63\u786E\u7684\u9875\u9762"],
141
141
  prompts: [
142
- "\u8FD9\u4E2A\u4EA7\u54C1\u5230\u5E95\u80FD\u505A\u4EC0\u4E48\uFF1F",
143
- "\u54EA\u4E2A\u4EA7\u54C1\u9002\u5408\u6211\u7684\u56E2\u961F\uFF1F",
144
- "\u5982\u4F55\u4E00\u6B65\u6B65\u5F00\u59CB\u4F7F\u7528\uFF1F",
145
- "\u4EF7\u683C\u662F\u591A\u5C11\uFF1F"
142
+ "\u6BCF\u95E8\u8BFE\u7A0B\u90FD\u8BB0\u5728\u4E0D\u540C\u7684\u8868\u683C\u91CC\u3002",
143
+ "\u673A\u5668\u505C\u4E86\uFF0C\u8981\u7B49\u6574\u6761\u7EBF\u505C\u4E0B\u6765\u624D\u77E5\u9053\u3002",
144
+ "\u4F1A\u5458\u6162\u6162\u5C31\u4E0D\u6765\u4E86\uFF0C\u6211\u4EEC\u4E5F\u4E0D\u77E5\u9053\u4E3A\u4EC0\u4E48\u3002",
145
+ "\u54EA\u4E2A\u4EA7\u54C1\u9002\u5408\u6211\u8FD9\u6837\u7684\u95EE\u9898\uFF1F"
146
146
  ]
147
147
  };
148
148
  var HI = {
149
149
  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",
150
- welcomeTitle: "\u0939\u092E\u093E\u0930\u0947 \u0909\u0924\u094D\u092A\u093E\u0926\u094B\u0902 \u0915\u0947 \u092C\u093E\u0930\u0947 \u092E\u0947\u0902 \u0915\u0941\u091B \u092D\u0940 \u092A\u0942\u091B\u0947\u0902",
151
- welcomeBody: "\u092C\u0924\u093E\u0907\u090F \u0906\u092A \u0915\u094D\u092F\u093E \u0915\u0930\u0928\u093E \u091A\u093E\u0939\u0924\u0947 \u0939\u0948\u0902, \u0914\u0930 \u092E\u0948\u0902 \u0906\u092A\u0915\u094B \u0938\u0939\u0940 \u0909\u0924\u094D\u092A\u093E\u0926, \u092A\u0947\u091C \u0914\u0930 \u0905\u0917\u0932\u093E \u0915\u0926\u092E \u092C\u0924\u093E\u090A\u0901\u0917\u093E\u0964",
150
+ 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?",
151
+ 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",
152
152
  tryAsking: "\u092F\u0939 \u092A\u0942\u091B\u0915\u0930 \u0926\u0947\u0916\u0947\u0902",
153
153
  focusProduct: "\u0915\u093F\u0938\u0940 \u0909\u0924\u094D\u092A\u093E\u0926 \u092A\u0930 \u0927\u094D\u092F\u093E\u0928 \u0926\u0947\u0902",
154
154
  allProducts: "\u0938\u092D\u0940 \u0909\u0924\u094D\u092A\u093E\u0926",
@@ -156,8 +156,8 @@ var HI = {
156
156
  showLess: "\u0915\u092E \u0926\u093F\u0916\u093E\u090F\u0901",
157
157
  sources: "\u0938\u094D\u0930\u094B\u0924",
158
158
  nextYouCouldAsk: "\u0906\u0917\u0947 \u0906\u092A \u092A\u0942\u091B \u0938\u0915\u0924\u0947 \u0939\u0948\u0902",
159
- placeholder: "\u0939\u092E\u093E\u0930\u0947 \u0909\u0924\u094D\u092A\u093E\u0926\u094B\u0902 \u0915\u0947 \u092C\u093E\u0930\u0947 \u092E\u0947\u0902 \u0915\u0941\u091B \u092D\u0940 \u092A\u0942\u091B\u0947\u0902\u2026",
160
- placeholderProduct: "{product} \u0915\u0947 \u092C\u093E\u0930\u0947 \u092E\u0947\u0902 \u092A\u0942\u091B\u0947\u0902\u2026",
159
+ placeholder: "\u0905\u092A\u0928\u0940 \u0938\u092E\u0938\u094D\u092F\u093E \u092F\u0939\u093E\u0901 \u092C\u0924\u093E\u090F\u0902\u2026",
160
+ 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",
161
161
  send: "\u092D\u0947\u091C\u0947\u0902",
162
162
  stop: "\u0930\u094B\u0915\u0947\u0902",
163
163
  newChat: "\u0928\u0908 \u092C\u093E\u0924\u091A\u0940\u0924",
@@ -190,16 +190,16 @@ var HI = {
190
190
  "\u0938\u0940\u0927\u0947 \u0938\u0939\u0940 \u092A\u0947\u091C \u092A\u0930"
191
191
  ],
192
192
  prompts: [
193
- "\u092F\u0939 \u0909\u0924\u094D\u092A\u093E\u0926 \u0905\u0938\u0932 \u092E\u0947\u0902 \u0915\u094D\u092F\u093E \u0915\u0930\u0924\u093E \u0939\u0948?",
194
- "\u092E\u0947\u0930\u0940 \u091F\u0940\u092E \u0915\u0947 \u0932\u093F\u090F \u0915\u094C\u0928 \u0938\u093E \u0909\u0924\u094D\u092A\u093E\u0926 \u0938\u0939\u0940 \u0939\u0948?",
195
- "\u0936\u0941\u0930\u0941\u0906\u0924 \u0915\u0948\u0938\u0947 \u0915\u0930\u0947\u0902, \u091A\u0930\u0923 \u0926\u0930 \u091A\u0930\u0923?",
196
- "\u0907\u0938\u0915\u0940 \u0915\u0940\u092E\u0924 \u0915\u093F\u0924\u0928\u0940 \u0939\u0948?"
193
+ "\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",
194
+ "\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",
195
+ "\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",
196
+ "\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?"
197
197
  ]
198
198
  };
199
199
  var ES = {
200
200
  badge: "Respuestas de IA basadas en nuestra documentaci\xF3n",
201
- welcomeTitle: "Pregunta lo que quieras sobre nuestros productos",
202
- welcomeBody: "Cu\xE9ntame qu\xE9 necesitas hacer y te indicar\xE9 el producto, la p\xE1gina y el siguiente paso.",
201
+ welcomeTitle: "\xBFQu\xE9 problema quieres resolver?",
202
+ welcomeBody: "Describe el problema que tienes con tus propias palabras. Tambi\xE9n puedes preguntar por un producto concreto o comparar varios. Cada respuesta procede directamente de nuestra documentaci\xF3n.",
203
203
  tryAsking: "Prueba a preguntar",
204
204
  focusProduct: "Centrarse en un producto",
205
205
  allProducts: "Todos los productos",
@@ -207,8 +207,8 @@ var ES = {
207
207
  showLess: "Ver menos",
208
208
  sources: "Fuentes",
209
209
  nextYouCouldAsk: "Tambi\xE9n puedes preguntar",
210
- placeholder: "Pregunta lo que quieras sobre nuestros productos\u2026",
211
- placeholderProduct: "Pregunta sobre {product}\u2026",
210
+ placeholder: "Describe el problema que tienes\u2026",
211
+ placeholderProduct: "Describe un problema o pregunta por {product}\u2026",
212
212
  send: "Enviar",
213
213
  stop: "Detener",
214
214
  newChat: "Nueva conversaci\xF3n",
@@ -241,16 +241,16 @@ var ES = {
241
241
  "Directo a la p\xE1gina correcta"
242
242
  ],
243
243
  prompts: [
244
- "\xBFQu\xE9 hace realmente este producto?",
245
- "\xBFQu\xE9 producto encaja con mi equipo?",
246
- "\xBFC\xF3mo empiezo, paso a paso?",
247
- "\xBFCu\xE1nto cuesta?"
244
+ "Cada curso que damos est\xE1 en una hoja de c\xE1lculo distinta.",
245
+ "Nos enteramos de que una m\xE1quina falla cuando para la l\xEDnea.",
246
+ "Los socios dejan de venir poco a poco y nunca sabemos por qu\xE9.",
247
+ "\xBFQu\xE9 producto encaja con un problema como el m\xEDo?"
248
248
  ]
249
249
  };
250
250
  var AR = {
251
251
  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",
252
- welcomeTitle: "\u0627\u0633\u0623\u0644 \u0623\u064A \u0634\u064A\u0621 \u0639\u0646 \u0645\u0646\u062A\u062C\u0627\u062A\u0646\u0627",
253
- welcomeBody: "\u0635\u0650\u0641 \u0645\u0627 \u062A\u0631\u064A\u062F \u0625\u0646\u062C\u0627\u0632\u0647 \u0648\u0633\u0623\u062F\u0644\u0651\u0643 \u0639\u0644\u0649 \u0627\u0644\u0645\u0646\u062A\u062C \u0648\u0627\u0644\u0635\u0641\u062D\u0629 \u0648\u0627\u0644\u062E\u0637\u0648\u0629 \u0627\u0644\u062A\u0627\u0644\u064A\u0629.",
252
+ welcomeTitle: "\u0645\u0627 \u0627\u0644\u0645\u0634\u0643\u0644\u0629 \u0627\u0644\u062A\u064A \u062A\u062D\u0627\u0648\u0644 \u062D\u0644\u0647\u0627\u061F",
253
+ welcomeBody: "\u0635\u0641 \u0627\u0644\u0645\u0634\u0643\u0644\u0629 \u0627\u0644\u062A\u064A \u062A\u0648\u0627\u062C\u0647\u0647\u0627 \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.",
254
254
  tryAsking: "\u062C\u0631\u0651\u0628 \u0623\u0646 \u062A\u0633\u0623\u0644",
255
255
  focusProduct: "\u0627\u0644\u062A\u0631\u0643\u064A\u0632 \u0639\u0644\u0649 \u0645\u0646\u062A\u062C",
256
256
  allProducts: "\u0643\u0644 \u0627\u0644\u0645\u0646\u062A\u062C\u0627\u062A",
@@ -258,8 +258,8 @@ var AR = {
258
258
  showLess: "\u0639\u0631\u0636 \u0623\u0642\u0644",
259
259
  sources: "\u0627\u0644\u0645\u0635\u0627\u062F\u0631",
260
260
  nextYouCouldAsk: "\u064A\u0645\u0643\u0646\u0643 \u0623\u0646 \u062A\u0633\u0623\u0644 \u0628\u0639\u062F \u0630\u0644\u0643",
261
- placeholder: "\u0627\u0633\u0623\u0644 \u0623\u064A \u0634\u064A\u0621 \u0639\u0646 \u0645\u0646\u062A\u062C\u0627\u062A\u0646\u0627\u2026",
262
- placeholderProduct: "\u0627\u0633\u0623\u0644 \u0639\u0646 {product}\u2026",
261
+ placeholder: "\u0635\u0641 \u0627\u0644\u0645\u0634\u0643\u0644\u0629 \u0627\u0644\u062A\u064A \u062A\u0648\u0627\u062C\u0647\u0647\u0627\u2026",
262
+ placeholderProduct: "\u0635\u0641 \u0645\u0634\u0643\u0644\u062A\u0643 \u0623\u0648 \u0627\u0633\u0623\u0644 \u0639\u0646 {product}\u2026",
263
263
  send: "\u0625\u0631\u0633\u0627\u0644",
264
264
  stop: "\u0625\u064A\u0642\u0627\u0641",
265
265
  newChat: "\u0645\u062D\u0627\u062F\u062B\u0629 \u062C\u062F\u064A\u062F\u0629",
@@ -292,16 +292,16 @@ var AR = {
292
292
  "\u0645\u0628\u0627\u0634\u0631\u0629\u064B \u0625\u0644\u0649 \u0627\u0644\u0635\u0641\u062D\u0629 \u0627\u0644\u0635\u062D\u064A\u062D\u0629"
293
293
  ],
294
294
  prompts: [
295
- "\u0645\u0627 \u0627\u0644\u0630\u064A \u064A\u0641\u0639\u0644\u0647 \u0647\u0630\u0627 \u0627\u0644\u0645\u0646\u062A\u062C \u0641\u0639\u0644\u064A\u064B\u0627\u061F",
296
- "\u0623\u064A \u0645\u0646\u062A\u062C \u064A\u0646\u0627\u0633\u0628 \u0641\u0631\u064A\u0642\u064A\u061F",
297
- "\u0643\u064A\u0641 \u0623\u0628\u062F\u0623 \u062E\u0637\u0648\u0629 \u0628\u062E\u0637\u0648\u0629\u061F",
298
- "\u0643\u0645 \u062A\u0628\u0644\u063A \u0627\u0644\u062A\u0643\u0644\u0641\u0629\u061F"
295
+ "\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.",
296
+ "\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.",
297
+ "\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.",
298
+ "\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"
299
299
  ]
300
300
  };
301
301
  var TA = {
302
302
  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",
303
- welcomeTitle: "\u0B8E\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0BA4\u0BAF\u0BBE\u0BB0\u0BBF\u0BAA\u0BCD\u0BAA\u0BC1\u0B95\u0BB3\u0BCD \u0BAA\u0BB1\u0BCD\u0BB1\u0BBF \u0B8E\u0BA4\u0BC8\u0BAF\u0BC1\u0BAE\u0BCD \u0B95\u0BC7\u0BB3\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD",
304
- welcomeBody: "\u0BA8\u0BC0\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B8E\u0BA9\u0BCD\u0BA9 \u0B9A\u0BC6\u0BAF\u0BCD\u0BAF \u0BB5\u0BBF\u0BB0\u0BC1\u0BAE\u0BCD\u0BAA\u0BC1\u0B95\u0BBF\u0BB1\u0BC0\u0BB0\u0BCD\u0B95\u0BB3\u0BCD \u0B8E\u0BA9\u0BCD\u0BB1\u0BC1 \u0B9A\u0BCA\u0BB2\u0BCD\u0BB2\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD; \u0B9A\u0BB0\u0BBF\u0BAF\u0BBE\u0BA9 \u0BA4\u0BAF\u0BBE\u0BB0\u0BBF\u0BAA\u0BCD\u0BAA\u0BC1, \u0BAA\u0B95\u0BCD\u0B95\u0BAE\u0BCD, \u0B85\u0B9F\u0BC1\u0BA4\u0BCD\u0BA4 \u0BAA\u0B9F\u0BBF \u0B86\u0B95\u0BBF\u0BAF\u0BB5\u0BB1\u0BCD\u0BB1\u0BC8\u0B95\u0BCD \u0B95\u0BBE\u0B9F\u0BCD\u0B9F\u0BC1\u0B95\u0BBF\u0BB1\u0BC7\u0BA9\u0BCD.",
303
+ 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?",
304
+ welcomeBody: "\u0BA8\u0BC0\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B8E\u0BA4\u0BBF\u0BB0\u0BCD\u0B95\u0BCA\u0BB3\u0BCD\u0BB3\u0BC1\u0BAE\u0BCD \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.",
305
305
  tryAsking: "\u0B87\u0BA4\u0BC8\u0B95\u0BCD \u0B95\u0BC7\u0B9F\u0BCD\u0B9F\u0BC1\u0BAA\u0BCD \u0BAA\u0BBE\u0BB0\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD",
306
306
  focusProduct: "\u0B92\u0BB0\u0BC1 \u0BA4\u0BAF\u0BBE\u0BB0\u0BBF\u0BAA\u0BCD\u0BAA\u0BBF\u0BB2\u0BCD \u0B95\u0BB5\u0BA9\u0BAE\u0BCD",
307
307
  allProducts: "\u0B85\u0BA9\u0BC8\u0BA4\u0BCD\u0BA4\u0BC1 \u0BA4\u0BAF\u0BBE\u0BB0\u0BBF\u0BAA\u0BCD\u0BAA\u0BC1\u0B95\u0BB3\u0BCD",
@@ -309,8 +309,8 @@ var TA = {
309
309
  showLess: "\u0B95\u0BC1\u0BB1\u0BC8\u0BB5\u0BBE\u0B95\u0B95\u0BCD \u0B95\u0BBE\u0B9F\u0BCD\u0B9F\u0BC1",
310
310
  sources: "\u0BAE\u0BC2\u0BB2\u0B99\u0BCD\u0B95\u0BB3\u0BCD",
311
311
  nextYouCouldAsk: "\u0B85\u0B9F\u0BC1\u0BA4\u0BCD\u0BA4\u0BC1 \u0BA8\u0BC0\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B95\u0BC7\u0B9F\u0BCD\u0B95\u0BB2\u0BBE\u0BAE\u0BCD",
312
- placeholder: "\u0B8E\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0BA4\u0BAF\u0BBE\u0BB0\u0BBF\u0BAA\u0BCD\u0BAA\u0BC1\u0B95\u0BB3\u0BCD \u0BAA\u0BB1\u0BCD\u0BB1\u0BBF \u0B8E\u0BA4\u0BC8\u0BAF\u0BC1\u0BAE\u0BCD \u0B95\u0BC7\u0BB3\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD\u2026",
313
- placeholderProduct: "{product} \u0BAA\u0BB1\u0BCD\u0BB1\u0BBF\u0B95\u0BCD \u0B95\u0BC7\u0BB3\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD\u2026",
312
+ placeholder: "\u0BA8\u0BC0\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0B8E\u0BA4\u0BBF\u0BB0\u0BCD\u0B95\u0BCA\u0BB3\u0BCD\u0BB3\u0BC1\u0BAE\u0BCD \u0B9A\u0BBF\u0B95\u0BCD\u0B95\u0BB2\u0BC8 \u0BB5\u0BBF\u0BB5\u0BB0\u0BBF\u0BAF\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD\u2026",
313
+ 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",
314
314
  send: "\u0B85\u0BA9\u0BC1\u0BAA\u0BCD\u0BAA\u0BC1",
315
315
  stop: "\u0BA8\u0BBF\u0BB1\u0BC1\u0BA4\u0BCD\u0BA4\u0BC1",
316
316
  newChat: "\u0BAA\u0BC1\u0BA4\u0BBF\u0BAF \u0B89\u0BB0\u0BC8\u0BAF\u0BBE\u0B9F\u0BB2\u0BCD",
@@ -343,10 +343,10 @@ var TA = {
343
343
  "\u0BA8\u0BC7\u0BB0\u0BBE\u0B95 \u0B9A\u0BB0\u0BBF\u0BAF\u0BBE\u0BA9 \u0BAA\u0B95\u0BCD\u0B95\u0BA4\u0BCD\u0BA4\u0BBF\u0BB1\u0BCD\u0B95\u0BC1"
344
344
  ],
345
345
  prompts: [
346
- "\u0B87\u0BA8\u0BCD\u0BA4\u0BA4\u0BCD \u0BA4\u0BAF\u0BBE\u0BB0\u0BBF\u0BAA\u0BCD\u0BAA\u0BC1 \u0B89\u0BA3\u0BCD\u0BAE\u0BC8\u0BAF\u0BBF\u0BB2\u0BCD \u0B8E\u0BA9\u0BCD\u0BA9 \u0B9A\u0BC6\u0BAF\u0BCD\u0B95\u0BBF\u0BB1\u0BA4\u0BC1?",
347
- "\u0B8E\u0BA9\u0BCD \u0B95\u0BC1\u0BB4\u0BC1\u0BB5\u0BBF\u0BB1\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?",
348
- "\u0BAA\u0B9F\u0BBF\u0BAA\u0BCD\u0BAA\u0B9F\u0BBF\u0BAF\u0BBE\u0B95 \u0B8E\u0BAA\u0BCD\u0BAA\u0B9F\u0BBF\u0BA4\u0BCD \u0BA4\u0BCA\u0B9F\u0B99\u0BCD\u0B95\u0BC1\u0BB5\u0BA4\u0BC1?",
349
- "\u0B87\u0BA4\u0BA9\u0BCD \u0BB5\u0BBF\u0BB2\u0BC8 \u0B8E\u0BA9\u0BCD\u0BA9?"
346
+ "\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.",
347
+ "\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.",
348
+ "\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.",
349
+ "\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?"
350
350
  ]
351
351
  };
352
352
  var STRINGS = {
@@ -1207,13 +1207,13 @@ var FALLBACK_EXPLORE_LIMITS = {
1207
1207
  historyTurns: 6
1208
1208
  };
1209
1209
  var DEFAULT_EXPLORE_EXAMPLE_PROMPTS = [
1210
- "What does this product actually do?",
1211
- "Which Burdenoff product fits my team?",
1212
- "How do I get started, step by step?",
1213
- "What does it integrate with?"
1210
+ "Every course we run lives in a different spreadsheet.",
1211
+ "We only hear a machine is down after the line has stopped.",
1212
+ "Members quietly stop showing up and we never know why.",
1213
+ "Which of your products fits a problem like mine?"
1214
1214
  ];
1215
- var FALLBACK_WELCOME_TITLE = "Ask anything about our products";
1216
- var FALLBACK_WELCOME_BODY = "Get straight answers drawn from our product documentation and public pages \u2014 with links back to the exact page each answer came from.";
1215
+ var FALLBACK_WELCOME_TITLE = "What problem are you trying to solve?";
1216
+ var FALLBACK_WELCOME_BODY = "Describe the problem you're facing, in your own words. You can also ask about a specific product or compare a few. Every answer comes straight from our documentation.";
1217
1217
  function buildFallbackCatalog(examplePrompts, welcome) {
1218
1218
  return {
1219
1219
  enabled: true,
@@ -2518,6 +2518,7 @@ function toPayload(staged) {
2518
2518
  textContent
2519
2519
  }));
2520
2520
  }
2521
+ var SHORT_VIEWPORT_PX = 420;
2521
2522
  var EXPLORE_CSS = `
2522
2523
  @keyframes boff-explore-pulse {
2523
2524
  0%, 80%, 100% { opacity: 0.25; transform: translateY(0); }
@@ -2552,6 +2553,12 @@ var EXPLORE_CSS = `
2552
2553
  .boff-explore-scroll {
2553
2554
  scrollbar-width: thin;
2554
2555
  scrollbar-color: hsl(var(--border)) transparent;
2556
+ /* Stop the transcript handing its scroll to the page. Without this, the first
2557
+ swipe that exhausts the transcript chains to the document \u2014 and on a host site
2558
+ that is 65-70% footer, which is how a phone ends up showing nothing but the
2559
+ footer. Engines that do not support this property ignore the line and keep
2560
+ today's behaviour; the scroll correction above covers them. */
2561
+ overscroll-behavior: contain;
2555
2562
  }
2556
2563
  .boff-explore-scroll::-webkit-scrollbar { width: 10px; }
2557
2564
  .boff-explore-scroll::-webkit-scrollbar-track { background: transparent; }
@@ -2669,6 +2676,68 @@ var EXPLORE_CSS = `
2669
2676
  .boff-explore-busy::after { animation: none; }
2670
2677
  .boff-explore-rise { animation: none; opacity: 1; transform: none; }
2671
2678
  }
2679
+
2680
+ /* ---- Pane height ----------------------------------------------------------------------
2681
+ This used to be one inline declaration, \`height: calc(100dvh - 64px)\`, and it carried two
2682
+ defects. An inline style cannot carry a fallback, so every engine without \`dvh\` (iOS
2683
+ Safari < 15.4, Chrome/WebView < 108, Samsung Internet < 21, Firefox < 101) dropped it
2684
+ whole; and the 64px came from a prop hard-coded to 64 on all 41 host pages that matches
2685
+ none of them \u2014 the burdenoff/algoshred chrome is 80px, the sticky-header sites are 65.
2686
+
2687
+ A class plus custom properties lets the cascade do the work: \`vh\` is the floor and \`dvh\`
2688
+ an upgrade where it exists, while the two measured values stay *lengths*, never a height.
2689
+ That distinction is the whole prerender contract. The host sites snapshot \`/explore\` by
2690
+ loading the built SPA in headless Chromium and writing the POST-HYDRATION DOM to
2691
+ dist/explore/index.html, so every attribute and inline value this component sets after
2692
+ mount IS the static HTML CloudFront serves. A measured pixel *height* would therefore
2693
+ hand every phone the prerender viewport's height until the bundle executes; a measured
2694
+ *offset* is a site-header height, which is the same on every device to within a few
2695
+ pixels, and the height built from it stays viewport-relative on the visitor's own screen.
2696
+
2697
+ --boff-explore-offset chrome above the pane (measured root top; the prop pre-measure)
2698
+ --boff-explore-inset the slice of the layout viewport hidden below the visible area \u2014
2699
+ the on-screen keyboard, which \`dvh\` does not track. Zero unless
2700
+ something is actually covering the bottom, so a snapshot taken
2701
+ with no keyboard open never carries it. */
2702
+ .boff-explore-viewport {
2703
+ height: calc(100vh - var(--boff-explore-offset, 0px) - var(--boff-explore-inset, 0px));
2704
+ }
2705
+ @supports (height: 100dvh) {
2706
+ .boff-explore-viewport {
2707
+ height: calc(100dvh - var(--boff-explore-offset, 0px) - var(--boff-explore-inset, 0px));
2708
+ }
2709
+ }
2710
+
2711
+ /* Landscape phones and other short viewports: a one-screen pane leaves a ~124px transcript
2712
+ sliver under ~610px of chrome and content. At or below the threshold the pane stops
2713
+ pretending to be a window and lets the page's own scrolling carry the transcript. The
2714
+ min-height is the available height rather than a fixed rem value, so the fallback can
2715
+ never be taller than the screen it is rescuing. */
2716
+ @media (max-height: ${SHORT_VIEWPORT_PX}px) {
2717
+ .boff-explore-viewport {
2718
+ height: auto;
2719
+ min-height: calc(100vh - var(--boff-explore-offset, 0px));
2720
+ }
2721
+ }
2722
+ @supports (height: 100dvh) {
2723
+ @media (max-height: ${SHORT_VIEWPORT_PX}px) {
2724
+ .boff-explore-viewport {
2725
+ min-height: calc(100dvh - var(--boff-explore-offset, 0px));
2726
+ }
2727
+ }
2728
+ }
2729
+
2730
+ /* ---- Composer dock --------------------------------------------------------------------
2731
+ Three declarations, each the fallback for the one after it: a plain 1rem where \`max()\`
2732
+ is unknown, then the measured overlap of any FOREIGN fixed chrome sitting over the
2733
+ composer (the host sites' cookie banner is 229px tall and lands exactly there), then the
2734
+ same plus the home-indicator inset. \`--boff-explore-chrome\` is set on the root only once
2735
+ an overlap has actually been measured, so everywhere else this collapses to 1rem. */
2736
+ .boff-explore-composer {
2737
+ padding-bottom: 1rem;
2738
+ padding-bottom: max(1rem, var(--boff-explore-chrome, 0px));
2739
+ padding-bottom: max(1rem, env(safe-area-inset-bottom), var(--boff-explore-chrome, 0px));
2740
+ }
2672
2741
  `;
2673
2742
  function ExploreStyles() {
2674
2743
  return /* @__PURE__ */ jsxRuntime.jsx("style", { dangerouslySetInnerHTML: { __html: EXPLORE_CSS } });
@@ -2690,6 +2759,8 @@ var CAPABILITIES = [
2690
2759
  body: "Get the sources and next steps \u2014 pricing, docs, a demo \u2014 without hunting."
2691
2760
  }
2692
2761
  ];
2762
+ var MIN_VISIBLE_FRACTION = 0.25;
2763
+ var SDK_OVERLAY_SELECTOR = "[data-boff-explore]";
2693
2764
  var CTA_VARIANTS = {
2694
2765
  CONTACT: "default",
2695
2766
  WAITLIST: "default",
@@ -2705,6 +2776,28 @@ function normalizeOffset(offset) {
2705
2776
  if (offset === void 0) return "0px";
2706
2777
  return typeof offset === "number" ? `${offset}px` : offset;
2707
2778
  }
2779
+ function isOwnElement(el, root) {
2780
+ if (el === document.body || el === document.documentElement) return true;
2781
+ if (root.contains(el)) return true;
2782
+ return el.closest(SDK_OVERLAY_SELECTOR) !== null;
2783
+ }
2784
+ function visualViewportHeight() {
2785
+ return window.visualViewport?.height ?? window.innerHeight;
2786
+ }
2787
+ function clamp(value, min, max) {
2788
+ return Math.min(Math.max(value, min), max);
2789
+ }
2790
+ function isRestoredNavigation() {
2791
+ const entries = window.performance?.getEntriesByType?.("navigation");
2792
+ const entry = entries?.[0];
2793
+ if (!entry) return true;
2794
+ const navigation = entry;
2795
+ return navigation.type === "reload" || navigation.type === "back_forward";
2796
+ }
2797
+ function pageOwnsScrolling(el) {
2798
+ if (window.innerHeight > SHORT_VIEWPORT_PX) return false;
2799
+ return el.scrollHeight - el.clientHeight <= 1;
2800
+ }
2708
2801
  function isInternalPath(url) {
2709
2802
  return url.startsWith("/") && !url.startsWith("//");
2710
2803
  }
@@ -3553,6 +3646,8 @@ function ExplorePage({
3553
3646
  const pickQueueRef = React.useRef(Promise.resolve());
3554
3647
  const [shareLabel, setShareLabel] = React.useState(T.share);
3555
3648
  const [shareUrl, setShareUrl] = React.useState(null);
3649
+ const rootRef = React.useRef(null);
3650
+ const composerRef = React.useRef(null);
3556
3651
  const scrollRef = React.useRef(null);
3557
3652
  const latestAssistantRef = React.useRef(null);
3558
3653
  const alignedForRef = React.useRef(null);
@@ -3580,11 +3675,196 @@ function ExplorePage({
3580
3675
  el.style.height = "auto";
3581
3676
  el.style.height = `${Math.min(el.scrollHeight, 200)}px`;
3582
3677
  }, [draft]);
3678
+ const [paneOffset, setPaneOffset] = React.useState(null);
3679
+ const [bottomInset, setBottomInset] = React.useState(0);
3680
+ const paneOffsetRef = React.useRef(0);
3681
+ const measurePane = React.useCallback(() => {
3682
+ if (heightMode !== "viewport") return;
3683
+ const el = rootRef.current;
3684
+ if (!el) return;
3685
+ const layoutHeight = window.innerHeight;
3686
+ if (layoutHeight === 0) return;
3687
+ const top = Math.round(
3688
+ clamp(el.getBoundingClientRect().top, 0, layoutHeight)
3689
+ );
3690
+ const viewport = window.visualViewport;
3691
+ const inset = viewport ? Math.round(
3692
+ clamp(
3693
+ layoutHeight - viewport.height - viewport.offsetTop,
3694
+ 0,
3695
+ layoutHeight
3696
+ )
3697
+ ) : 0;
3698
+ paneOffsetRef.current = top;
3699
+ setPaneOffset((current) => current === top ? current : top);
3700
+ setBottomInset((current) => current === inset ? current : inset);
3701
+ }, [heightMode]);
3702
+ const [chromeOverlap, setChromeOverlap] = React.useState(0);
3703
+ const measureChrome = React.useCallback(() => {
3704
+ const root = rootRef.current;
3705
+ const dock = composerRef.current;
3706
+ if (!root || !dock) return;
3707
+ if (typeof document.elementFromPoint !== "function") return;
3708
+ const viewportHeight = visualViewportHeight();
3709
+ const rect = dock.getBoundingClientRect();
3710
+ if (rect.width === 0 || viewportHeight === 0) return;
3711
+ if (rect.bottom <= 0 || rect.top >= viewportHeight) return;
3712
+ const edge = Math.min(rect.bottom, viewportHeight);
3713
+ const hit = document.elementFromPoint(rect.left + rect.width / 2, edge - 1);
3714
+ if (!hit || isOwnElement(hit, root)) {
3715
+ setChromeOverlap(0);
3716
+ return;
3717
+ }
3718
+ const overlap = Math.round(edge - hit.getBoundingClientRect().top);
3719
+ setChromeOverlap(overlap > 0 && overlap < viewportHeight ? overlap : 0);
3720
+ }, []);
3721
+ const remeasure = React.useCallback(() => {
3722
+ measurePane();
3723
+ measureChrome();
3724
+ }, [measurePane, measureChrome]);
3725
+ React.useEffect(() => {
3726
+ if (typeof window === "undefined") return;
3727
+ let frame = 0;
3728
+ const run = () => {
3729
+ frame = 0;
3730
+ remeasure();
3731
+ };
3732
+ const schedule = () => {
3733
+ if (frame) return;
3734
+ if (typeof window.requestAnimationFrame !== "function") {
3735
+ remeasure();
3736
+ return;
3737
+ }
3738
+ frame = window.requestAnimationFrame(run);
3739
+ };
3740
+ remeasure();
3741
+ const viewport = window.visualViewport;
3742
+ window.addEventListener("resize", schedule);
3743
+ window.addEventListener("orientationchange", schedule);
3744
+ viewport?.addEventListener("resize", schedule);
3745
+ viewport?.addEventListener("scroll", schedule);
3746
+ const observer = typeof MutationObserver === "function" ? new MutationObserver((records) => {
3747
+ const el = rootRef.current;
3748
+ if (el && records.every((record) => el.contains(record.target)))
3749
+ return;
3750
+ schedule();
3751
+ }) : null;
3752
+ observer?.observe(document.body, { childList: true, subtree: true });
3753
+ return () => {
3754
+ if (frame) window.cancelAnimationFrame(frame);
3755
+ window.removeEventListener("resize", schedule);
3756
+ window.removeEventListener("orientationchange", schedule);
3757
+ viewport?.removeEventListener("resize", schedule);
3758
+ viewport?.removeEventListener("scroll", schedule);
3759
+ observer?.disconnect();
3760
+ setPaneOffset(null);
3761
+ setBottomInset(0);
3762
+ setChromeOverlap(0);
3763
+ };
3764
+ }, [remeasure]);
3765
+ React.useEffect(() => {
3766
+ measureChrome();
3767
+ }, [measureChrome, paneOffset, bottomInset]);
3768
+ React.useEffect(() => {
3769
+ if (heightMode !== "viewport" || typeof window === "undefined") return;
3770
+ const { history: browserHistory } = window;
3771
+ const previousRestoration = "scrollRestoration" in browserHistory ? browserHistory.scrollRestoration : null;
3772
+ if (previousRestoration !== null)
3773
+ browserHistory.scrollRestoration = "manual";
3774
+ let frame = 0;
3775
+ let visitorMoved = false;
3776
+ const onVisitorMove = () => {
3777
+ visitorMoved = true;
3778
+ };
3779
+ const align = () => {
3780
+ if (visitorMoved) return;
3781
+ const el = rootRef.current;
3782
+ if (!el) return;
3783
+ const viewportHeight = visualViewportHeight();
3784
+ const rect = el.getBoundingClientRect();
3785
+ if (rect.height === 0 || viewportHeight === 0) return;
3786
+ const visible = Math.min(rect.bottom, viewportHeight) - Math.max(rect.top, 0);
3787
+ const reachable = Math.min(rect.height, viewportHeight);
3788
+ if (visible >= reachable * MIN_VISIBLE_FRACTION) return;
3789
+ window.scrollTo({
3790
+ top: Math.max(0, window.scrollY + rect.top),
3791
+ left: window.scrollX,
3792
+ behavior: "auto"
3793
+ });
3794
+ if (typeof document.elementFromPoint === "function") {
3795
+ const probe = document.elementFromPoint(
3796
+ Math.max(0, rect.left + rect.width / 2),
3797
+ 1
3798
+ );
3799
+ if (probe && !isOwnElement(probe, el)) {
3800
+ const chrome = probe.getBoundingClientRect().bottom;
3801
+ if (chrome > 0 && chrome < viewportHeight / 2) {
3802
+ window.scrollBy({ top: -chrome, left: 0, behavior: "auto" });
3803
+ }
3804
+ }
3805
+ }
3806
+ remeasure();
3807
+ };
3808
+ const alignIfRestored = () => {
3809
+ if (!isRestoredNavigation()) return;
3810
+ align();
3811
+ };
3812
+ alignIfRestored();
3813
+ if (typeof window.requestAnimationFrame === "function") {
3814
+ frame = window.requestAnimationFrame(alignIfRestored);
3815
+ }
3816
+ const onPageShow = (event) => {
3817
+ if (!event.persisted) {
3818
+ alignIfRestored();
3819
+ return;
3820
+ }
3821
+ visitorMoved = false;
3822
+ align();
3823
+ };
3824
+ window.addEventListener("pageshow", onPageShow);
3825
+ window.addEventListener("wheel", onVisitorMove, { passive: true });
3826
+ window.addEventListener("touchmove", onVisitorMove, { passive: true });
3827
+ window.addEventListener("keydown", onVisitorMove, { passive: true });
3828
+ return () => {
3829
+ if (frame) window.cancelAnimationFrame(frame);
3830
+ window.removeEventListener("pageshow", onPageShow);
3831
+ window.removeEventListener("wheel", onVisitorMove);
3832
+ window.removeEventListener("touchmove", onVisitorMove);
3833
+ window.removeEventListener("keydown", onVisitorMove);
3834
+ if (previousRestoration !== null)
3835
+ browserHistory.scrollRestoration = previousRestoration;
3836
+ };
3837
+ }, [heightMode, remeasure]);
3583
3838
  const handleScroll = React.useCallback(() => {
3584
3839
  const el = scrollRef.current;
3585
3840
  if (!el) return;
3586
3841
  stickToBottomRef.current = el.scrollHeight - el.scrollTop - el.clientHeight < 80;
3587
3842
  }, []);
3843
+ React.useEffect(() => {
3844
+ if (typeof window === "undefined") return;
3845
+ let frame = 0;
3846
+ const run = () => {
3847
+ frame = 0;
3848
+ const el = scrollRef.current;
3849
+ const dock = composerRef.current;
3850
+ if (!el || !dock) return;
3851
+ if (!pageOwnsScrolling(el)) return;
3852
+ stickToBottomRef.current = dock.getBoundingClientRect().bottom - visualViewportHeight() < 80;
3853
+ };
3854
+ const schedule = () => {
3855
+ if (frame) return;
3856
+ if (typeof window.requestAnimationFrame !== "function") {
3857
+ run();
3858
+ return;
3859
+ }
3860
+ frame = window.requestAnimationFrame(run);
3861
+ };
3862
+ window.addEventListener("scroll", schedule, { passive: true });
3863
+ return () => {
3864
+ if (frame) window.cancelAnimationFrame(frame);
3865
+ window.removeEventListener("scroll", schedule);
3866
+ };
3867
+ }, []);
3588
3868
  const latestAssistantId = React.useMemo(() => {
3589
3869
  for (let i = messages.length - 1; i >= 0; i -= 1) {
3590
3870
  const message = messages[i];
@@ -3600,16 +3880,32 @@ function ExplorePage({
3600
3880
  if (!stickToBottomRef.current) return;
3601
3881
  if (anchor.offsetHeight === 0) return;
3602
3882
  alignedForRef.current = latestAssistantId;
3603
- const delta = anchor.getBoundingClientRect().top - el.getBoundingClientRect().top;
3604
- el.scrollTop = Math.max(0, el.scrollTop + delta - 12);
3883
+ if (!pageOwnsScrolling(el)) {
3884
+ const delta2 = anchor.getBoundingClientRect().top - el.getBoundingClientRect().top;
3885
+ el.scrollTop = Math.max(0, el.scrollTop + delta2 - 12);
3886
+ return;
3887
+ }
3888
+ const delta = Math.round(
3889
+ anchor.getBoundingClientRect().top - paneOffsetRef.current - 12
3890
+ );
3891
+ if (delta !== 0) window.scrollBy({ top: delta, left: 0, behavior: "auto" });
3605
3892
  }, [latestAssistantId, messages]);
3606
3893
  React.useEffect(() => {
3894
+ if (messages.length === 0) return;
3607
3895
  if (!stickToBottomRef.current) return;
3608
3896
  if (latestAssistantId && alignedForRef.current === latestAssistantId)
3609
3897
  return;
3610
3898
  const el = scrollRef.current;
3611
3899
  if (!el) return;
3612
- el.scrollTop = el.scrollHeight;
3900
+ if (!pageOwnsScrolling(el)) {
3901
+ el.scrollTop = el.scrollHeight;
3902
+ return;
3903
+ }
3904
+ const dock = composerRef.current ?? el;
3905
+ const delta = Math.round(
3906
+ dock.getBoundingClientRect().bottom - visualViewportHeight()
3907
+ );
3908
+ if (delta > 0) window.scrollBy({ top: delta, left: 0, behavior: "auto" });
3613
3909
  }, [activity, latestAssistantId, messages]);
3614
3910
  const handleShare = React.useCallback(async () => {
3615
3911
  setShareLabel(T.copying);
@@ -3707,16 +4003,27 @@ function ExplorePage({
3707
4003
  const captchaOn = Boolean(
3708
4004
  catalog.captchaRequired && catalog.recaptchaSiteKey
3709
4005
  );
3710
- const rootStyle = heightMode === "viewport" ? { height: `calc(100dvh - ${normalizeOffset(viewportOffset)})` } : void 0;
4006
+ const rootStyle = {};
4007
+ if (heightMode === "viewport") {
4008
+ rootStyle["--boff-explore-offset"] = paneOffset === null ? normalizeOffset(viewportOffset) : `${paneOffset}px`;
4009
+ if (bottomInset > 0) {
4010
+ rootStyle["--boff-explore-inset"] = `${bottomInset}px`;
4011
+ }
4012
+ }
4013
+ if (chromeOverlap > 0) {
4014
+ rootStyle["--boff-explore-chrome"] = `${chromeOverlap}px`;
4015
+ }
3711
4016
  return /* @__PURE__ */ jsxRuntime.jsxs(
3712
4017
  "div",
3713
4018
  {
4019
+ ref: rootRef,
3714
4020
  "data-boff-explore": "page",
3715
4021
  "data-phase": phase,
3716
4022
  "data-locale": activeLocale,
3717
4023
  dir: rtl ? "rtl" : void 0,
3718
4024
  className: cn(
3719
4025
  "flex w-full min-w-0 flex-col overflow-x-hidden bg-background text-foreground",
4026
+ heightMode === "viewport" && "boff-explore-viewport",
3720
4027
  heightMode === "auto" && "min-h-[70vh]",
3721
4028
  className
3722
4029
  ),
@@ -3950,249 +4257,257 @@ function ExplorePage({
3950
4257
  ]
3951
4258
  }
3952
4259
  ) : null,
3953
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-border bg-background/85 px-4 pb-[max(1rem,env(safe-area-inset-bottom))] pt-3 backdrop-blur-md", children: /* @__PURE__ */ jsxRuntime.jsxs(
3954
- "form",
4260
+ /* @__PURE__ */ jsxRuntime.jsx(
4261
+ "div",
3955
4262
  {
3956
- "data-boff-explore": "composer",
3957
- className: "mx-auto w-full max-w-3xl",
3958
- onSubmit: (event) => {
3959
- event.preventDefault();
3960
- submitDraft();
3961
- },
3962
- children: [
3963
- error ? /* @__PURE__ */ jsxRuntime.jsx(ErrorBanner, { error, onRetry: retry, onReset: reset }) : null,
3964
- staged.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
3965
- "ul",
3966
- {
3967
- "data-boff-explore": "attachments",
3968
- className: "mb-2 flex flex-wrap gap-1.5",
3969
- "aria-label": T.attach,
3970
- children: staged.map((entry) => /* @__PURE__ */ jsxRuntime.jsxs(
3971
- "li",
4263
+ ref: composerRef,
4264
+ "data-boff-explore": "composer-dock",
4265
+ className: "boff-explore-composer border-t border-border bg-background/85 px-4 pt-3 backdrop-blur-md",
4266
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
4267
+ "form",
4268
+ {
4269
+ "data-boff-explore": "composer",
4270
+ className: "mx-auto w-full max-w-3xl",
4271
+ onSubmit: (event) => {
4272
+ event.preventDefault();
4273
+ submitDraft();
4274
+ },
4275
+ children: [
4276
+ error ? /* @__PURE__ */ jsxRuntime.jsx(ErrorBanner, { error, onRetry: retry, onReset: reset }) : null,
4277
+ staged.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
4278
+ "ul",
4279
+ {
4280
+ "data-boff-explore": "attachments",
4281
+ className: "mb-2 flex flex-wrap gap-1.5",
4282
+ "aria-label": T.attach,
4283
+ children: staged.map((entry) => /* @__PURE__ */ jsxRuntime.jsxs(
4284
+ "li",
4285
+ {
4286
+ "data-boff-explore": "attachment",
4287
+ "data-text-extracted": entry.textExtracted ? "true" : "false",
4288
+ className: "flex max-w-full items-center gap-1.5 rounded-full border border-border bg-muted/60 py-1 pl-2.5 pr-1 text-xs",
4289
+ children: [
4290
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Paperclip, { className: "h-3 w-3 shrink-0 text-muted-foreground" }),
4291
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium", title: entry.name, children: entry.name }),
4292
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "shrink-0 text-muted-foreground", children: [
4293
+ formatBytes(entry.size),
4294
+ entry.textExtracted ? "" : ` \xB7 ${T.attachmentNameOnly}`
4295
+ ] }),
4296
+ /* @__PURE__ */ jsxRuntime.jsx(
4297
+ "button",
4298
+ {
4299
+ type: "button",
4300
+ "data-boff-explore": "attachment-remove",
4301
+ onClick: () => removeAttachment(entry.id),
4302
+ "aria-label": fill(T.removeAttachment, { name: entry.name }),
4303
+ className: "ml-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-background hover:text-foreground",
4304
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-3 w-3" })
4305
+ }
4306
+ )
4307
+ ]
4308
+ },
4309
+ entry.id
4310
+ ))
4311
+ }
4312
+ ) : null,
4313
+ attachmentNotice !== null ? /* @__PURE__ */ jsxRuntime.jsx(
4314
+ "p",
3972
4315
  {
3973
- "data-boff-explore": "attachment",
3974
- "data-text-extracted": entry.textExtracted ? "true" : "false",
3975
- className: "flex max-w-full items-center gap-1.5 rounded-full border border-border bg-muted/60 py-1 pl-2.5 pr-1 text-xs",
4316
+ "data-boff-explore": "attachment-notice",
4317
+ role: "status",
4318
+ className: "mb-2 text-xs text-destructive",
4319
+ children: attachmentNotice
4320
+ }
4321
+ ) : null,
4322
+ /* @__PURE__ */ jsxRuntime.jsxs(
4323
+ "div",
4324
+ {
4325
+ className: cn(
4326
+ "flex min-w-0 items-end gap-2 rounded-2xl border bg-card p-2 shadow-sm transition-all",
4327
+ busy && "boff-explore-busy",
4328
+ overLimit ? "border-destructive/60" : "border-border focus-within:border-primary/40 focus-within:ring-1 focus-within:ring-ring"
4329
+ ),
3976
4330
  children: [
3977
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Paperclip, { className: "h-3 w-3 shrink-0 text-muted-foreground" }),
3978
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium", title: entry.name, children: entry.name }),
3979
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "shrink-0 text-muted-foreground", children: [
3980
- formatBytes(entry.size),
3981
- entry.textExtracted ? "" : ` \xB7 ${T.attachmentNameOnly}`
3982
- ] }),
3983
4331
  /* @__PURE__ */ jsxRuntime.jsx(
3984
- "button",
4332
+ Textarea,
4333
+ {
4334
+ ref: textareaRef,
4335
+ value: draft,
4336
+ rows: 1,
4337
+ disabled: composerDisabled,
4338
+ onChange: (event) => setDraft(event.target.value),
4339
+ onKeyDown: handleKeyDown,
4340
+ onCompositionStart: () => {
4341
+ composingRef.current = true;
4342
+ },
4343
+ onCompositionEnd: () => {
4344
+ composingRef.current = false;
4345
+ },
4346
+ "aria-label": "Ask a question",
4347
+ placeholder: composerDisabled ? phase === "limited" ? "Message limit reached \u2014 please try again later" : "Explore is unavailable right now" : focusedProductName ? fill(T.placeholderProduct, {
4348
+ product: focusedProductName
4349
+ }) : T.placeholder,
4350
+ 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"
4351
+ }
4352
+ ),
4353
+ /* @__PURE__ */ jsxRuntime.jsx(
4354
+ "input",
4355
+ {
4356
+ ref: fileInputRef,
4357
+ type: "file",
4358
+ multiple: true,
4359
+ className: "hidden",
4360
+ onChange: (event) => {
4361
+ void handleFilesPicked(event.target.files);
4362
+ event.target.value = "";
4363
+ }
4364
+ }
4365
+ ),
4366
+ /* @__PURE__ */ jsxRuntime.jsx(
4367
+ Button,
4368
+ {
4369
+ "data-boff-explore": "attach",
4370
+ type: "button",
4371
+ size: "icon",
4372
+ variant: "ghost",
4373
+ disabled: composerDisabled || staged.length >= MAX_ATTACHMENTS,
4374
+ "aria-label": T.attach,
4375
+ title: `${T.attach} \u2014 ${fill(T.attachHint, {
4376
+ max: String(MAX_ATTACHMENTS),
4377
+ size: String(MAX_ATTACHMENT_BYTES / (1024 * 1024))
4378
+ })}`,
4379
+ onClick: () => fileInputRef.current?.click(),
4380
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Paperclip, { className: "h-4 w-4" })
4381
+ }
4382
+ ),
4383
+ speech.supported ? /* @__PURE__ */ jsxRuntime.jsx(
4384
+ Button,
4385
+ {
4386
+ "data-boff-explore": "mic",
4387
+ "data-listening": speech.listening ? "true" : "false",
4388
+ type: "button",
4389
+ size: "icon",
4390
+ variant: speech.listening ? "default" : "ghost",
4391
+ disabled: composerDisabled,
4392
+ "aria-label": speech.listening ? T.stopDictating : T.dictate,
4393
+ "aria-pressed": speech.listening,
4394
+ title: speech.listening ? T.stopDictating : T.dictate,
4395
+ onClick: speech.toggle,
4396
+ className: cn(speech.listening && "animate-pulse"),
4397
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Mic, { className: "h-4 w-4" })
4398
+ }
4399
+ ) : null,
4400
+ busy ? /* @__PURE__ */ jsxRuntime.jsx(
4401
+ Button,
3985
4402
  {
4403
+ "data-boff-explore": "stop",
3986
4404
  type: "button",
3987
- "data-boff-explore": "attachment-remove",
3988
- onClick: () => removeAttachment(entry.id),
3989
- "aria-label": fill(T.removeAttachment, { name: entry.name }),
3990
- className: "ml-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-background hover:text-foreground",
3991
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-3 w-3" })
4405
+ size: "icon",
4406
+ variant: "secondary",
4407
+ "aria-label": T.stop,
4408
+ onClick: stop,
4409
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Square, { className: "h-4 w-4" })
4410
+ }
4411
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
4412
+ Button,
4413
+ {
4414
+ "data-boff-explore": "send",
4415
+ type: "submit",
4416
+ size: "icon",
4417
+ disabled: !canSubmit,
4418
+ "aria-label": T.send,
4419
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { className: "h-4 w-4" })
3992
4420
  }
3993
4421
  )
3994
4422
  ]
3995
- },
3996
- entry.id
3997
- ))
3998
- }
3999
- ) : null,
4000
- attachmentNotice !== null ? /* @__PURE__ */ jsxRuntime.jsx(
4001
- "p",
4002
- {
4003
- "data-boff-explore": "attachment-notice",
4004
- role: "status",
4005
- className: "mb-2 text-xs text-destructive",
4006
- children: attachmentNotice
4007
- }
4008
- ) : null,
4009
- /* @__PURE__ */ jsxRuntime.jsxs(
4010
- "div",
4011
- {
4012
- className: cn(
4013
- "flex min-w-0 items-end gap-2 rounded-2xl border bg-card p-2 shadow-sm transition-all",
4014
- busy && "boff-explore-busy",
4015
- overLimit ? "border-destructive/60" : "border-border focus-within:border-primary/40 focus-within:ring-1 focus-within:ring-ring"
4423
+ }
4016
4424
  ),
4017
- children: [
4018
- /* @__PURE__ */ jsxRuntime.jsx(
4019
- Textarea,
4425
+ speech.listening || speech.interim !== "" ? /* @__PURE__ */ jsxRuntime.jsxs(
4426
+ "p",
4427
+ {
4428
+ "data-boff-explore": "dictation",
4429
+ className: "mt-2 flex items-center gap-2 text-xs text-muted-foreground",
4430
+ "aria-live": "polite",
4431
+ children: [
4432
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative flex h-2 w-2 shrink-0", children: [
4433
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute inline-flex h-full w-full animate-ping rounded-full bg-primary opacity-75" }),
4434
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "relative inline-flex h-2 w-2 rounded-full bg-primary" })
4435
+ ] }),
4436
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "italic", children: speech.interim !== "" ? speech.interim : "Listening\u2026" })
4437
+ ]
4438
+ }
4439
+ ) : null,
4440
+ speech.error !== null ? /* @__PURE__ */ jsxRuntime.jsx(
4441
+ "p",
4442
+ {
4443
+ "data-boff-explore": "dictation-error",
4444
+ className: "mt-2 text-xs text-destructive",
4445
+ children: speech.error
4446
+ }
4447
+ ) : null,
4448
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [
4449
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children: "Enter to send \xB7 Shift + Enter for a new line" }),
4450
+ remainingToday !== null ? /* @__PURE__ */ jsxRuntime.jsxs("span", { "data-boff-explore": "remaining", children: [
4451
+ remainingToday,
4452
+ " message",
4453
+ remainingToday === 1 ? "" : "s",
4454
+ " left today"
4455
+ ] }) : null,
4456
+ /* @__PURE__ */ jsxRuntime.jsxs(
4457
+ "span",
4020
4458
  {
4021
- ref: textareaRef,
4022
- value: draft,
4023
- rows: 1,
4024
- disabled: composerDisabled,
4025
- onChange: (event) => setDraft(event.target.value),
4026
- onKeyDown: handleKeyDown,
4027
- onCompositionStart: () => {
4028
- composingRef.current = true;
4029
- },
4030
- onCompositionEnd: () => {
4031
- composingRef.current = false;
4032
- },
4033
- "aria-label": "Ask a question",
4034
- placeholder: composerDisabled ? phase === "limited" ? "Message limit reached \u2014 please try again later" : "Explore is unavailable right now" : focusedProductName ? fill(T.placeholderProduct, {
4035
- product: focusedProductName
4036
- }) : T.placeholder,
4037
- 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"
4459
+ className: cn(
4460
+ "ml-auto tabular-nums",
4461
+ overLimit && "font-medium text-destructive"
4462
+ ),
4463
+ children: [
4464
+ draft.length.toLocaleString(),
4465
+ " / ",
4466
+ maxLength.toLocaleString()
4467
+ ]
4038
4468
  }
4039
- ),
4469
+ )
4470
+ ] }),
4471
+ shareUrl ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 flex items-center gap-2", children: [
4040
4472
  /* @__PURE__ */ jsxRuntime.jsx(
4041
4473
  "input",
4042
4474
  {
4043
- ref: fileInputRef,
4044
- type: "file",
4045
- multiple: true,
4046
- className: "hidden",
4047
- onChange: (event) => {
4048
- void handleFilesPicked(event.target.files);
4049
- event.target.value = "";
4050
- }
4475
+ "data-boff-explore": "share-url",
4476
+ readOnly: true,
4477
+ value: shareUrl,
4478
+ "aria-label": "Read-only link to this conversation",
4479
+ onFocus: (event) => event.currentTarget.select(),
4480
+ className: "min-w-0 flex-1 rounded-md border border-border bg-muted px-2 py-1 text-xs text-muted-foreground"
4051
4481
  }
4052
4482
  ),
4053
4483
  /* @__PURE__ */ jsxRuntime.jsx(
4054
- Button,
4055
- {
4056
- "data-boff-explore": "attach",
4057
- type: "button",
4058
- size: "icon",
4059
- variant: "ghost",
4060
- disabled: composerDisabled || staged.length >= MAX_ATTACHMENTS,
4061
- "aria-label": T.attach,
4062
- title: `${T.attach} \u2014 ${fill(T.attachHint, {
4063
- max: String(MAX_ATTACHMENTS),
4064
- size: String(MAX_ATTACHMENT_BYTES / (1024 * 1024))
4065
- })}`,
4066
- onClick: () => fileInputRef.current?.click(),
4067
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Paperclip, { className: "h-4 w-4" })
4068
- }
4069
- ),
4070
- speech.supported ? /* @__PURE__ */ jsxRuntime.jsx(
4071
- Button,
4484
+ "button",
4072
4485
  {
4073
- "data-boff-explore": "mic",
4074
- "data-listening": speech.listening ? "true" : "false",
4075
4486
  type: "button",
4076
- size: "icon",
4077
- variant: speech.listening ? "default" : "ghost",
4078
- disabled: composerDisabled,
4079
- "aria-label": speech.listening ? T.stopDictating : T.dictate,
4080
- "aria-pressed": speech.listening,
4081
- title: speech.listening ? T.stopDictating : T.dictate,
4082
- onClick: speech.toggle,
4083
- className: cn(speech.listening && "animate-pulse"),
4084
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Mic, { className: "h-4 w-4" })
4487
+ className: "shrink-0 text-xs underline underline-offset-2",
4488
+ onClick: () => setShareUrl(null),
4489
+ children: "Done"
4085
4490
  }
4086
- ) : null,
4087
- busy ? /* @__PURE__ */ jsxRuntime.jsx(
4088
- Button,
4491
+ )
4492
+ ] }) : null,
4493
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [
4494
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: T.disclaimerShort }),
4495
+ /* @__PURE__ */ jsxRuntime.jsx(
4496
+ "button",
4089
4497
  {
4090
- "data-boff-explore": "stop",
4091
4498
  type: "button",
4092
- size: "icon",
4093
- variant: "secondary",
4094
- "aria-label": T.stop,
4095
- onClick: stop,
4096
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Square, { className: "h-4 w-4" })
4097
- }
4098
- ) : /* @__PURE__ */ jsxRuntime.jsx(
4099
- Button,
4100
- {
4101
- "data-boff-explore": "send",
4102
- type: "submit",
4103
- size: "icon",
4104
- disabled: !canSubmit,
4105
- "aria-label": T.send,
4106
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { className: "h-4 w-4" })
4499
+ "data-boff-explore": "disclaimer",
4500
+ onClick: () => setDisclaimerOpen(true),
4501
+ className: "shrink-0 underline underline-offset-2 transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
4502
+ children: T.disclaimer
4107
4503
  }
4108
4504
  )
4109
- ]
4110
- }
4111
- ),
4112
- speech.listening || speech.interim !== "" ? /* @__PURE__ */ jsxRuntime.jsxs(
4113
- "p",
4114
- {
4115
- "data-boff-explore": "dictation",
4116
- className: "mt-2 flex items-center gap-2 text-xs text-muted-foreground",
4117
- "aria-live": "polite",
4118
- children: [
4119
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative flex h-2 w-2 shrink-0", children: [
4120
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute inline-flex h-full w-full animate-ping rounded-full bg-primary opacity-75" }),
4121
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "relative inline-flex h-2 w-2 rounded-full bg-primary" })
4122
- ] }),
4123
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "italic", children: speech.interim !== "" ? speech.interim : "Listening\u2026" })
4124
- ]
4125
- }
4126
- ) : null,
4127
- speech.error !== null ? /* @__PURE__ */ jsxRuntime.jsx(
4128
- "p",
4129
- {
4130
- "data-boff-explore": "dictation-error",
4131
- className: "mt-2 text-xs text-destructive",
4132
- children: speech.error
4133
- }
4134
- ) : null,
4135
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [
4136
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children: "Enter to send \xB7 Shift + Enter for a new line" }),
4137
- remainingToday !== null ? /* @__PURE__ */ jsxRuntime.jsxs("span", { "data-boff-explore": "remaining", children: [
4138
- remainingToday,
4139
- " message",
4140
- remainingToday === 1 ? "" : "s",
4141
- " left today"
4142
- ] }) : null,
4143
- /* @__PURE__ */ jsxRuntime.jsxs(
4144
- "span",
4145
- {
4146
- className: cn(
4147
- "ml-auto tabular-nums",
4148
- overLimit && "font-medium text-destructive"
4149
- ),
4150
- children: [
4151
- draft.length.toLocaleString(),
4152
- " / ",
4153
- maxLength.toLocaleString()
4154
- ]
4155
- }
4156
- )
4157
- ] }),
4158
- shareUrl ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 flex items-center gap-2", children: [
4159
- /* @__PURE__ */ jsxRuntime.jsx(
4160
- "input",
4161
- {
4162
- "data-boff-explore": "share-url",
4163
- readOnly: true,
4164
- value: shareUrl,
4165
- "aria-label": "Read-only link to this conversation",
4166
- onFocus: (event) => event.currentTarget.select(),
4167
- className: "min-w-0 flex-1 rounded-md border border-border bg-muted px-2 py-1 text-xs text-muted-foreground"
4168
- }
4169
- ),
4170
- /* @__PURE__ */ jsxRuntime.jsx(
4171
- "button",
4172
- {
4173
- type: "button",
4174
- className: "shrink-0 text-xs underline underline-offset-2",
4175
- onClick: () => setShareUrl(null),
4176
- children: "Done"
4177
- }
4178
- )
4179
- ] }) : null,
4180
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [
4181
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: T.disclaimerShort }),
4182
- /* @__PURE__ */ jsxRuntime.jsx(
4183
- "button",
4184
- {
4185
- type: "button",
4186
- "data-boff-explore": "disclaimer",
4187
- onClick: () => setDisclaimerOpen(true),
4188
- className: "shrink-0 underline underline-offset-2 transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
4189
- children: T.disclaimer
4190
- }
4191
- )
4192
- ] })
4193
- ]
4505
+ ] })
4506
+ ]
4507
+ }
4508
+ )
4194
4509
  }
4195
- ) })
4510
+ )
4196
4511
  ]
4197
4512
  }
4198
4513
  );