{
  "version": 3,
  "sources": ["/cdn/shop/t/22/assets/sav-forma.js?r=1"],
  "sourcesContent": ["/* ============================================================================\n   sav-forma.js  \u00B7  Seventyninth Avenue \u2014 \"Forma\" homepage behaviour layer\n   Ported from the approved standalone mockup (raw.js blocks 1\u20133).\n   ----------------------------------------------------------------------------\n   LOAD IT LIKE THIS (constraint 3 \u2014 asset_url's ?v= does not change on\n   re-upload, so a literal cache-breaker is mandatory):\n\n       <script src=\"{{ 'sav-forma.js' | asset_url }}&r=1\" defer></script>\n\n   Bump &r=N on EVERY re-upload of this file.\n\n   THE .js GATE IS NOT HERE, ON PURPOSE.\n   raw.js block 1 (`document.documentElement.className += \" js\"`) is deleted.\n   The vendor theme already does it, earlier and better:\n       layout/theme.liquid:3          <html class=\"no-js\" \u2026>\n       snippets/js-variables.liquid:2 classList.replace('no-js','js')\n       rendered at layout/theme.liquid:52, i.e. BEFORE theme.css at :76.\n   So `.js` is on <html> before any stylesheet is parsed. Never put the gate in\n   this deferred file \u2014 it would run after parse and flash the content in\n   before hiding it.\n\n   THE BOOT-FAILURE GUARD IS NOT HERE EITHER, ALSO ON PURPOSE.\n   raw.js block 3 must stay a SEPARATE <script> element: a try/catch inside\n   this file cannot survive a syntax error in this file. Ship it inline at the\n   end of the section body \u2014 see build/sav-forma-boot-guard.liquid.\n\n   WHAT THIS FILE GUARANTEES\n   \u00B7 Nothing it does can throw on missing markup. Every lookup is null-safe,\n     and every per-root boot is wrapped in try/catch that force-opens that\n     root's reveals on failure. An exception must never leave [data-reveal]\n     elements at opacity:0 \u2014 that renders the page blank.\n   \u00B7 It never touches an element outside a .sav-forma root, with three named\n     exceptions (documented at each site): documentElement's .sav-wipe class, the\n     window/document scroll listeners, and the sticky-ancestor assertion,\n     which has to climb across the Shopify section boundary to be useful.\n   \u00B7 It is re-entrant: Shopify's theme editor replaces section DOM and fires\n     shopify:section:load. Booting is per-root and idempotent.\n   \u00B7 It creates exactly two window properties, both namespaced:\n     window.__savBooted (read by the boot guard) and window.__savForma\n     (debug handle for the post-deploy console checklist).\n   ========================================================================== */\n\n(function () {\n  \"use strict\";\n\n  /* Double-<script> guard. If the tag is emitted twice (a section duplicated\n     in the editor, or a stale cached copy alongside a fresh one) the second\n     copy must not install a second set of scroll listeners and a second poll. */\n  if (window.__savFormaLoaded) return;\n  window.__savFormaLoaded = true;\n\n  var doc     = document.documentElement;\n  var reduce  = !!(window.matchMedia && window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches);\n  var save    = !!(navigator.connection && navigator.connection.saveData);\n  var design  = !!(window.Shopify && window.Shopify.designMode);\n  var hasIO   = \"IntersectionObserver\" in window;\n  var console_ = window.console;\n\n  /* Videos this layer is allowed to touch. Deliberately NOT `video` \u2014 a\n     document- or body-scoped fallback root (see mount()) must never let the\n     autoplay nudge start a theme product video or pause one under reduced\n     motion. Every video in the ported markup matches one of these five. */\n  var OURS = \".pour video, .signoff video, .feature__media video, video[data-lazy], video[data-poster]\";\n\n  /* \u2500\u2500 helpers \u00B7 all null-safe, all total \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n  function all(scope, sel) {\n    if (!scope || !scope.querySelectorAll) return [];\n    try { return [].slice.call(scope.querySelectorAll(sel)); } catch (e) { return []; }\n  }\n  function one(scope, sel) {\n    if (!scope || !scope.querySelector) return null;\n    try { return scope.querySelector(sel); } catch (e) { return null; }\n  }\n  function live(el) {\n    /* An element removed by shopify:section:load must fall out of the shared\n       target lists on its own, without depending on the unload handler. */\n    if (!el) return false;\n    if (typeof el.isConnected === \"boolean\") return el.isConnected;\n    return document.contains ? document.contains(el) : true;\n  }\n  function uniq(arr) {\n    return arr.filter(function (v, i, a) { return v && a.indexOf(v) === i; });\n  }\n  function warn(msg) { if (console_ && console_.warn) console_.warn(msg); }\n  function err(msg, e) { if (console_ && console_.error) console_.error(msg, e); }\n\n  /* \u2550\u2550 1 \u00B7 SIGNATURE \u2014 @property registration \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n     Registered from script, not CSS, so a single feature test decides whether\n     the wipe runs at all. Without @property the custom property animates\n     DISCRETELY \u2014 the mask would jump rather than sweep, which looks like a\n     bug \u2014 so those browsers get the plain fade instead (raw.css:637\u2013652).\n     Global, not per-root: the registry and the .sav-wipe class are document-wide,\n     and a second registration on a re-render is caught below. */\n  var wipeOK = false;\n  if (!reduce && window.CSS && window.CSS.registerProperty) {\n    try {\n      window.CSS.registerProperty({\n        name: \"--sig-wipe\", syntax: \"<percentage>\", inherits: false, initialValue: \"0%\"\n      });\n      wipeOK = true;\n    } catch (e) {\n      /* already registered by a previous run = support exists */\n      wipeOK = !!(e && e.name === \"InvalidModificationError\");\n    }\n  }\n  if (wipeOK) doc.classList.add(\"sav-wipe\");   /* classList.add, not `className +=`:\n                                              idempotent across re-inits. */\n\n  /* \u2550\u2550 2 \u00B7 SHARED SCROLL ENGINE \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n     ONE scroll listener and ONE poll for the whole document, no matter how\n     many .sav-forma roots exist. The structure spec splits the port into\n     seven Shopify sections; the integration spec argues for one. This file is\n     correct under both: roots register into these shared lists.             */\n\n  var roots   = [];     /* booted roots, pruned lazily                        */\n  var targets = [];     /* [data-reveal] not yet revealed, across all roots   */\n  var paras   = [];     /* [data-parallax], across all roots                  */\n  var vlazy   = [];     /* videos awaiting hydration, across all roots        */\n  var pollId  = null;\n  var ticking = false;\n  var tickAt  = 0;\n  var listening = false;\n\n  /* BELT AND BRACES, and this one is not paranoia (raw.js:57\u201367).\n     IntersectionObserver is the efficient path, but its callbacks get\n     throttled or dropped in several real situations \u2014 an occluded tab, a\n     throttled renderer, a programmatic jump-scroll \u2014 and when that happens\n     the page stays PERMANENTLY invisible, which is the worst failure a reveal\n     system can have. Measured in the mockup build: after a scripted jump to\n     mid-page only 2 of 50 targets had been delivered. In Shopify this is not\n     an edge case at all \u2014 selecting a section in the theme editor makes\n     Shopify scrollIntoView() it, which is exactly that jump. */\n  function sweep() {\n    if (!targets.length) return;\n    var vh = window.innerHeight || doc.clientHeight || 0;\n    for (var i = targets.length - 1; i >= 0; i--) {\n      var el = targets[i];\n      if (!live(el)) { targets.splice(i, 1); continue; }\n      var r = el.getBoundingClientRect();\n      /* No `r.bottom > 0` test. Anything at or ABOVE the fold line counts as\n         seen, so content jumped past \u2014 a deep link, a restored scroll\n         position, the editor's scrollIntoView \u2014 can never be left invisible\n         behind the reader. */\n      if (r.top < vh * 0.94) {\n        el.classList.add(\"in\");\n        if (el.__savIO) { try { el.__savIO.unobserve(el); } catch (e) {} el.__savIO = null; }\n        targets.splice(i, 1);\n      }\n    }\n  }\n\n  /* The same belt, for lazy media. MEASURED DURING THIS PORT: in a throttled\n     renderer a freshly-created IntersectionObserver delivered NO callbacks at\n     all \u2014 not even for an element sitting at top:112 in a 860px viewport \u2014\n     while the reveal system sailed through on sweep() and the poll alone. The\n     mockup's video hydration was IO-only, so in that state the two full-bleed\n     films and the Amber turntable never load and the page silently degrades\n     to three still posters. Same band as the observer (150% of the viewport),\n     so this changes nothing about WHAT gets fetched or WHEN \u2014 only about\n     whether the trigger can be withheld. */\n  function vsweep() {\n    if (!vlazy.length) return;\n    var vh = window.innerHeight || doc.clientHeight || 0;\n    if (!vh) return;                       /* nothing is visible; fetch nothing */\n    var pad = vh * 1.5;\n    for (var i = vlazy.length - 1; i >= 0; i--) {\n      var v = vlazy[i];\n      if (!live(v) || v.dataset.hydrated) { vlazy.splice(i, 1); continue; }\n      var r = v.getBoundingClientRect();\n      if (r.top < vh + pad && r.bottom > -pad) { hydrate(v); vlazy.splice(i, 1); }\n    }\n  }\n\n  function needPoll() { return targets.length > 0 || vlazy.length > 0; }\n\n  /* Last line of defence. Both the observer AND the scroll event can be\n     withheld by a throttled renderer. A 500ms poll cannot be withheld, costs\n     one array-length check once the page is read, and cancels itself the\n     moment nothing is left. DO NOT \"optimise\" this away \u2014 it is the only\n     thing that recovers the theme editor's jump-scroll. */\n  function startPoll() {\n    if (pollId !== null || !needPoll()) return;\n    pollId = window.setInterval(function () {\n      sweep();\n      vsweep();\n      if (!needPoll()) { window.clearInterval(pollId); pollId = null; }\n    }, 500);\n  }\n\n  /* THE ONE PARALLAX. The rail drift that used to live here is gone (raw.js\n     :179\u2013184): its total travel was 256px against ~1,400px of hidden track,\n     so five of eight cards were unreachable at every viewport. The rails are\n     native scrollers now \u2014 see section 5. */\n  function frame() {\n    ticking = false;\n    if (reduce) return;\n    var vh = window.innerHeight || 0;\n    if (!vh) return;\n    for (var i = paras.length - 1; i >= 0; i--) {\n      var el = paras[i];\n      if (!live(el)) { paras.splice(i, 1); continue; }\n      var r = el.getBoundingClientRect();\n      if (r.bottom < -200 || r.top > vh + 200) continue;\n      var mid   = (r.top + r.height / 2 - vh / 2) / vh;          /* -1 \u2026 1 */\n      var depth = parseFloat(el.getAttribute(\"data-depth\")) || -12;\n      el.style.transform = \"translate3d(0,\" + (mid * depth).toFixed(2) + \"px,0)\";\n    }\n  }\n\n  /* sweep() runs OUTSIDE the rAF gate on purpose (raw.js:201\u2013207). If a\n     scheduled frame is never delivered \u2014 a background tab, a throttled\n     renderer \u2014 `ticking` stays true and every later scroll event is\n     swallowed, so anything gated behind rAF stops permanently. Parallax can\n     afford that (it is decoration); reveals cannot (they are the page).\n\n     NOTE FOR ANYONE EDITING: raw.js called updateBar() here. updateBar,\n     #stickbar and .bar-sentinel are all deleted with the mockup chrome. A\n     leftover call would be a ReferenceError on the first scroll event, the\n     handler would die, and nothing below the fold would ever reveal. */\n  function onScroll() {\n    sweep();\n    vsweep();\n    if (!ticking) {\n      ticking = true;\n      tickAt  = Date.now();\n      window.requestAnimationFrame(frame);\n    } else if (Date.now() - tickAt > 500) {\n      /* The scheduled frame was never delivered \u2014 measured in this port's own\n         test renderer, where requestAnimationFrame produced nothing at all.\n         Without this, `ticking` stays true forever and the parallax is dead\n         for the rest of the session. One synchronous run over one element\n         re-opens the gate; the cost is bounded by the 500ms window. */\n      tickAt = Date.now();\n      frame();\n    }\n  }\n\n  function listen() {\n    if (listening) return;\n    listening = true;\n    window.addEventListener(\"scroll\", onScroll, { passive: true });\n    window.addEventListener(\"resize\", onScroll, { passive: true });\n    document.addEventListener(\"visibilitychange\", onScroll);\n  }\n\n  /* \u2550\u2550 3 \u00B7 REVEALS (per root, into the shared engine) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n  function revealAll(list) {\n    list.forEach(function (el) { el.classList.add(\"in\"); });\n  }\n\n  function bootReveals(root, state) {\n    var list = all(root, \"[data-reveal]\");\n    if (!list.length) return;\n\n    /* THEME EDITOR: content must never be invisible to the merchant.\n       Shopify replaces the section DOM on every setting change and the fresh\n       [data-reveal] nodes come back at opacity:0 with nothing observing them.\n       The section also ships a request.design_mode !important stylesheet\n       override (integration spec \u00A78.2a) \u2014 this is the JS half of the same\n       belt. Reduced motion and no-IO take the same instant path. */\n    if (design || reduce || !hasIO) { revealAll(list); return; }\n\n    var io = new IntersectionObserver(function (entries) {\n      entries.forEach(function (e) {\n        if (!e.isIntersecting) return;\n        e.target.classList.add(\"in\");\n        try { io.unobserve(e.target); } catch (err2) {}\n        e.target.__savIO = null;\n        var i = targets.indexOf(e.target);\n        if (i > -1) targets.splice(i, 1);\n      });\n    }, { threshold: 0.18, rootMargin: \"0px 0px -6% 0px\" });\n\n    list.forEach(function (el) {\n      el.__savIO = io;\n      targets.push(el);\n      io.observe(el);\n    });\n    state.io = io;\n    startPoll();\n  }\n\n  /* \u2550\u2550 4 \u00B7 SIGNATURE DECODE GATE (per root) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n     The wipe starts at 320ms; on a slow connection an ungated wipe would\n     animate over nothing and then the logo would pop in fully drawn. Hold at\n     opacity 0 until decode resolves or a 900ms cap fires.\n\n     ONLY THE HERO SIGNATURE. The closing mark (`.signoff .sig`, #sig2) is\n     static \u2014 no wipe, no gate, no .ready. One gesture, once: the page opens\n     signed and closes signed, it does not sign itself twice. It is opted out\n     of the mask in CSS (raw.css:995\u2013998), and wiring it into this gate would\n     leave it inheriting --sig-wipe:0% and rendering INVISIBLE. */\n  function bootSignature(root, state) {\n    var sig = one(root, \".hero .sig\") || one(root, \".hero-foot .sig\");\n    if (!sig) return;\n    state.sig = sig;\n\n    sig.addEventListener(\"animationend\", function () { sig.style.willChange = \"auto\"; });\n\n    if (design) { sig.classList.add(\"ready\"); return; }\n\n    var img  = one(sig, \"img\");\n    var done = false;\n    var go = function () {\n      if (done) return;\n      done = true;\n      state.sigTimer = window.setTimeout(function () {\n        sig.style.willChange = \"mask-image\";\n        sig.classList.add(\"ready\");\n      }, reduce ? 200 : 320);\n    };\n\n    if (img && img.decode) {\n      try { img.decode().then(go, go); } catch (e) { go(); }\n    } else if (img && img.complete) {\n      go();\n    } else if (img) {\n      img.addEventListener(\"load\", go);\n      img.addEventListener(\"error\", go);\n    }\n    state.sigCap = window.setTimeout(go, 900);\n  }\n\n  /* \u2550\u2550 5 \u00B7 LAZY MEDIA (per root) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n     Nothing fetches an mp4 until it is within 150% of the viewport. On Data\n     Saver nothing but the poster is ever fetched.\n\n     Posters are lazy too. A <video poster> is fetched the moment the element\n     exists, even at preload=\"none\" \u2014 measured live in the mockup, the page\n     was pulling all three posters (~190 KB) before a reader had scrolled past\n     the hero. The two below-fold films carry data-poster instead. */\n  function tryPlay(v) {\n    if (reduce || save) return;\n    try { var p = v.play(); if (p && p.catch) p.catch(function () {}); } catch (e) {}\n  }\n\n  function hydrate(v) {\n    if (!v || v.dataset.hydrated) return;\n    v.dataset.hydrated = \"1\";\n    if (v.dataset.poster && !v.poster) v.poster = v.dataset.poster;\n    if (v.dataset.lazy && !v.src) v.src = v.dataset.lazy;\n    /* <source> children carry a REAL src (src is a required attribute, and\n       without it the no-JS page had no film and no poster). preload=\"none\"\n       means nothing was fetched, so load() is what starts it. data-lazy on a\n       source is still honoured in case a future block uses it. */\n    all(v, \"source[data-lazy]\").forEach(function (s) { s.src = s.dataset.lazy; });\n    try { v.load(); } catch (e) {}\n    /* Some engines only settle once data has arrived. raw.js hung this on the\n       hero <video>; the hero is a still now, so each film waits on its own. */\n    v.addEventListener(\"loadeddata\", function () { tryPlay(v); }, { once: true });\n    tryPlay(v);\n  }\n\n  function bootMedia(root, state) {\n    var vids = uniq(all(root, OURS));\n    if (!vids.length) return;\n    state.vids = vids;\n\n    if (save) {\n      /* Data Saver: never fetch an mp4. Posters only, so the page still reads. */\n      vids.forEach(function (v) {\n        if (v.dataset.poster && !v.poster) v.poster = v.dataset.poster;\n        v.preload = \"none\";\n        try { v.pause(); } catch (e) {}\n      });\n      return;\n    }\n\n    if (reduce) {\n      /* Every film is rewound and held on its poster. This also satisfies\n         WCAG 2.2.2 without adding a control to the frame. The poster is still\n         attached so the band is not a bare navy rectangle. */\n      vids.forEach(function (v) {\n        if (v.dataset.poster && !v.poster) v.poster = v.dataset.poster;\n        v.removeAttribute(\"autoplay\");\n        try { v.pause(); v.currentTime = 0; } catch (e) {}\n      });\n      return;\n    }\n\n    /* Both paths queue into the shared vsweep() list. hydrate() is idempotent\n       (dataset.hydrated), so whichever trigger arrives first wins and the\n       other prunes itself. */\n    vids.forEach(function (v) { if (vlazy.indexOf(v) === -1) vlazy.push(v); });\n\n    if (hasIO) {\n      var vio = new IntersectionObserver(function (entries) {\n        entries.forEach(function (e) {\n          if (!e.isIntersecting) return;\n          hydrate(e.target);\n          try { vio.unobserve(e.target); } catch (err2) {}\n        });\n      }, { rootMargin: \"150% 0px\" });\n      vids.forEach(function (v) { vio.observe(v); });\n      state.vio = vio;\n    }\n    startPoll();\n  }\n\n  /* \u2550\u2550 6 \u00B7 RAIL CONTROLS (per root) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n     The rails scroll natively; these are the pointer affordance, hidden by\n     CSS where there is no fine pointer. One click moves two cards.\n\n     SCROLL-SNAP WORKAROUND \u2014 this is new in the port and it is load-bearing.\n     `.rail{ scroll-snap-type: x mandatory }` (raw.css:750). Chrome re-snaps a\n     programmatic scrollLeft synchronously, so an arbitrary target is dragged\n     to the nearest snap point mid-flight; `sync()` then never sees the rail\n     settle on `target`, `target` is never cleared, and the next click\n     computes its base from a stale in-flight value. Two fixes, together:\n       (a) snap is switched OFF inline for the duration of a driven scroll and\n           restored on user takeover (or once the rail has settled ON a snap\n           position, where restoring cannot produce a visible jump);\n       (b) the target is computed from the cards' own offsets, so it IS a snap\n           position \u2014 restoring snap afterwards is then a no-op by\n           construction, not by luck. */\n  function bootRails(root, state) {\n    all(root, \"[data-rail-nav]\").forEach(function (nav) {\n      var id   = nav.getAttribute(\"data-rail-nav\");\n      var rail = id ? document.getElementById(id) : null;\n\n      /* Fallback if the id was renamed section-scoped in Liquid and the\n         attribute was not kept in step: climb to the nearest ancestor that\n         contains a .rail. Never `one(root, \".rail\")` \u2014 with both rails in one\n         Shopify section that would wire the second nav to the first rail. */\n      if (!rail) {\n        var p = nav.parentNode;\n        while (p && p.nodeType === 1 && !rail) { rail = one(p, \".rail\"); p = p.parentNode; }\n      }\n      if (!rail) return;\n\n      var prev = one(nav, \"[data-prev]\");\n      var next = one(nav, \"[data-next]\");\n\n      var target  = null;     /* pending absolute scrollLeft, or null         */\n      var snapOff = false;    /* inline scroll-snap-type:none currently set   */\n      var cards   = [];\n      var giveUp  = null;\n\n      function measure() { cards = all(rail, \".card\"); }\n\n      /* Snap position of card i. Card 0's snap position is 0: the track's\n         padding-inline is var(--g) and the rail's scroll-padding-inline-start\n         is the same var(--g), so they cancel. Every other card is therefore\n         offset by its distance from card 0. No need to resolve --g. */\n      function snapAt(i) {\n        if (!cards.length) return 0;\n        var j = Math.max(0, Math.min(cards.length - 1, i));\n        return Math.max(0, cards[j].offsetLeft - cards[0].offsetLeft);\n      }\n      function nearestIndex(x) {\n        var best = 0, bd = Infinity;\n        for (var i = 0; i < cards.length; i++) {\n          var d = Math.abs(snapAt(i) - x);\n          if (d < bd) { bd = d; best = i; }\n        }\n        return best;\n      }\n      function maxScroll() { return Math.max(0, rail.scrollWidth - rail.clientWidth); }\n\n      function setSnap(on) {\n        if (!rail.style) return;\n        if (on) { if (snapOff) { rail.style.scrollSnapType = \"\"; snapOff = false; } }\n        else    { if (!snapOff) { rail.style.scrollSnapType = \"none\"; snapOff = true; } }\n      }\n\n      /* Restore snap only where doing so cannot yank the rail sideways: on a\n         snap position, or hard against either end. Anywhere else it waits for\n         the user's own gesture, which is when a snap is expected anyway. */\n      function settle() {\n        if (!snapOff) return;\n        if (!cards.length) measure();\n        var x = rail.scrollLeft, max = maxScroll();\n        if (!cards.length || x <= 0 || x >= max - 2 || Math.abs(snapAt(nearestIndex(x)) - x) <= 2) {\n          setSnap(true);\n        }\n      }\n\n      /* An ABSOLUTE target, not scrollBy. scrollBy is relative to the live\n         scrollLeft, so two clicks inside one smooth animation both measure\n         from the same mid-flight position and the second is swallowed \u2014 which\n         is exactly how people use a pair of arrows. */\n      function step(dir) {\n        measure();\n        var max  = maxScroll();\n        var base = rail.scrollLeft;\n        if (target !== null && Math.abs(target - base) > 4) base = target;   /* still animating */\n\n        var t = cards.length\n          ? snapAt(nearestIndex(base) + dir * 2)\n          : base + dir * rail.clientWidth * 0.8;\n        t = Math.max(0, Math.min(max, t));\n\n        target = t;\n        setSnap(false);\n        try { rail.scrollTo({ left: t, behavior: reduce ? \"auto\" : \"smooth\" }); }\n        catch (e) { rail.scrollLeft = t; }        /* older engines: no options object */\n\n        /* If the smooth scroll lands a few subpixels off `t` the settle test\n           in sync() never fires and `target` would stick forever. */\n        if (giveUp) window.clearTimeout(giveUp);\n        giveUp = window.setTimeout(function () { target = null; settle(); sync(); },\n                                   reduce ? 60 : 900);\n        sync();\n      }\n\n      function sync() {\n        var max = maxScroll() - 2;\n        if (target !== null && Math.abs(rail.scrollLeft - target) <= 4) { target = null; settle(); }\n        if (prev) prev.disabled = rail.scrollLeft <= 0;\n        if (next) next.disabled = rail.scrollLeft >= max;\n      }\n\n      /* User takeover: drop the pending target and give snap back at once.\n         pointerdown/touchstart fire before the drag moves the rail, so the\n         gesture itself is snapped, which is what a reader expects. */\n      function takeover() {\n        target = null;\n        if (giveUp) { window.clearTimeout(giveUp); giveUp = null; }\n        setSnap(true);\n      }\n\n      if (prev) prev.addEventListener(\"click\", function () { step(-1); });\n      if (next) next.addEventListener(\"click\", function () { step(1); });\n      [\"wheel\", \"pointerdown\", \"touchstart\", \"keydown\"].forEach(function (ev) {\n        rail.addEventListener(ev, takeover, { passive: true });\n      });\n      rail.addEventListener(\"scroll\", sync, { passive: true });\n      window.addEventListener(\"resize\", sync, { passive: true });\n      state.railSyncs.push(sync);\n      measure();\n      sync();\n    });\n  }\n\n  /* \u2550\u2550 7 \u00B7 AUTOPLAY NUDGE (document-level, installed once) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n     Some browsers refuse muted autoplay until a gesture, and some only settle\n     once data has arrived. Try now, and once on first interaction. */\n  var nudged = false;\n  function playAll() {\n    if (reduce || save) return;\n    for (var i = roots.length - 1; i >= 0; i--) {\n      if (!live(roots[i])) { roots.splice(i, 1); continue; }\n      all(roots[i], OURS).forEach(function (v) {\n        if (!v.paused) return;\n        /* The Pour and the sign-off carry a REAL src on their <source>\n           children (src is required, and the no-JS page needs them), so this\n           nudge must not start them before the lazy observer says so \u2014\n           play() would fetch two full-viewport films at load. */\n        if ((v.dataset.lazy || v.dataset.poster) && !v.dataset.hydrated) return;\n        if (!v.currentSrc && !v.src && !one(v, \"source[src]\")) return;\n        tryPlay(v);\n      });\n    }\n  }\n  function installNudge() {\n    if (nudged || reduce || save) return;\n    nudged = true;\n    [\"pointerdown\", \"keydown\", \"touchstart\"].forEach(function (ev) {\n      window.addEventListener(ev, playAll, { once: true, passive: true });\n    });\n  }\n\n  /* \u2550\u2550 8 \u00B7 DEV ASSERTIONS \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n     The sticky failure is invisible until someone scrolls, so it gets a\n     console warning rather than a silent dead hero. This is the single most\n     useful thing in the file for this port: it names, by tag and id, any\n     vendor-theme or app-injected wrapper that has been dropped between\n     <body> and the pin.\n\n     It walks OUT of the .sav-forma root by design \u2014 the offender is almost\n     certainly #shopify-section-\u2026 , #MainContent or <main>, all of which are\n     above the root. It only reads computed styles; it changes nothing. */\n  var assertedOverflow = false;\n  function describe(n) {\n    return (n.tagName || \"?\").toLowerCase() +\n           (n.id ? \"#\" + n.id : \"\") +\n           (n.className && typeof n.className === \"string\" && n.className.trim()\n              ? \".\" + n.className.trim().split(/\\s+/).slice(0, 3).join(\".\") : \"\");\n  }\n  function assertSticky(root) {\n    var sticky = one(root, \".hero\") || one(root, \".pour\");\n    if (!sticky) return;\n    var n = sticky.parentNode, bad = [];\n    while (n && n.nodeType === 1) {\n      var cs;\n      try { cs = getComputedStyle(n); } catch (e) { break; }\n      var isRoot = (n === doc || n === document.body);\n\n      /* Any non-root ancestor with overflow other than visible/clip kills the\n         pin. html/body overflow-x:hidden is measurably harmless \u2014 overflow\n         propagates to the viewport \u2014 so they are exempt from this test only. */\n      if (!isRoot) {\n        var ox = cs.overflowX, oy = cs.overflowY;\n        if ((ox !== \"visible\" && ox !== \"clip\") || (oy !== \"visible\" && oy !== \"clip\")) {\n          bad.push(describe(n) + \"  overflow:\" + ox + \"/\" + oy);\n        }\n      }\n      /* Constraint 1. A transform on ANY ancestor \u2014 including <html> \u2014 makes\n         that ancestor the containing block and kills position:sticky in\n         WebKit. filter, perspective, backdrop-filter, contain:paint|layout\n         and will-change:transform do exactly the same thing. */\n      if (cs.transform && cs.transform !== \"none\")        bad.push(describe(n) + \"  transform:\" + cs.transform);\n      if (cs.filter && cs.filter !== \"none\")              bad.push(describe(n) + \"  filter:\" + cs.filter);\n      if (cs.perspective && cs.perspective !== \"none\")    bad.push(describe(n) + \"  perspective:\" + cs.perspective);\n      if (cs.backdropFilter && cs.backdropFilter !== \"none\") bad.push(describe(n) + \"  backdrop-filter:\" + cs.backdropFilter);\n      if (cs.contain && /paint|layout|strict|content/.test(cs.contain)) bad.push(describe(n) + \"  contain:\" + cs.contain);\n      if (cs.willChange && /transform|filter|perspective/.test(cs.willChange)) bad.push(describe(n) + \"  will-change:\" + cs.willChange);\n\n      n = n.parentNode;\n    }\n    if (bad.length) {\n      warn(\"[79th] position:sticky on .\" + (one(root, \".hero\") ? \"hero\" : \"pour\") +\n           \" is disabled by an ancestor. Use overflow-x:clip and remove the transform.\\n\" +\n           uniq(bad).join(\"\\n\"));\n    }\n    if (!assertedOverflow && doc.scrollWidth > doc.clientWidth + 1) {\n      assertedOverflow = true;\n      warn(\"[79th] horizontal overflow: \" + doc.scrollWidth + \" > \" + doc.clientWidth);\n    }\n  }\n\n  /* \u2550\u2550 9 \u00B7 BOOT / MOUNT / UNMOUNT \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n  function forceOpen(root) {\n    /* Last-resort visibility. Called when a root's boot threw. Mirrors the\n       inline boot guard, scoped to the root that failed. */\n    try {\n      all(root, \"[data-reveal]\").forEach(function (el) { el.classList.add(\"in\"); });\n      var s = one(root, \".hero .sig\") || one(root, \".hero-foot .sig\");\n      if (s) {\n        s.classList.add(\"ready\");\n        doc.classList.remove(\"sav-wipe\");\n        /* .ready alone is NOT enough. `.js .sav-forma .sig{opacity:0}` is only\n           lifted by the sigFade/sigDraw ANIMATION (fill:both) \u2014 there is no\n           plain `opacity:1` declaration on .sig.ready outside the .sav-wipe and\n           reduced-motion branches. An animation that never runs to completion\n           holds its FROM value, i.e. opacity 0, and the hero signature stays\n           invisible while every other element is open. Measured: with the\n           animation frozen, computed opacity on .sig.ready reads 0.\n           This inline write cannot affect a healthy page \u2014 forceOpen only runs\n           after a boot threw \u2014 and a running animation still overrides it. */\n        s.style.opacity = \"1\";\n        s.style.webkitMaskImage = \"none\";\n        s.style.maskImage = \"none\";\n      }\n    } catch (e) {}\n  }\n\n  function boot(root) {\n    var state = { io: null, vio: null, sig: null, sigTimer: null, sigCap: null,\n                  assertTimer: null, railSyncs: [], vids: [] };\n    root.__savState = state;\n\n    bootReveals(root, state);\n    bootSignature(root, state);\n    bootMedia(root, state);\n    bootRails(root, state);\n\n    /* Prune first. frame() is the only place that drops dead entries from\n       `paras`, and it returns before the prune loop under reduced motion \u2014 so\n       under `reduce` the array would grow by one node on every theme-editor\n       re-render and never shrink. targets/vlazy are pruned by sweep()/vsweep(),\n       which have no such early return, so only this list needs the help. */\n    for (var pi = paras.length - 1; pi >= 0; pi--) {\n      if (!live(paras[pi])) paras.splice(pi, 1);\n    }\n    all(root, \"[data-parallax]\").forEach(function (el) {\n      if (paras.indexOf(el) === -1) paras.push(el);\n    });\n\n    if (targets.length || paras.length || vlazy.length) listen();\n    installNudge();\n\n    /* Initial pass. sweep() first so anything already above the fold at first\n       paint (the whole of Panel A on a tall desktop) never waits on a scroll. */\n    sweep();\n    vsweep();\n    frame();\n    playAll();\n\n    state.assertTimer = window.setTimeout(function () { assertSticky(root); }, 1200);\n  }\n\n  function unmount(root) {\n    var state = root.__savState;\n    if (state) {\n      if (state.io)  { try { state.io.disconnect(); }  catch (e) {} }\n      if (state.vio) { try { state.vio.disconnect(); } catch (e) {} }\n      if (state.sigTimer)    window.clearTimeout(state.sigTimer);\n      if (state.sigCap)      window.clearTimeout(state.sigCap);\n      if (state.assertTimer) window.clearTimeout(state.assertTimer);\n      state.railSyncs.forEach(function (fn) {\n        try { window.removeEventListener(\"resize\", fn); } catch (e) {}\n      });\n      root.__savState = null;\n    }\n    var i = roots.indexOf(root);\n    if (i > -1) roots.splice(i, 1);\n    /* targets/paras belonging to this root fall out of the shared lists on\n       their next visit via live(); nothing else is needed. */\n    try { delete root.dataset.savBooted; } catch (e) { root.dataset.savBooted = \"\"; }\n  }\n\n  function collect(scope) {\n    var s = scope && scope.nodeType ? scope : document;\n    var list = [];\n    if (s.nodeType === 1 && s.classList && s.classList.contains(\"sav-forma\")) list.push(s);\n    return uniq(list.concat(all(s, \".sav-forma\")));\n  }\n\n  /* Reap roots whose DOM was replaced without a shopify:section:unload.\n     unmount() is the only thing that removes a rail's window-resize `sync`\n     listener and clears its timers, and it only runs on the unload event. The\n     editor normally fires unload before load, but a section re-render that\n     swaps innerHTML directly (an app, a Section Rendering API call, a theme\n     that re-renders on its own) produces load with no unload \u2014 and then every\n     re-render leaves another pair of resize listeners bound to a detached\n     rail, plus an IntersectionObserver that is never disconnected. */\n  function reap() {\n    for (var i = roots.length - 1; i >= 0; i--) {\n      if (!live(roots[i])) unmount(roots[i]);\n    }\n  }\n\n  function mount(scope) {\n    reap();\n    var found = collect(scope);\n\n    /* SAFETY NET. If the root class never made it into the Liquid, the CSS is\n       scoped to a class that does not exist, so nothing is hidden and nothing\n       is styled \u2014 but nothing works either, and the failure is silent. Adopt\n       the nearest sensible container so the rails, the lazy films and the\n       signature still run, and say so loudly. The nudge and the reduced-\n       motion pass are selector-scoped (OURS), so a wide root cannot reach a\n       theme video. */\n    if (!found.length) {\n      var probe = one(scope && scope.nodeType ? scope : document, \".pin .hero, .hero-foot .sig, [data-rail-nav]\");\n      if (probe) {\n        var host = probe.closest ? probe.closest(\".shopify-section\") : null;\n        found = [host || document.body];\n        warn(\"[79th] no .sav-forma root found \u2014 the stylesheet is scoped to it. \" +\n             \"Falling back to \" + describe(found[0]) + \". Add class=\\\"sav-forma\\\" to the section wrapper.\");\n      }\n    }\n\n    found.forEach(function (root) {\n      if (!root) return;\n\n      /* THE GUARD IS AN EXPANDO, NOT AN ATTRIBUTE, AND THAT IS DELIBERATE.\n         A `data-sav-booted` attribute is serialised by innerHTML. Anything\n         that round-trips this DOM through a string after boot \u2014 a bfcache\n         restore, an app that clones a section, a cached fragment \u2014 would hand\n         back markup that already claims to be booted, the boot would be\n         skipped, and every [data-reveal] node would stay at opacity:0. A blank\n         homepage, from a guard whose whole job is to prevent trouble.\n         Reproduced exactly that way while testing this port. An expando\n         property does not survive serialisation, so a fresh element always\n         boots and only the very same element is ever skipped. */\n      if (root.__savState) return;\n\n      if (roots.indexOf(root) === -1) roots.push(root);\n      try { boot(root); }\n      catch (e) {\n        forceOpen(root);\n        err(\"[79th] sav-forma boot failed for \" + describe(root) + \" \u2014 reveals forced open.\", e);\n      }\n      /* Informational only \u2014 for the post-deploy console checklist. Never read\n         as a guard. */\n      try { if (root.dataset) root.dataset.savBooted = \"1\"; } catch (e2) {}\n    });\n  }\n\n  if (document.readyState !== \"loading\") mount();\n  else document.addEventListener(\"DOMContentLoaded\", function () { mount(); });\n\n  /* Theme editor. Shopify replaces the section's DOM on every setting change;\n     the fresh nodes carry no dataset flag, so they boot, and a merely\n     re-fired event on an unchanged root does not double-bind. */\n  document.addEventListener(\"shopify:section:load\", function (e) {\n    try { mount(e.target); } catch (err2) { err(\"[79th] section:load mount failed\", err2); }\n  });\n  document.addEventListener(\"shopify:section:unload\", function (e) {\n    try { collect(e.target).forEach(unmount); } catch (err2) {}\n  });\n  /* Selecting a block or section in the editor scrolls it into view without\n     always producing a scroll event \u2014 the exact case the 500ms poll exists\n     for. Give it a direct nudge as well; both are cheap. */\n  [\"shopify:section:select\", \"shopify:block:select\", \"shopify:section:reorder\"].forEach(function (ev) {\n    document.addEventListener(ev, function () { sweep(); vsweep(); frame(); });\n  });\n\n  /* Debug handle for the post-deploy console checklist. Namespaced; nothing\n     in theme.js uses the prefix (checked). */\n  window.__savForma = {\n    mount: mount,\n    sweep: function () { sweep(); vsweep(); },\n    roots: roots,\n    pending: function () { return targets.length; },\n    pendingVideos: function () { return vlazy.length; },\n    flags: { reduce: reduce, save: save, design: design, wipe: wipeOK, io: hasIO }\n  };\n\n  /* Reached only if everything above ran. THIS MUST STAY THE LAST STATEMENT.\n     The separate guard script reads it \u2014 the live copy is the inline <script>\n     at the end of sections/sav-forma-home.liquid's body, NOT the superseded\n     build/sav-forma-boot-guard.liquid, which must not be deployed. */\n  window.__savBooted = true;\n})();\n"],
  "mappings": "CA0CC,UAAY,CACX,aAKA,GAAI,OAAO,iBAAkB,OAC7B,OAAO,iBAAmB,GAE1B,IAAI,IAAU,SAAS,gBACnB,OAAU,CAAC,EAAE,OAAO,YAAc,OAAO,WAAW,kCAAkC,EAAE,SACxF,KAAU,CAAC,EAAE,UAAU,YAAc,UAAU,WAAW,UAC1D,OAAU,CAAC,EAAE,OAAO,SAAW,OAAO,QAAQ,YAC9C,MAAU,yBAA0B,OACpC,SAAW,OAAO,QAMlB,KAAO,2FAGX,SAAS,IAAI,MAAO,IAAK,CACvB,GAAI,CAAC,OAAS,CAAC,MAAM,iBAAkB,MAAO,CAAC,EAC/C,GAAI,CAAE,MAAO,CAAC,EAAE,MAAM,KAAK,MAAM,iBAAiB,GAAG,CAAC,CAAG,OAAS,EAAG,CAAE,MAAO,CAAC,CAAG,CACpF,CACA,SAAS,IAAI,MAAO,IAAK,CACvB,GAAI,CAAC,OAAS,CAAC,MAAM,cAAe,OAAO,KAC3C,GAAI,CAAE,OAAO,MAAM,cAAc,GAAG,CAAG,OAAS,EAAG,CAAE,OAAO,IAAM,CACpE,CACA,SAAS,KAAK,GAAI,CAGhB,OAAK,GACD,OAAO,GAAG,aAAgB,UAAkB,GAAG,YAC5C,SAAS,SAAW,SAAS,SAAS,EAAE,EAAI,GAFnC,EAGlB,CACA,SAAS,KAAK,IAAK,CACjB,OAAO,IAAI,OAAO,SAAU,EAAG,EAAG,EAAG,CAAE,OAAO,GAAK,EAAE,QAAQ,CAAC,IAAM,CAAG,CAAC,CAC1E,CACA,SAAS,KAAK,IAAK,CAAM,UAAY,SAAS,MAAM,SAAS,KAAK,GAAG,CAAG,CACxE,SAAS,IAAI,IAAK,EAAG,CAAM,UAAY,SAAS,OAAO,SAAS,MAAM,IAAK,CAAC,CAAG,CAS/E,IAAI,OAAS,GACb,GAAI,CAAC,QAAU,OAAO,KAAO,OAAO,IAAI,iBACtC,GAAI,CACF,OAAO,IAAI,iBAAiB,CAC1B,KAAM,aAAc,OAAQ,eAAgB,SAAU,GAAO,aAAc,IAC7E,CAAC,EACD,OAAS,EACX,OAAS,EAAG,CAEV,OAAS,CAAC,EAAE,GAAK,EAAE,OAAS,2BAC9B,CAEE,QAAQ,IAAI,UAAU,IAAI,UAAU,EASxC,IAAI,MAAU,CAAC,EACX,QAAU,CAAC,EACX,MAAU,CAAC,EACX,MAAU,CAAC,EACX,OAAU,KACV,QAAU,GACV,OAAU,EACV,UAAY,GAWhB,SAAS,OAAQ,CACf,GAAK,QAAQ,OAEb,QADI,GAAK,OAAO,aAAe,IAAI,cAAgB,EAC1C,EAAI,QAAQ,OAAS,EAAG,GAAK,EAAG,IAAK,CAC5C,IAAI,GAAK,QAAQ,CAAC,EAClB,GAAI,CAAC,KAAK,EAAE,EAAG,CAAE,QAAQ,OAAO,EAAG,CAAC,EAAG,QAAU,CACjD,IAAI,EAAI,GAAG,sBAAsB,EAKjC,GAAI,EAAE,IAAM,GAAK,IAAM,CAErB,GADA,GAAG,UAAU,IAAI,IAAI,EACjB,GAAG,QAAS,CAAE,GAAI,CAAE,GAAG,QAAQ,UAAU,EAAE,CAAG,OAAS,EAAG,CAAC,CAAE,GAAG,QAAU,IAAM,CACpF,QAAQ,OAAO,EAAG,CAAC,CACrB,CACF,CACF,CAWA,SAAS,QAAS,CAChB,GAAK,MAAM,OACX,KAAI,GAAK,OAAO,aAAe,IAAI,cAAgB,EACnD,GAAK,GAEL,QADI,IAAM,GAAK,IACN,EAAI,MAAM,OAAS,EAAG,GAAK,EAAG,IAAK,CAC1C,IAAI,EAAI,MAAM,CAAC,EACf,GAAI,CAAC,KAAK,CAAC,GAAK,EAAE,QAAQ,SAAU,CAAE,MAAM,OAAO,EAAG,CAAC,EAAG,QAAU,CACpE,IAAI,EAAI,EAAE,sBAAsB,EAC5B,EAAE,IAAM,GAAK,KAAO,EAAE,OAAS,CAAC,MAAO,QAAQ,CAAC,EAAG,MAAM,OAAO,EAAG,CAAC,EAC1E,EACF,CAEA,SAAS,UAAW,CAAE,OAAO,QAAQ,OAAS,GAAK,MAAM,OAAS,CAAG,CAOrE,SAAS,WAAY,CACf,SAAW,MAAQ,CAAC,SAAS,IACjC,OAAS,OAAO,YAAY,UAAY,CACtC,MAAM,EACN,OAAO,EACF,SAAS,IAAK,OAAO,cAAc,MAAM,EAAG,OAAS,KAC5D,EAAG,GAAG,EACR,CAMA,SAAS,OAAQ,CAEf,GADA,QAAU,GACN,QACJ,KAAI,GAAK,OAAO,aAAe,EAC/B,GAAK,GACL,QAAS,EAAI,MAAM,OAAS,EAAG,GAAK,EAAG,IAAK,CAC1C,IAAI,GAAK,MAAM,CAAC,EAChB,GAAI,CAAC,KAAK,EAAE,EAAG,CAAE,MAAM,OAAO,EAAG,CAAC,EAAG,QAAU,CAC/C,IAAI,EAAI,GAAG,sBAAsB,EACjC,GAAI,IAAE,OAAS,MAAQ,EAAE,IAAM,GAAK,KACpC,KAAI,KAAS,EAAE,IAAM,EAAE,OAAS,EAAI,GAAK,GAAK,GAC1C,MAAQ,WAAW,GAAG,aAAa,YAAY,CAAC,GAAK,IACzD,GAAG,MAAM,UAAY,kBAAoB,IAAM,OAAO,QAAQ,CAAC,EAAI,QACrE,EACF,CAYA,SAAS,UAAW,CAClB,MAAM,EACN,OAAO,EACF,QAIM,KAAK,IAAI,EAAI,OAAS,MAM/B,OAAS,KAAK,IAAI,EAClB,MAAM,IAVN,QAAU,GACV,OAAU,KAAK,IAAI,EACnB,OAAO,sBAAsB,KAAK,EAUtC,CAEA,SAAS,QAAS,CACZ,YACJ,UAAY,GACZ,OAAO,iBAAiB,SAAU,SAAU,CAAE,QAAS,EAAK,CAAC,EAC7D,OAAO,iBAAiB,SAAU,SAAU,CAAE,QAAS,EAAK,CAAC,EAC7D,SAAS,iBAAiB,mBAAoB,QAAQ,EACxD,CAGA,SAAS,UAAU,KAAM,CACvB,KAAK,QAAQ,SAAU,GAAI,CAAE,GAAG,UAAU,IAAI,IAAI,CAAG,CAAC,CACxD,CAEA,SAAS,YAAY,KAAM,MAAO,CAChC,IAAI,KAAO,IAAI,KAAM,eAAe,EACpC,GAAK,KAAK,OAQV,IAAI,QAAU,QAAU,CAAC,MAAO,CAAE,UAAU,IAAI,EAAG,MAAQ,CAE3D,IAAI,GAAK,IAAI,qBAAqB,SAAU,QAAS,CACnD,QAAQ,QAAQ,SAAU,EAAG,CAC3B,GAAK,EAAE,eACP,GAAE,OAAO,UAAU,IAAI,IAAI,EAC3B,GAAI,CAAE,GAAG,UAAU,EAAE,MAAM,CAAG,OAAS,KAAM,CAAC,CAC9C,EAAE,OAAO,QAAU,KACnB,IAAI,EAAI,QAAQ,QAAQ,EAAE,MAAM,EAC5B,EAAI,IAAI,QAAQ,OAAO,EAAG,CAAC,EACjC,CAAC,CACH,EAAG,CAAE,UAAW,IAAM,WAAY,iBAAkB,CAAC,EAErD,KAAK,QAAQ,SAAU,GAAI,CACzB,GAAG,QAAU,GACb,QAAQ,KAAK,EAAE,EACf,GAAG,QAAQ,EAAE,CACf,CAAC,EACD,MAAM,GAAK,GACX,UAAU,EACZ,CAYA,SAAS,cAAc,KAAM,MAAO,CAClC,IAAI,IAAM,IAAI,KAAM,YAAY,GAAK,IAAI,KAAM,iBAAiB,EAChE,GAAK,IAKL,IAJA,MAAM,IAAM,IAEZ,IAAI,iBAAiB,eAAgB,UAAY,CAAE,IAAI,MAAM,WAAa,MAAQ,CAAC,EAE/E,OAAQ,CAAE,IAAI,UAAU,IAAI,OAAO,EAAG,MAAQ,CAElD,IAAI,IAAO,IAAI,IAAK,KAAK,EACrB,KAAO,GACP,GAAK,UAAY,CACf,OACJ,KAAO,GACP,MAAM,SAAW,OAAO,WAAW,UAAY,CAC7C,IAAI,MAAM,WAAa,aACvB,IAAI,UAAU,IAAI,OAAO,CAC3B,EAAG,OAAS,IAAM,GAAG,EACvB,EAEA,GAAI,KAAO,IAAI,OACb,GAAI,CAAE,IAAI,OAAO,EAAE,KAAK,GAAI,EAAE,CAAG,OAAS,EAAG,CAAE,GAAG,CAAG,MAC5C,KAAO,IAAI,SACpB,GAAG,EACM,MACT,IAAI,iBAAiB,OAAQ,EAAE,EAC/B,IAAI,iBAAiB,QAAS,EAAE,GAElC,MAAM,OAAS,OAAO,WAAW,GAAI,GAAG,EAC1C,CAUA,SAAS,QAAQ,EAAG,CAClB,GAAI,UAAU,MACd,GAAI,CAAE,IAAI,EAAI,EAAE,KAAK,EAAO,GAAK,EAAE,OAAO,EAAE,MAAM,UAAY,CAAC,CAAC,CAAG,OAAS,EAAG,CAAC,CAClF,CAEA,SAAS,QAAQ,EAAG,CAClB,GAAI,GAAC,GAAK,EAAE,QAAQ,UACpB,GAAE,QAAQ,SAAW,IACjB,EAAE,QAAQ,QAAU,CAAC,EAAE,SAAQ,EAAE,OAAS,EAAE,QAAQ,QACpD,EAAE,QAAQ,MAAQ,CAAC,EAAE,MAAK,EAAE,IAAM,EAAE,QAAQ,MAKhD,IAAI,EAAG,mBAAmB,EAAE,QAAQ,SAAU,EAAG,CAAE,EAAE,IAAM,EAAE,QAAQ,IAAM,CAAC,EAC5E,GAAI,CAAE,EAAE,KAAK,CAAG,OAAS,EAAG,CAAC,CAG7B,EAAE,iBAAiB,aAAc,UAAY,CAAE,QAAQ,CAAC,CAAG,EAAG,CAAE,KAAM,EAAK,CAAC,EAC5E,QAAQ,CAAC,EACX,CAEA,SAAS,UAAU,KAAM,MAAO,CAC9B,IAAI,KAAO,KAAK,IAAI,KAAM,IAAI,CAAC,EAC/B,GAAK,KAAK,OAGV,IAFA,MAAM,KAAO,KAET,KAAM,CAER,KAAK,QAAQ,SAAU,EAAG,CACpB,EAAE,QAAQ,QAAU,CAAC,EAAE,SAAQ,EAAE,OAAS,EAAE,QAAQ,QACxD,EAAE,QAAU,OACZ,GAAI,CAAE,EAAE,MAAM,CAAG,OAAS,EAAG,CAAC,CAChC,CAAC,EACD,MACF,CAEA,GAAI,OAAQ,CAIV,KAAK,QAAQ,SAAU,EAAG,CACpB,EAAE,QAAQ,QAAU,CAAC,EAAE,SAAQ,EAAE,OAAS,EAAE,QAAQ,QACxD,EAAE,gBAAgB,UAAU,EAC5B,GAAI,CAAE,EAAE,MAAM,EAAG,EAAE,YAAc,CAAG,OAAS,EAAG,CAAC,CACnD,CAAC,EACD,MACF,CAOA,GAFA,KAAK,QAAQ,SAAU,EAAG,CAAM,MAAM,QAAQ,CAAC,IAAM,IAAI,MAAM,KAAK,CAAC,CAAG,CAAC,EAErE,MAAO,CACT,IAAI,IAAM,IAAI,qBAAqB,SAAU,QAAS,CACpD,QAAQ,QAAQ,SAAU,EAAG,CAC3B,GAAK,EAAE,eACP,SAAQ,EAAE,MAAM,EAChB,GAAI,CAAE,IAAI,UAAU,EAAE,MAAM,CAAG,OAAS,KAAM,CAAC,EACjD,CAAC,CACH,EAAG,CAAE,WAAY,UAAW,CAAC,EAC7B,KAAK,QAAQ,SAAU,EAAG,CAAE,IAAI,QAAQ,CAAC,CAAG,CAAC,EAC7C,MAAM,IAAM,GACd,CACA,UAAU,EACZ,CAkBA,SAAS,UAAU,KAAM,MAAO,CAC9B,IAAI,KAAM,iBAAiB,EAAE,QAAQ,SAAU,IAAK,CAClD,IAAI,GAAO,IAAI,aAAa,eAAe,EACvC,KAAO,GAAK,SAAS,eAAe,EAAE,EAAI,KAM9C,GAAI,CAAC,KAEH,QADI,EAAI,IAAI,WACL,GAAK,EAAE,WAAa,GAAK,CAAC,MAAQ,KAAO,IAAI,EAAG,OAAO,EAAG,EAAI,EAAE,WAEzE,GAAI,CAAC,KAAM,OAEX,IAAI,KAAO,IAAI,IAAK,aAAa,EAC7B,KAAO,IAAI,IAAK,aAAa,EAE7B,OAAU,KACV,QAAU,GACV,MAAU,CAAC,EACX,OAAU,KAEd,SAAS,SAAU,CAAE,MAAQ,IAAI,KAAM,OAAO,CAAG,CAMjD,SAAS,OAAO,EAAG,CACjB,GAAI,CAAC,MAAM,OAAQ,MAAO,GAC1B,IAAI,EAAI,KAAK,IAAI,EAAG,KAAK,IAAI,MAAM,OAAS,EAAG,CAAC,CAAC,EACjD,OAAO,KAAK,IAAI,EAAG,MAAM,CAAC,EAAE,WAAa,MAAM,CAAC,EAAE,UAAU,CAC9D,CACA,SAAS,aAAa,EAAG,CAEvB,QADI,KAAO,EAAG,GAAK,IACV,EAAI,EAAG,EAAI,MAAM,OAAQ,IAAK,CACrC,IAAI,EAAI,KAAK,IAAI,OAAO,CAAC,EAAI,CAAC,EAC1B,EAAI,KAAM,GAAK,EAAG,KAAO,EAC/B,CACA,OAAO,IACT,CACA,SAAS,WAAY,CAAE,OAAO,KAAK,IAAI,EAAG,KAAK,YAAc,KAAK,WAAW,CAAG,CAEhF,SAAS,QAAQ,GAAI,CACd,KAAK,QACN,GAAU,UAAW,KAAK,MAAM,eAAiB,GAAI,QAAU,IACpD,UAAW,KAAK,MAAM,eAAiB,OAAQ,QAAU,IAC1E,CAKA,SAAS,QAAS,CAChB,GAAK,QACL,CAAK,MAAM,QAAQ,QAAQ,EAC3B,IAAI,EAAI,KAAK,WAAY,IAAM,UAAU,GACrC,CAAC,MAAM,QAAU,GAAK,GAAK,GAAK,IAAM,GAAK,KAAK,IAAI,OAAO,aAAa,CAAC,CAAC,EAAI,CAAC,GAAK,IACtF,QAAQ,EAAI,EAEhB,CAMA,SAAS,KAAK,IAAK,CACjB,QAAQ,EACR,IAAI,IAAO,UAAU,EACjB,KAAO,KAAK,WACZ,SAAW,MAAQ,KAAK,IAAI,OAAS,IAAI,EAAI,IAAG,KAAO,QAE3D,IAAI,EAAI,MAAM,OACV,OAAO,aAAa,IAAI,EAAI,IAAM,CAAC,EACnC,KAAO,IAAM,KAAK,YAAc,GACpC,EAAI,KAAK,IAAI,EAAG,KAAK,IAAI,IAAK,CAAC,CAAC,EAEhC,OAAS,EACT,QAAQ,EAAK,EACb,GAAI,CAAE,KAAK,SAAS,CAAE,KAAM,EAAG,SAAU,OAAS,OAAS,QAAS,CAAC,CAAG,OACjE,EAAG,CAAE,KAAK,WAAa,CAAG,CAI7B,QAAQ,OAAO,aAAa,MAAM,EACtC,OAAS,OAAO,WAAW,UAAY,CAAE,OAAS,KAAM,OAAO,EAAG,KAAK,CAAG,EAC/C,OAAS,GAAK,GAAG,EAC5C,KAAK,CACP,CAEA,SAAS,MAAO,CACd,IAAI,IAAM,UAAU,EAAI,EACpB,SAAW,MAAQ,KAAK,IAAI,KAAK,WAAa,MAAM,GAAK,IAAK,OAAS,KAAM,OAAO,GACpF,OAAM,KAAK,SAAW,KAAK,YAAc,GACzC,OAAM,KAAK,SAAW,KAAK,YAAc,IAC/C,CAKA,SAAS,UAAW,CAClB,OAAS,KACL,SAAU,OAAO,aAAa,MAAM,EAAG,OAAS,MACpD,QAAQ,EAAI,CACd,CAEI,MAAM,KAAK,iBAAiB,QAAS,UAAY,CAAE,KAAK,EAAE,CAAG,CAAC,EAC9D,MAAM,KAAK,iBAAiB,QAAS,UAAY,CAAE,KAAK,CAAC,CAAG,CAAC,EACjE,CAAC,QAAS,cAAe,aAAc,SAAS,EAAE,QAAQ,SAAU,GAAI,CACtE,KAAK,iBAAiB,GAAI,SAAU,CAAE,QAAS,EAAK,CAAC,CACvD,CAAC,EACD,KAAK,iBAAiB,SAAU,KAAM,CAAE,QAAS,EAAK,CAAC,EACvD,OAAO,iBAAiB,SAAU,KAAM,CAAE,QAAS,EAAK,CAAC,EACzD,MAAM,UAAU,KAAK,IAAI,EACzB,QAAQ,EACR,KAAK,CACP,CAAC,CACH,CAKA,IAAI,OAAS,GACb,SAAS,SAAU,CACjB,GAAI,UAAU,MACd,QAAS,EAAI,MAAM,OAAS,EAAG,GAAK,EAAG,IAAK,CAC1C,GAAI,CAAC,KAAK,MAAM,CAAC,CAAC,EAAG,CAAE,MAAM,OAAO,EAAG,CAAC,EAAG,QAAU,CACrD,IAAI,MAAM,CAAC,EAAG,IAAI,EAAE,QAAQ,SAAU,EAAG,CAClC,EAAE,UAKF,EAAE,QAAQ,MAAQ,EAAE,QAAQ,SAAW,CAAC,EAAE,QAAQ,UACnD,CAAC,EAAE,YAAc,CAAC,EAAE,KAAO,CAAC,IAAI,EAAG,aAAa,GACpD,QAAQ,CAAC,EACX,CAAC,CACH,CACF,CACA,SAAS,cAAe,CAClB,QAAU,QAAU,OACxB,OAAS,GACT,CAAC,cAAe,UAAW,YAAY,EAAE,QAAQ,SAAU,GAAI,CAC7D,OAAO,iBAAiB,GAAI,QAAS,CAAE,KAAM,GAAM,QAAS,EAAK,CAAC,CACpE,CAAC,EACH,CAYA,IAAI,iBAAmB,GACvB,SAAS,SAAS,EAAG,CACnB,OAAQ,EAAE,SAAW,KAAK,YAAY,GAC9B,EAAE,GAAK,IAAM,EAAE,GAAK,KACpB,EAAE,WAAa,OAAO,EAAE,WAAc,UAAY,EAAE,UAAU,KAAK,EAC/D,IAAM,EAAE,UAAU,KAAK,EAAE,MAAM,KAAK,EAAE,MAAM,EAAG,CAAC,EAAE,KAAK,GAAG,EAAI,GAC5E,CACA,SAAS,aAAa,KAAM,CAC1B,IAAI,OAAS,IAAI,KAAM,OAAO,GAAK,IAAI,KAAM,OAAO,EACpD,GAAK,OAEL,SADI,EAAI,OAAO,WAAY,IAAM,CAAC,EAC3B,GAAK,EAAE,WAAa,GAAG,CAC5B,IAAI,GACJ,GAAI,CAAE,GAAK,iBAAiB,CAAC,CAAG,OAAS,EAAG,CAAE,KAAO,CACrD,IAAI,OAAU,IAAM,KAAO,IAAM,SAAS,KAK1C,GAAI,CAAC,OAAQ,CACX,IAAI,GAAK,GAAG,UAAW,GAAK,GAAG,WAC1B,KAAO,WAAa,KAAO,QAAY,KAAO,WAAa,KAAO,SACrE,IAAI,KAAK,SAAS,CAAC,EAAI,cAAgB,GAAK,IAAM,EAAE,CAExD,CAKI,GAAG,WAAa,GAAG,YAAc,QAAe,IAAI,KAAK,SAAS,CAAC,EAAI,eAAiB,GAAG,SAAS,EACpG,GAAG,QAAU,GAAG,SAAW,QAAqB,IAAI,KAAK,SAAS,CAAC,EAAI,YAAc,GAAG,MAAM,EAC9F,GAAG,aAAe,GAAG,cAAgB,QAAW,IAAI,KAAK,SAAS,CAAC,EAAI,iBAAmB,GAAG,WAAW,EACxG,GAAG,gBAAkB,GAAG,iBAAmB,QAAQ,IAAI,KAAK,SAAS,CAAC,EAAI,qBAAuB,GAAG,cAAc,EAClH,GAAG,SAAW,8BAA8B,KAAK,GAAG,OAAO,GAAG,IAAI,KAAK,SAAS,CAAC,EAAI,aAAe,GAAG,OAAO,EAC9G,GAAG,YAAc,+BAA+B,KAAK,GAAG,UAAU,GAAG,IAAI,KAAK,SAAS,CAAC,EAAI,iBAAmB,GAAG,UAAU,EAEhI,EAAI,EAAE,UACR,CACI,IAAI,QACN,KAAK,+BAAiC,IAAI,KAAM,OAAO,EAAI,OAAS,QAC/D,+EACA,KAAK,GAAG,EAAE,KAAK,IAAI,CAAC,EAEvB,CAAC,kBAAoB,IAAI,YAAc,IAAI,YAAc,IAC3D,iBAAmB,GACnB,KAAK,+BAAiC,IAAI,YAAc,MAAQ,IAAI,WAAW,GAEnF,CAIA,SAAS,UAAU,KAAM,CAGvB,GAAI,CACF,IAAI,KAAM,eAAe,EAAE,QAAQ,SAAU,GAAI,CAAE,GAAG,UAAU,IAAI,IAAI,CAAG,CAAC,EAC5E,IAAI,EAAI,IAAI,KAAM,YAAY,GAAK,IAAI,KAAM,iBAAiB,EAC1D,IACF,EAAE,UAAU,IAAI,OAAO,EACvB,IAAI,UAAU,OAAO,UAAU,EAU/B,EAAE,MAAM,QAAU,IAClB,EAAE,MAAM,gBAAkB,OAC1B,EAAE,MAAM,UAAY,OAExB,OAAS,EAAG,CAAC,CACf,CAEA,SAAS,KAAK,KAAM,CAClB,IAAI,MAAQ,CAAE,GAAI,KAAM,IAAK,KAAM,IAAK,KAAM,SAAU,KAAM,OAAQ,KACxD,YAAa,KAAM,UAAW,CAAC,EAAG,KAAM,CAAC,CAAE,EACzD,KAAK,WAAa,MAElB,YAAY,KAAM,KAAK,EACvB,cAAc,KAAM,KAAK,EACzB,UAAU,KAAM,KAAK,EACrB,UAAU,KAAM,KAAK,EAOrB,QAAS,GAAK,MAAM,OAAS,EAAG,IAAM,EAAG,KAClC,KAAK,MAAM,EAAE,CAAC,GAAG,MAAM,OAAO,GAAI,CAAC,EAE1C,IAAI,KAAM,iBAAiB,EAAE,QAAQ,SAAU,GAAI,CAC7C,MAAM,QAAQ,EAAE,IAAM,IAAI,MAAM,KAAK,EAAE,CAC7C,CAAC,GAEG,QAAQ,QAAU,MAAM,QAAU,MAAM,SAAQ,OAAO,EAC3D,aAAa,EAIb,MAAM,EACN,OAAO,EACP,MAAM,EACN,QAAQ,EAER,MAAM,YAAc,OAAO,WAAW,UAAY,CAAE,aAAa,IAAI,CAAG,EAAG,IAAI,CACjF,CAEA,SAAS,QAAQ,KAAM,CACrB,IAAI,MAAQ,KAAK,WACjB,GAAI,MAAO,CACT,GAAI,MAAM,GAAO,GAAI,CAAE,MAAM,GAAG,WAAW,CAAG,OAAU,EAAG,CAAC,CAC5D,GAAI,MAAM,IAAO,GAAI,CAAE,MAAM,IAAI,WAAW,CAAG,OAAS,EAAG,CAAC,CACxD,MAAM,UAAa,OAAO,aAAa,MAAM,QAAQ,EACrD,MAAM,QAAa,OAAO,aAAa,MAAM,MAAM,EACnD,MAAM,aAAa,OAAO,aAAa,MAAM,WAAW,EAC5D,MAAM,UAAU,QAAQ,SAAU,GAAI,CACpC,GAAI,CAAE,OAAO,oBAAoB,SAAU,EAAE,CAAG,OAAS,EAAG,CAAC,CAC/D,CAAC,EACD,KAAK,WAAa,IACpB,CACA,IAAI,EAAI,MAAM,QAAQ,IAAI,EACtB,EAAI,IAAI,MAAM,OAAO,EAAG,CAAC,EAG7B,GAAI,CAAE,OAAO,KAAK,QAAQ,SAAW,OAAS,EAAG,CAAE,KAAK,QAAQ,UAAY,EAAI,CAClF,CAEA,SAAS,QAAQ,MAAO,CACtB,IAAI,EAAI,OAAS,MAAM,SAAW,MAAQ,SACtC,KAAO,CAAC,EACZ,OAAI,EAAE,WAAa,GAAK,EAAE,WAAa,EAAE,UAAU,SAAS,WAAW,GAAG,KAAK,KAAK,CAAC,EAC9E,KAAK,KAAK,OAAO,IAAI,EAAG,YAAY,CAAC,CAAC,CAC/C,CAUA,SAAS,MAAO,CACd,QAAS,EAAI,MAAM,OAAS,EAAG,GAAK,EAAG,IAChC,KAAK,MAAM,CAAC,CAAC,GAAG,QAAQ,MAAM,CAAC,CAAC,CAEzC,CAEA,SAAS,MAAM,MAAO,CACpB,KAAK,EACL,IAAI,MAAQ,QAAQ,KAAK,EASzB,GAAI,CAAC,MAAM,OAAQ,CACjB,IAAI,MAAQ,IAAI,OAAS,MAAM,SAAW,MAAQ,SAAU,8CAA8C,EAC1G,GAAI,MAAO,CACT,IAAI,KAAO,MAAM,QAAU,MAAM,QAAQ,kBAAkB,EAAI,KAC/D,MAAQ,CAAC,MAAQ,SAAS,IAAI,EAC9B,KAAK,0FACqB,SAAS,MAAM,CAAC,CAAC,EAAI,iDAAmD,CACpG,CACF,CAEA,MAAM,QAAQ,SAAU,KAAM,CAC5B,GAAK,MAYD,MAAK,WAET,CAAI,MAAM,QAAQ,IAAI,IAAM,IAAI,MAAM,KAAK,IAAI,EAC/C,GAAI,CAAE,KAAK,IAAI,CAAG,OACX,EAAG,CACR,UAAU,IAAI,EACd,IAAI,oCAAsC,SAAS,IAAI,EAAI,+BAA2B,CAAC,CACzF,CAGA,GAAI,CAAM,KAAK,UAAS,KAAK,QAAQ,UAAY,IAAK,OAAS,GAAI,CAAC,EACtE,CAAC,CACH,CAEI,SAAS,aAAe,UAAW,MAAM,EACxC,SAAS,iBAAiB,mBAAoB,UAAY,CAAE,MAAM,CAAG,CAAC,EAK3E,SAAS,iBAAiB,uBAAwB,SAAU,EAAG,CAC7D,GAAI,CAAE,MAAM,EAAE,MAAM,CAAG,OAAS,KAAM,CAAE,IAAI,mCAAoC,IAAI,CAAG,CACzF,CAAC,EACD,SAAS,iBAAiB,yBAA0B,SAAU,EAAG,CAC/D,GAAI,CAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,OAAO,CAAG,OAAS,KAAM,CAAC,CAC5D,CAAC,EAID,CAAC,yBAA0B,uBAAwB,yBAAyB,EAAE,QAAQ,SAAU,GAAI,CAClG,SAAS,iBAAiB,GAAI,UAAY,CAAE,MAAM,EAAG,OAAO,EAAG,MAAM,CAAG,CAAC,CAC3E,CAAC,EAID,OAAO,WAAa,CAClB,MAAO,MACP,MAAO,UAAY,CAAE,MAAM,EAAG,OAAO,CAAG,EACxC,MAAO,MACP,QAAS,UAAY,CAAE,OAAO,QAAQ,MAAQ,EAC9C,cAAe,UAAY,CAAE,OAAO,MAAM,MAAQ,EAClD,MAAO,CAAE,OAAQ,OAAQ,KAAM,KAAM,OAAQ,OAAQ,KAAM,OAAQ,GAAI,KAAM,CAC/E,EAMA,OAAO,YAAc,EACvB,GAAG",
  "names": []
}
