{
  "version": 3,
  "sources": ["/cdn/shop/t/26/assets/tdhq-page.js?b=20261014a"],
  "sourcesContent": ["/* ============================================================\n   TDHQ page sections behaviour \u2014 tdhq-page.js\n\n   Only two jobs: conditional contact-form fields, and moving focus to\n   the form's confirmation or error message after a submit.\n\n   Everything else in the page library is CSS and semantic HTML on\n   purpose \u2014 the FAQ accordion is <details>, the steps are an <ol>, the\n   cards are <a> elements. Nothing here is required to use a page.\n   ============================================================ */\n(function () {\n  'use strict';\n\n  if (window.__tdhqPageLoaded) return;\n  window.__tdhqPageLoaded = true;\n\n  /* ---------------------------------------------------------\n     CONDITIONAL CONTACT FIELDS\n     --------------------------------------------------------- */\n  function wireConditionalFields(scope) {\n    // Scoped rather than document-wide: Product Advice and Apply for Trade can\n    // both appear as forms on one page, and a global lookup would let the first\n    // form's controller drive the second form's fields.\n    var select = scope.querySelector('[data-tdhq-enquiry-type], [data-tdhq-controller]');\n    var groups = scope.querySelectorAll('[data-tdhq-when]');\n    var conditionallyRequired = scope.querySelectorAll('[data-tdhq-required-when]');\n    if (!select || (!groups.length && !conditionallyRequired.length)) return;\n\n    function apply() {\n      var value = controlValue(select);\n      Array.prototype.forEach.call(groups, function (group) {\n        var matches = group.getAttribute('data-tdhq-when').split(',').map(function (s) {\n          return s.trim();\n        });\n        var show = matches.indexOf(value) !== -1;\n        group.hidden = !show;\n\n        // A hidden field must never be submitted or block validation. Clearing\n        // the value also stops stale answers from a previously-selected enquiry\n        // type reaching the inbox and confusing whoever reads it.\n        Array.prototype.forEach.call(group.querySelectorAll('input, select, textarea'), function (field) {\n          field.disabled = !show;\n          if (!show) {\n            if (field.tagName === 'SELECT') { field.selectedIndex = 0; }\n            else { field.value = ''; }\n          }\n        });\n      });\n    }\n\n    /* A field that is only NEEDED for some answers - the telephone number when\n       the customer asks to be phoned. It stays visible and optional otherwise,\n       so the form does not grow and shrink as they answer; only the asterisk\n       and the browser's own validation change.\n\n       The condition NAMES ITS OWN CONTROLLER, because the field it depends on\n       is usually not the one that shows and hides groups: on Product Advice the\n       groups follow \"Advice type\" while the telephone number follows \"Preferred\n       reply\". Written as \"Preferred reply: Telephone, WhatsApp\"; with no label\n       before the colon it falls back to the section's main controller. */\n    function parseCondition(raw) {\n      var i = raw.indexOf(':');\n      var field = i > -1 ? raw.slice(0, i).trim() : '';\n      var values = (i > -1 ? raw.slice(i + 1) : raw).split(',').map(function (v) { return v.trim(); });\n      return { field: field, values: values };\n    }\n\n    function controllerFor(name) {\n      if (!name) { return select; }\n      return scope.querySelector('[name=\"contact[' + name.replace(/\"/g, '') + ']\"]') || select;\n    }\n\n    /* A RADIO GROUP HAS NO SINGLE ELEMENT TO READ. controllerFor hands back the\n       FIRST member of the group, and its .value is its own option - \"Email\" -\n       whether or not it is the one chosen. Preferred reply method is a radio\n       group now (brief 36), so read the member that is actually checked. */\n    function controlValue(ctl) {\n      if (!ctl) { return ''; }\n      if (ctl.type === 'radio' && ctl.name) {\n        var chosen = scope.querySelector('[name=\"' + ctl.name.replace(/\"/g, '') + '\"]:checked');\n        return chosen ? chosen.value : '';\n      }\n      return ctl.value;\n    }\n\n    function applyRequired() {\n      Array.prototype.forEach.call(conditionallyRequired, function (group) {\n        var cond = parseCondition(group.getAttribute('data-tdhq-required-when') || '');\n        var ctl = controllerFor(cond.field);\n        var need = !!ctl && cond.values.indexOf(controlValue(ctl)) !== -1;\n        /* Never required while hidden: the browser refuses to submit and points\n           at a control that is not on screen. */\n        if (group.hidden) { need = false; }\n        Array.prototype.forEach.call(group.querySelectorAll('input, select, textarea'), function (field) {\n          field.required = need;\n          field.setAttribute('aria-required', need ? 'true' : 'false');\n        });\n      });\n    }\n\n    var applyAll = function () { apply(); applyRequired(); };\n    select.addEventListener('change', applyAll);\n\n    /* Listen to every field a condition names, once each. */\n    var watched = [];\n    Array.prototype.forEach.call(conditionallyRequired, function (group) {\n      var cond = parseCondition(group.getAttribute('data-tdhq-required-when') || '');\n      var ctl = controllerFor(cond.field);\n      if (ctl && ctl !== select && watched.indexOf(ctl) === -1) {\n        watched.push(ctl);\n        /* One radio only hears its OWN change, so the group is watched through\n           the form wrapper the events bubble to instead. Registering the same\n           function twice on the same element is a no-op, so two conditions on\n           two groups still bind once. */\n        if (ctl.type === 'radio') { scope.addEventListener('change', applyRequired); }\n        else { ctl.addEventListener('change', applyRequired); }\n      }\n    });\n    // Run once on load: the groups render visible so a no-JS visitor sees\n    // everything, and this collapses them to the relevant set.\n    applyAll();\n\n    /* ---- ROUTE LINKS PRESELECT THE ADVICE TYPE (brief 16-21, 49) ----\n\n       The six advice route cards and the fitting band's Upload My Fitting\n       Photos all lead to this one form, and they used to land on it with\n       nothing chosen: the customer answers \"what do you need help with?\"\n       once by choosing a card and again by finding the same words in a list.\n\n       The choice travels in ?advice=<option value>. On load it is applied only\n       while the list is still unanswered, so a half-filled form that is\n       reloaded is never rewritten. A click on a link on THIS page applies it\n       with no page load at all, which is also what stops anything already\n       typed from being thrown away. Neither ever submits the form. */\n    function focusAfterController() {\n      var all = scope.querySelectorAll('input, select, textarea');\n      var passed = false;\n      for (var i = 0; i < all.length; i++) {\n        if (all[i] === select) { passed = true; continue; }\n        if (!passed || all[i].disabled || all[i].type === 'hidden') { continue; }\n        var box = all[i].getBoundingClientRect();\n        if (!box.width && !box.height) { continue; }\n        /* preventScroll: the browser has just jumped to the form's anchor, or\n           is scrolling to it below. Focusing would otherwise move the page a\n           second time, under the reader. */\n        try { all[i].focus({ preventScroll: true }); } catch (err) { all[i].focus(); }\n        return;\n      }\n    }\n\n    function preselect(value, moveFocus) {\n      if (!value || !select.options) { return false; }\n      for (var i = 0; i < select.options.length; i++) {\n        if (select.options[i].value !== value) { continue; }\n        if (select.value !== value) {\n          select.value = value;\n          /* A real change event: the custom dropdown repaints from it and the\n             conditional fields re-run. */\n          select.dispatchEvent(new Event('change', { bubbles: true }));\n        }\n        if (moveFocus) { focusAfterController(); }\n        return true;\n      }\n      return false;\n    }\n\n    function adviceFrom(search) {\n      try { return new URLSearchParams(search).get('advice') || ''; }\n      catch (err) { return ''; }\n    }\n\n    if (!select.value) { preselect(adviceFrom(window.location.search), true); }\n\n    document.addEventListener('click', function (e) {\n      if (e.defaultPrevented || e.metaKey || e.ctrlKey || e.shiftKey || e.button > 0) { return; }\n      var link = e.target && e.target.closest ? e.target.closest('a[href]') : null;\n      if (!link || link.target === '_blank') { return; }\n      var url;\n      try { url = new URL(link.href, window.location.href); } catch (err) { return; }\n      /* Only a link back to THIS page: from anywhere else it is an ordinary\n         navigation and the load-time branch above picks the choice up. */\n      if (url.pathname !== window.location.pathname) { return; }\n      var want = adviceFrom(url.search);\n      if (!want || !preselect(want, false)) { return; }\n      e.preventDefault();\n      var target = url.hash ? document.getElementById(url.hash.slice(1)) : null;\n      if (target) {\n        var still = window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n        target.scrollIntoView({ behavior: still ? 'auto' : 'smooth', block: 'start' });\n      }\n      focusAfterController();\n      /* The address bar keeps the choice, so the page can be shared or\n         reloaded and land the same way. Nothing personal is in it. */\n      try { window.history.replaceState(null, '', url.pathname + url.search + url.hash); } catch (err) {}\n    });\n  }\n\n  function initForms(root) {\n    var forms = root.querySelectorAll('[data-tdhq-form]');\n    if (forms.length) {\n      Array.prototype.forEach.call(forms, wireConditionalFields);\n    } else if (root === document) {\n      // The original contact form predates the wrapper attribute.\n      wireConditionalFields(document);\n    }\n  }\n\n  /* ---------------------------------------------------------\n     COLLECTION FILTER PANEL (narrow screens only)\n\n     The panel renders OPEN. This collapses it below the breakpoint, which is\n     the safe direction: if this script never runs, the filters are still on the\n     page and still work, because filtering is a plain GET form.\n\n     Desktop is never touched \u2014 there the panel is a sidebar and the trigger is\n     display:none, so collapsing it would hide filters with no way back.\n     --------------------------------------------------------- */\n  /* Named and idempotent so the Section-Rendering swap below can re-run it on\n     the freshly injected markup \u2014 injected HTML never executes scripts and\n     never inherits element-bound listeners. */\n  /* THE PANEL'S STATE OUTLIVES THE SECTION. Every facet tick replaces the\n     whole collection section, and initCollectionUI() runs again on the fresh\n     markup - so anything kept inside it is both re-created and never cleaned\n     up. Two faults came out of that: the media-query listener was registered\n     once per swap and never removed (three ticks, three listeners, one live\n     panel), and applyBreakpoint() collapsed the panel again after every tick,\n     so a phone shopper could apply exactly one filter per opening.\n\n     The query, its listener and the shopper's own choice therefore live here,\n     at page scope, and are looked up through the CURRENT root each time. */\n  /* 999px, matching the CSS rule that hides the panel (assets/tdhq-page.css,\n     inside @media (max-width: 999px)). At 899 they disagreed, so between 900\n     and 999 the panel stayed open in flow with no way to close it. */\n  var facetsNarrow = window.matchMedia('(max-width: 999px)');\n  var facetsOpenedByUser = null;   /* null = never touched; true = they opened it */\n\n  function facetsParts() {\n    var root = document.querySelector('[data-tdhq-collection]');\n    if (!root) { return null; }\n    var toggle = root.querySelector('[data-tdhq-facets-toggle]');\n    var panel = root.querySelector('[data-tdhq-facets]');\n    if (!toggle || !panel) { return null; }\n    return { root: root, toggle: toggle, panel: panel };\n  }\n\n  /* The state is named for what is TRUE of the markup the server sends:\n     closed. The script adds the class to OPEN the panel, so nothing has to\n     move after the page has painted. */\n  /* BELOW 1000PX THE OPEN PANEL IS A MODAL DRAWER (tdhq-page.css, audit\n     LST-03): the page behind is locked with the one scroll-lock class, the\n     panel is announced as a dialog named by its \"Filter\" title, focus stays\n     inside it, and the close button, the scrim, Escape and the results button\n     all close it and hand focus back to the Filter button. On the desktop rail\n     none of that applies: it is a sidebar, not a dialog. */\n  var facetsLocked = false;\n  function lockFacetsPage(on) {\n    if (on === facetsLocked) { return; }\n    facetsLocked = on;\n    document.documentElement.classList.toggle('tdhq-modal-open', on);\n  }\n\n  function setFacetsOpen(on) {\n    var p = facetsParts();\n    if (!p) { lockFacetsPage(false); return; }\n    p.root.classList.toggle('is-facets-open', on);\n    p.toggle.setAttribute('aria-expanded', on ? 'true' : 'false');\n    var modal = on && facetsNarrow.matches;\n    lockFacetsPage(modal);\n    if (modal) {\n      p.panel.setAttribute('role', 'dialog');\n      p.panel.setAttribute('aria-modal', 'true');\n      p.panel.setAttribute('aria-labelledby', 'tdhq-facets-title');\n    } else {\n      p.panel.removeAttribute('role');\n      p.panel.removeAttribute('aria-modal');\n      p.panel.removeAttribute('aria-labelledby');\n    }\n  }\n\n  function facetsDrawerOpen() {\n    var p = facetsParts();\n    return !!(p && facetsNarrow.matches && p.root.classList.contains('is-facets-open'));\n  }\n\n  function closeFacetsDrawer() {\n    facetsOpenedByUser = false;\n    setFacetsOpen(false);\n    var p = facetsParts();\n    if (p) { p.toggle.focus({ preventScroll: true }); }\n  }\n\n  /* Delegated: every filter tick replaces the section, and these must keep\n     working on the fresh markup. The results button closes the drawer and\n     lets its form submit go ahead (tdhq-page.js below renders the results). */\n  document.addEventListener('click', function (e) {\n    if (!e.target.closest) { return; }\n    if (e.target.closest('[data-tdhq-facets-close]')) {\n      e.preventDefault();\n      closeFacetsDrawer();\n      return;\n    }\n    if (e.target.closest('[data-tdhq-facets-apply]') && facetsDrawerOpen()) {\n      /* Only a form that will actually submit closes the drawer: an invalid price would otherwise be hidden with\n         its message (Codex filters-1021 F09). */\n      var applyForm = e.target.closest('form');\n      if (!applyForm || applyForm.checkValidity()) { closeFacetsDrawer(); }\n    }\n  });\n\n  document.addEventListener('keydown', function (e) {\n    if (!facetsDrawerOpen()) { return; }\n    var p = facetsParts();\n    if (e.key === 'Escape') {\n      /* A custom dropdown open inside the panel closes first. */\n      if (e.defaultPrevented) { return; }\n      e.preventDefault();\n      closeFacetsDrawer();\n      return;\n    }\n    if (e.key !== 'Tab') { return; }\n    var f = Array.prototype.filter.call(\n      p.panel.querySelectorAll('a[href], button:not([disabled]), input:not([disabled]):not([type=\"hidden\"]), select:not([disabled]), summary, [tabindex]:not([tabindex=\"-1\"])'),\n      function (n) { return n.offsetParent !== null || n === document.activeElement; }\n    );\n    if (!f.length) { return; }\n    var first = f[0], last = f[f.length - 1];\n    if (!p.panel.contains(document.activeElement)) { e.preventDefault(); first.focus(); return; }\n    if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus(); }\n    else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); }\n  });\n\n  /* Collapsed below the breakpoint UNLESS the shopper opened it, in which case\n     it stays open across as many filter applications as they want. Desktop is\n     never touched: there the panel is a sidebar and the trigger is\n     display:none, so collapsing would hide the filters with no way back. */\n  function applyFacetsBreakpoint() {\n    if (!facetsNarrow.matches) { setFacetsOpen(true); return; }\n    setFacetsOpen(facetsOpenedByUser === true);\n  }\n\n  /* Crossing the breakpoint is a real change of context - a rotated phone, a\n     resized window - so the remembered choice is forgotten there, and only\n     there. */\n  function onFacetsBreakpointChange() {\n    facetsOpenedByUser = null;\n    applyFacetsBreakpoint();\n  }\n  // addEventListener on MediaQueryList is not in older Safari; addListener is.\n  if (facetsNarrow.addEventListener) { facetsNarrow.addEventListener('change', onFacetsBreakpointChange); }\n  else if (facetsNarrow.addListener) { facetsNarrow.addListener(onFacetsBreakpointChange); }\n\n  /* ---------------------------------------------------------\n     LONG FACET LISTS: SHOW ALL / SHOW FEWER\n\n     A list longer than ten values renders its first eight and a button\n     (sections/tdhq-collection.liquid). It replaced a 300px inner scroller\n     that hid 20 of Interior's 27 brands behind a fade with no control, so\n     the last visible brand looked disabled. Without script every value shows\n     and the button stays hidden (html.js gates both in the CSS).\n\n     Every filter tick replaces the section, so the shopper's choice is kept\n     here per facet and put back on the fresh markup; a choice they made wins\n     over the server's \"a ticked value is hidden, open it\" default. The rail\n     stays pinned under the header and scrolls inside itself (21 Oct), so a\n     list opening or closing never moves the page.\n     --------------------------------------------------------- */\n  var facetListsOpen = {};\n\n  function setFacetList(btn, list, open) {\n    list.classList.toggle('is-expanded', open);\n    btn.setAttribute('aria-expanded', open ? 'true' : 'false');\n    btn.textContent = btn.getAttribute(open ? 'data-label-less' : 'data-label-more') || btn.textContent;\n  }\n\n  /* GROUPS KEEP THE STATE THE SHOPPER GAVE THEM (Codex filters-1021 F04): every group renders open, so a group\n     closed before a filter tick came back open with the new markup. The choice is recorded at the summary click\n     (before the disclosure animation runs) and put back on every re-render. */\n  var facetGroupsOpen = {};\n  document.addEventListener('click', function (e) {\n    var sum = e.target.closest && e.target.closest('details[data-tdhq-facet-group] > summary');\n    if (!sum) { return; }\n    var d = sum.parentNode;\n    facetGroupsOpen[d.getAttribute('data-tdhq-facet-group')] = !d.open;\n  }, true);\n\n  function syncFacetGroups(root) {\n    Array.prototype.forEach.call(root.querySelectorAll('details[data-tdhq-facet-group]'), function (d) {\n      var key = d.getAttribute('data-tdhq-facet-group');\n      if (Object.prototype.hasOwnProperty.call(facetGroupsOpen, key)) { d.open = facetGroupsOpen[key]; }\n    });\n  }\n\n  function syncFacetLists(root) {\n    syncFacetGroups(root);\n    Array.prototype.forEach.call(root.querySelectorAll('[data-tdhq-facets-more]'), function (btn) {\n      var list = document.getElementById(btn.getAttribute('aria-controls'));\n      if (!list) { return; }\n      var key = list.getAttribute('data-tdhq-facet') || list.id;\n      var open = Object.prototype.hasOwnProperty.call(facetListsOpen, key) ? facetListsOpen[key] : list.classList.contains('is-expanded');\n      setFacetList(btn, list, open);\n    });\n  }\n\n  /* SHOW ALL OPENS LIKE THE GROUPS DO (audit LST-19). The facet groups open\n     and close over ~200ms, but \"Show all 48\" took the Brand list from 302px to\n     1851px between two frames and everything below it jumped. The list now\n     grows and shrinks over the motion token (--tdhq-t, 220ms) with the shared\n     easing, and the rows it reveals fade in; closing keeps them on show until\n     the list has shrunk past them. Only on the shopper's click - the state put\n     back after a filter re-render is never animated. */\n  document.addEventListener('click', function (e) {\n    var btn = e.target.closest && e.target.closest('[data-tdhq-facets-more]');\n    if (!btn) { return; }\n    var list = document.getElementById(btn.getAttribute('aria-controls'));\n    if (!list) { return; }\n    var open = btn.getAttribute('aria-expanded') !== 'true';\n    var rail = btn.closest('[data-tdhq-facets]');\n    facetListsOpen[list.getAttribute('data-tdhq-facet') || list.id] = open;\n    // Closing a long list must not leave the shopper scrolled past it: once it has shrunk, the rail (its own scroller)\n    // brings the Show all button back into view, clear of the pinned Apply bar.\n    var keepInView = function () {\n      if (open || !rail || rail.scrollHeight <= rail.clientHeight) { return; }\n      var r = rail.getBoundingClientRect(), b = btn.getBoundingClientRect();\n      var foot = rail.querySelector('.tdhq-facets__foot');\n      var bottom = r.bottom - (foot ? foot.offsetHeight : 0) - 12;\n      if (b.top < r.top + 12) { rail.scrollTop -= r.top + 12 - b.top; }\n      else if (b.bottom > bottom) { rail.scrollTop += b.bottom - bottom; }\n    };\n    /* The label changes on the click; the rows move with TdhqMotion.resize (one height glide per list, a second click\n       mid-way starts from where the list is, Codex filters-1021 F20), and the closing rows stay until the list is shut. */\n    btn.setAttribute('aria-expanded', open ? 'true' : 'false');\n    btn.textContent = btn.getAttribute(open ? 'data-label-less' : 'data-label-more') || btn.textContent;\n    var shown = function (o) { list.classList.toggle('is-expanded', o); };\n    var M = window.TdhqMotion;\n    if (!M || !M.resize) { shown(open); keepInView(); return; }\n    var anim = M.resize(list, shown, open, true, keepInView);\n    if (anim && open) {\n      Array.prototype.slice.call(list.children, 8).forEach(function (row) {\n        row.animate([{ opacity: 0 }, { opacity: 1 }], { duration: M.ms('--tdhq-t', 220), easing: M.easing() });\n      });\n    }\n    /* Keyboard: the first value the list revealed takes focus, as in Shopify's Dawn (F19). A mouse click keeps\n       focus where it is (e.detail is 0 only for keyboard activation). */\n    if (open && e.detail === 0) {\n      var firstNew = list.children[8] && list.children[8].querySelector('input:not([disabled])');\n      if (firstNew) { firstNew.focus({ preventScroll: true }); }\n    }\n  });\n\n  function initCollectionUI() {\n    var root = document.querySelector('[data-tdhq-collection]');\n    if (!root || root.dataset.tdhqUiReady) return;\n    root.dataset.tdhqUiReady = '1';\n    syncFacetLists(root);\n    var toggle = root.querySelector('[data-tdhq-facets-toggle]');\n    var panel = root.querySelector('[data-tdhq-facets]');\n    if (!toggle || !panel) return;\n\n    toggle.addEventListener('click', function () {\n      var isCollapsed = !root.classList.contains('is-facets-open');\n      facetsOpenedByUser = isCollapsed;\n      setFacetsOpen(isCollapsed);\n      if (isCollapsed) {\n        // Opening: move focus into the panel so a keyboard user lands on the\n        // first control rather than staying on the trigger.\n        /* not a hidden field: the search page's rail carries its query in some */\n        var first = panel.querySelector('select, input:not([type=\"hidden\"]), summary, button');\n        if (first) first.focus({ preventScroll: true });\n      }\n    });\n\n    applyFacetsBreakpoint();\n\n    /* Sort submits immediately \u2014 it is a single choice, so batching it behind\n       Apply would just be a second click. The filter checkboxes deliberately do\n       NOT auto-submit: until no-reload filtering lands, each tick would cost a\n       full page load, so they are batched behind Apply. */\n    var sort = root.querySelector('[data-tdhq-sort]');\n    var form = root.querySelector('[data-tdhq-facets-form]');\n    if (sort && form) {\n      sort.addEventListener('change', function () {\n        if (typeof form.requestSubmit === 'function') form.requestSubmit();\n        else form.submit();\n      });\n    }\n\n    /* With no-reload filtering live (below), each checkbox tick can apply\n       immediately \u2014 the debounce batches a quick run of ticks into one\n       request. The Apply button still works and is the no-JS fallback. */\n    /* A reversed price range (minimum above maximum) is swapped before it is sent (Codex filters-1021 F16). The\n       listener runs in the capture phase, before the no-reload submit handler reads the form. */\n    form && form.addEventListener('submit', function () {\n      var lo = form.querySelector('input[name=\"filter.v.price.gte\"]');\n      var hi = form.querySelector('input[name=\"filter.v.price.lte\"]');\n      if (lo && hi && lo.value !== '' && hi.value !== '' && Number(lo.value) > Number(hi.value)) {\n        var t = lo.value; lo.value = hi.value; hi.value = t;\n      }\n    }, true);\n    var debounce;\n    form && form.addEventListener('change', function (e) {\n      if (e.target.type !== 'checkbox' && e.target.type !== 'number') return;\n      clearTimeout(debounce);\n      debounce = setTimeout(function () {\n        if (typeof form.requestSubmit === 'function') form.requestSubmit();\n        else form.submit();\n      }, 350);\n    });\n  }\n  initCollectionUI();\n\n  /* ---------------------------------------------------------\n     INSTANT PAGINATION + FILTERING \u2014 Section Rendering API.\n\n     Per shopify.dev best practice: fetch the SAME url with\n     `sections=<id>`, which returns { \"<id>\": \"<rendered html>\" },\n     then replace the section wrapper's outerHTML (innerHTML would\n     nest a second wrapper and duplicate its id). Rendering stays\n     in Liquid; this script only fetches and swaps.\n\n     Listeners are DELEGATED on document so they survive every\n     swap; per-element UI is re-initialised via initCollectionUI().\n     Plain links and the GET form remain the no-JS fallback.\n     --------------------------------------------------------- */\n  (function collectionAjax() {\n    if (!('fetch' in window) || !window.history || !window.history.pushState) return;\n\n    var inflight = null;\n    var loadSeq = 0;\n\n    /* ---- SOLD-OUT LAST, ACROSS EVERY PAGE ----------------------------------\n       Shopify has no sort that puts sold-out products last, and paginate\n       orders a page before Liquid sees it, so the section's own two-pass loop\n       could only reorder within one page. This builds page P from Shopify's\n       availability filter instead - in-stock list first, sold-out list after -\n       so every sold-out product comes after every in-stock one, under any sort\n       and any other filter, and moves back by itself when it is restocked.\n       The figures come from Liquid on the grid (data-sf-*). A product with some\n       variants left is in BOTH filter lists, so sold-out cards are taken from\n       the out-of-stock list with still-available products removed, and\n       (in + out - total) bounds how far that list is read. Anything that does\n       not add up leaves the server's page exactly as it was. */\n    var sfCache = {};\n    function sfGet(url) {\n      if (!sfCache[url]) {\n        sfCache[url] = fetch(url).then(function (r) {\n          if (!r.ok) { throw new Error('HTTP ' + r.status); }\n          return r.json();\n        });\n        sfCache[url].catch(function () { delete sfCache[url]; });\n      }\n      return sfCache[url];\n    }\n    function sfCards(html) {\n      var tpl = document.createElement('template');\n      tpl.innerHTML = html || '';\n      var g = tpl.content.querySelector('[data-tdhq-collection-grid]');\n      return g ? Array.prototype.slice.call(g.children) : [];\n    }\n    function sfIsOut(card) {\n      return card.classList.contains('tdhq-pcard--out') || !!card.querySelector('.tdhq-pcard--out');\n    }\n    function sfKey(card) {\n      var a = card.querySelector('a[href*=\"/products/\"]');\n      return a ? a.getAttribute('href').split('?')[0] : '';\n    }\n    /* PAINT ONCE (the client's \"products appear twice\", audit LST-01/LST-02).\n       This used to rebuild the grid the shopper was already looking at: on\n       GYEON row 1 card 4 painted as a sold-out tar remover and turned into a\n       sticker 200ms later, and every sold-out card below shifted a slot. Now\n       the section marks the cards this pass may still replace\n       (data-sf-pending: the sold-out cards on page 1, every card on a later\n       page) and tdhq-fix-listing.css keeps them invisible until it resolves.\n       stockFirst() only works out the order; sfApply() writes it and\n       sfRelease() shows what was held, so each slot is painted once, with its\n       final card. */\n    function stockFirst(root, sectionId, pageUrl) {\n      var g = root.querySelector('[data-tdhq-collection-grid][data-sf-param]');\n      if (!g) { return Promise.resolve(null); }\n      var d = g.dataset;\n      var inN = +d.sfIn, outN = +d.sfOut, total = +d.sfTotal, page = +d.sfPage, size = +d.sfSize;\n      if (!(inN > 0 && total > inN && size > 0 && page > 0)) { return Promise.resolve(null); }\n      var start = (page - 1) * size;\n      var end = Math.min(page * size, total);\n      if (start >= total) { return Promise.resolve(null); }\n      var current = Array.prototype.slice.call(g.children);\n      /* Page 1 with no sold-out card on it is already the first page of the\n         in-stock list. */\n      if (page === 1 && !current.some(sfIsOut)) { return Promise.resolve(null); }\n      var dup = Math.max(0, inN + outN - total);\n      var inCount = Math.max(0, Math.min(end, inN) - start);\n      var outFrom = Math.max(start, inN) - inN;\n      var outCount = end - Math.max(start, inN);\n      var outPages = outCount > 0 ? Math.ceil((outFrom + outCount + dup) / size) : 0;\n      if (outPages > 12) { return Promise.resolve(null); }\n\n      function listUrl(value, n) {\n        var u = new URL(pageUrl, window.location.origin);\n        u.searchParams.delete('page');\n        u.searchParams.delete('sections');\n        u.searchParams.delete(d.sfParam);\n        u.searchParams.append(d.sfParam, value);\n        if (n > 1) { u.searchParams.set('page', String(n)); }\n        u.searchParams.set('sections', sectionId);\n        return u.pathname + '?' + u.searchParams.toString();\n      }\n\n      var inJob = inCount > 0\n        ? sfGet(listUrl(d.sfInValue, page)).then(function (data) { return sfCards(data[sectionId]).slice(0, inCount); })\n        : Promise.resolve([]);\n      var outJobs = [];\n      for (var q = 1; q <= outPages; q++) { outJobs.push(sfGet(listUrl(d.sfOutValue, q))); }\n      var outJob = Promise.all(outJobs).then(function (list) {\n        var cards = [];\n        list.forEach(function (data) { cards = cards.concat(sfCards(data[sectionId]).filter(sfIsOut)); });\n        return cards.slice(outFrom, outFrom + outCount);\n      });\n\n      return Promise.all([inJob, outJob]).then(function (parts) {\n        var next = parts[0].concat(parts[1]);\n        /* Stock changed between requests, or a list came back short: keep the\n           server's page rather than show a wrong one. */\n        if (next.length !== end - start) { return null; }\n        var same = next.length === current.length && next.every(function (c, i) { return sfKey(c) === sfKey(current[i]); });\n        return same ? null : next;\n      });\n    }\n    /* On show: in the document and not held back by data-sf-pending. A grid\n       built off-screen (a filter, sort or page swap) has nothing on show. */\n    function sfShown(card) {\n      return card.isConnected && window.getComputedStyle(card).visibility === 'visible';\n    }\n    /* Writes the planned order. Cards the shopper can already see are never\n       moved: the order is written from the first slot that differs or was held\n       back, and every card placed from there on is new or was invisible until\n       now, so it is first seen as it arrives (with the grid's fade on a swap).\n       This used to settle the whole grid (is-settled) before re-appending every\n       card, which stopped the replay but also killed the entrance of a freshly\n       fetched page, so a filter, sort or page change snapped in (audit MOT-08). */\n    function sfApply(g, next) {\n      var current = Array.prototype.slice.call(g.children);\n      var byKey = {};\n      current.forEach(function (c) { var k = sfKey(c); if (k && !byKey[k]) { byKey[k] = c; } });\n      var revealed = current.some(function (c) {\n        return c.classList.contains('is-in') || !!c.querySelector('.is-in');\n      });\n      var ordered = next.map(function (c) {\n        var k = sfKey(c);\n        if (k && byKey[k]) { var have = byKey[k]; delete byKey[k]; return have; }\n        if (revealed) {\n          if (c.className && String(c.className).indexOf('reveal') > -1) { c.classList.add('is-in'); }\n          Array.prototype.forEach.call(c.querySelectorAll('[class*=\"reveal\"]'), function (n) { n.classList.add('is-in'); });\n        }\n        return c;\n      });\n      /* U.52: every card's on-show state is read before anything moves. Read\n         between the moves, each read made the browser restyle the grid again\n         (Lighthouse forced reflow, ~50 ms on a phone collection page). Moving\n         a card never changes whether another is on show: that depends only on\n         the grid's data-sf-pending and the card's own sold-out class. */\n      var shown = ordered.map(sfShown);\n      var keep = 0;\n      while (keep < ordered.length && ordered[keep] === current[keep] && shown[keep]) { keep++; }\n      var move = function () {\n        current.forEach(function (c) { if (ordered.indexOf(c) === -1) { g.removeChild(c); } });\n        for (var i = keep; i < ordered.length; i++) {\n          /* On show and still having to move (the in-stock list came back in\n             another order): it slides to its place without a second entrance. */\n          if (shown[i]) { ordered[i].classList.add('tdhq-sf-kept'); }\n          g.appendChild(ordered[i]);\n        }\n      };\n      /* cards already on show GLIDE to their new places (TdhqMotion.flip, 21 Oct); measured only when one moves */\n      var visibleMoves = false;\n      for (var s = keep; s < ordered.length; s++) { if (shown[s]) { visibleMoves = true; break; } }\n      if (visibleMoves && window.TdhqMotion) { window.TdhqMotion.flip(g, ':scope > *', move, null, true); } else { move(); }\n      g.setAttribute('data-sf-built', '');\n    }\n    /* Shows the cards data-sf-pending held back. They were invisible while the\n       grid's entrance ran, so the ones not just placed by sfApply are put back\n       in the same order, which starts their entrance now instead of leaving\n       them to pop in at full strength. */\n    function sfRelease(g) {\n      if (!g || !g.hasAttribute('data-sf-pending')) { return; }\n      var kids = Array.prototype.slice.call(g.children);\n      var from = -1;\n      if (g.isConnected) {\n        for (var i = 0; i < kids.length; i++) { if (!sfShown(kids[i])) { from = i; break; } }\n      }\n      g.removeAttribute('data-sf-pending');\n      if (from > -1) {\n        for (var j = from; j < kids.length; j++) { g.appendChild(kids[j]); }\n      }\n    }\n    /* The pass never holds the grid for long: after SF_WAIT the server's own\n       order stands and a late answer is ignored rather than swapped in. */\n    var SF_WAIT = 3000;\n    function sfWithin(job) {\n      return new Promise(function (resolve) {\n        var t = window.setTimeout(function () { resolve(null); }, SF_WAIT);\n        job.then(function (v) { window.clearTimeout(t); resolve(v); }, function () { window.clearTimeout(t); resolve(null); });\n      });\n    }\n    function announceSwap(root) {\n      var ev;\n      try { ev = new CustomEvent('tdhq:collection:updated', { detail: { root: root } }); }\n      catch (err) { ev = document.createEvent('CustomEvent'); ev.initCustomEvent('tdhq:collection:updated', false, false, { root: root }); }\n      document.dispatchEvent(ev);\n    }\n\n    /* ---- announcing the new result count -------------------------------\n       The count node inside the section carries aria-live, but the whole\n       section is replaced via outerHTML on every filter, sort and page: the\n       node the browser was observing is destroyed and a brand new one arrives\n       already containing its text, which is not a change to anything the\n       browser was watching. Nothing was ever announced. This region lives on\n       <body>, outside the swap, so it survives every render. */\n    function liveRegion() {\n      var el = document.getElementById('tdhq-collection-live');\n      if (!el) {\n        el = document.createElement('p');\n        el.id = 'tdhq-collection-live';\n        el.className = 'tdhq-visually-hidden';\n        el.setAttribute('role', 'status');\n        el.setAttribute('aria-live', 'polite');\n        el.setAttribute('aria-atomic', 'true');\n        document.body.appendChild(el);\n      }\n      return el;\n    }\n\n    function announceCount(fresh) {\n      var src = fresh && fresh.querySelector('[data-tdhq-collection-count]');\n      var text = src ? src.textContent.replace(/\\s+/g, ' ').trim() : '';\n      if (!text) { return; }\n      var el = liveRegion();\n      /* Blank first, so filtering from one 24-result set to another 24-result\n         set still fires - assigning an identical string is not a change.\n\n         A TIMER, not requestAnimationFrame: rAF does not run while the tab is\n         in the background, and an announcement that never arrives is worse than\n         one that arrives late. 30ms is long enough for the blank to be observed\n         and short enough to feel immediate. */\n      el.textContent = '';\n      window.setTimeout(function () { el.textContent = text; }, 30);\n    }\n\n    /* ---- putting focus back where the shopper was ------------------------\n       Focus used to go to the <h1> after every swap, which is correct for a\n       page navigation and wrong for a filter: the shopper is working in the\n       facet panel, and being thrown to the top of the page means tabbing all\n       the way back down for the next filter. Remember WHICH control was used\n       and re-find its equivalent in the fresh markup. */\n    function describeFocus() {\n      var a = document.activeElement;\n      if (!a || a === document.body) { return null; }\n      if (a.matches('[data-tdhq-sort]')) { return { sel: '[data-tdhq-sort]' }; }\n      if (a.matches('[data-tdhq-facets-toggle]')) { return { sel: '[data-tdhq-facets-toggle]' }; }\n      if (a.matches('[data-tdhq-facets-apply]')) { return { sel: '[data-tdhq-facets-apply]' }; }\n      if (a.name) {\n        return { sel: '[name=\"' + a.name.replace(/\"/g, '') + '\"]' +\n                      (a.value ? '[value=\"' + String(a.value).replace(/\"/g, '') + '\"]' : '') };\n      }\n      if (a.closest('.tdhq-pager')) { return { pager: (a.textContent || '').trim() }; }\n      /* A removed chip is gone from the fresh markup: focus the chip that took\n         its place, or the result count when it was the last one, rather than\n         throwing a keyboard user back to the heading. */\n      var chip = a.closest('.tdhq-chips li');\n      if (chip) { return { chip: Array.prototype.indexOf.call(chip.parentNode.children, chip) }; }\n      if (a.matches('a.tdhq-collection__stockchip')) { return { sel: 'a.tdhq-collection__stockchip' }; }\n      if (a.matches('a.tdhq-facets__clear')) { return { sel: '.tdhq-facets__title' }; }\n      if (a.closest('.tdhq-collection__brandactions')) { return { sel: '.tdhq-collection__brandactions a.tdhq-btn--primary' }; }\n      return null;\n    }\n\n    function restoreFocus(hint, fresh) {\n      if (!fresh) { return; }\n      var target = null;\n      if (hint && hint.sel) { target = fresh.querySelector(hint.sel); }\n      if (hint && typeof hint.chip === 'number') {\n        var chips = fresh.querySelectorAll('.tdhq-chips a[href]');\n        target = chips[Math.min(hint.chip, chips.length - 1)] || fresh.querySelector('[data-tdhq-collection-count]');\n      }\n      if (hint && hint.pager) {\n        var links = fresh.querySelectorAll('.tdhq-pager a[href]');\n        for (var i = 0; i < links.length; i++) {\n          if ((links[i].textContent || '').trim() === hint.pager) { target = links[i]; break; }\n        }\n      }\n      /* Nothing equivalent survived (the last page of a pager, a facet whose\n         value is now gone): the heading is the honest fallback. */\n      if (!target) { target = fresh.querySelector('h1'); }\n      if (target) {\n        if (!target.hasAttribute('tabindex') && !target.matches('a[href], button, input, select, textarea')) {\n          target.setAttribute('tabindex', '-1');\n        }\n        target.focus({ preventScroll: true });\n      }\n    }\n\n    function sectionWrap() {\n      var root = document.querySelector('[data-tdhq-collection]');\n      return root && root.closest('[id^=\"shopify-section-\"]');\n    }\n\n    /* THE HEADER PICTURE BELONGS TO THE COLLECTION, NOT TO THE FILTER (audit\n       LST-02). A collection with no image of its own shows its first product's\n       photo, and the first product changes with every filter and sort: the\n       header swapped from the Glatt bottle to another product on each tick and\n       was blank while the new one loaded, and a filter with no results left it\n       with no picture at all. The picture on show is carried into the new\n       render. A reload or shared link of a filtered address still renders the\n       server's own choice. */\n    function keepHeaderThumb(wrap, node) {\n      var oldT = wrap.querySelector('.tdhq-collection__thumb');\n      var newH = node.querySelector('.tdhq-collection__header');\n      if (!oldT || !newH || newH.classList.contains('tdhq-collection__header--slim')) { return; }\n      var newT = newH.querySelector('.tdhq-collection__thumb');\n      if (newT) { newT.parentNode.replaceChild(oldT, newT); }\n      else {\n        newH.insertBefore(oldT, newH.firstChild);\n        newH.classList.add('tdhq-collection__header--thumb');\n      }\n    }\n\n    /* The listing the grid currently shows (path + query, never the #hash). */\n    var listedUrl = window.location.pathname + window.location.search;\n\n    function load(url, push) {\n      var wrap = sectionWrap();\n      if (!wrap) { window.location.href = url; return; }\n      try { var lu = new URL(url, window.location.origin); listedUrl = lu.pathname + lu.search; } catch (e) {}\n      var sectionId = wrap.id.replace('shopify-section-', '');\n\n      if (inflight) inflight.abort();\n      var ctl = ('AbortController' in window) ? new AbortController() : null;\n      inflight = ctl;\n\n      wrap.setAttribute('aria-busy', 'true');\n      var focusHint = describeFocus();\n      var seq = ++loadSeq;\n      /* dim only when the answer is slow: a tick answered within 120 ms does not flash grey (as the blog pager) */\n      window.setTimeout(function () { if (seq === loadSeq && wrap.isConnected) { wrap.classList.add('is-updating'); } }, 120);\n\n      var u = new URL(url, window.location.origin);\n      u.searchParams.set('sections', sectionId);\n\n      /* 12 s at most, then the page loads normally (Codex 21 Oct) */\n      var timedOut = false;\n      var guard = ctl ? window.setTimeout(function () { timedOut = true; ctl.abort(); }, 12000) : 0;\n      fetch(u.toString(), ctl ? { signal: ctl.signal } : {})\n        .then(function (r) { window.clearTimeout(guard); return r.json(); })\n        .then(function (data) {\n          var html = data[sectionId];\n          /* a section that fails to render is null inside a 200 \u2014 fall back\n             to real navigation rather than leaving a dead page */\n          if (!html) { window.location.href = url; return; }\n          /* Built off-screen - sold-out cards moved to the end of the whole\n             listing (stockFirst above) - and swapped in once, so the grid never\n             shows one order and then another. */\n          var tpl = document.createElement('template');\n          tpl.innerHTML = html;\n          var node = tpl.content.firstElementChild;\n          if (!node) { window.location.href = url; return; }\n          return sfWithin(stockFirst(node, sectionId, url))\n            .then(function (next) {\n              if (seq !== loadSeq) { return; }\n              var ng = node.querySelector('[data-tdhq-collection-grid]');\n              /* the grid stays settled: a filter, sort or page change arrives as one short fade of the whole grid\n                 (dtc-core.css is-arriving), not a card-by-card entrance (805 ms, 21 Oct) */\n              if (ng) {\n                ng.classList.add('is-arriving');\n                ng.addEventListener('animationend', function arrived(ev) {\n                  if (ev.target !== ng) { return; }\n                  ng.classList.remove('is-arriving');\n                  ng.removeEventListener('animationend', arrived);\n                });\n              }\n              if (ng && next) { sfApply(ng, next); }\n              sfRelease(ng);\n              keepHeaderThumb(wrap, node);\n              /* An open filter drawer stays open, where it was scrolled to,\n                 instead of sliding in again after every tick. */\n              var oldRoot = wrap.querySelector('[data-tdhq-collection]');\n              var newRoot = node.querySelector('[data-tdhq-collection]');\n              var oldPanel = wrap.querySelector('[data-tdhq-facets]');\n              var panelTop = oldPanel ? oldPanel.scrollTop : 0;\n              if (oldRoot && newRoot && oldRoot.classList.contains('is-facets-open')) { newRoot.classList.add('is-facets-open'); }\n              /* Swapping this markup in is safe by construction: the payload is our own\n                 theme's Liquid, server-rendered by Shopify on the SAME origin \u2014\n                 the fetch URL is location.pathname plus params from our own form\n                 and pager links, and Liquid escapes user input (e.g. filter\n                 values) server-side. This is shopify.dev's documented pattern for\n                 the Section Rendering API; do not route third-party or\n                 user-composed strings through this path. */\n              wrap.replaceWith(node);\n              var newPanel = node.querySelector('[data-tdhq-facets]');\n              if (push) history.pushState({ tdhqCollection: true }, '', url);\n              initCollectionUI();\n              /* After initCollectionUI has re-opened the lists and groups, so the saved scroll is not clipped by a\n                 still-collapsed rail (Codex filters-1021 F05). */\n              if (newPanel && panelTop) { newPanel.scrollTop = panelTop; }\n              var fresh = sectionWrap();\n              if (fresh) {\n                /* The swapped-in markup contains a brand new sort <select>, and\n                   `shopify:section:load` does NOT fire for the Section Rendering\n                   API on the storefront - only in the theme editor. Without this\n                   the custom dropdown silently reverted to a native one after the\n                   first filter. */\n                if (window.dtcSelectRefresh) { window.dtcSelectRefresh(fresh); }\n                /* Back to the top of the results only when the shopper has\n                   scrolled past it (a page link at the foot of the grid), and\n                   smoothly. Filtering near the top no longer jolts the page. */\n                if (fresh.getBoundingClientRect().top < 0) {\n                  var calm = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n                  fresh.scrollIntoView({ block: 'start', behavior: calm ? 'auto' : 'smooth' });\n                }\n                announceCount(fresh);\n                restoreFocus(focusHint, fresh);\n                announceSwap(fresh);\n              }\n            });\n        })\n        .catch(function (err) {\n          if (err && err.name === 'AbortError' && !timedOut) return;   /* replaced by a newer listing */\n          window.location.href = url; /* network trouble or no answer in 12 s: degrade to normal nav */\n        });\n    }\n\n    /* EVERY LINK THAT ONLY CHANGES THE LISTING RENDERS IN PLACE (audit LST-09).\n       Ticking a filter was a no-reload swap, but removing the same filter with\n       its chip, \"Clear all\", the in-stock chip, the brand band's \"Shop N in\n       stock\" and the empty state's page and filter links were plain links: a\n       white full reload and a jump to the top of the page. All of them are\n       Shopify's own url_to_add / url_to_remove (or the listing's own address\n       with a page or sort), so the section renders the same result without\n       leaving the page. */\n    var LISTING_LINKS = '.tdhq-pager a[href], .tdhq-chips a[href], a.tdhq-facets__clear, a.tdhq-collection__stockchip, ' +\n      '.tdhq-collection__brandactions a.tdhq-btn--primary, .tdhq-empty a[href*=\"sort_by=\"], ' +\n      /* the search results page, which uses the same rail (audit LST-13) */\n      '.dtc-collection__pager a[href], a[data-tdhq-listing-link]';\n    document.addEventListener('click', function (e) {\n      if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;\n      var a = e.target.closest(LISTING_LINKS);\n      if (!a || !a.closest('[data-tdhq-collection]')) return;\n      e.preventDefault();\n      load(a.href, true);\n    });\n\n    document.addEventListener('submit', function (e) {\n      var form = e.target.closest('[data-tdhq-facets-form]');\n      if (!form) return;\n      e.preventDefault();\n      /* Empty fields stay out of the URL: an untouched price range was\n         writing `filter.v.price.gte=&filter.v.price.lte=` into every sorted\n         or filtered address. */\n      var params = new URLSearchParams();\n      new FormData(form).forEach(function (value, key) {\n        if (typeof value === 'string' && value.trim() === '') { return; }\n        params.append(key, value);\n      });\n      var qs = params.toString();\n      var target = window.location.pathname + (qs ? '?' + qs : '');\n      /* The results button in the phone drawer submits the form the ticks have\n         already applied: the grid on show is that result, so it is not fetched\n         and faded in a second time. */\n      if (target === listedUrl) { return; }\n      load(target, true);\n    });\n\n    window.addEventListener('popstate', function () {\n      /* back/forward re-renders the state the URL describes - but an in-page\n         link (\"About the brand\" -> #about-brand) fires popstate too. Reloading\n         the grid for it scrolled the page back up to the results as soon as\n         it had reached the anchor (1,817px down, then back to 202px on\n         Bio Bombs; client report 2026-09-22). Only a change of path or query\n         is a new listing; a #fragment on the same listing is left alone. */\n      var now = window.location.pathname + window.location.search;\n      if (now === listedUrl) { return; }\n      if (sectionWrap()) load(window.location.href, false);\n    });\n\n    /* A grid rendered into the page (the page as first served, or the theme\n       editor re-rendering the section after a settings change): fill it\n       stock-first when the section says the order may still change\n       (data-sf-pending). The grid is claimed at once (data-sf-claimed), so the\n       section's own safety net, which shows the held cards if this script\n       never runs, stands down for THAT grid only. The claim used to be one\n       page-wide flag and only the first page load ran the pass, so after an\n       editor re-render the new grid's held cards were never shown: 21 of 24\n       GYEON cards stayed invisible (skeptic, editor re-render at 1440). The\n       held cards are always shown in the end, whatever the pass does. A grid\n       that is no longer pending (the net already fired) is left exactly as\n       the shopper sees it. */\n    function stockFirstInPlace(wrap) {\n      if (!wrap) { return; }\n      var g = wrap.querySelector('[data-tdhq-collection-grid][data-sf-pending]');\n      if (!g || g.hasAttribute('data-sf-claimed')) { return; }\n      g.setAttribute('data-sf-claimed', '');\n      var sectionId = wrap.id.replace('shopify-section-', '');\n      var job;\n      try { job = stockFirst(wrap, sectionId, window.location.href); }\n      catch (err) { job = Promise.resolve(null); }\n      sfWithin(job).then(function (next) {\n        if (!g.isConnected || !g.hasAttribute('data-sf-pending')) { return; }\n        try { if (next) { sfApply(g, next); } }\n        catch (err) { next = null; }\n        sfRelease(g);\n        if (next) { announceSwap(wrap); }\n      });\n    }\n    stockFirstInPlace(sectionWrap());\n\n    /* THE THEME EDITOR re-renders this section in place after every change\n       and fires shopify:section:load on the new markup (the Section Rendering\n       swaps above never fire it). The new grid gets the same pass, its filter\n       UI is wired (dtc-select.js rebuilds the sort on the same event), and the\n       lists fetched for the old settings are dropped (a new page size changes\n       every page). */\n    document.addEventListener('shopify:section:load', function (event) {\n      var sec = event.target;\n      if (!sec || !sec.querySelector || !sec.querySelector('[data-tdhq-collection]')) { return; }\n      sfCache = {};\n      listedUrl = window.location.pathname + window.location.search;\n      initCollectionUI();\n      stockFirstInPlace(sec.matches('[id^=\"shopify-section-\"]') ? sec : sec.closest('[id^=\"shopify-section-\"]'));\n    });\n  })();\n\n  /* ---------------------------------------------------------\n     CUSTOMERS ALSO BROWSE: ONE TREATMENT FOR EVERY TILE PICTURE\n\n     A tile shows a collection image or a product photo, and the rail fitted\n     every one inside a 16px inset on its grey square. Right for a packshot or\n     a logo on white, which melts into the grey; wrong for a photograph: Car\n     Care & Detailing's 3:2 shop photo sat as a 208px picture inside its 241px\n     tile beside four cut-outs that read edge to edge (audit shop-19). Liquid\n     knows an image's shape, not its colours, so once it loads this reads its\n     edges, the same test tdhq-quickadd.js makes for product cards:\n       - two opposite light edges: a packshot or logo. Fitted, as before.\n       - otherwise a photo no longer than 3:2 either way fills the tile;\n       - a longer photo stays whole with its edge colours as the bars.\n     If the canvas cannot be read the tile keeps the fitted default.\n     --------------------------------------------------------- */\n  /* Related-collection tile pictures are framed by the site-wide script\n     (snippets/tdhq-fit-script.liquid); the markup marks them. */\n\n  /* ---------------------------------------------------------\n     THE VARIANT A FILTER MATCHED\n     A product card links the product's one plain address (no listing tags\n     for a crawler to collect). When a size or colour filter matched one\n     variant the card carries its id in data-tdhq-v, and the click opens the\n     product on that variant. Capture phase, so it runs before any other\n     handler reads the link; a card without the attribute is untouched.\n     --------------------------------------------------------- */\n  function variantLink(e) {\n    var a = e.target.closest && e.target.closest('a[data-tdhq-v]');\n    if (!a || a.href.indexOf('variant=') > -1) return;\n    a.href = a.href.split('#')[0].split('?')[0] + '?variant=' + encodeURIComponent(a.getAttribute('data-tdhq-v'));\n  }\n  document.addEventListener('click', variantLink, true);\n  document.addEventListener('auxclick', variantLink, true);\n\n  /* ---------------------------------------------------------\n     PAGER: the current page number in view\n     A list of up to 15 pages prints every page number on one line that\n     scrolls sideways when it does not fit. Bring the current number to the\n     middle of that line (the line only: the page itself does not move).\n     --------------------------------------------------------- */\n  (function () {\n    var rail = document.querySelector('[data-tdhq-pager-nums]');\n    var cur = rail && rail.querySelector('.is-current');\n    if (!cur || rail.scrollWidth <= rail.clientWidth) return;\n    var r = rail.getBoundingClientRect();\n    var c = cur.getBoundingClientRect();\n    rail.scrollLeft += (c.left + c.width / 2) - (r.left + r.width / 2);\n  })();\n\n  /* ---------------------------------------------------------\n     COLLECTION DESCRIPTION: Read more\n     Delegated on document because the collection section is replaced with\n     outerHTML on every filter, sort and page, which would drop a listener\n     bound to the button. The button only shows on phones (tdhq-page.css).\n     --------------------------------------------------------- */\n  document.addEventListener('click', function (e) {\n    var btn = e.target.closest && e.target.closest('[data-tdhq-desc-toggle]');\n    if (!btn) return;\n    var desc = document.getElementById(btn.getAttribute('aria-controls'));\n    if (!desc) return;\n    var open = !desc.classList.contains('is-open');\n    var set = function (o) {\n      desc.classList.toggle('is-open', o);\n      btn.setAttribute('aria-expanded', o ? 'true' : 'false');\n      btn.textContent = o ? 'Read less' : 'Read more';\n    };\n    /* the FAQ answers' glide (TdhqMotion.resize); the fade stays on the moving edge while it closes */\n    if (window.TdhqMotion && window.TdhqMotion.resize) { window.TdhqMotion.resize(desc, set, open, false); } else { set(open); }\n  });\n\n  initForms(document);\n\n  // Editing a form section in the theme editor re-renders it, which discards\n  // the listeners bound above.\n  document.addEventListener('shopify:section:load', function (event) {\n    initForms(event.target);\n  });\n\n  /* ---------------------------------------------------------\n     POST-SUBMIT FOCUS\n     Shopify reloads the page after a contact-form post, so without this\n     the outcome is announced nowhere and the visitor is left at the top\n     of the page unsure whether anything happened.\n     --------------------------------------------------------- */\n  (function formOutcome() {\n    var target = document.querySelector('[data-tdhq-form-err]') ||\n                 document.querySelector('[data-tdhq-form-ok]');\n    if (!target) return;\n\n    target.focus({ preventScroll: true });\n    target.scrollIntoView({ block: 'center', behavior: 'auto' });\n  })();\n})();\n\n/* ============================================================\n   BLOG PAGES CHANGE IN PLACE (owner 21 Oct: \"when you change pages in blogs its super bad now and not smooth at\n   all\"). The pager's links were full page loads that landed on the big banner again. A pager link now swaps only\n   the results region (sections/dtc-blog.liquid #blog-results) through the Section Rendering API, the documented\n   pattern also used for the collection grid: the banner and the filters stay, the next page is warmed on hover or\n   touch, the old results dim only if the answer takes over 120ms, the new page fades in, the view moves to the\n   results when they are off screen, and focus goes to the article count. The address changes with pushState and\n   Back/Forward restore both the page and where the reader was. The links stay real ?page=N addresses: a modified\n   click, no script, an error or an unexpected answer is an ordinary page load.\n   ============================================================ */\n(function () {\n  'use strict';\n  if (!('fetch' in window) || !window.history || !history.pushState || !('content' in document.createElement('template'))) { return; }\n  var SEL = '[data-tdhq-blog-results]';\n  function region() { return document.querySelector(SEL); }\n  if (!region()) { return; }\n  var warm = {};\n  var ctl = null;\n  var seq = 0;\n  var listed = location.pathname + location.search;\n\n  function state(extra) {\n    var s = {};\n    var cur = history.state;\n    if (cur && typeof cur === 'object') { for (var k in cur) { if (Object.prototype.hasOwnProperty.call(cur, k)) { s[k] = cur[k]; } } }\n    for (var j in extra) { if (Object.prototype.hasOwnProperty.call(extra, j)) { s[j] = extra[j]; } }\n    return s;\n  }\n  try { history.replaceState(state({ tdhqBlog: 1, y: window.scrollY }), ''); } catch (e) {}\n  /* the entry keeps where the reader scrolled to, so Forward comes back there, not to the top (Codex 21 Oct) */\n  var yTimer = 0;\n  window.addEventListener('scroll', function () {\n    window.clearTimeout(yTimer);\n    yTimer = window.setTimeout(function () {\n      if (!region()) { return; }\n      try { history.replaceState(state({ tdhqBlog: 1, y: window.scrollY }), ''); } catch (e) {}\n    }, 300);\n  }, { passive: true });\n\n  function sectionUrl(url) {\n    var r = region();\n    var wrap = r && r.closest('[id^=\"shopify-section-\"]');\n    if (!wrap) { return null; }\n    var u = new URL(url, location.origin);\n    u.searchParams.set('section_id', wrap.id.replace('shopify-section-', ''));\n    return u.toString();\n  }\n  function get(url) {\n    var su = sectionUrl(url);\n    if (!su) { return Promise.reject(new Error('no section')); }\n    if (!warm[su]) {\n      /* 12 s at most, then the page loads normally (Codex 21 Oct: a stalled request left the list dimmed) */\n      var ctl = ('AbortController' in window) ? new AbortController() : null;\n      var guard = ctl ? window.setTimeout(function () { ctl.abort(); }, 12000) : 0;\n      warm[su] = fetch(su, ctl ? { credentials: 'same-origin', signal: ctl.signal } : { credentials: 'same-origin' }).then(function (res) {\n        window.clearTimeout(guard);\n        if (!res.ok) { throw new Error('HTTP ' + res.status); }\n        return res.text();\n      });\n      warm[su].catch(function () { delete warm[su]; });\n    }\n    return warm[su];\n  }\n\n  function load(url, push, restoreY) {\n    var r = region();\n    if (!r) { location.href = url; return; }\n    var my = ++seq;\n    /* the page being loaded is the page listed from now on (as the collection pager): Back then Forward before\n       the first answer came used to show page 1 under a page 2 address (Codex 21 Oct) */\n    try { var lu = new URL(url, location.origin); listed = lu.pathname + lu.search; } catch (e) {}\n    var busy = window.setTimeout(function () { if (my === seq) { r.classList.add('is-updating'); r.setAttribute('aria-busy', 'true'); } }, 120);\n    get(url).then(function (html) {\n      if (my !== seq) { return; }\n      window.clearTimeout(busy);\n      var tpl = document.createElement('template');\n      tpl.innerHTML = html;\n      var fresh = tpl.content.querySelector(SEL);\n      if (!fresh) { location.href = url; return; }\n      var cur = region();\n      if (!cur) { location.href = url; return; }\n      fresh.classList.add('is-arriving');\n      cur.replaceWith(fresh);\n      fresh.addEventListener('animationend', function arrived(ev) {\n        if (ev.target !== fresh) { return; }   /* a card picture's own fade-in bubbles up first */\n        fresh.classList.remove('is-arriving');\n        fresh.removeEventListener('animationend', arrived);\n      });\n      listed = new URL(url, location.origin).pathname + new URL(url, location.origin).search;\n      if (push) { history.pushState({ tdhqBlog: 1, y: 0 }, '', url); }\n      /* the title follows the page, in the server's own \"| Page N |\" form */\n      var pg = Number(new URL(url, location.origin).searchParams.get('page')) || 1;\n      var tt = document.title.replace(/ \\| Page \\d+(?= \\|)/, '');\n      if (pg > 1) { tt = tt.indexOf(' | ') > -1 ? tt.replace(/ \\| (?!.* \\| )/, ' | Page ' + pg + ' | ') : tt + ' | Page ' + pg; }\n      document.title = tt;\n      var calm = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n      if (typeof restoreY === 'number') {\n        window.scrollTo(0, restoreY);\n      } else {\n        var top = fresh.getBoundingClientRect().top;\n        if (top < 0 || top > window.innerHeight * 0.6) { fresh.scrollIntoView({ block: 'start', behavior: calm ? 'auto' : 'smooth' }); }\n      }\n      var count = fresh.querySelector('.dtc-blog__count');\n      if (count && typeof restoreY !== 'number') {\n        count.setAttribute('tabindex', '-1');\n        count.focus({ preventScroll: true });\n      }\n    }).catch(function () {\n      window.clearTimeout(busy);\n      if (my === seq) { location.href = url; }\n    });\n  }\n\n  function pagerLink(e) {\n    var a = e.target && e.target.closest ? e.target.closest(SEL + ' .dtc-blog__pager a[href]') : null;\n    if (!a || a.origin !== location.origin) { return null; }\n    return a;\n  }\n  ['pointerenter', 'focusin', 'touchstart'].forEach(function (type) {\n    document.addEventListener(type, function (e) { var a = pagerLink(e); if (a) { get(a.href).catch(function () {}); } }, { capture: true, passive: true });\n  });\n  document.addEventListener('click', function (e) {\n    if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) { return; }\n    var a = pagerLink(e);\n    if (!a) { return; }\n    e.preventDefault();\n    try { history.replaceState(state({ tdhqBlog: 1, y: window.scrollY }), ''); } catch (err) {}\n    load(a.href, true);\n  });\n  window.addEventListener('popstate', function (e) {\n    if (!region()) { return; }\n    var now = location.pathname + location.search;\n    if (now === listed) { return; }\n    var st = e.state;\n    load(location.href, false, st && typeof st.y === 'number' ? st.y : undefined);\n  });\n})();\n"],
  "mappings": "CAUC,UAAY,CACX,aAEA,GAAI,OAAO,iBAAkB,OAC7B,OAAO,iBAAmB,GAK1B,SAAS,sBAAsB,MAAO,CAIpC,IAAI,OAAS,MAAM,cAAc,kDAAkD,EAC/E,OAAS,MAAM,iBAAiB,kBAAkB,EAClD,sBAAwB,MAAM,iBAAiB,2BAA2B,EAC9E,GAAI,CAAC,QAAW,CAAC,OAAO,QAAU,CAAC,sBAAsB,OAAS,OAElE,SAAS,OAAQ,CACf,IAAI,MAAQ,aAAa,MAAM,EAC/B,MAAM,UAAU,QAAQ,KAAK,OAAQ,SAAU,MAAO,CACpD,IAAI,QAAU,MAAM,aAAa,gBAAgB,EAAE,MAAM,GAAG,EAAE,IAAI,SAAU,EAAG,CAC7E,OAAO,EAAE,KAAK,CAChB,CAAC,EACG,KAAO,QAAQ,QAAQ,KAAK,IAAM,GACtC,MAAM,OAAS,CAAC,KAKhB,MAAM,UAAU,QAAQ,KAAK,MAAM,iBAAiB,yBAAyB,EAAG,SAAU,MAAO,CAC/F,MAAM,SAAW,CAAC,KACb,OACC,MAAM,UAAY,SAAY,MAAM,cAAgB,EACjD,MAAM,MAAQ,GAEzB,CAAC,CACH,CAAC,CACH,CAYA,SAAS,eAAe,IAAK,CAC3B,IAAI,EAAI,IAAI,QAAQ,GAAG,EACnB,MAAQ,EAAI,GAAK,IAAI,MAAM,EAAG,CAAC,EAAE,KAAK,EAAI,GAC1C,QAAU,EAAI,GAAK,IAAI,MAAM,EAAI,CAAC,EAAI,KAAK,MAAM,GAAG,EAAE,IAAI,SAAU,EAAG,CAAE,OAAO,EAAE,KAAK,CAAG,CAAC,EAC/F,MAAO,CAAE,MAAO,MAAO,OAAQ,MAAO,CACxC,CAEA,SAAS,cAAc,KAAM,CAC3B,OAAK,MACE,MAAM,cAAc,kBAAoB,KAAK,QAAQ,KAAM,EAAE,EAAI,KAAK,GAAK,MACpF,CAMA,SAAS,aAAa,IAAK,CACzB,GAAI,CAAC,IAAO,MAAO,GACnB,GAAI,IAAI,OAAS,SAAW,IAAI,KAAM,CACpC,IAAI,OAAS,MAAM,cAAc,UAAY,IAAI,KAAK,QAAQ,KAAM,EAAE,EAAI,YAAY,EACtF,OAAO,OAAS,OAAO,MAAQ,EACjC,CACA,OAAO,IAAI,KACb,CAEA,SAAS,eAAgB,CACvB,MAAM,UAAU,QAAQ,KAAK,sBAAuB,SAAU,MAAO,CACnE,IAAI,KAAO,eAAe,MAAM,aAAa,yBAAyB,GAAK,EAAE,EACzE,IAAM,cAAc,KAAK,KAAK,EAC9B,KAAO,CAAC,CAAC,KAAO,KAAK,OAAO,QAAQ,aAAa,GAAG,CAAC,IAAM,GAG3D,MAAM,SAAU,KAAO,IAC3B,MAAM,UAAU,QAAQ,KAAK,MAAM,iBAAiB,yBAAyB,EAAG,SAAU,MAAO,CAC/F,MAAM,SAAW,KACjB,MAAM,aAAa,gBAAiB,KAAO,OAAS,OAAO,CAC7D,CAAC,CACH,CAAC,CACH,CAEA,IAAI,SAAW,UAAY,CAAE,MAAM,EAAG,cAAc,CAAG,EACvD,OAAO,iBAAiB,SAAU,QAAQ,EAG1C,IAAI,QAAU,CAAC,EACf,MAAM,UAAU,QAAQ,KAAK,sBAAuB,SAAU,MAAO,CACnE,IAAI,KAAO,eAAe,MAAM,aAAa,yBAAyB,GAAK,EAAE,EACzE,IAAM,cAAc,KAAK,KAAK,EAC9B,KAAO,MAAQ,QAAU,QAAQ,QAAQ,GAAG,IAAM,KACpD,QAAQ,KAAK,GAAG,EAKZ,IAAI,OAAS,QAAW,MAAM,iBAAiB,SAAU,aAAa,EACnE,IAAI,iBAAiB,SAAU,aAAa,EAEvD,CAAC,EAGD,SAAS,EAcT,SAAS,sBAAuB,CAG9B,QAFI,IAAM,MAAM,iBAAiB,yBAAyB,EACtD,OAAS,GACJ,EAAI,EAAG,EAAI,IAAI,OAAQ,IAAK,CACnC,GAAI,IAAI,CAAC,IAAM,OAAQ,CAAE,OAAS,GAAM,QAAU,CAClD,GAAI,GAAC,QAAU,IAAI,CAAC,EAAE,UAAY,IAAI,CAAC,EAAE,OAAS,UAClD,KAAI,IAAM,IAAI,CAAC,EAAE,sBAAsB,EACvC,GAAI,GAAC,IAAI,OAAS,CAAC,IAAI,QAIvB,IAAI,CAAE,IAAI,CAAC,EAAE,MAAM,CAAE,cAAe,EAAK,CAAC,CAAG,OAAS,IAAK,CAAE,IAAI,CAAC,EAAE,MAAM,CAAG,CAC7E,QACF,CACF,CAEA,SAAS,UAAU,MAAO,UAAW,CACnC,GAAI,CAAC,OAAS,CAAC,OAAO,QAAW,MAAO,GACxC,QAAS,EAAI,EAAG,EAAI,OAAO,QAAQ,OAAQ,IACzC,GAAI,OAAO,QAAQ,CAAC,EAAE,QAAU,MAChC,OAAI,OAAO,QAAU,QACnB,OAAO,MAAQ,MAGf,OAAO,cAAc,IAAI,MAAM,SAAU,CAAE,QAAS,EAAK,CAAC,CAAC,GAEzD,WAAa,qBAAqB,EAC/B,GAET,MAAO,EACT,CAEA,SAAS,WAAW,OAAQ,CAC1B,GAAI,CAAE,OAAO,IAAI,gBAAgB,MAAM,EAAE,IAAI,QAAQ,GAAK,EAAI,OACvD,IAAK,CAAE,MAAO,EAAI,CAC3B,CAEK,OAAO,OAAS,UAAU,WAAW,OAAO,SAAS,MAAM,EAAG,EAAI,EAEvE,SAAS,iBAAiB,QAAS,SAAU,EAAG,CAC9C,GAAI,IAAE,kBAAoB,EAAE,SAAW,EAAE,SAAW,EAAE,UAAY,EAAE,OAAS,GAC7E,KAAI,KAAO,EAAE,QAAU,EAAE,OAAO,QAAU,EAAE,OAAO,QAAQ,SAAS,EAAI,KACxE,GAAI,GAAC,MAAQ,KAAK,SAAW,UAC7B,KAAI,IACJ,GAAI,CAAE,IAAM,IAAI,IAAI,KAAK,KAAM,OAAO,SAAS,IAAI,CAAG,OAAS,IAAK,CAAE,MAAQ,CAG9E,GAAI,IAAI,WAAa,OAAO,SAAS,SACrC,KAAI,KAAO,WAAW,IAAI,MAAM,EAChC,GAAI,GAAC,MAAQ,CAAC,UAAU,KAAM,EAAK,GACnC,GAAE,eAAe,EACjB,IAAI,OAAS,IAAI,KAAO,SAAS,eAAe,IAAI,KAAK,MAAM,CAAC,CAAC,EAAI,KACrE,GAAI,OAAQ,CACV,IAAI,MAAQ,OAAO,WAAW,kCAAkC,EAAE,QAClE,OAAO,eAAe,CAAE,SAAU,MAAQ,OAAS,SAAU,MAAO,OAAQ,CAAC,CAC/E,CACA,qBAAqB,EAGrB,GAAI,CAAE,OAAO,QAAQ,aAAa,KAAM,GAAI,IAAI,SAAW,IAAI,OAAS,IAAI,IAAI,CAAG,OAAS,IAAK,CAAC,KACpG,CAAC,CACH,CAEA,SAAS,UAAU,KAAM,CACvB,IAAI,MAAQ,KAAK,iBAAiB,kBAAkB,EAChD,MAAM,OACR,MAAM,UAAU,QAAQ,KAAK,MAAO,qBAAqB,EAChD,OAAS,UAElB,sBAAsB,QAAQ,CAElC,CA4BA,IAAI,aAAe,OAAO,WAAW,oBAAoB,EACrD,mBAAqB,KAEzB,SAAS,aAAc,CACrB,IAAI,KAAO,SAAS,cAAc,wBAAwB,EAC1D,GAAI,CAAC,KAAQ,OAAO,KACpB,IAAI,OAAS,KAAK,cAAc,2BAA2B,EACvD,MAAQ,KAAK,cAAc,oBAAoB,EACnD,MAAI,CAAC,QAAU,CAAC,MAAgB,KACzB,CAAE,KAAM,KAAM,OAAQ,OAAQ,MAAO,KAAM,CACpD,CAWA,IAAI,aAAe,GACnB,SAAS,eAAe,GAAI,CACtB,KAAO,eACX,aAAe,GACf,SAAS,gBAAgB,UAAU,OAAO,kBAAmB,EAAE,EACjE,CAEA,SAAS,cAAc,GAAI,CACzB,IAAI,EAAI,YAAY,EACpB,GAAI,CAAC,EAAG,CAAE,eAAe,EAAK,EAAG,MAAQ,CACzC,EAAE,KAAK,UAAU,OAAO,iBAAkB,EAAE,EAC5C,EAAE,OAAO,aAAa,gBAAiB,GAAK,OAAS,OAAO,EAC5D,IAAI,MAAQ,IAAM,aAAa,QAC/B,eAAe,KAAK,EAChB,OACF,EAAE,MAAM,aAAa,OAAQ,QAAQ,EACrC,EAAE,MAAM,aAAa,aAAc,MAAM,EACzC,EAAE,MAAM,aAAa,kBAAmB,mBAAmB,IAE3D,EAAE,MAAM,gBAAgB,MAAM,EAC9B,EAAE,MAAM,gBAAgB,YAAY,EACpC,EAAE,MAAM,gBAAgB,iBAAiB,EAE7C,CAEA,SAAS,kBAAmB,CAC1B,IAAI,EAAI,YAAY,EACpB,MAAO,CAAC,EAAE,GAAK,aAAa,SAAW,EAAE,KAAK,UAAU,SAAS,gBAAgB,EACnF,CAEA,SAAS,mBAAoB,CAC3B,mBAAqB,GACrB,cAAc,EAAK,EACnB,IAAI,EAAI,YAAY,EAChB,GAAK,EAAE,OAAO,MAAM,CAAE,cAAe,EAAK,CAAC,CACjD,CAKA,SAAS,iBAAiB,QAAS,SAAU,EAAG,CAC9C,GAAK,EAAE,OAAO,QACd,IAAI,EAAE,OAAO,QAAQ,0BAA0B,EAAG,CAChD,EAAE,eAAe,EACjB,kBAAkB,EAClB,MACF,CACA,GAAI,EAAE,OAAO,QAAQ,0BAA0B,GAAK,iBAAiB,EAAG,CAGtE,IAAI,UAAY,EAAE,OAAO,QAAQ,MAAM,GACnC,CAAC,WAAa,UAAU,cAAc,IAAK,kBAAkB,CACnE,EACF,CAAC,EAED,SAAS,iBAAiB,UAAW,SAAU,EAAG,CAChD,GAAK,iBAAiB,EACtB,KAAI,EAAI,YAAY,EACpB,GAAI,EAAE,MAAQ,SAAU,CAEtB,GAAI,EAAE,iBAAoB,OAC1B,EAAE,eAAe,EACjB,kBAAkB,EAClB,MACF,CACA,GAAI,EAAE,MAAQ,MACd,KAAI,EAAI,MAAM,UAAU,OAAO,KAC7B,EAAE,MAAM,iBAAiB,+IAA+I,EACxK,SAAU,EAAG,CAAE,OAAO,EAAE,eAAiB,MAAQ,IAAM,SAAS,aAAe,CACjF,EACA,GAAK,EAAE,OACP,KAAI,MAAQ,EAAE,CAAC,EAAG,KAAO,EAAE,EAAE,OAAS,CAAC,EACvC,GAAI,CAAC,EAAE,MAAM,SAAS,SAAS,aAAa,EAAG,CAAE,EAAE,eAAe,EAAG,MAAM,MAAM,EAAG,MAAQ,CACxF,EAAE,UAAY,SAAS,gBAAkB,OAAS,EAAE,eAAe,EAAG,KAAK,MAAM,GAC5E,CAAC,EAAE,UAAY,SAAS,gBAAkB,OAAQ,EAAE,eAAe,EAAG,MAAM,MAAM,KAC7F,CAAC,EAMD,SAAS,uBAAwB,CAC/B,GAAI,CAAC,aAAa,QAAS,CAAE,cAAc,EAAI,EAAG,MAAQ,CAC1D,cAAc,qBAAuB,EAAI,CAC3C,CAKA,SAAS,0BAA2B,CAClC,mBAAqB,KACrB,sBAAsB,CACxB,CAEI,aAAa,iBAAoB,aAAa,iBAAiB,SAAU,wBAAwB,EAC5F,aAAa,aAAe,aAAa,YAAY,wBAAwB,EAiBtF,IAAI,eAAiB,CAAC,EAEtB,SAAS,aAAa,IAAK,KAAM,KAAM,CACrC,KAAK,UAAU,OAAO,cAAe,IAAI,EACzC,IAAI,aAAa,gBAAiB,KAAO,OAAS,OAAO,EACzD,IAAI,YAAc,IAAI,aAAa,KAAO,kBAAoB,iBAAiB,GAAK,IAAI,WAC1F,CAKA,IAAI,gBAAkB,CAAC,EACvB,SAAS,iBAAiB,QAAS,SAAU,EAAG,CAC9C,IAAI,IAAM,EAAE,OAAO,SAAW,EAAE,OAAO,QAAQ,0CAA0C,EACzF,GAAK,IACL,KAAI,EAAI,IAAI,WACZ,gBAAgB,EAAE,aAAa,uBAAuB,CAAC,EAAI,CAAC,EAAE,KAChE,EAAG,EAAI,EAEP,SAAS,gBAAgB,KAAM,CAC7B,MAAM,UAAU,QAAQ,KAAK,KAAK,iBAAiB,gCAAgC,EAAG,SAAU,EAAG,CACjG,IAAI,IAAM,EAAE,aAAa,uBAAuB,EAC5C,OAAO,UAAU,eAAe,KAAK,gBAAiB,GAAG,IAAK,EAAE,KAAO,gBAAgB,GAAG,EAChG,CAAC,CACH,CAEA,SAAS,eAAe,KAAM,CAC5B,gBAAgB,IAAI,EACpB,MAAM,UAAU,QAAQ,KAAK,KAAK,iBAAiB,yBAAyB,EAAG,SAAU,IAAK,CAC5F,IAAI,KAAO,SAAS,eAAe,IAAI,aAAa,eAAe,CAAC,EACpE,GAAK,KACL,KAAI,IAAM,KAAK,aAAa,iBAAiB,GAAK,KAAK,GACnD,KAAO,OAAO,UAAU,eAAe,KAAK,eAAgB,GAAG,EAAI,eAAe,GAAG,EAAI,KAAK,UAAU,SAAS,aAAa,EAClI,aAAa,IAAK,KAAM,IAAI,EAC9B,CAAC,CACH,CASA,SAAS,iBAAiB,QAAS,SAAU,EAAG,CAC9C,IAAI,IAAM,EAAE,OAAO,SAAW,EAAE,OAAO,QAAQ,yBAAyB,EACxE,GAAK,IACL,KAAI,KAAO,SAAS,eAAe,IAAI,aAAa,eAAe,CAAC,EACpE,GAAK,KACL,KAAI,KAAO,IAAI,aAAa,eAAe,IAAM,OAC7C,KAAO,IAAI,QAAQ,oBAAoB,EAC3C,eAAe,KAAK,aAAa,iBAAiB,GAAK,KAAK,EAAE,EAAI,KAGlE,IAAI,WAAa,UAAY,CAC3B,GAAI,QAAQ,CAAC,MAAQ,KAAK,cAAgB,KAAK,cAC/C,KAAI,EAAI,KAAK,sBAAsB,EAAG,EAAI,IAAI,sBAAsB,EAChE,KAAO,KAAK,cAAc,oBAAoB,EAC9C,OAAS,EAAE,QAAU,KAAO,KAAK,aAAe,GAAK,GACrD,EAAE,IAAM,EAAE,IAAM,GAAM,KAAK,WAAa,EAAE,IAAM,GAAK,EAAE,IAClD,EAAE,OAAS,SAAU,KAAK,WAAa,EAAE,OAAS,QAC7D,EAGA,IAAI,aAAa,gBAAiB,KAAO,OAAS,OAAO,EACzD,IAAI,YAAc,IAAI,aAAa,KAAO,kBAAoB,iBAAiB,GAAK,IAAI,YACxF,IAAI,MAAQ,SAAU,EAAG,CAAE,KAAK,UAAU,OAAO,cAAe,CAAC,CAAG,EAChE,EAAI,OAAO,WACf,GAAI,CAAC,GAAK,CAAC,EAAE,OAAQ,CAAE,MAAM,IAAI,EAAG,WAAW,EAAG,MAAQ,CAC1D,IAAI,KAAO,EAAE,OAAO,KAAM,MAAO,KAAM,GAAM,UAAU,EAQvD,GAPI,MAAQ,MACV,MAAM,UAAU,MAAM,KAAK,KAAK,SAAU,CAAC,EAAE,QAAQ,SAAU,IAAK,CAClE,IAAI,QAAQ,CAAC,CAAE,QAAS,CAAE,EAAG,CAAE,QAAS,CAAE,CAAC,EAAG,CAAE,SAAU,EAAE,GAAG,WAAY,GAAG,EAAG,OAAQ,EAAE,OAAO,CAAE,CAAC,CACvG,CAAC,EAIC,MAAQ,EAAE,SAAW,EAAG,CAC1B,IAAI,SAAW,KAAK,SAAS,CAAC,GAAK,KAAK,SAAS,CAAC,EAAE,cAAc,uBAAuB,EACrF,UAAY,SAAS,MAAM,CAAE,cAAe,EAAK,CAAC,CACxD,GACF,CAAC,EAED,SAAS,kBAAmB,CAC1B,IAAI,KAAO,SAAS,cAAc,wBAAwB,EAC1D,GAAI,GAAC,MAAQ,KAAK,QAAQ,aAC1B,MAAK,QAAQ,YAAc,IAC3B,eAAe,IAAI,EACnB,IAAI,OAAS,KAAK,cAAc,2BAA2B,EACvD,MAAQ,KAAK,cAAc,oBAAoB,EACnD,GAAI,GAAC,QAAU,CAAC,OAEhB,QAAO,iBAAiB,QAAS,UAAY,CAC3C,IAAI,YAAc,CAAC,KAAK,UAAU,SAAS,gBAAgB,EAG3D,GAFA,mBAAqB,YACrB,cAAc,WAAW,EACrB,YAAa,CAIf,IAAI,MAAQ,MAAM,cAAc,qDAAqD,EACjF,OAAO,MAAM,MAAM,CAAE,cAAe,EAAK,CAAC,CAChD,CACF,CAAC,EAED,sBAAsB,EAMtB,IAAI,KAAO,KAAK,cAAc,kBAAkB,EAC5C,KAAO,KAAK,cAAc,yBAAyB,EACnD,MAAQ,MACV,KAAK,iBAAiB,SAAU,UAAY,CACtC,OAAO,KAAK,eAAkB,WAAY,KAAK,cAAc,EAC5D,KAAK,OAAO,CACnB,CAAC,EAQH,MAAQ,KAAK,iBAAiB,SAAU,UAAY,CAClD,IAAI,GAAK,KAAK,cAAc,kCAAkC,EAC1D,GAAK,KAAK,cAAc,kCAAkC,EAC9D,GAAI,IAAM,IAAM,GAAG,QAAU,IAAM,GAAG,QAAU,IAAM,OAAO,GAAG,KAAK,EAAI,OAAO,GAAG,KAAK,EAAG,CACzF,IAAI,EAAI,GAAG,MAAO,GAAG,MAAQ,GAAG,MAAO,GAAG,MAAQ,CACpD,CACF,EAAG,EAAI,EACP,IAAI,SACJ,MAAQ,KAAK,iBAAiB,SAAU,SAAU,EAAG,CAC/C,EAAE,OAAO,OAAS,YAAc,EAAE,OAAO,OAAS,WACtD,aAAa,QAAQ,EACrB,SAAW,WAAW,UAAY,CAC5B,OAAO,KAAK,eAAkB,WAAY,KAAK,cAAc,EAC5D,KAAK,OAAO,CACnB,EAAG,GAAG,EACR,CAAC,GACH,CACA,iBAAiB,GAehB,UAA0B,CACzB,GAAI,EAAE,UAAW,SAAW,CAAC,OAAO,SAAW,CAAC,OAAO,QAAQ,UAAW,OAE1E,IAAI,SAAW,KACX,QAAU,EAcV,QAAU,CAAC,EACf,SAAS,MAAM,IAAK,CAClB,OAAK,QAAQ,GAAG,IACd,QAAQ,GAAG,EAAI,MAAM,GAAG,EAAE,KAAK,SAAU,EAAG,CAC1C,GAAI,CAAC,EAAE,GAAM,MAAM,IAAI,MAAM,QAAU,EAAE,MAAM,EAC/C,OAAO,EAAE,KAAK,CAChB,CAAC,EACD,QAAQ,GAAG,EAAE,MAAM,UAAY,CAAE,OAAO,QAAQ,GAAG,CAAG,CAAC,GAElD,QAAQ,GAAG,CACpB,CACA,SAAS,QAAQ,KAAM,CACrB,IAAI,IAAM,SAAS,cAAc,UAAU,EAC3C,IAAI,UAAY,MAAQ,GACxB,IAAI,EAAI,IAAI,QAAQ,cAAc,6BAA6B,EAC/D,OAAO,EAAI,MAAM,UAAU,MAAM,KAAK,EAAE,QAAQ,EAAI,CAAC,CACvD,CACA,SAAS,QAAQ,KAAM,CACrB,OAAO,KAAK,UAAU,SAAS,iBAAiB,GAAK,CAAC,CAAC,KAAK,cAAc,kBAAkB,CAC9F,CACA,SAAS,MAAM,KAAM,CACnB,IAAI,EAAI,KAAK,cAAc,uBAAuB,EAClD,OAAO,EAAI,EAAE,aAAa,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC,EAAI,EACpD,CAWA,SAAS,WAAW,KAAM,UAAW,QAAS,CAC5C,IAAI,EAAI,KAAK,cAAc,4CAA4C,EACvE,GAAI,CAAC,EAAK,OAAO,QAAQ,QAAQ,IAAI,EACrC,IAAI,EAAI,EAAE,QACN,IAAM,CAAC,EAAE,KAAM,KAAO,CAAC,EAAE,MAAO,MAAQ,CAAC,EAAE,QAAS,KAAO,CAAC,EAAE,OAAQ,KAAO,CAAC,EAAE,OACpF,GAAI,EAAE,IAAM,GAAK,MAAQ,KAAO,KAAO,GAAK,KAAO,GAAM,OAAO,QAAQ,QAAQ,IAAI,EACpF,IAAI,OAAS,KAAO,GAAK,KACrB,IAAM,KAAK,IAAI,KAAO,KAAM,KAAK,EACrC,GAAI,OAAS,MAAS,OAAO,QAAQ,QAAQ,IAAI,EACjD,IAAI,QAAU,MAAM,UAAU,MAAM,KAAK,EAAE,QAAQ,EAGnD,GAAI,OAAS,GAAK,CAAC,QAAQ,KAAK,OAAO,EAAK,OAAO,QAAQ,QAAQ,IAAI,EACvE,IAAI,IAAM,KAAK,IAAI,EAAG,IAAM,KAAO,KAAK,EACpC,QAAU,KAAK,IAAI,EAAG,KAAK,IAAI,IAAK,GAAG,EAAI,KAAK,EAChD,QAAU,KAAK,IAAI,MAAO,GAAG,EAAI,IACjC,SAAW,IAAM,KAAK,IAAI,MAAO,GAAG,EACpC,SAAW,SAAW,EAAI,KAAK,MAAM,QAAU,SAAW,KAAO,IAAI,EAAI,EAC7E,GAAI,SAAW,GAAM,OAAO,QAAQ,QAAQ,IAAI,EAEhD,SAAS,QAAQ,MAAO,EAAG,CACzB,IAAI,EAAI,IAAI,IAAI,QAAS,OAAO,SAAS,MAAM,EAC/C,SAAE,aAAa,OAAO,MAAM,EAC5B,EAAE,aAAa,OAAO,UAAU,EAChC,EAAE,aAAa,OAAO,EAAE,OAAO,EAC/B,EAAE,aAAa,OAAO,EAAE,QAAS,KAAK,EAClC,EAAI,GAAK,EAAE,aAAa,IAAI,OAAQ,OAAO,CAAC,CAAC,EACjD,EAAE,aAAa,IAAI,WAAY,SAAS,EACjC,EAAE,SAAW,IAAM,EAAE,aAAa,SAAS,CACpD,CAMA,QAJI,MAAQ,QAAU,EAClB,MAAM,QAAQ,EAAE,UAAW,IAAI,CAAC,EAAE,KAAK,SAAU,KAAM,CAAE,OAAO,QAAQ,KAAK,SAAS,CAAC,EAAE,MAAM,EAAG,OAAO,CAAG,CAAC,EAC7G,QAAQ,QAAQ,CAAC,CAAC,EAClB,QAAU,CAAC,EACN,EAAI,EAAG,GAAK,SAAU,IAAO,QAAQ,KAAK,MAAM,QAAQ,EAAE,WAAY,CAAC,CAAC,CAAC,EAClF,IAAI,OAAS,QAAQ,IAAI,OAAO,EAAE,KAAK,SAAU,KAAM,CACrD,IAAI,MAAQ,CAAC,EACb,YAAK,QAAQ,SAAU,KAAM,CAAE,MAAQ,MAAM,OAAO,QAAQ,KAAK,SAAS,CAAC,EAAE,OAAO,OAAO,CAAC,CAAG,CAAC,EACzF,MAAM,MAAM,QAAS,QAAU,QAAQ,CAChD,CAAC,EAED,OAAO,QAAQ,IAAI,CAAC,MAAO,MAAM,CAAC,EAAE,KAAK,SAAU,MAAO,CACxD,IAAI,KAAO,MAAM,CAAC,EAAE,OAAO,MAAM,CAAC,CAAC,EAGnC,GAAI,KAAK,SAAW,IAAM,MAAS,OAAO,KAC1C,IAAI,KAAO,KAAK,SAAW,QAAQ,QAAU,KAAK,MAAM,SAAU,EAAG,EAAG,CAAE,OAAO,MAAM,CAAC,IAAM,MAAM,QAAQ,CAAC,CAAC,CAAG,CAAC,EAClH,OAAO,KAAO,KAAO,IACvB,CAAC,CACH,CAGA,SAAS,QAAQ,KAAM,CACrB,OAAO,KAAK,aAAe,OAAO,iBAAiB,IAAI,EAAE,aAAe,SAC1E,CAQA,SAAS,QAAQ,EAAG,KAAM,CACxB,IAAI,QAAU,MAAM,UAAU,MAAM,KAAK,EAAE,QAAQ,EAC/C,MAAQ,CAAC,EACb,QAAQ,QAAQ,SAAU,EAAG,CAAE,IAAI,EAAI,MAAM,CAAC,EAAO,GAAK,CAAC,MAAM,CAAC,IAAK,MAAM,CAAC,EAAI,EAAK,CAAC,EAoBxF,QAnBI,SAAW,QAAQ,KAAK,SAAU,EAAG,CACvC,OAAO,EAAE,UAAU,SAAS,OAAO,GAAK,CAAC,CAAC,EAAE,cAAc,QAAQ,CACpE,CAAC,EACG,QAAU,KAAK,IAAI,SAAU,EAAG,CAClC,IAAI,EAAI,MAAM,CAAC,EACf,GAAI,GAAK,MAAM,CAAC,EAAG,CAAE,IAAI,KAAO,MAAM,CAAC,EAAG,cAAO,MAAM,CAAC,EAAU,IAAM,CACxE,OAAI,WACE,EAAE,WAAa,OAAO,EAAE,SAAS,EAAE,QAAQ,QAAQ,EAAI,IAAM,EAAE,UAAU,IAAI,OAAO,EACxF,MAAM,UAAU,QAAQ,KAAK,EAAE,iBAAiB,mBAAmB,EAAG,SAAU,EAAG,CAAE,EAAE,UAAU,IAAI,OAAO,CAAG,CAAC,GAE3G,CACT,CAAC,EAMG,MAAQ,QAAQ,IAAI,OAAO,EAC3B,KAAO,EACJ,KAAO,QAAQ,QAAU,QAAQ,IAAI,IAAM,QAAQ,IAAI,GAAK,MAAM,IAAI,GAAK,OAYlF,QAXI,KAAO,UAAY,CACrB,QAAQ,QAAQ,SAAU,EAAG,CAAM,QAAQ,QAAQ,CAAC,IAAM,IAAM,EAAE,YAAY,CAAC,CAAK,CAAC,EACrF,QAAS,EAAI,KAAM,EAAI,QAAQ,OAAQ,IAGjC,MAAM,CAAC,GAAK,QAAQ,CAAC,EAAE,UAAU,IAAI,cAAc,EACvD,EAAE,YAAY,QAAQ,CAAC,CAAC,CAE5B,EAEI,aAAe,GACV,EAAI,KAAM,EAAI,QAAQ,OAAQ,IAAO,GAAI,MAAM,CAAC,EAAG,CAAE,aAAe,GAAM,KAAO,CACtF,cAAgB,OAAO,WAAc,OAAO,WAAW,KAAK,EAAG,aAAc,KAAM,KAAM,EAAI,EAAY,KAAK,EAClH,EAAE,aAAa,gBAAiB,EAAE,CACpC,CAKA,SAAS,UAAU,EAAG,CACpB,GAAI,GAAC,GAAK,CAAC,EAAE,aAAa,iBAAiB,GAC3C,KAAI,KAAO,MAAM,UAAU,MAAM,KAAK,EAAE,QAAQ,EAC5C,KAAO,GACX,GAAI,EAAE,aACJ,QAAS,EAAI,EAAG,EAAI,KAAK,OAAQ,IAAO,GAAI,CAAC,QAAQ,KAAK,CAAC,CAAC,EAAG,CAAE,KAAO,EAAG,KAAO,EAGpF,GADA,EAAE,gBAAgB,iBAAiB,EAC/B,KAAO,GACT,QAAS,EAAI,KAAM,EAAI,KAAK,OAAQ,IAAO,EAAE,YAAY,KAAK,CAAC,CAAC,EAEpE,CAGA,IAAI,QAAU,IACd,SAAS,SAAS,IAAK,CACrB,OAAO,IAAI,QAAQ,SAAU,QAAS,CACpC,IAAI,EAAI,OAAO,WAAW,UAAY,CAAE,QAAQ,IAAI,CAAG,EAAG,OAAO,EACjE,IAAI,KAAK,SAAU,EAAG,CAAE,OAAO,aAAa,CAAC,EAAG,QAAQ,CAAC,CAAG,EAAG,UAAY,CAAE,OAAO,aAAa,CAAC,EAAG,QAAQ,IAAI,CAAG,CAAC,CACvH,CAAC,CACH,CACA,SAAS,aAAa,KAAM,CAC1B,IAAI,GACJ,GAAI,CAAE,GAAK,IAAI,YAAY,0BAA2B,CAAE,OAAQ,CAAE,KAAM,IAAK,CAAE,CAAC,CAAG,OAC5E,IAAK,CAAE,GAAK,SAAS,YAAY,aAAa,EAAG,GAAG,gBAAgB,0BAA2B,GAAO,GAAO,CAAE,KAAM,IAAK,CAAC,CAAG,CACrI,SAAS,cAAc,EAAE,CAC3B,CASA,SAAS,YAAa,CACpB,IAAI,GAAK,SAAS,eAAe,sBAAsB,EACvD,OAAK,KACH,GAAK,SAAS,cAAc,GAAG,EAC/B,GAAG,GAAK,uBACR,GAAG,UAAY,uBACf,GAAG,aAAa,OAAQ,QAAQ,EAChC,GAAG,aAAa,YAAa,QAAQ,EACrC,GAAG,aAAa,cAAe,MAAM,EACrC,SAAS,KAAK,YAAY,EAAE,GAEvB,EACT,CAEA,SAAS,cAAc,MAAO,CAC5B,IAAI,IAAM,OAAS,MAAM,cAAc,8BAA8B,EACjE,KAAO,IAAM,IAAI,YAAY,QAAQ,OAAQ,GAAG,EAAE,KAAK,EAAI,GAC/D,GAAK,KACL,KAAI,GAAK,WAAW,EAQpB,GAAG,YAAc,GACjB,OAAO,WAAW,UAAY,CAAE,GAAG,YAAc,IAAM,EAAG,EAAE,EAC9D,CAQA,SAAS,eAAgB,CACvB,IAAI,EAAI,SAAS,cACjB,GAAI,CAAC,GAAK,IAAM,SAAS,KAAQ,OAAO,KACxC,GAAI,EAAE,QAAQ,kBAAkB,EAAK,MAAO,CAAE,IAAK,kBAAmB,EACtE,GAAI,EAAE,QAAQ,2BAA2B,EAAK,MAAO,CAAE,IAAK,2BAA4B,EACxF,GAAI,EAAE,QAAQ,0BAA0B,EAAK,MAAO,CAAE,IAAK,0BAA2B,EACtF,GAAI,EAAE,KACJ,MAAO,CAAE,IAAK,UAAY,EAAE,KAAK,QAAQ,KAAM,EAAE,EAAI,MACtC,EAAE,MAAQ,WAAa,OAAO,EAAE,KAAK,EAAE,QAAQ,KAAM,EAAE,EAAI,KAAO,GAAI,EAEvF,GAAI,EAAE,QAAQ,aAAa,EAAK,MAAO,CAAE,OAAQ,EAAE,aAAe,IAAI,KAAK,CAAE,EAI7E,IAAI,KAAO,EAAE,QAAQ,gBAAgB,EACrC,OAAI,KAAe,CAAE,KAAM,MAAM,UAAU,QAAQ,KAAK,KAAK,WAAW,SAAU,IAAI,CAAE,EACpF,EAAE,QAAQ,8BAA8B,EAAY,CAAE,IAAK,8BAA+B,EAC1F,EAAE,QAAQ,sBAAsB,EAAY,CAAE,IAAK,qBAAsB,EACzE,EAAE,QAAQ,gCAAgC,EAAY,CAAE,IAAK,oDAAqD,EAC/G,IACT,CAEA,SAAS,aAAa,KAAM,MAAO,CACjC,GAAK,MACL,KAAI,OAAS,KAEb,GADI,MAAQ,KAAK,MAAO,OAAS,MAAM,cAAc,KAAK,GAAG,GACzD,MAAQ,OAAO,KAAK,MAAS,SAAU,CACzC,IAAI,MAAQ,MAAM,iBAAiB,qBAAqB,EACxD,OAAS,MAAM,KAAK,IAAI,KAAK,KAAM,MAAM,OAAS,CAAC,CAAC,GAAK,MAAM,cAAc,8BAA8B,CAC7G,CACA,GAAI,MAAQ,KAAK,OAEf,QADI,MAAQ,MAAM,iBAAiB,qBAAqB,EAC/C,EAAI,EAAG,EAAI,MAAM,OAAQ,IAChC,IAAK,MAAM,CAAC,EAAE,aAAe,IAAI,KAAK,IAAM,KAAK,MAAO,CAAE,OAAS,MAAM,CAAC,EAAG,KAAO,EAKnF,SAAU,OAAS,MAAM,cAAc,IAAI,GAC5C,SACE,CAAC,OAAO,aAAa,UAAU,GAAK,CAAC,OAAO,QAAQ,0CAA0C,GAChG,OAAO,aAAa,WAAY,IAAI,EAEtC,OAAO,MAAM,CAAE,cAAe,EAAK,CAAC,GAExC,CAEA,SAAS,aAAc,CACrB,IAAI,KAAO,SAAS,cAAc,wBAAwB,EAC1D,OAAO,MAAQ,KAAK,QAAQ,0BAA0B,CACxD,CAUA,SAAS,gBAAgB,KAAM,KAAM,CACnC,IAAI,KAAO,KAAK,cAAc,yBAAyB,EACnD,KAAO,KAAK,cAAc,0BAA0B,EACxD,GAAI,GAAC,MAAQ,CAAC,MAAQ,KAAK,UAAU,SAAS,+BAA+B,GAC7E,KAAI,KAAO,KAAK,cAAc,yBAAyB,EACnD,KAAQ,KAAK,WAAW,aAAa,KAAM,IAAI,GAEjD,KAAK,aAAa,KAAM,KAAK,UAAU,EACvC,KAAK,UAAU,IAAI,gCAAgC,GAEvD,CAGA,IAAI,UAAY,OAAO,SAAS,SAAW,OAAO,SAAS,OAE3D,SAAS,KAAK,IAAK,KAAM,CACvB,IAAI,KAAO,YAAY,EACvB,GAAI,CAAC,KAAM,CAAE,OAAO,SAAS,KAAO,IAAK,MAAQ,CACjD,GAAI,CAAE,IAAI,GAAK,IAAI,IAAI,IAAK,OAAO,SAAS,MAAM,EAAG,UAAY,GAAG,SAAW,GAAG,MAAQ,OAAS,EAAG,CAAC,CACvG,IAAI,UAAY,KAAK,GAAG,QAAQ,mBAAoB,EAAE,EAElD,UAAU,SAAS,MAAM,EAC7B,IAAI,IAAO,oBAAqB,OAAU,IAAI,gBAAoB,KAClE,SAAW,IAEX,KAAK,aAAa,YAAa,MAAM,EACrC,IAAI,UAAY,cAAc,EAC1B,IAAM,EAAE,QAEZ,OAAO,WAAW,UAAY,CAAM,MAAQ,SAAW,KAAK,aAAe,KAAK,UAAU,IAAI,aAAa,CAAK,EAAG,GAAG,EAEtH,IAAI,EAAI,IAAI,IAAI,IAAK,OAAO,SAAS,MAAM,EAC3C,EAAE,aAAa,IAAI,WAAY,SAAS,EAGxC,IAAI,SAAW,GACX,MAAQ,IAAM,OAAO,WAAW,UAAY,CAAE,SAAW,GAAM,IAAI,MAAM,CAAG,EAAG,IAAK,EAAI,EAC5F,MAAM,EAAE,SAAS,EAAG,IAAM,CAAE,OAAQ,IAAI,MAAO,EAAI,CAAC,CAAC,EAClD,KAAK,SAAU,EAAG,CAAE,cAAO,aAAa,KAAK,EAAU,EAAE,KAAK,CAAG,CAAC,EAClE,KAAK,SAAU,KAAM,CACpB,IAAI,KAAO,KAAK,SAAS,EAGzB,GAAI,CAAC,KAAM,CAAE,OAAO,SAAS,KAAO,IAAK,MAAQ,CAIjD,IAAI,IAAM,SAAS,cAAc,UAAU,EAC3C,IAAI,UAAY,KAChB,IAAI,KAAO,IAAI,QAAQ,kBACvB,GAAI,CAAC,KAAM,CAAE,OAAO,SAAS,KAAO,IAAK,MAAQ,CACjD,OAAO,SAAS,WAAW,KAAM,UAAW,GAAG,CAAC,EAC7C,KAAK,SAAU,KAAM,CACpB,GAAI,MAAQ,QACZ,KAAI,GAAK,KAAK,cAAc,6BAA6B,EAGrD,KACF,GAAG,UAAU,IAAI,aAAa,EAC9B,GAAG,iBAAiB,eAAgB,SAAS,QAAQ,GAAI,CACnD,GAAG,SAAW,KAClB,GAAG,UAAU,OAAO,aAAa,EACjC,GAAG,oBAAoB,eAAgB,OAAO,EAChD,CAAC,GAEC,IAAM,MAAQ,QAAQ,GAAI,IAAI,EAClC,UAAU,EAAE,EACZ,gBAAgB,KAAM,IAAI,EAG1B,IAAI,QAAU,KAAK,cAAc,wBAAwB,EACrD,QAAU,KAAK,cAAc,wBAAwB,EACrD,SAAW,KAAK,cAAc,oBAAoB,EAClD,SAAW,SAAW,SAAS,UAAY,EAC3C,SAAW,SAAW,QAAQ,UAAU,SAAS,gBAAgB,GAAK,QAAQ,UAAU,IAAI,gBAAgB,EAQhH,KAAK,YAAY,IAAI,EACrB,IAAI,SAAW,KAAK,cAAc,oBAAoB,EAClD,MAAM,QAAQ,UAAU,CAAE,eAAgB,EAAK,EAAG,GAAI,GAAG,EAC7D,iBAAiB,EAGb,UAAY,WAAY,SAAS,UAAY,UACjD,IAAI,MAAQ,YAAY,EACxB,GAAI,MAAO,CAUT,GAJI,OAAO,kBAAoB,OAAO,iBAAiB,KAAK,EAIxD,MAAM,sBAAsB,EAAE,IAAM,EAAG,CACzC,IAAI,KAAO,OAAO,YAAc,OAAO,WAAW,kCAAkC,EAAE,QACtF,MAAM,eAAe,CAAE,MAAO,QAAS,SAAU,KAAO,OAAS,QAAS,CAAC,CAC7E,CACA,cAAc,KAAK,EACnB,aAAa,UAAW,KAAK,EAC7B,aAAa,KAAK,CACpB,EACF,CAAC,CACL,CAAC,EACA,MAAM,SAAU,IAAK,CAChB,KAAO,IAAI,OAAS,cAAgB,CAAC,WACzC,OAAO,SAAS,KAAO,IACzB,CAAC,CACL,CAUA,IAAI,cAAgB,+OAIpB,SAAS,iBAAiB,QAAS,SAAU,EAAG,CAC9C,GAAI,IAAE,kBAAoB,EAAE,SAAW,GAAK,EAAE,SAAW,EAAE,SAAW,EAAE,UAAY,EAAE,QACtF,KAAI,EAAI,EAAE,OAAO,QAAQ,aAAa,EAClC,CAAC,GAAK,CAAC,EAAE,QAAQ,wBAAwB,IAC7C,EAAE,eAAe,EACjB,KAAK,EAAE,KAAM,EAAI,GACnB,CAAC,EAED,SAAS,iBAAiB,SAAU,SAAU,EAAG,CAC/C,IAAI,KAAO,EAAE,OAAO,QAAQ,yBAAyB,EACrD,GAAK,KACL,GAAE,eAAe,EAIjB,IAAI,OAAS,IAAI,gBACjB,IAAI,SAAS,IAAI,EAAE,QAAQ,SAAU,MAAO,IAAK,CAC3C,OAAO,OAAU,UAAY,MAAM,KAAK,IAAM,IAClD,OAAO,OAAO,IAAK,KAAK,CAC1B,CAAC,EACD,IAAI,GAAK,OAAO,SAAS,EACrB,OAAS,OAAO,SAAS,UAAY,GAAK,IAAM,GAAK,IAIrD,SAAW,WACf,KAAK,OAAQ,EAAI,EACnB,CAAC,EAED,OAAO,iBAAiB,WAAY,UAAY,CAO9C,IAAI,IAAM,OAAO,SAAS,SAAW,OAAO,SAAS,OACjD,MAAQ,WACR,YAAY,GAAG,KAAK,OAAO,SAAS,KAAM,EAAK,CACrD,CAAC,EAcD,SAAS,kBAAkB,KAAM,CAC/B,GAAK,KACL,KAAI,EAAI,KAAK,cAAc,8CAA8C,EACzE,GAAI,GAAC,GAAK,EAAE,aAAa,iBAAiB,GAC1C,GAAE,aAAa,kBAAmB,EAAE,EACpC,IAAI,UAAY,KAAK,GAAG,QAAQ,mBAAoB,EAAE,EAClD,IACJ,GAAI,CAAE,IAAM,WAAW,KAAM,UAAW,OAAO,SAAS,IAAI,CAAG,OACxD,IAAK,CAAE,IAAM,QAAQ,QAAQ,IAAI,CAAG,CAC3C,SAAS,GAAG,EAAE,KAAK,SAAU,KAAM,CACjC,GAAI,GAAC,EAAE,aAAe,CAAC,EAAE,aAAa,iBAAiB,GACvD,IAAI,CAAM,MAAQ,QAAQ,EAAG,IAAI,CAAK,OAC/B,IAAK,CAAE,KAAO,IAAM,CAC3B,UAAU,CAAC,EACP,MAAQ,aAAa,IAAI,EAC/B,CAAC,GACH,CACA,kBAAkB,YAAY,CAAC,EAQ/B,SAAS,iBAAiB,uBAAwB,SAAU,MAAO,CACjE,IAAI,IAAM,MAAM,OACZ,CAAC,KAAO,CAAC,IAAI,eAAiB,CAAC,IAAI,cAAc,wBAAwB,IAC7E,QAAU,CAAC,EACX,UAAY,OAAO,SAAS,SAAW,OAAO,SAAS,OACvD,iBAAiB,EACjB,kBAAkB,IAAI,QAAQ,0BAA0B,EAAI,IAAM,IAAI,QAAQ,0BAA0B,CAAC,EAC3G,CAAC,CACH,GAAG,EA4BH,SAAS,YAAY,EAAG,CACtB,IAAI,EAAI,EAAE,OAAO,SAAW,EAAE,OAAO,QAAQ,gBAAgB,EACzD,CAAC,GAAK,EAAE,KAAK,QAAQ,UAAU,EAAI,KACvC,EAAE,KAAO,EAAE,KAAK,MAAM,GAAG,EAAE,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,EAAI,YAAc,mBAAmB,EAAE,aAAa,aAAa,CAAC,EAC9G,CACA,SAAS,iBAAiB,QAAS,YAAa,EAAI,EACpD,SAAS,iBAAiB,WAAY,YAAa,EAAI,GAQtD,UAAY,CACX,IAAI,KAAO,SAAS,cAAc,wBAAwB,EACtD,IAAM,MAAQ,KAAK,cAAc,aAAa,EAClD,GAAI,GAAC,KAAO,KAAK,aAAe,KAAK,aACrC,KAAI,EAAI,KAAK,sBAAsB,EAC/B,EAAI,IAAI,sBAAsB,EAClC,KAAK,YAAe,EAAE,KAAO,EAAE,MAAQ,GAAM,EAAE,KAAO,EAAE,MAAQ,GAClE,GAAG,EAQH,SAAS,iBAAiB,QAAS,SAAU,EAAG,CAC9C,IAAI,IAAM,EAAE,OAAO,SAAW,EAAE,OAAO,QAAQ,yBAAyB,EACxE,GAAK,IACL,KAAI,KAAO,SAAS,eAAe,IAAI,aAAa,eAAe,CAAC,EACpE,GAAK,KACL,KAAI,KAAO,CAAC,KAAK,UAAU,SAAS,SAAS,EACzC,IAAM,SAAU,EAAG,CACrB,KAAK,UAAU,OAAO,UAAW,CAAC,EAClC,IAAI,aAAa,gBAAiB,EAAI,OAAS,OAAO,EACtD,IAAI,YAAc,EAAI,YAAc,WACtC,EAEI,OAAO,YAAc,OAAO,WAAW,OAAU,OAAO,WAAW,OAAO,KAAM,IAAK,KAAM,EAAK,EAAY,IAAI,IAAI,GAC1H,CAAC,EAED,UAAU,QAAQ,EAIlB,SAAS,iBAAiB,uBAAwB,SAAU,MAAO,CACjE,UAAU,MAAM,MAAM,CACxB,CAAC,GAQA,UAAuB,CACtB,IAAI,OAAS,SAAS,cAAc,sBAAsB,GAC7C,SAAS,cAAc,qBAAqB,EACpD,SAEL,OAAO,MAAM,CAAE,cAAe,EAAK,CAAC,EACpC,OAAO,eAAe,CAAE,MAAO,SAAU,SAAU,MAAO,CAAC,EAC7D,GAAG,CACL,GAAG,GAYF,UAAY,CACX,aACA,GAAI,EAAE,UAAW,SAAW,CAAC,OAAO,SAAW,CAAC,QAAQ,WAAa,EAAE,YAAa,SAAS,cAAc,UAAU,GAAM,OAC3H,IAAI,IAAM,2BACV,SAAS,QAAS,CAAE,OAAO,SAAS,cAAc,GAAG,CAAG,CACxD,GAAI,CAAC,OAAO,EAAK,OACjB,IAAI,KAAO,CAAC,EACR,IAAM,KACN,IAAM,EACN,OAAS,SAAS,SAAW,SAAS,OAE1C,SAAS,MAAM,MAAO,CACpB,IAAI,EAAI,CAAC,EACL,IAAM,QAAQ,MAClB,GAAI,KAAO,OAAO,KAAQ,SAAY,QAAS,KAAK,IAAW,OAAO,UAAU,eAAe,KAAK,IAAK,CAAC,IAAK,EAAE,CAAC,EAAI,IAAI,CAAC,GAC3H,QAAS,KAAK,MAAa,OAAO,UAAU,eAAe,KAAK,MAAO,CAAC,IAAK,EAAE,CAAC,EAAI,MAAM,CAAC,GAC3F,OAAO,CACT,CACA,GAAI,CAAE,QAAQ,aAAa,MAAM,CAAE,SAAU,EAAG,EAAG,OAAO,OAAQ,CAAC,EAAG,EAAE,CAAG,OAAS,EAAG,CAAC,CAExF,IAAI,OAAS,EACb,OAAO,iBAAiB,SAAU,UAAY,CAC5C,OAAO,aAAa,MAAM,EAC1B,OAAS,OAAO,WAAW,UAAY,CACrC,GAAK,OAAO,EACZ,GAAI,CAAE,QAAQ,aAAa,MAAM,CAAE,SAAU,EAAG,EAAG,OAAO,OAAQ,CAAC,EAAG,EAAE,CAAG,OAAS,EAAG,CAAC,CAC1F,EAAG,GAAG,CACR,EAAG,CAAE,QAAS,EAAK,CAAC,EAEpB,SAAS,WAAW,IAAK,CACvB,IAAI,EAAI,OAAO,EACX,KAAO,GAAK,EAAE,QAAQ,0BAA0B,EACpD,GAAI,CAAC,KAAQ,OAAO,KACpB,IAAI,EAAI,IAAI,IAAI,IAAK,SAAS,MAAM,EACpC,SAAE,aAAa,IAAI,aAAc,KAAK,GAAG,QAAQ,mBAAoB,EAAE,CAAC,EACjE,EAAE,SAAS,CACpB,CACA,SAAS,IAAI,IAAK,CAChB,IAAI,GAAK,WAAW,GAAG,EACvB,GAAI,CAAC,GAAM,OAAO,QAAQ,OAAO,IAAI,MAAM,YAAY,CAAC,EACxD,GAAI,CAAC,KAAK,EAAE,EAAG,CAEb,IAAIA,KAAO,oBAAqB,OAAU,IAAI,gBAAoB,KAC9D,MAAQA,KAAM,OAAO,WAAW,UAAY,CAAEA,KAAI,MAAM,CAAG,EAAG,IAAK,EAAI,EAC3E,KAAK,EAAE,EAAI,MAAM,GAAIA,KAAM,CAAE,YAAa,cAAe,OAAQA,KAAI,MAAO,EAAI,CAAE,YAAa,aAAc,CAAC,EAAE,KAAK,SAAU,IAAK,CAElI,GADA,OAAO,aAAa,KAAK,EACrB,CAAC,IAAI,GAAM,MAAM,IAAI,MAAM,QAAU,IAAI,MAAM,EACnD,OAAO,IAAI,KAAK,CAClB,CAAC,EACD,KAAK,EAAE,EAAE,MAAM,UAAY,CAAE,OAAO,KAAK,EAAE,CAAG,CAAC,CACjD,CACA,OAAO,KAAK,EAAE,CAChB,CAEA,SAAS,KAAK,IAAK,KAAM,SAAU,CACjC,IAAI,EAAI,OAAO,EACf,GAAI,CAAC,EAAG,CAAE,SAAS,KAAO,IAAK,MAAQ,CACvC,IAAI,GAAK,EAAE,IAGX,GAAI,CAAE,IAAI,GAAK,IAAI,IAAI,IAAK,SAAS,MAAM,EAAG,OAAS,GAAG,SAAW,GAAG,MAAQ,OAAS,EAAG,CAAC,CAC7F,IAAI,KAAO,OAAO,WAAW,UAAY,CAAM,KAAO,MAAO,EAAE,UAAU,IAAI,aAAa,EAAG,EAAE,aAAa,YAAa,MAAM,EAAK,EAAG,GAAG,EAC1I,IAAI,GAAG,EAAE,KAAK,SAAU,KAAM,CAC5B,GAAI,KAAO,IACX,QAAO,aAAa,IAAI,EACxB,IAAI,IAAM,SAAS,cAAc,UAAU,EAC3C,IAAI,UAAY,KAChB,IAAI,MAAQ,IAAI,QAAQ,cAAc,GAAG,EACzC,GAAI,CAAC,MAAO,CAAE,SAAS,KAAO,IAAK,MAAQ,CAC3C,IAAI,IAAM,OAAO,EACjB,GAAI,CAAC,IAAK,CAAE,SAAS,KAAO,IAAK,MAAQ,CACzC,MAAM,UAAU,IAAI,aAAa,EACjC,IAAI,YAAY,KAAK,EACrB,MAAM,iBAAiB,eAAgB,SAAS,QAAQ,GAAI,CACtD,GAAG,SAAW,QAClB,MAAM,UAAU,OAAO,aAAa,EACpC,MAAM,oBAAoB,eAAgB,OAAO,EACnD,CAAC,EACD,OAAS,IAAI,IAAI,IAAK,SAAS,MAAM,EAAE,SAAW,IAAI,IAAI,IAAK,SAAS,MAAM,EAAE,OAC5E,MAAQ,QAAQ,UAAU,CAAE,SAAU,EAAG,EAAG,CAAE,EAAG,GAAI,GAAG,EAE5D,IAAI,GAAK,OAAO,IAAI,IAAI,IAAK,SAAS,MAAM,EAAE,aAAa,IAAI,MAAM,CAAC,GAAK,EACvE,GAAK,SAAS,MAAM,QAAQ,sBAAuB,EAAE,EACrD,GAAK,IAAK,GAAK,GAAG,QAAQ,KAAK,EAAI,GAAK,GAAG,QAAQ,iBAAkB,WAAa,GAAK,KAAK,EAAI,GAAK,WAAa,IACtH,SAAS,MAAQ,GACjB,IAAI,KAAO,OAAO,YAAc,OAAO,WAAW,kCAAkC,EAAE,QACtF,GAAI,OAAO,UAAa,SACtB,OAAO,SAAS,EAAG,QAAQ,MACtB,CACL,IAAI,IAAM,MAAM,sBAAsB,EAAE,KACpC,IAAM,GAAK,IAAM,OAAO,YAAc,KAAO,MAAM,eAAe,CAAE,MAAO,QAAS,SAAU,KAAO,OAAS,QAAS,CAAC,CAC9H,CACA,IAAI,MAAQ,MAAM,cAAc,kBAAkB,EAC9C,OAAS,OAAO,UAAa,WAC/B,MAAM,aAAa,WAAY,IAAI,EACnC,MAAM,MAAM,CAAE,cAAe,EAAK,CAAC,GAEvC,CAAC,EAAE,MAAM,UAAY,CACnB,OAAO,aAAa,IAAI,EACpB,KAAO,MAAO,SAAS,KAAO,IACpC,CAAC,CACH,CAEA,SAAS,UAAU,EAAG,CACpB,IAAI,EAAI,EAAE,QAAU,EAAE,OAAO,QAAU,EAAE,OAAO,QAAQ,IAAM,2BAA2B,EAAI,KAC7F,MAAI,CAAC,GAAK,EAAE,SAAW,SAAS,OAAiB,KAC1C,CACT,CACA,CAAC,eAAgB,UAAW,YAAY,EAAE,QAAQ,SAAU,KAAM,CAChE,SAAS,iBAAiB,KAAM,SAAU,EAAG,CAAE,IAAI,EAAI,UAAU,CAAC,EAAO,GAAK,IAAI,EAAE,IAAI,EAAE,MAAM,UAAY,CAAC,CAAC,CAAK,EAAG,CAAE,QAAS,GAAM,QAAS,EAAK,CAAC,CACxJ,CAAC,EACD,SAAS,iBAAiB,QAAS,SAAU,EAAG,CAC9C,GAAI,IAAE,kBAAoB,EAAE,SAAW,GAAK,EAAE,SAAW,EAAE,SAAW,EAAE,UAAY,EAAE,QACtF,KAAI,EAAI,UAAU,CAAC,EACnB,GAAK,EACL,GAAE,eAAe,EACjB,GAAI,CAAE,QAAQ,aAAa,MAAM,CAAE,SAAU,EAAG,EAAG,OAAO,OAAQ,CAAC,EAAG,EAAE,CAAG,OAAS,IAAK,CAAC,CAC1F,KAAK,EAAE,KAAM,EAAI,GACnB,CAAC,EACD,OAAO,iBAAiB,WAAY,SAAU,EAAG,CAC/C,GAAK,OAAO,EACZ,KAAI,IAAM,SAAS,SAAW,SAAS,OACvC,GAAI,MAAQ,OACZ,KAAI,GAAK,EAAE,MACX,KAAK,SAAS,KAAM,GAAO,IAAM,OAAO,GAAG,GAAM,SAAW,GAAG,EAAI,MAAS,GAC9E,CAAC,CACH,GAAG",
  "names": ["ctl"]
}
