@burdenoff/website-sdk 2026.924.10 → 2026.924.12

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.
@@ -2033,6 +2033,45 @@ function buildFallbackCatalog(examplePrompts, welcome) {
2033
2033
  conceptHighlights: []
2034
2034
  };
2035
2035
  }
2036
+ var BAKED_CATALOG_ELEMENT_ID = "boff-explore-catalog";
2037
+ function bakedCatalogLocale() {
2038
+ if (typeof navigator === "undefined") return "";
2039
+ return (navigator.language || "").toLowerCase().split("-")[0] ?? "";
2040
+ }
2041
+ function snapshotBakedElement() {
2042
+ if (typeof document === "undefined") return null;
2043
+ const el = document.getElementById(BAKED_CATALOG_ELEMENT_ID);
2044
+ if (!el || el.tagName !== "SCRIPT" || el.getAttribute("type") !== "application/json")
2045
+ return null;
2046
+ return {
2047
+ product: el.getAttribute("data-product") ?? "",
2048
+ locale: el.getAttribute("data-locale") ?? "",
2049
+ text: el.textContent ?? ""
2050
+ };
2051
+ }
2052
+ var BAKED_AT_LOAD = snapshotBakedElement();
2053
+ function isCatalogShape(value) {
2054
+ if (!value || typeof value !== "object") return false;
2055
+ const c = value;
2056
+ const listOrAbsent = (v) => v === void 0 || v === null || Array.isArray(v);
2057
+ const textOrAbsent = (v) => v === void 0 || v === null || typeof v === "string";
2058
+ return (c["enabled"] === void 0 || typeof c["enabled"] === "boolean") && listOrAbsent(c["products"]) && listOrAbsent(c["examplePrompts"]) && listOrAbsent(c["conceptHighlights"]) && textOrAbsent(c["welcomeTitle"]) && textOrAbsent(c["welcomeBody"]);
2059
+ }
2060
+ function readBakedCatalog(productSlug) {
2061
+ const baked = snapshotBakedElement() ?? BAKED_AT_LOAD;
2062
+ if (!baked) return null;
2063
+ if (baked.product !== (productSlug ?? "")) return null;
2064
+ if (baked.locale && baked.locale !== bakedCatalogLocale()) return null;
2065
+ try {
2066
+ const parsed = JSON.parse(baked.text);
2067
+ return isCatalogShape(parsed) ? parsed : null;
2068
+ } catch {
2069
+ return null;
2070
+ }
2071
+ }
2072
+ function serializeBakedCatalog(raw) {
2073
+ return JSON.stringify(raw).replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
2074
+ }
2036
2075
  function normalizeCatalog(raw, fallback) {
2037
2076
  return {
2038
2077
  enabled: raw.enabled !== false,
@@ -2282,9 +2321,17 @@ function useExploreChat(options = {}) {
2282
2321
  ),
2283
2322
  [promptKey, welcomeKey]
2284
2323
  );
2285
- const [catalog, setCatalog] = useState(fallbackCatalog);
2324
+ const [bakedRaw] = useState(
2325
+ () => readBakedCatalog(productSlug)
2326
+ );
2327
+ const [catalog, setCatalog] = useState(
2328
+ () => bakedRaw ? normalizeCatalog(bakedRaw, fallbackCatalog) : fallbackCatalog
2329
+ );
2330
+ const [serverCatalogRaw, setServerCatalogRaw] = useState(bakedRaw);
2286
2331
  const [messages, setMessages] = useState([]);
2287
- const [phase, setPhase] = useState("loading");
2332
+ const [phase, setPhase] = useState(
2333
+ () => bakedRaw ? bakedRaw.enabled === false ? "disabled" : "ready" : "loading"
2334
+ );
2288
2335
  const [error, setError] = useState(null);
2289
2336
  const [remainingToday, setRemainingToday] = useState(null);
2290
2337
  const [focusProduct, setFocusProductState] = useState(null);
@@ -2302,7 +2349,7 @@ function useExploreChat(options = {}) {
2302
2349
  shareTokenRef.current = readShareToken();
2303
2350
  }
2304
2351
  const isSharedView = shareTokenRef.current !== null;
2305
- const catalogRef = useRef(fallbackCatalog);
2352
+ const catalogRef = useRef(catalog);
2306
2353
  const turnCountRef = useRef(0);
2307
2354
  const focusProductRef = useRef(null);
2308
2355
  const lastSentTextRef = useRef(null);
@@ -2448,25 +2495,29 @@ function useExploreChat(options = {}) {
2448
2495
  const raw = res.data?.exploreCatalog;
2449
2496
  if (res.errors?.length || !raw) {
2450
2497
  console.warn(
2451
- "[WebSDK] exploreCatalog unavailable \u2014 using the built-in fallback catalog",
2498
+ "[WebSDK] exploreCatalog unavailable \u2014 keeping the catalog the page started with",
2452
2499
  res.errors?.[0]?.message
2453
2500
  );
2454
2501
  setPhase((prev) => prev === "loading" ? "ready" : prev);
2455
2502
  return;
2456
2503
  }
2457
- const next = normalizeCatalog(raw, fallbackCatalog);
2504
+ const next = normalizeCatalog(
2505
+ raw,
2506
+ bakedRaw ? normalizeCatalog(bakedRaw, fallbackCatalog) : fallbackCatalog
2507
+ );
2458
2508
  setCatalog(next);
2509
+ setServerCatalogRaw(raw);
2459
2510
  catalogRef.current = next;
2460
2511
  setPhase((prev) => {
2461
2512
  if (!next.enabled) return "disabled";
2462
- return prev === "loading" ? "ready" : prev;
2513
+ return prev === "loading" || prev === "disabled" ? "ready" : prev;
2463
2514
  });
2464
2515
  };
2465
2516
  void load();
2466
2517
  return () => {
2467
2518
  cancelled = true;
2468
2519
  };
2469
- }, [client, productSlug, fallbackCatalog]);
2520
+ }, [client, productSlug, fallbackCatalog, bakedRaw]);
2470
2521
  const startPolling = useCallback(
2471
2522
  (conversationToken, messageId) => {
2472
2523
  pollGenerationRef.current += 1;
@@ -2934,6 +2985,7 @@ function useExploreChat(options = {}) {
2934
2985
  return {
2935
2986
  phase,
2936
2987
  catalog,
2988
+ serverCatalogRaw,
2937
2989
  messages,
2938
2990
  activity,
2939
2991
  remainingToday,
@@ -3892,6 +3944,48 @@ var EXPLORE_CSS = `
3892
3944
  }
3893
3945
  .boff-explore-strip::-webkit-scrollbar { display: none; }
3894
3946
 
3947
+ /* The product chips run past the edge of their row (there are 38). A hard edge sliced the
3948
+ last visible chip mid-word ("Bi", "BigC") right beside "All 38"; a short fade says "there
3949
+ is more this way" instead. A mask carries only alpha, so the gradient's colour is a token
3950
+ that never shows. Mirrored for right-to-left locales, whose row runs the other way. */
3951
+ .boff-explore-chips-fade {
3952
+ /* Focus scrolling honours scroll-padding, so a tabbed-to chip is brought clear of the fade
3953
+ rather than left half-hidden under it. */
3954
+ scroll-padding-inline-end: 2rem;
3955
+ -webkit-mask-image: linear-gradient(to right, hsl(var(--foreground)) calc(100% - 2rem), hsl(var(--foreground) / 0));
3956
+ mask-image: linear-gradient(to right, hsl(var(--foreground)) calc(100% - 2rem), hsl(var(--foreground) / 0));
3957
+ }
3958
+ /* A fade over a fixed edge would leave the LAST chip under it once the row is scrolled to
3959
+ the end \u2014 the visitor could never read it. A trailing spacer the width of the fade lets
3960
+ the final chip scroll clear of it. A pseudo-element rather than padding: trailing padding
3961
+ on a flex scroll container is not reliably part of its scrollable overflow. */
3962
+ .boff-explore-chips-fade::after {
3963
+ content: "";
3964
+ flex: 0 0 2rem;
3965
+ }
3966
+ [dir="rtl"] .boff-explore-chips-fade {
3967
+ -webkit-mask-image: linear-gradient(to left, hsl(var(--foreground)) calc(100% - 2rem), hsl(var(--foreground) / 0));
3968
+ mask-image: linear-gradient(to left, hsl(var(--foreground)) calc(100% - 2rem), hsl(var(--foreground) / 0));
3969
+ }
3970
+
3971
+ /* The concept rail had the chip row's problem: the card at its edge was cut hard mid-word
3972
+ ("Apparatus Rig", "CONCEPT ILLUST") on a dozen sites. It fades an edge only while there are
3973
+ more cards beyond it \u2014 the same state that lights the arrow on that side \u2014 so a rail
3974
+ scrolled to its end shows its last card whole. Physical edges, because that state is
3975
+ physical: it is measured from the left in either reading direction. */
3976
+ .boff-explore-rail-fade-left {
3977
+ -webkit-mask-image: linear-gradient(to right, hsl(var(--foreground) / 0), hsl(var(--foreground)) 3rem);
3978
+ mask-image: linear-gradient(to right, hsl(var(--foreground) / 0), hsl(var(--foreground)) 3rem);
3979
+ }
3980
+ .boff-explore-rail-fade-right {
3981
+ -webkit-mask-image: linear-gradient(to right, hsl(var(--foreground)) calc(100% - 3rem), hsl(var(--foreground) / 0));
3982
+ mask-image: linear-gradient(to right, hsl(var(--foreground)) calc(100% - 3rem), hsl(var(--foreground) / 0));
3983
+ }
3984
+ .boff-explore-rail-fade-left.boff-explore-rail-fade-right {
3985
+ -webkit-mask-image: linear-gradient(to right, hsl(var(--foreground) / 0), hsl(var(--foreground)) 3rem, hsl(var(--foreground)) calc(100% - 3rem), hsl(var(--foreground) / 0));
3986
+ mask-image: linear-gradient(to right, hsl(var(--foreground) / 0), hsl(var(--foreground)) 3rem, hsl(var(--foreground)) calc(100% - 3rem), hsl(var(--foreground) / 0));
3987
+ }
3988
+
3895
3989
  @keyframes boff-explore-fade-in {
3896
3990
  from { opacity: 0; transform: translateY(2px); }
3897
3991
  to { opacity: 1; transform: none; }
@@ -3968,10 +4062,10 @@ var EXPLORE_CSS = `
3968
4062
  Colour comes from the product's --primary token, so it is whatever that site's palette
3969
4063
  already is, never a colour chosen here. */
3970
4064
  .boff-explore-invite {
3971
- border-color: hsl(var(--primary) / 0.45);
4065
+ border-color: hsl(var(--primary) / 0.6);
3972
4066
  box-shadow:
3973
- 0 0 0 4px hsl(var(--primary) / 0.08),
3974
- 0 8px 24px -12px hsl(var(--primary) / 0.45);
4067
+ 0 0 0 4px hsl(var(--primary) / 0.12),
4068
+ 0 8px 24px -12px hsl(var(--primary) / 0.55);
3975
4069
  animation: boff-explore-breathe 3.2s ease-in-out infinite;
3976
4070
  }
3977
4071
  /* Focus and typing both mean "I have found it", and the hint has done its job. */
@@ -3981,8 +4075,8 @@ var EXPLORE_CSS = `
3981
4075
  box-shadow: 0 0 0 4px hsl(var(--primary) / 0.10);
3982
4076
  }
3983
4077
  @keyframes boff-explore-breathe {
3984
- 0%, 100% { box-shadow: 0 0 0 4px hsl(var(--primary) / 0.07), 0 8px 24px -12px hsl(var(--primary) / 0.40); }
3985
- 50% { box-shadow: 0 0 0 7px hsl(var(--primary) / 0.13), 0 8px 28px -12px hsl(var(--primary) / 0.55); }
4078
+ 0%, 100% { box-shadow: 0 0 0 4px hsl(var(--primary) / 0.10), 0 8px 24px -12px hsl(var(--primary) / 0.50); }
4079
+ 50% { box-shadow: 0 0 0 7px hsl(var(--primary) / 0.18), 0 8px 28px -12px hsl(var(--primary) / 0.65); }
3986
4080
  }
3987
4081
 
3988
4082
  /* Every one of the above is decoration. Reduced motion removes the movement and keeps the
@@ -4070,8 +4164,18 @@ var EXPLORE_CSS = `
4070
4164
  .boff-explore-scroll .boff-explore-capabilities { display: none; }
4071
4165
  }
4072
4166
  @container boff-explore-pane (min-width: ${toRem(WELCOME_FIT_MIN_WIDTH_PX)}) and (max-height: ${toRem(WELCOME_FIT_STEP_PX[1])}) {
4073
- /* Step 2. */
4167
+ /* Step 2. At a 4:1 crop the picture is ~44px tall, and the full-size caveat badge covered
4168
+ half of it \u2014 on ten sites, every card, whenever the consent banner was up. It stays (the
4169
+ picture is still a mockup), just smaller and tucked into the corner. */
4074
4170
  .boff-explore-scroll .boff-explore-concept-media { aspect-ratio: 4 / 1; }
4171
+ .boff-explore-scroll .boff-explore-concept-badge {
4172
+ top: 0.25rem;
4173
+ left: 0.25rem;
4174
+ padding: 0 0.3125rem;
4175
+ font-size: 0.5rem;
4176
+ line-height: 0.75rem;
4177
+ letter-spacing: 0.02em;
4178
+ }
4075
4179
  }
4076
4180
  @container boff-explore-pane (min-width: ${toRem(WELCOME_FIT_MIN_WIDTH_PX)}) and (max-height: ${toRem(WELCOME_FIT_STEP_PX[2])}) {
4077
4181
  /* Step 3. Title-only cards. The "concept illustration" caveat lives on the picture, so it
@@ -5230,6 +5334,7 @@ function ErrorBanner({
5230
5334
  }
5231
5335
  function PromptCarousel({
5232
5336
  strings: T,
5337
+ label,
5233
5338
  prompts,
5234
5339
  onPrompt,
5235
5340
  disabled
@@ -5261,7 +5366,7 @@ function PromptCarousel({
5261
5366
  return /* @__PURE__ */ jsxs(
5262
5367
  "div",
5263
5368
  {
5264
- className: "flex min-w-0 touch-pan-y items-center gap-1.5",
5369
+ className: "grid min-w-0 touch-pan-y grid-cols-[minmax(0,1fr)_auto_auto] items-center gap-x-1.5 gap-y-1.5 sm:grid-cols-[auto_minmax(0,1fr)_auto]",
5265
5370
  role: "group",
5266
5371
  "aria-roledescription": "carousel",
5267
5372
  "aria-label": "Example questions",
@@ -5271,13 +5376,14 @@ function PromptCarousel({
5271
5376
  onBlurCapture: () => setPaused(false),
5272
5377
  ...swipe,
5273
5378
  children: [
5379
+ /* @__PURE__ */ jsx("p", { className: "col-start-1 row-start-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground sm:col-span-3", children: label }),
5274
5380
  count > 1 ? /* @__PURE__ */ jsx(
5275
5381
  "button",
5276
5382
  {
5277
5383
  type: "button",
5278
5384
  "aria-label": T.prevSuggestion,
5279
5385
  onClick: () => go(-1),
5280
- className: "inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
5386
+ className: "col-start-2 row-start-1 inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring sm:col-start-1 sm:row-start-2",
5281
5387
  children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" })
5282
5388
  }
5283
5389
  ) : null,
@@ -5291,14 +5397,23 @@ function PromptCarousel({
5291
5397
  "aria-label": `Ask: ${current}`,
5292
5398
  "aria-live": paused ? "polite" : "off",
5293
5399
  onClick: () => onPrompt(current),
5294
- className: "boff-explore-fade group flex min-w-0 flex-1 items-center gap-2 rounded-full border border-border bg-card px-4 py-2 text-left text-sm text-card-foreground shadow-sm transition-colors hover:border-primary/50 hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
5400
+ className: cn(
5401
+ "group col-span-3 row-start-2 flex min-w-0 items-center gap-2 rounded-full border border-border bg-card px-4 py-2 max-sm:min-h-[3.625rem] max-sm:rounded-2xl text-left text-sm text-card-foreground shadow-sm transition-colors hover:border-primary/50 hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
5402
+ count > 1 ? "sm:col-span-1 sm:col-start-2" : "sm:col-span-3"
5403
+ ),
5295
5404
  children: [
5296
5405
  /* @__PURE__ */ jsx(Sparkles, { className: "h-3.5 w-3.5 shrink-0 text-primary" }),
5297
- /* @__PURE__ */ jsx("span", { className: "truncate", children: current }),
5298
- /* @__PURE__ */ jsx(ArrowUp, { className: "ml-auto h-3.5 w-3.5 shrink-0 rotate-45 text-muted-foreground transition-colors group-hover:text-primary" })
5406
+ /* @__PURE__ */ jsx(
5407
+ "span",
5408
+ {
5409
+ className: "boff-explore-fade min-w-0 max-sm:line-clamp-3 sm:truncate",
5410
+ children: current
5411
+ },
5412
+ current
5413
+ ),
5414
+ /* @__PURE__ */ jsx(ArrowUp, { className: "ml-auto h-3.5 w-3.5 shrink-0 rotate-45 text-muted-foreground transition-colors group-hover:text-primary max-sm:hidden" })
5299
5415
  ]
5300
- },
5301
- current
5416
+ }
5302
5417
  ),
5303
5418
  count > 1 ? /* @__PURE__ */ jsx(
5304
5419
  "button",
@@ -5306,7 +5421,7 @@ function PromptCarousel({
5306
5421
  type: "button",
5307
5422
  "aria-label": T.nextSuggestion,
5308
5423
  onClick: () => go(1),
5309
- className: "inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
5424
+ className: "col-start-3 row-start-1 inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring sm:row-start-2",
5310
5425
  children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })
5311
5426
  }
5312
5427
  ) : null
@@ -5337,7 +5452,7 @@ function ProductStrip({
5337
5452
  {
5338
5453
  className: cn(
5339
5454
  "boff-explore-strip flex min-w-0 flex-1 gap-2",
5340
- expanded ? "flex-wrap" : "flex-nowrap overflow-x-auto"
5455
+ expanded ? "flex-wrap" : "boff-explore-chips-fade flex-nowrap overflow-x-auto"
5341
5456
  ),
5342
5457
  children: [
5343
5458
  /* @__PURE__ */ jsx(
@@ -5405,8 +5520,11 @@ function ConceptStrip({
5405
5520
  const measureRail = useCallback(() => {
5406
5521
  const el = railRef.current;
5407
5522
  if (!el) return;
5408
- setCanLeft(el.scrollLeft > 1);
5409
- setCanRight(el.scrollLeft + el.clientWidth < el.scrollWidth - 1);
5523
+ const max = el.scrollWidth - el.clientWidth;
5524
+ const rtl = typeof getComputedStyle === "function" && getComputedStyle(el).direction === "rtl";
5525
+ const fromLeft = rtl ? max + el.scrollLeft : el.scrollLeft;
5526
+ setCanLeft(fromLeft > 1);
5527
+ setCanRight(fromLeft < max - 1);
5410
5528
  }, []);
5411
5529
  useEffect(() => {
5412
5530
  const el = railRef.current;
@@ -5475,11 +5593,15 @@ function ConceptStrip({
5475
5593
  onScroll: measureRail,
5476
5594
  "data-boff-explore": "concept-strip",
5477
5595
  "aria-label": T.conceptStripLabel,
5478
- className: "boff-explore-strip flex min-w-0 snap-x gap-3 overflow-x-auto pb-1",
5596
+ className: cn(
5597
+ "boff-explore-strip flex min-w-0 snap-x gap-3 overflow-x-auto pb-1 sm:mx-10",
5598
+ canLeft && "boff-explore-rail-fade-left",
5599
+ canRight && "boff-explore-rail-fade-right"
5600
+ ),
5479
5601
  children: visible.map((highlight) => /* @__PURE__ */ jsx(
5480
5602
  "li",
5481
5603
  {
5482
- className: "shrink-0 snap-start",
5604
+ className: "flex shrink-0 snap-start",
5483
5605
  children: /* @__PURE__ */ jsxs(
5484
5606
  "button",
5485
5607
  {
@@ -5515,14 +5637,14 @@ function ConceptStrip({
5515
5637
  "span",
5516
5638
  {
5517
5639
  "aria-hidden": "true",
5518
- className: "pointer-events-none absolute left-1.5 top-1.5 rounded-full border border-border bg-background/90 px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide text-foreground",
5640
+ className: "boff-explore-concept-badge pointer-events-none absolute left-1.5 top-1.5 rounded-full border border-border bg-background/90 px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide text-foreground",
5519
5641
  children: T.conceptIllustration
5520
5642
  }
5521
5643
  )
5522
5644
  ] }),
5523
- /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-col gap-0.5 p-2.5", children: [
5645
+ /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5 p-2.5", children: [
5524
5646
  /* @__PURE__ */ jsx("span", { className: "line-clamp-2 text-xs font-semibold leading-snug text-card-foreground", children: highlight.title }),
5525
- /* @__PURE__ */ jsx("span", { className: "truncate text-[11px] text-muted-foreground", children: highlight.productName })
5647
+ /* @__PURE__ */ jsx("span", { className: "mt-auto truncate text-[11px] text-muted-foreground", children: highlight.productName })
5526
5648
  ] })
5527
5649
  ]
5528
5650
  }
@@ -5670,18 +5792,16 @@ function WelcomeState({
5670
5792
  },
5671
5793
  i
5672
5794
  )) }),
5673
- prompts.length > 0 ? /* @__PURE__ */ jsxs("div", { className: "boff-explore-rise boff-explore-rise-2 mt-4", children: [
5674
- /* @__PURE__ */ jsx("p", { className: "mb-1.5 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: T.tryAsking }),
5675
- /* @__PURE__ */ jsx(
5676
- PromptCarousel,
5677
- {
5678
- strings: T,
5679
- prompts,
5680
- onPrompt,
5681
- disabled
5682
- }
5683
- )
5684
- ] }) : null,
5795
+ prompts.length > 0 ? /* @__PURE__ */ jsx("div", { className: "boff-explore-rise boff-explore-rise-2 mt-4", children: /* @__PURE__ */ jsx(
5796
+ PromptCarousel,
5797
+ {
5798
+ strings: T,
5799
+ label: T.tryAsking,
5800
+ prompts,
5801
+ onPrompt,
5802
+ disabled
5803
+ }
5804
+ ) }) : null,
5685
5805
  products.length > 0 ? /* @__PURE__ */ jsxs("div", { className: "boff-explore-rise boff-explore-rise-3 mt-4", children: [
5686
5806
  /* @__PURE__ */ jsx("p", { className: "mb-1.5 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: T.focusProduct }),
5687
5807
  /* @__PURE__ */ jsx(
@@ -5739,6 +5859,7 @@ function ExplorePage({
5739
5859
  const {
5740
5860
  phase,
5741
5861
  catalog,
5862
+ serverCatalogRaw,
5742
5863
  messages,
5743
5864
  activity,
5744
5865
  remainingToday,
@@ -6170,6 +6291,10 @@ function ExplorePage({
6170
6291
  const captchaOn = Boolean(
6171
6292
  catalog.captchaRequired && catalog.recaptchaSiteKey
6172
6293
  );
6294
+ const bakedCatalogJson = useMemo(
6295
+ () => serverCatalogRaw && serverCatalogRaw.enabled !== false ? serializeBakedCatalog(serverCatalogRaw) : null,
6296
+ [serverCatalogRaw]
6297
+ );
6173
6298
  const rootStyle = {};
6174
6299
  if (heightMode === "viewport") {
6175
6300
  rootStyle["--boff-explore-offset"] = paneOffset === null ? normalizeOffset(viewportOffset) : `${paneOffset}px`;
@@ -6209,6 +6334,16 @@ function ExplorePage({
6209
6334
  ),
6210
6335
  /* @__PURE__ */ jsx(ProseStyles, {}),
6211
6336
  /* @__PURE__ */ jsx(ExploreStyles, {}),
6337
+ bakedCatalogJson ? /* @__PURE__ */ jsx(
6338
+ "script",
6339
+ {
6340
+ id: BAKED_CATALOG_ELEMENT_ID,
6341
+ type: "application/json",
6342
+ "data-product": productSlug ?? "",
6343
+ "data-locale": bakedCatalogLocale(),
6344
+ dangerouslySetInnerHTML: { __html: bakedCatalogJson }
6345
+ }
6346
+ ) : null,
6212
6347
  /* @__PURE__ */ jsx(ExploreAnswerStyles, {}),
6213
6348
  !showWelcome ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 border-b border-border px-4 py-2.5", children: [
6214
6349
  /* @__PURE__ */ jsx(
@@ -6683,7 +6818,7 @@ function ExplorePage({
6683
6818
  )
6684
6819
  ] }) : null,
6685
6820
  /* @__PURE__ */ jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [
6686
- /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: T.disclaimerShort }),
6821
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 sm:truncate", children: T.disclaimerShort }),
6687
6822
  /* @__PURE__ */ jsx(
6688
6823
  "button",
6689
6824
  {