@noodleseed/assistant 1.25.1 → 1.26.0

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 (44) hide show
  1. package/README.md +54 -20
  2. package/dist/{app-view-element-BNkQab1B.d.ts → app-view-element-C_ATXseu.d.ts} +1 -1
  3. package/dist/{app-view-element-DhuiNW_x.d.cts → app-view-element-CiFVNIke.d.cts} +1 -1
  4. package/dist/app-view.cjs +5 -5
  5. package/dist/app-view.cjs.map +1 -1
  6. package/dist/app-view.d.cts +3 -3
  7. package/dist/app-view.d.ts +3 -3
  8. package/dist/app-view.js +2 -2
  9. package/dist/{appearance-B6vSg8Ub.d.cts → appearance-C24W6BRj.d.cts} +7 -3
  10. package/dist/{appearance-B6vSg8Ub.d.ts → appearance-C24W6BRj.d.ts} +7 -3
  11. package/dist/{chunk-5TYS2Q6S.js → chunk-5NBHHNI3.js} +2 -2
  12. package/dist/{chunk-FJYPE4GC.js → chunk-5PW6PXCI.js} +702 -122
  13. package/dist/chunk-5PW6PXCI.js.map +1 -0
  14. package/dist/{chunk-7BQHW37I.js → chunk-FNXAVRL5.js} +7 -1
  15. package/dist/{chunk-7BQHW37I.js.map → chunk-FNXAVRL5.js.map} +1 -1
  16. package/dist/{chunk-CF2SCDLF.js → chunk-XKTUXFGX.js} +6 -6
  17. package/dist/chunk-XKTUXFGX.js.map +1 -0
  18. package/dist/{client-BkogON2A.d.ts → client-BheCOERq.d.ts} +51 -2
  19. package/dist/{client-C07ppTU_.d.cts → client-BiMRVxjs.d.cts} +51 -2
  20. package/dist/client.cjs.map +1 -1
  21. package/dist/client.d.cts +2 -2
  22. package/dist/client.d.ts +2 -2
  23. package/dist/client.js +1 -1
  24. package/dist/embed.global.js +171 -89
  25. package/dist/index.cjs +709 -124
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.cts +6 -53
  28. package/dist/index.d.ts +6 -53
  29. package/dist/index.js +3 -3
  30. package/dist/react/client.cjs.map +1 -1
  31. package/dist/react/client.d.cts +2 -2
  32. package/dist/react/client.d.ts +2 -2
  33. package/dist/react/client.js +1 -1
  34. package/dist/react.cjs +709 -124
  35. package/dist/react.cjs.map +1 -1
  36. package/dist/react.d.cts +4 -4
  37. package/dist/react.d.ts +4 -4
  38. package/dist/react.js +4 -4
  39. package/dist/server.d.cts +1 -1
  40. package/dist/server.d.ts +1 -1
  41. package/package.json +1 -1
  42. package/dist/chunk-CF2SCDLF.js.map +0 -1
  43. package/dist/chunk-FJYPE4GC.js.map +0 -1
  44. /package/dist/{chunk-5TYS2Q6S.js.map → chunk-5NBHHNI3.js.map} +0 -0
package/dist/react.cjs CHANGED
@@ -15197,7 +15197,7 @@ __export(react_exports, {
15197
15197
  module.exports = __toCommonJS(react_exports);
15198
15198
  var import_react2 = require("react");
15199
15199
 
15200
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_supports-color@7.2.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
15200
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
15201
15201
  init_v4();
15202
15202
  var RELATED_TASK_META_KEY = "io.modelcontextprotocol/related-task";
15203
15203
  var JSONRPC_VERSION = "2.0";
@@ -20594,7 +20594,7 @@ var pipelineType = ZodPipeline.create;
20594
20594
  // ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/mini/parse.js
20595
20595
  init_core2();
20596
20596
 
20597
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_supports-color@7.2.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
20597
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
20598
20598
  function isZ4Schema(s2) {
20599
20599
  const schema = s2;
20600
20600
  return !!schema._zod;
@@ -20657,7 +20657,7 @@ function getLiteralValue(schema) {
20657
20657
  return void 0;
20658
20658
  }
20659
20659
 
20660
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_supports-color@7.2.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/interfaces.js
20660
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/interfaces.js
20661
20661
  function isTerminal(status) {
20662
20662
  return status === "completed" || status === "failed" || status === "cancelled";
20663
20663
  }
@@ -20665,7 +20665,7 @@ function isTerminal(status) {
20665
20665
  // ../../node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@4.4.3/node_modules/zod-to-json-schema/dist/esm/parsers/string.js
20666
20666
  var ALPHA_NUMERIC = new Set("ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvxyz0123456789");
20667
20667
 
20668
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_supports-color@7.2.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-json-schema-compat.js
20668
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-json-schema-compat.js
20669
20669
  function getMethodLiteral(schema) {
20670
20670
  const shape = getObjectShape(schema);
20671
20671
  const methodSchema = shape?.method;
@@ -20686,7 +20686,7 @@ function parseWithCompat(schema, data) {
20686
20686
  return result.data;
20687
20687
  }
20688
20688
 
20689
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_supports-color@7.2.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js
20689
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js
20690
20690
  var DEFAULT_REQUEST_TIMEOUT_MSEC = 6e4;
20691
20691
  var Protocol = class {
20692
20692
  constructor(_options) {
@@ -22346,7 +22346,7 @@ function unmountAssistantApp(card) {
22346
22346
 
22347
22347
  // src/appearance.ts
22348
22348
  var common = {
22349
- fontFamily: "inherit",
22349
+ fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
22350
22350
  monoFontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
22351
22351
  baseFontSize: 15,
22352
22352
  messageFontSize: 15,
@@ -22357,7 +22357,7 @@ var common = {
22357
22357
  buttonRadius: 999,
22358
22358
  launcherRadius: 999,
22359
22359
  spacing: 8,
22360
- backdropBlur: 18,
22360
+ backdropBlur: 6,
22361
22361
  motionScale: 1
22362
22362
  };
22363
22363
  var DEFAULT_APPEARANCE = {
@@ -22377,7 +22377,7 @@ var DEFAULT_APPEARANCE = {
22377
22377
  accent: "#C2410C",
22378
22378
  accentText: "#FFFFFF",
22379
22379
  link: "#9A3412",
22380
- divider: "#E4E4E7",
22380
+ divider: "rgba(0, 0, 0, 0.1)",
22381
22381
  focus: "#C2410C",
22382
22382
  success: "#16835D",
22383
22383
  warning: "#A45B00",
@@ -22385,7 +22385,7 @@ var DEFAULT_APPEARANCE = {
22385
22385
  overlay: "#18181B66",
22386
22386
  code: "#F1F1F3",
22387
22387
  widgetFrame: "#E4E4E7",
22388
- shadow: "0 4px 16px rgba(0, 0, 0, 0.06), 0 24px 70px rgba(0, 0, 0, 0.10)"
22388
+ shadow: "0 4px 16px rgba(0, 0, 0, 0.06)"
22389
22389
  },
22390
22390
  dark: {
22391
22391
  ...common,
@@ -22400,7 +22400,7 @@ var DEFAULT_APPEARANCE = {
22400
22400
  accent: "#FB923C",
22401
22401
  accentText: "#1C0A02",
22402
22402
  link: "#FDBA74",
22403
- divider: "#292524",
22403
+ divider: "rgba(255, 255, 255, 0.1)",
22404
22404
  focus: "#FB923C",
22405
22405
  success: "#58C69A",
22406
22406
  warning: "#F2B45F",
@@ -22408,15 +22408,15 @@ var DEFAULT_APPEARANCE = {
22408
22408
  overlay: "#00000099",
22409
22409
  code: "#26262C",
22410
22410
  widgetFrame: "#34343B",
22411
- shadow: "0 8px 32px rgba(0, 0, 0, 0.48)"
22411
+ shadow: "0 8px 32px rgba(0, 0, 0, 0.4)"
22412
22412
  }
22413
22413
  },
22414
22414
  layout: {
22415
22415
  mode: "floating",
22416
- position: "bottom-right",
22417
- panelWidth: 520,
22418
- panelMinHeight: 540,
22419
- panelMaxHeight: 820,
22416
+ position: "bottom-center",
22417
+ panelWidth: 970,
22418
+ panelMinHeight: 0,
22419
+ panelMaxHeight: 1025,
22420
22420
  edgeOffset: 20,
22421
22421
  zIndex: 2147483e3,
22422
22422
  density: "comfortable",
@@ -22429,11 +22429,13 @@ var DEFAULT_APPEARANCE = {
22429
22429
  showLauncher: true,
22430
22430
  showHeader: true,
22431
22431
  showAvatars: true,
22432
- showTimestamps: false
22432
+ showTimestamps: false,
22433
+ showPoweredBy: true
22433
22434
  },
22434
22435
  labels: {
22435
- welcomeHeading: "How can I help?",
22436
+ welcomeHeading: "",
22436
22437
  welcomeMessage: "",
22438
+ launcherPlaceholder: "Chat with us",
22437
22439
  composerPlaceholder: "Ask a question\u2026",
22438
22440
  thinking: "Thinking",
22439
22441
  send: "Send",
@@ -22467,11 +22469,12 @@ var DEFAULT_APPEARANCE = {
22467
22469
  },
22468
22470
  presentation: {
22469
22471
  panel: {
22470
- surface: "glass",
22472
+ surface: "solid",
22471
22473
  elevation: "soft",
22472
22474
  border: "subtle"
22473
22475
  },
22474
22476
  launcher: {
22477
+ style: "pill",
22475
22478
  icon: "brand-mark",
22476
22479
  size: "md",
22477
22480
  status: "none",
@@ -22481,7 +22484,11 @@ var DEFAULT_APPEARANCE = {
22481
22484
  composer: { leadingIcon: "none", sendIcon: "arrow-up", shape: "pill" },
22482
22485
  messages: { userStyle: "bubble", assistantStyle: "plain" }
22483
22486
  },
22484
- suggestedPrompts: [],
22487
+ suggestedPrompts: [
22488
+ "What products do you have?",
22489
+ "Tell me about your business",
22490
+ "How can I get in touch?"
22491
+ ],
22485
22492
  locale: "en",
22486
22493
  direction: "auto"
22487
22494
  };
@@ -22497,7 +22504,7 @@ function resolveAppearance(input = {}) {
22497
22504
  mark: themedAsset(branding?.mark)
22498
22505
  },
22499
22506
  theme: {
22500
- defaultMode: branding?.colorScheme ?? DEFAULT_APPEARANCE.theme.defaultMode,
22507
+ defaultMode: assistant?.theme ?? branding?.colorScheme ?? DEFAULT_APPEARANCE.theme.defaultMode,
22501
22508
  light: resolveTheme("light", branding),
22502
22509
  dark: resolveTheme("dark", branding)
22503
22510
  },
@@ -22508,9 +22515,17 @@ function resolveAppearance(input = {}) {
22508
22515
  ...assistant?.layout?.edgeOffset === void 0 ? {} : { edgeOffset: boundedNumber(assistant.layout.edgeOffset, 0, 96) }
22509
22516
  },
22510
22517
  behavior: { ...DEFAULT_APPEARANCE.behavior, ...assistant?.behavior },
22511
- labels: { ...DEFAULT_APPEARANCE.labels, ...assistant?.labels },
22518
+ labels: {
22519
+ ...DEFAULT_APPEARANCE.labels,
22520
+ ...branding?.name ? { launcherPlaceholder: `Chat with ${branding.name}` } : {},
22521
+ ...assistant?.labels
22522
+ },
22512
22523
  presentation: resolvePresentation(assistant?.presentation),
22513
- suggestedPrompts: assistant?.suggestedPrompts ?? DEFAULT_APPEARANCE.suggestedPrompts,
22524
+ suggestedPrompts: assistant?.suggestedPrompts ?? (branding?.name ? [
22525
+ "What products do you have?",
22526
+ `Tell me about ${branding.name}`,
22527
+ "How can I get in touch?"
22528
+ ] : DEFAULT_APPEARANCE.suggestedPrompts),
22514
22529
  ...assistant?.privacyUrl ? { privacyUrl: assistant.privacyUrl } : {},
22515
22530
  ...assistant?.termsUrl ? { termsUrl: assistant.termsUrl } : {},
22516
22531
  locale: assistant?.locale ?? DEFAULT_APPEARANCE.locale,
@@ -24781,6 +24796,10 @@ async function resolve(value) {
24781
24796
  return Promise.resolve(value);
24782
24797
  }
24783
24798
 
24799
+ // ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/index.js
24800
+ init_external();
24801
+ init_external();
24802
+
24784
24803
  // ../../node_modules/.pnpm/ai@6.0.201_zod@4.4.3/node_modules/ai/dist/index.mjs
24785
24804
  init_v4();
24786
24805
  init_v4();
@@ -27523,6 +27542,11 @@ function isRecord3(value) {
27523
27542
  // src/session-source.ts
27524
27543
  var NOODLE_CLOUD_URL = "https://cloud.noodleseed.dev";
27525
27544
  var PUBLIC_SESSION_PATH = "/v1/assistant/public-sessions";
27545
+ var PUBLIC_CONFIGURATION_PATH = "/v1/assistant/public-configurations";
27546
+ function publicConfigurationUrl(serviceUrl, embedId) {
27547
+ const base = (serviceUrl || NOODLE_CLOUD_URL).replace(/\/+$/, "");
27548
+ return `${base}${PUBLIC_CONFIGURATION_PATH}/${encodeURIComponent(embedId)}`;
27549
+ }
27526
27550
  function resolveSessionSource(options) {
27527
27551
  const { sessionEndpoint, embedId, serviceUrl } = options;
27528
27552
  if (Boolean(embedId) === Boolean(sessionEndpoint)) {
@@ -29034,11 +29058,11 @@ function createDOMPurify() {
29034
29058
  const originalDocument = document2;
29035
29059
  const currentScript = originalDocument.currentScript;
29036
29060
  window2.DocumentFragment;
29037
- const HTMLTemplateElement = window2.HTMLTemplateElement, Node = window2.Node, Element = window2.Element, NodeFilter = window2.NodeFilter, _window$NamedNodeMap = window2.NamedNodeMap;
29061
+ const HTMLTemplateElement = window2.HTMLTemplateElement, Node = window2.Node, Element2 = window2.Element, NodeFilter = window2.NodeFilter, _window$NamedNodeMap = window2.NamedNodeMap;
29038
29062
  _window$NamedNodeMap === void 0 ? window2.NamedNodeMap || window2.MozNamedAttrMap : _window$NamedNodeMap;
29039
29063
  window2.HTMLFormElement;
29040
29064
  const DOMParser = window2.DOMParser, trustedTypes = window2.trustedTypes;
29041
- const ElementPrototype = Element.prototype;
29065
+ const ElementPrototype = Element2.prototype;
29042
29066
  const cloneNode = lookupGetter(ElementPrototype, "cloneNode");
29043
29067
  const remove = lookupGetter(ElementPrototype, "remove");
29044
29068
  const getNextSibling = lookupGetter(ElementPrototype, "nextSibling");
@@ -31688,19 +31712,40 @@ function queryRequired(root, selector) {
31688
31712
  if (!element) throw new Error(`assistant renderer is missing ${selector}`);
31689
31713
  return element;
31690
31714
  }
31691
- function assistantElementMarkup(appearance, open, styles) {
31715
+ function assistantElementMarkup(appearance, styles) {
31692
31716
  return `${styles}
31693
- <button class="launcher" type="button" aria-label="${escapeAttribute(appearance.labels.open)}" aria-controls="assistant-panel" aria-expanded="${String(open)}"><slot name="launcher-icon"></slot><span class="visually-hidden" data-session-status aria-live="polite" hidden></span></button>
31717
+ <div class="launcher">
31718
+ <slot name="launcher-icon"></slot>
31719
+ <span class="launcher-loader" aria-hidden="true"></span>
31720
+ <button class="launcher-trigger" type="button" aria-label="${escapeAttribute(appearance.labels.open)}" aria-controls="assistant-launcher-form" aria-expanded="false">
31721
+ <span class="launcher-label">${escapeAttribute(appearance.labels.launcherPlaceholder)}</span>
31722
+ <span class="launcher-arrow" aria-hidden="true"></span>
31723
+ </button>
31724
+ <form class="launcher-form" id="assistant-launcher-form" aria-hidden="true" autocomplete="off">
31725
+ <input class="launcher-input" type="text" aria-label="${escapeAttribute(appearance.labels.launcherPlaceholder)}" placeholder="${escapeAttribute(appearance.labels.launcherPlaceholder)}" tabindex="-1">
31726
+ <button class="launcher-send" type="submit" aria-label="${escapeAttribute(appearance.labels.send)}"></button>
31727
+ </form>
31728
+ <span class="visually-hidden" data-session-status aria-live="polite" hidden></span>
31729
+ </div>
31694
31730
  <section class="panel" id="assistant-panel" role="dialog" aria-label="${escapeAttribute(appearance.brand.name)}">
31695
31731
  <header><slot name="header-leading"></slot><img class="brand-logo" alt=""><strong></strong><slot name="header-actions"></slot><button class="close" type="button" aria-label="${escapeAttribute(appearance.labels.close)}"></button></header>
31696
31732
  <div class="welcome"><slot name="empty-state"></slot></div>
31697
- <div class="suggested-prompts"></div>
31698
31733
  <div class="messages-region">
31699
31734
  <div class="messages" aria-live="polite"></div>
31700
31735
  <button class="new-messages" type="button" aria-label="${escapeAttribute(appearance.labels.newMessages)}" hidden></button>
31701
31736
  </div>
31702
- <form><slot name="composer-leading"></slot><textarea rows="1"></textarea><button class="send" type="submit"></button><slot name="composer-trailing"></slot></form>
31737
+ <div class="input-section">
31738
+ <div class="suggested-prompts"></div>
31739
+ <form class="composer"><slot name="composer-leading"></slot><textarea rows="1"></textarea><button class="send" type="submit"></button><slot name="composer-trailing"></slot></form>
31740
+ </div>
31703
31741
  <nav class="legal" aria-label="Legal"></nav>
31742
+ <div class="powered-by-row">
31743
+ <a class="powered-by" href="https://noodleseed.com" target="_blank" rel="noopener noreferrer">
31744
+ <span>Powered by</span>
31745
+ <span class="powered-by-icon" aria-hidden="true"><svg width="14" height="14" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><rect width="16" height="16" rx="8" fill="currentColor" fill-opacity="0.12"></rect><path d="M8.58023 12.8485C6.27833 12.8463 4.41315 11.0141 4.42117 8.75681L4.43588 4.61714L8.66254 4.62118C10.9644 4.62339 12.8296 6.45561 12.8216 8.71287C12.8135 10.9975 10.9128 12.8507 8.58023 12.8485Z" fill="currentColor"></path><path d="M8.82627 4.76869C11.1282 4.7709 12.9933 6.60312 12.9853 8.86038L12.9706 13L8.74395 12.996C6.44206 12.9938 4.57687 11.1616 4.5849 8.90432C4.59302 6.6197 6.49364 4.76646 8.82627 4.76869Z" fill="currentColor"></path><ellipse cx="3.69536" cy="3.68106" rx="0.695363" ry="0.681056" fill="currentColor"></ellipse></svg></span>
31746
+ <span class="powered-by-name">Noodle Seed</span>
31747
+ </a>
31748
+ </div>
31704
31749
  <slot name="conversation-footer"></slot>
31705
31750
  </section>`;
31706
31751
  }
@@ -31719,6 +31764,230 @@ function appendLegalLinks(legal, appearance) {
31719
31764
  }
31720
31765
  }
31721
31766
 
31767
+ // src/element-theme-resolution.ts
31768
+ function resolveAssistantTheme(input) {
31769
+ if (input.configured === "light" || input.configured === "dark") return input.configured;
31770
+ const hostMode = resolveHostTheme(input.host, input.media);
31771
+ return input.configured === "invert" ? opposite(hostMode) : hostMode;
31772
+ }
31773
+ function resolveHostTheme(host, media) {
31774
+ const view = host.ownerDocument.defaultView;
31775
+ for (let node = host.parentElement; node; node = node.parentElement) {
31776
+ const declared = declaredTheme(node);
31777
+ if (declared) return declared;
31778
+ const computed = computedTheme(view?.getComputedStyle(node).colorScheme);
31779
+ if (computed) return computed;
31780
+ }
31781
+ return media?.matches ? "dark" : "light";
31782
+ }
31783
+ function computedTheme(colorScheme) {
31784
+ const modes = colorScheme?.split(/\s+/) ?? [];
31785
+ if (modes.includes("dark") && !modes.includes("light")) return "dark";
31786
+ if (modes.includes("light") && !modes.includes("dark")) return "light";
31787
+ return void 0;
31788
+ }
31789
+ function declaredTheme(element) {
31790
+ const value = element.getAttribute("data-theme") ?? element.getAttribute("data-color-scheme") ?? element.getAttribute("data-mode");
31791
+ if (value === "dark" || value === "light") return value;
31792
+ if (element.classList.contains("dark")) return "dark";
31793
+ if (element.classList.contains("light")) return "light";
31794
+ return void 0;
31795
+ }
31796
+ function opposite(mode) {
31797
+ return mode === "dark" ? "light" : "dark";
31798
+ }
31799
+
31800
+ // src/element-host-environment-controller.ts
31801
+ var AssistantElementHostEnvironmentController = class {
31802
+ #host;
31803
+ #appearance;
31804
+ #applyTheme;
31805
+ #close;
31806
+ #media;
31807
+ #themeObserver;
31808
+ constructor(options) {
31809
+ this.#host = options.host;
31810
+ this.#appearance = options.appearance;
31811
+ this.#applyTheme = options.applyTheme;
31812
+ this.#close = options.close;
31813
+ }
31814
+ get media() {
31815
+ return this.#media;
31816
+ }
31817
+ resolvedTheme() {
31818
+ return resolveAssistantTheme({
31819
+ host: this.#host,
31820
+ configured: this.#host.getAttribute("theme") ?? this.#appearance().theme.defaultMode,
31821
+ ...this.#media ? { media: this.#media } : {}
31822
+ });
31823
+ }
31824
+ connect() {
31825
+ this.disconnect();
31826
+ this.#media = globalThis.matchMedia?.("(prefers-color-scheme: dark)");
31827
+ this.#media?.addEventListener("change", this.#applyTheme);
31828
+ this.#themeObserver = new MutationObserver(this.#applyTheme);
31829
+ for (let node = this.#host.parentElement; node; node = node.parentElement) {
31830
+ this.#themeObserver.observe(node, {
31831
+ attributes: true,
31832
+ attributeFilter: ["class", "data-theme", "data-color-scheme", "data-mode", "style"]
31833
+ });
31834
+ }
31835
+ document.addEventListener("keydown", this.#handleDocumentKeydown);
31836
+ document.addEventListener("pointerdown", this.#handleDocumentPointerDown);
31837
+ }
31838
+ disconnect() {
31839
+ this.#media?.removeEventListener("change", this.#applyTheme);
31840
+ this.#media = void 0;
31841
+ this.#themeObserver?.disconnect();
31842
+ this.#themeObserver = void 0;
31843
+ document.removeEventListener("keydown", this.#handleDocumentKeydown);
31844
+ document.removeEventListener("pointerdown", this.#handleDocumentPointerDown);
31845
+ }
31846
+ #handleDocumentKeydown = (event) => {
31847
+ if (event.key === "Escape" && this.#host.hasAttribute("open") && this.#appearance().behavior.closeOnEscape) {
31848
+ this.#close();
31849
+ }
31850
+ };
31851
+ #handleDocumentPointerDown = (event) => {
31852
+ if (this.#host.hasAttribute("open") && this.#appearance().behavior.closeOnOutsideClick && !event.composedPath().includes(this.#host)) {
31853
+ this.#close();
31854
+ }
31855
+ };
31856
+ };
31857
+
31858
+ // src/element-launcher-controller.ts
31859
+ var AssistantElementLauncherController = class {
31860
+ #host;
31861
+ #appearance;
31862
+ #openPanel;
31863
+ #sendMessage;
31864
+ #root;
31865
+ constructor(options) {
31866
+ this.#host = options.host;
31867
+ this.#appearance = options.appearance;
31868
+ this.#openPanel = options.openPanel;
31869
+ this.#sendMessage = options.sendMessage;
31870
+ }
31871
+ connect(root) {
31872
+ this.disconnect();
31873
+ this.#root = root;
31874
+ queryRequired(root, ".launcher").addEventListener(
31875
+ "click",
31876
+ this.#handleLauncherClick
31877
+ );
31878
+ queryRequired(root, ".launcher-trigger").addEventListener(
31879
+ "click",
31880
+ this.#handleTrigger
31881
+ );
31882
+ queryRequired(root, ".launcher-form").addEventListener(
31883
+ "submit",
31884
+ this.#handleSubmit
31885
+ );
31886
+ queryRequired(root, ".launcher-input").addEventListener(
31887
+ "keydown",
31888
+ this.#handleInputKeydown
31889
+ );
31890
+ document.addEventListener("pointerdown", this.#handleDocumentPointerDown);
31891
+ this.sync();
31892
+ }
31893
+ disconnect() {
31894
+ document.removeEventListener("pointerdown", this.#handleDocumentPointerDown);
31895
+ this.#root = void 0;
31896
+ }
31897
+ sync() {
31898
+ const root = this.#root;
31899
+ if (!root) return;
31900
+ const appearance = this.#appearance();
31901
+ const style = appearance.presentation.launcher.style;
31902
+ this.#host.dataset.launcherStyle = style;
31903
+ const trigger = queryRequired(root, ".launcher-trigger");
31904
+ const label = queryRequired(root, ".launcher-label");
31905
+ const input = queryRequired(root, ".launcher-input");
31906
+ label.textContent = appearance.labels.launcherPlaceholder;
31907
+ input.placeholder = appearance.labels.launcherPlaceholder;
31908
+ input.setAttribute("aria-label", appearance.labels.launcherPlaceholder);
31909
+ trigger.setAttribute("aria-label", appearance.labels.open);
31910
+ queryRequired(root, ".launcher-send").setAttribute(
31911
+ "aria-label",
31912
+ appearance.labels.send
31913
+ );
31914
+ queryRequired(root, ".launcher").hidden = !appearance.behavior.showLauncher;
31915
+ queryRequired(root, ".powered-by-row").hidden = !appearance.behavior.showPoweredBy;
31916
+ if (style === "bubble" || this.#host.hasAttribute("open")) this.collapse(true);
31917
+ }
31918
+ collapse(force = false) {
31919
+ const root = this.#root;
31920
+ if (!root) return;
31921
+ const input = queryRequired(root, ".launcher-input");
31922
+ if (!force && input.value.trim()) return;
31923
+ this.#host.removeAttribute("launcher-expanded");
31924
+ const form = queryRequired(root, ".launcher-form");
31925
+ const trigger = queryRequired(root, ".launcher-trigger");
31926
+ form.setAttribute("aria-hidden", "true");
31927
+ trigger.setAttribute("aria-expanded", "false");
31928
+ input.tabIndex = -1;
31929
+ input.blur();
31930
+ }
31931
+ focusTrigger() {
31932
+ this.#root?.querySelector(".launcher-trigger")?.focus();
31933
+ }
31934
+ #expand() {
31935
+ const root = this.#root;
31936
+ if (!root || this.#appearance().presentation.launcher.style === "bubble") return;
31937
+ this.#host.setAttribute("launcher-expanded", "");
31938
+ const form = queryRequired(root, ".launcher-form");
31939
+ const trigger = queryRequired(root, ".launcher-trigger");
31940
+ const input = queryRequired(root, ".launcher-input");
31941
+ form.setAttribute("aria-hidden", "false");
31942
+ trigger.setAttribute("aria-expanded", "true");
31943
+ input.tabIndex = 0;
31944
+ requestAnimationFrame(() => {
31945
+ if (this.#host.hasAttribute("launcher-expanded")) input.focus();
31946
+ });
31947
+ }
31948
+ #handleTrigger = () => {
31949
+ if (this.#appearance().presentation.launcher.style === "bubble") {
31950
+ this.#openPanel();
31951
+ return;
31952
+ }
31953
+ this.#expand();
31954
+ };
31955
+ #handleLauncherClick = (event) => {
31956
+ if (event.composedPath().some(
31957
+ (target) => target instanceof Element && target.matches(".launcher-trigger, .launcher-form")
31958
+ )) {
31959
+ return;
31960
+ }
31961
+ this.#handleTrigger();
31962
+ };
31963
+ #handleSubmit = (event) => {
31964
+ event.preventDefault();
31965
+ const input = this.#root?.querySelector(".launcher-input");
31966
+ const message = input?.value.trim() ?? "";
31967
+ if (input) input.value = "";
31968
+ this.#openPanel();
31969
+ if (message) this.#sendMessage(message);
31970
+ };
31971
+ #handleInputKeydown = (event) => {
31972
+ if (event.key === "Enter" && !event.isComposing) {
31973
+ event.preventDefault();
31974
+ this.#root?.querySelector(".launcher-form")?.requestSubmit();
31975
+ return;
31976
+ }
31977
+ if (event.key !== "Escape") return;
31978
+ event.preventDefault();
31979
+ event.stopPropagation();
31980
+ const input = this.#root?.querySelector(".launcher-input");
31981
+ if (input) input.value = "";
31982
+ this.collapse(true);
31983
+ this.focusTrigger();
31984
+ };
31985
+ #handleDocumentPointerDown = (event) => {
31986
+ if (event.composedPath().includes(this.#host)) return;
31987
+ this.collapse();
31988
+ };
31989
+ };
31990
+
31722
31991
  // src/element-page-context-controller.ts
31723
31992
  var AssistantElementPageContextController = class {
31724
31993
  #snapshot;
@@ -31772,10 +32041,12 @@ var AssistantElementPresentationGate = class {
31772
32041
  syncOpenState() {
31773
32042
  const open = this.#host.hasAttribute("open");
31774
32043
  const presentationReady = this.#host.hasAttribute("data-presentation-ready");
31775
- const launcher = this.#host.shadowRoot?.querySelector(".launcher");
31776
- launcher?.setAttribute("aria-expanded", String(open && presentationReady));
31777
- launcher?.setAttribute("aria-busy", String(open && !presentationReady));
31778
- if (launcher) launcher.disabled = open && !presentationReady;
32044
+ const publicConfigurationLoading = this.#host.hasAttribute("data-public-configuration-loading");
32045
+ const presentationBlocked = !presentationReady && (open || publicConfigurationLoading);
32046
+ const launcher = this.#host.shadowRoot?.querySelector(".launcher-trigger");
32047
+ launcher?.setAttribute("aria-busy", String(presentationBlocked));
32048
+ if (launcher) launcher.disabled = presentationBlocked;
32049
+ this.#host.shadowRoot?.querySelector(".panel")?.setAttribute("aria-hidden", String(!(open && presentationReady)));
31779
32050
  if (open && this.#host.isConnected) this.#primeSession();
31780
32051
  }
31781
32052
  reveal() {
@@ -31786,6 +32057,233 @@ var AssistantElementPresentationGate = class {
31786
32057
  }
31787
32058
  };
31788
32059
 
32060
+ // src/assistant-configuration-schema.ts
32061
+ var hexColorSchema = external_exports.string().regex(/^#[0-9A-Fa-f]{6}$/);
32062
+ var browserAssetUrlSchema = external_exports.string().trim().url().refine(isSecureBrowserAssetUrl, "must use https (http is allowed only for loopback testing)");
32063
+ var httpsUrlSchema = external_exports.string().trim().url().refine(isHttpsUrl2, "must use https");
32064
+ var brandAssetSchema = external_exports.object({
32065
+ uri: browserAssetUrlSchema,
32066
+ darkUri: browserAssetUrlSchema.optional(),
32067
+ alt: external_exports.string().trim().min(1).max(240)
32068
+ }).strict();
32069
+ var brandThemeSchema = external_exports.object({
32070
+ surface: hexColorSchema.optional(),
32071
+ surfaceRaised: hexColorSchema.optional(),
32072
+ surfaceMuted: hexColorSchema.optional(),
32073
+ text: hexColorSchema.optional(),
32074
+ textMuted: hexColorSchema.optional(),
32075
+ accent: hexColorSchema.optional(),
32076
+ accentText: hexColorSchema.optional(),
32077
+ link: hexColorSchema.optional(),
32078
+ border: hexColorSchema.optional(),
32079
+ borderStrong: hexColorSchema.optional(),
32080
+ focus: hexColorSchema.optional(),
32081
+ success: hexColorSchema.optional(),
32082
+ warning: hexColorSchema.optional(),
32083
+ danger: hexColorSchema.optional(),
32084
+ code: hexColorSchema.optional()
32085
+ }).strict();
32086
+ var brandingSchema = external_exports.object({
32087
+ name: external_exports.string().trim().min(1).max(160).optional(),
32088
+ accent: hexColorSchema.optional(),
32089
+ surface: hexColorSchema.optional(),
32090
+ surfaceDark: hexColorSchema.optional(),
32091
+ logo: brandAssetSchema.optional(),
32092
+ mark: brandAssetSchema.optional(),
32093
+ avatar: brandAssetSchema.optional(),
32094
+ theme: external_exports.object({ light: brandThemeSchema.optional(), dark: brandThemeSchema.optional() }).strict().optional(),
32095
+ radius: external_exports.enum(["none", "sm", "md", "lg"]).optional(),
32096
+ density: external_exports.enum(["compact", "comfortable"]).optional(),
32097
+ typography: external_exports.enum(["system", "serif", "mono"]).optional(),
32098
+ colorScheme: external_exports.enum(["auto", "light", "dark"]).optional()
32099
+ }).strict();
32100
+ var labelsSchema = external_exports.object({
32101
+ welcomeHeading: external_exports.string().trim().min(1).max(160).optional(),
32102
+ welcomeMessage: external_exports.string().max(1e3).optional(),
32103
+ launcherPlaceholder: external_exports.string().trim().min(1).max(160).optional(),
32104
+ composerPlaceholder: external_exports.string().trim().min(1).max(160).optional(),
32105
+ thinking: external_exports.string().trim().min(1).max(80).optional(),
32106
+ send: external_exports.string().trim().min(1).max(80).optional(),
32107
+ stop: external_exports.string().trim().min(1).max(80).optional(),
32108
+ close: external_exports.string().trim().min(1).max(80).optional(),
32109
+ open: external_exports.string().trim().min(1).max(80).optional(),
32110
+ confirm: external_exports.string().trim().min(1).max(80).optional(),
32111
+ decline: external_exports.string().trim().min(1).max(80).optional(),
32112
+ cancel: external_exports.string().trim().min(1).max(80).optional(),
32113
+ confirmationHeading: external_exports.string().trim().min(1).max(120).optional(),
32114
+ additionalDetails: external_exports.string().trim().min(1).max(120).optional(),
32115
+ redacted: external_exports.string().trim().min(1).max(120).optional(),
32116
+ completed: external_exports.string().trim().min(1).max(80).optional(),
32117
+ stopped: external_exports.string().trim().min(1).max(80).optional(),
32118
+ copy: external_exports.string().trim().min(1).max(80).optional(),
32119
+ newMessages: external_exports.string().trim().min(1).max(80).optional(),
32120
+ reconnect: external_exports.string().trim().min(1).max(80).optional(),
32121
+ newConversation: external_exports.string().trim().min(1).max(80).optional(),
32122
+ retry: external_exports.string().trim().min(1).max(80).optional(),
32123
+ unavailable: external_exports.string().trim().min(1).max(240).optional(),
32124
+ sessionExpired: external_exports.string().trim().min(1).max(240).optional(),
32125
+ sessionIdle: external_exports.string().trim().min(1).max(120).optional(),
32126
+ sessionLoading: external_exports.string().trim().min(1).max(120).optional(),
32127
+ sessionReady: external_exports.string().trim().min(1).max(120).optional(),
32128
+ sessionError: external_exports.string().trim().min(1).max(120).optional(),
32129
+ signInHeading: external_exports.string().trim().min(1).max(120).optional(),
32130
+ signInBody: external_exports.string().max(240).optional(),
32131
+ signInAction: external_exports.string().trim().min(1).max(80).optional(),
32132
+ signUpAction: external_exports.string().trim().min(1).max(80).optional()
32133
+ }).strict();
32134
+ var presentationSchema = external_exports.object({
32135
+ panel: external_exports.object({
32136
+ surface: external_exports.enum(["solid", "glass"]).optional(),
32137
+ elevation: external_exports.enum(["soft", "dramatic"]).optional(),
32138
+ border: external_exports.enum(["subtle", "strong"]).optional(),
32139
+ radius: external_exports.number().int().min(0).max(64).optional()
32140
+ }).strict().optional(),
32141
+ launcher: external_exports.object({
32142
+ style: external_exports.enum(["pill", "bubble"]).optional(),
32143
+ icon: external_exports.enum(["brand-mark", "chat", "none"]).optional(),
32144
+ size: external_exports.enum(["md", "lg"]).optional(),
32145
+ status: external_exports.enum(["none", "session"]).optional(),
32146
+ effect: external_exports.enum(["none", "pulse"]).optional()
32147
+ }).strict().optional(),
32148
+ header: external_exports.object({
32149
+ mark: external_exports.enum(["none", "brand-mark", "status"]).optional(),
32150
+ badge: external_exports.object({
32151
+ text: external_exports.string().trim().min(1).max(80),
32152
+ tone: external_exports.enum(["neutral", "success", "warning", "danger"]).optional(),
32153
+ indicator: external_exports.boolean().optional()
32154
+ }).strict().optional()
32155
+ }).strict().optional(),
32156
+ composer: external_exports.object({
32157
+ leadingIcon: external_exports.enum(["none", "brand-mark"]).optional(),
32158
+ sendIcon: external_exports.enum(["arrow-up", "paper-plane"]).optional(),
32159
+ shape: external_exports.enum(["rounded", "pill"]).optional()
32160
+ }).strict().optional(),
32161
+ messages: external_exports.object({
32162
+ userStyle: external_exports.enum(["bubble", "accent"]).optional(),
32163
+ assistantStyle: external_exports.enum(["plain", "bubble"]).optional()
32164
+ }).strict().optional()
32165
+ }).strict();
32166
+ var assistantUiSchema = external_exports.object({
32167
+ theme: external_exports.enum(["auto", "light", "dark", "invert"]).optional(),
32168
+ layout: external_exports.object({
32169
+ mode: external_exports.enum(["floating", "inline", "drawer"]).optional(),
32170
+ position: external_exports.enum(["bottom-left", "bottom-center", "bottom-right"]).optional(),
32171
+ panelWidth: external_exports.number().int().min(280).max(1200).optional(),
32172
+ panelMinHeight: external_exports.number().int().min(240).max(1600).optional(),
32173
+ panelMaxHeight: external_exports.number().int().min(320).max(2400).optional(),
32174
+ edgeOffset: external_exports.number().int().min(0).max(96).optional(),
32175
+ zIndex: external_exports.number().int().min(0).max(2147483647).optional(),
32176
+ density: external_exports.enum(["compact", "comfortable"]).optional(),
32177
+ mobileFullscreen: external_exports.boolean().optional()
32178
+ }).strict().optional(),
32179
+ behavior: external_exports.object({
32180
+ startOpen: external_exports.boolean().optional(),
32181
+ closeOnEscape: external_exports.boolean().optional(),
32182
+ closeOnOutsideClick: external_exports.boolean().optional(),
32183
+ showLauncher: external_exports.boolean().optional(),
32184
+ showHeader: external_exports.boolean().optional(),
32185
+ showAvatars: external_exports.boolean().optional(),
32186
+ showTimestamps: external_exports.boolean().optional(),
32187
+ showPoweredBy: external_exports.boolean().optional()
32188
+ }).strict().optional(),
32189
+ labels: labelsSchema.optional(),
32190
+ presentation: presentationSchema.optional(),
32191
+ suggestedPrompts: external_exports.array(external_exports.string().trim().min(1).max(240)).max(8).optional(),
32192
+ privacyUrl: httpsUrlSchema.optional(),
32193
+ termsUrl: httpsUrlSchema.optional(),
32194
+ locale: external_exports.string().trim().min(2).max(35).optional(),
32195
+ direction: external_exports.enum(["ltr", "rtl", "auto"]).optional()
32196
+ }).strict();
32197
+ var assistantConfigurationSchema = external_exports.object({ branding: brandingSchema.optional(), assistant: assistantUiSchema.optional() }).strict();
32198
+ function parseAssistantConfiguration(value) {
32199
+ const parsed = assistantConfigurationSchema.safeParse(value);
32200
+ return parsed.success ? parsed.data : void 0;
32201
+ }
32202
+ function isHttpsUrl2(value) {
32203
+ try {
32204
+ return new URL(value).protocol === "https:";
32205
+ } catch {
32206
+ return false;
32207
+ }
32208
+ }
32209
+ function isSecureBrowserAssetUrl(value) {
32210
+ try {
32211
+ const url2 = new URL(value);
32212
+ if (url2.protocol === "https:") return true;
32213
+ if (url2.protocol !== "http:") return false;
32214
+ return url2.hostname === "localhost" || url2.hostname === "127.0.0.1" || url2.hostname === "[::1]";
32215
+ } catch {
32216
+ return false;
32217
+ }
32218
+ }
32219
+
32220
+ // src/element-public-configuration-controller.ts
32221
+ var AssistantElementPublicConfigurationController = class {
32222
+ #source;
32223
+ #apply;
32224
+ #loadingChanged;
32225
+ #generation = 0;
32226
+ #bootstrap;
32227
+ #abort;
32228
+ constructor(source, apply2, loadingChanged) {
32229
+ this.#source = source;
32230
+ this.#apply = apply2;
32231
+ this.#loadingChanged = loadingChanged;
32232
+ }
32233
+ connect() {
32234
+ this.#restart();
32235
+ }
32236
+ refresh() {
32237
+ this.#restart();
32238
+ }
32239
+ disconnect() {
32240
+ this.#generation += 1;
32241
+ this.#abort?.abort();
32242
+ this.#abort = void 0;
32243
+ this.#bootstrap = void 0;
32244
+ }
32245
+ #restart() {
32246
+ this.disconnect();
32247
+ this.#prime();
32248
+ }
32249
+ #prime() {
32250
+ const source = this.#source();
32251
+ if (!source.embedId || this.#bootstrap) return;
32252
+ const generation = this.#generation;
32253
+ const abort = new AbortController();
32254
+ this.#abort = abort;
32255
+ const fetcher = source.fetch ?? ((input, init) => globalThis.fetch(input, init));
32256
+ this.#loadingChanged(true);
32257
+ const bootstrap = Promise.resolve().then(
32258
+ () => fetcher(publicConfigurationUrl(source.serviceUrl, source.embedId), {
32259
+ method: "GET",
32260
+ headers: { accept: "application/json" },
32261
+ credentials: "omit",
32262
+ cache: "no-cache",
32263
+ signal: abort.signal
32264
+ })
32265
+ ).then(async (response) => {
32266
+ if (!response.ok) return;
32267
+ const value = await response.json();
32268
+ if (generation !== this.#generation || !isRecord6(value)) {
32269
+ return;
32270
+ }
32271
+ const configuration = parseAssistantConfiguration(value.configuration);
32272
+ if (configuration !== void 0) this.#apply(configuration);
32273
+ }).catch(() => void 0).finally(() => {
32274
+ if (generation === this.#generation) this.#loadingChanged(false);
32275
+ if (this.#bootstrap === bootstrap) {
32276
+ this.#bootstrap = void 0;
32277
+ this.#abort = void 0;
32278
+ }
32279
+ });
32280
+ this.#bootstrap = bootstrap;
32281
+ }
32282
+ };
32283
+ function isRecord6(value) {
32284
+ return typeof value === "object" && value !== null && !Array.isArray(value);
32285
+ }
32286
+
31789
32287
  // src/element-scroll-controller.ts
31790
32288
  var AssistantElementScrollController = class {
31791
32289
  #region;
@@ -31915,44 +32413,69 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
31915
32413
  *, *::before, *::after { box-sizing: border-box; }
31916
32414
  .visually-hidden { position: absolute !important; width: 1px !important; height: 1px !important; padding: 0 !important; margin: -1px !important; overflow: hidden !important; clip: rect(0, 0, 0, 0) !important; white-space: nowrap !important; border: 0 !important; }
31917
32415
  .visually-hidden[hidden] { display: none !important; }
31918
- :host { color-scheme: light dark; font-family: var(--ns-assistant-font-family, var(--ns-assistant-default-font-family)); font-size: var(--ns-assistant-base-font-size, var(--ns-assistant-default-base-font-size)); line-height: var(--ns-assistant-line-height, var(--ns-assistant-default-line-height)); z-index: var(--ns-assistant-z-index, var(--ns-assistant-default-z-index)); -webkit-font-smoothing: antialiased; }
31919
- :host([data-mode="floating"]) { position: fixed; bottom: 20px; right: 20px; }
31920
- :host([data-mode="floating"][data-position="bottom-left"]) { right: auto; left: 20px; }
32416
+ :host { --ns-assistant-halo-launcher-action: #f4f4f5; --ns-assistant-halo-launcher-action-hover: #e4e4e7; --ns-assistant-halo-launcher-border: rgba(0,0,0,.04); --ns-assistant-halo-launcher-shadow: 0 1px 8px rgba(0,0,0,.04); --ns-assistant-halo-launcher-shadow-hover: 0 2px 12px rgba(0,0,0,.06); --ns-assistant-halo-send-button: #e4e4e7; --ns-assistant-halo-send-button-text: #09090b; box-sizing: border-box; color-scheme: light dark; font-family: var(--ns-assistant-font-family, var(--ns-assistant-default-font-family)); font-size: var(--ns-assistant-base-font-size, var(--ns-assistant-default-base-font-size)); line-height: var(--ns-assistant-line-height, var(--ns-assistant-default-line-height)); z-index: var(--ns-assistant-z-index, var(--ns-assistant-default-z-index)); -webkit-font-smoothing: antialiased; }
32417
+ :host([data-theme="dark"]) { --ns-assistant-halo-launcher-action: #3f3f46; --ns-assistant-halo-launcher-action-hover: #52525b; --ns-assistant-halo-launcher-border: rgba(255,255,255,.1); --ns-assistant-halo-launcher-shadow: 0 4px 20px rgba(0,0,0,.3); --ns-assistant-halo-launcher-shadow-hover: 0 6px 24px rgba(0,0,0,.4); --ns-assistant-halo-send-button: #3f3f46; --ns-assistant-halo-send-button-text: #fff; }
32418
+ :host([data-mode="floating"]) { position: fixed; }
32419
+ :host([data-mode="floating"][open]) { width: min(var(--ns-assistant-panel-width, var(--ns-assistant-default-panel-width)), 100vw); }
31921
32420
  button { font: inherit; }
31922
32421
  button, textarea, input, select { -webkit-tap-highlight-color: transparent; }
31923
- .launcher { display: grid; place-items: center; width: 48px; height: 48px; border: 1px solid var(--ns-assistant-launcher-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); border-radius: 999px; color: var(--ns-assistant-launcher-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-launcher, var(--ns-assistant-panel, var(--ns-assistant-default-panel))); box-shadow: 0 8px 28px rgba(0,0,0,.14); cursor: pointer; transition: transform .24s cubic-bezier(.25,1,.5,1), box-shadow .2s ease; }
31924
- .launcher:hover { transform: translateY(-2px) scale(1.03); box-shadow: 0 8px 26px rgba(0,0,0,.16); }
31925
- .launcher img { width: 28px; height: 28px; border-radius: 50%; object-fit: contain; }
31926
- .panel { display: none; flex-direction: column; width: min(var(--ns-assistant-panel-width, var(--ns-assistant-default-panel-width)), calc(100vw - 40px)); min-height: var(--ns-assistant-min-height, var(--ns-assistant-default-min-height)); max-height: min(var(--ns-assistant-max-height, var(--ns-assistant-default-max-height)), calc(100vh - 40px)); overflow: hidden; color: var(--ns-assistant-panel-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-panel, var(--ns-assistant-default-panel)); border: 1px solid var(--ns-assistant-panel-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); border-radius: var(--ns-assistant-panel-radius, var(--ns-assistant-default-panel-radius)); box-shadow: var(--ns-assistant-shadow, var(--ns-assistant-default-shadow)); transform-origin: bottom right; isolation: isolate; animation: halo-panel-in .28s cubic-bezier(.23,1,.32,1) both; }
32422
+ .launcher { display: flex; align-items: center; justify-content: center; gap: 12px; width: max-content; min-height: 44px; padding: 10px 14px; color: var(--ns-assistant-launcher-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-launcher, color-mix(in srgb, var(--ns-assistant-panel, var(--ns-assistant-default-panel)) 50%, transparent)); border: 1px solid var(--ns-assistant-launcher-border, var(--ns-assistant-halo-launcher-border)); border-radius: 999px; box-shadow: var(--ns-assistant-halo-launcher-shadow), -6px 0 18px color-mix(in srgb, var(--ns-assistant-accent, var(--ns-assistant-default-accent)) 20%, transparent), 6px 0 18px color-mix(in srgb, var(--ns-assistant-accent, var(--ns-assistant-default-accent)) 20%, transparent), 0 0 40px color-mix(in srgb, var(--ns-assistant-accent, var(--ns-assistant-default-accent)) 10%, transparent); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); transition: width .5s cubic-bezier(.25,1,.5,1), height .5s cubic-bezier(.25,1,.5,1), padding .5s cubic-bezier(.25,1,.5,1), gap .35s cubic-bezier(.25,1,.5,1), transform .6s cubic-bezier(.25,1,.5,1), background-color .3s ease, box-shadow .3s ease; }
32423
+ :host([data-presentation-ready]) .launcher { padding: 10px 12px; }
32424
+ .launcher[hidden] { display: none; }
32425
+ .launcher:hover { transform: scale(1.02); box-shadow: var(--ns-assistant-halo-launcher-shadow-hover), -6px 0 18px color-mix(in srgb, var(--ns-assistant-accent, var(--ns-assistant-default-accent)) 20%, transparent), 6px 0 18px color-mix(in srgb, var(--ns-assistant-accent, var(--ns-assistant-default-accent)) 20%, transparent); }
32426
+ .launcher-trigger, .launcher-form { min-width: 0; margin: 0; padding: 0; border: 0; background: transparent; font: inherit; }
32427
+ .launcher-trigger { display: flex; align-items: center; gap: 12px; min-height: 28px; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); cursor: text; }
32428
+ .launcher-label { padding-left: 6px; white-space: nowrap; font-size: 15px; line-height: 20px; }
32429
+ .launcher-arrow, .launcher-send { position: relative; display: grid; width: 28px; height: 28px; flex: 0 0 28px; place-items: center; border: 0; border-radius: 50%; color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background: var(--ns-assistant-launcher-action, var(--ns-assistant-halo-launcher-action)); cursor: pointer; }
32430
+ .launcher-arrow:hover, .launcher-send:hover { background: var(--ns-assistant-launcher-action-hover, var(--ns-assistant-halo-launcher-action-hover)); }
32431
+ .launcher-arrow::before, .launcher-send::before { content: ''; width: 16px; height: 16px; background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 19V5M5 12l7-7 7 7' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 19V5M5 12l7-7 7 7' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; }
32432
+ .launcher-form { display: none; flex: 1; align-items: center; gap: 12px; opacity: 0; pointer-events: none; }
32433
+ .launcher-input { width: 100%; min-width: 0; height: 28px; padding: 0 0 0 6px; color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background: transparent; border: 0; outline: 0; box-shadow: none; appearance: none; font: inherit; font-size: 16px; line-height: 20px; }
32434
+ .launcher-input::placeholder { color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); }
32435
+ :host([launcher-expanded]) .launcher { width: min(400px, calc(100vw - 40px)); justify-content: flex-start; }
32436
+ :host([launcher-expanded]) .launcher-trigger { display: none; }
32437
+ :host([launcher-expanded]) .launcher-form { display: flex; opacity: 1; pointer-events: auto; }
32438
+ :host([data-launcher-style="bubble"]) .launcher { gap: 0; min-height: 0; padding: 6px; cursor: pointer; }
32439
+ :host([data-launcher-style="bubble"]) .launcher-trigger { position: absolute; inset: 0; display: block; width: 100%; height: 100%; cursor: pointer; }
32440
+ :host([data-launcher-style="bubble"]) .launcher-label, :host([data-launcher-style="bubble"]) .launcher-arrow, :host([data-launcher-style="bubble"]) .launcher-form { display: none; }
32441
+ :host([data-launcher-style="bubble"]) .launcher-visual { width: 32px; height: 32px; flex-basis: 32px; }
32442
+ .launcher-loader { display: none; width: 16px; height: 16px; flex: 0 0 16px; border: 2px solid var(--ns-assistant-divider, var(--ns-assistant-default-divider)); border-top-color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); border-radius: 50%; animation: halo-spin .8s linear infinite; }
32443
+ :host([data-session-state="loading"]:not([data-presentation-ready])) .launcher-loader, :host([data-public-configuration-loading]:not([data-presentation-ready])) .launcher-loader { display: block; }
32444
+ :host([data-session-state="loading"]:not([data-presentation-ready])) .launcher > :not(.launcher-loader):not([data-session-status]), :host([data-public-configuration-loading]:not([data-presentation-ready])) .launcher > :not(.launcher-loader):not([data-session-status]) { display: none; }
32445
+ .panel { display: none; flex-direction: column; width: 100%; max-width: 970px; height: min(85dvh, var(--ns-assistant-max-height, var(--ns-assistant-default-max-height)), calc(100dvh - 40px)); min-height: min(var(--ns-assistant-min-height, var(--ns-assistant-default-min-height)), calc(100dvh - 40px)); max-height: min(var(--ns-assistant-max-height, var(--ns-assistant-default-max-height)), calc(100dvh - 40px)); overflow: hidden; color: var(--ns-assistant-panel-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-panel, var(--ns-assistant-default-panel)); border: 1px solid var(--ns-assistant-panel-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); border-radius: var(--ns-assistant-panel-radius, var(--ns-assistant-default-panel-radius)); box-shadow: var(--ns-assistant-shadow, var(--ns-assistant-default-shadow)); transform-origin: bottom center; isolation: isolate; animation: halo-panel-in .3s ease both; }
32446
+ :host([data-mode="floating"][open]) .panel { width: calc(100% - 40px); margin-inline: 20px; }
31927
32447
  :host([open][data-presentation-ready]) .panel { display: flex; }
31928
32448
  .panel { position: relative; }
31929
32449
  :host([open][data-presentation-ready]) .launcher { display: none; }
31930
32450
  :host([open]:not([data-presentation-ready])) .launcher { cursor: progress; opacity: .72; transform: none; }
31931
- header { display: flex; flex: 0 0 auto; gap: 10px; align-items: center; min-height: 64px; padding: 12px 18px; color: var(--ns-assistant-header-text, inherit); background: var(--ns-assistant-header, transparent); border-bottom: 1px solid color-mix(in srgb, var(--ns-assistant-header-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))) 78%, transparent); }
32451
+ header { display: flex; flex: 0 0 auto; gap: 10px; align-items: center; min-height: 64px; padding: 16px 20px; color: var(--ns-assistant-header-text, inherit); background: var(--ns-assistant-header, transparent); border-bottom: 1px solid var(--ns-assistant-header-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); }
31932
32452
  header strong { flex: 1; font-size: 16px; font-weight: 600; letter-spacing: 0; }
31933
32453
  .brand-logo { display: block; max-width: 120px; max-height: 28px; object-fit: contain; }
31934
32454
  .close, .send { display: grid; place-items: center; border: 0; border-radius: var(--ns-assistant-button-radius, var(--ns-assistant-default-button-radius)); cursor: pointer; }
31935
- .close { position: relative; width: 44px; height: 44px; padding: 0; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); background: transparent; transition: background .15s ease, color .15s ease, transform .15s ease; }
31936
- .close::before { content: ''; width: 18px; height: 18px; background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m6 6 12 12M18 6 6 18' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m6 6 12 12M18 6 6 18' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat; }
32455
+ .close { position: relative; width: 44px; height: 44px; margin: -6px; padding: 0; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); background: transparent; transition: background .15s ease, color .15s ease, transform .15s ease; }
32456
+ .close::before { content: ''; width: 20px; height: 20px; background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m6 6 12 12M18 6 6 18' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m6 6 12 12M18 6 6 18' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat; }
31937
32457
  .close:hover { color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background: var(--ns-assistant-elevated, var(--ns-assistant-default-elevated)); }
31938
32458
  .close:active { transform: scale(.96); }
31939
- .welcome { flex: 0 0 auto; padding: 30px 22px 18px; }
32459
+ .welcome { flex: 0 0 auto; padding: 24px 20px 8px; }
31940
32460
  .welcome h2 { margin: 0; font-size: 1.35em; line-height: 1.25; letter-spacing: 0; }
31941
32461
  .welcome p { max-width: 42ch; margin: 7px 0 0; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); }
31942
- :host([has-messages]) .welcome, :host([has-messages]) .suggested-prompts { display: none; }
31943
- .suggested-prompts { display: flex; flex: 0 0 auto; flex-wrap: wrap; gap: 8px; padding: 0 20px 16px; }
32462
+ .welcome:has(.empty-state[hidden]) { display: none; }
32463
+ :host([has-messages]) .welcome { display: none; }
32464
+ .input-section { flex: 0 0 auto; padding: 8px 16px 16px; }
32465
+ .suggested-prompts { display: flex; flex: 0 0 auto; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
31944
32466
  .suggested-prompts:empty { display: none; }
31945
- .suggested-prompts button { min-height: 44px; padding: 8px 14px; color: var(--ns-assistant-suggestion-text, var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text))); background: var(--ns-assistant-suggestion, color-mix(in srgb, var(--ns-assistant-input, var(--ns-assistant-default-input)) 58%, transparent)); border: 1px solid var(--ns-assistant-suggestion-border, color-mix(in srgb, var(--ns-assistant-divider, var(--ns-assistant-default-divider)) 82%, transparent)); border-radius: 999px; cursor: pointer; font-size: .86em; transition: background .2s ease, color .2s ease, border-color .2s ease, transform .2s ease; }
31946
- .suggested-prompts button:hover { color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background: var(--ns-assistant-elevated, var(--ns-assistant-default-elevated)); transform: translateY(-1px); }
32467
+ .suggested-prompts button { position: relative; display: inline-flex; align-items: center; padding: 6px 12px; color: var(--ns-assistant-suggestion-text, var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text))); background: var(--ns-assistant-suggestion, transparent); border: 1px solid var(--ns-assistant-suggestion-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); border-radius: 999px; cursor: pointer; font-size: 12px; white-space: nowrap; transition: background .2s ease, color .2s ease; }
32468
+ .suggested-prompts button::before { content: ''; position: absolute; inset: -6px -2px; }
32469
+ .suggested-prompts button:hover { color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background: var(--ns-assistant-elevated, var(--ns-assistant-default-elevated)); }
31947
32470
  .messages-region { position: relative; display: flex; flex: 1 1 auto; min-height: 0; overflow: hidden; }
31948
32471
  .messages-region::before, .messages-region::after { content: ''; position: absolute; right: 0; left: 0; z-index: 1; height: 18px; pointer-events: none; opacity: 0; transition: opacity .18s ease; }
31949
32472
  .messages-region::before { top: 0; background: linear-gradient(to bottom, color-mix(in srgb, var(--ns-assistant-panel, var(--ns-assistant-default-panel)) 92%, transparent), transparent); }
31950
32473
  .messages-region::after { bottom: 0; background: linear-gradient(to top, color-mix(in srgb, var(--ns-assistant-panel, var(--ns-assistant-default-panel)) 92%, transparent), transparent); }
31951
32474
  .messages-region[data-can-scroll-up]::before, .messages-region[data-can-scroll-down]::after { opacity: 1; }
31952
- .messages { flex: 1 1 auto; width: 100%; min-height: 0; padding: 18px 20px 24px; overflow-y: auto; background: var(--ns-assistant-canvas, transparent); overscroll-behavior: contain; scroll-behavior: smooth; }
32475
+ .messages { flex: 1 1 auto; width: 100%; min-height: 0; padding: 16px 20px; overflow-y: auto; background: var(--ns-assistant-canvas, transparent); overscroll-behavior: contain; scroll-behavior: smooth; }
31953
32476
  .messages::-webkit-scrollbar { width: 6px; }
31954
32477
  .messages::-webkit-scrollbar-thumb { background: var(--ns-assistant-divider, var(--ns-assistant-default-divider)); border-radius: 999px; }
31955
- .message { width: fit-content; max-width: 88%; margin: 0 0 14px; padding: 0; border-radius: var(--ns-assistant-card-radius, var(--ns-assistant-default-card-radius)); background: transparent; white-space: pre-wrap; animation: halo-message-in .2s ease both; }
32478
+ .message { width: fit-content; max-width: 88%; margin: 0 0 12px; padding: 0; border-radius: var(--ns-assistant-card-radius, var(--ns-assistant-default-card-radius)); background: transparent; white-space: pre-wrap; animation: halo-message-in .2s ease both; }
31956
32479
  .message > span, .message > .markdown { overflow-wrap: anywhere; }
31957
32480
  .message .avatar { float: left; width: 24px; height: 24px; margin-right: 9px; border-radius: 50%; object-fit: cover; }
31958
32481
  .message time { display: block; margin-top: 4px; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); font-size: .75em; line-height: 1.2; }
@@ -31965,7 +32488,7 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
31965
32488
  .new-messages { position: absolute; left: 50%; bottom: 14px; z-index: 2; width: 44px; height: 44px; padding: 0; color: var(--ns-assistant-secondary-button-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-secondary-button, color-mix(in srgb, var(--ns-assistant-input, var(--ns-assistant-default-input)) 92%, transparent)); border: 1px solid var(--ns-assistant-secondary-button-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); border-radius: var(--ns-assistant-button-radius, var(--ns-assistant-default-button-radius)); box-shadow: 0 8px 24px rgba(0,0,0,.12); transform: translateX(-50%); cursor: pointer; }
31966
32489
  .new-messages::before { content: ''; display: block; width: 18px; height: 18px; margin: auto; background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m6 9 6 6 6-6' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m6 9 6 6 6-6' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; }
31967
32490
  .message.assistant { max-width: 100%; color: var(--ns-assistant-assistant-message-text, inherit); background: var(--ns-assistant-assistant-message, transparent); border: 1px solid var(--ns-assistant-assistant-message-border, transparent); }
31968
- .message.user { display: grid; max-width: 85%; justify-items: start; gap: 3px; margin-left: auto; padding: 10px 16px 8px; color: var(--ns-assistant-user-message-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-user-message, var(--ns-assistant-elevated, var(--ns-assistant-default-elevated))); border: 1px solid var(--ns-assistant-user-message-border, transparent); border-radius: var(--ns-assistant-card-radius, var(--ns-assistant-default-card-radius)); font-size: .94em; }
32491
+ .message.user { display: grid; max-width: 85%; justify-items: start; gap: 3px; margin-left: auto; padding: 10px 16px; color: var(--ns-assistant-user-message-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-user-message, var(--ns-assistant-elevated, var(--ns-assistant-default-elevated))); border: 1px solid var(--ns-assistant-user-message-border, transparent); border-radius: var(--ns-assistant-card-radius, var(--ns-assistant-default-card-radius)); font-size: 14px; }
31969
32492
  .message.user time { margin-top: 0; }
31970
32493
  .markdown { white-space: normal; }
31971
32494
  .markdown p { margin: 0 0 8px; }
@@ -32015,31 +32538,39 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
32015
32538
  .input-request input:focus-visible, .input-request select:focus-visible { border-color: var(--ns-assistant-focus, var(--ns-assistant-default-focus)); box-shadow: 0 0 0 2px var(--ns-assistant-focus, var(--ns-assistant-default-focus)); }
32016
32539
  .input-request .proposal-actions { margin-top: 2px; }
32017
32540
  ${ASSISTANT_APP_VIEW_CSS}
32018
- form { display: flex; flex: 0 0 auto; gap: 8px; align-items: center; min-height: 56px; margin: 8px 16px 16px; padding: 6px 6px 6px 16px; color: var(--ns-assistant-composer-text, inherit); border: 1px solid var(--ns-assistant-composer-border, color-mix(in srgb, var(--ns-assistant-divider, var(--ns-assistant-default-divider)) 86%, transparent)); border-radius: var(--ns-assistant-input-radius, var(--ns-assistant-default-input-radius)); background: var(--ns-assistant-composer, color-mix(in srgb, var(--ns-assistant-input, var(--ns-assistant-default-input)) 92%, transparent)); box-shadow: 0 1px 2px rgba(0,0,0,.04), 0 8px 24px rgba(0,0,0,.035); transition: border-color .15s ease, box-shadow .15s ease; }
32019
- form:focus-within { box-shadow: inset 0 0 0 1px var(--ns-assistant-focus, var(--ns-assistant-default-focus)), 0 0 0 2px var(--ns-assistant-focus, var(--ns-assistant-default-focus)); }
32541
+ .composer { display: flex; flex: 0 0 auto; gap: 8px; align-items: center; min-height: 44px; margin: 0; padding: 8px 8px 8px 16px; color: var(--ns-assistant-composer-text, inherit); border: 1px solid var(--ns-assistant-composer-border, transparent); border-radius: var(--ns-assistant-input-radius, var(--ns-assistant-default-input-radius)); background: var(--ns-assistant-composer, var(--ns-assistant-input, var(--ns-assistant-default-input))); transition: border-color .15s ease, box-shadow .15s ease; }
32542
+ .composer:focus-within { border-color: var(--ns-assistant-focus, var(--ns-assistant-default-focus)); box-shadow: 0 0 0 2px color-mix(in srgb, var(--ns-assistant-focus, var(--ns-assistant-default-focus)) 32%, transparent); }
32020
32543
  textarea { flex: 1; min-height: 24px; max-height: 120px; resize: none; padding: 0; color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background: transparent; border: 0; border-radius: 0; outline: 0; box-shadow: none; appearance: none; -webkit-appearance: none; font: inherit; font-size: 16px; line-height: 24px; }
32021
32544
  textarea::placeholder { color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); }
32022
32545
  textarea:focus, textarea:focus-visible { outline: none; box-shadow: none; }
32023
32546
  button:focus-visible { outline: 3px solid var(--ns-assistant-focus, var(--ns-assistant-default-focus)); outline-offset: 2px; }
32024
- .send { position: relative; display: block; width: 44px; height: 44px; flex: 0 0 44px; padding: 0; overflow: hidden; color: transparent; border-radius: 999px; background: var(--ns-assistant-primary-button, var(--ns-assistant-accent, var(--ns-assistant-default-accent))); font-size: 0; line-height: 0; transition: transform .15s ease, background .15s ease; }
32025
- .send::before { content: ''; position: absolute; top: 50%; left: 50%; width: 17px; height: 17px; background: var(--ns-assistant-primary-button-text, var(--ns-assistant-accent-text, var(--ns-assistant-default-accent-text))); transform: translate(-50%, -50%); -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 19V5M5 12l7-7 7 7' fill='none' stroke='black' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 19V5M5 12l7-7 7 7' fill='none' stroke='black' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; }
32026
- .send:hover { transform: scale(1.05); background: var(--ns-assistant-hover, color-mix(in srgb, var(--ns-assistant-primary-button, var(--ns-assistant-accent, var(--ns-assistant-default-accent))) 88%, var(--ns-assistant-primary-button-text, var(--ns-assistant-accent-text, var(--ns-assistant-default-accent-text))) 12%)); }
32547
+ .send { position: relative; display: block; width: 44px; height: 44px; flex: 0 0 44px; margin: -8px; padding: 0; overflow: visible; color: var(--ns-assistant-primary-button-text, var(--ns-assistant-halo-send-button-text)); border-radius: 999px; background: transparent; font-size: 0; line-height: 0; }
32548
+ .send::after { content: ''; position: absolute; top: 50%; left: 50%; z-index: 0; width: 28px; height: 28px; border-radius: 50%; background: var(--ns-assistant-primary-button, var(--ns-assistant-halo-send-button)); transform: translate(-50%, -50%); }
32549
+ .send::before { content: ''; position: absolute; top: 50%; left: 50%; z-index: 1; width: 16px; height: 16px; background: currentColor; transform: translate(-50%, -50%); -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 19V5M5 12l7-7 7 7' fill='none' stroke='black' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 19V5M5 12l7-7 7 7' fill='none' stroke='black' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; }
32550
+ .send:hover::after { background: var(--ns-assistant-hover, var(--ns-assistant-default-hover)); }
32027
32551
  :host([busy]) .send::before { width: 13px; height: 13px; border-radius: 3px; -webkit-mask: none; mask: none; }
32028
32552
  .send:disabled, textarea:disabled { opacity: .55; cursor: not-allowed; }
32029
- .legal { display: flex; gap: 12px; justify-content: center; padding: 0 12px 9px; font-size: .75em; }
32553
+ .legal { display: flex; gap: 12px; justify-content: center; padding: 0 12px 8px; font-size: .75em; }
32030
32554
  .legal:empty { display: none; }
32031
32555
  .legal a { color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); text-underline-offset: 2px; }
32556
+ .powered-by-row { display: flex; flex: 0 0 auto; justify-content: center; padding-bottom: 12px; }
32557
+ .powered-by-row[hidden] { display: none; }
32558
+ .powered-by { display: inline-flex; align-items: center; gap: 6px; margin: 0 auto 12px; padding: 0 16px; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); font-size: 11px; line-height: 1; text-decoration: none; opacity: .7; transition: opacity .12s ease, color .12s ease; }
32559
+ .powered-by:hover { color: var(--ns-assistant-text, var(--ns-assistant-default-text)); opacity: 1; }
32560
+ .powered-by-icon { display: inline-flex; width: 14px; height: 14px; }
32561
+ .powered-by-name { font-weight: 500; }
32032
32562
  ::slotted([slot="conversation-footer"]) { display: block; padding: 0 16px 12px; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); font-size: 11px; text-align: center; }
32033
- @keyframes halo-panel-in { from { opacity: 0; transform: translateY(14px) scale(.985); } to { opacity: 1; transform: none; } }
32563
+ @keyframes halo-panel-in { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: none; } }
32034
32564
  @keyframes halo-message-in { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: none; } }
32035
32565
  @keyframes halo-shimmer { from { background-position: 100% center; } to { background-position: 0 center; } }
32036
32566
  @keyframes halo-caret-blink { 50% { opacity: 0; } }
32567
+ @keyframes halo-spin { to { transform: rotate(360deg); } }
32037
32568
  :host([data-density="compact"]) .welcome { padding: 20px 18px 12px; }
32038
- @media (max-width: 640px) { :host([mobile-fullscreen][open]) { inset: 0; } :host([mobile-fullscreen][open]) .panel { width: 100vw; min-height: 100vh; max-height: 100vh; border: 0; border-radius: 0; } :host([mobile-fullscreen]) header { padding-top: max(12px, env(safe-area-inset-top)); padding-right: max(18px, env(safe-area-inset-right)); padding-left: max(18px, env(safe-area-inset-left)); } :host([mobile-fullscreen]) form { margin-right: max(16px, env(safe-area-inset-right)); margin-bottom: max(16px, env(safe-area-inset-bottom)); margin-left: max(16px, env(safe-area-inset-left)); } :host([mobile-fullscreen]) .legal, :host([mobile-fullscreen]) ::slotted([slot="conversation-footer"]) { padding-bottom: max(10px, env(safe-area-inset-bottom)); } }
32569
+ @media (max-width: 640px) { :host([mobile-fullscreen][open]) { inset: 0; width: 100vw; transform: none; } :host([mobile-fullscreen][open]) .panel { width: 100vw; max-width: none; height: 100dvh; min-height: 100dvh; max-height: 100dvh; margin: 0; border: 0; border-radius: 0; } :host([mobile-fullscreen]) header { padding-top: calc(16px + env(safe-area-inset-top)); padding-right: calc(20px + env(safe-area-inset-right)); padding-left: calc(20px + env(safe-area-inset-left)); } :host([mobile-fullscreen]) .messages { padding-right: calc(20px + env(safe-area-inset-right)); padding-left: calc(20px + env(safe-area-inset-left)); } :host([mobile-fullscreen]) .input-section { padding-right: calc(16px + env(safe-area-inset-right)); padding-bottom: calc(16px + env(safe-area-inset-bottom)); padding-left: calc(16px + env(safe-area-inset-left)); } :host([mobile-fullscreen]) .legal, :host([mobile-fullscreen]) ::slotted([slot="conversation-footer"]) { padding-bottom: max(10px, env(safe-area-inset-bottom)); } }
32039
32570
  @media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; } .messages { scroll-behavior: auto; } .message.assistant.streaming .markdown::after { animation: none; } }
32040
32571
  @media (forced-colors: active) { .message.thinking > span { color: CanvasText; background: none; } }
32041
32572
  @media (hover: none) { .message-copy { opacity: 1; } }
32042
- @media (max-width: 560px) { :host([data-mode="floating"]) { inset: auto 12px 12px; } :host([open]) .panel { width: calc(100vw - 24px); max-height: calc(100vh - 24px); } }
32573
+ @media (max-width: 560px) { :host([data-mode="floating"]:not([open])) { bottom: 20px; } :host([open]:not([mobile-fullscreen])) .panel { width: calc(100vw - 40px); max-height: calc(100dvh - 40px); } }
32043
32574
  </style>`;
32044
32575
 
32045
32576
  // src/host-appearance.ts
@@ -32148,6 +32679,7 @@ function syncAssistantPresentation(host, root, appearance, mode, sessionState) {
32148
32679
  host.dataset.panelSurface = presentation.panel.surface;
32149
32680
  host.dataset.panelElevation = presentation.panel.elevation;
32150
32681
  host.dataset.panelBorder = presentation.panel.border;
32682
+ host.dataset.launcherStyle = presentation.launcher.style;
32151
32683
  host.dataset.launcherEffect = presentation.launcher.effect;
32152
32684
  host.dataset.messageUserStyle = presentation.messages.userStyle;
32153
32685
  host.dataset.messageAssistantStyle = presentation.messages.assistantStyle;
@@ -32160,11 +32692,11 @@ function syncAssistantPresentation(host, root, appearance, mode, sessionState) {
32160
32692
  }
32161
32693
  host.style.setProperty(
32162
32694
  "--ns-assistant-presentation-launcher-size",
32163
- presentation.launcher.size === "lg" ? "56px" : "48px"
32695
+ presentation.launcher.size === "lg" ? "56px" : "44px"
32164
32696
  );
32165
32697
  host.style.setProperty(
32166
32698
  "--ns-assistant-presentation-panel-background",
32167
- presentation.panel.surface === "solid" ? "var(--ns-assistant-panel, var(--ns-assistant-default-panel))" : "color-mix(in srgb, var(--ns-assistant-panel, var(--ns-assistant-default-panel)) 88%, transparent)"
32699
+ presentation.panel.surface === "solid" ? "var(--ns-assistant-panel, var(--ns-assistant-default-panel))" : "color-mix(in srgb, var(--ns-assistant-panel, var(--ns-assistant-default-panel)) 50%, transparent)"
32168
32700
  );
32169
32701
  host.style.setProperty(
32170
32702
  "--ns-assistant-presentation-shadow",
@@ -32172,7 +32704,7 @@ function syncAssistantPresentation(host, root, appearance, mode, sessionState) {
32172
32704
  );
32173
32705
  host.style.setProperty(
32174
32706
  "--ns-assistant-presentation-border",
32175
- panelBorder(presentation.panel.border)
32707
+ panelBorder(presentation.panel.border, mode)
32176
32708
  );
32177
32709
  replaceFallback(root, "launcher-icon", [launcherVisual(appearance, mode, sessionState)]);
32178
32710
  const accessibleStatus = root.querySelector("[data-session-status]");
@@ -32185,7 +32717,7 @@ function syncAssistantPresentation(host, root, appearance, mode, sessionState) {
32185
32717
  replaceFallback(root, "empty-state", [emptyState(appearance)]);
32186
32718
  replaceFallback(root, "composer-leading", composerLeading(appearance, mode));
32187
32719
  replaceFallback(root, "conversation-footer", []);
32188
- const form = root.querySelector("form");
32720
+ const form = root.querySelector(".composer");
32189
32721
  if (form) form.dataset.shape = presentation.composer.shape;
32190
32722
  const send = root.querySelector(".send");
32191
32723
  if (send) send.dataset.icon = presentation.composer.sendIcon;
@@ -32205,18 +32737,21 @@ function panelShadow(elevation) {
32205
32737
  }
32206
32738
  return "var(--ns-assistant-default-shadow)";
32207
32739
  }
32208
- function panelBorder(border) {
32740
+ function panelBorder(border, mode) {
32209
32741
  if (border === "strong") {
32210
32742
  return "1px solid var(--ns-assistant-divider, var(--ns-assistant-default-divider))";
32211
32743
  }
32212
- return "1px solid color-mix(in srgb, var(--ns-assistant-divider, var(--ns-assistant-default-divider)) 74%, transparent)";
32744
+ const opacity = mode === "light" ? 60 : 100;
32745
+ return `1px solid color-mix(in srgb, var(--ns-assistant-divider, var(--ns-assistant-default-divider)) ${opacity}%, transparent)`;
32213
32746
  }
32214
32747
  function launcherVisual(appearance, mode, sessionState) {
32215
32748
  const launcher = appearance.presentation.launcher;
32216
32749
  const visual = document.createElement("span");
32217
32750
  visual.className = "launcher-visual";
32218
32751
  visual.setAttribute("aria-hidden", "true");
32219
- visual.append(icon(launcher.icon, appearance, mode, "launcher-glyph"));
32752
+ const visualKind = launcher.icon === "brand-mark" && !(appearance.brand.mark[mode] ?? appearance.brand.logo[mode]) ? launcher.style === "bubble" ? "chat" : "none" : launcher.icon;
32753
+ visual.hidden = visualKind === "none";
32754
+ visual.append(icon(visualKind, appearance, mode, "launcher-glyph"));
32220
32755
  if (launcher.status === "session") {
32221
32756
  const status = document.createElement("span");
32222
32757
  status.className = "launcher-status";
@@ -32266,9 +32801,12 @@ function headerBadge(appearance) {
32266
32801
  function emptyState(appearance) {
32267
32802
  const section = document.createElement("section");
32268
32803
  section.className = "empty-state";
32269
- const heading = document.createElement("h2");
32270
- heading.textContent = appearance.labels.welcomeHeading;
32271
- section.append(heading);
32804
+ section.hidden = !appearance.labels.welcomeHeading && !appearance.labels.welcomeMessage;
32805
+ if (appearance.labels.welcomeHeading) {
32806
+ const heading = document.createElement("h2");
32807
+ heading.textContent = appearance.labels.welcomeHeading;
32808
+ section.append(heading);
32809
+ }
32272
32810
  const description = appearance.labels.welcomeMessage;
32273
32811
  if (description) {
32274
32812
  const paragraph = document.createElement("p");
@@ -32295,7 +32833,7 @@ function toneIndicator(tone) {
32295
32833
  return indicator;
32296
32834
  }
32297
32835
  function icon(kind, appearance, mode, className) {
32298
- const mark = appearance.brand.mark[mode];
32836
+ const mark = appearance.brand.mark[mode] ?? appearance.brand.logo[mode];
32299
32837
  if (kind === "brand-mark" && mark) {
32300
32838
  const image = document.createElement("img");
32301
32839
  image.className = className;
@@ -32347,11 +32885,17 @@ function applyAssistantElementTheme(input) {
32347
32885
  var presentationStyles = `<style>
32348
32886
  :host([data-mode="floating"]) {
32349
32887
  bottom: var(--ns-assistant-edge-offset, var(--ns-assistant-default-edge-offset));
32350
- right: var(--ns-assistant-edge-offset, var(--ns-assistant-default-edge-offset));
32888
+ left: 50%;
32889
+ transform: translateX(-50%);
32351
32890
  }
32352
32891
  :host([data-mode="floating"][data-position="bottom-left"]) {
32353
- right: auto;
32354
32892
  left: var(--ns-assistant-edge-offset, var(--ns-assistant-default-edge-offset));
32893
+ transform: none;
32894
+ }
32895
+ :host([data-mode="floating"][data-position="bottom-right"]) {
32896
+ right: var(--ns-assistant-edge-offset, var(--ns-assistant-default-edge-offset));
32897
+ left: auto;
32898
+ transform: none;
32355
32899
  }
32356
32900
  .panel {
32357
32901
  background: var(--ns-assistant-panel-background, var(--ns-assistant-presentation-panel-background));
@@ -32368,22 +32912,26 @@ var presentationStyles = `<style>
32368
32912
 
32369
32913
  .launcher {
32370
32914
  position: relative;
32371
- width: var(--ns-assistant-launcher-size, var(--ns-assistant-presentation-launcher-size));
32372
- height: var(--ns-assistant-launcher-size, var(--ns-assistant-presentation-launcher-size));
32373
32915
  border-radius: var(--ns-assistant-launcher-radius, var(--ns-assistant-default-launcher-radius));
32374
32916
  isolation: isolate;
32375
32917
  }
32918
+ :host([data-launcher-style="bubble"]) .launcher {
32919
+ width: var(--ns-assistant-launcher-size, var(--ns-assistant-presentation-launcher-size));
32920
+ height: var(--ns-assistant-launcher-size, var(--ns-assistant-presentation-launcher-size));
32921
+ }
32376
32922
  :host([data-launcher-effect="pulse"]) .launcher {
32377
32923
  animation: assistant-launcher-pulse 2s ease-in-out infinite;
32378
32924
  }
32379
32925
  .launcher-visual {
32380
32926
  position: relative;
32381
32927
  display: grid;
32382
- width: 100%;
32383
- height: 100%;
32928
+ width: 28px;
32929
+ height: 28px;
32930
+ flex: 0 0 28px;
32384
32931
  place-items: center;
32385
32932
  border-radius: inherit;
32386
32933
  }
32934
+ .launcher-visual[hidden] { display: none; }
32387
32935
  .launcher-glyph, .composer-leading-glyph {
32388
32936
  display: block;
32389
32937
  width: 18px;
@@ -32411,10 +32959,28 @@ var presentationStyles = `<style>
32411
32959
  -webkit-mask: none;
32412
32960
  mask: none;
32413
32961
  }
32962
+ .launcher-visual .launcher-glyph:is(img) {
32963
+ width: 28px;
32964
+ height: 28px;
32965
+ border-radius: 50%;
32966
+ filter: grayscale(100%);
32967
+ opacity: .6;
32968
+ transition: width .5s cubic-bezier(.25,1,.5,1), height .5s cubic-bezier(.25,1,.5,1), filter .5s cubic-bezier(.25,1,.5,1), opacity .5s cubic-bezier(.25,1,.5,1);
32969
+ }
32970
+ .launcher:hover .launcher-glyph:is(img), :host([launcher-expanded]) .launcher-glyph:is(img) {
32971
+ filter: none;
32972
+ opacity: 1;
32973
+ }
32974
+ :host([data-launcher-style="bubble"]) .launcher-glyph:is(img) {
32975
+ width: 32px;
32976
+ height: 32px;
32977
+ filter: none;
32978
+ opacity: 1;
32979
+ }
32414
32980
  .launcher-status {
32415
32981
  position: absolute;
32416
- right: 1px;
32417
- bottom: 1px;
32982
+ right: -1px;
32983
+ bottom: -1px;
32418
32984
  width: 10px;
32419
32985
  height: 10px;
32420
32986
  border: 2px solid var(--ns-assistant-panel, var(--ns-assistant-default-panel));
@@ -32543,7 +33109,6 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32543
33109
  #conversationGeneration = 0;
32544
33110
  #messages;
32545
33111
  #thinking;
32546
- #media;
32547
33112
  #context;
32548
33113
  #modelContext;
32549
33114
  #pageContext;
@@ -32555,11 +33120,17 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32555
33120
  () => this.#primeSession(),
32556
33121
  () => this.focusComposer()
32557
33122
  );
33123
+ #publicConfiguration = new AssistantElementPublicConfigurationController(
33124
+ () => ({ embedId: this.embedId, serviceUrl: this.serviceUrl, fetch: this.#fetch }),
33125
+ (configuration) => this.#applyConfiguration(configuration),
33126
+ (loading) => this.#setPublicConfigurationLoading(loading)
33127
+ );
32558
33128
  #pendingUserEcho;
32559
33129
  #sessionState = "idle";
32560
33130
  #startOpenApplied = false;
32561
33131
  #readyDispatched = false;
32562
33132
  #turnInFlight = false;
33133
+ #fetch;
32563
33134
  #hostAppearance;
32564
33135
  #appearanceWarningKeys = /* @__PURE__ */ new Set();
32565
33136
  #appearanceStyleSnapshot = /* @__PURE__ */ new Map();
@@ -32569,6 +33140,17 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32569
33140
  embedId = "";
32570
33141
  /** Only for a dev or self-hosted service; the published snippet needs no origin. */
32571
33142
  serviceUrl = "";
33143
+ get fetch() {
33144
+ return this.#fetch;
33145
+ }
33146
+ set fetch(value) {
33147
+ if (this.#fetch === value) return;
33148
+ this.#fetch = value;
33149
+ if (this.#client) this.resetSession();
33150
+ if (!this.isConnected) return;
33151
+ if (this.embedId) this.#publicConfiguration.refresh();
33152
+ else this.#primeSession();
33153
+ }
32572
33154
  get appearance() {
32573
33155
  return this.#hostAppearance;
32574
33156
  }
@@ -32587,11 +33169,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32587
33169
  }
32588
33170
  return this.#appendMessage(role, text3);
32589
33171
  },
32590
- applyConfiguration: (configuration) => {
32591
- this.#appearance = resolveAppearance(configuration);
32592
- this.#syncAppearance();
32593
- this.#applyStartOpenPolicy();
32594
- },
33172
+ applyConfiguration: (configuration) => this.#applyConfiguration(configuration),
32595
33173
  labels: () => this.#appearance.labels,
32596
33174
  respond: (id, response) => this.respond(id, response),
32597
33175
  dispatchError: (detail) => this.#dispatchError(detail),
@@ -32607,7 +33185,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32607
33185
  client,
32608
33186
  sendMessage: (message) => this.sendMessage(message),
32609
33187
  updateModelContext: (update) => this.updateModelContext(update),
32610
- theme: this.#resolvedMode()
33188
+ theme: this.#environment.resolvedTheme()
32611
33189
  },
32612
33190
  {
32613
33191
  ...sandboxUrl === void 0 ? {} : { sandboxUrl },
@@ -32620,18 +33198,28 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32620
33198
  this.#revealLatest();
32621
33199
  }
32622
33200
  });
33201
+ #launcher = new AssistantElementLauncherController({
33202
+ host: this,
33203
+ appearance: () => this.#appearance,
33204
+ openPanel: () => this.open(),
33205
+ sendMessage: (message) => this.#sendGuarded(message)
33206
+ });
33207
+ #environment = new AssistantElementHostEnvironmentController({
33208
+ host: this,
33209
+ appearance: () => this.#appearance,
33210
+ applyTheme: () => this.#applyTheme(),
33211
+ close: () => this.#closeAndRestoreFocus()
33212
+ });
32623
33213
  connectedCallback() {
32624
33214
  if (!this.shadowRoot) this.attachShadow({ mode: "open" });
32625
33215
  if (!this.sessionEndpoint) this.sessionEndpoint = this.getAttribute("session-endpoint") ?? "";
32626
33216
  if (!this.embedId) this.embedId = this.getAttribute("embed-id") ?? "";
32627
33217
  if (!this.serviceUrl) this.serviceUrl = this.getAttribute("service-url") ?? "";
32628
33218
  if (!this.sessionEndpoint && !this.embedId) this.#presentationGate.reveal();
32629
- this.#media = globalThis.matchMedia?.("(prefers-color-scheme: dark)");
32630
- this.#media?.addEventListener("change", this.#handleSystemTheme);
32631
- document.addEventListener("keydown", this.#handleDocumentKeydown);
32632
- document.addEventListener("pointerdown", this.#handleDocumentPointerDown);
33219
+ this.#environment.connect();
32633
33220
  if (this.#appearance.behavior.startOpen) this.#applyStartOpenPolicy();
32634
33221
  this.#render();
33222
+ if (this.embedId) this.#publicConfiguration.connect();
32635
33223
  if (!this.#readyDispatched) {
32636
33224
  this.#readyDispatched = true;
32637
33225
  this.dispatchEvent(new CustomEvent("assistant-ready"));
@@ -32652,22 +33240,25 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32652
33240
  this.#clientEndpoint = "";
32653
33241
  this.#unsubscribeClient = void 0;
32654
33242
  this.#sessionBootstrap = void 0;
33243
+ this.#publicConfiguration.disconnect();
32655
33244
  this.#scroll.disconnect();
33245
+ this.#launcher.disconnect();
32656
33246
  this.#setBusy(false);
32657
- this.#media?.removeEventListener("change", this.#handleSystemTheme);
32658
- document.removeEventListener("keydown", this.#handleDocumentKeydown);
32659
- document.removeEventListener("pointerdown", this.#handleDocumentPointerDown);
33247
+ this.#environment.disconnect();
32660
33248
  }
32661
33249
  attributeChangedCallback(name21) {
32662
33250
  if (name21 === "theme") this.#applyTheme();
32663
33251
  if (name21 === "open") this.#presentationGate.syncOpenState();
32664
33252
  }
32665
33253
  open() {
33254
+ this.#launcher.collapse(true);
32666
33255
  this.setAttribute("open", "");
33256
+ if (this.hasAttribute("data-presentation-ready")) queueMicrotask(() => this.focusComposer());
32667
33257
  this.dispatchEvent(new CustomEvent("assistant-open"));
32668
33258
  }
32669
33259
  close() {
32670
33260
  this.removeAttribute("open");
33261
+ this.#launcher.collapse(true);
32671
33262
  this.dispatchEvent(new CustomEvent("assistant-close"));
32672
33263
  }
32673
33264
  toggle() {
@@ -32804,17 +33395,6 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32804
33395
  if (generation === this.#conversationGeneration) this.#setBusy(false);
32805
33396
  }
32806
33397
  }
32807
- #handleSystemTheme = () => this.#applyTheme();
32808
- #handleDocumentKeydown = (event) => {
32809
- if (event.key === "Escape" && this.hasAttribute("open") && this.#appearance.behavior.closeOnEscape) {
32810
- this.#closeAndRestoreFocus();
32811
- }
32812
- };
32813
- #handleDocumentPointerDown = (event) => {
32814
- if (this.hasAttribute("open") && this.#appearance.behavior.closeOnOutsideClick && !event.composedPath().includes(this)) {
32815
- this.close();
32816
- }
32817
- };
32818
33398
  #ensureClient() {
32819
33399
  const key = sessionSourceKey(this);
32820
33400
  if (this.#client && this.#clientEndpoint === key) return this.#client;
@@ -32830,8 +33410,13 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32830
33410
  const client = this.embedId ? createAssistantClient({
32831
33411
  embedId: this.embedId,
32832
33412
  ...this.serviceUrl ? { serviceUrl: this.serviceUrl } : {},
33413
+ ...this.#fetch ? { fetch: this.#fetch } : {},
33414
+ ...behavior
33415
+ }) : createAssistantClient({
33416
+ sessionEndpoint: this.sessionEndpoint,
33417
+ ...this.#fetch ? { fetch: this.#fetch } : {},
32833
33418
  ...behavior
32834
- }) : createAssistantClient({ sessionEndpoint: this.sessionEndpoint, ...behavior });
33419
+ });
32835
33420
  this.#client = client;
32836
33421
  this.#clientEndpoint = key;
32837
33422
  this.#unsubscribeClient = client.subscribe((event) => {
@@ -32860,6 +33445,8 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32860
33445
  this.dispatchEvent(new CustomEvent("assistant-event", { detail: event }));
32861
33446
  this.#events.handle(event);
32862
33447
  if (event.event === "session_started") {
33448
+ this.#publicConfiguration.disconnect();
33449
+ this.removeAttribute("data-public-configuration-loading");
32863
33450
  this.#presentationGate.reveal();
32864
33451
  this.#setSessionState("ready");
32865
33452
  this.#messages?.querySelector(".conversation-error")?.remove();
@@ -32909,10 +33496,10 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32909
33496
  if (!this.#messages) return void 0;
32910
33497
  const message = document.createElement("div");
32911
33498
  message.className = `message ${role}`;
32912
- if (role === "assistant" && this.#appearance.behavior.showAvatars && this.#appearance.brand.avatar[this.#resolvedMode()]) {
33499
+ if (role === "assistant" && this.#appearance.behavior.showAvatars && this.#appearance.brand.avatar[this.#environment.resolvedTheme()]) {
32913
33500
  const avatar = document.createElement("img");
32914
33501
  avatar.className = "avatar";
32915
- avatar.src = this.#appearance.brand.avatar[this.#resolvedMode()] ?? "";
33502
+ avatar.src = this.#appearance.brand.avatar[this.#environment.resolvedTheme()] ?? "";
32916
33503
  avatar.alt = "";
32917
33504
  message.append(avatar);
32918
33505
  }
@@ -32993,12 +33580,8 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32993
33580
  this.#primeSession();
32994
33581
  this.dispatchEvent(new CustomEvent("assistant-new-conversation"));
32995
33582
  }
32996
- #resolvedMode() {
32997
- const configured = this.getAttribute("theme") ?? this.#appearance.theme.defaultMode;
32998
- return configured === "auto" ? this.#media?.matches ? "dark" : "light" : configured;
32999
- }
33000
33583
  #applyTheme() {
33001
- const mode = this.#resolvedMode();
33584
+ const mode = this.#environment.resolvedTheme();
33002
33585
  for (const warning of applyAssistantElementTheme({
33003
33586
  host: this,
33004
33587
  root: this.shadowRoot,
@@ -33021,13 +33604,23 @@ var NoodleAssistantElement = class extends HTMLElementBase {
33021
33604
  updateAssistantAppTheme(app, mode);
33022
33605
  }
33023
33606
  }
33607
+ #applyConfiguration(configuration) {
33608
+ this.#appearance = resolveAppearance(configuration);
33609
+ this.#syncAppearance();
33610
+ this.#applyStartOpenPolicy();
33611
+ }
33612
+ #setPublicConfigurationLoading(loading) {
33613
+ this.toggleAttribute("data-public-configuration-loading", loading);
33614
+ if (loading) this.#presentationGate.syncOpenState();
33615
+ else this.#presentationGate.reveal();
33616
+ }
33024
33617
  #setSessionState(state) {
33025
33618
  this.#sessionState = state;
33026
33619
  syncAssistantSessionVisualState(this, this.shadowRoot, state, this.#appearance);
33027
33620
  }
33028
33621
  #closeAndRestoreFocus() {
33029
33622
  this.close();
33030
- this.shadowRoot?.querySelector(".launcher")?.focus();
33623
+ this.#launcher.focusTrigger();
33031
33624
  }
33032
33625
  #applyStartOpenPolicy() {
33033
33626
  if (this.#startOpenApplied) return;
@@ -33053,10 +33646,6 @@ var NoodleAssistantElement = class extends HTMLElementBase {
33053
33646
  textarea.placeholder = appearance.labels.composerPlaceholder;
33054
33647
  textarea.setAttribute("aria-label", appearance.labels.composerPlaceholder);
33055
33648
  queryRequired(this.shadowRoot, ".send").textContent = appearance.labels.send;
33056
- queryRequired(this.shadowRoot, ".launcher").setAttribute(
33057
- "aria-label",
33058
- appearance.labels.open
33059
- );
33060
33649
  queryRequired(this.shadowRoot, ".close").setAttribute(
33061
33650
  "aria-label",
33062
33651
  appearance.labels.close
@@ -33070,11 +33659,11 @@ var NoodleAssistantElement = class extends HTMLElementBase {
33070
33659
  button2.addEventListener("click", () => this.#sendGuarded(prompt));
33071
33660
  prompts.append(button2);
33072
33661
  }
33073
- queryRequired(this.shadowRoot, ".launcher").hidden = !appearance.behavior.showLauncher;
33074
33662
  queryRequired(this.shadowRoot, "header").hidden = !appearance.behavior.showHeader;
33075
33663
  const legal = queryRequired(this.shadowRoot, ".legal");
33076
33664
  legal.replaceChildren();
33077
33665
  appendLegalLinks(legal, this.#appearance);
33666
+ this.#launcher.sync();
33078
33667
  this.#applyTheme();
33079
33668
  }
33080
33669
  #render() {
@@ -33092,12 +33681,11 @@ var NoodleAssistantElement = class extends HTMLElementBase {
33092
33681
  this.toggleAttribute("mobile-fullscreen", appearance.layout.mobileFullscreen);
33093
33682
  this.shadowRoot.innerHTML = assistantElementMarkup(
33094
33683
  appearance,
33095
- this.hasAttribute("open"),
33096
33684
  `${ASSISTANT_ELEMENT_STYLES}${presentationStyles}`
33097
33685
  );
33098
33686
  queryRequired(this.shadowRoot, "strong").textContent = appearance.brand.name;
33099
33687
  const logo = queryRequired(this.shadowRoot, ".brand-logo");
33100
- const logoUrl = appearance.brand.logo[this.#resolvedMode()];
33688
+ const logoUrl = appearance.brand.logo[this.#environment.resolvedTheme()];
33101
33689
  if (logoUrl) {
33102
33690
  logo.src = logoUrl;
33103
33691
  logo.alt = appearance.brand.name;
@@ -33125,12 +33713,9 @@ var NoodleAssistantElement = class extends HTMLElementBase {
33125
33713
  this.#messages = this.shadowRoot.querySelector(".messages") ?? void 0;
33126
33714
  this.#messages?.append(...conversation);
33127
33715
  this.#thinking = this.#messages?.querySelector(".thinking") ?? void 0;
33128
- this.shadowRoot.querySelector(".launcher")?.addEventListener("click", () => {
33129
- this.open();
33130
- this.focusComposer();
33131
- });
33716
+ this.#launcher.connect(this.shadowRoot);
33132
33717
  this.shadowRoot.querySelector(".close")?.addEventListener("click", () => this.#closeAndRestoreFocus());
33133
- const form = queryRequired(this.shadowRoot, "form");
33718
+ const form = queryRequired(this.shadowRoot, ".composer");
33134
33719
  form.addEventListener("submit", (event) => {
33135
33720
  event.preventDefault();
33136
33721
  if (this.hasAttribute("busy")) {