@sevenfold/setto-client 0.24.3 → 0.24.5

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.
@@ -22054,13 +22054,6 @@ function norwegian(locale) {
22054
22054
  function intro(locale, name) {
22055
22055
  return norwegian(locale) ? `Hei! Jeg er Barista, ${name ? `${name}s` : "nettstedets"} AI-assistent. Jeg svarer ut fra det teamet har delt her, og hjelper deg videre til dem når det trengs.` : `Hello! I’m Barista, the AI assistant for ${name ?? "this website"}. I answer from what the team has shared here and help you reach them when needed.`;
22056
22056
  }
22057
- function contactTeam() {
22058
- const link = document.querySelector(
22059
- 'a[href*="kontakt" i], a[href*="contact" i], a[href^="mailto:"]'
22060
- );
22061
- if (link) link.click();
22062
- else window.location.hash = "kontakt";
22063
- }
22064
22057
  function validColor(value, fallback) {
22065
22058
  return value && (/^#[0-9a-f]{3,8}$/i.test(value) || /^rgba?\(/i.test(value)) ? value : fallback;
22066
22059
  }
@@ -22132,6 +22125,18 @@ function BaristaIcon() {
22132
22125
  }
22133
22126
  ) });
22134
22127
  }
22128
+ function PersonIcon() {
22129
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", width: "20", height: "20", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
22130
+ "path",
22131
+ {
22132
+ d: "M12 12.25a4.25 4.25 0 1 0 0-8.5 4.25 4.25 0 0 0 0 8.5ZM4.75 20.25c.55-3.35 3.3-5.5 7.25-5.5s6.7 2.15 7.25 5.5",
22133
+ fill: "none",
22134
+ stroke: "currentColor",
22135
+ strokeWidth: "1.8",
22136
+ strokeLinecap: "round"
22137
+ }
22138
+ ) });
22139
+ }
22135
22140
  function SiteChatComposer({
22136
22141
  value,
22137
22142
  onChange,
@@ -22161,7 +22166,11 @@ function SiteChatComposer({
22161
22166
  textarea.style.height = `${height}px`;
22162
22167
  }, [value]);
22163
22168
  useEffect(() => {
22164
- if (!busy) textareaRef.current?.focus();
22169
+ if (busy || document.visibilityState !== "visible") return;
22170
+ const textarea = textareaRef.current;
22171
+ if (!textarea || document.activeElement === textarea) return;
22172
+ const frame = window.requestAnimationFrame(() => textarea.focus({ preventScroll: true }));
22173
+ return () => window.cancelAnimationFrame(frame);
22165
22174
  }, [busy]);
22166
22175
  function send() {
22167
22176
  if (!value.trim() && attachments.length === 0) return;
@@ -22185,7 +22194,9 @@ function SiteChatComposer({
22185
22194
  className: `setto-chat__composer${open ? " is-open" : ""}`,
22186
22195
  onSubmit: handleSubmit,
22187
22196
  onPointerDown: (event) => {
22188
- if (event.target === event.currentTarget) textareaRef.current?.focus();
22197
+ if (event.target === event.currentTarget) {
22198
+ textareaRef.current?.focus({ preventScroll: true });
22199
+ }
22189
22200
  },
22190
22201
  children: [
22191
22202
  attachments.length > 0 ? /* @__PURE__ */ jsx("ul", { className: "setto-chat__attachments", children: attachments.map((attachment, index) => /* @__PURE__ */ jsxs("li", { children: [
@@ -22260,7 +22271,7 @@ function SiteChatComposer({
22260
22271
  }
22261
22272
  );
22262
22273
  }
22263
- function useChatViewport(active, logRef) {
22274
+ function useChatViewport(active, logRef, pinToBottomRef, programmaticScrollRef) {
22264
22275
  useEffect(() => {
22265
22276
  if (!active) return;
22266
22277
  const root = document.documentElement;
@@ -22291,10 +22302,26 @@ function useChatViewport(active, logRef) {
22291
22302
  Math.round(window.innerHeight),
22292
22303
  Math.round((visualViewport?.height ?? window.innerHeight) + (visualViewport?.offsetTop ?? 0))
22293
22304
  );
22305
+ let viewportHeight = -1;
22306
+ let viewportTop = -1;
22307
+ let viewportWidth = -1;
22308
+ let scrollFrame = 0;
22309
+ let releaseScrollFrame = 0;
22310
+ const log = logRef.current;
22311
+ const updatePinState = () => {
22312
+ if (programmaticScrollRef.current) return;
22313
+ if (!log) return;
22314
+ pinToBottomRef.current = log.scrollHeight - log.scrollTop - log.clientHeight <= 96;
22315
+ };
22294
22316
  const update = () => {
22295
22317
  const height = Math.round(visualViewport?.height ?? window.innerHeight);
22296
22318
  const top = Math.round(visualViewport?.offsetTop ?? 0);
22297
22319
  const width = Math.round(visualViewport?.width ?? window.innerWidth);
22320
+ if (height < 1 || width < 1) return;
22321
+ if (height === viewportHeight && top === viewportTop && width === viewportWidth) return;
22322
+ viewportHeight = height;
22323
+ viewportTop = top;
22324
+ viewportWidth = width;
22298
22325
  const nextLayoutHeight = Math.max(
22299
22326
  Math.round(root.clientHeight),
22300
22327
  Math.round(window.innerHeight),
@@ -22309,13 +22336,19 @@ function useChatViewport(active, logRef) {
22309
22336
  root.style.setProperty("--setto-chat-height", `${height}px`);
22310
22337
  root.style.setProperty("--setto-chat-top", `${top}px`);
22311
22338
  root.style.setProperty("--setto-chat-layout-height", `${layoutHeight}px`);
22312
- if (window.scrollY !== 0) window.scrollTo(0, 0);
22313
- window.requestAnimationFrame(() => {
22314
- const log = logRef.current;
22315
- if (log) log.scrollTop = log.scrollHeight;
22339
+ window.cancelAnimationFrame(scrollFrame);
22340
+ scrollFrame = window.requestAnimationFrame(() => {
22341
+ if (!log || !pinToBottomRef.current) return;
22342
+ programmaticScrollRef.current = true;
22343
+ log.scrollTop = log.scrollHeight;
22344
+ window.cancelAnimationFrame(releaseScrollFrame);
22345
+ releaseScrollFrame = window.requestAnimationFrame(() => {
22346
+ programmaticScrollRef.current = false;
22347
+ });
22316
22348
  });
22317
22349
  };
22318
22350
  update();
22351
+ log?.addEventListener("scroll", updatePinState, { passive: true });
22319
22352
  visualViewport?.addEventListener("resize", update);
22320
22353
  visualViewport?.addEventListener("scroll", update);
22321
22354
  window.addEventListener("orientationchange", update);
@@ -22323,6 +22356,10 @@ function useChatViewport(active, logRef) {
22323
22356
  visualViewport?.removeEventListener("resize", update);
22324
22357
  visualViewport?.removeEventListener("scroll", update);
22325
22358
  window.removeEventListener("orientationchange", update);
22359
+ log?.removeEventListener("scroll", updatePinState);
22360
+ window.cancelAnimationFrame(scrollFrame);
22361
+ window.cancelAnimationFrame(releaseScrollFrame);
22362
+ programmaticScrollRef.current = false;
22326
22363
  root.style.removeProperty("--setto-chat-height");
22327
22364
  root.style.removeProperty("--setto-chat-top");
22328
22365
  root.style.removeProperty("--setto-chat-layout-height");
@@ -22334,9 +22371,9 @@ function useChatViewport(active, logRef) {
22334
22371
  body.style.right = previous.bodyRight;
22335
22372
  body.style.width = previous.bodyWidth;
22336
22373
  body.style.overflow = previous.bodyOverflow;
22337
- window.scrollTo(0, savedScrollY);
22374
+ window.scrollTo({ top: savedScrollY, left: 0, behavior: "auto" });
22338
22375
  };
22339
- }, [active, logRef]);
22376
+ }, [active, logRef, pinToBottomRef, programmaticScrollRef]);
22340
22377
  }
22341
22378
  function SettoChat() {
22342
22379
  const { config } = useSetto();
@@ -22357,23 +22394,16 @@ function SettoChat() {
22357
22394
  humanAvailable: false,
22358
22395
  avatarUrl: null
22359
22396
  });
22360
- const [leadOpen, setLeadOpen] = useState(false);
22361
- const [leadStatus, setLeadStatus] = useState("idle");
22362
- const [lead, setLead] = useState({
22363
- name: "",
22364
- email: "",
22365
- phone: "",
22366
- interest: "",
22367
- consent: false
22368
- });
22369
22397
  const conversationId = useRef(null);
22370
22398
  const visitor = useRef(null);
22371
22399
  const logRef = useRef(null);
22400
+ const pinToBottomRef = useRef(true);
22401
+ const programmaticScrollRef = useRef(false);
22372
22402
  const filesRef = useRef([]);
22373
22403
  const formId = useId();
22374
22404
  const palette = useMemo(() => chatPalette(config.brandColors), [config.brandColors]);
22375
22405
  useChatStyles();
22376
- useChatViewport(mounted, logRef);
22406
+ useChatViewport(mounted, logRef, pinToBottomRef, programmaticScrollRef);
22377
22407
  const locale = i18n.language || "no";
22378
22408
  const isNo = norwegian(locale);
22379
22409
  const siteName = settings?.displayName?.trim() || config.displayName?.trim() || null;
@@ -22388,19 +22418,6 @@ function SettoChat() {
22388
22418
  sending: "Svarer …",
22389
22419
  attach: "Legg ved bilde",
22390
22420
  remove: "Fjern",
22391
- contact: "Kontakt teamet",
22392
- followUp: "Be om oppfølging",
22393
- followUpTitle: "La teamet følge opp",
22394
- followUpDetail: "Legg igjen kontaktinformasjon hvis du vil at teamet skal følge opp denne samtalen.",
22395
- name: "Navn",
22396
- email: "E-post",
22397
- phone: "Telefon",
22398
- interest: "Hva vil du ha hjelp med?",
22399
- consent: "Ja, teamet kan bruke opplysningene mine til å følge opp denne henvendelsen.",
22400
- leadSend: "Send forespørsel",
22401
- leadSent: "Takk — forespørselen er sendt til teamet.",
22402
- leadFailed: "Kunne ikke lagre forespørselen. Prøv igjen eller kontakt teamet direkte.",
22403
- leadConversation: "Still et spørsmål først, så kan vi knytte oppfølgingen til samtalen.",
22404
22421
  failed: "Jeg får ikke svart akkurat nå. Kontakt gjerne teamet direkte.",
22405
22422
  image: "Bilde",
22406
22423
  team: "Teamet",
@@ -22416,19 +22433,6 @@ function SettoChat() {
22416
22433
  sending: "Replying …",
22417
22434
  attach: "Attach image",
22418
22435
  remove: "Remove",
22419
- contact: "Contact the team",
22420
- followUp: "Ask for follow-up",
22421
- followUpTitle: "Let the team follow up",
22422
- followUpDetail: "Leave contact details if you want the team to follow up on this conversation.",
22423
- name: "Name",
22424
- email: "Email",
22425
- phone: "Phone",
22426
- interest: "What would you like help with?",
22427
- consent: "Yes, the team may use my details to follow up on this enquiry.",
22428
- leadSend: "Send request",
22429
- leadSent: "Thanks — your request has been sent to the team.",
22430
- leadFailed: "We could not save your request. Please try again or contact the team directly.",
22431
- leadConversation: "Ask a question first so we can link the follow-up to this conversation.",
22432
22436
  failed: "I cannot reply right now. Please contact the team directly.",
22433
22437
  image: "Image",
22434
22438
  team: "The team",
@@ -22465,8 +22469,8 @@ function SettoChat() {
22465
22469
  if (!response.ok) return;
22466
22470
  const next = await response.json();
22467
22471
  conversationId.current = next.conversationId;
22472
+ pinToBottomRef.current = true;
22468
22473
  setMessages(next.messages);
22469
- setLeadOpen(false);
22470
22474
  setDrawer(false);
22471
22475
  } finally {
22472
22476
  setLoadingConversation(false);
@@ -22511,10 +22515,19 @@ function SettoChat() {
22511
22515
  });
22512
22516
  }, [mounted, settings, locale]);
22513
22517
  useEffect(() => {
22514
- if (!mounted) return;
22518
+ if (!mounted || !pinToBottomRef.current) return;
22515
22519
  const log = logRef.current;
22516
- if (log) log.scrollTo({ top: log.scrollHeight, behavior: sending ? "auto" : "smooth" });
22517
- }, [messages, mounted, sending, leadOpen]);
22520
+ if (!log) return;
22521
+ programmaticScrollRef.current = true;
22522
+ log.scrollTo({ top: log.scrollHeight, behavior: sending ? "auto" : "smooth" });
22523
+ const timer = window.setTimeout(() => {
22524
+ programmaticScrollRef.current = false;
22525
+ }, sending ? 50 : 500);
22526
+ return () => {
22527
+ window.clearTimeout(timer);
22528
+ programmaticScrollRef.current = false;
22529
+ };
22530
+ }, [messages, mounted, sending]);
22518
22531
  useEffect(() => {
22519
22532
  filesRef.current = files;
22520
22533
  }, [files]);
@@ -22562,6 +22575,7 @@ function SettoChat() {
22562
22575
  }, [mounted]);
22563
22576
  if (!settings || window.location.pathname.startsWith("/setto")) return null;
22564
22577
  function show() {
22578
+ pinToBottomRef.current = true;
22565
22579
  setMounted(true);
22566
22580
  window.requestAnimationFrame(() => setVisible(true));
22567
22581
  ensureVisitor();
@@ -22586,7 +22600,6 @@ function SettoChat() {
22586
22600
  setMessages([{ role: "assistant", content: intro(locale, settings?.displayName ?? void 0) }]);
22587
22601
  setDraft("");
22588
22602
  setQueued(false);
22589
- setLeadOpen(false);
22590
22603
  setDrawer(false);
22591
22604
  clearPendingFiles();
22592
22605
  }
@@ -22616,6 +22629,7 @@ function SettoChat() {
22616
22629
  const content = draft.trim();
22617
22630
  const turnFiles = files;
22618
22631
  if (!content && turnFiles.length === 0) return;
22632
+ pinToBottomRef.current = true;
22619
22633
  setDraft("");
22620
22634
  setFiles([]);
22621
22635
  setSending(true);
@@ -22693,36 +22707,6 @@ function SettoChat() {
22693
22707
  setSending(false);
22694
22708
  }
22695
22709
  }
22696
- async function submitLead(event) {
22697
- event.preventDefault();
22698
- if (leadStatus === "sending" || !conversationId.current || !visitor.current) {
22699
- setLeadStatus("failed");
22700
- return;
22701
- }
22702
- setLeadStatus("sending");
22703
- try {
22704
- const response = await fetch(
22705
- `${apiUrl}/sites/${encodeURIComponent(config.siteId)}/chat/leads`,
22706
- {
22707
- method: "POST",
22708
- headers: { "Content-Type": "application/json", Accept: "application/json" },
22709
- body: JSON.stringify({
22710
- conversationId: conversationId.current,
22711
- visitorId: visitor.current,
22712
- consent: lead.consent,
22713
- name: lead.name.trim() || void 0,
22714
- email: lead.email.trim() || void 0,
22715
- phone: lead.phone.trim() || void 0,
22716
- interest: lead.interest.trim() || void 0
22717
- })
22718
- }
22719
- );
22720
- if (!response.ok) throw new Error("lead_failed");
22721
- setLeadStatus("sent");
22722
- } catch {
22723
- setLeadStatus("failed");
22724
- }
22725
- }
22726
22710
  return /* @__PURE__ */ jsxs(
22727
22711
  "aside",
22728
22712
  {
@@ -22811,128 +22795,47 @@ function SettoChat() {
22811
22795
  )
22812
22796
  ] }),
22813
22797
  /* @__PURE__ */ jsxs("div", { className: "setto-chat__body", children: [
22814
- /* @__PURE__ */ jsxs(
22798
+ /* @__PURE__ */ jsx(
22815
22799
  "div",
22816
22800
  {
22817
22801
  className: "setto-chat__log",
22818
22802
  ref: logRef,
22819
22803
  "aria-live": "polite",
22820
22804
  "aria-busy": loadingConversation,
22821
- children: [
22822
- /* @__PURE__ */ jsx("div", { className: "setto-chat__message-list", children: messages.map((item, index) => /* @__PURE__ */ jsxs(
22823
- "div",
22824
- {
22825
- className: `setto-chat__message setto-chat__message--${item.role}`,
22826
- children: [
22827
- item.role === "human" ? /* @__PURE__ */ jsx("span", { className: "setto-chat__speaker", children: labels.team }) : null,
22828
- /* @__PURE__ */ jsx("span", { className: "setto-chat__message-copy", children: item.content || /* @__PURE__ */ jsx("span", { className: "setto-chat__typing", children: "···" }) }),
22829
- item.attachments?.map((attachment) => /* @__PURE__ */ jsx(
22830
- "a",
22831
- {
22832
- className: "setto-chat__image",
22833
- href: attachment.url,
22834
- target: "_blank",
22835
- rel: "noreferrer",
22836
- children: /* @__PURE__ */ jsx("img", { src: attachment.url, alt: labels.image })
22837
- },
22838
- attachment.id
22839
- ))
22840
- ]
22841
- },
22842
- item.id ?? `${item.role}-${index}`
22843
- )) }),
22844
- /* @__PURE__ */ jsxs("div", { className: "setto-chat__actions", children: [
22845
- /* @__PURE__ */ jsxs("button", { type: "button", onClick: contactTeam, children: [
22846
- labels.contact,
22847
- /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "↗" })
22848
- ] }),
22849
- /* @__PURE__ */ jsx(
22850
- "button",
22851
- {
22852
- type: "button",
22853
- onClick: () => {
22854
- setLeadOpen((value) => !value);
22855
- setLeadStatus("idle");
22856
- },
22857
- "aria-expanded": leadOpen,
22858
- children: labels.followUp
22859
- }
22860
- )
22861
- ] }),
22862
- leadOpen ? /* @__PURE__ */ jsxs("form", { className: "setto-chat__lead", onSubmit: submitLead, children: [
22863
- /* @__PURE__ */ jsx("strong", { children: labels.followUpTitle }),
22864
- /* @__PURE__ */ jsx("p", { children: labels.followUpDetail }),
22865
- /* @__PURE__ */ jsxs("div", { className: "setto-chat__lead-grid", children: [
22866
- /* @__PURE__ */ jsxs("label", { children: [
22867
- labels.name,
22868
- /* @__PURE__ */ jsx(
22869
- "input",
22870
- {
22871
- value: lead.name,
22872
- maxLength: 160,
22873
- onChange: (event) => setLead((current) => ({ ...current, name: event.target.value }))
22874
- }
22875
- )
22876
- ] }),
22877
- /* @__PURE__ */ jsxs("label", { children: [
22878
- labels.email,
22879
- /* @__PURE__ */ jsx(
22880
- "input",
22881
- {
22882
- type: "email",
22883
- value: lead.email,
22884
- maxLength: 320,
22885
- onChange: (event) => setLead((current) => ({ ...current, email: event.target.value }))
22886
- }
22887
- )
22888
- ] }),
22889
- /* @__PURE__ */ jsxs("label", { children: [
22890
- labels.phone,
22891
- /* @__PURE__ */ jsx(
22892
- "input",
22893
- {
22894
- type: "tel",
22895
- value: lead.phone,
22896
- maxLength: 64,
22897
- onChange: (event) => setLead((current) => ({ ...current, phone: event.target.value }))
22898
- }
22899
- )
22900
- ] }),
22901
- /* @__PURE__ */ jsxs("label", { children: [
22902
- labels.interest,
22903
- /* @__PURE__ */ jsx(
22904
- "input",
22905
- {
22906
- value: lead.interest,
22907
- maxLength: 500,
22908
- onChange: (event) => setLead((current) => ({ ...current, interest: event.target.value }))
22909
- }
22910
- )
22911
- ] })
22912
- ] }),
22913
- /* @__PURE__ */ jsxs("label", { className: "setto-chat__consent", children: [
22914
- /* @__PURE__ */ jsx(
22915
- "input",
22805
+ children: /* @__PURE__ */ jsx("div", { className: "setto-chat__message-list", children: messages.map((item, index) => /* @__PURE__ */ jsxs(
22806
+ "div",
22807
+ {
22808
+ className: `setto-chat__message setto-chat__message--${item.role}`,
22809
+ children: [
22810
+ item.role === "assistant" || item.role === "human" ? /* @__PURE__ */ jsx(
22811
+ "span",
22916
22812
  {
22917
- type: "checkbox",
22918
- checked: lead.consent,
22919
- onChange: (event) => setLead((current) => ({ ...current, consent: event.target.checked }))
22813
+ className: `setto-chat__avatar setto-chat__avatar--${item.role}`,
22814
+ "aria-hidden": "true",
22815
+ children: item.role === "human" && item.avatarUrl ? /* @__PURE__ */ jsx("img", { src: item.avatarUrl, alt: "" }) : item.role === "human" ? /* @__PURE__ */ jsx(PersonIcon, {}) : /* @__PURE__ */ jsx(BaristaIcon, {})
22920
22816
  }
22921
- ),
22922
- labels.consent
22923
- ] }),
22924
- leadStatus === "sent" ? /* @__PURE__ */ jsx("p", { className: "setto-chat__lead-success", children: labels.leadSent }) : null,
22925
- leadStatus === "failed" ? /* @__PURE__ */ jsx("p", { className: "setto-chat__lead-error", children: conversationId.current ? labels.leadFailed : labels.leadConversation }) : null,
22926
- leadStatus !== "sent" ? /* @__PURE__ */ jsx(
22927
- "button",
22928
- {
22929
- type: "submit",
22930
- disabled: leadStatus === "sending" || !lead.consent || !lead.email.trim() && !lead.phone.trim(),
22931
- children: leadStatus === "sending" ? labels.sending : labels.leadSend
22932
- }
22933
- ) : null
22934
- ] }) : null
22935
- ]
22817
+ ) : null,
22818
+ /* @__PURE__ */ jsxs("div", { className: "setto-chat__message-stack", children: [
22819
+ item.role === "assistant" || item.role === "human" ? /* @__PURE__ */ jsx("span", { className: "setto-chat__speaker", children: item.role === "human" ? labels.team : "Barista" }) : null,
22820
+ /* @__PURE__ */ jsxs("div", { className: "setto-chat__message-bubble", children: [
22821
+ /* @__PURE__ */ jsx("span", { className: "setto-chat__message-copy", children: item.content || /* @__PURE__ */ jsx("span", { className: "setto-chat__typing", children: "···" }) }),
22822
+ item.attachments?.map((attachment) => /* @__PURE__ */ jsx(
22823
+ "a",
22824
+ {
22825
+ className: "setto-chat__image",
22826
+ href: attachment.url,
22827
+ target: "_blank",
22828
+ rel: "noreferrer",
22829
+ children: /* @__PURE__ */ jsx("img", { src: attachment.url, alt: labels.image })
22830
+ },
22831
+ attachment.id
22832
+ ))
22833
+ ] })
22834
+ ] })
22835
+ ]
22836
+ },
22837
+ item.id ?? `${item.role}-${index}`
22838
+ )) })
22936
22839
  }
22937
22840
  ),
22938
22841
  /* @__PURE__ */ jsxs("div", { className: "setto-chat__composer-shell", children: [
@@ -22994,12 +22897,11 @@ function useChatStyles() {
22994
22897
  style.textContent = `
22995
22898
  .setto-chat{position:fixed;right:max(18px,env(safe-area-inset-right));bottom:max(18px,env(safe-area-inset-bottom));z-index:2147483000;color:var(--setto-chat-ink);font-family:"Archivo Variable",Archivo,system-ui,sans-serif;-webkit-font-smoothing:antialiased}.setto-chat *,.setto-chat *::before,.setto-chat *::after{box-sizing:border-box}.setto-chat button,.setto-chat input,.setto-chat textarea{font:inherit}.setto-chat--mounted{top:0;right:auto;bottom:auto;left:0;width:100vw;height:var(--setto-chat-layout-height,100lvh);overflow:hidden;background:var(--setto-chat-canvas);opacity:0;transition:opacity ${CLOSE_MS}ms ease}.setto-chat--visible{opacity:1}.setto-chat__shell{position:absolute;top:var(--setto-chat-top,0);left:0;width:100%;height:var(--setto-chat-height,100svh);display:flex;overflow:hidden;background:var(--setto-chat-canvas);opacity:0;transform:translateY(12px) scale(.994);transform-origin:center bottom;transition:opacity ${CLOSE_MS}ms ease,transform ${CLOSE_MS}ms cubic-bezier(.16,1,.3,1)}.setto-chat--visible .setto-chat__shell{opacity:1;transform:none}
22996
22899
  .setto-chat__scrim{position:absolute;inset:0;z-index:45;border:0;background:rgba(33,23,17,.32);opacity:0;pointer-events:none;transition:opacity 220ms ease}.setto-chat__scrim.is-open{opacity:1;pointer-events:auto}.setto-chat__chats{position:relative;z-index:50;width:min(84vw,280px);height:100%;flex:0 0 280px;padding:1rem .85rem calc(1rem + env(safe-area-inset-bottom));display:flex;flex-direction:column;gap:.9rem;background:color-mix(in srgb,var(--setto-chat-crema) 32%,var(--setto-chat-canvas));border-right:1px solid color-mix(in srgb,var(--setto-chat-ink) 12%,transparent);overflow:hidden}.setto-chat__chats-heading{display:flex;align-items:center;justify-content:space-between;gap:.5rem;min-height:34px;font-size:.66rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:color-mix(in srgb,var(--setto-chat-ink) 58%,transparent)}.setto-chat__chats-heading button{width:34px;height:34px;padding:0;border:0;border-radius:8px;background:transparent;color:color-mix(in srgb,var(--setto-chat-ink) 58%,transparent);display:inline-flex;align-items:center;justify-content:center;cursor:pointer}.setto-chat__new{display:flex;align-items:center;gap:.55rem;width:100%;padding:.5rem .55rem;border:0;border-radius:8px;background:transparent;color:var(--setto-chat-ink);font-weight:600;font-size:.9rem;text-align:left;cursor:pointer;transition:background 140ms ease}.setto-chat__new:hover{background:color-mix(in srgb,var(--setto-chat-ink) 5%,transparent)}.setto-chat__chat-list{display:flex;flex-direction:column;gap:.1rem;flex:1;min-height:0;overflow:auto;overscroll-behavior:contain;margin-right:-.85rem;padding-right:.3rem}.setto-chat__chat-list p{margin:.35rem .55rem;font-size:.85rem;line-height:1.5;color:color-mix(in srgb,var(--setto-chat-ink) 58%,transparent)}.setto-chat__chat-row{width:100%;display:grid;grid-template-columns:minmax(0,1fr) auto;gap:.4rem;padding:.55rem;border:0;border-radius:8px;background:transparent;color:var(--setto-chat-ink);text-align:left;cursor:pointer}.setto-chat__chat-row:hover,.setto-chat__chat-row.is-active{background:color-mix(in srgb,var(--setto-chat-ink) 7.5%,transparent)}.setto-chat__chat-row span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.9rem;font-weight:600}.setto-chat__chat-row time{font-size:.72rem;color:color-mix(in srgb,var(--setto-chat-ink) 55%,transparent)}
22997
- .setto-chat__main{position:relative;z-index:1;display:flex;flex:1;min-width:0;max-width:820px;height:100%;margin:0 auto;flex-direction:column;background:var(--setto-chat-canvas)}.setto-chat__header{position:relative;z-index:30;min-height:58px;padding:.35rem .75rem;display:flex;align-items:center;gap:.5rem;flex:0 0 auto;background:transparent;isolation:isolate}.setto-chat__header::before{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;background:color-mix(in srgb,var(--setto-chat-crema) 70%,transparent);backdrop-filter:blur(18px) saturate(150%);-webkit-backdrop-filter:blur(18px) saturate(150%);-webkit-mask-image:linear-gradient(to bottom,rgba(0,0,0,1) 45%,rgba(0,0,0,.45) 78%,rgba(0,0,0,0) 100%);mask-image:linear-gradient(to bottom,rgba(0,0,0,1) 45%,rgba(0,0,0,.45) 78%,rgba(0,0,0,0) 100%)}.setto-chat__round-button{flex:none;width:46px;height:46px;padding:0;border:1px solid color-mix(in srgb,var(--setto-chat-ink) 12%,transparent);border-radius:50%;background:var(--setto-chat-raised);color:var(--setto-chat-ink);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background 160ms ease,border-color 160ms ease,color 160ms ease}.setto-chat__round-button:hover{background:var(--setto-chat-crema);border-color:var(--setto-chat-accent);color:var(--setto-chat-accent)}.setto-chat__round-button:active{transform:scale(.96)}.setto-chat__brand{flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;line-height:1.15;text-align:center}.setto-chat__brand h2{margin:0;color:var(--setto-chat-ink);font-size:1.02rem;font-weight:600;line-height:1.15}.setto-chat__brand p{max-width:100%;margin:2px 0 0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:color-mix(in srgb,var(--setto-chat-ink) 56%,transparent);font-size:.78rem;line-height:1.15}
22998
- .setto-chat__body{position:relative;display:flex;flex:1 1 auto;min-height:0;flex-direction:column}.setto-chat__log{display:flex;flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;flex-direction:column;padding:1.3rem .75rem 8rem;scroll-behavior:smooth;-webkit-overflow-scrolling:touch}.setto-chat__message-list{display:flex;flex-direction:column}.setto-chat__message{display:block;margin-bottom:1.5rem;font-size:16px;line-height:1.65;overflow-wrap:anywhere;white-space:pre-wrap;color:color-mix(in srgb,var(--setto-chat-ink) 88%,transparent)}.setto-chat__message--assistant{align-self:stretch;max-width:100%;padding:0;background:transparent}.setto-chat__message--visitor{align-self:flex-end;max-width:85%;margin-bottom:1.25rem;padding:.65rem .95rem;background:var(--setto-chat-crema);color:var(--setto-chat-ink);border:1px solid color-mix(in srgb,var(--setto-chat-ink) 7%,transparent);border-radius:20px 20px 4px 20px;font-size:.95rem;line-height:1.55;box-shadow:0 1px 2px color-mix(in srgb,var(--setto-chat-ink) 6%,transparent)}.setto-chat__message--human{align-self:stretch;max-width:100%;padding-left:.8rem;border-left:2px solid var(--setto-chat-accent)}.setto-chat__message--system{align-self:center;max-width:85%;padding:.25rem .6rem;color:color-mix(in srgb,var(--setto-chat-ink) 55%,transparent);font-size:.78rem;line-height:1.45;text-align:center}.setto-chat__speaker{display:block;margin-bottom:.15rem;color:var(--setto-chat-accent);font-size:.68rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase}.setto-chat__typing{display:inline-block;animation:setto-chat-pulse 1s ease-in-out infinite}.setto-chat__image{display:block;width:max-content;max-width:100%;margin-top:.65rem;overflow:hidden;border-radius:14px;border:1px solid color-mix(in srgb,var(--setto-chat-ink) 10%,transparent)}.setto-chat__image img{display:block;width:min(280px,100%);max-height:260px;object-fit:cover}
22999
- .setto-chat__actions{display:flex;flex-wrap:wrap;gap:1.35rem;margin-top:auto;padding:1.2rem 0 .65rem}.setto-chat__actions button{display:inline-flex;align-items:center;gap:.25rem;padding:.2rem 0;border:0;background:transparent;color:var(--setto-chat-accent);font-size:.9rem;font-weight:700;cursor:pointer}.setto-chat__lead{display:grid;gap:.6rem;margin:.5rem 0 1rem;padding:1rem;border:1px solid color-mix(in srgb,var(--setto-chat-ink) 12%,transparent);border-radius:16px;background:color-mix(in srgb,var(--setto-chat-crema) 58%,var(--setto-chat-canvas))}.setto-chat__lead strong{font-size:.95rem}.setto-chat__lead p{margin:0;color:color-mix(in srgb,var(--setto-chat-ink) 65%,transparent);font-size:.8rem;line-height:1.45}.setto-chat__lead-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.55rem}.setto-chat__lead label{display:grid;gap:.25rem;font-size:.72rem;font-weight:700}.setto-chat__lead input{min-width:0;padding:.55rem .6rem;border:1px solid color-mix(in srgb,var(--setto-chat-ink) 18%,transparent);border-radius:8px;background:var(--setto-chat-canvas);color:var(--setto-chat-ink);font-size:.85rem}.setto-chat__consent{display:flex!important;align-items:flex-start;gap:.45rem;font-weight:400!important;line-height:1.4}.setto-chat__lead>button{justify-self:start;padding:.55rem .8rem;border:0;border-radius:9px;background:var(--setto-chat-accent);color:var(--setto-chat-raised);font-size:.78rem;font-weight:700;cursor:pointer}.setto-chat__lead>button:disabled{opacity:.4;cursor:default}.setto-chat__lead-success{color:#28633d!important;font-weight:700}.setto-chat__lead-error{color:#a33024!important;font-weight:700}
22900
+ .setto-chat__main{position:relative;z-index:1;display:flex;flex:1;min-width:0;max-width:820px;height:100%;margin:0 auto;flex-direction:column;background:var(--setto-chat-canvas)}.setto-chat__header{position:absolute;inset:0 0 auto;z-index:30;min-height:58px;padding:.35rem .75rem;display:flex;align-items:center;gap:.5rem;background:linear-gradient(to bottom,color-mix(in srgb,var(--setto-chat-crema) 88%,transparent),color-mix(in srgb,var(--setto-chat-crema) 72%,transparent));border-bottom:1px solid color-mix(in srgb,var(--setto-chat-ink) 12%,transparent);backdrop-filter:blur(20px) saturate(150%);-webkit-backdrop-filter:blur(20px) saturate(150%);isolation:isolate}.setto-chat__round-button{flex:none;width:46px;height:46px;padding:0;border:1px solid color-mix(in srgb,var(--setto-chat-ink) 12%,transparent);border-radius:50%;background:var(--setto-chat-raised);color:var(--setto-chat-ink);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background 160ms ease,border-color 160ms ease,color 160ms ease}.setto-chat__round-button:hover{background:var(--setto-chat-crema);border-color:var(--setto-chat-accent);color:var(--setto-chat-accent)}.setto-chat__round-button:active{transform:scale(.96)}.setto-chat__brand{flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;line-height:1.15;text-align:center}.setto-chat__brand h2{margin:0;color:var(--setto-chat-ink);font-size:1.02rem;font-weight:600;line-height:1.15}.setto-chat__brand p{max-width:100%;margin:2px 0 0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:color-mix(in srgb,var(--setto-chat-ink) 56%,transparent);font-size:.78rem;line-height:1.15}
22901
+ .setto-chat__body{position:relative;display:flex;flex:1 1 auto;min-height:0;height:100%;flex-direction:column}.setto-chat__log{display:flex;flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;flex-direction:column;padding:calc(58px + 1.3rem) .75rem 8rem;scroll-behavior:smooth;-webkit-overflow-scrolling:touch}.setto-chat__message-list{display:flex;flex-direction:column}.setto-chat__message{--setto-chat-bubble:color-mix(in srgb,var(--setto-chat-ink) 7%,var(--setto-chat-canvas));display:flex;align-items:flex-end;gap:.55rem;width:100%;margin-bottom:1rem;color:color-mix(in srgb,var(--setto-chat-ink) 92%,transparent);font-size:16px;line-height:1.5;overflow-wrap:anywhere}.setto-chat__message-stack{display:flex;min-width:0;max-width:min(78%,36rem);flex-direction:column;align-items:flex-start}.setto-chat__message-bubble{position:relative;min-width:2.5rem;padding:.58rem .82rem;border-radius:19px 19px 19px 5px;background:var(--setto-chat-bubble);white-space:pre-wrap}.setto-chat__message--assistant .setto-chat__message-bubble::before,.setto-chat__message--human .setto-chat__message-bubble::before{content:"";position:absolute;z-index:0;left:-7px;bottom:0;width:16px;height:17px;border-bottom-right-radius:14px;background:var(--setto-chat-bubble)}.setto-chat__message--assistant .setto-chat__message-bubble::after,.setto-chat__message--human .setto-chat__message-bubble::after{content:"";position:absolute;z-index:1;left:-10px;bottom:0;width:10px;height:18px;border-bottom-right-radius:10px;background:var(--setto-chat-canvas)}.setto-chat__message-copy,.setto-chat__image{position:relative;z-index:2}.setto-chat__message--visitor{--setto-chat-bubble:#0a84ff;justify-content:flex-end;color:#fff}.setto-chat__message--visitor .setto-chat__message-stack{align-items:flex-end}.setto-chat__message--visitor .setto-chat__message-bubble{border-radius:19px 19px 5px 19px}.setto-chat__message--visitor .setto-chat__message-bubble::before{content:"";position:absolute;z-index:0;right:-7px;bottom:0;width:16px;height:17px;border-bottom-left-radius:14px;background:var(--setto-chat-bubble)}.setto-chat__message--visitor .setto-chat__message-bubble::after{content:"";position:absolute;z-index:1;right:-10px;bottom:0;width:10px;height:18px;border-bottom-left-radius:10px;background:var(--setto-chat-canvas)}.setto-chat__message--system{justify-content:center;color:color-mix(in srgb,var(--setto-chat-ink) 55%,transparent);font-size:.78rem;line-height:1.45;text-align:center}.setto-chat__message--system .setto-chat__message-stack{max-width:85%;align-items:center}.setto-chat__message--system .setto-chat__message-bubble{padding:.25rem .6rem;background:transparent}.setto-chat__avatar{position:relative;z-index:3;display:grid;place-items:center;flex:0 0 34px;width:34px;height:34px;margin-bottom:1px;overflow:hidden;border:2px solid var(--setto-chat-canvas);border-radius:50%;background:var(--setto-chat-crema);color:var(--setto-chat-ink);box-shadow:0 2px 8px color-mix(in srgb,var(--setto-chat-ink) 14%,transparent)}.setto-chat__avatar--assistant{background:var(--setto-chat-accent);color:var(--setto-chat-raised)}.setto-chat__avatar img{display:block;width:100%;height:100%;object-fit:cover}.setto-chat__speaker{display:block;margin:0 0 .2rem .4rem;color:color-mix(in srgb,var(--setto-chat-ink) 52%,transparent);font-size:.69rem;font-weight:500;line-height:1.2}.setto-chat__typing{display:inline-block;animation:setto-chat-pulse 1s ease-in-out infinite}.setto-chat__image{display:block;width:max-content;max-width:100%;margin-top:.65rem;overflow:hidden;border-radius:13px}.setto-chat__image img{display:block;width:min(280px,100%);max-height:260px;object-fit:cover}
23000
22902
  .setto-chat__composer-shell{position:absolute;left:0;right:0;bottom:0;z-index:25;display:grid;grid-template-columns:minmax(0,1fr);padding:1.5rem .75rem 0;background:transparent;isolation:isolate}.setto-chat__composer-shell::before{content:"";position:absolute;inset:0;pointer-events:none;background:linear-gradient(to bottom,transparent 0%,color-mix(in srgb,var(--setto-chat-canvas) 82%,transparent) 46%,var(--setto-chat-canvas) 66%);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);-webkit-mask-image:linear-gradient(to bottom,rgba(0,0,0,0) 0%,rgba(0,0,0,.4) 34%,rgba(0,0,0,1) 66%);mask-image:linear-gradient(to bottom,rgba(0,0,0,0) 0%,rgba(0,0,0,.4) 34%,rgba(0,0,0,1) 66%)}.setto-chat__composer{position:relative;z-index:1;display:flex;flex-direction:column;gap:.15rem;width:100%;min-width:0;margin:0;padding:.35rem .4rem;border:2px solid color-mix(in srgb,var(--setto-chat-ink) 10%,transparent);border-radius:24px;background:var(--setto-chat-canvas);box-shadow:0 8px 24px -16px color-mix(in srgb,var(--setto-chat-ink) 28%,transparent);transition:padding 220ms cubic-bezier(.16,1,.3,1),border-color 200ms ease,box-shadow 360ms cubic-bezier(.16,1,.3,1)}.setto-chat__composer.is-open{padding:.55rem .5rem}.setto-chat__composer:focus-within{border-color:var(--setto-chat-accent)}.setto-chat__composer textarea,.setto-chat__composer textarea:hover,.setto-chat__composer textarea:focus,.setto-chat__composer textarea:focus-visible{width:100%;min-height:36px;max-height:200px;padding:.45rem .25rem;resize:none;-webkit-appearance:none!important;appearance:none!important;border:0!important;border-radius:0!important;outline:0!important;box-shadow:none!important;background:transparent!important;color:var(--setto-chat-ink);font-family:"Archivo Variable",Archivo,system-ui,sans-serif;font-size:16px;line-height:1.35;transition:min-height 220ms cubic-bezier(.16,1,.3,1)}.setto-chat__composer.is-open textarea{min-height:40px}.setto-chat__composer textarea::placeholder{color:color-mix(in srgb,var(--setto-chat-ink) 52%,transparent)}.setto-chat__composer-tools{display:flex;align-items:center;gap:.4rem;width:100%;min-width:0}.setto-chat__attach{flex:none;width:34px;height:34px;padding:0;border:0;border-radius:50%;background:transparent;color:color-mix(in srgb,var(--setto-chat-ink) 58%,transparent);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background 160ms ease,color 160ms ease}.setto-chat__attach:hover:not(:disabled){background:color-mix(in srgb,var(--setto-chat-ink) 6%,transparent);color:var(--setto-chat-ink)}.setto-chat__attach:disabled{opacity:.4;cursor:default}.setto-chat__send{flex:none;width:36px;height:36px;margin-left:auto;padding:0;border:0;border-radius:50%;background:var(--setto-chat-accent);color:var(--setto-chat-raised);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:transform 360ms cubic-bezier(.16,1,.3,1),box-shadow 360ms cubic-bezier(.16,1,.3,1),background 200ms ease,opacity 200ms ease}.setto-chat__send:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 12px 24px -12px color-mix(in srgb,var(--setto-chat-ink) 45%,transparent)}.setto-chat__send:active:not(:disabled){transform:translateY(0);box-shadow:0 4px 10px -8px color-mix(in srgb,var(--setto-chat-ink) 40%,transparent);transition-duration:90ms}.setto-chat__send:disabled{opacity:.35;cursor:default}.setto-chat__send.is-queued{animation:setto-chat-queued 1.1s ease-in-out infinite}.setto-chat__attachments{display:flex;flex-wrap:wrap;gap:.4rem;list-style:none;margin:0;padding:.15rem .15rem 0}.setto-chat__attachments li{position:relative;width:56px;height:56px;border-radius:10px;overflow:hidden;border:1px solid color-mix(in srgb,var(--setto-chat-ink) 12%,transparent);background:var(--setto-chat-crema)}.setto-chat__attachments img{display:block;width:100%;height:100%;object-fit:cover}.setto-chat__attachments button{position:absolute;top:2px;right:2px;width:18px;height:18px;padding:0;border:0;border-radius:50%;background:color-mix(in srgb,var(--setto-chat-ink) 72%,transparent);color:#fff;display:inline-flex;align-items:center;justify-content:center;cursor:pointer}.setto-chat__composer-floor{position:relative;z-index:1;width:calc(100% + 1.5rem);height:max(.35rem,env(safe-area-inset-bottom));margin-left:-.75rem;background:var(--setto-chat-canvas)}
23001
22903
  .setto-chat__launcher{width:58px;height:58px;padding:3px;border:1px solid rgba(255,255,255,.54);border-radius:50%;background:color-mix(in srgb,var(--setto-chat-raised) 35%,transparent);box-shadow:0 10px 30px color-mix(in srgb,var(--setto-chat-ink) 24%,transparent),inset 0 0 0 1px color-mix(in srgb,var(--setto-chat-ink) 9%,transparent);backdrop-filter:blur(14px) saturate(115%);-webkit-backdrop-filter:blur(14px) saturate(115%);color:var(--setto-chat-ink);display:grid;place-items:center;cursor:pointer;transition:transform 180ms ease,box-shadow 180ms ease}.setto-chat__launcher:hover{transform:translateY(-2px);box-shadow:0 15px 35px color-mix(in srgb,var(--setto-chat-ink) 28%,transparent),inset 0 0 0 1px color-mix(in srgb,var(--setto-chat-ink) 9%,transparent)}.setto-chat__launcher span{width:46px;height:46px;border-radius:50%;display:grid;place-items:center;background:var(--setto-chat-accent);color:var(--setto-chat-raised)}.setto-chat__launcher img{display:block;width:50px;height:50px;border-radius:50%;object-fit:cover}.setto-chat__launcher:focus-visible,.setto-chat button:focus-visible,.setto-chat input:focus-visible{outline:2px solid var(--setto-chat-accent);outline-offset:2px}@keyframes setto-chat-pulse{50%{opacity:.35}}@keyframes setto-chat-queued{50%{opacity:.55}}
23002
- @media(max-width:700px){.setto-chat__chats{position:absolute;inset:0 auto 0 0;transform:translateX(-100%);transition:transform 260ms cubic-bezier(.16,1,.3,1);box-shadow:14px 0 35px color-mix(in srgb,var(--setto-chat-ink) 16%,transparent)}.setto-chat__chats--open{transform:none}.setto-chat__main{width:100%;max-width:none;margin:0}.setto-chat__log{padding-left:.75rem;padding-right:.75rem}.setto-chat__lead-grid{grid-template-columns:1fr}.setto-chat__actions{gap:1.1rem}.setto-chat__actions button{font-size:.88rem}}@media(min-width:700px){.setto-chat__header,.setto-chat__log{padding-left:1.25rem;padding-right:1.25rem}.setto-chat__composer-shell{padding-left:1.25rem;padding-right:1.25rem}.setto-chat__composer-floor{width:calc(100% + 2.5rem);margin-left:-1.25rem}.setto-chat__message{font-size:16.5px}}@media(prefers-reduced-motion:reduce){.setto-chat,.setto-chat__shell,.setto-chat__chats,.setto-chat__launcher,.setto-chat__composer,.setto-chat__composer textarea,.setto-chat__send{transition:none!important}.setto-chat__typing,.setto-chat__send.is-queued{animation:none}}
22904
+ @media(max-width:700px){.setto-chat__chats{position:absolute;inset:0 auto 0 0;transform:translateX(-100%);transition:transform 260ms cubic-bezier(.16,1,.3,1);box-shadow:14px 0 35px color-mix(in srgb,var(--setto-chat-ink) 16%,transparent)}.setto-chat__chats--open{transform:none}.setto-chat__main{width:100%;max-width:none;margin:0}.setto-chat__log{padding-left:.75rem;padding-right:.75rem}}@media(min-width:700px){.setto-chat__header,.setto-chat__log{padding-left:1.25rem;padding-right:1.25rem}.setto-chat__composer-shell{padding-left:1.25rem;padding-right:1.25rem}.setto-chat__composer-floor{width:calc(100% + 2.5rem);margin-left:-1.25rem}.setto-chat__message{font-size:16.5px}}@media(prefers-reduced-motion:reduce){.setto-chat,.setto-chat__shell,.setto-chat__chats,.setto-chat__launcher,.setto-chat__composer,.setto-chat__composer textarea,.setto-chat__send{transition:none!important}.setto-chat__typing,.setto-chat__send.is-queued{animation:none}}
23003
22905
  `;
23004
22906
  document.head.appendChild(style);
23005
22907
  return () => style.remove();