PageSourceSearch

https://assets.bbb.org/header-footer/8f221d988ef29c230549c78e8c79e311a2e81fd5/assets/js/scripts.js

js bbb.org collected 2026-09-24 07:34:03 UTC 72,053 bytes, 1,673 lines download raw bytes

1import { g as getCookie, c as countries, s as setCookie, d as defaultExpiration, a as BaseCustomSelect, B as BaseAutocomplete } from "./BaseAutocomplete.js";
2const userTypes = {
3  business: "business",
4  consumer: "consumer",
5  both: "both"
6};
7class MyAccount extends HTMLElement {
8  constructor() {
9    super();
10    const params = new Proxy(new URLSearchParams(window.location.search), {
11      get: (searchParams, prop) => searchParams.get(prop)
12    });
13    this.useRedesign = window.headerFooterData.isMyBbbRedesignEnabled || params.useMenuRedesign === "true";
14    this.render = () => {
15      this.setButtonOnClick();
16      try {
17        this.initData();
18      } catch {
19        this.user = null;
20      }
21      this.updateButtonLabel();
22      clearInterval(this.cookieInterval);
23      this.cookieInterval = window.setInterval(this.checkAuthState, 5e3);
24    };
25  }
26  connectedCallback() {
27    this.render();
28  }
29  disconnectedCallback() {
30    clearInterval(this.cookieInterval);
31  }
32  checkAuthState = () => {
33    const isLoggedIn = getCookie("iabbb_auth_login_hint") === "true";
34    if (!this.user && isLoggedIn) {
35      this.initData();
36    } else if (this.user && !isLoggedIn) {
37      this.user = null;
38    }
39    this.updateButtonLabel();
40  };
41  initData = () => {
42    if (this.user) {
43      return;
44    }
45    if (getCookie("iabbb_auth_login_hint") !== "true") {
46      this.user = null;
47      return;
48    }
49    const userTypeCode = getCookie("iabbb_auth_user_type");
50    let userType;
51    if (userTypeCode === "b") {
52      userType = userTypes.business;
53    } else if (userTypeCode === "bc") {
54      userType = userTypes.both;
55    } else {
56      userType = userTypes.consumer;
57    }
58    this.user = { userType };
59  };
60  buildAndOpenRedesignDialog = () => {
61    const closeIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512" fill="currentColor" aria-hidden="true" focusable="false" width="1em" height="1em"><path d="M7.5 105c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l151 151 151-151c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-151 151 151 151c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-151-151-151 151c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l151-151-151-151z"/></svg>`;
62    const visuallyHiddenLabel = `<span class="visually-hidden">close account dialog</span>`;
63    const closeButton = document.createElement("button");
64    closeButton.className = "account-close-button bds-button-unstyled";
65    closeButton.innerHTML = `${closeIcon}${visuallyHiddenLabel}`;
66    const dialog = document.createElement("dialog");
67    dialog.className = "account-dialog-redesign";
68    dialog.setAttribute("data-has-user", this.user ? "true" : "false");
69    closeButton.onclick = () => {
70      this.destroyRedesignDialog();
71      this.querySelector("button").focus();
72    };
73    dialog.appendChild(closeButton);
74    const chevronRightIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" fill="currentColor" aria-hidden="true" focusable="false" width="1em" height="1em"><path d="M311.1 233.4c12.5 12.5 12.5 32.8 0 45.3l-192 192c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L243.2 256 73.9 86.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l192 192z"/></svg>`;
75    if (this.user) {
76      const loggedInSection = document.createElement("div");
77      loggedInSection.className = "account-links-section";
78      dialog.appendChild(loggedInSection);
79      const bbbAccountHeading = document.createElement("h3");
80      bbbAccountHeading.innerText = "BBB Account";
81      bbbAccountHeading.className = "bbb-account-heading";
82      loggedInSection.appendChild(bbbAccountHeading);
83      const accountDivider = document.createElement("div");
84      accountDivider.className = "account-dialog-slim-divider";
85      loggedInSection.appendChild(accountDivider);
86      const linksSection = document.createElement("div");
87      linksSection.className = "account-links-list";
88      loggedInSection.appendChild(linksSection);
89      if (this.user.userType === userTypes.business || this.user.userType === userTypes.both) {
90        const businessPortalLink = document.createElement("a");
91        businessPortalLink.href = `${window.headerFooterData.baseUrl}/account/bid-selector`;
92        businessPortalLink.className = "account-dialog-link";
93        businessPortalLink.innerHTML = `
94          <span class="account-dialog-link-text">Business Portal</span>
95          <span class="account-dialog-link-chevron" aria-hidden="true">${chevronRightIcon}</span>
96        `;
97        linksSection.appendChild(businessPortalLink);
98      }
99      if (this.user.userType === userTypes.consumer || this.user.userType === userTypes.both) {
100        const reviewsLink = document.createElement("a");
101        reviewsLink.href = `${window.headerFooterData.baseUrl}/account/reviews`;
102        reviewsLink.className = "account-dialog-link";
103        reviewsLink.innerHTML = `
104          <span class="account-dialog-link-text">Reviews</span>
105          <span class="account-dialog-link-chevron" aria-hidden="true">${chevronRightIcon}</span>
106        `;
107        linksSection.appendChild(reviewsLink);
108        const complaintsLink = document.createElement("a");
109        complaintsLink.href = `${window.headerFooterData.baseUrl}/account/complaints`;
110        complaintsLink.className = "account-dialog-link";
111        complaintsLink.innerHTML = `
112          <span class="account-dialog-link-text">Complaints</span>
113          <span class="account-dialog-link-chevron" aria-hidden="true">${chevronRightIcon}</span>
114        `;
115        linksSection.appendChild(complaintsLink);
116        const scamsLink = document.createElement("a");
117        scamsLink.href = `${window.headerFooterData.baseUrl}/account/scams`;
118        scamsLink.className = "account-dialog-link";
119        scamsLink.innerHTML = `
120          <span class="account-dialog-link-text">Scams</span>
121          <span class="account-dialog-link-chevron" aria-hidden="true">${chevronRightIcon}</span>
122        `;
123        linksSection.appendChild(scamsLink);
124      }
125      const myAccountLink = document.createElement("a");
126      myAccountLink.href = `${window.headerFooterData.baseUrl}/account/home`;
127      myAccountLink.className = "account-dialog-link";
128      myAccountLink.innerHTML = `
129        <span class="account-dialog-link-text">Profile</span>
130        <span class="account-dialog-link-chevron" aria-hidden="true">${chevronRightIcon}</span>
131      `;
132      linksSection.appendChild(myAccountLink);
133      if (this.user.userType === userTypes.consumer) {
134        const registerBusinessLink = document.createElement("a");
135        registerBusinessLink.className = "register-account-link";
136        registerBusinessLink.innerText = "Register for a Business Account";
137        registerBusinessLink.href = `${window.headerFooterData.baseUrl}/account/register/business`;
138        linksSection.appendChild(registerBusinessLink);
139      } else if (this.user.userType === userTypes.business) {
140        const registerConsumerLink = document.createElement("a");
141        registerConsumerLink.className = "register-account-link";
142        registerConsumerLink.innerText = "Register for a Personal Account";
143        registerConsumerLink.href = `${window.headerFooterData.baseUrl}/account/register/personal`;
144        linksSection.appendChild(registerConsumerLink);
145      }
146    } else {
147      const notLoggedInSection = document.createElement("div");
148      notLoggedInSection.className = "access-your-account-section";
149      dialog.appendChild(notLoggedInSection);
150      const accessAccountHeading = document.createElement("h3");
151      accessAccountHeading.innerText = "Access Your BBB Account";
152      accessAccountHeading.className = "access-account-heading";
153      notLoggedInSection.appendChild(accessAccountHeading);
154      const accessDivider = document.createElement("div");
155      accessDivider.className = "account-dialog-divider";
156      notLoggedInSection.appendChild(accessDivider);
157      const signInOrRegisterSection = document.createElement("div");
158      signInOrRegisterSection.className = "sign-in-or-register-section";
159      notLoggedInSection.appendChild(signInOrRegisterSection);
160      const signInBlurb = document.createElement("div");
161      signInBlurb.className = "sign-in-blurb";
162      signInBlurb.innerHTML = `<span class="sign-in-emphasis">Sign in</span> or <span class="sign-in-emphasis">register</span> for an <span class="sign-in-emphasis">Account</span> to manage your business or personal interactions with BBB.`;
163      signInOrRegisterSection.appendChild(signInBlurb);
164      const signInLink = document.createElement("a");
165      signInLink.innerText = "Sign In";
166      signInLink.className = "bds-cta";
167      signInLink.setAttribute("data-type", "featured");
168      signInLink.href = `${window.headerFooterData.baseUrl}/account/login`;
169      signInOrRegisterSection.appendChild(signInLink);
170      const signInDivider = document.createElement("div");
171      signInDivider.className = "account-dialog-divider";
172      signInOrRegisterSection.appendChild(signInDivider);
173      const registerLink = document.createElement("a");
174      registerLink.innerText = "Register for an account";
175      registerLink.className = "register-link";
176      registerLink.href = `${window.headerFooterData.baseUrl}/account/register/personal`;
177      signInOrRegisterSection.appendChild(registerLink);
178    }
179    if (window.headerFooterData?.bbb?.name) {
180      const localBbbDivider = document.createElement("div");
181      localBbbDivider.className = "account-dialog-slim-divider";
182      dialog.appendChild(localBbbDivider);
183      const localBbbSection = document.createElement("div");
184      localBbbSection.className = "account-local-bbb-section";
185      const localBbbHeading = document.createElement("h3");
186      localBbbHeading.id = "localBbbHeading";
187      localBbbHeading.innerText = "Local BBB";
188      localBbbSection.appendChild(localBbbHeading);
189      const houseBuildingIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512" aria-hidden="true" focusable="false" width="1em" height="1em" fill="currentColor"><path d="M368 0c-26.5 0-48 21.5-48 48V153.9l64 58.7V208c0-8.8 7.2-16 16-16h32c8.8 0 16 7.2 16 16v32c0 8.8-7.2 16-16 16H413.2c1.9 6.8 2.8 13.9 2.8 21.1V288h16c8.8 0 16 7.2 16 16v32c0 8.8-7.2 16-16 16H416V464c0 18-6 34.6-16 48H592c26.5 0 48-21.5 48-48V48c0-26.5-21.5-48-48-48H368zM512 208c0-8.8 7.2-16 16-16h32c8.8 0 16 7.2 16 16v32c0 8.8-7.2 16-16 16H528c-8.8 0-16-7.2-16-16V208zm16 80h32c8.8 0 16 7.2 16 16v32c0 8.8-7.2 16-16 16H528c-8.8 0-16-7.2-16-16V304c0-8.8 7.2-16 16-16zM400 96h32c8.8 0 16 7.2 16 16v32c0 8.8-7.2 16-16 16H400c-8.8 0-16-7.2-16-16V112c0-8.8 7.2-16 16-16zm112 16c0-8.8 7.2-16 16-16h32c8.8 0 16 7.2 16 16v32c0 8.8-7.2 16-16 16H528c-8.8 0-16-7.2-16-16V112zM0 277.1V464c0 26.5 21.5 48 48 48H336c26.5 0 48-21.5 48-48V277.1c0-13.5-5.6-26.3-15.6-35.4l-144-132c-18.4-16.8-46.5-16.8-64.9 0l-144 132C5.6 250.8 0 263.7 0 277.1zM144 296c0-13.3 10.7-24 24-24h48c13.3 0 24 10.7 24 24v48c0 13.3-10.7 24-24 24H168c-13.3 0-24-10.7-24-24V296z"/></svg>`;
190      const localBbbCard = document.createElement("div");
191      localBbbCard.className = "account-local-bbb-card";
192      const localBbbLink = document.createElement("a");
193      localBbbLink.className = "account-local-bbb-link";
194      localBbbLink.href = window.headerFooterData?.bbb?.url || "/bbb-directory";
195      localBbbLink.innerHTML = `
196        <span class="account-local-bbb-label">
197          <span class="account-local-bbb-icon" aria-hidden="true">${houseBuildingIcon}</span>
198          <span class="account-local-bbb-text">
199            <span class="account-local-bbb-name">${window.headerFooterData.bbb.name}</span>
200          </span>
201        </span>
202        <span class="account-local-bbb-chevron" aria-hidden="true">${chevronRightIcon}</span>
203      `;
204      const changeLink = document.createElement("a");
205      changeLink.href = `${window.headerFooterData.baseUrl}/manage-location`;
206      changeLink.id = "changeBbbLink";
207      changeLink.className = "change-bbb-link";
208      changeLink.setAttribute("aria-labelledby", "changeBbbLink localBbbHeading");
209      changeLink.innerText = "Change";
210      localBbbCard.appendChild(localBbbLink);
211      localBbbCard.appendChild(changeLink);
212      localBbbSection.appendChild(localBbbCard);
213      dialog.appendChild(localBbbSection);
214    }
215    if (this.user) {
216      const signOutButton = document.createElement("a");
217      signOutButton.className = "sign-out-button-redesign";
218      signOutButton.innerText = "Sign Out";
219      const signOutReturnUrl = window.location.pathname.startsWith("/account") ? `${window.headerFooterData.baseUrl}/account/login` : window.location.href;
220      signOutButton.href = `${window.headerFooterData.baseUrl}/account/logout?returnUrl=${encodeURIComponent(signOutReturnUrl)}`;
221      dialog.appendChild(signOutButton);
222    }
223    document.body.appendChild(dialog);
224    this.updateDialogPosition(dialog);
225    dialog.showModal();
226    dialog.addEventListener("click", (e) => {
227      const dialogDimensions = dialog.getBoundingClientRect();
228      if (e.clientX < dialogDimensions.left || e.clientX > dialogDimensions.right || e.clientY < dialogDimensions.top || e.clientY > dialogDimensions.bottom) {
229        dialog.close();
230        this.destroyRedesignDialog();
231      }
232    });
233    dialog.addEventListener("close", () => {
234      if (document.querySelector(".account-dialog-redesign")) {
235        this.destroyRedesignDialog();
236      }
237      this.querySelector("button").focus();
238    });
239    window.addEventListener("resize", this.handleRedesignDialogPositionOnResize, { passive: true });
240  };
241  handleLegacyDialogPositionOnResize = () => {
242    const dialogToListen = document.querySelector(".account-dialog");
243    this.updateDialogPosition(dialogToListen);
244  };
245  handleRedesignDialogPositionOnResize = () => {
246    const dialogToListen = document.querySelector(".account-dialog-redesign");
247    this.updateDialogPosition(dialogToListen);
248  };
249  updateDialogPosition = (dialog) => {
250    const buttonBoundingClientRect = this.querySelector("button").getBoundingClientRect();
251    if (!dialog || buttonBoundingClientRect.left === 0) {
252      return;
253    }
254    const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
255    if (vw < 768) {
256      dialog.style.left = "revert";
257    } else {
258      const desktopDialogWidth = this.user ? 300 : 500;
259      dialog.style.left = `${buttonBoundingClientRect.right - desktopDialogWidth}px`;
260    }
261    dialog.style.top = `${buttonBoundingClientRect.top}px`;
262  };
263  destroyRedesignDialog = () => {
264    const dialog = document.querySelector(".account-dialog-redesign");
265    if (dialog) {
266      dialog.remove();
267    }
268    window.removeEventListener("resize", this.handleRedesignDialogPositionOnResize);
269  };
270  /**
271   * Emit a custom event
272   * @param {string} name - The event name
273   * @param {object} detail - Any details to pass along with the event
274   */
275  emit = (name, detail = {}) => {
276    const event = new CustomEvent(name, {
277      bubbles: true,
278      cancelable: true,
279      composed: true,
280      detail
281    });
282    return this.dispatchEvent(event);
283  };
284  setButtonOnClick = () => {
285    const btn = this.querySelector("button");
286    btn.onclick = () => {
287      this.buildAndOpenRedesignDialog();
288    };
289  };
290  updateButtonLabel = () => {
291    const label = this.querySelector(".my-account-label");
292    if (!label) {
293      return;
294    }
295    label.textContent = this.user ? "My account" : "Sign in";
296  };
297}
298customElements.define("iabbb-my-account", MyAccount);
299function waitForSatellite(callback, onTimeout, timeout = 5e3, interval = 200) {
300  const start = Date.now();
301  (function check() {
302    if (window._satellite) {
303      callback();
304    } else if (Date.now() - start < timeout) {
305      setTimeout(check, interval);
306    } else {
307      onTimeout();
308    }
309  })();
310}
311const queue = [];
312let waitingForSatellite = false;
313function fire({ name, dataLayerProperties }) {
314  if (dataLayerProperties !== null && window.webDigitalData) {
315    window.webDigitalData = {
316      ...window.webDigitalData,
317      direct_call: dataLayerProperties
318    };
319  }
320  window._satellite.track(name);
321}
322function drainQueue() {
323  waitingForSatellite = false;
324  while (queue.length > 0) {
325    fire(queue.shift());
326  }
327}
328const aaTrackEvent = (name, dataLayerProperties = null) => {
329  queue.push({
330    name,
331    dataLayerProperties: dataLayerProperties !== null ? { ...dataLayerProperties } : null
332  });
333  if (window._satellite) {
334    drainQueue();
335    return;
336  }
337  if (!waitingForSatellite) {
338    waitingForSatellite = true;
339    waitForSatellite(drainQueue, () => {
340      waitingForSatellite = false;
341    });
342  }
343};
344const HEADER_LANGUAGE_DROPDOWN_OPEN = "header_language_dropdown_open";
345const HEADER_LANGUAGE_SWITCH = "header_language_switch";
346const trackLanguageDropdownOpen = () => {
347  aaTrackEvent(HEADER_LANGUAGE_DROPDOWN_OPEN);
348};
349const gtranslateScriptUrl = "https://cdn.gtranslate.net/widgets/latest/ln.js";
350const defaultSettings = {
351  default_language: "en",
352  native_language_names: true,
353  languages: ["en", "es", "fr", "zh-CN", "tr", "ru", "ja", "vi", "pt"],
354  wrapper_selector: ".gtranslate_wrapper",
355  alt_flags: { en: "usa", es: "mexico", pt: "brazil" }
356};
357let windowLoadPromise;
358let widgetLoadPromise;
359const waitForWindowLoad = () => {
360  if (document.readyState === "complete") {
361    return Promise.resolve();
362  }
363  windowLoadPromise ??= new Promise((resolve) => {
364    window.addEventListener("load", resolve, { once: true });
365  });
366  return windowLoadPromise;
367};
368const hasLanguageLinks = () => document.querySelector(".gtranslate_wrapper a[data-gt-lang]") !== null;
369const loadWidget = () => new Promise((resolve) => {
370  const script = document.createElement("script");
371  script.src = gtranslateScriptUrl;
372  script.dataset.iabbbGtranslateLoader = "true";
373  script.addEventListener("load", resolve, { once: true });
374  script.addEventListener("error", resolve, { once: true });
375  document.head.append(script);
376});
377const ensureGTranslate = async () => {
378  await waitForWindowLoad();
379  if (hasLanguageLinks()) {
380    return;
381  }
382  window.gtranslateSettings ??= defaultSettings;
383  widgetLoadPromise ??= loadWidget();
384  await widgetLoadPromise;
385  widgetLoadPromise = void 0;
386};
387const trackLanguageSwitch = ({ languageCode }) => {
388  if (document.documentElement.lang === languageCode) {
389    return;
390  }
391  aaTrackEvent(HEADER_LANGUAGE_SWITCH, {
392    language_code: languageCode
393  });
394};
395const languageDisplayMap = {
396  en: "EN",
397  es: "ES",
398  fr: "FR",
399  "zh-CN": "ZH",
400  tr: "TR",
401  ru: "RU",
402  ja: "JA",
403  vi: "VI",
404  pt: "PT"
405};
406const updateLangLink = (link, closeFunc) => {
407  const langCode = link.getAttribute("data-gt-lang");
408  if (!languageDisplayMap[langCode] || link.dataset.iabbbLanguageLinkEnhanced === "true") {
409    return;
410  }
411  link.dataset.iabbbLanguageLinkEnhanced = "true";
412  const languageName = link.textContent;
413  const languageCode = document.createElement("span");
414  languageCode.className = "language-list-code";
415  languageCode.textContent = languageDisplayMap[langCode];
416  link.replaceChildren(languageCode, languageName);
417  link.addEventListener("click", () => {
418    trackLanguageSwitch({ languageCode: langCode });
419    closeFunc();
420  });
421};
422class NavMenu extends HTMLElement {
423  connectedCallback() {
424    this.moveHeaderMenu();
425    this.replaceLinkWithButton();
426    document.addEventListener("keydown", this.escapeHandler);
427    this.addEventListener("click", this.clickEventHandler);
428    this.collapseSubnavs();
429    this.setUpLanguageMenu();
430    this.languageLinksObserver = new MutationObserver(this.setUpLanguageMenu);
431    this.languageLinksObserver.observe(this, { childList: true, subtree: true });
432  }
433  disconnectedCallback() {
434    document.removeEventListener("keydown", this.escapeHandler);
435    document.removeEventListener("click", this.lightDismissHandler);
436    this.removeEventListener("click", this.clickEventHandler);
437    this.languageLinksObserver?.disconnect();
438  }
439  clickEventHandler = (event) => {
440    const subnavButton = event.target.closest(".has-subnav button");
441    if (subnavButton) {
442      this.toggleSubnav(subnavButton);
443      return;
444    }
445    const languageButton = event.target.closest(".language-dropdown-link");
446    if (languageButton) {
447      if (languageButton.getAttribute("aria-expanded") === "false") {
448        trackLanguageDropdownOpen();
449      }
450      this.toggleSubnav(languageButton);
451    }
452  };
453  /**
454   * Emit a custom event
455   * @param {string} type - The event type
456   * @param {object} detail - Any details to pass along with the event
457   */
458  emit = (type, detail = {}) => {
459    const event = new CustomEvent(`${this.localName}:${type}`, {
460      bubbles: true,
461      cancelable: true,
462      detail
463    });
464    return this.dispatchEvent(event);
465  };
466  collapseSubnavs = () => {
467    for (const liWithSubnav of this.querySelectorAll(".has-subnav")) {
468      const linkId = liWithSubnav.querySelector("a").getAttribute("id");
469      const expandBtn = document.createElement("button");
470      expandBtn.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" aria-hidden="true" focusable="false" height="1em" width="1em"><path d="M241 337c-9.4 9.4-24.6 9.4-33.9 0L47 177c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l143 143L367 143c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9L241 337z"></path></svg>`;
471      expandBtn.setAttribute("aria-expanded", "false");
472      expandBtn.setAttribute("aria-labelledby", linkId);
473      liWithSubnav.insertBefore(expandBtn, liWithSubnav.querySelector("ul"));
474    }
475    for (const mainNavLink of this.querySelectorAll("#headerNavMenu ul > li a")) {
476      mainNavLink.addEventListener("click", (e) => {
477        this.emit("click-main-link", { label: e.currentTarget.innerText });
478      });
479    }
480    for (const subNavLink of this.querySelectorAll("#headerNavMenu ul > li ul a")) {
481      subNavLink.addEventListener("click", (e) => {
482        const parentElement = e.currentTarget.closest("li").closest("ul").closest("li");
483        if (!parentElement) {
484          return;
485        }
486        this.emit("click-sub-link", { label: e.currentTarget.innerText, parentLabel: parentElement.innerText });
487      });
488    }
489  };
490  replaceLinkWithButton = () => {
491    const link = this.querySelector('[href="#headerNavMenu"]');
492    if (!link) {
493      return;
494    }
495    const btn = document.createElement("button");
496    btn.innerHTML = link.innerHTML;
497    btn.className = link.className;
498    btn.setAttribute("aria-expanded", "false");
499    link.replaceWith(btn);
500    btn.addEventListener("click", this.toggleMenu);
501  };
502  moveHeaderMenu() {
503    const navMenu = document.getElementById("headerNavMenu");
504    this.querySelector("nav").append(navMenu);
505  }
506  toggleMenu = () => {
507    const isOpen = this.querySelector("button").getAttribute("aria-expanded") === "true";
508    if (isOpen) {
509      this.closeMenu();
510    } else {
511      document.addEventListener("keydown", this.escapeHandler);
512      this.addEventListener("focusout", this.focusOutHandler);
513      document.addEventListener("click", this.lightDismissHandler);
514      this.querySelector("nav").setAttribute("data-open", "true");
515      this.querySelector("button").setAttribute("aria-expanded", "true");
516      this.trackMenuOpen();
517    }
518  };
519  closeMenu = () => {
520    document.removeEventListener("keydown", this.escapeHandler);
521    this.removeEventListener("focusout", this.focusOutHandler);
522    document.removeEventListener("click", this.lightDismissHandler);
523    this.querySelector("nav").removeAttribute("data-open");
524    this.querySelector("button").setAttribute("aria-expanded", "false");
525    for (const subnavButton of this.querySelectorAll('.nav-menu button[aria-expanded="true"]')) {
526      subnavButton.setAttribute("aria-expanded", "false");
527    }
528    this.trackMenuClose();
529  };
530  trackMenuOpen = () => {
531    this.querySelector("button").classList.remove("dtm-header-menu-button-closed");
532    this.querySelector("button").classList.add("dtm-header-menu-button-opened");
533    this.emit("expanded");
534  };
535  trackMenuClose = () => {
536    this.querySelector("button").classList.remove("dtm-header-menu-button-opened");
537    this.querySelector("button").classList.add("dtm-header-menu-button-closed");
538    this.emit("collapsed");
539  };
540  toggleSubnav = (node) => {
541    const isCurrentlyExpanded = node.getAttribute("aria-expanded");
542    this.emit("toggle-subnav", {
543      label: node.innerText,
544      isCurrentlyExpanded
545    });
546    node.setAttribute("aria-expanded", isCurrentlyExpanded === "false" ? "true" : "false");
547  };
548  escapeHandler = (e) => {
549    if (e.isComposing) {
550      return;
551    }
552    const isOpen = this.querySelector("button").getAttribute("aria-expanded") === "true";
553    if (e.key === "Escape" && isOpen) {
554      this.toggleMenu();
555    }
556  };
557  lightDismissHandler = (event) => {
558    if (!event.composedPath().includes(this)) {
559      this.toggleMenu();
560    }
561  };
562  focusOutHandler = (event) => {
563    if (!event.relatedTarget) {
564      return;
565    }
566    const menuContainsFocus = this.contains(event.relatedTarget);
567    if (!menuContainsFocus) {
568      this.closeMenu();
569    }
570  };
571  setUpLanguageMenu = () => {
572    ensureGTranslate();
573    const languageLinks = this.querySelectorAll(".language-subnav-list .gtranslate_wrapper a");
574    for (const link of languageLinks) {
575      updateLangLink(link, this.closeMenu);
576    }
577  };
578}
579customElements.define("iabbb-nav-menu", NavMenu);
580class DesktopNav {
581  constructor() {
582    this.nav = document.querySelector(".desktop-nav");
583    if (!this.nav) {
584      return;
585    }
586    this.buttons = this.nav.querySelectorAll(".desktop-nav-button");
587    this.init();
588  }
589  init() {
590    this.buttons.forEach((button) => {
591      button.addEventListener("click", (e) => this.toggleDropdown(e.currentTarget));
592    });
593    document.addEventListener("click", (e) => {
594      if (!e.target.closest(".desktop-nav-item")) {
595        this.closeAllDropdowns();
596      }
597    });
598    document.addEventListener("keydown", (e) => {
599      if (e.key === "Escape") {
600        this.closeAllDropdowns();
601      }
602    });
603  }
604  toggleDropdown(button) {
605    const isExpanded = button.getAttribute("aria-expanded") === "true";
606    this.closeAllDropdowns();
607    if (!isExpanded) {
608      button.setAttribute("aria-expanded", "true");
609    }
610  }
611  closeAllDropdowns() {
612    this.buttons.forEach((button) => {
613      button.setAttribute("aria-expanded", "false");
614    });
615  }
616}
617if (document.readyState === "loading") {
618  document.addEventListener("DOMContentLoaded", () => new DesktopNav());
619} else {
620  new DesktopNav();
621}
622class DesktopLanguageSelector extends HTMLElement {
623  connectedCallback() {
624    this.button = this.querySelector("button");
625    if (!this.button) {
626      return;
627    }
628    this.button.addEventListener("click", this.openDialog);
629    this.dialogRoot = this.closest("iabbb-header") || document.body;
630    const dialog = this.dialogRoot.querySelector(".language-dialog");
631    if (dialog) {
632      this.setupDialog(dialog);
633    } else {
634      this.dialogObserver = new MutationObserver(() => {
635        const dialog2 = this.dialogRoot.querySelector(".language-dialog");
636        if (dialog2) {
637          this.dialogObserver.disconnect();
638          this.setupDialog(dialog2);
639        }
640      });
641      this.dialogObserver.observe(this.dialogRoot, { childList: true, subtree: true });
642    }
643  }
644  disconnectedCallback() {
645    this.button?.removeEventListener("click", this.openDialog);
646    this.dialogObserver?.disconnect();
647    this.languageLinksObserver?.disconnect();
648    this.dialog?.removeEventListener("click", this.handleDialogClick);
649    this.dialog?.removeEventListener("cancel", this.handleDialogCancel);
650    this.dialog?.removeEventListener("close", this.handleDialogClose);
651  }
652  setupDialog = (dialog) => {
653    this.dialog = dialog;
654    this.setupCloseHandlers();
655    this.setupLanguageLinks();
656    this.languageLinksObserver = new MutationObserver(this.setupLanguageLinks);
657    this.languageLinksObserver.observe(dialog, { childList: true, subtree: true });
658  };
659  openDialog = () => {
660    if (!this.dialog || this.dialog.open) {
661      return;
662    }
663    trackLanguageDropdownOpen();
664    this.positionDialog();
665    this.dialog.showModal();
666    this.button.setAttribute("aria-expanded", "true");
667  };
668  closeDialog = () => {
669    if (this.dialog?.open) {
670      this.dialog.close();
671    }
672    this.resetDialogTrigger();
673  };
674  setupLanguageLinks = () => {
675    ensureGTranslate();
676    const languageLinks = this.dialog.querySelectorAll(".gtranslate_wrapper a");
677    for (const link of languageLinks) {
678      updateLangLink(link, this.closeDialog);
679    }
680  };
681  positionDialog = () => {
682    const buttonRect = this.button.getBoundingClientRect();
683    this.dialog.style.position = "fixed";
684    this.dialog.style.left = `${buttonRect.left}px`;
685    this.dialog.style.top = `${buttonRect.bottom + 8}px`;
686    this.dialog.style.margin = "0";
687  };
688  handleDialogClick = (event) => {
689    const dialogDimensions = this.dialog.getBoundingClientRect();
690    if (event.clientX < dialogDimensions.left || event.clientX > dialogDimensions.right || event.clientY < dialogDimensions.top || event.clientY > dialogDimensions.bottom) {
691      this.closeDialog();
692    }
693  };
694  handleDialogCancel = (event) => {
695    event.preventDefault();
696    this.closeDialog();
697  };
698  handleDialogClose = () => {
699    if (!this.dialog.open) {
700      this.resetDialogTrigger();
701    }
702  };
703  resetDialogTrigger = () => {
704    this.button.setAttribute("aria-expanded", "false");
705    this.button.focus();
706  };
707  setupCloseHandlers = () => {
708    this.dialog.addEventListener("click", this.handleDialogClick);
709    this.dialog.addEventListener("cancel", this.handleDialogCancel);
710    this.dialog.addEventListener("close", this.handleDialogClose);
711  };
712}
713customElements.define("iabbb-language-selector", DesktopLanguageSelector);
714class LocaleSelector extends HTMLElement {
715  constructor() {
716    super();
717    this.render = () => {
718      this.showChangeLocationView = false;
719      this.initData();
720      this.useDialogElement = false;
721      if (this.useDialogElement) {
722        this.addDialogElement();
723      }
724      this.replaceLinkWithButton();
725    };
726  }
727  connectedCallback() {
728    this.render();
729  }
730  initData = () => {
731    const rawCookie = getCookie("iabbb_user_location");
732    const userLocationId = rawCookie ? decodeURIComponent(rawCookie) : null;
733    if (userLocationId) {
734      const userLocationIdParts = decodeURIComponent(userLocationId).split("_");
735      const userCountry = userLocationIdParts[userLocationIdParts.length - 1];
736      const userState = userLocationIdParts[userLocationIdParts.length - 2];
737      const userCity = userLocationIdParts.slice(0, userLocationIdParts.length - 2).join(" ");
738      if (userCountry && userState && userCity) {
739        this.userLocationName = userCountry && userState && userCity ? `${userCity}, ${userState}, ${userCountry}` : null;
740        this.userLocationUrl = `/${[
741          `${countries.find((x) => x.value === userCountry).shortLabel.toLowerCase()}`,
742          `${userState.toLowerCase()}`,
743          `${userCity.toLowerCase().replace(" ", "-")}`
744        ].join("/")}`;
745      }
746    }
747    if (window.headerFooterData?.bbb) {
748      this.bbbName = window.headerFooterData.bbb.name;
749      this.bbbUrl = window.headerFooterData.bbb.url;
750    }
751    this.hasUserLocation = this.bbbName && this.userLocationName;
752  };
753  /**
754   * Emit a custom event
755   * @param {string} name - The event name
756   * @param {object} detail - Any details to pass along with the event
757   */
758  emit = (name, detail = {}) => {
759    const event = new CustomEvent(name, {
760      bubbles: true,
761      cancelable: true,
762      composed: true,
763      detail
764    });
765    return this.dispatchEvent(event);
766  };
767  addDialogElement = () => {
768    const closeIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512" aria-hidden="true" fill="currentColor" focusable="false" height="1em" width="1em"><path d="M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3l105.4 105.3c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256l105.3-105.4z"></path></svg>`;
769    const visuallyHiddenLabel = `<span class="visually-hidden">close outage disclaimer</span>`;
770    const closeButton = document.createElement("button");
771    closeButton.className = "ls-close-button bds-button-unstyled";
772    closeButton.innerHTML = `${closeIcon}${visuallyHiddenLabel}`;
773    const dialog = document.createElement("dialog");
774    dialog.className = "locale-selector-dialog";
775    dialog.tabIndex = -1;
776    const dialogContent = document.createElement("div");
777    const formMethodDialog = document.createElement("form");
778    formMethodDialog.method = "dialog";
779    formMethodDialog.appendChild(closeButton);
780    dialogContent.appendChild(formMethodDialog);
781    dialog.appendChild(dialogContent);
782    const screen = document.createElement("div");
783    screen.id = "locale-selector-screen";
784    if (this.hasUserLocation) {
785      screen.appendChild(this.buildShowLocationDialogContent());
786    } else {
787      screen.appendChild(this.buildChangeLocationDialogContent());
788    }
789    dialogContent.appendChild(screen);
790    dialog.addEventListener("click", ({ target: dialog2 }) => {
791      if (dialog2.nodeName === "DIALOG") {
792        dialog2.close("dismiss");
793      }
794    });
795    dialog.addEventListener("close", () => {
796      if (this.showChangeLocationView) {
797        screen.innerHTML = "";
798        screen.appendChild(this.buildShowLocationDialogContent());
799        this.showChangeLocationView = false;
800      }
801    });
802    this.appendChild(dialog);
803  };
804  buildAndOpenLegacyDialog = () => {
805    const closeIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512" aria-hidden="true" fill="currentColor" focusable="false" height="1em" width="1em"><path d="M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3l105.4 105.3c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256l105.3-105.4z"></path></svg>`;
806    const visuallyHiddenLabel = `<span class="visually-hidden">close outage disclaimer</span>`;
807    const closeButton = document.createElement("button");
808    closeButton.className = "ls-close-button bds-button-unstyled";
809    closeButton.innerHTML = `${closeIcon}${visuallyHiddenLabel}`;
810    const dialog = document.createElement("div");
811    dialog.role = "dialog";
812    dialog.className = "locale-selector-dialog";
813    dialog.tabIndex = -1;
814    const dialogContent = document.createElement("div");
815    closeButton.onclick = () => {
816      this.destroyLegacyDialog();
817      this.querySelector("button").focus();
818    };
819    dialogContent.appendChild(closeButton);
820    dialog.appendChild(dialogContent);
821    const screen = document.createElement("div");
822    screen.id = "locale-selector-screen";
823    if (this.hasUserLocation) {
824      screen.appendChild(this.buildShowLocationDialogContent());
825    } else {
826      screen.appendChild(this.buildChangeLocationDialogContent());
827    }
828    dialogContent.appendChild(screen);
829    this.updateDialogPosition(dialog);
830    const dialogBackdrop = document.createElement("div");
831    dialogBackdrop.className = "locale-selector-dialog-backdrop";
832    document.body.appendChild(dialogBackdrop);
833    dialogBackdrop.addEventListener("click", () => {
834      this.destroyLegacyDialog();
835    });
836    document.body.appendChild(dialog);
837    dialog.focus();
838    dialog.addEventListener("keydown", (e) => {
839      if (e.key === "Escape") {
840        this.destroyLegacyDialog();
841        this.querySelector("button").focus();
842      }
843    });
844    window.addEventListener("resize", this.handleLegacyDialogPositionOnResize, { passive: true });
845  };
846  handleLegacyDialogPositionOnResize = () => {
847    const dialogToListen = document.querySelector(".locale-selector-dialog");
848    this.updateDialogPosition(dialogToListen);
849  };
850  destroyLegacyDialog = () => {
851    document.querySelector(".locale-selector-dialog-backdrop").remove();
852    document.querySelector(".locale-selector-dialog").remove();
853    window.removeEventListener("resize", this.handleLegacyDialogPositionOnResize);
854    for (const nonDialogElement of this.nonDialogElements) {
855      nonDialogElement.removeAttribute("inert");
856    }
857  };
858  // Use only when we rely solely on native dialog/anchor positioning
859  // updateLinkIfUserHasNoLocation = () => {
860  //   const link = this.querySelector('a');
861  //   if (!this.hasUserLocation) {
862  //     link.innerHTML = link.innerHTML.replace('My BBB', 'Set location');
863  //   }
864  // };
865  replaceLinkWithButton = () => {
866    const link = this.querySelector("a");
867    if (!link) {
868      return;
869    }
870    const btn = document.createElement("button");
871    btn.innerHTML = this.hasUserLocation ? link.innerHTML : link.innerHTML.replace("My BBB", "Set location");
872    btn.className = `${link.className} bds-button-unstyled`;
873    btn.setAttribute("aria-expanded", "false");
874    btn.onclick = (e) => {
875      this.emit(`${this.localName}:open-dialog`, {
876        label: e.target.innerText
877      });
878      if (this.useDialogElement) {
879        this.querySelector("dialog").showModal();
880        this.querySelector("dialog").focus();
881      } else {
882        this.nonDialogElements = document.querySelectorAll("body > :not(script)");
883        for (const nonDialogElement of this.nonDialogElements) {
884          nonDialogElement.setAttribute("inert", "inert");
885        }
886        this.buildAndOpenLegacyDialog();
887      }
888    };
889    link.replaceWith(btn);
890  };
891  updateDialogPosition = (dialog) => {
892    const buttonBoundingClientRect = this.querySelector("button").getBoundingClientRect();
893    dialog.style.left = `${buttonBoundingClientRect.left}px`;
894    dialog.style.top = `${buttonBoundingClientRect.top}px`;
895  };
896  buildShowLocationDialogContent = () => {
897    const linkIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" aria-hidden="true" fill="currentColor" focusable="false" height="1em" width="1em"><path d="M0 256a256 256 0 1 0 512 0 256 256 0 1 0-512 0zm241 121c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l87-87-87-87c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0L345 239c9.4 9.4 9.4 24.6 0 33.9L241 377z"></path></svg>`;
898    const locationHeading = document.createElement("h2");
899    locationHeading.tabIndex = -1;
900    locationHeading.innerText = "My Home Location";
901    const locationLink = document.createElement("a");
902    locationLink.className = "active-underline";
903    locationLink.href = this.userLocationUrl;
904    locationLink.innerHTML = `${this.userLocationName}${linkIcon}`;
905    locationLink.onclick = () => {
906      this.emit(`${this.localName}:click-location-link`, {
907        location: this.userLocationName
908      });
909    };
910    const changeLocationButton = document.createElement("button");
911    changeLocationButton.className = "bds-button-unstyled ls-change-home-location";
912    changeLocationButton.innerText = "Change home location";
913    changeLocationButton.onclick = () => {
914      this.showChangeLocationView = true;
915      document.querySelector("#locale-selector-screen").innerHTML = "";
916      document.querySelector("#locale-selector-screen").appendChild(this.buildChangeLocationDialogContent());
917      document.querySelector("#locale-selector-screen h2").focus();
918    };
919    const bbbHeading = document.createElement("h2");
920    bbbHeading.className = "my-bbb-heading";
921    bbbHeading.innerText = "My BBB";
922    const bbbLink = document.createElement("a");
923    bbbLink.className = "active-underline dtm-locale-selector-location-name";
924    bbbLink.href = this.bbbUrl;
925    bbbLink.innerHTML = `${this.bbbName}${linkIcon}`;
926    const container = document.createElement("div");
927    container.appendChild(locationHeading);
928    container.appendChild(locationLink);
929    container.appendChild(changeLocationButton);
930    container.appendChild(bbbHeading);
931    container.appendChild(bbbLink);
932    return container;
933  };
934  buildChangeLocationDialogContent = () => {
935    const legend = document.createElement("legend");
936    const heading = document.createElement("h2");
937    heading.tabIndex = -1;
938    heading.innerText = "Set Your Home Location:";
939    legend.appendChild(heading);
940    const customSelect = document.createElement("iabbb-ls-country-custom-select");
941    customSelect.className = "enhanced-select";
942    customSelect.innerHTML = `
943      <label class="visually-hidden" for="ls_country">Country</label>
944      <select id="ls_country" name="ls_country">
945        <option value="USA">United States</option>
946        <option value="CAN">Canada</option>
947      </select>
948    `;
949    const nearAutocomplete = document.createElement("iabbb-ls-autocomplete");
950    nearAutocomplete.innerHTML = `
951      <div class="input-group">
952        <label class="dtm-locale-selector-location-pin" for="ls_loc">
953          <svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 384 512" aria-hidden="true" focusable="false" height="1em" width="1em">
954            <path d="M215.7 499.2C267 435 384 279.4 384 192 384 86 298 0 192 0S0 86 0 192c0 87.4 117 243 168.3 307.2 12.3 15.3 35.1 15.3 47.4 0zM192 128a64 64 0 1 1 0 128 64 64 0 1 1 0-128z"></path>
955          </svg>
956          <span class="visually-hidden">Near</span>
957        </label>
958        <input id="ls_loc" name="ls_loc" placeholder="city, state or zip" autocomplete="off" autocapitalize="none">
959      </div>
960    `;
961    nearAutocomplete.className = "autocomplete";
962    const button = document.createElement("button");
963    button.className = "bds-button dtm-locale-selector-set-location";
964    button.innerText = "Set Location";
965    const fieldset = document.createElement("fieldset");
966    fieldset.className = "change-location";
967    fieldset.appendChild(legend);
968    fieldset.appendChild(customSelect);
969    fieldset.appendChild(nearAutocomplete);
970    fieldset.appendChild(button);
971    const form = document.createElement("form");
972    form.onsubmit = this.onLocationChangeFormSubmit;
973    form.appendChild(fieldset);
974    return form;
975  };
976  showLocationError = () => {
977    const locationError = "Location must be a valid city (e.g. Los Angeles, CA) or postal code (e.g. 90210)";
978    const warningIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" aria-hidden="true" height="1em" width="1em" fill="currentColor"><path d="M256 32c14.2 0 27.3 7.5 34.5 19.8l216 368c7.3 12.4 7.3 27.7.2 40.1S486.3 480 472 480H40c-14.3 0-27.6-7.7-34.7-20.1s-7-27.8.2-40.1l216-368C228.7 39.5 241.8 32 256 32zm0 128c-13.3 0-24 10.7-24 24v112c0 13.3 10.7 24 24 24s24-10.7 24-24V184c0-13.3-10.7-24-24-24zm32 224c0-17.7-14.3-32-32-32s-32 14.3-32 32 14.3 32 32 32 32-14.3 32-32z"></path></svg>`;
979    const inputId = document.querySelector("iabbb-ls-autocomplete input").id;
980    const error = document.createElement("span");
981    error.className = "error";
982    error.id = `${inputId}-error`;
983    error.innerHTML = `${warningIcon}${locationError}`;
984    const autocomplete = document.querySelector("iabbb-ls-autocomplete");
985    autocomplete.parentNode.insertBefore(error, autocomplete);
986    const autocompleteInput = autocomplete.querySelector("input");
987    autocompleteInput.setAttribute("aria-describedby", error.id);
988    autocompleteInput.setAttribute("aria-invalid", true);
989    autocompleteInput.focus();
990  };
991  clearLocationError = () => {
992    const error = document.querySelector(".error");
993    if (error) {
994      error.remove();
995      const autocomplete = document.querySelector("iabbb-ls-autocomplete");
996      const autocompleteInput = autocomplete.querySelector("input");
997      autocompleteInput.removeAttribute("aria-describedby");
998      autocompleteInput.removeAttribute("aria-invalid");
999    }
1000  };
1001  onLocationChangeFormSubmit = async (e) => {
1002    e.preventDefault();
1003    this.clearLocationError();
1004    const initialUserLocationId = getCookie("iabbb_user_location");
1005    const initialUserBbbId = getCookie("iabbb_user_bbb");
1006    const formValues = Object.fromEntries(new FormData(e.target));
1007    const selectedCountryName = formValues.ls_country;
1008    const selectedLocation = formValues.ls_loc;
1009    const locationId = await fetch(
1010      `${window.headerFooterData.baseUrl}/api/suggest/location?country=${selectedCountryName}&input=${selectedLocation}&maxMatches=1`,
1011      { credentials: "omit" }
1012    ).then((res) => {
1013      return res.json();
1014    }).then((matches) => {
1015      return matches.length > 0 ? matches[0].id : null;
1016    });
1017    if (locationId) {
1018      fetch(`${window.headerFooterData.baseUrl}/api/location/bbblocation?locationId=${locationId}`).then((res) => {
1019        if (!res.ok) {
1020          throw new Error(`${res.statusText} (status: ${res.status})`);
1021        }
1022        return res.json();
1023      }).then((location) => {
1024        const locationId2 = `${location.city}_${location.state}_${location.threeLetterIsoCountryCode}`;
1025        setCookie("iabbb_user_location", locationId2, defaultExpiration);
1026        setCookie("iabbb_user_postalcode", location.postalCode, defaultExpiration);
1027        if (location.bbbInfo?.bbbId) {
1028          setCookie("iabbb_user_bbb", location.bbbInfo.bbbId, defaultExpiration);
1029          window.headerFooterData = {
1030            ...window.headerFooterData || {},
1031            bbb: {
1032              name: location.bbbInfo.bbbName,
1033              url: location.bbbInfo.urls.bbbUrl
1034            }
1035          };
1036          this.bbbName = window.headerFooterData?.bbb.name;
1037          this.bbbUrl = window.headerFooterData?.bbb.url;
1038          this.userLocationUrl = `/${location.country.toLowerCase()}/${location.state.toLowerCase()}/${location.citySeo}`;
1039          this.userLocationName = `${location.city}, ${location.state}, ${location.threeLetterIsoCountryCode}`;
1040        }
1041        const nearInput = document.getElementById("find_loc");
1042        if (nearInput && !nearInput.value) {
1043          nearInput.value = location.displayText;
1044          setCookie("iabbb_find_location", locationId2, defaultExpiration);
1045        }
1046        const savedCulture = getCookie("iabbb_user_culture");
1047        const selectedCountry = countries.find((x) => x.value === selectedCountryName);
1048        if (selectedCountry.culture !== savedCulture) {
1049          setCookie("iabbb_user_culture", selectedCountry.culture, defaultExpiration);
1050          setCookie("iabbb_find_location", locationId2, defaultExpiration);
1051        }
1052        this.emit(`${this.localName}:set-location`, {
1053          county: selectedCountry.fullLabel,
1054          culture: selectedCountry.culture,
1055          location: locationId2
1056        });
1057        if (decodeURIComponent(initialUserLocationId) !== locationId2) {
1058          this.emit("iabbb:localeselector.setlocation", {
1059            id: location.id,
1060            city: location.city,
1061            state: location.state,
1062            country: location.country,
1063            postalCode: location.postalCode,
1064            latLng: location.latLng,
1065            bbbInfo: {
1066              bbbId: location.bbbInfo.bbbId,
1067              bbbName: location.bbbInfo.bbbName,
1068              primaryCountry: location.bbbInfo.primaryCountry,
1069              primaryLanguage: location.bbbInfo.primaryLanguage
1070            }
1071          });
1072          if (initialUserBbbId !== location.bbbInfo.bbbId) {
1073            fetch(`${window.headerFooterData.baseUrl}/header-footer/api/bbb-data?id=${location.bbbInfo.bbbId}`).then((res) => {
1074              if (!res.ok) {
1075                throw new Error(`${res.statusText} (status: ${res.status})`);
1076              }
1077              return res.json();
1078            }).then((location2) => {
1079              this.emit("hf:set-bbb", location2);
1080            });
1081          }
1082        }
1083        if (!initialUserLocationId) {
1084          this.querySelector("button").innerHTML = this.querySelector("button").innerHTML.replace(
1085            "Set location",
1086            "My BBB"
1087          );
1088        }
1089        const screen = document.querySelector("#locale-selector-screen");
1090        screen.innerHTML = "";
1091        screen.appendChild(this.buildShowLocationDialogContent());
1092        this.showChangeLocationView = false;
1093        document.querySelector("#locale-selector-screen h2").focus();
1094      }).catch((err) => {
1095        console.error(err);
1096      });
1097    } else {
1098      this.showLocationError();
1099    }
1100  };
1101}
1102customElements.define("iabbb-locale-selector", LocaleSelector);
1103class LocaleSelectorCountryCustomSelect extends BaseCustomSelect {
1104  getInitialValue = () => {
1105    const savedCulture = getCookie("iabbb_user_culture");
1106    if (!savedCulture) {
1107      return this.select.value;
1108    }
1109    return countries.find((x) => x.culture === savedCulture)?.value || this.select.value;
1110  };
1111  getOptionHtml = (val) => {
1112    const country = countries.find((x) => x.value === val);
1113    return `<img src="${country.flag}" alt="" /><span class="option-label">${country.fullLabel}</span>`;
1114  };
1115  optionClassName = "dtm-locale-selector-country";
1116}
1117customElements.define("iabbb-ls-country-custom-select", LocaleSelectorCountryCustomSelect);
1118class LocaleSelectorAutocomplete extends BaseAutocomplete {
1119  connectedCallback() {
1120    this.render();
1121    self.addEventListener("change-ls-language", this.changeLanguageEventListener);
1122    const savedNearLocationId = decodeURIComponent(getCookie("iabbb_user_location"));
1123    if (savedNearLocationId) {
1124      const nearLocationIdParts = decodeURIComponent(savedNearLocationId).split("_");
1125      const nearState = nearLocationIdParts[nearLocationIdParts.length - 2];
1126      const nearCity = nearLocationIdParts.slice(0, nearLocationIdParts.length - 2).join(" ");
1127      if (nearState && nearCity) {
1128        this.querySelector("input").value = `${nearCity}, ${nearState}`;
1129        this.showClearButton();
1130      }
1131    }
1132  }
1133  disconnectedCallback() {
1134    self.removeEventListener("change-ls-language", this.changeLanguageEventListener);
1135  }
1136  getOptionAttributes = (result, inputText) => {
1137    return {
1138      html: inputText.trim().length > 1 ? result.displayText.replaceAll(new RegExp(inputText, "ig"), (match) => `<span>${match}</span>`) : result.displayText,
1139      attributes: result.isCurrentLocation ? [{ name: "data-value", value: result.value }] : null
1140    };
1141  };
1142  getOptions = (query) => {
1143    const userLocation = decodeURIComponent(getCookie("iabbb_user_physical_location"));
1144    const country = document.querySelector('[name="ls_country"]').value;
1145    let currentLocationOption;
1146    if (userLocation) {
1147      const [city, state, userCountry] = userLocation.split(", ");
1148      if (country === userCountry) {
1149        currentLocationOption = {
1150          displayText: "Current location",
1151          value: `${city}, ${state}`,
1152          isCurrentLocation: true
1153        };
1154      }
1155    }
1156    if (query.trim().length === 0) {
1157      return currentLocationOption ? Promise.resolve([currentLocationOption]) : Promise.resolve([]);
1158    }
1159    return fetch(
1160      `${window.headerFooterData.baseUrl}/api/suggest/location?country=${country}&input=${query}&maxMatches=6`,
1161      { credentials: "omit" }
1162    ).then((res) => {
1163      if (res.ok) {
1164        return res.json();
1165      }
1166      return res.text().then((msg) => {
1167        throw msg;
1168      });
1169    }).then((results) => currentLocationOption ? [currentLocationOption, ...results] : results).catch((error) => {
1170      console.error(error);
1171      return Promise.resolve([]);
1172    });
1173  };
1174  changeLanguageEventListener = () => {
1175    this.querySelector("input").value = "";
1176  };
1177}
1178customElements.define("iabbb-ls-autocomplete", LocaleSelectorAutocomplete);
1179class Footer extends HTMLElement {
1180  connectedCallback() {
1181    this.addAnalyticsEventListeners();
1182  }
1183  disconnectedCallback() {
1184    this.removeAnalyticsEventListeners();
1185  }
1186  addAnalyticsEventListeners = () => {
1187    const logo = this.querySelector("[data-logo-link]");
1188    logo.addEventListener("click", this.handleLogoClick);
1189    const mainLinks = this.querySelectorAll(".main .dtm-footer-link");
1190    for (const mainLink of mainLinks) {
1191      mainLink.addEventListener("click", this.handleMainLinkClick);
1192    }
1193    const bottomLinks = this.querySelectorAll(".bottom .dtm-footer-link");
1194    for (const bottomLink of bottomLinks) {
1195      bottomLink.addEventListener("click", this.handleBottomLinkClick);
1196    }
1197    const socialLinks = this.querySelectorAll(".main .dtm-footer-social-link");
1198    for (const socialLink of socialLinks) {
1199      socialLink.addEventListener("click", this.handleSocialLinkClick);
1200    }
1201  };
1202  removeAnalyticsEventListeners = () => {
1203    const logo = this.querySelector("[data-logo-link]");
1204    logo.removeEventListener("click", this.handleLogoClick);
1205    const mainLinks = this.querySelectorAll(".main .dtm-footer-link");
1206    for (const mainLink of mainLinks) {
1207      mainLink.removeEventListener("click", this.handleMainLinkClick);
1208    }
1209    const bottomLinks = this.querySelectorAll(".bottom .dtm-footer-link");
1210    for (const bottomLink of bottomLinks) {
1211      bottomLink.removeEventListener("click", this.handleBottomLinkClick);
1212    }
1213    const socialLinks = this.querySelectorAll(".main .dtm-footer-social-link");
1214    for (const socialLink of socialLinks) {
1215      socialLink.removeEventListener("click", this.handleSocialLinkClick);
1216    }
1217  };
1218}
1219customElements.define("iabbb-footer", Footer);
1220class Header extends HTMLElement {
1221  connectedCallback() {
1222    self.addEventListener("hf:set-bbb", this.handleSetBbb);
1223    self.addEventListener("iabbb-country-custom-select:select", this.syncCountryCustomSelects);
1224    this.addAnalyticsEventListeners();
1225  }
1226  disconnectedCallback() {
1227    self.removeEventListener("hf:set-bbb", this.handleSetBbb);
1228    self.addEventListener("iabbb-country-custom-select:select", this.syncCountryCustomSelects);
1229    this.removeAnalyticsEventListeners();
1230  }
1231  /**
1232   * Emit a custom event
1233   * @param {string} name - The event name
1234   * @param {object} detail - Any details to pass along with the event
1235   */
1236  emit = (name, detail = {}) => {
1237    const event = new CustomEvent(name, {
1238      bubbles: true,
1239      cancelable: true,
1240      composed: true,
1241      detail
1242    });
1243    return this.dispatchEvent(event);
1244  };
1245  handleSetBbb = (e) => {
1246    this.updatePopularCategories(e.detail.popularCategories);
1247  };
1248  syncCountryCustomSelects = (e) => {
1249    this.emit("iabbb-country-custom-select:manual-set-option", { value: e.detail.value });
1250  };
1251  addAnalyticsEventListeners = () => {
1252    self.addEventListener("iabbb-locale-selector:click-location-link", this.handleClickLocaleSelectorLocationLink);
1253    self.addEventListener("iabbb-search-bar:execute", this.handleSearchExecute);
1254    self.addEventListener("iabbb-find-autocomplete:type", this.handleFindAutocompleteType);
1255    self.addEventListener("iabbb-near-autocomplete:type", this.handleNearAutocompleteType);
1256    self.addEventListener("iabbb-find-autocomplete:select-option", this.handleFindAutocompleteSelect);
1257    self.addEventListener("iabbb-near-autocomplete:select-option", this.handleNearAutocompleteSelect);
1258  };
1259  removeAnalyticsEventListeners = () => {
1260    self.removeEventListener(
1261      "iabbb-locale-selector:click-location-link",
1262      this.handleClickLocaleSelectorLocationLink
1263    );
1264    self.removeEventListener("iabbb-search-bar:execute", this.handleSearchExecute);
1265    self.removeEventListener("iabbb-find-autocomplete:type", this.handleFindAutocompleteType);
1266    self.removeEventListener("iabbb-near-autocomplete:type", this.handleNearAutocompleteType);
1267    self.removeEventListener("iabbb-find-autocomplete:select-option", this.handleFindAutocompleteSelect);
1268    self.removeEventListener("iabbb-near-autocomplete:select-option", this.handleNearAutocompleteSelect);
1269  };
1270  updatePopularCategories = (popularCategories) => {
1271    window.headerFooterData = {
1272      ...window.headerFooterData || {},
1273      bbb: {
1274        ...window.headerFooterData?.bbb || {},
1275        popularCategories
1276      }
1277    };
1278  };
1279  handleSearchExecute = () => {
1280    aaTrackEvent("searchCompleted");
1281    aaTrackEvent("searchExecuted");
1282  };
1283  handleFindAutocompleteType = (e) => {
1284    this.updateSearchDataLayer({
1285      find_query: e.detail.query,
1286      find_method: "type",
1287      used_type_aheads: "false"
1288    });
1289  };
1290  handleNearAutocompleteType = (e) => {
1291    this.updateSearchDataLayer({
1292      near_query: e.detail.query,
1293      near_method: "type",
1294      used_type_aheads: "false"
1295    });
1296  };
1297  handleFindAutocompleteSelect = (e) => {
1298    this.updateSearchDataLayer({
1299      find_query: e.detail.value,
1300      find_method: "selected",
1301      used_type_aheads: "true"
1302    });
1303  };
1304  handleNearAutocompleteSelect = (e) => {
1305    this.updateSearchDataLayer({
1306      near_query: e.detail.value,
1307      near_method: "selected",
1308      used_type_aheads: "true"
1309    });
1310  };
1311  updateSearchDataLayer = (updatedSearchDataLayer) => {
1312    if (window.webDigitalData?.search_info) {
1313      window.webDigitalData.search_info = {
1314        ...window.webDigitalData.search_info,
1315        updatedSearchDataLayer
1316      };
1317    }
1318  };
1319}
1320customElements.define("iabbb-header", Header);
1321const cookieGroups = [
1322  {
1323    name: "Necessary Cookies",
1324    description: "These cookies are necessary for the site to function and cannot be switched off in our systems. They are usually only set in response to actions made by you that amount to a request for services, such as setting your privacy preferences, logging in or filling in forms. You can set your browser to block or alert you about these cookies, but some parts of the site will not work. These cookies do not store any personally identifiable information.",
1325    isReadOnly: true
1326  },
1327  {
1328    name: "Functional Cookies",
1329    description: "These cookies enable the site to provide enhanced functionality and personalization. They may be set by us or by third party providers whose services we have added to our pages. If you do not allow these cookies, some or all of these services may not function properly."
1330  },
1331  {
1332    name: "Performance Cookies",
1333    description: "These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us to know which pages are the most and least popular and see how visitors move around the site. All information these cookies collect is aggregated and therefore anonymous. If you do not allow these cookies we will not know when you have visited our site, and will not be able to monitor its performance."
1334  },
1335  {
1336    name: "Marketing Cookies",
1337    description: "These cookies may be set through our site by our advertising partners. They may be used by those companies to build a profile of your interests and show you relevant content on other sites. They do not store personal information directly, but are based on uniquely identifying your browser or device. If you do not allow these cookies, you will experience less targeted advertising."
1338  }
1339];
1340class CookiesMessage extends HTMLElement {
1341  constructor() {
1342    super();
1343    this.render = () => {
1344      this.enhanceAcceptAllCookies();
1345      if (typeof HTMLDialogElement === "function") {
1346        this.createPolicyDialog();
1347        this.replaceManageCookiesLinkWithButton();
1348      }
1349      this.addScrollPadding();
1350    };
1351  }
1352  connectedCallback() {
1353    this.render();
1354  }
1355  createPolicyDialog = () => {
1356    const dialog = document.createElement("dialog");
1357    dialog.tabIndex = -1;
1358    const dialogContent = document.createElement("div");
1359    const heading = document.createElement("h2");
1360    heading.className = "bds-h2";
1361    heading.innerText = "Cookie Preferences";
1362    const paragraph = document.createElement("p");
1363    paragraph.innerText = "Many websites use cookies or similar tools to store information on your browser or device. We use cookies on BBB websites to remember your preferences, improve website performance and enhance user experience, and to recommend content we believe will be most relevant to you. Most cookies collect anonymous information such as how users arrive at and use the website. Some cookies are necessary to allow the website to function properly, but you may choose to not allow other types of cookies below.";
1364    dialogContent.appendChild(heading);
1365    dialogContent.appendChild(paragraph);
1366    const form = document.createElement("form");
1367    form.action = "/manage-cookies";
1368    form.method = "post";
1369    form.onsubmit = (e) => {
1370      if ("FormData" in window) {
1371        e.preventDefault();
1372        const formValues = Object.fromEntries(new FormData(e.target));
1373        this.setCookiesPolicy({
1374          necessary: true,
1375          functional: formValues.functional === "true",
1376          performance: formValues.performance === "true",
1377          marketing: formValues.marketing === "true"
1378        });
1379        this.setCookiesPreferencesSet();
1380        this.querySelector("dialog").close();
1381        this.showSavedPreferencesMessage();
1382      }
1383    };
1384    for (const cookieGroup of cookieGroups) {
1385      const group = this.createGroup(cookieGroup.name, cookieGroup.description, cookieGroup.isReadOnly);
1386      form.appendChild(group);
1387    }
1388    const actions = document.createElement("div");
1389    actions.className = "actions";
1390    const saveChangesButton = document.createElement("button");
1391    saveChangesButton.innerText = "Save Changes";
1392    saveChangesButton.className = "bds-button";
1393    const acceptAllButton = document.createElement("button");
1394    acceptAllButton.className = "bds-button-unstyled";
1395    acceptAllButton.name = "allow-all";
1396    acceptAllButton.value = "true";
1397    acceptAllButton.type = "button";
1398    acceptAllButton.innerText = "Accept All Cookies";
1399    acceptAllButton.onclick = () => {
1400      this.setAcceptAllCookiesPolicy();
1401      this.setCookiesPreferencesSet();
1402      this.querySelector("dialog").close();
1403      this.showSavedPreferencesMessage();
1404    };
1405    actions.appendChild(saveChangesButton);
1406    actions.appendChild(acceptAllButton);
1407    form.appendChild(actions);
1408    dialogContent.appendChild(form);
1409    dialog.appendChild(dialogContent);
1410    dialog.addEventListener("click", ({ target: dialog2 }) => {
1411      if (dialog2.nodeName === "DIALOG") {
1412        dialog2.close("dismiss");
1413      }
1414    });
1415    this.appendChild(dialog);
1416  };
1417  replaceManageCookiesLinkWithButton = () => {
1418    const link = this.querySelector(".actions a");
1419    if (!link) {
1420      return;
1421    }
1422    const btn = document.createElement("button");
1423    btn.innerHTML = link.innerHTML;
1424    btn.className = `${link.className || ""} bds-button-unstyled`;
1425    btn.onclick = () => {
1426      this.querySelector("dialog").showModal();
1427      this.querySelector("dialog").focus();
1428    };
1429    link.replaceWith(btn);
1430  };
1431  createGroup = (name, description, isReadOnly = false) => {
1432    const id = name.replace(" ", "").replace("Cookies", "").toLowerCase();
1433    const container = document.createElement("div");
1434    container.className = "cookies-group";
1435    const heading = document.createElement("h3");
1436    heading.className = "bds-h4";
1437    heading.id = `${id}-heading`;
1438    heading.innerText = name;
1439    const details = document.createElement("details");
1440    const summary = document.createElement("summary");
1441    summary.innerText = `What are ${name.toLowerCase()}?`;
1442    const detailsFull = document.createElement("div");
1443    detailsFull.innerText = description;
1444    details.appendChild(summary);
1445    details.appendChild(detailsFull);
1446    container.appendChild(heading);
1447    container.appendChild(details);
1448    if (isReadOnly) {
1449      const disclaimer = document.createElement("p");
1450      disclaimer.innerText = `${name} must always be enabled`;
1451      container.appendChild(disclaimer);
1452    } else {
1453      const fields = document.createElement("fieldset");
1454      fields.setAttribute("aria-labelledby", `${id}-heading`);
1455      const iconRadio = `<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
1456        <circle
1457          class="background"
1458          cx="12"
1459          cy="12"
1460          r="11.5"
1461          stroke="currentColor"
1462          fill="none"
1463          stroke-width="1"
1464          vector-effect="non-scaling-stroke"
1465        />
1466        <circle class="radio" cx="12" cy="12" fill="currentColor" />
1467      </svg>`;
1468      const radioContainerTrue = document.createElement("div");
1469      radioContainerTrue.className = "bds-form-group";
1470      radioContainerTrue.innerHTML = `
1471        <div class="bds-radio" data-enhanced="true">
1472          <input type="radio" id="${id}-input-0" name="${id}" value="true" checked="" />
1473          ${iconRadio}
1474          <label for="${id}-input-0">Use ${name.toLowerCase()}</label>
1475        </div>
1476      `;
1477      const radioContainerFalse = document.createElement("div");
1478      radioContainerFalse.className = "bds-form-group";
1479      radioContainerFalse.innerHTML = `
1480        <div class="bds-radio" data-enhanced="true">
1481          <input type="radio" id="${id}-input-1" name="${id}" value="false" />
1482          ${iconRadio}
1483          <label for="${id}-input-1">Do not use ${name.toLowerCase()}</label>
1484        </div>
1485      `;
1486      fields.appendChild(radioContainerTrue);
1487      fields.appendChild(radioContainerFalse);
1488      container.appendChild(fields);
1489    }
1490    return container;
1491  };
1492  enhanceAcceptAllCookies = () => {
1493    this.querySelector("form").addEventListener("submit", (e) => {
1494      e.preventDefault();
1495      this.setAcceptAllCookiesPolicy();
1496      this.setCookiesPreferencesSet();
1497      this.showSavedPreferencesMessage();
1498    });
1499  };
1500  setCookiesPolicy = (cookiesPolicy) => {
1501    setCookie("iabbb_cookies_policy", JSON.stringify(cookiesPolicy), defaultExpiration);
1502  };
1503  setAcceptAllCookiesPolicy = () => {
1504    const allCookiesPolicy = {
1505      necessary: true,
1506      functional: true,
1507      performance: true,
1508      marketing: true
1509    };
1510    this.setCookiesPolicy(allCookiesPolicy);
1511  };
1512  setCookiesPreferencesSet = () => {
1513    setCookie("iabbb_cookies_preferences_set", "true", defaultExpiration);
1514  };
1515  showSavedPreferencesMessage = () => {
1516    const message = this.querySelector(".layout p");
1517    message.innerHTML = `Your cookie settings have been saved. You can <a href="${window.headerFooterData.baseUrl}/manage-cookies">change your cookie settings</a> at any time.`;
1518    message.tabIndex = -1;
1519    const hideThisMessageButton = document.createElement("button");
1520    hideThisMessageButton.innerText = "Hide This Message";
1521    hideThisMessageButton.className = "bds-button";
1522    hideThisMessageButton.onclick = () => {
1523      this.innerHTML = "";
1524    };
1525    this.querySelector(".layout .actions").innerHTML = "";
1526    this.querySelector(".layout .actions").appendChild(hideThisMessageButton);
1527    message.focus();
1528  };
1529  // Add scroll padding to prevent focused elements from being obscured by this message.
1530  // Credit: https://codepen.io/TPG/pen/QWVMXMg
1531  // Changed: Added overflow: auto to inline styles, as scroll-padding was otherwise not taking effect
1532  // Changed: references to header were switched to cookies message container, and scroll-padding-top was switched to scroll-padding-bottom
1533  addScrollPadding = () => {
1534    const MEDIA_MATCH = "(min-width: 20em)";
1535    const EXTRA_PADDING = 6;
1536    const style = document.head.appendChild(document.createElement("style"));
1537    const scrollFocusedElementIntoView = (height) => {
1538      const focused = document.activeElement || document.body;
1539      if (focused !== document.body && !this.contains(focused)) {
1540        if (focused.getBoundingClientRect().top < height) {
1541          focused.scrollIntoView();
1542        }
1543      }
1544    };
1545    const applyScrollPadding = () => {
1546      if (!style) {
1547        return;
1548      }
1549      const height = this.offsetHeight + EXTRA_PADDING;
1550      if ("CSS" in window && CSS.supports("selector(:has(*))")) {
1551        style.innerHTML = `html:has(:not(.cookies-message *, .cookies-policy-dialog *):focus)  { scroll-padding-bottom:${height}px; overflow: auto; }`;
1552      } else {
1553        style.innerHTML = `html { scroll-padding-bottom:${height}px; overflow: auto; }`;
1554      }
1555      scrollFocusedElementIntoView(height);
1556    };
1557    if ("ResizeObserver" in window) {
1558      const observer = new ResizeObserver(applyScrollPadding);
1559      const enableResizeMonitor = () => {
1560        observer.observe(this);
1561      };
1562      const disableResizeMonitor = () => {
1563        if (!style) {
1564          return;
1565        }
1566        observer.unobserve(this);
1567        style.innerHTML = "";
1568      };
1569      const query = window.matchMedia(MEDIA_MATCH);
1570      query.addEventListener("change", (e) => {
1571        if (e.matches) {
1572          enableResizeMonitor();
1573        } else {
1574          disableResizeMonitor();
1575        }
1576      });
1577      if (query.matches) {
1578        enableResizeMonitor();
1579      }
1580    }
1581  };
1582}
1583customElements.define("iabbb-cookies-message", CookiesMessage);
1584class OutageDisclaimer extends HTMLElement {
1585  constructor() {
1586    super();
1587    this.render = () => {
1588      this.addCloseButton();
1589    };
1590  }
1591  connectedCallback() {
1592    this.render();
1593  }
1594  addCloseButton = () => {
1595    const closeIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512" aria-hidden="true" fill="currentColor" focusable="false" height="1em" width="1em"><path d="M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3l105.4 105.3c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256l105.3-105.4z"></path></svg>`;
1596    const visuallyHiddenLabel = `<span class="visually-hidden">close outage disclaimer</span>`;
1597    const closeButton = document.createElement("button");
1598    closeButton.className = "bds-button-unstyled";
1599    closeButton.innerHTML = `${closeIcon}${visuallyHiddenLabel}`;
1600    closeButton.onclick = () => {
1601      this.addDisclaimerAcknowledgedCookie();
1602      this.style.display = "none";
1603    };
1604    this.appendChild(closeButton);
1605  };
1606  addDisclaimerAcknowledgedCookie = () => {
1607    setCookie("iabbb_outage_disclaimer", "true");
1608  };
1609}
1610customElements.define("iabbb-outage-disclaimer", OutageDisclaimer);
1611function autoDetectLocation() {
1612  const baseUrl = window.headerFooterData?.baseUrl;
1613  if (!baseUrl) {
1614    if (document.readyState !== "complete") {
1615      window.addEventListener("load", autoDetectLocation, { once: true });
1616    }
1617    return;
1618  }
1619  const rawCookie = getCookie("iabbb_user_location");
1620  if (rawCookie) {
1621    return;
1622  }
1623  fetch(`${baseUrl}/api/geoip/`).then((res) => {
1624    if (!res.ok) {
1625      throw new Error(`GeoIP failed (status: ${res.status})`);
1626    }
1627    return res.json();
1628  }).then(({ location, geoIpInfo }) => {
1629    const postalCode = location?.postalCode || geoIpInfo?.postalCode;
1630    if (!postalCode || !location?.city || !location?.state) {
1631      return;
1632    }
1633    const locationId = location.id || `${location.city}_${location.state}_${location.threeLetterIsoCountryCode}`;
1634    setCookie("iabbb_user_location", locationId, defaultExpiration);
1635    setCookie("iabbb_user_postalcode", postalCode, defaultExpiration);
1636    if (location.latLng?.lat != null && location.latLng?.lng != null) {
1637      setCookie("iabbb_user_latlng", `${location.latLng.lat},${location.latLng.lng}`, defaultExpiration);
1638    }
1639    if (location.bbbInfo?.bbbId) {
1640      setCookie("iabbb_user_bbb", location.bbbInfo.bbbId, defaultExpiration);
1641      window.headerFooterData = {
1642        ...window.headerFooterData || {},
1643        bbb: {
1644          name: location.bbbInfo.bbbName,
1645          url: location.bbbInfo.urls?.bbbUrl
1646        }
1647      };
1648    }
1649    document.dispatchEvent(
1650      new CustomEvent("iabbb:localeselector.setlocation", {
1651        bubbles: true,
1652        detail: {
1653          id: location.id,
1654          city: location.city,
1655          state: location.state,
1656          country: location.country,
1657          postalCode,
1658          latLng: location.latLng,
1659          bbbInfo: location.bbbInfo ? {
1660            bbbId: location.bbbInfo.bbbId,
1661            bbbName: location.bbbInfo.bbbName,
1662            primaryCountry: location.bbbInfo.primaryCountry,
1663            primaryLanguage: location.bbbInfo.primaryLanguage
1664          } : null
1665        }
1666      })
1667    );
1668  }).catch((err) => {
1669    console.warn("[initGeoLocation] auto-detect failed:", err);
1670  });
1671}
1672autoDetectLocation();
1673//# sourceMappingURL=scripts.js.map

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.