{
  "version": 3,
  "sources": ["../components/timer.js", "../components/TabbedNavigator.js", "../components/site-nav.js", "../components/scroll-to-top.js", "../components/combobox/listbox.js", "../components/secondary-nav.js", "../components/wx-loader.js", "../locationSearch.js", "../components/combobox/combobox.js", "../components/recent-locations.js", "../components/combobox/location-listbox.js", "../components/saved-locations.js", "../components/saved-locations-section.js", "../aws-rum.js", "../components/offline-banner.js", "../components/aria-live.js", "../components/Tabs.js", "../components/map.js", "../components/alertMap.js", "../components/geobuf.js", "../components/util.js", "../components/stateAlertMap.js", "../components/state-alerts-handler.js"],
  "sourcesContent": ["/** Convenience class for using setTimeout. */\nexport default class Timer {\n  constructor() {\n    this.timer = this.callback = this.delay = null;\n  }\n\n  stop = () => {\n    if (this.timer === null) return;\n    clearTimeout(this.timer);\n    this.timer = this.callback = this.delay = null;\n  };\n\n  start = (callback, delay) => {\n    this.stop();\n    this.callback = callback;\n    this.delay = Number.isFinite(delay) ? delay : 2000;\n    this.timer = setTimeout(callback, this.delay);\n  };\n\n  reset = () => {\n    if (this.timer === null) return;\n    this.start(this.callback, this.delay);\n  };\n}\n", "class TabbedNavigator extends HTMLElement {\n  constructor() {\n    super();\n\n    // Bind this context to methods that need it\n    this.handleAlertAnchorClick = this.handleAlertAnchorClick.bind(this);\n    this.handleDescendantClick = this.handleDescendantClick.bind(this);\n    this.handleTabButtonClick = this.handleTabButtonClick.bind(this);\n    this.handlePopState = this.handlePopState.bind(this);\n    this.switchToTab = this.switchToTab.bind(this);\n    this.scrollToAccordion = this.scrollToAccordion.bind(this);\n    this.navigateAlertAnchor = this.navigateAlertAnchor.bind(this);\n    this.updateTabScrollState = this.updateTabScrollState.bind(this);\n  }\n\n  connectedCallback() {\n    const pointTablist = this.querySelector(\"#point-page-tablist\");\n    if (pointTablist) {\n      // Capture scroll events because they do not bubble.\n      this.addEventListener(\"scroll\", this.updateTabScrollState, true);\n      this.tablistResizeObserver = new ResizeObserver(\n        this.updateTabScrollState,\n      );\n      this.tablistResizeObserver.observe(this);\n      this.tablistResizeObserver.observe(pointTablist);\n      pointTablist.querySelectorAll(\".tab-button\").forEach((tab) => {\n        this.tablistResizeObserver.observe(tab);\n      });\n      this.updateTabScrollState();\n    }\n\n    // If no tabs are selected by default, then select the first one\n    const selected = Array.from(\n      this.querySelectorAll(\".tab-button[data-selected]\"),\n    );\n    if (!selected.length) {\n      this.switchToTab(this.querySelector(\"button\").dataset.tabName);\n    }\n\n    // Intercept click events on Alert links at the\n    // top of the page and handle them in this component\n    Array.from(document.querySelectorAll(\"wx-point-alert-links a\")).forEach(\n      (alertAnchor) => {\n        alertAnchor.addEventListener(\"click\", this.handleAlertAnchorClick);\n      },\n    );\n\n    // Intercept click events on Alert spans that are in tab\n    // containers controlled by this component\n    this.addEventListener(\"click\", this.handleDescendantClick);\n    window.addEventListener(\"popstate\", this.handlePopState);\n\n    // Add needed event listeners\n    Array.from(this.querySelectorAll(\"button.tab-button\")).forEach((button) => {\n      button.addEventListener(\"click\", this.handleTabButtonClick);\n      button.addEventListener(\"keydown\", this.handleTabListKeydown);\n    });\n  }\n\n  disconnectedCallback() {\n    this.tablistResizeObserver?.disconnect();\n    this.removeEventListener(\"scroll\", this.updateTabScrollState, true);\n    window.removeEventListener(\"popstate\", this.handlePopState);\n\n    // Remove any event listeners\n    Array.from(this.querySelectorAll(\"button.tab-button\")).forEach((button) => {\n      button.removeEventListener(\"click\", this.handleTabButtonClick);\n      button.removeEventListener(\"keydown\", this.handleTabListKeydown);\n    });\n  }\n\n  updateTabScrollState() {\n    const tablist = this.querySelector(\"#point-page-tablist\");\n    const maxScroll = tablist ? tablist.scrollWidth - tablist.clientWidth : 0;\n    this.toggleAttribute(\"data-tabs-overflow\", maxScroll > 0);\n    this.toggleAttribute(\n      \"data-tabs-scroll-left\",\n      maxScroll > 0 && tablist.scrollLeft > 0,\n    );\n    // Allow for fractional scroll positions at the right edge.\n    this.toggleAttribute(\n      \"data-tabs-scroll-right\",\n      maxScroll > 0 && maxScroll - tablist.scrollLeft > 1,\n    );\n  }\n\n  navigateWithInitialHash() {\n    const hash = new URL(window.location).hash;\n    if (!hash || hash === \"\") {\n      return;\n    }\n\n    try {\n      const matchedTabButton = this.querySelector(\n        `[data-tab-name=\"${hash.replace(\"#\", \"\")}\"]`,\n      );\n      if (matchedTabButton) {\n        this.switchToTab(matchedTabButton.dataset.tabName);\n        matchedTabButton.parentElement.scrollIntoView();\n        return;\n      }\n\n      const childElement = this.querySelector(\n        `${hash},wx-tab-container, .wx-tab-container ${hash}`,\n      );\n      if (childElement) {\n        const tabContainer = childElement.closest(\".wx-tab-container\");\n        this.switchToTab(tabContainer.id);\n        if (childElement.matches(\".usa-accordion\")) {\n          this.toggleAccordion(childElement, true);\n          document.addEventListener(\"DOMContentLoaded\", () => {\n            this.scrollToAccordion(childElement);\n          });\n        }\n      }\n    } catch (e) {\n      // Guard against hashes that are not valid DOM identifiers. We can't\n      // prevent users from typing random stuff in the address bar, but we\n      // prevent our scripts from crashing if they do.\n    }\n  }\n\n  switchToTab(tabId) {\n    // First, deactivate all tabs\n    Array.from(this.querySelectorAll(\".tab-button, .wx-tab-container\")).forEach(\n      (element) => {\n        element.removeAttribute(\"data-selected\");\n        if (element.matches(\".tab-button\")) {\n          element.setAttribute(\"aria-expanded\", \"false\");\n          element.setAttribute(\"tabindex\", \"-1\");\n        }\n      },\n    );\n\n    // Active the tab button\n    const tabButton = this.querySelector(`[data-tab-name=\"${tabId}\"]`);\n    tabButton.setAttribute(\"data-selected\", \"\");\n    tabButton.setAttribute(\"aria-expanded\", \"true\");\n    tabButton.removeAttribute(\"tabindex\");\n\n    // Activate the corresponding container\n    const tabContainer = this.querySelector(`#${tabId}`);\n    tabContainer.setAttribute(\"data-selected\", \"\");\n\n    // Trigger a custom event for use externally\n    // when tabs switch\n    const event = new CustomEvent(\"wx:tab-switched\", {\n      detail: {\n        tabId,\n      },\n      bubbles: true,\n    });\n    this.dispatchEvent(event);\n  }\n\n  handleTabButtonClick(event) {\n    const tabButton = event.currentTarget;\n    this.switchToTab(tabButton.dataset.tabName);\n    // Since this was an actual click, update the hash\n    // of the site to the tab button's id and push it into the browser history\n    window.history.pushState(null, null, tabButton.dataset.url);\n  }\n\n  handlePopState() {\n    const currentPath = window.location.pathname;\n    const matchingTab = Array.from(\n      this.querySelectorAll(\".tab-button[data-url]\"),\n    ).find((tabButton) => {\n      const tabUrl = new URL(tabButton.dataset.url, window.location.origin);\n      return tabUrl.pathname === currentPath;\n    });\n\n    if (matchingTab) {\n      this.switchToTab(matchingTab.dataset.tabName);\n      matchingTab.focus({ preventScroll: true });\n    }\n  }\n\n  /**\n   * A catch-all listener for click events inside the navigator and any\n   * of its constituent tab content panes.\n   * We use this to filter out for wx-alert clicks, which will be handled\n   * separately.\n   */\n  handleDescendantClick(event) {\n    if (!event.target.matches(\"a\")) {\n      return;\n    }\n    const linkWrapper = event.target.closest(\".wx-alert-link\");\n    if (!linkWrapper) {\n      return;\n    }\n    this.navigateAlertAnchor(event.target);\n  }\n\n  navigateAlertAnchor(anchorEl) {\n    const hash = new URL(anchorEl.href).hash;\n    const accordionEl = this.querySelector(`${hash}.usa-accordion`);\n\n    if (accordionEl) {\n      // If we get here, then the element referred\n      // to by the href is a child of this tabbed\n      // navigator.\n      // We need to toggle to the correct tab pane\n      // to properly display and scroll to the element.\n      const tabContainer = accordionEl.closest(\".wx-tab-container\");\n      this.switchToTab(tabContainer.id);\n      this.toggleAccordion(accordionEl, true);\n\n      // Because we use a sticky position on\n      // the tab button area, the normal browser\n      // scrolling will not display the proper position\n      // to the user. Instead, we have to roll our\n      // own scrolling method\n      this.scrollToAccordion(accordionEl);\n      window.history.replaceState(null, null, hash);\n    }\n  }\n\n  handleAlertAnchorClick(event) {\n    event.preventDefault();\n    this.navigateAlertAnchor(event.currentTarget);\n  }\n\n  toggleAccordion(accordionElement, on = true) {\n    const button = accordionElement.querySelector(\n      \"button.usa-accordion__button\",\n    );\n    const content = accordionElement.querySelector(\".usa-accordion__content\");\n\n    if (on) {\n      button.setAttribute(\"aria-expanded\", \"true\");\n      content.removeAttribute(\"hidden\");\n    } else {\n      button.setAttribute(\"aria-expanded\", \"false\");\n      content.addAttribute(\"hidden\", \"\");\n    }\n  }\n\n  handleTabListKeydown(event) {\n    // Per W3C guidelines, arrow keys and other navigation\n    // keys should be used (instead of tab) to navigate the\n    // focus of tab buttons.\n    // See (https://www.w3.org/WAI/ARIA/apg/patterns/tabs/examples/tabs-manual/)\n    const currentElement = event.target;\n    const isFirst = currentElement.matches(\":first-child\");\n    const isLast = currentElement.matches(\":last-child\");\n    if (event.key === \"ArrowRight\") {\n      if (isLast) {\n        event.target.parentElement\n          .querySelector(\".tab-button:first-child\")\n          .focus();\n      } else {\n        currentElement.nextElementSibling.focus();\n      }\n      event.preventDefault();\n    } else if (event.key === \"ArrowLeft\") {\n      if (isFirst) {\n        event.target.parentElement\n          .querySelector(\".tab-button:last-child\")\n          .focus();\n      } else {\n        currentElement.previousElementSibling.focus();\n      }\n      event.preventDefault();\n    } else if (event.key === \"Home\") {\n      event.target.parentElement\n        .querySelector(\".tab-button:first-child\")\n        .focus();\n      event.preventDefault();\n    } else if (event.key === \"End\") {\n      event.target.parentElement\n        .querySelector(\".tab-button:last-child\")\n        .focus();\n      event.preventDefault();\n    }\n  }\n\n  scrollToAccordion(accordionElement) {\n    const accordionTop = accordionElement.getBoundingClientRect().top;\n    const buttonArea = this.querySelector(\".tab-buttons\");\n    const buttonAreaHeight = buttonArea.getBoundingClientRect().height;\n    const scrollY = accordionTop + window.scrollY - buttonAreaHeight;\n    window.scrollTo(0, scrollY);\n  }\n}\n\nif (!window.customElements.get(\"wx-tabbed-nav\")) {\n  window.customElements.define(\"wx-tabbed-nav\", TabbedNavigator);\n}\n", "/**\n * Site navigation interaction\n */\n\n// Import the tabbed-nav component, which is used by\n// the search box popout\nimport \"./TabbedNavigator.js\";\n\nconst setupSiteSearchMenuButton = (siteSubmenuElement) => {\n  const button = siteSubmenuElement.querySelector(`button[aria-expanded]`);\n\n  button.addEventListener(\"click\", () => {\n    if (button.getAttribute(\"aria-expanded\") === \"false\") {\n      button.setAttribute(\"aria-expanded\", \"true\");\n    } else {\n      button.setAttribute(\"aria-expanded\", \"false\");\n    }\n  });\n};\n\ndocument.addEventListener(\"DOMContentLoaded\", () => {\n  // Find the site search submenu and add a click listener\n  // to toggle the aria-expanded attribute.\n  const siteSearchSubmenu = document.getElementById(\"site-search-submenu\");\n  if (siteSearchSubmenu) {\n    setupSiteSearchMenuButton(siteSearchSubmenu);\n  }\n});\n", "/** @file Code to show/hide a \"scroll to top\" button. */\n\nconst mobileButton = document.querySelector(\".ride-up-button--mobile\");\nconst tabletButton = document.querySelector(\".ride-up-button--tablet\");\nconst footerRegion = document.querySelector(\"footer\");\n\nconst prefersReducedMotion = window.matchMedia?.(\n  \"(prefers-reduced-motion: reduce)\",\n)?.matches;\n\nlet scrollBracket = 0;\nlet bottomY = 0;\nlet hideThreshold = window.innerHeight * 1.75;\n// Show after scrolling up a 1/5 of a viewport.\nlet minScrollThreshold = window.innerHeight * 0.2;\nlet protectedArea = false;\n\nwindow.addEventListener(\"resize\", () => {\n  hideThreshold = window.innerHeight * 1.75;\n  minScrollThreshold = window.innerHeight * 0.2;\n});\n\nwindow.addEventListener(\n  \"scroll\",\n  () => {\n    // has the user scrolled more than 128 units?\n    if (window.scrollY / 128 !== scrollBracket) {\n      scrollBracket = window.scrollY >> 7;\n      // never show the buttons in the top 200vh or when the user scrolls down\n      if (window.scrollY < hideThreshold || window.scrollY > bottomY) {\n        mobileButton.classList.remove(\"ride-up-button--visible\");\n        tabletButton.classList.remove(\"ride-up-button--visible\");\n        bottomY = window.scrollY;\n      } else if (bottomY - window.scrollY > minScrollThreshold) {\n        mobileButton.classList.add(\"ride-up-button--visible\");\n        tabletButton.classList.add(\"ride-up-button--visible\");\n        bottomY = window.scrollY;\n      }\n    }\n  },\n  { passive: true },\n);\n\nconst scrollUp = () => {\n  if (prefersReducedMotion) {\n    window.scrollTo(0, 0);\n  } else {\n    window.scrollTo({ top: 0, behavior: \"smooth\" });\n  }\n};\n\nmobileButton.addEventListener(\"click\", scrollUp);\ntabletButton.addEventListener(\"click\", scrollUp);\n", "/**\n * WCAG compliant listbox component\n * See https://www.w3.org/WAI/ARIA/apg/patterns/listbox/\n */\n\nexport default class Listbox extends HTMLElement {\n  constructor() {\n    super();\n\n    this.template = document.createElement(\"template\");\n    this.template.innerHTML = `\n        <slot></slot>`;\n    this.attachShadow({ mode: \"open\" });\n    this.shadowRoot.append(this.template.content.cloneNode(true));\n\n    // Maps a key name to a handler for\n    // key events by the name of the key\n    this.keyMapping = {\n      ArrowUp: this.moveUp,\n      ArrowDown: this.moveDown,\n      Enter: this.selectPseudoFocused,\n      Home: this.moveHome,\n      End: this.moveEnd,\n    };\n\n    // Bind methods\n    this.bindEventListeners = this.bindEventListeners.bind(this);\n    this.unbindEventListeners = this.unbindEventListeners.bind(this);\n    this.handleFocus = this.handleFocus.bind(this);\n    this.handleKeyDown = this.handleKeyDown.bind(this);\n    this.handleItemsChanged = this.handleItemsChanged.bind(this);\n    this.moveDown = this.moveDown.bind(this);\n    this.moveUp = this.moveUp.bind(this);\n    this.moveHome = this.moveHome.bind(this);\n    this.moveEnd = this.moveEnd.bind(this);\n    this.selectPseudoFocused = this.selectPseudoFocused.bind(this);\n    this.pseudoFocusItem = this.pseudoFocusItem.bind(this);\n    this.selectItem = this.selectItem.bind(this);\n\n    this.bindEventListeners();\n  }\n\n  connectedCallback() {\n    this.bindEventListeners();\n    this.setAttribute(\"role\", \"listbox\");\n  }\n\n  disconnectedCallback() {\n    this.unbindEventListeners();\n  }\n\n  bindEventListeners() {\n    this.addEventListener(\"focus\", this.handleFocus);\n    this.shadowRoot\n      .querySelector(\"slot\")\n      .addEventListener(\"slotchange\", this.handleItemsChanged);\n    this.addEventListener(\"keydown\", this.handleKeyDown);\n    this.addEventListener(\"click\", this.handleClick);\n  }\n\n  unbindEventListeners() {\n    this.removeEventListener(\"focus\", this.handleFocus);\n    this.removeEventListener(\"keydown\", this.handleKeyDown);\n    this.removeEventListener(\"click\", this.handleClick);\n  }\n\n  handleFocus(e) {\n    // Automatically pseudo-focus the\n    // selected item.\n    // If there is no selected item,\n    // use the first item.\n    const selected = this.selection;\n    if (selected) {\n      this.pseudoFocusItem(selected);\n    } else {\n      const first = this.querySelector(`[role=\"option\"]`);\n      if (first) {\n        this.pseudoFocusItem(first);\n      }\n    }\n  }\n\n  handleClick(event) {\n    // We check to see if one of the options is in\n    // the chain of the bubbled click event\n    const closestOption = event.target.closest(`[role=\"option\"]`);\n    if (closestOption) {\n      event.currentTarget.selectItem(closestOption);\n    }\n  }\n\n  /**\n   * Attempts to look up a bound event handler\n   * for the given key, and calls it.\n   * Does nothing if the given key is not in\n   * the component's keyMapping dictionary.\n   */\n  handleKeyDown(event) {\n    if (event.target.keyMapping) {\n      const handler = event.target.keyMapping[event.key];\n      if (handler) {\n        handler.bind(this)(event);\n        event.preventDefault();\n      }\n    }\n  }\n\n  /**\n   * Handler for when slotted elements change.\n   * This is where we configure our listbox option\n   * elements as they are attached/removed.\n   * In this case, we add the data-option-index\n   * attribute to specify an order of options as they\n   * are presented in the dom (even though they can\n   * be nested in different lists).\n   * We also give each option an id based on the\n   * current component's id, if there isn't one already\n   * present.\n   */\n  handleItemsChanged(event) {\n    const host = event.target.getRootNode().host;\n    Array.from(host.querySelectorAll(`[role=\"option\"]`)).forEach(\n      (option, idx) => {\n        option.setAttribute(\"data-option-index\", idx);\n\n        // If the listbox itself has an id set, use\n        // that as a base for setting unique ids on\n        // each option. Do not set any id on an option\n        // that already has an id value.\n        // These ids are necessary for other wrapping\n        // components -- like a combobox -- that need\n        // to use aria-activedescendant to manage assistive\n        // technology focus capabilities.\n        if (!option.id && host.id) {\n          option.id = `${host.id}-option-${idx}`;\n        }\n      },\n    );\n  }\n\n  /**\n   * Pseudo Focus is what we are calling screenreader\n   * focus that is separate from the browser's DOM focus.\n   * It is managed primarily by the use of aria-activedescendant\n   * and should also be visually indicated through styling.\n   * This method removes the pseudo-focus state from all elements\n   * and if an element is also passed in, adds the state to that element.\n   * @param HTMLElement element\n   */\n  pseudoFocusItem(element) {\n    // If the passed on object is null or falsy,\n    // we un-focus all options in this component\n    Array.from(this.querySelectorAll(`[role=\"option\"]`)).forEach((option) => {\n      option.removeAttribute(\"data-pseudo-focus\");\n    });\n\n    if (element) {\n      element.setAttribute(\"data-pseudo-focus\", \"true\");\n\n      // Some listboxes might be inside an overflowed\n      // or scrolling container. Be sure to scroll the\n      // focused item into view\n      if (element.offsetTop < this.scrollTop) {\n        // user has scrolled past the item, so go back up\n        this.scrollTop = element.offsetTop;\n      } else if (\n        element.offsetTop + element.offsetHeight >\n        this.scrollTop + this.offsetHeight\n      ) {\n        // user is above the item, so go down\n        this.scrollTop =\n          element.offsetTop - this.offsetHeight + element.offsetHeight;\n      }\n\n      // If this component as the attribute\n      // `selection-follows-focus` set to \"true\",\n      // we also select the element we are focusing\n      if (this.getAttribute(\"selection-follows-focus\") === \"true\") {\n        this.selectItem(element);\n      }\n    }\n  }\n\n  /**\n   * If there is an item that is currently pseudo-focused,\n   * this method will call selectItem on that element.\n   */\n  selectPseudoFocused() {\n    const element = this.pseudoFocus;\n    if (element) {\n      this.selectItem(element);\n    }\n  }\n\n  /**\n   * Select item marks the provided element as being\n   * selected, for the purposes of listbox selection.\n   * It will also remove selection on any previously\n   * selected element(s).\n   * If the fireEvent parameter is set to true (as is by default),\n   * a change event will be dispatched from this component.\n   * @param HTMLElement element\n   * @param boolean fireEvent - Whether or not to dispatch\n   * a change event after selection. True by default.\n   */\n  selectItem(element, fireEvent = true) {\n    // De-select any that are already selected\n    Array.from(this.querySelectorAll(`[aria-selected=\"true\"]`)).forEach(\n      (selectedEl) => {\n        selectedEl.removeAttribute(\"aria-selected\");\n      },\n    );\n\n    // If there is an incoming element, select that one.\n    // By moving this into a cased control flow,\n    // we ensure that passing a falsy value for the element\n    // has the effect of clearing the current selection only.\n    if (element) {\n      element.setAttribute(\"aria-selected\", \"true\");\n      this.value = element.getAttribute(\"value\");\n    }\n\n    if (fireEvent) {\n      this.dispatchEvent(\n        new Event(\"change\", {\n          bubbles: true,\n          cancelable: true,\n        }),\n      );\n    }\n  }\n\n  /**\n   * Moves the pseudo focus one option previous\n   * in the listbox, based on overall option order.\n   * Navigation triggers the custom event wx:popup-nav\n   */\n  moveUp(event) {\n    // Find the element with the pseudo-focus.\n    // If there isn't one, bail.\n    const current = this.pseudoFocus;\n    if (current) {\n      const options = Array.from(this.querySelectorAll(`[role=\"option\"]`));\n      const currentIndex = options.indexOf(current);\n      const prev = currentIndex > 0 ? options[currentIndex - 1] : null;\n      // If prev does not exist, the call to pseudoFocusItem\n      // will un-pseudo focus everything the component\n      this.pseudoFocusItem(prev);\n      this.dispatchEvent(\n        new CustomEvent(\"wx:popup-nav\", {\n          bubbles: true,\n          detail: {\n            previous: current,\n            next: prev,\n            beyondTop: !prev && !this.pseudoFocus,\n            navCommand: \"moveUp\",\n          },\n        }),\n      );\n    }\n  }\n\n  /**\n   * Moves the pseudo focus to the next option\n   * element in the listbox, based on overall option\n   * order.\n   * Navigation triggers the custom event wx:popup-nav\n   */\n  moveDown(event) {\n    const current = this.pseudoFocus;\n    const options = Array.from(this.querySelectorAll(`[role=\"option\"]`));\n    if (!options.length) {\n      return;\n    }\n    const firstOption = options[0];\n    const lastOption = options[options.length - 1];\n    if (current === lastOption) {\n      return;\n    }\n    const currentIndex = options.indexOf(current);\n    const next = currentIndex >= 0 ? options[currentIndex + 1] : firstOption;\n\n    if (next && next !== current) {\n      this.pseudoFocusItem(next);\n      this.dispatchEvent(\n        new CustomEvent(\"wx:popup-nav\", {\n          bubbles: true,\n          detail: {\n            previous: current,\n            next: next,\n            navCommand: \"moveDown\",\n          },\n        }),\n      );\n    }\n  }\n\n  /**\n   * Moves the pseudo focus to the last option overall.\n   * Navigation triggers the custom event wx:popup-nav\n   */\n  moveHome(event) {\n    const current = this.pseudoFocus;\n    const options = Array.from(this.querySelectorAll(`[role=\"option\"]`));\n    const firstOption = options.length ? options[0] : null;\n    if (current && firstOption && current !== firstOption) {\n      this.pseudoFocusItem(firstOption);\n\n      this.dispatchEvent(\n        new CustomEvent(\"wx:popup-nav\", {\n          bubbles: true,\n          detail: {\n            previous: current,\n            next: firstOption,\n          },\n        }),\n      );\n    }\n  }\n\n  /**\n   * Moves the pseudo focus to the first option overall.\n   * Navigation triggers the custom event wx:popup-nav\n   */\n  moveEnd(event) {\n    const current = this.pseudoFocus;\n    const options = Array.from(this.querySelectorAll(`[role=\"option\"]`));\n    const lastOption = options.length ? options[options.length - 1] : null;\n    if (current && lastOption && current !== lastOption) {\n      this.pseudoFocusItem(lastOption);\n\n      this.dispatchEvent(\n        new CustomEvent(\"wx:popup-nav\", {\n          bubbles: true,\n          detail: {\n            previous: current,\n            next: lastOption,\n          },\n        }),\n      );\n    }\n  }\n\n  get selection() {\n    return this.querySelector(`[role=\"option\"][aria-selected=\"true\"]`);\n  }\n\n  get pseudoFocus() {\n    return this.querySelector(`[data-pseudo-focus=\"true\"]`);\n  }\n\n  static get observedAttributes() {\n    return [\"selection-follows-focus\"];\n  }\n}\n\nwindow.customElements.define(\"wx-listbox\", Listbox);\n", "import \"./combobox/listbox.js\";\n\nexport function navigateToElement(combobox) {\n  const popup = combobox.querySelector('[slot=\"popup\"]');\n  const selected = popup && popup.selection;\n  const targetUrl = selected && selected.getAttribute(\"data-value\");\n\n  if (targetUrl) {\n    window.location.href = targetUrl;\n  }\n}\n\n// Make navigateToElement available globally for inline onchange handler\nwindow.navigateToElement = navigateToElement;\n\ndocument.addEventListener(\"DOMContentLoaded\", () => {\n  const sections = document.querySelectorAll(\".section-content h2[id]\");\n  const navLinks = document.querySelectorAll(\".usa-sidenav__item a\");\n\n  const observerOptions = {\n    root: null, // Uses the browser viewport\n    rootMargin: \"0px 0px -90% 0px\", // Triggers when section hits the upper-middle screen\n    threshold: 0,\n  };\n\n  const observerCallback = (entries) => {\n    entries.forEach((entry) => {\n      if (entry.isIntersecting) {\n        const id = entry.target.getAttribute(\"id\");\n\n        // Remove active class from all links\n        navLinks.forEach((link) => link.classList.remove(\"usa-current\"));\n\n        // Add active class to matching link\n        const activeLink = document.querySelector(\n          `.usa-sidenav__item a[href=\"#${id}\"]`,\n        );\n        if (activeLink) {\n          activeLink.classList.add(\"usa-current\");\n        }\n      }\n    });\n  };\n\n  // Set the first link as active on page load\n  if (navLinks.length > 0) {\n    navLinks[0].classList.add(\"usa-current\");\n  }\n\n  const observer = new IntersectionObserver(observerCallback, observerOptions);\n  sections.forEach((section) => observer.observe(section));\n});\n", "/** @file this is for the events to show and hide the wx-loader */\n\nconst hideNavigationLoader = () => {\n  document.querySelectorAll(\"wx-search-loading-indicator\").forEach((loader) => {\n    loader.setAttribute(\"aria-hidden\", true);\n  });\n};\n\n/**\n * If there is a navigation loader available on the page,\n * make sure that it is being displayed.\n *\n * Each loader is supposed to have a `loader-for` attribute\n * with one or more unique identifiers. Pick the desired loader\n * by passing the ID when emitting the event.\n */\nconst showNavigationLoader = (event) => {\n  const loaders = document.querySelectorAll(\"wx-search-loading-indicator\");\n  const activeNav = event.detail?.id;\n\n  loaders.forEach((loader) => {\n    const loaderIsFor = (loader.getAttribute(\"loader-for\") || \"\").split(\" \");\n    if (loaderIsFor.includes(activeNav)) {\n      loader.removeAttribute(\"aria-hidden\");\n    }\n  });\n  if (loaders.length) {\n    const text = gettext(\"js.loader.loading-text.01\");\n    window.dispatchEvent(new CustomEvent(\"wx-announce\", { detail: { text } }));\n  }\n};\n\nwindow.addEventListener(\"wx-hide-navigation-loader\", hideNavigationLoader);\nwindow.addEventListener(\"wx-show-navigation-loader\", showNavigationLoader);\n\n// When the page is shown, hide the navigation loader. This is the best we can\n// do to handle hiding it when the back button is clicked. This code is not\n// (necessarily) executed again when the back button is pressed. Instead, its\n// state may simply be popped from the history stack. The pageshow event is\n// fired any time this page is shown, regardless of source, and our event\n// listener would persist as part of the popped state. The downside is there's\n// a flash of the loader before it gets hidden.\n//\n// In the event that the browser has already unloaded this page's state from\n// the history stack (to recoup memory, for example), then the page will\n// reload entirely. In that case, the loader is already hidden.\nwindow.addEventListener(\"pageshow\", hideNavigationLoader);\n", "/** @file Set up browser geolocation and handle searching by it. */\n\n(() => {\n  const goToLocationPage = (latitude, longitude) => {\n    // Submit the form, so we get the same behavior regardless of how we end up\n    // navigating to the location page.\n    const form = document.querySelector(\"form[data-location-search]\");\n    form.setAttribute(\"action\", `/forecast/point/${latitude}/${longitude}`);\n\n    form.submit();\n  };\n\n  const removeBrowserLocationButtons = (buttons) => {\n    // make a copy and reverse so we don't accidentally clobber ourselves.\n    Array.from(buttons)\n      .reverse()\n      .forEach((button) => {\n        if (button) {\n          const sibling = button.previousElementSibling;\n          if (sibling) {\n            sibling.remove();\n          }\n          button.remove();\n        }\n      });\n  };\n\n  const setupBrowserGeolocation = async () => {\n    // There can be multiple buttons used for selecting the browser location.\n    // For example, one can be hidden away in the nav bar while another is\n    // present lower down on the page. Be sure to add the behavior to\n    // all buttons\n    const buttons = document.querySelectorAll(\n      \"button.weathergov-use-browser-location\",\n    );\n\n    // If the browser does not support the geolocation API, just bail out. Take\n    // the \"use my location\" button away too. Also bop out if we don't have a\n    // button for some reason. Just being safe.\n    if (!navigator.geolocation) {\n      removeBrowserLocationButtons(buttons);\n      return;\n    }\n\n    // Whether we should independently prompt the user prior to asking the browser\n    // for their location. IF we can detect existing permissions AND the user has\n    // not already granted or denied us, THEN we should prompt first. If we can't\n    // detect existing permissions, don't prompt because otherwise we end up\n    // putting up our prompt for that user every time they try to use their\n    // location.\n    let shouldPrompt = false;\n\n    if (navigator.permissions) {\n      try {\n        // Query for geolocation permissions.\n        const status = await navigator.permissions.query({\n          name: \"geolocation\",\n        });\n\n        // If the user has already denied location, we can go ahead and bail out.\n        // Changing browser settings is not detectable within the page, so they'll\n        // have to reload to get the option back anyway.\n        //\n        // Might need to reconsider this. It might be preferable to leave the\n        // button and show users a popup. There are several reasons we might get\n        // the \"denied\" state:\n        //\n        // 1. The web browser does not have permission from the operating system.\n        // 2. The web browser is configured to deny permission by default.\n        // 3. The user has denied access to our site in particular.\n        //\n        // In cases 1 and 2, users may not be aware of their settings. If we show\n        // the button and then popup a message when they click it letting them\n        // know they need to change their browser settings, maybe that's useful.\n        // The immediate drawback I can think of is we have no way of knowing\n        // whether it's a browser setting or an operating system setting, so we\n        // can't give them any more helpful advice than \"check your settings.\"\n        //\n        // In case 3, however, we should just leave the user alone. They have\n        // already said no, and that should be the end of it.\n        //\n        // Key important takeaway, though, is that \"denied\" means all of those\n        // things and it is impossible for us to know which.\n        if (status.state === \"denied\") {\n          removeBrowserLocationButtons(buttons);\n          return;\n        }\n\n        // If the user has not denied us permission, then we should show our own\n        // prompt if the user has not yet granted us permission.\n        shouldPrompt = status.state === \"prompt\";\n      } catch (_) {\n        // An exception in the permissions API likely indicates that the specific\n        // attribute we queried for isn't available. That doesn't mean the feature\n        // doesn't exist, though, so we should continue as if the permissions API\n        // doesn't exist at all and not use our prompt.\n      }\n    }\n\n    const buttonHandler = async (e) => {\n      // Stop any other event behavior, in case our button is inside a form\n      // or something.\n      e.preventDefault();\n      e.stopPropagation();\n\n      let proceed = true;\n\n      // If location is available and we know that the user has neither denied or\n      // granted us permission to use it, we will let them know before asking for\n      // it. It's kind of a double-opt-in.\n      if (shouldPrompt) {\n        const text = gettext(\"js.location-search.prompt.user-consent.01\");\n        proceed = window.confirm(text);\n      }\n\n      // If we don't know about the permission, we were already approved to use\n      // it, or the user has signaled that we can ask for it... ask for it!\n      if (proceed) {\n        // Show the loader animation, if available\n        window.dispatchEvent(\n          new CustomEvent(\"wx-show-navigation-loader\", {\n            detail: { id: e.currentTarget.getAttribute(\"id\") },\n          }),\n        );\n\n        navigator.geolocation.getCurrentPosition(\n          // Success callback\n          ({ coords: { latitude, longitude } }) => {\n            // Scale down the precision on these.\n            const lat = Math.round(latitude * 1_000) / 1_000;\n            const long = Math.round(longitude * 1_000) / 1_000;\n\n            // And navigate away!\n            goToLocationPage(lat, long);\n          },\n          // Error callback\n          ({ code, message }) => {\n            if (code > 1) {\n              // There was a problem getting the user's location. They allowed it,\n              // but the browser gave us an error.\n              // (Error code 1 is for when the user denies access to location, so\n              // for our purposes, that is not an error.)\n\n              const alertText = interpolate(\n                gettext(\"js.location-search.alert.geolocation-error.01\"),\n                [message],\n              );\n              alert(alertText);\n            }\n          },\n        );\n      }\n    };\n\n    Array.from(buttons).forEach((button) => {\n      button.addEventListener(\"click\", buttonHandler);\n    });\n  };\n  setupBrowserGeolocation();\n})();\n", "/**\n * WCAG compliant Combobox component\n */\nconst comboTemplate = `\n<div>\n  <slot name=\"input\"></slot>\n  <div>\n    <slot name=\"clear-button\"></slot>\n    <slot name=\"toggle-button\"></slot>\n  </div>\n</div>\n<slot name=\"popup\"></slot>\n`;\nexport default class Combobox extends HTMLElement {\n  constructor() {\n    super();\n    this.popup = null;\n\n    this.template = document.createElement(\"template\");\n    this.template.innerHTML = comboTemplate;\n    this.attachShadow({ mode: \"open\", delegatesFocus: true });\n    this.shadowRoot.append(this.template.content.cloneNode(true));\n    this.shadowRoot.addEventListener(\n      \"slotchange\",\n      this.handleSlotChange.bind(this),\n    );\n\n    // Bound methods\n    this.handleInput = this.handleInput.bind(this);\n    this.handleFocus = this.handleFocus.bind(this);\n    this.handleBlur = this.handleBlur.bind(this);\n    this.handleListboxMouseDown = this.handleListboxMouseDown.bind(this);\n    this.handleKeyDown = this.handleKeyDown.bind(this);\n    this.showPopup = this.showPopup.bind(this);\n    this.hidePopup = this.hidePopup.bind(this);\n    this.submit = this.submit.bind(this);\n    this.handlePopupChange = this.handlePopupChange.bind(this);\n    this.handleToggleClick = this.handleToggleClick.bind(this);\n    this.handleClearClick = this.handleClearClick.bind(this);\n  }\n\n  connectedCallback() {\n    // We need to ensure that the component has a unique id.\n    // This is used to compute popup option ids, which are necessary\n    // for the correct usage of aria-activedescendant and related\n    // pseudo-focus capabilites for assistive technologies.\n    if (!this.id) {\n      console.error(\n        `${this.tagName.toLowerCase()} requires an 'id' attribute to be set`,\n      );\n    }\n\n    // Keyboard and input based events will be listened for on\n    // the input element specifically, and handled on this component.\n    this.input = this.querySelector(`input[slot=\"input\"]`);\n    if (this.input) {\n      this.input.addEventListener(\"input\", this.handleInput);\n      this.input.addEventListener(\"keydown\", this.handleKeyDown);\n      this.input.addEventListener(\"focus\", this.handleFocus);\n      this.input.addEventListener(\"blur\", this.handleBlur);\n    }\n\n    this.addEventListener(\"focus\", this.handleFocus);\n    this.addEventListener(\"blur\", this.handleBlur);\n\n    // The wx:popup-nav is a custom event that will be fired by any\n    // element that is serving as the combobox's popup, such as a\n    // listbox, whenever a navigation event occurs in that element.\n    // In our most common use case, this is when the pseudoFocus\n    // is moved within a listbox that is slotted in this combobox.\n    this.addEventListener(\"wx:popup-nav\", this.handlePopupNav);\n\n    // Set up the appropriate event handlers for the clear button\n    // and the toggle button.\n    this.toggleButton = this.querySelector(`[slot=\"toggle-button\"]`);\n    if (this.toggleButton) {\n      this.toggleButton.addEventListener(\"click\", this.handleToggleClick);\n    }\n    this.clearButton = this.querySelector(`[slot=\"clear-button\"]`);\n    if (this.clearButton) {\n      this.clearButton.addEventListener(\"click\", this.handleClearClick);\n    }\n  }\n\n  /**\n   * Will attempt to show the popup child\n   * element for the combobox, while setting\n   * the appropriate aria attributes needed for\n   * both screenreading and styling.\n   */\n  showPopup() {\n    if (this.input) {\n      this.input.setAttribute(\"aria-expanded\", true);\n      this.setAttribute(\"expanded\", true);\n    }\n    if (this.popup) {\n      const target = this.popup.selection ?? this.popup.pseudoFocus;\n      if (target) {\n        this.popup.pseudoFocusItem(target);\n      }\n    }\n  }\n\n  /**\n   * Will hide the popup child element\n   * for the combobox, by setting the appropriate\n   * attributes needed for screenreading and styling\n   */\n  hidePopup() {\n    this.removeAttribute(\"expanded\");\n    this.input.removeAttribute(\"aria-expanded\");\n    this.input.removeAttribute(\"aria-activedescendant\");\n  }\n\n  /**\n   * Find the closest ancestor <form> element.\n   * If there is one, trigger its submit() method.\n   * Because we work with an input, it will be\n   * considered part of that form and its data will be\n   * used as part of the form action.\n   */\n  submit() {\n    this.closest(\"form\")?.submit();\n  }\n\n  /**\n   * Handle any changes to slotted elements.\n   * This is where we bind and/or remove listeners for\n   * the component that serves as the popup for the\n   * combobox (usually a listbox).\n   * We do it here instead of at component callback time\n   * because we want to leave open the possibility for\n   * popups to be dynamically swapped out if needed,\n   * and to still have all the appropriate event handling\n   * setup when that happens.\n   * This handler also sets ids on the popup itself if\n   * there isn't already one, as well as updating the\n   * combobox input aria-controls to map to the\n   * incoming popup element.\n   */\n  handleSlotChange(event) {\n    const name = event.target.getAttribute(\"name\");\n    const assigned = event.target.assignedElements();\n\n    if (name === \"popup\") {\n      // If there is an existing popup that was attached,\n      // remove any event listeners from it.\n      if (this.popup) {\n        this.popup.removeEventListener(\"change\", this.handlePopupChange);\n        this.popup.removeEventListener(\n          \"mousedown\",\n          this.handleListboxMouseDown,\n        );\n      }\n\n      // Now check if there is a new popup assigned or\n      // if the slot is empty. Either way assign the value\n      // to the stored popup\n      this.popup = assigned.length ? assigned[0] : null;\n      if (this.popup) {\n        this.popup.addEventListener(\"change\", this.handlePopupChange);\n        this.popup.addEventListener(\"mousedown\", this.handleListboxMouseDown);\n\n        // If the listbox element does not have an id set, use\n        // this component's id as a base for creating a unique id.\n        // The listbox options need to have their own unique ids\n        // for the use of aria-activedescendant, which handles pseudo\n        // focus in assistive technologies\n        if (!this.popup.id) {\n          this.popup.id = `${this.id}-popup`;\n\n          // Trigger slotchange event manually\n          this.popup.innerHTML = this.popup.innerHTML;\n        }\n        this.input.setAttribute(\"aria-controls\", this.popup.id);\n\n        this.handlePopupChange({ target: this.popup });\n      }\n    }\n  }\n\n  /**\n   * We need to stop the default behavior of mousedown\n   * on the listbox, so that the normal browser doesn't\n   * try to change focus/blur. This is what otherwise happens\n   * in FF and Safari (but not Chrome), where click events\n   * in the listbox will never be hit because by that time\n   * the input has already blurred and lost focus.\n   */\n  handleListboxMouseDown(event) {\n    event.preventDefault();\n  }\n\n  /**\n   * Handle specific popup navigation event cases.\n   * We want to open the popup if the user tries to\n   * navigate down and it's not already open.\n   * Likewise, if we are already at the top of the popup and\n   * we move up again, it should hide the component.\n   * An additional behavior that is crucial for accessibility\n   * is that any popup child that has pseudofocus will be mapped\n   * to the combobox input's aria-activedescendant, which is a\n   * way of mapping screenreader focus that is separate from\n   * browser element focus.\n   */\n  handlePopupNav(event) {\n    if (event.detail.beyondTop) {\n      // If the user has navigated beyond the top option in the list\n      // (usually a #moveUp when the first item is already selected),\n      // we hide the list\n      this.hidePopup();\n    } else if (\n      event.detail.navCommand === \"moveDown\" &&\n      !event.detail.previous\n    ) {\n      // If there was no previous focus element and we are moving down,\n      // we should attempt to open the popup. This scenario can occur if:\n      // 1. The user has focused the input, revelating the popup, then\n      // 2. The user navigated up past the first item, closing the popup, then\n      // 3. The user navigated down again\n      this.showPopup();\n    }\n\n    // If there is an item pseudoFocused, we update\n    // aria-activedescendant.\n    // Otherwise, remove the attribute entirely\n    if (event.target.pseudoFocus) {\n      this.input.setAttribute(\n        \"aria-activedescendant\",\n        event.target.pseudoFocus.id,\n      );\n    } else {\n      this.input.removeAttribute(\"aria-activedescendant\");\n    }\n  }\n\n  /**\n   * Popup elements can fire generic change events.\n   * In the case of a combobox, we expect that the target\n   * of the event can have a selection.\n   * Set the value of the combobox input to the provided selection.\n   */\n  handlePopupChange(event) {\n    if (event.target.selection) {\n      this.hidePopup();\n\n      const option = event.target.selection;\n      const value = option.getAttribute?.(\"data-value\");\n\n      // \"data-value-for\" is the id of a hidden input used to store the \"real\" value\n      const id = this.input.getAttribute(\"data-value-for\");\n\n      if (value && id) {\n        const element = this.querySelector(`input[name=${id}][type=hidden]`);\n        if (element) element.value = value;\n      }\n\n      this.input.value = event.target.selection.textContent || null;\n    } else {\n      this.input.value = null;\n    }\n\n    if (this.input.value) {\n      const clearButton = this.querySelector(`[slot=\"clear-button\"]`);\n      clearButton.classList.remove(\"empty\");\n    }\n  }\n\n  /**\n   * The combobox keydown event handler will attempt\n   * to find a keyMapping dictionary on its slotted popup\n   * component, such as is available for a listbox.\n   * This allows us to trigger the popup's handlers for the given\n   * keys, without needed to implement them all over again\n   * in this component.\n   */\n  handleKeyDown(event) {\n    const popupIsOpen = this.getAttribute(\"expanded\") === \"true\";\n    if (this.popup) {\n      if (event.key === \"Escape\") {\n        this.popup.pseudoFocusItem(null);\n        return this.hidePopup();\n      } else if (event.key === \"ArrowDown\" && !popupIsOpen) {\n        // We focus the first item\n        this.popup.pseudoFocusItem(\n          this.popup.querySelector(`[role=\"option\"][data-option-index=\"0\"]`),\n        );\n        return this.showPopup();\n      }\n\n      // Otherwise, let the listbox handle the event, so long\n      // as it has a keymapping defined.\n      if (this.popup.keyMapping) {\n        const handler = this.popup.keyMapping[event.key];\n        if (handler) {\n          const boundHandler = handler.bind(this.popup);\n          boundHandler(event);\n          event.preventDefault();\n        }\n      }\n    }\n  }\n\n  /**\n   * Cick handler for the toggle button.\n   * Will show or hide the popup depending\n   * on the state.\n   */\n  handleToggleClick(event) {\n    event.preventDefault();\n    if (this.getAttribute(\"expanded\") === \"true\") {\n      this.hidePopup();\n    } else {\n      this.showPopup();\n      this.input.focus();\n    }\n  }\n\n  /**\n   * Click handler for the clear button.\n   * Will clear the input and reset state on the\n   * popup.\n   */\n  handleClearClick(event) {\n    event.preventDefault();\n    this.popup.pseudoFocusItem(null);\n    this.input.value = \"\";\n    this.handleInput();\n    this.input.focus();\n    this.hidePopup();\n  }\n\n  /**\n   * Text input handler for the combobox input element.\n   * Will attempt to call the `filterText()` method of any\n   * slotted popup element using the input's current value.\n   * Will also update the presence of the clear button based\n   * on the input's new value.\n   */\n  handleInput(event) {\n    if (this.popup) {\n      if (!this.hasAttribute(\"expanded\")) {\n        this.showPopup();\n      }\n      if (this.popup.filterText) {\n        this.popup.filterText(this.input.value);\n      }\n    }\n\n    // Hide or show the clear button's slot\n    // based on the input value's presence\n    const clearButton = this.querySelector(`[slot=\"clear-button\"]`);\n    if (this.input.value && this.input.value !== \"\") {\n      clearButton.classList.remove(\"empty\");\n    } else {\n      clearButton.classList.add(\"empty\");\n    }\n  }\n\n  /**\n   * When gaining focus, show the popup but only\n   * if there are actual options available in the popup.\n   */\n  handleFocus(event) {\n    const hasItems = this.popup.querySelectorAll(`[role=\"option\"]`).length;\n    if (hasItems) {\n      this.showPopup();\n    }\n  }\n\n  /**\n   * Hide the popup when this element loses focus.\n   */\n  handleBlur(event) {\n    // Only perform blur operations if the target of the\n    // event is outside of the combobox component\n    const ancestor = event.relatedTarget?.closest(this.tagName);\n    if (ancestor !== this) {\n      this.popup.pseudoFocusItem(null);\n      this.hidePopup();\n      if (this.popup && this.popup.selection) {\n        this.input.value = this.popup.selection.textContent;\n        const clearButton = this.querySelector(`[slot=\"clear-button\"]`);\n        clearButton.classList.remove(\"empty\");\n      }\n    }\n  }\n\n  /**\n   * The only attribute we listen for changes on is 'disabled',\n   * which reacts by disabling (or re-enabling) all constinuent\n   * elements that can be disabled. This prevents any key or mouse\n   * events from triggering event handlers.\n   */\n  attributeChangedCallback(name, oldVal, newVal) {\n    if (name === \"disabled\" && newVal === \"true\") {\n      this.input.setAttribute(\"disabled\", true);\n      this.clearButton.setAttribute(\"disabled\", true);\n      this.toggleButton.setAttribute(\"disabled\", true);\n      this.hidePopup();\n    } else if (name === \"disabled\") {\n      this.input.removeAttribute(\"disabled\");\n      this.clearButton.removeAttribute(\"disabled\");\n      this.toggleButton.removeAttribute(\"disabled\");\n    }\n  }\n\n  get isExpanded() {\n    return this.getAttribute(\"expanded\") === \"true\";\n  }\n\n  static get observedAttributes() {\n    return [\"disabled\"];\n  }\n}\n\nif (!window.customElements.get(\"wx-combobox\")) {\n  window.customElements.define(\"wx-combobox\", Combobox);\n}\n", "/** @file Manage a visitor's recent locations in local storage. */\n\nconst RECENT_LOC_STORAGE = \"wxgov_recent_locations\";\n\n/**\n * @typedef {Object} RecentLocation from local storage\n * @property {string} url the point forecast url for the location\n * @property {string} text the human-readable location name\n */\n\n/**\n * Get the list of recent locations from local storage.\n *\n * @returns {RecentLocation}\n */\nexport function getRecentLocations() {\n  try {\n    const existing = localStorage.getItem(RECENT_LOC_STORAGE);\n    const parsed = JSON.parse(existing ?? \"[]\");\n\n    // Check if any saved locations still have the old /point/lat/long url format\n    const needsUpdate = parsed.filter(({ url }) => url.startsWith(\"/point\"));\n\n    if (needsUpdate.length > 0) {\n      // Prepend the forecast path to any URLs that need it\n      const updated = parsed.map(({ url, ...rest }) => ({\n        ...rest,\n        url: url.startsWith(\"/forecast\") ? url : `/forecast${url}`,\n      }));\n      localStorage.setItem(RECENT_LOC_STORAGE, JSON.stringify(updated));\n      return updated;\n    }\n    return parsed;\n  } catch (e) {\n    return [];\n  }\n}\n\n/**\n * Insert a recent location into local storage.\n * If the location already exists, move it to the top.\n *\n * @param {RecentLocation} obj - the recent location\n */\nexport function addRecentLocation(obj) {\n  try {\n    // First we need to see if there are any existing\n    // items already saved in the saved searches array\n    const existing = localStorage.getItem(RECENT_LOC_STORAGE);\n    const parsed = JSON.parse(existing ?? \"[]\");\n    // Now remove any items for the same URL. This way we don't\n    // end up having a whole list of the same place\n    const filtered = parsed.filter(({ url }) => url !== obj.url);\n    // Just keep the most recent ten.\n    const sliced = filtered.slice(0, 9);\n\n    // Put the new entry at the front of the list\n    sliced.unshift(obj);\n\n    // Now serialize and save\n    localStorage.setItem(RECENT_LOC_STORAGE, JSON.stringify(sliced));\n  } catch (e) {\n    /* do nothing */\n  }\n}\n", "import Listbox from \"./listbox.js\";\nimport { getRecentLocations, addRecentLocation } from \"../recent-locations.js\";\nimport Timer from \"../timer.js\";\n\nconst debouncer = new Timer();\n\nconst getRedirectUrlFromAddressCandidate = (addressCandidate) => {\n  const { type, lat, lon, abbr } = addressCandidate;\n  const typeLowercase = type.toLowerCase();\n  if (typeLowercase === \"county\") {\n    return `/wx/location-search/county/${lat}/${lon}`;\n  } else if (typeLowercase === \"state or province\" && abbr) {\n    return `/forecast/state/${abbr}`;\n  }\n  return `/forecast/point/${lat}/${lon}`;\n};\n\n/**\n * @typedef {Object} Suggestion from geocode.arcgis.com\n * @property {boolean} isCollection\n * @property {string} magicKey\n * @property {string} text the human-readable location name\n */\n\n/**\n * @typedef {Object} SavedLocation from local storage\n * @property {string} url the point forecast url for the location\n * @property {string} text the human-readable location name\n */\n\n/**\n * Helper function. Creates an `li` element for a given choice.\n *\n * @param {number} setSize the number of results in the list\n * @param {string|undefined} describedby the id of the element which describes the list (optional)\n * @param {Suggestion|SavedLocation} suggestion the data for this item\n * @param {number} idx the item's position in the list\n * */\nconst makeListItemFromResultItem = (setSize, describedby, suggestion, idx) => {\n  const item = document.createElement(\"li\");\n  item.innerText = suggestion.text;\n  item.setAttribute(\"role\", \"option\");\n  item.setAttribute(\"aria-setsize\", setSize);\n  item.setAttribute(\"posinset\", idx + 1);\n  item.setAttribute(\"aria-selected\", false);\n  if (describedby) {\n    item.setAttribute(\"aria-describedby\", describedby);\n  }\n  if (suggestion.magicKey) {\n    item.setAttribute(\"data-magic-key\", suggestion.magicKey);\n  } else if (suggestion.url) {\n    item.setAttribute(\"data-url\", suggestion.url);\n  } else {\n    return null;\n  }\n  return item;\n};\n\n/**\n * Given a `ul` for location search results, create all the child `li`s.\n *\n * @param {HTMLElement} resultListElement the container for the result list\n * @param {HTMLElement|undefined} ariaDescEl the element which describes the list (optional)\n * @param {Array<Suggestion|SavedLocation>} suggestions\n */\nconst makeListFromResult = (resultListElement, ariaDescEl, suggestions) => {\n  resultListElement.innerHTML = \"\";\n  const setSize = suggestions.length;\n  const describedby = ariaDescEl.id;\n  const newItems = suggestions.map((suggestion, idx) => {\n    return makeListItemFromResultItem(setSize, describedby, suggestion, idx);\n  });\n  resultListElement.append(...newItems);\n};\n\nexport default class LocationListbox extends Listbox {\n  constructor() {\n    super();\n\n    // Private property defaults\n    this.inputDelay = 250;\n\n    // Bound component methods\n    this.updateSavedSearches = this.updateSavedSearches.bind(this);\n    this.getSearchResults = this.getSearchResults.bind(this);\n    this.handlePopupNav = this.handlePopupNav.bind(this);\n  }\n\n  connectedCallback() {\n    super.connectedCallback();\n\n    this.addEventListener(\"wx:popup-nav\", this.handlePopupNav);\n\n    // If there is a place set via attribute, we add\n    // it to the saved search results\n    if (this.dataset.place) {\n      addRecentLocation({\n        text: this.dataset.place,\n        url: window.location.pathname,\n      });\n    }\n    this.updateSavedSearches();\n  }\n\n  /**\n   * Override selectItem to first fetch the location data\n   * (either from cache or live) for the option with the\n   * given magicKey\n   */\n  selectItem(element) {\n    // For consistency, let's force even the regular calls\n    // to selectItem to be wrapped as promises\n    const selectItemPromise = new Promise((resolve) => {\n      resolve(super.selectItem(element));\n    });\n\n    // If the incoming element is falsy, just return the\n    // promise to call the super version.\n    if (!element) {\n      return selectItemPromise;\n    }\n\n    // Otherwise, if the option's data-url attribute exists, use that.\n    if (element.getAttribute(\"data-url\")) {\n      return new Promise((resolve) => {\n        if (this.getAttribute(\"auto-submit\") === \"true\") {\n          addRecentLocation({\n            text: element.innerText,\n            url: element.getAttribute(\"data-url\"),\n          });\n          const form = this.closest(\"form[data-location-search]\");\n          form.setAttribute(\"action\", element.getAttribute(\"data-url\"));\n          form.submit();\n          // Show the loader animation, if available\n          window.dispatchEvent(\n            new CustomEvent(\"wx-show-navigation-loader\", {\n              detail: { id: this.getAttribute(\"id\") },\n            }),\n          );\n        }\n\n        resolve(super.selectItem(element));\n      });\n    }\n\n    // Otherwise, attempt to get cached/fetched\n    // geographic data and add that to the option element\n    // dataset/attributes.\n    // This is so consumers of the change event can see the result.\n    if (element.dataset.magicKey) {\n      return this.getGeodataForKey(element.dataset.magicKey).then((geoData) => {\n        if (geoData) {\n          element.setAttribute(\"data-lat\", geoData.lat);\n          element.setAttribute(\"data-lon\", geoData.lon);\n          if (this.getAttribute(\"auto-submit\") === \"true\") {\n            const formUrl = getRedirectUrlFromAddressCandidate(geoData);\n\n            addRecentLocation({\n              text: element.innerText,\n              url: formUrl,\n            });\n\n            const form = this.closest(\"form[data-location-search]\");\n            form.setAttribute(\"action\", formUrl);\n            form.submit();\n            // Show the loader animation, if available\n            window.dispatchEvent(\n              new CustomEvent(\"wx-show-navigation-loader\", {\n                detail: { id: this.getAttribute(\"id\") },\n              }),\n            );\n          }\n        }\n        super.selectItem(element);\n      });\n    }\n\n    return selectItemPromise;\n  }\n\n  /**\n   * For this subclass of the listbox, we want to\n   * prefetch and cache location data for the magicKey\n   * for any result list item. We speculatively do so\n   * whenever a given item receives the pseudoFocus.\n   */\n  handlePopupNav(event) {\n    if (this.pseudoFocus) {\n      const key = this.pseudoFocus.dataset.value;\n      this.cacheLocationGeodata(key);\n    }\n  }\n\n  /**\n   * Retrieve saved locations from local storage and\n   * insert them into the popup, filtering first by\n   * `filterTerm` if one is given.\n   */\n  updateSavedSearches(filterTerm) {\n    const savedSearchesGroup = this.querySelector(\n      '[role=\"group\"].saved-searches',\n    );\n    const savedSearchesLabel = this.querySelector(\n      '[role=\"heading\"].saved-searches',\n    );\n    if (savedSearchesGroup) {\n      let saved = getRecentLocations();\n\n      // Clear any existing search items in the element.\n      // We will regenerate them.\n      savedSearchesGroup.innerHTML = \"\";\n\n      if (filterTerm) {\n        const match = filterTerm.toLowerCase();\n        saved = saved.filter((option) =>\n          option.text.toLowerCase().includes(match),\n        );\n      }\n\n      // If there are no saved searches, we should hide\n      // the list and the label together\n      if (!saved.length) {\n        savedSearchesLabel?.classList?.add?.(\"hidden\");\n        savedSearchesGroup.classList.add(\"hidden\");\n      } else {\n        savedSearchesLabel?.classList?.remove?.(\"hidden\");\n        savedSearchesGroup.classList.remove(\"hidden\");\n        makeListFromResult(savedSearchesGroup, savedSearchesLabel, saved);\n      }\n    }\n  }\n\n  async getSearchResults(text) {\n    const response = await this.searchLocation(text);\n    if (response.ok) {\n      const data = await response.json();\n      return data;\n    }\n    return { suggestions: [] };\n  }\n\n  /** Announce updated search results in an Aria live region. */\n  announceResults() {\n    const numResults = this.querySelectorAll(\"li\").length;\n    const translation = ngettext(\n      \"js.location-combo-box.aria.search-updated.01\",\n      \"js.location-combo-box.aria.search-updated.01-plural\",\n      numResults,\n    );\n    const transWithCount = interpolate(translation, [numResults]);\n    window.dispatchEvent(\n      new CustomEvent(\"wx-announce\", {\n        detail: { text: transWithCount, delay: 0 },\n      }),\n    );\n  }\n\n  async filterText(text) {\n    debouncer.start(async () => {\n      const data = await this.getSearchResults(text);\n      const resultListElement = this.querySelector(\n        '[role=\"group\"].data-results',\n      );\n      const headerElement = this.querySelector('[role=\"heading\"].data-results');\n      if (resultListElement) {\n        resultListElement.remove();\n        makeListFromResult(resultListElement, headerElement, data.suggestions);\n        this.append(resultListElement);\n      }\n      this.updateSavedSearches(text);\n      this.announceResults();\n    }, this.inputDelay);\n  }\n\n  /**\n   * Asynchronously fetches specific location data\n   * for a given search result, stashing it away in\n   * the cache\n   */\n  async cacheLocationGeodata(magicKey) {\n    if (!window.sessionStorage.getItem(magicKey)) {\n      const result = await this.getLocationGeodata(magicKey);\n      window.sessionStorage.setItem(magicKey, JSON.stringify(result));\n    }\n  }\n\n  /**\n   * Attempts to retrieve location data for a search\n   * result by its magicKey from the cache.\n   * If not present, will make the Arc API call\n   * to fetch the data.\n   */\n  async getGeodataForKey(magicKey) {\n    const cached = window.sessionStorage.getItem(magicKey);\n    if (!cached) {\n      return this.getLocationGeodata(magicKey);\n    }\n    return JSON.parse(cached);\n  }\n\n  async getLocationGeodata(magicKey) {\n    const url = `https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/findAddressCandidates?magicKey=${magicKey}&f=json&_=1695666335115&outFields=Type,RegionAbbr`;\n    const response = await fetch(url, {\n      headers: { \"Content-Type\": \"application/json\" },\n    });\n    const results = await response.json();\n    return this.processLocationGeodata(results);\n  }\n\n  processLocationGeodata(results) {\n    if (\n      !results.error &&\n      Array.isArray(results.candidates) &&\n      results.candidates.length > 0\n    ) {\n      // Take the first available location (highest score)\n      const firstCandidate = results.candidates[0];\n      const { x, y } = firstCandidate.location;\n      const type = firstCandidate.attributes.Type;\n      const abbr = firstCandidate.attributes.RegionAbbr;\n\n      const lat = Math.round(y * 1_000) / 1_000;\n      const lon = Math.round(x * 1_000) / 1_000;\n      return { lat, lon, type, abbr };\n    }\n\n    return null;\n  }\n\n  async searchLocation(text) {\n    const url = `https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/suggest?f=json&countryCode=USA%2CPRI%2CVIR%2CGUM%2CASM&category=Land+Features%2CBay%2CChannel%2CCove%2CDam%2CDelta%2CGulf%2CLagoon%2CLake%2COcean%2CReef%2CReservoir%2CSea%2CSound%2CStrait%2CWaterfall%2CWharf%2CAmusement+Park%2CHistorical+Monument%2CLandmark%2CTourist+Attraction%2CZoo%2CCollege%2CBeach%2CCampground%2CGolf+Course%2CHarbor%2CNature+Reserve%2COther+Parks+and+Outdoors%2CPark%2CRacetrack%2CScenic+Overlook%2CSki+Resort%2CSports+Center%2CSports+Field%2CWildlife+Reserve%2CAirport%2CFerry%2CMarina%2CPier%2CPort%2CResort%2CPostal%2CPopulated+Place&maxSuggestions=10&_=1695666335097&text=${text}`;\n    return fetch(url, { headers: { \"Content-Type\": \"application/json\" } });\n  }\n}\n\nif (!window.customElements.get(\"wx-location-listbox\")) {\n  window.customElements.define(\"wx-location-listbox\", LocationListbox);\n}\n", "/** @file Manage a visitor's recent/favorite locations in local storage. */\n\nconst SAVED_LOC_STORAGE = \"wxgov_saved_locations\";\nconst RECENT_LOC_STORAGE = \"wxgov_recent_locations\";\nconst TAB_REGEX = new RegExp(\"\\/(?:alerts|today|7-day|maps|analysis).*\", \"i\");\n\n/**\n * @typedef {Object} SavedLocations from local storage\n * @property {Object.<string, string>} hashed object of saved location (lowercase-text : url)\n * @property {Array<SavedLocation>} sorted sorted list of saved locations\n */\n\n/**\n * @typedef {Object} SavedLocation from local storage\n * @property {string} text the human-readable location name\n * @property {string} url the point forecast url for the location\n */\n\n/**\n * Remove a trailing forecast tab while preserving the rest of the URL.\n * @param {string} url location URL\n * @returns {string} location URL without a tab suffix\n */\nfunction normalizeLocationUrl(url) {\n  if (typeof url !== \"string\") return url;\n\n  return url.replace(TAB_REGEX, \"\");\n}\n\n/**\n * Normalize both URL representations in a saved-location collection.\n * @param {SavedLocations} storage saved location collection\n * @returns {SavedLocations} normalized collection\n */\nfunction normalizeSavedLocationStorage(storage) {\n  if (storage?.hashed) {\n    storage.hashed = Object.fromEntries(\n      Object.entries(storage.hashed).map(([text, url]) => [\n        text,\n        normalizeLocationUrl(url),\n      ]),\n    );\n  }\n  if (storage?.sorted) {\n    storage.sorted = storage.sorted.map((location) => ({\n      ...location,\n      url: normalizeLocationUrl(location.url),\n    }));\n  }\n  return storage;\n}\n\n/**\n * Get JSON parsed local storage for saved locations\n * @returns {SavedLocations}\n */\nfunction getParsedSavedLocationStorage() {\n  const storage = localStorage.getItem(SAVED_LOC_STORAGE);\n  const parsedStorage = JSON.parse(storage ?? \"{}\");\n  return normalizeSavedLocationStorage(parsedStorage);\n}\n\n/**\n * Set saved location local storage to new JSON item\n * @param {SavedLocations} newStorage saved location collection to set\n */\nfunction setSavedLocationStorage(newStorage) {\n  localStorage.setItem(\n    SAVED_LOC_STORAGE,\n    JSON.stringify(normalizeSavedLocationStorage(newStorage)),\n  );\n}\n\n/**\n * Get the sorted list of saved locations from local storage\n * @returns {Array<SavedLocation>}\n */\nexport function getSavedLocations() {\n  const current = getParsedSavedLocationStorage();\n\n  return current?.sorted ? current.sorted : [];\n}\n\n/**\n * Returns if location is within the saved location local storage\n * @param {string} locText location to match if in saved location storage\n * @returns {boolean}\n */\nexport function hasSavedLocation(locText) {\n  let found = false;\n  if (locText?.length) {\n    const locLower = locText?.toLowerCase();\n    const existing = getParsedSavedLocationStorage();\n    found = existing?.hashed && Object.hasOwn(existing.hashed, locLower);\n  }\n  return found;\n}\n\n/**\n * Adds a new location to saved locations in local storage, maintaining sorted order\n * @param {SavedLocation} obj saved location object to add to storage\n */\nexport function addSavedLocation(obj) {\n  // Validate obj\n  if (!obj && !obj?.text?.toLowerCase() && !obj?.url) return;\n\n  const textLower = obj.text.toLowerCase();\n  const existing = getParsedSavedLocationStorage();\n  const hashed = existing?.hashed ?? {};\n  const sorted = existing?.sorted ?? [];\n\n  if (!Object.hasOwn(hashed, textLower)) {\n    if (sorted?.length) {\n      // Find the correct sorted location to insert new element based on text\n      const largerElemIndex = sorted.findIndex((item) => {\n        return item?.text?.toLowerCase() > textLower;\n      });\n      // Insert new element before the larger element\n      if (largerElemIndex === -1) {\n        sorted.push(obj);\n      } else {\n        sorted.splice(largerElemIndex, 0, obj);\n      }\n    } else {\n      sorted.push(obj);\n    }\n    hashed[textLower] = obj?.url;\n    setSavedLocationStorage({\n      hashed: hashed,\n      sorted: sorted,\n    });\n  }\n}\n\n/**\n * Removes the saved location from storage that matches the location string\n * @param {string} loc location string to remove from storage\n */\nexport function removeSavedLocation(loc) {\n  const locLower = loc?.toLowerCase();\n  const existing = getParsedSavedLocationStorage();\n  const existingSorted = existing?.sorted ?? [];\n  const existingHashed = existing?.hashed ?? {};\n  const existingElemIdx = existingSorted.findIndex((item) => {\n    return item?.text?.toLowerCase() === locLower;\n  });\n\n  if (existingElemIdx > -1) {\n    // Remove element in place and update storage with new collection\n    existingSorted.splice(existingElemIdx, 1);\n    delete existingHashed[loc.toLowerCase()];\n    setSavedLocationStorage({ sorted: existingSorted, hashed: existingHashed });\n  }\n}\n", "/**\n * Saved location section handler\n */\nimport {\n  getSavedLocations,\n  hasSavedLocation,\n  addSavedLocation,\n  removeSavedLocation,\n} from \"./saved-locations.js\";\n\nclass SavedLocationsSection extends HTMLElement {\n  constructor() {\n    super();\n\n    this.displayClass = \"\";\n    this.hideClass = \"display-none\";\n    this.buttonItemIdPrefix = \"saved-locations-section-btn-\";\n    this.ariaCheckedAttribute = \"aria-checked\";\n\n    this.savedLocations = {};\n\n    this.sectionType = this.dataset?.type ?? \"front\";\n    this.sectionCols = this.dataset?.columns ?? \"true\";\n    this.sectionEl = this.querySelector(\n      `#saved-locations-section-${this.sectionType}`,\n    );\n    this.templateLi = this.querySelector(\n      `#saved-locations-section-${this.sectionType}-li`,\n    );\n\n    this.bindEventListeners = this.bindEventListeners.bind(this);\n    this.unbindEventlisteners = this.unbindEventlisteners.bind(this);\n\n    this.initSection = this.initSection.bind(this);\n    this.hideList = this.hideList.bind(this);\n    this.showList = this.showList.bind(this);\n\n    this.addListButtonEvents = this.addListButtonEvents.bind(this);\n    this.createList = this.createList.bind(this);\n    this.createListItem = this.createListItem.bind(this);\n    this.getListColumnClass = this.getListColumnClassList.bind(this);\n\n    this.onListButtonClick = this.onListButtonClick.bind(this);\n    this.onSavedLocationsButtonAdd = this.onSavedLocationsButtonAdd.bind(this);\n    this.onSavedLocationsButtonRemove =\n      this.onSavedLocationsButtonRemove.bind(this);\n    this.onSectionLocationAdd = this.onSectionLocationAdd.bind(this);\n    this.onSectionLocationRemove = this.onSectionLocationRemove.bind(this);\n  }\n\n  connectedCallback() {\n    this.bindEventListeners();\n    this.initSection();\n  }\n\n  disconnectedCallback() {\n    this.unbindEventlisteners();\n  }\n\n  bindEventListeners() {\n    window.addEventListener(\n      \"wx-saved-locations:button-add\",\n      this.onSavedLocationsButtonAdd,\n    );\n    window.addEventListener(\n      \"wx-saved-locations:button-remove\",\n      this.onSavedLocationsButtonRemove,\n    );\n    window.addEventListener(\n      \"wx-saved-locations:section-add\",\n      this.onSectionLocationAdd,\n    );\n    window.addEventListener(\n      \"wx-saved-locations:section-remove\",\n      this.onSectionLocationRemove,\n    );\n  }\n  unbindEventlisteners() {\n    window.removeEventListener(\n      \"wx-saved-locations:button-add\",\n      this.onSavedLocationsButtonAdd,\n    );\n    window.removeEventListener(\n      \"wx-saved-locations:button-remove\",\n      this.onSavedLocationsButtonRemove,\n    );\n    window.removeEventListener(\n      \"wx-saved-locations:section-add\",\n      this.onSectionLocationAdd,\n    );\n    window.removeEventListener(\n      \"wx-saved-locations:section-remove\",\n      this.onSectionLocationRemove,\n    );\n  }\n\n  initSection() {\n    const currentLocations = getSavedLocations();\n    if (currentLocations?.length) {\n      this.createList(currentLocations);\n      this.showList();\n    } else {\n      this.hideList();\n    }\n  }\n\n  hideList() {\n    this.sectionEl?.classList?.add(this.hideClass);\n  }\n\n  showList() {\n    this.sectionEl?.classList?.remove(this.hideClass);\n  }\n\n  cleanString(str) {\n    return str?.trim()?.replace(/\\W/g, \"\")?.toLowerCase();\n  }\n\n  createList(locations) {\n    const listUl = this.querySelector(\"ul\");\n    const listColumnClass = this.getListColumnClassList(locations.length);\n    if (listColumnClass?.length) listUl.classList.add(...listColumnClass);\n\n    const newElems = [];\n\n    for (let index = 0; index < locations.length; index++) {\n      const { text, url } = locations[index];\n      const element = this.createListItem(text, url);\n      newElems.push(element);\n    }\n    listUl.replaceChildren();\n    listUl.append(...newElems);\n    this.addListButtonEvents();\n  }\n\n  createListItem(text, url) {\n    const cleanedText = this.cleanString(text);\n    this.savedLocations[text] = true;\n\n    // Clone the template\n    const templateLi = this.templateLi;\n    const clonedLi = document.importNode(templateLi.content, true);\n\n    // Update the template\n    const liButton = clonedLi.querySelector(\"button\");\n    liButton.id = `${liButton.id}${cleanedText}`;\n    liButton.setAttribute(\"data-loctext\", text);\n    liButton.setAttribute(\"data-locurl\", url);\n    liButton.setAttribute(\"aria-label\", `Saved location ${text}`);\n\n    const liAnchor = clonedLi.querySelector(\"a\");\n    const anchorId = `saved-locations-section-label-${cleanedText}`;\n    liAnchor.id = anchorId;\n    liAnchor.setAttribute(\"href\", url);\n    liAnchor.innerText = text;\n\n    return clonedLi;\n  }\n\n  getListColumnClassList(itemLength) {\n    if (this.sectionCols === \"false\") return \"\";\n    const columnBase = \"use-columns\",\n      classRange = [\n        { min: 25, class: \"--x4\" },\n        { min: 17, class: \"--x3\" },\n        { min: 9, class: \"--x2\" },\n      ];\n    let columnPostfix;\n\n    for (let index = 0; index < classRange.length; index++) {\n      if (itemLength >= classRange[index].min) {\n        columnPostfix = classRange[index].class;\n        break;\n      }\n    }\n\n    return columnPostfix ? [columnBase, `${columnBase}${columnPostfix}`] : [];\n  }\n\n  addListButtonEvents() {\n    const buttonElems = this.querySelectorAll(\"button.saved-locations-button\");\n    buttonElems.forEach((btn) => {\n      btn.addEventListener(\"click\", this.onListButtonClick);\n    });\n  }\n\n  onListButtonClick(e) {\n    const currentTarget = e.currentTarget;\n    const currentLoc = currentTarget.dataset.loctext;\n    const currentUrl = currentTarget.dataset.locurl;\n    if (this.savedLocations[currentLoc] === true) {\n      currentTarget.setAttribute(this.ariaCheckedAttribute, false);\n      this.savedLocations[currentLoc] = false;\n      removeSavedLocation(currentLoc);\n      window.dispatchEvent(\n        new CustomEvent(\"wx-saved-locations:section-remove\", {\n          detail: {\n            text: currentLoc,\n            url: currentUrl,\n            caller: this.sectionType,\n          },\n        }),\n      );\n    } else {\n      currentTarget.setAttribute(this.ariaCheckedAttribute, true);\n      this.savedLocations[currentLoc] = true;\n      addSavedLocation({ text: currentLoc, url: currentTarget.dataset.locurl });\n      window.dispatchEvent(\n        new CustomEvent(\"wx-saved-locations:section-add\", {\n          detail: {\n            text: currentLoc,\n            url: currentUrl,\n            caller: this.sectionType,\n          },\n        }),\n      );\n    }\n  }\n\n  onSavedLocationsButtonAdd(e) {\n    // If already in list, set the button to saved, otherwise add to the list\n    const detail = e.detail ?? {};\n    const addLocation = detail?.text ?? \"\";\n    if (addLocation in this.savedLocations) {\n      if (this.savedLocations[addLocation] === false) {\n        // Get the button\n        const buttonId = `${this.buttonItemIdPrefix}${this.cleanString(addLocation)}`;\n        const buttonElem = this.querySelector(`#${buttonId}`);\n        buttonElem.setAttribute(this.ariaCheckedAttribute, true);\n        this.savedLocations[addLocation] = true;\n      }\n    } else {\n      // Find where to insert new node\n      const currentSavedLocations = getSavedLocations();\n      const currentList = this.querySelectorAll(\"li\");\n      const currentListUl = this.querySelector(\"ul\");\n\n      const currentLocationIndex = currentSavedLocations.findIndex((loc) => {\n        return addLocation === loc.text;\n      });\n\n      if (currentLocationIndex !== -1) {\n        // Gather previous list's column class and get new class\n        const currentColumnClass = this.getListColumnClassList(\n          currentList.length,\n        );\n        const newColumnClass = this.getListColumnClassList(\n          currentList.length + 1,\n        );\n\n        // Create new DOM element\n        const currentLocationItem = currentSavedLocations[currentLocationIndex];\n        const newListItem = this.createListItem(\n          currentLocationItem.text,\n          currentLocationItem.url,\n        );\n\n        // Attach event listener to button\n        const newListButton = newListItem.querySelector(\n          \"button.saved-locations-button\",\n        );\n        newListButton.addEventListener(\"click\", this.onListButtonClick);\n\n        // Insert into the list\n        if (currentList?.length === 0) {\n          currentListUl.append(newListItem);\n        } else if (currentLocationIndex === 0) {\n          currentList[0].before(newListItem);\n        } else {\n          currentList[currentLocationIndex - 1].after(newListItem);\n        }\n        // Update column class\n        if (currentColumnClass?.length)\n          currentListUl.classList.remove(...currentColumnClass);\n        if (newColumnClass?.length)\n          currentListUl.classList.add(...newColumnClass);\n\n        // Update local tracking\n        this.savedLocations[addLocation] = true;\n\n        // If previously hidden, now show\n        if (currentList?.length === 0) {\n          this.showList();\n        }\n      }\n    }\n  }\n\n  onSavedLocationsButtonRemove(e) {\n    // Disable the necessary button but don't remove from the list yet\n    const detail = e.detail ?? {};\n\n    const addLocation = detail?.text ?? \"\";\n    if (addLocation in this.savedLocations) {\n      if (this.savedLocations[addLocation] === true) {\n        // Get the button and disable\n        const buttonId = `${this.buttonItemIdPrefix}${this.cleanString(addLocation)}`;\n        const buttonElem = this.querySelector(`#${buttonId}`);\n        buttonElem.setAttribute(this.ariaCheckedAttribute, false);\n        this.savedLocations[addLocation] = false;\n      }\n    }\n  }\n\n  onSectionLocationAdd(e) {\n    // Another section has set item to saved, now update this list also\n    const detail = e.detail ?? {};\n    const caller = detail?.caller;\n    if (caller === this.sectionType) return;\n\n    const addLocation = detail?.text ?? \"\";\n\n    if (addLocation in this.savedLocations) {\n      if (this.savedLocations[addLocation] === false) {\n        // Get the button\n        const buttonId = `${this.buttonItemIdPrefix}${this.cleanString(addLocation)}`;\n        const buttonElem = this.querySelector(`#${buttonId}`);\n        buttonElem.setAttribute(this.ariaCheckedAttribute, true);\n        this.savedLocations[addLocation] = true;\n      }\n    }\n  }\n\n  onSectionLocationRemove(e) {\n    // Another section has set item to unsaved, now update this list also\n    const detail = e.detail ?? {};\n    const caller = detail?.caller;\n    if (caller === this.sectionType) return;\n\n    const removeLocation = detail?.text ?? \"\";\n\n    if (removeLocation in this.savedLocations) {\n      if (this.savedLocations[removeLocation] === true) {\n        // Get the button and disable\n        const buttonId = `${this.buttonItemIdPrefix}${this.cleanString(removeLocation)}`;\n        const buttonElem = this.querySelector(`#${buttonId}`);\n        buttonElem.setAttribute(this.ariaCheckedAttribute, false);\n        this.savedLocations[removeLocation] = false;\n      }\n    }\n  }\n}\n\nif (!window.customElements.get(\"wx-saved-locations-section\")) {\n  window.customElements.define(\n    \"wx-saved-locations-section\",\n    SavedLocationsSection,\n  );\n}\n", "/**\n * Pull the application ID from a specific meta tag, if the tag is there.\n * If it is not present, the given environment is not set up for using RUM.\n */\nconst getRUMApplicationId = () => {\n  const tag = document.querySelector(`meta[data-name=\"aws-rum-app-id\"]`);\n  if (!tag || !tag.getAttribute(\"content\")) {\n    console.warn(`No valid RUM application id found in markup.`);\n    return null;\n  }\n  return tag.getAttribute(\"content\");\n};\n\n/**\n * General configuration for our environment(s)\n */\nconst config = {\n  sessionSampleRate: 1.0,\n  identityPoolId: \"us-east-1:d53843c8-350a-4c14-a929-8c0b2844cf62\",\n  endpoint: \"https://dataplane.rum.us-east-1.amazonaws.com\",\n  telemetries: [\"performance\", \"errors\", \"http\"],\n  allowCookies: true,\n  enableXRay: false,\n  signing: true, // If you have a public resource policy and wish to send unsigned requests please set this to false\n  disableAutoPageView: true,\n  customEvents: { enabled: true },\n};\n\n/**\n * Extracted version of the anonymous function in snippet used for creating\n * the RUM client and attaching it to the window as a global.\n */\nconst createAwsRumClient = (name, id, version, region, scriptSrc, config) => {\n  window.AwsRumClient = {\n    q: [],\n    n: name,\n    i: id,\n    v: version,\n    r: region,\n    c: config,\n  };\n\n  window[name] = function (config, p) {\n    window.AwsRumClient.q.push({ c: config, p });\n  };\n\n  const scriptTag = document.createElement(\"script\");\n  scriptTag.async = true;\n  scriptTag.src = scriptSrc;\n  document.head.insertBefore(\n    scriptTag,\n    document.getElementsByTagName(\"script\")[0],\n  );\n};\n\n/**\n * Helper function for determining page groups based on the\n * provided path. Used for giving stable labels to different kinds\n * of URLs.\n */\nconst pageGroups = (path) => {\n  const match = path.match(\n    /^\\/(forecast\\/county|forecast\\/state|cms|forecast\\/point|place)/,\n  );\n  if (!match) {\n    // this pathname is not part of a RUM page group\n    return null;\n  }\n  const what = match[1];\n  // rename endpoints for clarity on the RUM side\n  switch (what) {\n    case \"forecast/point\":\n      return \"forecast\";\n    case \"forecast/county\":\n      return \"county\";\n    case \"forecast/state\":\n      return \"state\";\n    default:\n      return what;\n  }\n};\n\nconst isUsingHTMX = () => {\n  // We determine if we are using HTMX by checking that the\n  // HTMX script element is on the page\n  const script = document.querySelector(`script[src*=\"point-htmx\"]`);\n  if (script) {\n    return true;\n  }\n  return false;\n};\n\nconst getPointForecastPageName = (path) => {\n  const match = path.match(\n    /^\\/forecast\\/point\\/[0-9-.]+\\/[0-9-.]+\\/(alerts|analysis|7-day|today|maps)/,\n  );\n  if (!match) {\n    return null;\n  }\n  return match[1];\n};\n\n/**\n * Sets up the various page views and custom events\n * that we want to record.\n * This function should be run after the RUM client is\n * successfully initialized, as it expects there to be a\n * global (window) function named 'cwr'\n */\nconst setupRecording = () => {\n  // Add event listeners for TabbedNavigator interactions.\n  // If we are using HTMX, we will also want to add listeners\n  // for when the tab content loads\n\n  // When a user switches to another tab\n  // in any TabbedNavigator\n  document.addEventListener(\"wx:tab-switched\", (event) => {\n    const rumEventData = {\n      path: window.location.pathname,\n      isPointPage: !!window.location.pathname.match(/\\/forecast\\/point/),\n      usingHTMX: isUsingHTMX(),\n      tabId: event.detail.tabId,\n    };\n    window.cwr(\"recordEvent\", { type: \"tabbed_nav_click\", data: rumEventData });\n  });\n\n  // When tab contents have loaded behind the scenes\n  // via HTMX-like functionality\n  document.addEventListener(\"wx:tab-content-loaded\", (event) => {\n    const rumEventData = {\n      path: window.location.pathname,\n      isPointPage: !!window.location.pathname.match(/\\/forecast\\/point/),\n      usingHTMX: isUsingHTMX(),\n      tabId: event.detail.tabId,\n    };\n    window.cwr(\"recordEvent\", {\n      type: \"tab_content_loaded\",\n      data: rumEventData,\n    });\n  });\n\n  // When there was an error loading tab contents in the background\n  // using HTMX like functionality\n  document.addEventListener(\"wx:tab-content-error\", (event) => {\n    const rumEventData = {\n      path: window.location.pathname,\n      isPointPage: !!window.location.pathname.match(/\\/forecast\\/point/),\n      usingHTMX: isUsingHTMX(),\n      tabId: event.detail.tabId,\n      errorCode: event.detail.status,\n    };\n    window.cwr(\"recordEvent\", {\n      type: \"tab_content_error\",\n      data: rumEventData,\n    });\n  });\n\n  const pathname = window.location.pathname;\n  const pageTags = [];\n\n  // Get the initial \"page name\" tag.\n  // This will be the type of page, ie\n  // 'forecast', 'county', 'state' or the literal\n  // url in all other cases\n  const pageTypeTag = pageGroups(pathname);\n  if (pageTypeTag) {\n    pageTags.push(pageTypeTag);\n  }\n\n  // Next, check to see if this is a point forecast page or\n  // not. If so, add the 'point-forecast' tag, as well as the\n  // specific tab page name tag for point forecasts\n  const pointForecastTabPageName = getPointForecastPageName(pathname);\n  if (pointForecastTabPageName) {\n    pageTags.push(\"point-forecast\", pointForecastTabPageName);\n  }\n\n  // If we are in 'HTMX' mode, lets add that as a tag\n  // as well\n  if (isUsingHTMX()) {\n    pageTags.push(\"using-htmx\");\n  }\n\n  // Finally, record the pageView\n  if (pageTags.length) {\n    window.cwr(\"recordPageView\", { pageId: pathname, pageTags });\n  } else {\n    window.cwr(\"recordPageView\", { pageId: pathname });\n  }\n};\n\n/**\n * Initialize the RUM client if there is a valid application id,\n * then set up the kinds of page views and custom events\n * we want to record.\n * Note that an invalid or missing application id will return early\n */\n(function () {\n  // If there is not a valid application id, immediately\n  // return to prevent initialization of RUM.\n  const APPLICATION_ID = getRUMApplicationId();\n  if (!APPLICATION_ID) {\n    return;\n  }\n  const APPLICATION_VERSION = \"1.0.0\";\n  const APPLICATION_REGION = \"us-east-1\";\n\n  // Initialize the RUM client on the window\n  createAwsRumClient(\n    \"cwr\",\n    APPLICATION_ID,\n    APPLICATION_VERSION,\n    APPLICATION_REGION,\n    \"https://client.rum.us-east-1.amazonaws.com/1.x/cwr.js\",\n    config,\n  );\n\n  // Set up the page views and custom events for recording\n  setupRecording();\n})();\n", "import Timer from \"./timer.js\";\n\n// Store a reference to the original fetch function\nwindow._fetch = window.fetch;\n\nconst replaceFetch = () => {\n  const banner = document.querySelector(\"#wx-offline-banner__container\");\n  const template = document.querySelector(\"#wx-offline-banner__template\");\n  const importantHosts = JSON.parse(\n    document.getElementById(\"third-party-site-list\").textContent,\n  );\n  importantHosts.push(window.location.host);\n  const maxDelay = 1800000; // 30 minutes\n\n  const debouncer = {\n    banner: new Timer(),\n    ariaLive: new Timer(),\n  };\n  const metronome = {\n    ping: new Timer(),\n  };\n\n  const hideOfflineBanner = () => {\n    try {\n      banner.innerHTML = \"\";\n      metronome.ping.stop();\n      const text = gettext(\"js.offline-banner.aria.you-are-back-online.01\");\n      window.dispatchEvent(\n        new CustomEvent(\"wx-announce\", { detail: { text } }),\n      );\n    } catch (_) {\n      /* do nothing */\n    }\n  };\n\n  const checkOffline = () => {\n    if (!navigator.onLine) {\n      metronome.ping.reset();\n    } else {\n      window._fetch\n        .apply(this, [\"/health/\"])\n        .then((_) => hideOfflineBanner())\n        .catch((_) => metronome.ping.reset());\n    }\n  };\n\n  const showOfflineBanner = () => {\n    try {\n      if (!banner.children.length) {\n        debouncer.ariaLive.start(() => {\n          banner.appendChild(template.content.cloneNode(true));\n          banner.scrollIntoView();\n        }, 1000);\n      }\n      metronome.ping.start(checkOffline);\n    } catch (_) {\n      /* do nothing */\n    }\n  };\n\n  const wait = (delay) => new Promise((resolve) => setTimeout(resolve, delay));\n\n  /**\n   * This is a wrapper around the original window.fetch, to provide\n   * automatic retry and offline banners.\n   *\n   * By default, it retries 10 times, but you can pass `wxMaxRetries`:\n   *\n   *     fetch(\"url\", {..}, {wxMaxRetries: 5})\n   *\n   * The original fetch is at window._fetch.\n   */\n  window.fetch = (resource, options = {}) => {\n    const maxRetries = options.wxMaxRetries || 10;\n    const tries = options.wxTries || 1;\n    let requestedHost;\n    try {\n      requestedHost = new URL(resource).host;\n    } catch (error) {\n      /* do nothing */\n    }\n\n    if (importantHosts.includes(requestedHost)) {\n      return window._fetch(resource, options).catch((error) => {\n        showOfflineBanner();\n        if (tries <= maxRetries) {\n          options.wxTries = tries + 1;\n          options.wxMaxRetries = maxRetries;\n          const array = new Uint32Array(1);\n          const rand = crypto.getRandomValues(array)[0];\n          const jitter = (rand % 100) + 1;\n          const delay = Math.min(500 * 2 ** tries + jitter, maxDelay);\n          return wait(delay).then(() => window.fetch(resource, options));\n        } else {\n          throw error;\n        }\n      });\n    } else {\n      return window._fetch(resource, options);\n    }\n  };\n};\n\nif (document.readyState === \"loading\") {\n  document.addEventListener(\"DOMContentLoaded\", replaceFetch, {\n    once: true,\n  });\n} else {\n  replaceFetch();\n}\n", "import Timer from \"./timer.js\";\n\nconst debouncer = new Timer();\n/**\n * Cache the text here to compare text between calls.\n *\n * This is needed because some screenreaders will not announce \"repeat\" messages.\n */\nlet text = \"\";\n\n/**\n * Adds a span of screenreader only text to\n * a page-wide aria-live region,\n * which is itself also hidden.\n * The update is on a 1 second delay, which is preferred\n * based on convos with USWDS.\n *\n * To use:\n *   const text = gettext(\"js.<keyFromDjangojs.po>.01\"));\n *   window.dispatchEvent(new CustomEvent(\"wx-announce\", { detail: { text }}));\n */\nconst updateAriaLive = (e) => {\n  const delay = Number.isFinite(e.detail?.delay) ? e.detail?.delay : 1000;\n  // check if this is a repeat message\n  if (text === e.detail?.text) {\n    // if so, append a non-breaking space\n    text += \"\\u00A0\";\n  } else {\n    // otherwise, use the new text\n    text = e.detail?.text;\n  }\n  debouncer.start(() => {\n    const span = document.createElement(\"span\");\n    span.innerText = text;\n    const liveRegion = document.querySelector(\"#sr-only\");\n    liveRegion.innerHTML = \"\";\n    liveRegion.append(span);\n  }, delay);\n};\n\nwindow.addEventListener(\"wx-announce\", updateAriaLive);\n", "/**\n * Generic WCAG Tabs component\n * ------------------------------------------\n * This is a progressively enhanced component.\n * tab, tablist, and tabpanel elements are expected\n * to have the correct `role` attributes and other\n * aria references.\n * See\n * https://www.w3.org/WAI/ARIA/apg/patterns/tabs/\n */\nclass Tabs extends HTMLElement {\n  constructor() {\n    super();\n\n    // Bound methods\n    this.handleTabClick = this.handleTabClick.bind(this);\n    this.handleKeyDown = this.handleKeyDown.bind(this);\n  }\n\n  connectedCallback() {\n    Array.from(this.querySelectorAll('[role=\"tab\"]')).forEach((tabElement) => {\n      tabElement.addEventListener(\"click\", this.handleTabClick);\n    });\n    this.addEventListener(\"keydown\", this.handleKeyDown);\n  }\n\n  disconnectedCallback() {\n    this.removeEventListener(\"keydown\", this.handleKeyDown);\n    Array.from(this.querySelectorAll('[role=\"tab\"]')).forEach((tabElement) => {\n      tabElement.removeEventListener(\"click\", this.handleTabClick);\n    });\n  }\n\n  /**\n   * The click handler should update the tab's\n   * aria-selected attribute, and also update the\n   * data-tabpanel-selected attribute on its corresponding\n   * tabpanel.\n   * Any hiding/showing of tabpanel content should be\n   * handled by implementor's CSS\n   */\n  handleTabClick(event) {\n    const tab = event.target.closest('[role=\"tab\"]');\n    const panelId = tab.getAttribute(\"aria-controls\");\n    const panel = document.getElementById(panelId);\n    if (panel) {\n      this.tabs.forEach((tabElement) => {\n        tabElement.setAttribute(\"aria-selected\", false);\n      });\n      tab.setAttribute(\"aria-selected\", true);\n      this.tabpanels.forEach((tabpanelElement) => {\n        tabpanelElement.setAttribute(\"data-tabpanel-selected\", false);\n      });\n      panel.setAttribute(\"data-tabpanel-selected\", true);\n      panel.setAttribute(\"aria-labelledby\", tab.id);\n      this.setAttribute(\"data-selected\", panelId);\n    }\n\n    window.dispatchEvent(new CustomEvent(\"wx-tab-focused\", { detail: tab }));\n  }\n\n  /**\n   * Binds key handling events as specified in\n   * the WCAG recommendations\n   */\n  handleKeyDown(event) {\n    const currentFocus = this.querySelector(\n      '[role=\"tab\"]:focus,[role=\"tab\"]:focus-within',\n    );\n    const firstItemInFocus = currentFocus.matches(\n      '[role=\"tab\"]:first-child:focus, [role=\"tab\"]:first-child:focus-within',\n    );\n    const lastItemInFocus = currentFocus.matches(\n      '[role=\"tab\"]:last-child:focus, [role=\"tab\"]:last-child:focus-within',\n    );\n    let handled = false;\n    if (event.key === \"ArrowLeft\") {\n      if (firstItemInFocus) {\n        this.focusTab(this.querySelector('[role=\"tab\"]:last-child'));\n      } else {\n        this.focusTab(currentFocus.previousElementSibling);\n      }\n      handled = true;\n    } else if (event.key === \"ArrowRight\") {\n      if (lastItemInFocus) {\n        this.focusTab(this.querySelector('[role=\"tab\"]:first-child'));\n      } else {\n        this.focusTab(currentFocus.nextElementSibling);\n      }\n      handled = true;\n    } else if (event.key === \"Space\" || event.key === \"Enter\") {\n      currentFocus.click();\n      handled = true;\n    } else if (event.key === \"Home\") {\n      this.focusTab(this.querySelector('[role=\"tab\"]:first-child'));\n      handled = true;\n    } else if (event.key === \"End\") {\n      this.focusTab(this.querySelector('[role=\"tab\"]:last-child'));\n      handled = true;\n    }\n\n    if (handled) {\n      event.stopPropagation();\n      event.preventDefault();\n    }\n  }\n\n  focusTab(anElement) {\n    // It is not required that the element with the role tab\n    // be a focusable element. In such cases, we need to\n    // check its children for elements that can receive focus.\n    // We do this in the simplest possible way, limiting ourselves\n    // to a, button, or any element with a tabindex\n    const matchString = \"a, button, [tabindex]\";\n    if (anElement.matches(matchString)) {\n      anElement.focus();\n    } else {\n      const childFocusElement = anElement.querySelector(matchString);\n      if (childFocusElement) {\n        childFocusElement.focus();\n      }\n    }\n  }\n\n  get tabs() {\n    return Array.from(this.querySelectorAll('[role=\"tab\"]'));\n  }\n\n  get tabpanels() {\n    return this.tabs.map((tabElement) => {\n      const panelId = tabElement.getAttribute(\"aria-controls\");\n      return document.getElementById(panelId);\n    });\n  }\n}\n\nif (!window.customElements.get(\"wx-tabs\")) {\n  window.customElements.define(\"wx-tabs\", Tabs);\n}\n", "/** True when a geometry has points on both sides of the antimeridian. */\nconst crossesAntimeridian = ({ coordinates }) => {\n  let east = false;\n  let west = false;\n\n  const walk = (coords) => {\n    if (typeof coords[0] === \"number\") {\n      east ||= coords[0] > 150;\n      west ||= coords[0] < -150;\n      return;\n    }\n    coords.forEach(walk);\n  };\n  walk(coordinates);\n\n  return east && west;\n};\n\n/** Move points east of the antimeridian west of -180 so the shape draws as one piece. */\nconst shiftAntimeridian = (geometry) => {\n  const wrapPoint = (coord) => {\n    let lng = coord[0];\n    if (lng > 0) lng -= 360; // Shift Aleutians to -180...-190 range\n    return [lng, coord[1]];\n  };\n\n  // Define the recursion to handle Polygon vs MultiPolygon coordinates\n  const transformCoords = (coords) => {\n    if (typeof coords[0] === \"number\") {\n      return wrapPoint(coords);\n    }\n    return coords.map(transformCoords);\n  };\n\n  if (geometry.coordinates) {\n    geometry.coordinates = transformCoords(geometry.coordinates);\n  }\n};\n\n/** Move the Aleutians west of -180 so Alaska draws as one piece. */\nexport const shiftAleutians = (boundary, alerts = []) => {\n  // Only a boundary straddling the antimeridian needs it, and its alerts ride along\n  if (!boundary?.coordinates || !crossesAntimeridian(boundary)) {\n    return;\n  }\n\n  // Process Boundary (it's a Geometry object)\n  shiftAntimeridian(boundary);\n\n  // Process Alerts\n  alerts.forEach((alert) => {\n    if (alert.geometry) {\n      shiftAntimeridian(alert.geometry);\n    }\n  });\n};\n\nconst ESRI_API_KEY =\n  \"AAPK1dd93729edc54e84ade1ea5dc0f4f9d3EPexfd5qirlO3QtHGBj5JQL7iUYHQOb4yLjfKEYFLcyN9PlMd87lMjjv8D3DxDsQ\";\n\n/** Hide the alert map and show the non-critical map error in its place. */\nexport const showMapError = (elementId) => {\n  document\n    .getElementById(\"wx-alert-map-error\")\n    .classList.remove(\"display-none\");\n  document\n    .getElementById(elementId)\n    .closest(\"wx-alert-map, wx-wfo-map\").style.display = \"none\";\n};\n\n/** Put a Leaflet map on the Esri streets basemap. */\nexport const createBaseMap = (elementId, options) => {\n  const L = window.L;\n  const map = L.map(elementId, options).setView([0, 0], 0);\n\n  // Leaflet is managed by a Ukrainian team. The default attribution they put on\n  // maps includes a Ukrainian flag to show their national pride. But as an\n  // official website of the US Government, that might not be appropriate for\n  // us, so we remove the flag.\n  map.attributionControl.setPrefix(\n    \"<a href='https://leafletjs.com' title='A JavaScript library for interactive maps'>Leaflet</a>\",\n  );\n\n  // Add Esri Basemap\n  L.esri.Vector.vectorBasemapLayer(\"arcgis/streets\", {\n    apiKey: ESRI_API_KEY,\n  }).addTo(map);\n\n  return map;\n};\n", "import { createBaseMap, shiftAleutians } from \"./map.js\";\n\nconst ICON_URLS = {\n  warning: \"/public/images/weather/wx_alerticon_circle_warning.svg\",\n  watch: \"/public/images/weather/wx_alerticon_circle_watch.svg\",\n  other: \"/public/images/weather/wx_alerticon_circle_other.svg\",\n};\n\nconst CLUSTER_PRIORITIES = [\"other\", \"watch\", \"warning\"];\n\nconst styles = {\n  outline: {\n    color: \"#11181D\",\n    weight: 3,\n    opacity: 1,\n    fillOpacity: 0,\n    dashArray: \"1 4\",\n    lineCap: \"round\",\n  },\n  warning: {\n    fillColor: \"#D83933\",\n    color: \"#FB5A47\",\n    opacity: 0.85,\n    fillOpacity: 0.3,\n  },\n  watch: {\n    fillColor: \"#D2B93B\",\n    color: \"#947100\",\n    opacity: 0.85,\n    fillOpacity: 0.3,\n  },\n  other: {\n    fillColor: \"#B4C1CD\",\n    color: \"#585E63\",\n    opacity: 0.85,\n    fillOpacity: 0.3,\n  },\n  active: {\n    fillOpacity: 0.5,\n  },\n  hover: {\n    fillOpacity: 0.7,\n    opacity: 1.0,\n    weight: 7,\n  },\n};\n\n/** Render an outline plus clustered, day-filtered alerts on the Esri basemap. */\nexport const createAlertMap = ({\n  elementId,\n  name,\n  maxZoom,\n  outline,\n  alerts,\n  autoPan,\n  onExpandToggle,\n}) => {\n  const L = window.L;\n  const polylabel = window.polylabel;\n  const layersByDay = { 1: [], 2: [], 3: [], 4: [], 5: [], all: [] };\n  let curDayIndex = \"all\";\n\n  const activeLayers = () => layersByDay[curDayIndex] ?? [];\n\n  shiftAleutians(outline, alerts);\n\n  const map = createBaseMap(elementId, {\n    zoomDelta: 1,\n    zoomSnap: 0.5,\n    maxZoom,\n  });\n\n  /** A custom expand/shrink button for the map container. */\n  const ExpandControl = L.Control.extend({\n    options: {\n      position: \"topright\",\n    },\n\n    onAdd: function (map) {\n      this.map = map;\n      this.container = map.getContainer().parentElement;\n      this.button = document.createElement(\"button\");\n      this.button.classList.add(\"wx-radar-expand\", \"padding-0\", \"margin-1\");\n      this.buttonSetToExpand();\n      this.button.addEventListener(\"click\", this._resize.bind(this));\n      return this.button;\n    },\n\n    buttonSetToExpand: function () {\n      this.button.innerHTML = `<svg role=\"img\" aria-hidden=\"true\" class=\"width-full height-full\"><use xlink:href=\"/public/images/uswds/sprite.svg#zoom_out_map\"></use></svg>`;\n      this.button.setAttribute(\"aria-label\", `Expand the ${name} alert map`);\n    },\n\n    buttonSetToCollapse: function () {\n      this.button.innerHTML = `<svg role=\"img\" aria-hidden=\"true\" class=\"width-full height-full\"><use xlink:href=\"/public/images/spritesheet.svg#wx_zoom-in-map\"></use></svg>`;\n      this.button.setAttribute(\"aria-label\", `Collapse the ${name} alert map`);\n    },\n\n    _resize: function () {\n      onExpandToggle(this.container);\n      this.button.classList.toggle(\"wx-map-control__expanded\");\n      if (this.button.classList.contains(\"wx-map-control__expanded\")) {\n        this.buttonSetToCollapse();\n      } else {\n        this.buttonSetToExpand();\n      }\n\n      // Critical for Leaflet to recalculate the canvas size\n      this.map.invalidateSize();\n    },\n\n    onRemove: function () {\n      // noop\n    },\n  });\n  new ExpandControl().addTo(map);\n\n  // Styles and icons\n  const MapIcon = L.Icon.extend({\n    options: {\n      iconSize: [32, 32],\n      iconAnchor: [16, 16],\n      popupAnchor: [0, -8],\n    },\n  });\n\n  const icons = {\n    warning: new MapIcon({ iconUrl: ICON_URLS.warning }),\n    watch: new MapIcon({ iconUrl: ICON_URLS.watch }),\n    other: new MapIcon({ iconUrl: ICON_URLS.other }),\n  };\n\n  const getLargeIcon = (type) =>\n    new MapIcon({\n      iconUrl: ICON_URLS[type],\n      iconSize: [40, 40],\n      iconAnchor: [20, 20],\n      popupAnchor: [0, -10],\n    });\n\n  /** Convert a map's bounds in lat/lng to x/y. */\n  const getXYBounds = () => {\n    const latlngBounds = map.getBounds();\n    const southeast = latlngBounds.getSouthEast();\n    const northwest = latlngBounds.getNorthWest();\n    return L.bounds(\n      [northwest.lat, northwest.lng],\n      [southeast.lat, southeast.lng],\n    );\n  };\n\n  /** Determine the center of a layer, considering only points within the viewport. */\n  const visibleCenter = (layer, xybounds) => {\n    const { geometry } = layer.getLayers()[0].feature;\n\n    // If it's a Polygon, we wrap it in an array to treat it like a MultiPolygon with one item\n    const polygonList =\n      geometry.type === \"MultiPolygon\"\n        ? geometry.coordinates\n        : [geometry.coordinates];\n\n    // Loop through list of polygons\n    // When finding the center, return center\n    for (const polygonCoords of polygonList) {\n      // Get Center of polygon using polylabel (center of mass)\n      const [lng, lat] = polylabel(polygonCoords, 0.000001);\n      const labelCenter = L.latLng(lat, lng);\n\n      // If the natural center of this polygon is visible, return\n      if (map.getBounds().contains(labelCenter)) {\n        return labelCenter;\n      }\n\n      // If natural center isn't visible, the polygon might still be partially on screen\n      const points = polygonCoords[0].map(([lng, lat]) => L.point([lat, lng]));\n\n      // Clip polygon within viewport (`xybounds`)\n      const clippedPoints = L.PolyUtil.clipPolygon(points, xybounds);\n\n      if (clippedPoints.length > 0) {\n        // Convert clipped xy points back to LatLngs for polygonCenter\n        const clippedLatLngs = clippedPoints.map((p) => L.latLng([p.x, p.y]));\n        try {\n          return L.PolyUtil.polygonCenter(clippedLatLngs, map.options.crs);\n        } catch {\n          // Fallback if polygonCenter fails on weird clipped shapes\n        }\n      }\n    }\n\n    // If no part of any polygon is within the viewport\n    return null;\n  };\n\n  /** Change the opacity of the selected alert. */\n  const handleMarkerEvent = (e, layer) => {\n    switch (e.type) {\n      case \"click\":\n        layer.setStyle(styles.active);\n        break;\n      case \"popupclose\":\n      case \"mouseout\":\n        layer.resetStyle();\n        break;\n      case \"mouseover\":\n        layer.setStyle(styles.hover);\n        break;\n      default:\n        break;\n    }\n  };\n\n  /** Marker Clusters for alert Icons **/\n  const markers = L.markerClusterGroup({\n    showCoverageOnHover: false,\n\n    // Cluster marker Icon rendering function, icon defaults to highest alert clustered\n    iconCreateFunction: (cluster) => {\n      const highest = Math.max(\n        ...cluster\n          .getAllChildMarkers()\n          .map((marker) => CLUSTER_PRIORITIES.indexOf(marker.alert_type)),\n      );\n      const type = CLUSTER_PRIORITIES[highest] ?? \"other\";\n      const count = cluster.getChildCount();\n\n      return L.divIcon({\n        html: `\n          <div class=\"alert-cluster-badge-container\" title=\"${count} ${type} alerts\">\n            <img src=\"${ICON_URLS[type]}\" class=\"alert-cluster-main-icon\" alt=\"\" />\n            <div class=\"alert-cluster-badge alert-badge-${type}\" aria-hidden=\"true\">\n              ${count}\n            </div>\n          </div>\n        `,\n        className: \"leaflet-cluster-icon\",\n        iconSize: [40, 40],\n        iconAnchor: [20, 20],\n      });\n    },\n  });\n\n  /** Marker Cluster event functions  **/\n  markers.on(\"spiderfied\", (e) => {\n    if (e.cluster._icon) {\n      // When cluster is spiderfied, it needs to be invisible\n      e.cluster._icon.style.opacity = \"0\";\n      e.cluster._icon.style.pointerEvents = \"none\";\n    }\n  });\n\n  markers.on(\"unspiderfied\", (e) => {\n    if (e.cluster._icon) {\n      // When cluster is unspiderfied, it needs to be visible\n      e.cluster._icon.style.opacity = \"1\";\n      e.cluster._icon.style.pointerEvents = \"auto\";\n    }\n  });\n\n  // zoom to the outline (but do not draw it yet)\n  const outlineLayer = L.geoJSON(outline, { style: styles.outline });\n  map.fitBounds(outlineLayer.getBounds(), { padding: [15, 15] });\n  const outlineXYBounds = getXYBounds();\n  const outlineZoom = map.getZoom();\n  let latestZoom = outlineZoom;\n\n  /** Restacks all active alert polygons reversed, based on their initial render index. */\n  const restackAlerts = () => {\n    [...activeLayers()]\n      .sort((a, b) => b.wx_render_index - a.wx_render_index)\n      .forEach((layer) => {\n        if (map.hasLayer(layer)) {\n          layer.bringToFront();\n        }\n      });\n\n    // Bring the outline to the front at the end\n    outlineLayer.bringToFront();\n  };\n\n  /** Redraw icons on zoom in or pan; reset them on zoom out. */\n  const handleMotion = (e) => {\n    // Reset style when moved\n    activeLayers().forEach((layer) => layer.resetStyle());\n\n    const zoom = e.target.getZoom();\n    if (zoom <= outlineZoom && latestZoom > outlineZoom) {\n      activeLayers().forEach((layer) => {\n        layer.wx_marker.setLatLng(layer.wx_marker.wx_orig_pos);\n      });\n    } else {\n      const xybounds = getXYBounds();\n      activeLayers().forEach((layer) => {\n        // Fix visible center can be null if the polygon isn't in viewport. if null, skip\n        const center = visibleCenter(layer, xybounds);\n        if (center) {\n          layer.wx_marker.setLatLng(center);\n        }\n      });\n    }\n    latestZoom = zoom;\n\n    // Only refresh if marker cluster is full\n    if (markers.getLayers().length > 0) {\n      try {\n        markers.refreshClusters();\n      } catch (err) {\n        console.warn(\"MarkerCluster refresh suppressed during motion:\", err);\n      }\n    }\n  };\n\n  map.on(\"zoomend\", handleMotion);\n  map.on(\"moveend\", handleMotion);\n\n  /** Show alerts for the selected day or for \"all\". */\n  const filterMap = () => {\n    // If we aren't viewing \"all\", hide the \"all\" layers first\n    if (curDayIndex !== \"all\") {\n      layersByDay.all.forEach((layer) => {\n        layer.setStyle({ fillOpacity: 0, opacity: 0 });\n        layer.wx_marker.remove();\n      });\n    }\n\n    // Remove existing markers\n    markers.clearLayers();\n    activeLayers().forEach((layer) => {\n      layer.resetStyle();\n      markers.addLayer(layer.wx_marker);\n    });\n\n    if (markers.getLayers().length > 0) {\n      markers.refreshClusters();\n    }\n  };\n\n  // Empty map { alertId: layer } for hovering over alert accordian\n  const alertIdToLayer = {};\n\n  // Highlight function for mouseover events\n  const highlightAlert = (alertId) => {\n    const layer = alertIdToLayer[alertId];\n    if (!layer) return;\n\n    const marker = layer.wx_marker;\n\n    // Update Marker icon and z-index\n    marker.setIcon(getLargeIcon(marker.alert_type));\n    marker._icon?.classList.add(\"alert-marker-mouseover\");\n    marker.setZIndexOffset(100000);\n    layer.bringToFront();\n\n    // Set hover style\n    layer.setStyle(styles.hover);\n  };\n\n  // Highlight function for mouseout events\n  const unhighlightAlert = (alertId) => {\n    const layer = alertIdToLayer[alertId];\n    if (!layer) return;\n\n    const marker = layer.wx_marker;\n\n    // Reset Marker\n    marker.setIcon(icons[marker.alert_type]);\n    marker._icon?.classList.remove(\"alert-marker-mouseover\");\n    marker.setZIndexOffset(0);\n\n    // Reset Visual Style\n    layer.resetStyle();\n\n    // Place layer back in it's original order\n    restackAlerts();\n  };\n\n  // List for storing alert labels\n  const markerList = [];\n\n  // create alert layers and sort them\n  for (let i = alerts.length - 1; i >= 0; i--) {\n    const { id, type, geometry, days, popup } = alerts[i];\n    if (!geometry) continue;\n\n    try {\n      const layer = L.geoJSON(geometry, { style: styles[type] }).addTo(map);\n      const center = visibleCenter(layer, outlineXYBounds);\n\n      // Store the render index for sorting during highlight events\n      layer.wx_render_index = i;\n\n      layer.wx_marker = L.marker(center, { icon: icons[type] });\n      layer.wx_marker.alert_type = type;\n      layer.wx_marker.wx_orig_pos = center;\n      layer.wx_marker.bindPopup(popup, { autoPan });\n      layer.wx_marker.on(\"click\", (e) => handleMarkerEvent(e, layer));\n      layer.wx_marker.on(\"popupclose\", (e) => handleMarkerEvent(e, layer));\n      layer.wx_marker.on(\"mouseover\", () => highlightAlert(id));\n      layer.wx_marker.on(\"mouseout\", () => unhighlightAlert(id));\n\n      alertIdToLayer[id] = layer;\n\n      // Add marker to list\n      markerList.push(layer.wx_marker);\n\n      days.forEach((day) => layersByDay[day]?.push(layer));\n      layersByDay.all.push(layer);\n    } catch (error) {\n      console.error(`Could not draw alert ${id}`, error);\n    }\n  }\n\n  // Add cluster markers\n  markers.addLayers(markerList);\n  map.addLayer(markers);\n\n  // day selection starts on \"all\", but the user might have changed it\n  const selected = document.querySelector(\n    \"wx-tabs button[aria-selected='true']\",\n  );\n  curDayIndex = selected?.dataset.alertDay ?? \"all\";\n\n  outlineLayer.addTo(map);\n  filterMap();\n\n  // ready to handle day change events, other wx-tabs on the page don't carry an alert day\n  window.addEventListener(\"wx-tab-focused\", (e) => {\n    const day = e.detail.dataset.alertDay;\n    if (day) {\n      curDayIndex = day;\n      filterMap();\n    }\n  });\n\n  return { map, highlightAlert, unhighlightAlert };\n};\n", "/** Fetch a Geobuf endpoint as an arraybuffer, rejecting on a non-2xx response. */\nexport const fetchGeobuf = (url) =>\n  fetch(url).then((res) => {\n    if (!res.ok) {\n      throw new Error(`${url} responded with ${res.status}`);\n    }\n    return res.arrayBuffer();\n  });\n\n/** Decode a Geobuf arraybuffer back into GeoJSON. */\nexport const decodeGeobuf = (buffer) => {\n  const geojson = window.geobuf.decode(new window.Pbf(buffer));\n  // An empty FeatureCollection encodes without a feature_collection field and decodes to {}\n  return geojson.type ? geojson : { type: \"FeatureCollection\", features: [] };\n};\n", "export const checkForLeaflet = (callback) => {\n  if (window.L && window.L.esri && window.L.esri.Vector) {\n    callback();\n  } else {\n    // DOMContentLoaded fires after every deferred script, the Leaflet plugins and geobuf included\n    document.addEventListener(\"DOMContentLoaded\", callback, { once: true });\n  }\n};\n", "import { createAlertMap } from \"./alertMap.js\";\nimport { decodeGeobuf, fetchGeobuf } from \"./geobuf.js\";\nimport { showMapError } from \"./map.js\";\nimport { checkForLeaflet } from \"./util.js\";\n\n/**\n * stateAlertMap.js\n * Logic for fetching state boundaries and alerts via Geobuf endpoints.\n */\n\nconst MAP_ID = \"wx-state-alert-map\";\n\n// Get Metadata from the script tag we added to alerts.html\nconst meta = JSON.parse(document.getElementById(\"state-metadata\").textContent);\n\n// Kick off at module load so the fetches overlap the Leaflet script load\nconst geobufRequests = Promise.all([\n  fetchGeobuf(`/wx/state/${meta.stateCode}/`),\n  fetchGeobuf(`/wx/state/${meta.stateCode}/alerts`),\n]);\n\n/** HTML shown inside a popup when clicking on an alert icon on the map. */\nconst getPopupHTML = (eventSlug, eventName, countiesCount) => {\n  const { trans } = meta;\n  const container = document.createElement(\"div\");\n  container.classList.add(\"text-center\");\n\n  const label =\n    countiesCount === 1\n      ? trans.subdivision_name\n      : trans.subdivision_name_plural;\n\n  const buttonText = trans.see_list_pattern.replace(\n    \"{subdivision}\",\n    trans.subdivision_name_plural,\n  );\n\n  container.innerHTML = `\n    <div class=\"font-body-xs margin-bottom-2px text-bold text-primary-darkest\">\n      ${gettext(eventName)}\n    </div>\n    <div class=\"font-body-xs margin-bottom-2px text-base-dark\">\n      ${countiesCount} ${label}\n    </div>\n    <div>\n      <button class=\"usa-button usa-button--unstyled font-body-xs usa-link\" type=\"button\">\n        ${buttonText}\n      </button>\n    </div>\n  `;\n\n  const btn = container.querySelector(\"button\");\n  btn.addEventListener(\"click\", () => {\n    const targetId = `id-${eventSlug}`;\n    const element = document.getElementById(targetId);\n\n    if (element) {\n      element.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n      element.focus({ preventScroll: true });\n    }\n  });\n\n  return container;\n};\n\nconst setupStateMap = async () => {\n  const loader = document.getElementById(\"wx_map_loader\");\n\n  // Fetch Data from internal endpoints\n  try {\n    // Wait for GIS layers\n    const [boundaryBuf, alertsBuf] = await geobufRequests;\n    const boundary = decodeGeobuf(boundaryBuf);\n    const alerts = decodeGeobuf(alertsBuf);\n\n    createAlertMap({\n      elementId: MAP_ID,\n      name: \"state\",\n      maxZoom: 15,\n      outline: boundary,\n      autoPan: true,\n      onExpandToggle: (container) => {\n        container.classList.toggle(\"wx-state-alert-map-container__expanded\");\n      },\n      // Extract metadata from the decoded FeatureCollection\n      alerts: alerts.features.map(({ geometry, properties }) => ({\n        id: properties.hash,\n        type: properties.metadata.level.text || \"other\",\n        geometry,\n        days: properties.alertDays || [],\n        popup: getPopupHTML(\n          properties.event.toLowerCase().replace(/\\s+/g, \"-\"),\n          properties.event,\n          properties.total_counties_display || 0,\n        ),\n      })),\n    });\n\n    // un-hide the day tabs now that everything is loaded\n    document.getElementById(\"state-alerts\").classList.remove(\"display-none\");\n\n    if (loader) {\n      loader.classList.add(\"hidden\");\n      setTimeout(() => {\n        loader.style.display = \"none\";\n      }, 400);\n    }\n  } catch (err) {\n    console.error(\"Error loading or decoding state map data:\", err);\n\n    // Show error message to user and hide the map container\n    showMapError(MAP_ID);\n  }\n};\n\ncheckForLeaflet(setupStateMap);\n", "/**\n * Component to handle merging and filtering state alerts by event type.\n * This class processes raw alert data from the backend, groups it by event name,\n * and renders it into the DOM using HTML templates to maintain a clean separation\n * between logic and presentation.\n */\nexport default class StateAlertsHandler {\n  constructor() {\n    // Retrieve the data bridges provided by the Django template\n    const dataElem = document.getElementById(\"alerts-data\");\n    const metaElem = document.getElementById(\"state-metadata\");\n\n    // Guard clause: if data is missing, don't initialize\n    if (!dataElem || !metaElem) return;\n\n    // Parse the JSON data provided by the backend\n    this.rawAlerts = JSON.parse(dataElem.textContent);\n    this.meta = JSON.parse(metaElem.textContent);\n\n    // Cache DOM references for performance\n    this.stateAlertContainer = document.getElementById(\n      \"state-alerts-container\",\n    );\n    this.template = document.getElementById(\"state-alert-template\");\n    this.allTabs = document.querySelectorAll(\"button[data-alert-day]\");\n\n    this.init();\n  }\n\n  /**\n   * Initializes the component by rendering the default view (\"all\")\n   * and setting up event listeners for the day-filtering tabs.\n   */\n  init() {\n    // Initial render: show all active alerts\n    this.render(\"all\");\n\n    // Set up click listeners for the segmented tab control\n    this.allTabs.forEach((btn) => {\n      btn.addEventListener(\"click\", (e) => {\n        const day = e.currentTarget.getAttribute(\"data-alert-day\");\n        this.syncTabs(day); // Visual update for the buttons\n        this.render(day); // Logic update for the content\n      });\n    });\n  }\n\n  /**\n   * Updates the ARIA state of the tab buttons to reflect the current selection.\n   * @param {string} selectedDay - The numeric day index or \"all\".\n   */\n  syncTabs(selectedDay) {\n    this.allTabs.forEach((btn) => {\n      const isMatch = btn.getAttribute(\"data-alert-day\") === selectedDay;\n      btn.setAttribute(\"aria-selected\", isMatch ? \"true\" : \"false\");\n    });\n  }\n\n  /**\n   * Filters and groups alerts, then draws them into the container.\n   * @param {string} selectedDay - The numeric day index or \"all\".\n   */\n  render(selectedDay) {\n    /**\n     * Filter and Group\n     * Multiple backend alerts might share the same \"event\" (\"Flood Warning\").\n     * We merge them so we can show one \"Flood Warning\" block with a combined list of counties.\n     */\n    const grouped = this.rawAlerts.reduce((acc, alert) => {\n      // Check if the alert is active for the day the user selected\n      const isDayMatch =\n        selectedDay === \"all\" ||\n        alert.alertDays.some((d) => String(d) === String(selectedDay));\n\n      if (isDayMatch) {\n        const eventName = alert.event;\n        // Initialize the group if it doesn't exist\n        if (!acc[eventName]) {\n          acc[eventName] = {\n            name: eventName,\n            level: alert.metadata.level.text,\n            counties: new Map(), // Use a Map to ensure unique FIPS entries\n          };\n        }\n        // Merge counties into the unique Map\n        Object.entries(alert.counties_dict).forEach(([fips, name]) => {\n          acc[eventName].counties.set(fips, name);\n        });\n      }\n      return acc;\n    }, {});\n\n    // Clear existing content before re-rendering\n    this.stateAlertContainer.innerHTML = \"\";\n    const groups = Object.values(grouped);\n\n    // Handle \"No Alerts\" state\n    if (groups.length === 0) {\n      this.stateAlertContainer.innerHTML = `<div class=\"no-alerts-msg margin-top-2\">${this.meta.trans.none}</div>`;\n      return;\n    }\n\n    // Access the nested sub-template for individual county links\n    const countyTemplate = this.template.content.getElementById(\n      \"county-link-template\",\n    );\n\n    /**\n     * Render Each Group\n     */\n    groups.forEach((group, index) => {\n      // Clone the main alert box template\n      const clone = this.template.content.cloneNode(true);\n      const alertBox = clone.querySelector(\".wx-state-alert\");\n\n      const iconUse = alertBox.querySelector(\".js-alert-icon-use\");\n      const currentHref =\n        iconUse.getAttribute(\"href\") || iconUse.getAttribute(\"xlink:href\");\n      if (currentHref) {\n        const basePath = currentHref.split(\"#\")[0];\n        iconUse.setAttribute(\"href\", `${basePath}#warning`);\n        iconUse.setAttribute(\"xlink:href\", `${basePath}#warning`);\n      }\n\n      // Apply dynamic attributes and IDs for linking from the map\n      const eventId = `id-${slugify(group.name)}`;\n      alertBox.id = eventId;\n      alertBox.setAttribute(\"data-alert-level\", group.level.toLowerCase());\n\n      // Set the title (\"flood warning\")\n      alertBox.querySelector(\".js-event-name\").textContent =\n        group.name.toLowerCase();\n\n      // Convert Map back to an array and sort alphabetically by county name\n      const entries = Array.from(group.counties.entries()).sort((a, b) => {\n        return a[1].localeCompare(b[1], undefined, { sensitivity: \"base\" });\n      });\n\n      // Construct the \"X of Y Counties\" localized string\n      const pattern = this.meta.trans.count_pattern;\n      const displayStr = pattern\n        .replace(\"{count}\", entries.length)\n        .replace(\"{total}\", this.meta.totalCounties)\n        .replace(\"{subdivision}\", this.meta.trans.subdivision_name_plural);\n\n      alertBox.querySelector(\".js-count-display\").textContent = displayStr;\n\n      const list = alertBox.querySelector(\".js-county-list\");\n\n      // Dynamic Grid Logic: adjust columns based on the density of the county list\n      if (entries.length > 8) list.classList.add(\"county-columns\");\n\n      if (entries.length > 24)\n        list.classList.add(\n          \"desktop__county-column-4\",\n          \"tablet__county-column-3\",\n        );\n      else if (entries.length > 16)\n        list.classList.add(\"tablet__county-column-3\");\n      else if (entries.length > 8)\n        list.classList.add(\"tablet__county-column-2\");\n\n      const toggleBtn = alertBox.querySelector(\".js-list-toggle\");\n      const collapsibleContainer = alertBox.querySelector(\n        \".js-collapsible-container\",\n      );\n      const toggleText = alertBox.querySelector(\".js-toggle-text\");\n      const toggleIcon = alertBox.querySelector(\".js-toggle-icon\");\n\n      const collapseCountyLimit = 32;\n\n      if (entries.length > collapseCountyLimit) {\n        toggleBtn.classList.remove(\"display-none\");\n        collapsibleContainer.classList.add(\"display-none\");\n\n        // Translations `Expand {pluralSubdivision}`\n        const pluralSubdivision = this.meta.trans.subdivision_name_plural;\n        const expandLabel = this.meta.trans.expand_pattern.replace(\n          \"{subdivision}\",\n          pluralSubdivision,\n        );\n        const collapseLabel = this.meta.trans.collapse_pattern.replace(\n          \"{subdivision}\",\n          pluralSubdivision,\n        );\n        toggleText.textContent = expandLabel;\n\n        // Collapse/Expand Event logic\n        toggleBtn.addEventListener(\"click\", () => {\n          const isExpanded = toggleBtn.getAttribute(\"aria-expanded\") === \"true\";\n          const newState = !isExpanded;\n\n          toggleBtn.setAttribute(\"aria-expanded\", newState);\n          collapsibleContainer.classList.toggle(\"display-none\", isExpanded);\n\n          alertBox.classList.toggle(\"is-expanded\", newState);\n\n          toggleText.textContent = newState ? collapseLabel : expandLabel;\n\n          const iconName = newState ? \"remove_circle\" : \"add_circle\";\n          const currentHref =\n            toggleIcon.getAttribute(\"href\") ||\n            toggleIcon.getAttribute(\"xlink:href\");\n          const basePath = currentHref.split(\"#\")[0];\n\n          toggleIcon.setAttribute(\"href\", `${basePath}#${iconName}`);\n          toggleIcon.setAttribute(\"xlink:href\", `${basePath}#${iconName}`);\n        });\n      }\n\n      /**\n       * Populate County Links\n       * For every county in the group, we clone the sub-template and fill it.\n       */\n      entries.forEach(([fips, name]) => {\n        const liClone = countyTemplate.content.cloneNode(true);\n        const link = liClone.querySelector(\".js-county-link\");\n\n        // Populate link data slots\n        link.href = `/forecast/county/${fips}/`;\n        liClone.querySelector(\".js-county-name\").textContent = name;\n        liClone.querySelector(\".js-subdivision-label\").textContent =\n          ` ${this.meta.trans.subdivision_name}`;\n        liClone.querySelector(\".js-state-code\").textContent =\n          this.meta.stateCode;\n\n        // Append the item to the group's <ul>\n        list.appendChild(liClone);\n      });\n\n      // Add the fully populated alert block to the page\n      this.stateAlertContainer.appendChild(clone);\n    });\n  }\n}\n\n/**\n * Slugification helper.\n * Converts \"Special Weather Statement\" to \"special-weather-statement\".\n */\nconst slugify = (text) => text.toLowerCase().replace(/[\\s\\W|_]+/g, \"-\");\n\nnew StateAlertsHandler();\n"],
  "mappings": "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",
  "names": ["Timer", "callback", "delay", "TabbedNavigator", "pointTablist", "tab", "alertAnchor", "button", "tablist", "maxScroll", "hash", "matchedTabButton", "childElement", "tabContainer", "tabId", "element", "tabButton", "event", "currentPath", "matchingTab", "anchorEl", "accordionEl", "accordionElement", "on", "content", "currentElement", "isFirst", "isLast", "accordionTop", "buttonAreaHeight", "scrollY", "setupSiteSearchMenuButton", "siteSubmenuElement", "button", "siteSearchSubmenu", "mobileButton", "tabletButton", "footerRegion", "prefersReducedMotion", "scrollBracket", "bottomY", "hideThreshold", "minScrollThreshold", "hideThreshold", "minScrollThreshold", "scrollBracket", "bottomY", "mobileButton", "tabletButton", "scrollUp", "prefersReducedMotion", "Listbox", "e", "selected", "first", "event", "closestOption", "handler", "host", "option", "idx", "element", "fireEvent", "selectedEl", "current", "options", "currentIndex", "prev", "firstOption", "lastOption", "next", "navigateToElement", "combobox", "popup", "selected", "targetUrl", "sections", "navLinks", "observerOptions", "observerCallback", "entries", "entry", "id", "link", "activeLink", "observer", "section", "hideNavigationLoader", "loader", "showNavigationLoader", "event", "loaders", "activeNav", "text", "goToLocationPage", "latitude", "longitude", "form", "removeBrowserLocationButtons", "buttons", "button", "sibling", "shouldPrompt", "status", "buttonHandler", "e", "proceed", "text", "lat", "long", "code", "message", "alertText", "comboTemplate", "Combobox", "target", "event", "name", "assigned", "value", "id", "element", "popupIsOpen", "handler", "clearButton", "oldVal", "newVal", "RECENT_LOC_STORAGE", "getRecentLocations", "existing", "parsed", "url", "updated", "rest", "addRecentLocation", "obj", "sliced", "debouncer", "Timer", "getRedirectUrlFromAddressCandidate", "addressCandidate", "type", "lat", "lon", "abbr", "typeLowercase", "makeListItemFromResultItem", "setSize", "describedby", "suggestion", "idx", "item", "makeListFromResult", "resultListElement", "ariaDescEl", "suggestions", "newItems", "LocationListbox", "Listbox", "addRecentLocation", "element", "selectItemPromise", "resolve", "form", "geoData", "formUrl", "event", "key", "filterTerm", "savedSearchesGroup", "savedSearchesLabel", "saved", "getRecentLocations", "match", "option", "text", "response", "numResults", "translation", "transWithCount", "data", "headerElement", "magicKey", "result", "cached", "url", "results", "firstCandidate", "x", "y", "SAVED_LOC_STORAGE", "TAB_REGEX", "normalizeLocationUrl", "url", "normalizeSavedLocationStorage", "storage", "text", "location", "getParsedSavedLocationStorage", "SAVED_LOC_STORAGE", "parsedStorage", "setSavedLocationStorage", "newStorage", "getSavedLocations", "current", "addSavedLocation", "obj", "textLower", "existing", "getParsedSavedLocationStorage", "hashed", "sorted", "largerElemIndex", "item", "setSavedLocationStorage", "removeSavedLocation", "loc", "locLower", "existingSorted", "existingHashed", "existingElemIdx", "SavedLocationsSection", "currentLocations", "getSavedLocations", "str", "locations", "listUl", "listColumnClass", "newElems", "index", "text", "url", "element", "cleanedText", "templateLi", "clonedLi", "liButton", "liAnchor", "anchorId", "itemLength", "columnBase", "classRange", "columnPostfix", "btn", "e", "currentTarget", "currentLoc", "currentUrl", "removeSavedLocation", "addSavedLocation", "addLocation", "buttonId", "currentSavedLocations", "currentList", "currentListUl", "currentLocationIndex", "loc", "currentColumnClass", "newColumnClass", "currentLocationItem", "newListItem", "detail", "removeLocation", "getRUMApplicationId", "tag", "config", "createAwsRumClient", "name", "id", "version", "region", "scriptSrc", "p", "scriptTag", "pageGroups", "path", "match", "what", "isUsingHTMX", "getPointForecastPageName", "setupRecording", "event", "rumEventData", "pathname", "pageTags", "pageTypeTag", "pointForecastTabPageName", "APPLICATION_ID", "replaceFetch", "banner", "template", "importantHosts", "maxDelay", "debouncer", "Timer", "metronome", "hideOfflineBanner", "text", "checkOffline", "_", "showOfflineBanner", "wait", "delay", "resolve", "resource", "options", "maxRetries", "tries", "requestedHost", "error", "array", "jitter", "debouncer", "Timer", "text", "updateAriaLive", "e", "delay", "span", "liveRegion", "Tabs", "tabElement", "event", "tab", "panelId", "panel", "tabpanelElement", "currentFocus", "firstItemInFocus", "lastItemInFocus", "handled", "anElement", "matchString", "childFocusElement", "crossesAntimeridian", "coordinates", "east", "west", "walk", "coords", "shiftAntimeridian", "geometry", "wrapPoint", "coord", "lng", "transformCoords", "shiftAleutians", "boundary", "alerts", "alert", "ESRI_API_KEY", "showMapError", "elementId", "createBaseMap", "options", "L", "map", "ICON_URLS", "CLUSTER_PRIORITIES", "styles", "createAlertMap", "elementId", "name", "maxZoom", "outline", "alerts", "autoPan", "onExpandToggle", "L", "polylabel", "layersByDay", "curDayIndex", "activeLayers", "shiftAleutians", "map", "createBaseMap", "ExpandControl", "MapIcon", "icons", "getLargeIcon", "type", "getXYBounds", "latlngBounds", "southeast", "northwest", "visibleCenter", "layer", "xybounds", "geometry", "polygonList", "polygonCoords", "lng", "lat", "labelCenter", "points", "clippedPoints", "clippedLatLngs", "p", "handleMarkerEvent", "e", "markers", "cluster", "highest", "marker", "count", "outlineLayer", "outlineXYBounds", "outlineZoom", "latestZoom", "restackAlerts", "a", "b", "handleMotion", "zoom", "center", "err", "filterMap", "alertIdToLayer", "highlightAlert", "alertId", "unhighlightAlert", "markerList", "i", "id", "days", "popup", "day", "error", "fetchGeobuf", "url", "res", "decodeGeobuf", "buffer", "geojson", "checkForLeaflet", "callback", "MAP_ID", "meta", "geobufRequests", "fetchGeobuf", "getPopupHTML", "eventSlug", "eventName", "countiesCount", "trans", "container", "label", "buttonText", "targetId", "element", "setupStateMap", "loader", "boundaryBuf", "alertsBuf", "boundary", "decodeGeobuf", "alerts", "createAlertMap", "geometry", "properties", "err", "showMapError", "checkForLeaflet", "StateAlertsHandler", "dataElem", "metaElem", "btn", "day", "selectedDay", "isMatch", "grouped", "acc", "alert", "d", "eventName", "fips", "name", "groups", "countyTemplate", "group", "index", "clone", "alertBox", "iconUse", "currentHref", "basePath", "eventId", "slugify", "entries", "a", "b", "displayStr", "list", "toggleBtn", "collapsibleContainer", "toggleText", "toggleIcon", "pluralSubdivision", "expandLabel", "collapseLabel", "isExpanded", "newState", "iconName", "liClone", "link", "text"]
}
