91 Plus

自由轉調、輕鬆練歌,打造 91 譜的最佳體驗!

2024-03-21 기준 버전입니다. 최신 버전을 확인하세요.

설치하기 전에, Greasy Fork는 이 스크립트에 사용자가 아닌 스크립트 작성자의 이익을 위한 기능인 역기능이 포함되어 있음을 알려드립니다.

이 스크립트는 사용자의 브라우징 활동을 추적하는 코드를 포함합니다. 스크립트 작성자의 설명: 使用 Google Analytics 了解使用情況

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name         91 Plus
// @namespace    https://github.com/DonkeyBear
// @version      1.7.0
// @author       DonkeyBear
// @description  自由轉調、輕鬆練歌,打造 91 譜的最佳體驗!
// @icon         https://www.91pu.com.tw/icons/favicon-32x32.png
// @match        *://www.91pu.com.tw/m/*
// @match        *://www.91pu.com.tw/song/*
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.global.prod.js
// @grant        GM_addStyle
// @grant        GM_getValue
// @grant        GM_setValue
// @antifeature  tracking  使用 Google Analytics 了解使用情況
// ==/UserScript==

(e=>{if(typeof GM_addStyle=="function"){GM_addStyle(e);return}const t=document.createElement("style");t.textContent=e,document.head.append(t)})(' @import"https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.min.css";#trigger-overlay[data-v-658df74c]{position:fixed;top:0;left:0;right:0;bottom:0;z-index:500}.bi[data-v-33d92514]{color:var(--2d5c579c);font-size:var(--0168355c);-webkit-text-stroke:var(--5c7f6b49) var(--2d5c579c)}.bi[data-v-33d92514]:before{transition:text-shadow .2s}.bi[active=true][data-v-33d92514]:before{text-shadow:0 0 .5rem rgb(75,156,169)}.toolbar-icon[data-v-2b5c1219]{cursor:pointer;padding:.25rem .75rem}.adjust-widget[data-v-1c41dc23]{display:flex}.adjust-widget .adjust-button[data-v-1c41dc23]{border:0;border-radius:.25rem;background:transparent}.adjust-widget .adjust-button[data-v-1c41dc23]:hover{background:rgba(0,0,0,.025)}.adjust-widget .adjust-button[data-v-1c41dc23]:disabled{opacity:.25}.adjust-widget .adjust-button.adjust-button-middle[data-v-1c41dc23]{flex-grow:1;color:var(--791a4684);font-size:calc(var(--37e19b46) * .75);font-weight:700}.adjust-widget .adjust-button.adjust-button-left[data-v-1c41dc23]{padding-right:1rem}.adjust-widget .adjust-button.adjust-button-right[data-v-1c41dc23]{padding-left:1rem}.slide-and-fade-enter-active[data-v-f161c46c],.slide-and-fade-leave-active[data-v-f161c46c]{transition:all .2s}.slide-and-fade-enter-from[data-v-f161c46c],.slide-and-fade-leave-to[data-v-f161c46c]{transform:translateY(10%);opacity:0}#plus91-sheet-popup[data-v-f161c46c]{position:absolute;left:0;right:0;bottom:100%;background:#fafafa;border:1px solid lightgray;padding:1rem 2rem;border-radius:1rem;margin:.5rem 1rem}.transpose-range-container[data-v-f161c46c]{margin-top:1rem}.transpose-range-container input[type=range][data-v-f161c46c]{width:100%}.instrument-select-container[data-v-f161c46c]{display:flex;border:1px solid lightgray;border-radius:.25rem;margin-top:1rem;background:white}.instrument-select-container .instrument-select-button[data-v-f161c46c]{width:33.3333333333%;border:0;border-right:1px solid lightgray;background:transparent;color:#666;padding:.5rem;font-size:.65rem;font-weight:700;cursor:pointer!important}.instrument-select-container .instrument-select-button[data-v-f161c46c]:last-child{border:0;border-radius:0 .25rem .25rem 0}.instrument-select-container .instrument-select-button[data-v-f161c46c]:first-child{border-radius:.25rem 0 0 .25rem}.instrument-select-container .instrument-select-button[data-v-f161c46c]:hover{background:whitesmoke}.chord-container .chord-name[data-v-1eb5094e]{font-size:.5rem;font-weight:900;color:#666;text-align:center}.chord-container .chord-chart[data-v-1eb5094e]{margin:-.6rem 0 -.25rem}.slide-and-fade-enter-active[data-v-84de48ae],.slide-and-fade-leave-active[data-v-84de48ae]{transition:all .2s}.slide-and-fade-enter-from[data-v-84de48ae],.slide-and-fade-leave-to[data-v-84de48ae]{transform:translateY(10%);opacity:0}#plus91-chord-popup[data-v-84de48ae]{position:absolute;left:0;right:0;bottom:100%;background:#fafafa;border:1px solid lightgray;border-radius:1rem;margin:.5rem 1rem;padding:1rem}#plus91-chord-popup .banner[data-v-84de48ae]{display:flex;align-items:center;background:rgba(75,156,169,.25);color:color-mix(in srgb,rgba(75,156,169,.65) 50%,black 50%);border-radius:.5rem;padding:.5rem .75rem;margin-bottom:.25rem}#plus91-chord-popup .banner section[data-v-84de48ae]{flex-grow:1;margin-left:.5rem}#plus91-chord-popup .chord-popup-container[data-v-84de48ae]{display:grid;grid-template-columns:repeat(6,1fr);column-gap:.5rem;padding-top:.4rem}.slide-and-fade-enter-active[data-v-eff17405],.slide-and-fade-leave-active[data-v-eff17405]{transition:all .2s}.slide-and-fade-enter-from[data-v-eff17405],.slide-and-fade-leave-to[data-v-eff17405]{transform:translateY(10%);opacity:0}#plus91-font-popup[data-v-eff17405]{position:absolute;left:0;right:0;bottom:100%;background:#fafafa;border:1px solid lightgray;padding:1rem 2rem;border-radius:1rem;margin:.5rem 1rem}.slide-and-fade-enter-active[data-v-e329f5af],.slide-and-fade-leave-active[data-v-e329f5af]{transition:all .2s}.slide-and-fade-enter-from[data-v-e329f5af],.slide-and-fade-leave-to[data-v-e329f5af]{transform:translateY(10%);opacity:0}#plus91-settings-popup[data-v-e329f5af]{position:absolute;left:0;right:0;bottom:100%;background:#fafafa;border:1px solid lightgray;border-radius:1rem;margin:.5rem 1rem;padding:1rem}#plus91-settings-popup .setting-item[data-v-e329f5af]{display:flex;align-items:center;justify-content:space-between;padding:.5rem 1rem;border-radius:.5rem;cursor:pointer}#plus91-settings-popup .setting-item[data-v-e329f5af]:hover{background:rgba(0,0,0,.05)}.icon-button[data-v-e9902592]{display:flex;flex-direction:column;align-items:center;cursor:pointer;padding:0 .6rem .4rem;border-radius:.25rem}.icon-button[data-v-e9902592]:hover{background:rgba(0,0,0,.025)}.icon-button .button-text[data-v-e9902592]{font-size:.5rem;color:var(--9047bc34)}.slide-and-fade-enter-active[data-v-d041b049],.slide-and-fade-leave-active[data-v-d041b049]{transition:all .2s}.slide-and-fade-enter-from[data-v-d041b049],.slide-and-fade-leave-to[data-v-d041b049]{transform:translateY(10%);opacity:0}#plus91-menu-popup[data-v-d041b049]{position:absolute;left:0;right:0;bottom:100%;background:#fafafa;border:1px solid lightgray;padding:1rem 2rem;border-radius:1rem;margin:.5rem 1rem}#plus91-menu-popup .menu-popup-container[data-v-d041b049]{display:flex;justify-content:space-around}.hotkey-item[data-v-9f1c2e95]{display:flex;justify-content:space-between;align-items:center;padding:0 .25rem;border-radius:.25rem;height:1.4rem}.hotkey-item[data-v-9f1c2e95]:nth-child(odd){background:rgba(0,0,0,.025)}.desc.title[data-v-9f1c2e95]{font-size:.55rem;color:#999}.hotkeys[data-v-9f1c2e95]{display:flex}.hr[data-v-9f1c2e95]{display:flex;flex-grow:1;border-top:1px solid lightgray;margin-left:.25rem}kbd[data-v-9f1c2e95]{font-size:.6rem;border:solid lightgray;border-width:1px .1rem .15rem;border-radius:.2rem;padding:0 .2rem;letter-spacing:-.025rem;color:#666;margin-left:.15rem}.slide-and-fade-enter-active[data-v-a88e7568],.slide-and-fade-leave-active[data-v-a88e7568]{transition:all .2s}.slide-and-fade-enter-from[data-v-a88e7568],.slide-and-fade-leave-to[data-v-a88e7568]{transform:translateY(10%);opacity:0}#plus91-hotkey-popup[data-v-a88e7568]{position:absolute;left:0;right:0;bottom:100%;background:#fafafa;border:1px solid lightgray;padding:1rem 2rem;border-radius:1rem;margin:.5rem 1rem}#plus91-hotkey-popup .hotkey-popup-container[data-v-a88e7568]{display:flex;color:#444}#plus91-hotkey-popup section[data-v-a88e7568]{flex-grow:1;width:50%;margin:-.1rem 0}#plus91-hotkey-popup section.left-part[data-v-a88e7568]{border-right:1px solid lightgray;margin-left:-.5rem;padding-right:.5rem}#plus91-hotkey-popup section.right-part[data-v-a88e7568]{padding-left:.5rem;margin-right:-.5rem}#plus91-hotkey-popup kbd[data-v-a88e7568]{font-size:.65rem;border:solid lightgray;border-width:1px .1rem .15rem;border-radius:.2rem;padding:0 .2rem;letter-spacing:-.025rem;color:#666}.slide-enter-active[data-v-a29224c8],.slide-leave-active[data-v-a29224c8]{transition:transform .2s}.slide-enter-from[data-v-a29224c8],.slide-leave-to[data-v-a29224c8]{transform:translateY(100%)}#plus91-footer[data-v-a29224c8]{z-index:1000;display:flex;justify-content:center;position:fixed;left:0;right:0;bottom:0}.footer-container[data-v-a29224c8]{width:min(100vw,768px);background:rgba(75,156,169,.65);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);padding:.25rem .5rem .75rem;display:flex;justify-content:space-between;align-items:center;border-radius:1rem 1rem 0 0;border:1px solid rgb(90,140,160);border-bottom:0}.slide-enter-active[data-v-265bcfd2],.slide-leave-active[data-v-265bcfd2]{transition:transform .2s}.slide-enter-from[data-v-265bcfd2],.slide-leave-to[data-v-265bcfd2]{transform:translateY(-100%)}#plus91-header[data-v-265bcfd2]{z-index:1000;display:flex;justify-content:center;position:fixed;left:0;right:0;top:0}.header-container[data-v-265bcfd2]{width:min(100vw,768px);background:rgba(75,156,169,.65);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);padding:.25rem .5rem;display:flex;justify-content:space-between;align-items:center;border-radius:0 0 1rem 1rem;border:1px solid rgb(90,140,160);border-top:0}.header-container input[data-v-265bcfd2]{flex-grow:1;width:100%;border-radius:50rem;border:0;font-size:.8rem;font-weight:700;padding:.35rem 1.25rem;background:rgba(255,255,255,.6666666667);color:#0009;opacity:.5;transition:all .2s}.header-container input[data-v-265bcfd2]:focus-visible{outline:0;opacity:1}.fade-enter-active[data-v-e9c78cc3],.fade-leave-active[data-v-e9c78cc3]{transition:opacity .2s}.fade-enter-from[data-v-e9c78cc3],.fade-leave-to[data-v-e9c78cc3]{opacity:0}#dark-mode-overlay[data-v-e9c78cc3]{position:fixed;top:0;left:0;right:0;bottom:0;z-index:800;-webkit-backdrop-filter:invert(1) hue-rotate(145deg) saturate(.75);backdrop-filter:invert(1) hue-rotate(145deg) saturate(.75);pointer-events:none}html{background:#fafafa url(/templets/pu/images/tone-bg.gif)}#vue-91plus{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,sans-serif}.tfunc2{margin:10px}#mtitle{font-family:system-ui}input[type=range],input[type=range]::-webkit-slider-thumb,input[type=range]::-webkit-slider-runnable-track{-webkit-appearance:none;box-shadow:none}input[type=range]::-webkit-slider-thumb,input[type=range]::-webkit-slider-runnable-track{border:1px solid rgba(68,68,68,.25)}input[type=range]::-webkit-slider-thumb{background:#60748d}#viptoneWindow.window,#bottomad,.update_vip_bar,.wmask,header,footer,.autoscroll,.backplace,.set .keys,.set .plays,.set .clear,.setint .hr:nth-child(4),.setint .hr:nth-child(5),.setint .hr:nth-child(6),.adsbygoogle{display:none!important} ');

(function (vue) {
  'use strict';

  var __defProp = Object.defineProperty;
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
  var __publicField = (obj, key, value) => {
    __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
    return value;
  };
  var __accessCheck = (obj, member, msg) => {
    if (!member.has(obj))
      throw TypeError("Cannot " + msg);
  };
  var __privateGet = (obj, member, getter) => {
    __accessCheck(obj, member, "read from private field");
    return getter ? getter.call(obj) : member.get(obj);
  };
  var __privateAdd = (obj, member, value) => {
    if (member.has(obj))
      throw TypeError("Cannot add the same private member more than once");
    member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
  };
  var __privateSet = (obj, member, value, setter) => {
    __accessCheck(obj, member, "write to private field");
    setter ? setter.call(obj, value) : member.set(obj, value);
    return value;
  };
  var __privateMethod = (obj, member, method) => {
    __accessCheck(obj, member, "access private method");
    return method;
  };
  var _unformat, unformat_fn, _store, _watchTranspose, watchTranspose_fn, _watchFontSize, watchFontSize_fn;
  var isVue2 = false;
  /*!
   * pinia v2.1.7
   * (c) 2023 Eduardo San Martin Morote
   * @license MIT
   */
  let activePinia;
  const setActivePinia = (pinia2) => activePinia = pinia2;
  const piniaSymbol = (
    /* istanbul ignore next */
    Symbol()
  );
  function isPlainObject(o) {
    return o && typeof o === "object" && Object.prototype.toString.call(o) === "[object Object]" && typeof o.toJSON !== "function";
  }
  var MutationType;
  (function(MutationType2) {
    MutationType2["direct"] = "direct";
    MutationType2["patchObject"] = "patch object";
    MutationType2["patchFunction"] = "patch function";
  })(MutationType || (MutationType = {}));
  function createPinia() {
    const scope = vue.effectScope(true);
    const state = scope.run(() => vue.ref({}));
    let _p = [];
    let toBeInstalled = [];
    const pinia2 = vue.markRaw({
      install(app) {
        setActivePinia(pinia2);
        {
          pinia2._a = app;
          app.provide(piniaSymbol, pinia2);
          app.config.globalProperties.$pinia = pinia2;
          toBeInstalled.forEach((plugin) => _p.push(plugin));
          toBeInstalled = [];
        }
      },
      use(plugin) {
        if (!this._a && !isVue2) {
          toBeInstalled.push(plugin);
        } else {
          _p.push(plugin);
        }
        return this;
      },
      _p,
      // it's actually undefined here
      // @ts-expect-error
      _a: null,
      _e: scope,
      _s: /* @__PURE__ */ new Map(),
      state
    });
    return pinia2;
  }
  const noop$1 = () => {
  };
  function addSubscription(subscriptions, callback, detached, onCleanup = noop$1) {
    subscriptions.push(callback);
    const removeSubscription = () => {
      const idx = subscriptions.indexOf(callback);
      if (idx > -1) {
        subscriptions.splice(idx, 1);
        onCleanup();
      }
    };
    if (!detached && vue.getCurrentScope()) {
      vue.onScopeDispose(removeSubscription);
    }
    return removeSubscription;
  }
  function triggerSubscriptions(subscriptions, ...args) {
    subscriptions.slice().forEach((callback) => {
      callback(...args);
    });
  }
  const fallbackRunWithContext = (fn) => fn();
  function mergeReactiveObjects(target, patchToApply) {
    if (target instanceof Map && patchToApply instanceof Map) {
      patchToApply.forEach((value, key) => target.set(key, value));
    }
    if (target instanceof Set && patchToApply instanceof Set) {
      patchToApply.forEach(target.add, target);
    }
    for (const key in patchToApply) {
      if (!patchToApply.hasOwnProperty(key))
        continue;
      const subPatch = patchToApply[key];
      const targetValue = target[key];
      if (isPlainObject(targetValue) && isPlainObject(subPatch) && target.hasOwnProperty(key) && !vue.isRef(subPatch) && !vue.isReactive(subPatch)) {
        target[key] = mergeReactiveObjects(targetValue, subPatch);
      } else {
        target[key] = subPatch;
      }
    }
    return target;
  }
  const skipHydrateSymbol = (
    /* istanbul ignore next */
    Symbol()
  );
  function shouldHydrate(obj) {
    return !isPlainObject(obj) || !obj.hasOwnProperty(skipHydrateSymbol);
  }
  const { assign } = Object;
  function isComputed(o) {
    return !!(vue.isRef(o) && o.effect);
  }
  function createOptionsStore(id, options, pinia2, hot) {
    const { state, actions, getters } = options;
    const initialState = pinia2.state.value[id];
    let store;
    function setup() {
      if (!initialState && true) {
        {
          pinia2.state.value[id] = state ? state() : {};
        }
      }
      const localState = vue.toRefs(pinia2.state.value[id]);
      return assign(localState, actions, Object.keys(getters || {}).reduce((computedGetters, name) => {
        computedGetters[name] = vue.markRaw(vue.computed(() => {
          setActivePinia(pinia2);
          const store2 = pinia2._s.get(id);
          return getters[name].call(store2, store2);
        }));
        return computedGetters;
      }, {}));
    }
    store = createSetupStore(id, setup, options, pinia2, hot, true);
    return store;
  }
  function createSetupStore($id, setup, options = {}, pinia2, hot, isOptionsStore) {
    let scope;
    const optionsForPlugin = assign({ actions: {} }, options);
    const $subscribeOptions = {
      deep: true
      // flush: 'post',
    };
    let isListening;
    let isSyncListening;
    let subscriptions = [];
    let actionSubscriptions = [];
    let debuggerEvents;
    const initialState = pinia2.state.value[$id];
    if (!isOptionsStore && !initialState && true) {
      {
        pinia2.state.value[$id] = {};
      }
    }
    vue.ref({});
    let activeListener;
    function $patch(partialStateOrMutator) {
      let subscriptionMutation;
      isListening = isSyncListening = false;
      if (typeof partialStateOrMutator === "function") {
        partialStateOrMutator(pinia2.state.value[$id]);
        subscriptionMutation = {
          type: MutationType.patchFunction,
          storeId: $id,
          events: debuggerEvents
        };
      } else {
        mergeReactiveObjects(pinia2.state.value[$id], partialStateOrMutator);
        subscriptionMutation = {
          type: MutationType.patchObject,
          payload: partialStateOrMutator,
          storeId: $id,
          events: debuggerEvents
        };
      }
      const myListenerId = activeListener = Symbol();
      vue.nextTick().then(() => {
        if (activeListener === myListenerId) {
          isListening = true;
        }
      });
      isSyncListening = true;
      triggerSubscriptions(subscriptions, subscriptionMutation, pinia2.state.value[$id]);
    }
    const $reset = isOptionsStore ? function $reset2() {
      const { state } = options;
      const newState = state ? state() : {};
      this.$patch(($state) => {
        assign($state, newState);
      });
    } : (
      /* istanbul ignore next */
      noop$1
    );
    function $dispose() {
      scope.stop();
      subscriptions = [];
      actionSubscriptions = [];
      pinia2._s.delete($id);
    }
    function wrapAction(name, action) {
      return function() {
        setActivePinia(pinia2);
        const args = Array.from(arguments);
        const afterCallbackList = [];
        const onErrorCallbackList = [];
        function after2(callback) {
          afterCallbackList.push(callback);
        }
        function onError(callback) {
          onErrorCallbackList.push(callback);
        }
        triggerSubscriptions(actionSubscriptions, {
          args,
          name,
          store,
          after: after2,
          onError
        });
        let ret;
        try {
          ret = action.apply(this && this.$id === $id ? this : store, args);
        } catch (error) {
          triggerSubscriptions(onErrorCallbackList, error);
          throw error;
        }
        if (ret instanceof Promise) {
          return ret.then((value) => {
            triggerSubscriptions(afterCallbackList, value);
            return value;
          }).catch((error) => {
            triggerSubscriptions(onErrorCallbackList, error);
            return Promise.reject(error);
          });
        }
        triggerSubscriptions(afterCallbackList, ret);
        return ret;
      };
    }
    const partialStore = {
      _p: pinia2,
      // _s: scope,
      $id,
      $onAction: addSubscription.bind(null, actionSubscriptions),
      $patch,
      $reset,
      $subscribe(callback, options2 = {}) {
        const removeSubscription = addSubscription(subscriptions, callback, options2.detached, () => stopWatcher());
        const stopWatcher = scope.run(() => vue.watch(() => pinia2.state.value[$id], (state) => {
          if (options2.flush === "sync" ? isSyncListening : isListening) {
            callback({
              storeId: $id,
              type: MutationType.direct,
              events: debuggerEvents
            }, state);
          }
        }, assign({}, $subscribeOptions, options2)));
        return removeSubscription;
      },
      $dispose
    };
    const store = vue.reactive(partialStore);
    pinia2._s.set($id, store);
    const runWithContext = pinia2._a && pinia2._a.runWithContext || fallbackRunWithContext;
    const setupStore = runWithContext(() => pinia2._e.run(() => (scope = vue.effectScope()).run(setup)));
    for (const key in setupStore) {
      const prop = setupStore[key];
      if (vue.isRef(prop) && !isComputed(prop) || vue.isReactive(prop)) {
        if (!isOptionsStore) {
          if (initialState && shouldHydrate(prop)) {
            if (vue.isRef(prop)) {
              prop.value = initialState[key];
            } else {
              mergeReactiveObjects(prop, initialState[key]);
            }
          }
          {
            pinia2.state.value[$id][key] = prop;
          }
        }
      } else if (typeof prop === "function") {
        const actionValue = wrapAction(key, prop);
        {
          setupStore[key] = actionValue;
        }
        optionsForPlugin.actions[key] = prop;
      } else
        ;
    }
    {
      assign(store, setupStore);
      assign(vue.toRaw(store), setupStore);
    }
    Object.defineProperty(store, "$state", {
      get: () => pinia2.state.value[$id],
      set: (state) => {
        $patch(($state) => {
          assign($state, state);
        });
      }
    });
    pinia2._p.forEach((extender) => {
      {
        assign(store, scope.run(() => extender({
          store,
          app: pinia2._a,
          pinia: pinia2,
          options: optionsForPlugin
        })));
      }
    });
    if (initialState && isOptionsStore && options.hydrate) {
      options.hydrate(store.$state, initialState);
    }
    isListening = true;
    isSyncListening = true;
    return store;
  }
  function defineStore(idOrOptions, setup, setupOptions) {
    let id;
    let options;
    const isSetupStore = typeof setup === "function";
    if (typeof idOrOptions === "string") {
      id = idOrOptions;
      options = isSetupStore ? setupOptions : setup;
    } else {
      options = idOrOptions;
      id = idOrOptions.id;
    }
    function useStore2(pinia2, hot) {
      const hasContext = vue.hasInjectionContext();
      pinia2 = // in test mode, ignore the argument provided as we can always retrieve a
      // pinia instance with getActivePinia()
      pinia2 || (hasContext ? vue.inject(piniaSymbol, null) : null);
      if (pinia2)
        setActivePinia(pinia2);
      pinia2 = activePinia;
      if (!pinia2._s.has(id)) {
        if (isSetupStore) {
          createSetupStore(id, setup, options, pinia2);
        } else {
          createOptionsStore(id, options, pinia2);
        }
      }
      const store = pinia2._s.get(id);
      return store;
    }
    useStore2.$id = id;
    return useStore2;
  }
  function isObject$1(v) {
    return typeof v === "object" && v !== null;
  }
  function normalizeOptions(options, factoryOptions) {
    options = isObject$1(options) ? options : /* @__PURE__ */ Object.create(null);
    return new Proxy(options, {
      get(target, key, receiver) {
        if (key === "key")
          return Reflect.get(target, key, receiver);
        return Reflect.get(target, key, receiver) || Reflect.get(factoryOptions, key, receiver);
      }
    });
  }
  function get(state, path) {
    return path.reduce((obj, p) => {
      return obj == null ? void 0 : obj[p];
    }, state);
  }
  function set(state, path, val) {
    return path.slice(0, -1).reduce((obj, p) => {
      if (/^(__proto__)$/.test(p))
        return {};
      else
        return obj[p] = obj[p] || {};
    }, state)[path[path.length - 1]] = val, state;
  }
  function pick(baseState, paths) {
    return paths.reduce((substate, path) => {
      const pathArray = path.split(".");
      return set(substate, pathArray, get(baseState, pathArray));
    }, {});
  }
  function hydrateStore(store, { storage, serializer, key, debug }) {
    try {
      const fromStorage = storage == null ? void 0 : storage.getItem(key);
      if (fromStorage)
        store.$patch(serializer == null ? void 0 : serializer.deserialize(fromStorage));
    } catch (error) {
      if (debug)
        console.error(error);
    }
  }
  function persistState(state, { storage, serializer, key, paths, debug }) {
    try {
      const toStore = Array.isArray(paths) ? pick(state, paths) : state;
      storage.setItem(key, serializer.serialize(toStore));
    } catch (error) {
      if (debug)
        console.error(error);
    }
  }
  function createPersistedState(factoryOptions = {}) {
    return (context) => {
      const { auto = false } = factoryOptions;
      const {
        options: { persist = auto },
        store,
        pinia: pinia2
      } = context;
      if (!persist)
        return;
      if (!(store.$id in pinia2.state.value)) {
        const original_store = pinia2._s.get(store.$id.replace("__hot:", ""));
        if (original_store)
          Promise.resolve().then(() => original_store.$persist());
        return;
      }
      const persistences = (Array.isArray(persist) ? persist.map((p) => normalizeOptions(p, factoryOptions)) : [normalizeOptions(persist, factoryOptions)]).map(
        ({
          storage = localStorage,
          beforeRestore = null,
          afterRestore = null,
          serializer = {
            serialize: JSON.stringify,
            deserialize: JSON.parse
          },
          key = store.$id,
          paths = null,
          debug = false
        }) => {
          var _a;
          return {
            storage,
            beforeRestore,
            afterRestore,
            serializer,
            key: ((_a = factoryOptions.key) != null ? _a : (k) => k)(typeof key == "string" ? key : key(store.$id)),
            paths,
            debug
          };
        }
      );
      store.$persist = () => {
        persistences.forEach((persistence) => {
          persistState(store.$state, persistence);
        });
      };
      store.$hydrate = ({ runHooks = true } = {}) => {
        persistences.forEach((persistence) => {
          const { beforeRestore, afterRestore } = persistence;
          if (runHooks)
            beforeRestore == null ? void 0 : beforeRestore(context);
          hydrateStore(store, persistence);
          if (runHooks)
            afterRestore == null ? void 0 : afterRestore(context);
        });
      };
      persistences.forEach((persistence) => {
        const { beforeRestore, afterRestore } = persistence;
        beforeRestore == null ? void 0 : beforeRestore(context);
        hydrateStore(store, persistence);
        afterRestore == null ? void 0 : afterRestore(context);
        store.$subscribe(
          (_mutation, state) => {
            persistState(state, persistence);
          },
          {
            detached: true
          }
        );
      });
    };
  }
  var src_default = createPersistedState();
  const _export_sfc = (sfc, props) => {
    const target = sfc.__vccOpts || sfc;
    for (const [key, val] of props) {
      target[key] = val;
    }
    return target;
  };
  const _sfc_main$g = {};
  const _hoisted_1$f = { id: "trigger-overlay" };
  function _sfc_render(_ctx, _cache) {
    return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$f);
  }
  const TriggerOverlay = /* @__PURE__ */ _export_sfc(_sfc_main$g, [["render", _sfc_render], ["__scopeId", "data-v-658df74c"]]);
  const _Chord = class _Chord {
    /** @param {string} chordString  */
    constructor(chordString) {
      this.chordString = chordString;
    }
    /**
     * @param {number} delta
     * @returns {Chord}
     */
    transpose(delta) {
      this.chordString = this.chordString.replaceAll(/[A-G][#b]?/g, (note) => {
        const isSharp = _Chord.sharps.includes(note);
        const scale = isSharp ? _Chord.sharps : _Chord.flats;
        const noteIndex = scale.indexOf(note);
        const transposedIndex = (noteIndex + delta + 12) % 12;
        const transposedNote = scale[transposedIndex];
        return transposedNote;
      });
      return this;
    }
    /** @returns {Chord} */
    switchModifier() {
      this.chordString = this.chordString.replaceAll(/[A-G][#b]/g, (note) => {
        const scale = note.includes("#") ? _Chord.sharps : _Chord.flats;
        const newScale = note.includes("#") ? _Chord.flats : _Chord.sharps;
        const noteIndex = scale.indexOf(note);
        return newScale[noteIndex];
      });
      return this;
    }
    /** @returns {Chord} */
    useSharpModifier() {
      this.chordString = this.chordString.replaceAll(/[A-G]b/g, (note) => {
        const noteIndex = _Chord.flats.indexOf(note);
        return _Chord.sharps[noteIndex];
      });
      return this;
    }
    /** @returns {Chord} */
    useFlatModifier() {
      this.chordString = this.chordString.replaceAll(/[A-G]#/g, (note) => {
        const noteIndex = _Chord.sharps.indexOf(note);
        return _Chord.flats[noteIndex];
      });
      return this;
    }
    /** @returns {string} */
    toString() {
      return this.chordString;
    }
    /** @returns {string} */
    toFormattedString() {
      return this.chordString.replaceAll(
        /[#b]/g,
        /* html */
        `<sup>$&</sup>`
      );
    }
  };
  __publicField(_Chord, "sharps", ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]);
  __publicField(_Chord, "flats", ["C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B"]);
  let Chord = _Chord;
  var _GM_getValue = /* @__PURE__ */ (() => typeof GM_getValue != "undefined" ? GM_getValue : void 0)();
  var _GM_setValue = /* @__PURE__ */ (() => typeof GM_setValue != "undefined" ? GM_setValue : void 0)();
  class MonkeyStorage {
    /**
     * @param {String} key 
     * @returns {String|null}
     */
    static getItem(key) {
      if (_GM_getValue) {
        return _GM_getValue(key, null);
      } else {
        return localStorage.getItem(key);
      }
    }
    /**
     * @param {String} key 
     * @param {String} value 
     * @returns {void}
     */
    static setItem(key, value) {
      if (_GM_setValue) {
        _GM_setValue(key, value);
      } else {
        localStorage.setItem(key, value);
      }
    }
  }
  var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
  var lib = {};
  var compress$1 = {};
  var any = {};
  var constants = {};
  (function(exports) {
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.FLOAT_COMPRESSION_PRECISION = 1e3;
    exports.DATE_LOW_PRECISION = 1e5;
    exports.FLOAT_FULL_PRECISION_DELIMITER = ",";
    exports.FLOAT_REDUCED_PRECISION_DELIMITER = ".";
    exports.INTEGER_TOKEN = "¢";
    exports.FLOAT_TOKEN = "£";
    exports.STRING_TOKEN = "¨";
    exports.DATE_TOKEN = "ø";
    exports.LP_DATE_TOKEN = "±";
    exports.UNREFERENCED_INTEGER_TOKEN = "¤";
    exports.UNREFERENCED_FLOAT_TOKEN = "¥";
    exports.UNREFERENCED_STRING_TOKEN = "´";
    exports.UNREFERENCED_DATE_TOKEN = "¿";
    exports.UNREFERENCED_LP_DATE_TOKEN = "ÿ";
    exports.REF_INTEGER_TOKEN = "º";
    exports.REF_FLOAT_TOKEN = "Ý";
    exports.REF_STRING_TOKEN = "ß";
    exports.REF_DATE_TOKEN = "×";
    exports.REF_LP_DATE_TOKEN = "ü";
    exports.NULL_TOKEN = "§";
    exports.UNDEFINED_TOKEN = "µ";
    exports.BOOLEAN_TRUE_TOKEN = "»";
    exports.BOOLEAN_FALSE_TOKEN = "«";
    exports.ESCAPE_CHARACTER = "\\";
    exports.ESCAPED_STRING_TOKEN = "" + exports.ESCAPE_CHARACTER + exports.STRING_TOKEN;
    exports.ESCAPED_UNREFERENCED_STRING_TOKEN = "" + exports.ESCAPE_CHARACTER + exports.UNREFERENCED_STRING_TOKEN;
    exports.REGEX_ESCAPE_CHARACTER = new RegExp(exports.ESCAPE_CHARACTER.replace("\\", "\\\\"), "g");
    exports.REGEX_ESCAPED_ESCAPE_CHARACTER = new RegExp(exports.ESCAPE_CHARACTER.replace("\\", "\\\\") + exports.ESCAPE_CHARACTER.replace("\\", "\\\\"), "g");
    exports.REGEX_STRING_TOKEN = new RegExp(exports.STRING_TOKEN, "g");
    exports.REGEX_ESCAPED_STRING_TOKEN = new RegExp(exports.ESCAPE_CHARACTER + exports.ESCAPED_STRING_TOKEN, "g");
    exports.REGEX_UNREFERENCED_STRING_TOKEN = new RegExp(exports.UNREFERENCED_STRING_TOKEN, "g");
    exports.REGEX_UNREFERENCED_ESCAPED_STRING_TOKEN = new RegExp(exports.ESCAPE_CHARACTER + exports.ESCAPED_UNREFERENCED_STRING_TOKEN, "g");
    exports.DATE_REGEX = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z/;
    exports.OBJECT_START_TOKEN = "{";
    exports.OBJECT_END_TOKEN = "}";
    exports.TEMPLATE_OBJECT_START = "¦";
    exports.TEMPLATE_OBJECT_END = "‡";
    exports.TEMPLATE_OBJECT_FINAL = "—";
    exports.ARRAY_START_TOKEN = "|";
    exports.ARRAY_END_TOKEN = "÷";
    exports.ARRAY_REPEAT_TOKEN = "þ";
    exports.ARRAY_REPEAT_MANY_TOKEN = "^";
    exports.ARRAY_REPEAT_COUNT_THRESHOLD = 4;
    exports.REFERENCE_HEADER_LENGTH = 1;
    exports.DELIMITING_TOKENS_THRESHOLD = 122;
    exports.STRING_IDENT_PREFIX = "$";
    exports.INTEGER_SMALL_EXCLUSIVE_BOUND_LOWER = -10;
    exports.INTEGER_SMALL_EXCLUSIVE_BOUND_UPPER = 10;
    exports.INTEGER_SMALL_TOKEN_EXCLUSIVE_BOUND_LOWER = 191;
    exports.INTEGER_SMALL_TOKEN_EXCLUSIVE_BOUND_UPPER = 211;
    exports.INTEGER_SMALL_TOKEN_OFFSET = -201;
    exports.INTEGER_SMALL_TOKEN_ELEMENT_OFFSET = 9;
    exports.INTEGER_SMALL_TOKENS = ["À", "Á", "Â", "Ã", "Ä", "Å", "Æ", "Ç", "È", "É", "Ê", "Ë", "Ì", "Í", "Î", "Ï", "Ð", "Ñ", "Ò"];
  })(constants);
  Object.defineProperty(any, "__esModule", { value: true });
  var constants_1$a = constants;
  function compressAny(compressors2, context, obj, invertedIndex, writer2, options) {
    var type = typeof obj;
    if (type === "number") {
      compressors2.number(compressors2, context, obj, invertedIndex, writer2, options);
    } else if (type === "string") {
      compressors2.string(compressors2, context, obj, invertedIndex, writer2, options);
    } else if (type === "boolean") {
      writer2.write(obj ? constants_1$a.BOOLEAN_TRUE_TOKEN : constants_1$a.BOOLEAN_FALSE_TOKEN);
    } else if (obj === null) {
      writer2.write(constants_1$a.NULL_TOKEN);
    } else if (obj === void 0) {
      writer2.write(constants_1$a.UNDEFINED_TOKEN);
    } else if (Array.isArray(obj)) {
      compressors2.array(compressors2, context, obj, invertedIndex, writer2, options);
    } else if (obj instanceof Date) {
      compressors2.date(compressors2, context, obj.getTime(), invertedIndex, writer2, options);
    } else {
      compressors2.object(compressors2, context, obj, invertedIndex, writer2, options);
    }
  }
  any.compressAny = compressAny;
  var array$1 = {};
  var writer = {};
  var __extends = commonjsGlobal && commonjsGlobal.__extends || function() {
    var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d, b) {
      d.__proto__ = b;
    } || function(d, b) {
      for (var p in b)
        if (b.hasOwnProperty(p))
          d[p] = b[p];
    };
    return function(d, b) {
      extendStatics(d, b);
      function __() {
        this.constructor = d;
      }
      d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
  }();
  Object.defineProperty(writer, "__esModule", { value: true });
  var ZipsonWriter = (
    /** @class */
    function() {
      function ZipsonWriter2() {
      }
      return ZipsonWriter2;
    }()
  );
  writer.ZipsonWriter = ZipsonWriter;
  var ZipsonStringWriter = (
    /** @class */
    function(_super) {
      __extends(ZipsonStringWriter2, _super);
      function ZipsonStringWriter2() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.value = "";
        return _this;
      }
      ZipsonStringWriter2.prototype.write = function(data2) {
        this.value += data2;
      };
      ZipsonStringWriter2.prototype.end = function() {
      };
      return ZipsonStringWriter2;
    }(ZipsonWriter)
  );
  writer.ZipsonStringWriter = ZipsonStringWriter;
  var util$1 = {};
  Object.defineProperty(util$1, "__esModule", { value: true });
  var constants_1$9 = constants;
  var maxInteger = 2147483648;
  var minInteger = -2147483649;
  var base62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  function compressInteger(number2) {
    if (number2 === 0) {
      return "0";
    }
    var result = "";
    var carry = number2 < 0 ? -number2 : number2;
    var current = 0;
    var fraction;
    while (carry > 0) {
      carry = carry / 62;
      fraction = carry % 1;
      current = fraction * 62 + 0.1 << 0;
      carry -= fraction;
      result = base62[current] + result;
    }
    result = number2 < 0 ? "-" + result : result;
    return result;
  }
  util$1.compressInteger = compressInteger;
  function decompressInteger(compressedInteger) {
    var value = 0;
    if (compressedInteger[0] === "0") {
      return value;
    } else {
      var negative = compressedInteger[0] === "-";
      var multiplier = 1;
      var leftBound = negative ? 1 : 0;
      for (var i = compressedInteger.length - 1; i >= leftBound; i--) {
        var code = compressedInteger.charCodeAt(i);
        var current = code - 48;
        if (code >= 97) {
          current -= 13;
        } else if (code >= 65) {
          current -= 7;
        }
        value += current * multiplier;
        multiplier *= 62;
      }
      return negative ? -value : value;
    }
  }
  util$1.decompressInteger = decompressInteger;
  function compressFloat(float, fullPrecision) {
    if (fullPrecision === void 0) {
      fullPrecision = false;
    }
    if (fullPrecision) {
      var _a = float.toString().split("."), integer = _a[0], fraction = _a[1];
      var operator = integer === "-0" ? "-" : "";
      return "" + operator + compressInteger(parseInt(integer)) + constants_1$9.FLOAT_FULL_PRECISION_DELIMITER + fraction;
    } else {
      var integer = float >= maxInteger ? Math.floor(float) : float <= minInteger ? Math.ceil(float) : float << 0;
      var fraction = Math.round(constants_1$9.FLOAT_COMPRESSION_PRECISION * (float % 1));
      return "" + compressInteger(integer) + constants_1$9.FLOAT_REDUCED_PRECISION_DELIMITER + compressInteger(fraction);
    }
  }
  util$1.compressFloat = compressFloat;
  function decompressFloat(compressedFloat) {
    if (compressedFloat.indexOf(constants_1$9.FLOAT_FULL_PRECISION_DELIMITER) > -1) {
      var _a = compressedFloat.split(constants_1$9.FLOAT_FULL_PRECISION_DELIMITER), integer = _a[0], fraction = _a[1];
      var mult = integer === "-0" ? -1 : 1;
      var uncompressedInteger = decompressInteger(integer);
      return mult * parseFloat(uncompressedInteger + "." + fraction);
    } else {
      var _b = compressedFloat.split(constants_1$9.FLOAT_REDUCED_PRECISION_DELIMITER), integer = _b[0], fraction = _b[1];
      var uncompressedInteger = decompressInteger(integer);
      var uncompressedFraction = decompressInteger(fraction);
      return uncompressedInteger + uncompressedFraction / constants_1$9.FLOAT_COMPRESSION_PRECISION;
    }
  }
  util$1.decompressFloat = decompressFloat;
  Object.defineProperty(array$1, "__esModule", { value: true });
  var constants_1$8 = constants;
  var writer_1 = writer;
  var util_1$5 = util$1;
  function compressArray(compressors2, context, array2, invertedIndex, writer2, options) {
    context.arrayLevel++;
    if (context.arrayLevel > context.arrayItemWriters.length) {
      context.arrayItemWriters.push(new writer_1.ZipsonStringWriter());
    }
    var arrayItemWriter = context.arrayItemWriters[context.arrayLevel - 1];
    var parentWriter = context.arrayItemWriters[context.arrayLevel - 2] || writer2;
    parentWriter.write(constants_1$8.ARRAY_START_TOKEN);
    var previousItem = "";
    var repeatedTimes = 0;
    var repeatManyCount = 0;
    var templateObject = new compressors2.template.Object(array2[0], array2[1]);
    if (templateObject.isTemplating) {
      templateObject.compressTemplate(compressors2, context, invertedIndex, parentWriter, options);
    }
    for (var i = 0; i < array2.length; i++) {
      var item = array2[i];
      arrayItemWriter.value = "";
      if (item === void 0) {
        item = null;
      }
      if (i > 1 && templateObject.isTemplating) {
        templateObject.isNextTemplateable(array2[i], parentWriter);
      }
      if (templateObject.isTemplating) {
        templateObject.compressTemplateValues(compressors2, context, invertedIndex, arrayItemWriter, options, array2[i]);
      } else {
        compressors2.any(compressors2, context, item, invertedIndex, arrayItemWriter, options);
      }
      if (arrayItemWriter.value === previousItem) {
        repeatedTimes++;
        if (repeatedTimes >= constants_1$8.ARRAY_REPEAT_COUNT_THRESHOLD) {
          if (repeatManyCount === 0) {
            parentWriter.write(constants_1$8.ARRAY_REPEAT_MANY_TOKEN);
          }
          repeatManyCount++;
        } else {
          parentWriter.write(constants_1$8.ARRAY_REPEAT_TOKEN);
        }
      } else {
        repeatedTimes = 0;
        if (repeatManyCount > 0) {
          parentWriter.write(util_1$5.compressInteger(repeatManyCount));
          repeatManyCount = 0;
        }
        parentWriter.write(arrayItemWriter.value);
        previousItem = arrayItemWriter.value;
      }
    }
    if (repeatManyCount > 0) {
      parentWriter.write(util_1$5.compressInteger(repeatManyCount));
    }
    if (templateObject.isTemplating) {
      templateObject.end(parentWriter);
    }
    parentWriter.write(constants_1$8.ARRAY_END_TOKEN);
    context.arrayLevel--;
  }
  array$1.compressArray = compressArray;
  var string = {};
  Object.defineProperty(string, "__esModule", { value: true });
  var constants_1$7 = constants;
  var util_1$4 = util$1;
  function compressString(compressors2, context, obj, invertedIndex, writer2, options) {
    var foundRef;
    var stringIdent = constants_1$7.STRING_IDENT_PREFIX + obj;
    if (options.detectUtcTimestamps && obj[obj.length - 1] === "Z" && obj.match(constants_1$7.DATE_REGEX)) {
      var date2 = Date.parse(obj);
      compressors2.date(compressors2, context, date2, invertedIndex, writer2, options);
    } else if ((foundRef = invertedIndex.stringMap[stringIdent]) !== void 0) {
      writer2.write("" + constants_1$7.REF_STRING_TOKEN + foundRef);
    } else {
      var ref2 = util_1$4.compressInteger(invertedIndex.stringCount);
      var newRef = "" + constants_1$7.STRING_TOKEN + obj.replace(constants_1$7.REGEX_ESCAPE_CHARACTER, constants_1$7.ESCAPE_CHARACTER + constants_1$7.ESCAPE_CHARACTER).replace(constants_1$7.REGEX_STRING_TOKEN, constants_1$7.ESCAPED_STRING_TOKEN) + constants_1$7.STRING_TOKEN;
      if (ref2.length + constants_1$7.REFERENCE_HEADER_LENGTH + 1 < newRef.length) {
        invertedIndex.stringMap[stringIdent] = ref2;
        invertedIndex.stringCount++;
        writer2.write(newRef);
      } else {
        writer2.write("" + constants_1$7.UNREFERENCED_STRING_TOKEN + obj.replace(constants_1$7.REGEX_ESCAPE_CHARACTER, constants_1$7.ESCAPE_CHARACTER + constants_1$7.ESCAPE_CHARACTER).replace(constants_1$7.REGEX_UNREFERENCED_STRING_TOKEN, constants_1$7.ESCAPED_UNREFERENCED_STRING_TOKEN) + constants_1$7.UNREFERENCED_STRING_TOKEN);
      }
    }
  }
  string.compressString = compressString;
  var number = {};
  Object.defineProperty(number, "__esModule", { value: true });
  var constants_1$6 = constants;
  var util_1$3 = util$1;
  function compressNumber(compressors2, context, obj, invertedIndex, writer2, options) {
    var foundRef;
    if (obj % 1 === 0) {
      if (obj < constants_1$6.INTEGER_SMALL_EXCLUSIVE_BOUND_UPPER && obj > constants_1$6.INTEGER_SMALL_EXCLUSIVE_BOUND_LOWER) {
        writer2.write(constants_1$6.INTEGER_SMALL_TOKENS[obj + constants_1$6.INTEGER_SMALL_TOKEN_ELEMENT_OFFSET]);
      } else if ((foundRef = invertedIndex.integerMap[obj]) !== void 0) {
        writer2.write("" + constants_1$6.REF_INTEGER_TOKEN + foundRef);
      } else {
        var ref2 = util_1$3.compressInteger(invertedIndex.integerCount);
        var compressedInteger = util_1$3.compressInteger(obj);
        var newRef = "" + constants_1$6.INTEGER_TOKEN + compressedInteger;
        if (ref2.length + constants_1$6.REFERENCE_HEADER_LENGTH < newRef.length) {
          invertedIndex.integerMap[obj] = ref2;
          invertedIndex.integerCount++;
          writer2.write(newRef);
        } else {
          writer2.write("" + constants_1$6.UNREFERENCED_INTEGER_TOKEN + compressedInteger);
        }
      }
    } else {
      var compressedFloat = util_1$3.compressFloat(obj, options.fullPrecisionFloats);
      if ((foundRef = invertedIndex.floatMap[compressedFloat]) !== void 0) {
        writer2.write("" + constants_1$6.REF_FLOAT_TOKEN + foundRef);
      } else {
        var ref2 = util_1$3.compressInteger(invertedIndex.floatCount);
        var newRef = "" + constants_1$6.FLOAT_TOKEN + compressedFloat;
        if (ref2.length + constants_1$6.REFERENCE_HEADER_LENGTH < newRef.length) {
          invertedIndex.floatMap[compressedFloat] = ref2;
          invertedIndex.floatCount++;
          writer2.write(newRef);
        } else {
          writer2.write("" + constants_1$6.UNREFERENCED_FLOAT_TOKEN + compressedFloat);
        }
      }
    }
  }
  number.compressNumber = compressNumber;
  var object$1 = {};
  Object.defineProperty(object$1, "__esModule", { value: true });
  var constants_1$5 = constants;
  function compressObject(compressors2, context, obj, invertedIndex, writer2, options) {
    writer2.write(constants_1$5.OBJECT_START_TOKEN);
    var keys = Object.keys(obj);
    var templateObject = new compressors2.template.Object(obj[keys[0]], obj[keys[1]]);
    if (templateObject.isTemplating) {
      templateObject.compressTemplate(compressors2, context, invertedIndex, writer2, options);
    }
    for (var i = 0; i < keys.length; i++) {
      if (i > 1 && templateObject.isTemplating) {
        templateObject.isNextTemplateable(obj[keys[i]], writer2);
      }
      if (templateObject.isTemplating) {
        compressors2.string(compressors2, context, keys[i], invertedIndex, writer2, options);
        templateObject.compressTemplateValues(compressors2, context, invertedIndex, writer2, options, obj[keys[i]]);
      } else {
        var key = keys[i];
        var val = obj[key];
        if (val !== void 0) {
          compressors2.string(compressors2, context, key, invertedIndex, writer2, options);
          compressors2.any(compressors2, context, val, invertedIndex, writer2, options);
        }
      }
    }
    if (templateObject.isTemplating) {
      templateObject.end(writer2);
    }
    writer2.write(constants_1$5.OBJECT_END_TOKEN);
  }
  object$1.compressObject = compressObject;
  var date = {};
  Object.defineProperty(date, "__esModule", { value: true });
  var constants_1$4 = constants;
  var util_1$2 = util$1;
  function compressDate(compressors2, context, obj, invertedIndex, writer2, options) {
    var foundRef;
    var lowPrecisionDate = obj / constants_1$4.DATE_LOW_PRECISION;
    var isLowPrecision = lowPrecisionDate % 1 === 0;
    if (isLowPrecision) {
      if ((foundRef = invertedIndex.lpDateMap[lowPrecisionDate]) !== void 0) {
        writer2.write("" + constants_1$4.REF_LP_DATE_TOKEN + foundRef);
      } else {
        var ref2 = util_1$2.compressInteger(invertedIndex.lpDateCount);
        var compressedDate = util_1$2.compressInteger(lowPrecisionDate);
        var newRef = "" + constants_1$4.LP_DATE_TOKEN + compressedDate;
        if (ref2.length + constants_1$4.REFERENCE_HEADER_LENGTH < newRef.length) {
          invertedIndex.lpDateMap[lowPrecisionDate] = ref2;
          invertedIndex.lpDateCount++;
          writer2.write(newRef);
        } else {
          writer2.write("" + constants_1$4.UNREFERENCED_LP_DATE_TOKEN + compressedDate);
        }
      }
    } else {
      if ((foundRef = invertedIndex.dateMap[obj]) !== void 0) {
        writer2.write("" + constants_1$4.REF_DATE_TOKEN + foundRef);
      } else {
        var ref2 = util_1$2.compressInteger(invertedIndex.dateCount);
        var compressedDate = util_1$2.compressInteger(obj);
        var newRef = "" + constants_1$4.DATE_TOKEN + compressedDate;
        if (ref2.length + constants_1$4.REFERENCE_HEADER_LENGTH < newRef.length) {
          invertedIndex.dateMap[obj] = ref2;
          invertedIndex.dateCount++;
          writer2.write(newRef);
        } else {
          writer2.write("" + constants_1$4.UNREFERENCED_DATE_TOKEN + compressedDate);
        }
      }
    }
  }
  date.compressDate = compressDate;
  var object = {};
  var util = {};
  Object.defineProperty(util, "__esModule", { value: true });
  function isObject(obj) {
    var type = typeof obj;
    if (type === "number") {
      return false;
    } else if (type === "string") {
      return false;
    } else if (type === "boolean") {
      return false;
    } else if (obj === null) {
      return false;
    } else if (Array.isArray(obj)) {
      return false;
    } else if (obj instanceof Date) {
      return false;
    } else if (obj === void 0) {
      return false;
    } else {
      return true;
    }
  }
  util.isObject = isObject;
  Object.defineProperty(object, "__esModule", { value: true });
  var constants_1$3 = constants;
  var util_1$1 = util;
  var TemplateObject = (
    /** @class */
    function() {
      function TemplateObject2(a, b) {
        this.isTemplating = false;
        this.struct = [];
        if (a != null && b != null) {
          this.isTemplating = buildTemplate(a, b, this.struct);
        }
      }
      TemplateObject2.prototype.compressTemplate = function(compressors2, context, invertedIndex, writer2, options) {
        compresObjectTemplate(compressors2, context, invertedIndex, writer2, options, this.struct);
      };
      TemplateObject2.prototype.compressTemplateValues = function(compressors2, context, invertedIndex, writer2, options, obj) {
        compressObjectValues(compressors2, context, invertedIndex, writer2, options, this.struct, obj);
      };
      TemplateObject2.prototype.isNextTemplateable = function(obj, writer2) {
        this.isTemplating = conformsToStructure(this.struct, obj);
        if (!this.isTemplating) {
          writer2.write(constants_1$3.TEMPLATE_OBJECT_FINAL);
        }
      };
      TemplateObject2.prototype.end = function(writer2) {
        writer2.write(constants_1$3.TEMPLATE_OBJECT_FINAL);
      };
      return TemplateObject2;
    }()
  );
  object.TemplateObject = TemplateObject;
  function buildTemplate(a, b, struct, level) {
    if (level === void 0) {
      level = 0;
    }
    if (level > 6) {
      return false;
    }
    var keysA = Object.keys(a);
    var keysB = Object.keys(b);
    if (keysA.length !== keysB.length) {
      return false;
    }
    if (keysA.length > 10) {
      return false;
    }
    keysA.sort(function(a2, b2) {
      return a2.localeCompare(b2);
    });
    keysB.sort(function(a2, b2) {
      return a2.localeCompare(b2);
    });
    for (var i = 0; i < keysA.length; i++) {
      var keyA = keysA[i];
      var keyB = keysB[i];
      if (keyA !== keyB) {
        return false;
      }
      var valueA = a[keyA];
      var valueB = b[keyB];
      if (util_1$1.isObject(valueA)) {
        if (!util_1$1.isObject(valueB)) {
          return false;
        }
        var nextStruct = [];
        struct.push([keyA, nextStruct]);
        if (!buildTemplate(valueA, valueB, nextStruct, level + 1)) {
          return false;
        }
      } else if (util_1$1.isObject(valueB)) {
        return false;
      } else {
        struct.push([keyA]);
      }
    }
    return level > 0 || util_1$1.isObject(a);
  }
  function conformsToStructure(struct, obj) {
    if (!obj) {
      return false;
    }
    if (Object.keys(obj).length !== struct.length) {
      return false;
    }
    for (var i = 0; i < struct.length; i++) {
      var key = struct[i][0];
      var isNested = struct[i].length > 1;
      if (obj[key] === void 0) {
        return false;
      }
      if (isNested) {
        var x2 = struct[i];
        x2[1];
        if (!conformsToStructure(struct[i][1], obj[key])) {
          return false;
        }
      } else {
        if (util_1$1.isObject(obj[key])) {
          return false;
        }
      }
    }
    return true;
  }
  function compresObjectTemplate(compressors2, context, invertedIndex, writer2, options, struct) {
    writer2.write(constants_1$3.TEMPLATE_OBJECT_START);
    for (var i = 0; i < struct.length; i++) {
      var key = struct[i][0];
      var isNested = struct[i].length > 1;
      compressors2.string(compressors2, context, key, invertedIndex, writer2, options);
      if (isNested) {
        compresObjectTemplate(compressors2, context, invertedIndex, writer2, options, struct[i][1]);
      }
    }
    writer2.write(constants_1$3.TEMPLATE_OBJECT_END);
  }
  function compressObjectValues(compressors2, context, invertedIndex, writer2, options, struct, obj) {
    for (var i = 0; i < struct.length; i++) {
      var key = struct[i][0];
      var value = obj[key];
      var isNested = struct[i].length > 1;
      if (isNested) {
        compressObjectValues(compressors2, context, invertedIndex, writer2, options, struct[i][1], value);
      } else {
        compressors2.any(compressors2, context, value, invertedIndex, writer2, options);
      }
    }
  }
  Object.defineProperty(compress$1, "__esModule", { value: true });
  var any_1 = any;
  var array_1 = array$1;
  var string_1 = string;
  var number_1 = number;
  var object_1 = object$1;
  var date_1 = date;
  var object_2 = object;
  var compressors = {
    any: any_1.compressAny,
    array: array_1.compressArray,
    object: object_1.compressObject,
    string: string_1.compressString,
    date: date_1.compressDate,
    number: number_1.compressNumber,
    template: {
      Object: object_2.TemplateObject
    }
  };
  function makeCompressContext() {
    return {
      arrayItemWriters: [],
      arrayLevel: 0
    };
  }
  compress$1.makeCompressContext = makeCompressContext;
  function makeInvertedIndex() {
    return {
      stringMap: {},
      integerMap: {},
      floatMap: {},
      dateMap: {},
      lpDateMap: {},
      stringCount: 0,
      integerCount: 0,
      floatCount: 0,
      dateCount: 0,
      lpDateCount: 0
    };
  }
  compress$1.makeInvertedIndex = makeInvertedIndex;
  function compress(context, obj, invertedIndex, writer2, options) {
    compressors.any(compressors, context, obj, invertedIndex, writer2, options);
  }
  compress$1.compress = compress;
  var decompress$1 = {};
  var common = {};
  (function(exports) {
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.SKIP_SCALAR = {};
    (function(TargetType) {
      TargetType["ARRAY"] = "ARRAY";
      TargetType["OBJECT"] = "OBJECT";
      TargetType["SCALAR"] = "SCALAR";
      TargetType["TEMPLATE_OBJECT"] = "TEMPLATE_OBJECT";
      TargetType["TEMPLATE_OBJECT_PROPERTIES"] = "TEMPLATE_OBJECT_PROPERTIES";
      TargetType["TEMPLATE_OBJECT_ELEMENTS"] = "TEMPLATE_OBJECT_ELEMENTS";
    })(exports.TargetType || (exports.TargetType = {}));
  })(common);
  var stages = {};
  var scalar = {};
  Object.defineProperty(scalar, "__esModule", { value: true });
  var constants_1$2 = constants;
  var common_1$3 = common;
  var util_1 = util$1;
  function decompressScalar(token, data2, cursor, orderedIndex) {
    var startIndex = cursor.index;
    var endIndex = cursor.index + 1;
    var foundStringToken;
    if (token === constants_1$2.STRING_TOKEN && (foundStringToken = constants_1$2.STRING_TOKEN) || token === constants_1$2.UNREFERENCED_STRING_TOKEN && (foundStringToken = constants_1$2.UNREFERENCED_STRING_TOKEN)) {
      var escaped = true;
      while (escaped && endIndex < data2.length) {
        endIndex = data2.indexOf(foundStringToken, endIndex);
        var iNumEscapeCharacters = 1;
        escaped = false;
        while (data2[endIndex - iNumEscapeCharacters] === constants_1$2.ESCAPE_CHARACTER) {
          escaped = iNumEscapeCharacters % 2 === 1;
          iNumEscapeCharacters++;
        }
        endIndex++;
      }
      if (endIndex <= startIndex) {
        endIndex = data2.length;
      }
    } else {
      while (!(data2.charCodeAt(endIndex) > constants_1$2.DELIMITING_TOKENS_THRESHOLD) && endIndex < data2.length) {
        endIndex++;
      }
    }
    if (!cursor.drain && endIndex === data2.length) {
      return common_1$3.SKIP_SCALAR;
    }
    cursor.index = endIndex - 1;
    var tokenCharCode = token.charCodeAt(0);
    if (tokenCharCode > constants_1$2.INTEGER_SMALL_TOKEN_EXCLUSIVE_BOUND_LOWER && tokenCharCode < constants_1$2.INTEGER_SMALL_TOKEN_EXCLUSIVE_BOUND_UPPER) {
      return tokenCharCode + constants_1$2.INTEGER_SMALL_TOKEN_OFFSET;
    } else if (token === constants_1$2.ARRAY_REPEAT_MANY_TOKEN) {
      return util_1.decompressInteger(data2.substring(startIndex + 1, endIndex));
    } else if (token === constants_1$2.REF_STRING_TOKEN) {
      return orderedIndex.strings[util_1.decompressInteger(data2.substring(startIndex + 1, endIndex))];
    } else if (token === constants_1$2.REF_INTEGER_TOKEN) {
      return orderedIndex.integers[util_1.decompressInteger(data2.substring(startIndex + 1, endIndex))];
    } else if (token === constants_1$2.REF_FLOAT_TOKEN) {
      return orderedIndex.floats[util_1.decompressInteger(data2.substring(startIndex + 1, endIndex))];
    } else if (token === constants_1$2.REF_DATE_TOKEN) {
      return orderedIndex.dates[util_1.decompressInteger(data2.substring(startIndex + 1, endIndex))];
    } else if (token === constants_1$2.REF_LP_DATE_TOKEN) {
      return orderedIndex.lpDates[util_1.decompressInteger(data2.substring(startIndex + 1, endIndex))];
    } else if (token === constants_1$2.STRING_TOKEN) {
      return orderedIndex.strings[orderedIndex.strings.length] = data2.substring(startIndex + 1, endIndex - 1).replace(constants_1$2.REGEX_ESCAPED_ESCAPE_CHARACTER, constants_1$2.ESCAPE_CHARACTER).replace(constants_1$2.REGEX_ESCAPED_STRING_TOKEN, constants_1$2.STRING_TOKEN);
    } else if (token === constants_1$2.INTEGER_TOKEN) {
      return orderedIndex.integers[orderedIndex.integers.length] = util_1.decompressInteger(data2.substring(startIndex + 1, endIndex));
    } else if (token === constants_1$2.FLOAT_TOKEN) {
      return orderedIndex.floats[orderedIndex.floats.length] = util_1.decompressFloat(data2.substring(startIndex + 1, endIndex));
    } else if (token === constants_1$2.DATE_TOKEN) {
      return orderedIndex.dates[orderedIndex.dates.length] = new Date(util_1.decompressInteger(data2.substring(startIndex + 1, endIndex))).toISOString();
    } else if (token === constants_1$2.LP_DATE_TOKEN) {
      return orderedIndex.lpDates[orderedIndex.lpDates.length] = new Date(constants_1$2.DATE_LOW_PRECISION * util_1.decompressInteger(data2.substring(startIndex + 1, endIndex))).toISOString();
    } else if (token === constants_1$2.UNREFERENCED_STRING_TOKEN) {
      return data2.substring(startIndex + 1, endIndex - 1).replace(constants_1$2.REGEX_ESCAPED_ESCAPE_CHARACTER, constants_1$2.ESCAPE_CHARACTER).replace(constants_1$2.REGEX_UNREFERENCED_ESCAPED_STRING_TOKEN, constants_1$2.UNREFERENCED_STRING_TOKEN);
    } else if (token === constants_1$2.UNREFERENCED_INTEGER_TOKEN) {
      return util_1.decompressInteger(data2.substring(startIndex + 1, endIndex));
    } else if (token === constants_1$2.UNREFERENCED_FLOAT_TOKEN) {
      return util_1.decompressFloat(data2.substring(startIndex + 1, endIndex));
    } else if (token === constants_1$2.UNREFERENCED_DATE_TOKEN) {
      return new Date(util_1.decompressInteger(data2.substring(startIndex + 1, endIndex))).toISOString();
    } else if (token === constants_1$2.UNREFERENCED_LP_DATE_TOKEN) {
      return new Date(constants_1$2.DATE_LOW_PRECISION * util_1.decompressInteger(data2.substring(startIndex + 1, endIndex))).toISOString();
    } else if (token === constants_1$2.BOOLEAN_TRUE_TOKEN) {
      return true;
    } else if (token === constants_1$2.BOOLEAN_FALSE_TOKEN) {
      return false;
    } else if (token === constants_1$2.NULL_TOKEN) {
      return null;
    } else if (token === constants_1$2.UNDEFINED_TOKEN) {
      return void 0;
    }
    throw new Error("Unexpected scalar " + token + " at " + startIndex + "-" + endIndex);
  }
  scalar.decompressScalar = decompressScalar;
  var element = {};
  var template = {};
  Object.defineProperty(template, "__esModule", { value: true });
  function appendTemplateObjectValue(templateObjectTarget, targetValue) {
    var currentPath = templateObjectTarget.paths[templateObjectTarget.currentPathIndex];
    var i = 0;
    var targetObject = templateObjectTarget.currentObject;
    for (; i < currentPath.length - 1; i++) {
      var fragment = currentPath[i];
      targetObject = targetObject[fragment] = targetObject[fragment] || {};
    }
    if (targetValue !== void 0) {
      targetObject[currentPath[i]] = targetValue;
    }
  }
  function appendTemplateObjectPropertiesValue(templateObjectElementsTarget, targetValue) {
    if (templateObjectElementsTarget.currentPathIndex === -1) {
      templateObjectElementsTarget.value[targetValue] = templateObjectElementsTarget.currentObject = {};
    } else {
      appendTemplateObjectValue(templateObjectElementsTarget, targetValue);
    }
    if (++templateObjectElementsTarget.currentPathIndex === templateObjectElementsTarget.expectedPaths) {
      templateObjectElementsTarget.currentPathIndex = -1;
    }
  }
  template.appendTemplateObjectPropertiesValue = appendTemplateObjectPropertiesValue;
  function appendTemplateObjectElementsValue(templateObjectPropertiesTarget, targetValue) {
    if (templateObjectPropertiesTarget.currentPathIndex === 0) {
      templateObjectPropertiesTarget.currentObject = {};
      templateObjectPropertiesTarget.value.push(templateObjectPropertiesTarget.currentObject);
    }
    appendTemplateObjectValue(templateObjectPropertiesTarget, targetValue);
    if (++templateObjectPropertiesTarget.currentPathIndex === templateObjectPropertiesTarget.expectedPaths) {
      templateObjectPropertiesTarget.currentPathIndex = 0;
    }
  }
  template.appendTemplateObjectElementsValue = appendTemplateObjectElementsValue;
  Object.defineProperty(element, "__esModule", { value: true });
  var constants_1$1 = constants;
  var common_1$2 = common;
  var scalar_1$1 = scalar;
  var template_1 = template;
  function decompressElement(c, cursor, data2, orderedIndex) {
    var targetValue;
    if (c === constants_1$1.ARRAY_END_TOKEN || c === constants_1$1.OBJECT_END_TOKEN) {
      targetValue = cursor.currentTarget.value;
      cursor.currentTarget = cursor.stack[cursor.pointer - 1];
      cursor.pointer--;
    } else {
      targetValue = scalar_1$1.decompressScalar(c, data2, cursor, orderedIndex);
      if (targetValue === common_1$2.SKIP_SCALAR) {
        return false;
      }
    }
    if (cursor.currentTarget.type === common_1$2.TargetType.SCALAR) {
      cursor.currentTarget.value = targetValue;
    } else if (cursor.currentTarget.type === common_1$2.TargetType.ARRAY) {
      cursor.currentTarget.value[cursor.currentTarget.value.length] = targetValue;
    } else if (cursor.currentTarget.type === common_1$2.TargetType.OBJECT) {
      if (cursor.currentTarget.key != null) {
        cursor.currentTarget.value[cursor.currentTarget.key] = targetValue;
        cursor.currentTarget.key = void 0;
      } else {
        cursor.currentTarget.key = targetValue;
      }
    } else if (cursor.currentTarget.type === common_1$2.TargetType.TEMPLATE_OBJECT) {
      cursor.currentTarget.currentToken = targetValue;
      cursor.currentTarget.currentTokens.push(targetValue);
    } else if (cursor.currentTarget.type === common_1$2.TargetType.TEMPLATE_OBJECT_PROPERTIES) {
      template_1.appendTemplateObjectPropertiesValue(cursor.currentTarget, targetValue);
    } else if (cursor.currentTarget.type === common_1$2.TargetType.TEMPLATE_OBJECT_ELEMENTS) {
      template_1.appendTemplateObjectElementsValue(cursor.currentTarget, targetValue);
    }
    return true;
  }
  element.decompressElement = decompressElement;
  Object.defineProperty(stages, "__esModule", { value: true });
  var constants_1 = constants;
  var common_1$1 = common;
  var scalar_1 = scalar;
  var element_1 = element;
  function decompressStages(cursor, data2, orderedIndex) {
    for (; cursor.index < data2.length; cursor.index++) {
      var c = data2[cursor.index];
      if (c === constants_1.ARRAY_START_TOKEN) {
        cursor.currentTarget = { type: common_1$1.TargetType.ARRAY, value: [] };
        cursor.stack[++cursor.pointer] = cursor.currentTarget;
      } else if (c === constants_1.OBJECT_START_TOKEN) {
        cursor.currentTarget = { type: common_1$1.TargetType.OBJECT, value: {} };
        cursor.stack[++cursor.pointer] = cursor.currentTarget;
      } else if (c === constants_1.ARRAY_REPEAT_TOKEN && (cursor.currentTarget.type === common_1$1.TargetType.ARRAY || cursor.currentTarget.type === common_1$1.TargetType.TEMPLATE_OBJECT_ELEMENTS)) {
        var repeatedItem = cursor.currentTarget.value[cursor.currentTarget.value.length - 1];
        cursor.currentTarget.value.push(repeatedItem);
      } else if (c === constants_1.ARRAY_REPEAT_MANY_TOKEN && (cursor.currentTarget.type === common_1$1.TargetType.ARRAY || cursor.currentTarget.type === common_1$1.TargetType.TEMPLATE_OBJECT_ELEMENTS)) {
        var repeatCount = scalar_1.decompressScalar(data2[cursor.index], data2, cursor, orderedIndex);
        if (repeatCount === common_1$1.SKIP_SCALAR) {
          return;
        }
        var repeatedItem = cursor.currentTarget.value[cursor.currentTarget.value.length - 1];
        for (var i = 0; i < repeatCount; i++) {
          cursor.currentTarget.value.push(repeatedItem);
        }
      } else if (c === constants_1.TEMPLATE_OBJECT_START && (cursor.currentTarget.type === common_1$1.TargetType.TEMPLATE_OBJECT || cursor.currentTarget.type === common_1$1.TargetType.OBJECT || cursor.currentTarget.type === common_1$1.TargetType.ARRAY)) {
        if (cursor.currentTarget.type !== common_1$1.TargetType.TEMPLATE_OBJECT) {
          var parentTarget = cursor.currentTarget;
          cursor.currentTarget = { type: common_1$1.TargetType.TEMPLATE_OBJECT, value: void 0, currentTokens: [], currentRoute: [], paths: [], level: 0, parentTarget };
          cursor.stack[++cursor.pointer] = cursor.currentTarget;
        } else {
          for (var i = 0; i < cursor.currentTarget.currentTokens.length - 1; i++) {
            var currentToken = cursor.currentTarget.currentTokens[i];
            cursor.currentTarget.paths[cursor.currentTarget.paths.length] = cursor.currentTarget.currentRoute.concat(currentToken);
          }
          if (cursor.currentTarget.currentToken != null) {
            cursor.currentTarget.currentRoute.push(cursor.currentTarget.currentToken);
          }
          cursor.currentTarget.currentTokens = [];
          cursor.currentTarget.level++;
        }
      } else if (c === constants_1.TEMPLATE_OBJECT_END && cursor.currentTarget.type === common_1$1.TargetType.TEMPLATE_OBJECT) {
        for (var i = 0; i < cursor.currentTarget.currentTokens.length; i++) {
          var currentToken = cursor.currentTarget.currentTokens[i];
          cursor.currentTarget.paths[cursor.currentTarget.paths.length] = cursor.currentTarget.currentRoute.concat(currentToken);
        }
        cursor.currentTarget.currentTokens = [];
        cursor.currentTarget.currentRoute = cursor.currentTarget.currentRoute.slice(0, -1);
        cursor.currentTarget.level--;
        if (cursor.currentTarget.level < 0) {
          var paths = cursor.currentTarget.paths;
          var parentTarget = cursor.currentTarget.parentTarget;
          cursor.pointer--;
          if (parentTarget.type === common_1$1.TargetType.ARRAY) {
            cursor.currentTarget = { type: common_1$1.TargetType.TEMPLATE_OBJECT_ELEMENTS, value: parentTarget.value, paths, currentPathIndex: 0, expectedPaths: paths.length, currentObject: {} };
          } else if (parentTarget.type === common_1$1.TargetType.OBJECT) {
            cursor.currentTarget = { type: common_1$1.TargetType.TEMPLATE_OBJECT_PROPERTIES, value: parentTarget.value, paths, currentPathIndex: -1, expectedPaths: paths.length, currentObject: {} };
          }
          cursor.stack[++cursor.pointer] = cursor.currentTarget;
        }
      } else if (c === constants_1.TEMPLATE_OBJECT_FINAL) {
        cursor.currentTarget = cursor.stack[--cursor.pointer];
      } else {
        if (!element_1.decompressElement(c, cursor, data2, orderedIndex)) {
          return;
        }
      }
    }
  }
  stages.decompressStages = decompressStages;
  Object.defineProperty(decompress$1, "__esModule", { value: true });
  var common_1 = common;
  var stages_1 = stages;
  function makeOrderedIndex() {
    return {
      strings: [],
      integers: [],
      floats: [],
      dates: [],
      lpDates: []
    };
  }
  decompress$1.makeOrderedIndex = makeOrderedIndex;
  function makeCursor(drain) {
    var rootTarget = { type: common_1.TargetType.SCALAR, value: void 0 };
    var stack = new Array(10);
    stack[0] = rootTarget;
    return { index: 0, rootTarget, stack, currentTarget: rootTarget, pointer: 0, drain };
  }
  function decompress(data2, orderedIndex) {
    var cursor = makeCursor(true);
    stages_1.decompressStages(cursor, data2, orderedIndex);
    return cursor.rootTarget.value;
  }
  decompress$1.decompress = decompress;
  function decompressIncremental(orderedIndex) {
    var cursor = makeCursor(false);
    var buffer = "";
    function increment(data2) {
      if (data2 === null) {
        cursor.drain = true;
      } else if (data2.length === 0) {
        return;
      } else {
        buffer += data2;
      }
      var cursorIndexBefore = cursor.index;
      stages_1.decompressStages(cursor, buffer, orderedIndex);
      var movedAmount = cursor.index - cursorIndexBefore;
      if (movedAmount > 0) {
        buffer = buffer.substring(movedAmount);
        cursor.index -= movedAmount;
      }
    }
    return { increment, cursor };
  }
  decompress$1.decompressIncremental = decompressIncremental;
  (function(exports) {
    function __export(m) {
      for (var p in m)
        if (!exports.hasOwnProperty(p))
          exports[p] = m[p];
    }
    Object.defineProperty(exports, "__esModule", { value: true });
    var compress_1 = compress$1;
    var writer_12 = writer;
    var decompress_1 = decompress$1;
    __export(writer);
    __export(common);
    function parse(data2) {
      var orderedIndex = decompress_1.makeOrderedIndex();
      return decompress_1.decompress(data2, orderedIndex);
    }
    exports.parse = parse;
    function parseIncremental() {
      var orderedIndex = decompress_1.makeOrderedIndex();
      var _a = decompress_1.decompressIncremental(orderedIndex), cursor = _a.cursor, increment = _a.increment;
      return function(data2) {
        increment(data2);
        if (data2 === null) {
          return cursor.rootTarget.value;
        }
      };
    }
    exports.parseIncremental = parseIncremental;
    function stringifyTo(data2, writer2, options) {
      if (options === void 0) {
        options = {};
      }
      var invertedIndex = compress_1.makeInvertedIndex();
      var context = compress_1.makeCompressContext();
      compress_1.compress(context, data2, invertedIndex, writer2, options);
      writer2.end();
    }
    exports.stringifyTo = stringifyTo;
    function stringify(data2, options) {
      var writer2 = new writer_12.ZipsonStringWriter();
      stringifyTo(data2, writer2, options);
      return writer2.value;
    }
    exports.stringify = stringify;
  })(lib);
  const useStore = defineStore("store", {
    state() {
      return {
        // ####################
        // 元件相關狀態
        // ####################
        isDarkMode: false,
        isToolbarsShow: false,
        isPopupShow: {
          sheet: false,
          chord: false,
          font: false,
          settings: false,
          menu: false,
          // 選單內功能
          hotkey: false
        },
        // ####################
        // 偏好設定相關狀態
        // ####################
        agreeToArchiveSheet: true,
        // ####################
        // 譜面相關狀態
        // ####################
        transpose: 0,
        /** 在 `StoreHandler` 裡賦值 */
        originalCapo: 0,
        /** 在 `StoreHandler` 裡賦值,HTML 格式 */
        originalKey: "",
        /** `font-size` 的變化值 */
        fontSizeDelta: 0,
        /** 在 `StoreHandler` 裡賦值,單位為 px */
        originalFontSize: 0,
        /** 在 `StoreHandler` 裡賦值,單位為 px */
        originalLineHeight: 0
      };
    },
    persist: {
      key: "plus91-preferences",
      storage: MonkeyStorage,
      deserialize: lib.parse,
      serialize: lib.stringify,
      paths: ["isDarkMode", "agreeToArchiveSheet"],
      beforeRestore() {
        console.log("[91 Plus] 讀取偏好設置中");
      },
      afterRestore() {
        console.log("[91 Plus] 偏好設置讀取完畢");
      },
      debug: true
    },
    getters: {
      currentCapo() {
        return this.originalCapo + this.transpose;
      },
      currentKey() {
        return new Chord(this.originalKey).transpose(-this.transpose).toFormattedString();
      }
    },
    actions: {
      toggleToolbars() {
        if (this.isToolbarsShow) {
          this.closePopups();
        } else {
          this.isPopupShow.sheet = true;
        }
        this.isToolbarsShow = !this.isToolbarsShow;
      },
      closePopups() {
        for (const popup in this.isPopupShow) {
          this.isPopupShow[popup] = false;
        }
      },
      /** @param {'sheet'|'chord'|'font'|'settings'|'menu'|'hotkey'} name */
      togglePopup(name) {
        for (const popup in this.isPopupShow) {
          if (popup === name) {
            this.isPopupShow[popup] = !this.isPopupShow[popup];
          } else {
            this.isPopupShow[popup] = false;
          }
        }
      },
      plusTranspose(numberToPlus) {
        let newTranspose = this.transpose + numberToPlus;
        const newCapo = this.originalCapo + newTranspose;
        if (newCapo === 12 || newCapo === -12) {
          newTranspose = -this.originalCapo;
        }
        this.transpose = newTranspose;
      }
    }
  });
  const _hoisted_1$e = ["active"];
  const _sfc_main$f = {
    __name: "BootstrapIcon",
    props: {
      icon: {
        type: String,
        required: true
      },
      color: {
        type: String,
        default: "whitesmoke"
      },
      size: {
        type: String,
        default: "1rem"
      },
      stroke: {
        type: String,
        default: "0"
      },
      active: {
        type: Boolean,
        default: false
      }
    },
    setup(__props) {
      vue.useCssVars((_ctx) => ({
        "2d5c579c": __props.color,
        "0168355c": __props.size,
        "5c7f6b49": __props.stroke
      }));
      return (_ctx, _cache) => {
        return vue.openBlock(), vue.createElementBlock("i", {
          class: vue.normalizeClass(`bi bi-${__props.icon}`),
          active: __props.active
        }, null, 10, _hoisted_1$e);
      };
    }
  };
  const BootstrapIcon = /* @__PURE__ */ _export_sfc(_sfc_main$f, [["__scopeId", "data-v-33d92514"]]);
  const _hoisted_1$d = { class: "toolbar-icon" };
  const _sfc_main$e = {
    __name: "ToolbarIcon",
    props: {
      icon: {
        type: String,
        required: true
      },
      stroke: {
        type: String,
        default: "0"
      },
      active: {
        type: Boolean,
        default: false
      },
      color: {
        type: String,
        default: "whitesmoke"
      }
    },
    setup(__props) {
      return (_ctx, _cache) => {
        return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$d, [
          vue.createVNode(BootstrapIcon, {
            icon: __props.icon,
            color: __props.color,
            size: "1.3rem",
            stroke: __props.stroke,
            active: __props.active
          }, null, 8, ["icon", "color", "stroke", "active"])
        ]);
      };
    }
  };
  const ToolbarIcon = /* @__PURE__ */ _export_sfc(_sfc_main$e, [["__scopeId", "data-v-2b5c1219"]]);
  const _hoisted_1$c = { class: "adjust-widget" };
  const _hoisted_2$b = ["disabled"];
  const _hoisted_3$6 = ["disabled"];
  const _hoisted_4$4 = ["disabled"];
  const _sfc_main$d = {
    __name: "AdjustWidget",
    props: {
      iconLeft: {
        type: String,
        default: "caret-left-fill"
      },
      iconRight: {
        type: String,
        default: "caret-right-fill"
      },
      disabledLeft: {
        type: Boolean,
        default: false
      },
      disabledMiddle: {
        type: Boolean,
        default: false
      },
      disabledRight: {
        type: Boolean,
        default: false
      },
      color: {
        type: String,
        default: "#444"
      },
      size: {
        type: String,
        default: "1.25rem"
      },
      onclickLeft: Function,
      onclickMiddle: Function,
      onclickRight: Function
    },
    setup(__props) {
      vue.useCssVars((_ctx) => ({
        "791a4684": __props.color,
        "37e19b46": __props.size
      }));
      return (_ctx, _cache) => {
        return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$c, [
          vue.createElementVNode("button", {
            class: "adjust-button adjust-button-left",
            onClick: _cache[0] || (_cache[0] = (...args) => __props.onclickLeft && __props.onclickLeft(...args)),
            disabled: __props.disabledLeft
          }, [
            vue.createVNode(BootstrapIcon, {
              icon: __props.iconLeft,
              color: __props.color,
              size: __props.size
            }, null, 8, ["icon", "color", "size"])
          ], 8, _hoisted_2$b),
          vue.createElementVNode("button", {
            class: "adjust-button adjust-button-middle",
            onClick: _cache[1] || (_cache[1] = (...args) => __props.onclickMiddle && __props.onclickMiddle(...args)),
            disabled: __props.disabledMiddle
          }, [
            vue.renderSlot(_ctx.$slots, "default", {}, void 0, true)
          ], 8, _hoisted_3$6),
          vue.createElementVNode("button", {
            class: "adjust-button adjust-button-right",
            onClick: _cache[2] || (_cache[2] = (...args) => __props.onclickRight && __props.onclickRight(...args)),
            disabled: __props.disabledRight
          }, [
            vue.createVNode(BootstrapIcon, {
              icon: __props.iconRight,
              color: __props.color,
              size: __props.size
            }, null, 8, ["icon", "color", "size"])
          ], 8, _hoisted_4$4)
        ]);
      };
    }
  };
  const AdjustWidget = /* @__PURE__ */ _export_sfc(_sfc_main$d, [["__scopeId", "data-v-1c41dc23"]]);
  class ChordSheetElement {
    /** @param {HTMLElement} chordSheetElement  */
    constructor(chordSheetElement) {
      /** @param {NodeList} nodeList */
      __privateAdd(this, _unformat);
      this.chordSheetElement = chordSheetElement;
    }
    /**
     * 將 Header 和譜上的和弦移調,並實質修改於 DOM
     * @param {number} delta 相對於當前調的移調值
     */
    static transposeSheet(delta) {
      $("#tone_z .tf").each(function() {
        const chord = new Chord($(this).text());
        const newChordHTML = chord.transpose(-delta).toFormattedString();
        $(this).html(newChordHTML);
      });
    }
    /** @returns {ChordSheetElement} */
    formatUnderlines() {
      const underlineEl = this.chordSheetElement.querySelectorAll("u");
      const doubleUnderlineEl = this.chordSheetElement.querySelectorAll("abbr");
      underlineEl.forEach((el) => {
        el.innerText = `{_${el.innerText}_}`;
      });
      doubleUnderlineEl.forEach((el) => {
        el.innerText = `{=${el.innerText}=}`;
      });
      return this;
    }
    /** @returns {ChordSheetElement} */
    unformatUnderlines() {
      const underlineEl = this.chordSheetElement.querySelectorAll("u");
      const doubleUnderlineEl = this.chordSheetElement.querySelectorAll("abbr");
      __privateMethod(this, _unformat, unformat_fn).call(this, underlineEl);
      __privateMethod(this, _unformat, unformat_fn).call(this, doubleUnderlineEl);
      return this;
    }
  }
  _unformat = new WeakSet();
  unformat_fn = function(nodeList) {
    nodeList.forEach((el) => {
      el.innerHTML = el.innerText.replaceAll(/{_|{=|=}|_}/g, "").replaceAll(
        /[a-zA-Z0-9#/]+/g,
        /* html */
        `<span class="tf">$&</span>`
      );
    });
  };
  class ChordSheetDocument {
    constructor() {
      this.el = {
        mtitle: document.getElementById("mtitle"),
        tkinfo: document.querySelector(".tkinfo"),
        capoSelect: document.querySelector(".capo .select"),
        tinfo: document.querySelector(".tinfo"),
        tone_z: document.getElementById("tone_z")
      };
    }
    getId() {
      const urlParams = new URLSearchParams(window.location.search);
      return Number(urlParams.get("id"));
    }
    getTitle() {
      return this.el.mtitle.innerText.trim();
    }
    getKey() {
      var _a;
      const match = (_a = this.el.tkinfo) == null ? void 0 : _a.innerText.match(new RegExp("(?<=原調:)\\w*"));
      return match ? match[0].trim() : "";
    }
    getPlay() {
      var _a;
      const match = (_a = this.el.capoSelect) == null ? void 0 : _a.innerText.split(/\s*\/\s*/);
      return match ? match[1].trim() : "";
    }
    getCapo() {
      var _a;
      const match = (_a = this.el.capoSelect) == null ? void 0 : _a.innerText.split(/\s*\/\s*/);
      return match ? Number(match[0]) : 0;
    }
    getSinger() {
      var _a;
      const match = (_a = this.el.tinfo) == null ? void 0 : _a.innerText.match(new RegExp("(?<=演唱:).*(?=\\n|$)"));
      return match ? match[0].trim() : "";
    }
    getComposer() {
      var _a;
      const match = (_a = this.el.tinfo) == null ? void 0 : _a.innerText.match(new RegExp("(?<=曲:).*?(?=詞:|$)"));
      return match ? match[0].trim() : "";
    }
    getLyricist() {
      var _a;
      const match = (_a = this.el.tinfo) == null ? void 0 : _a.innerText.match(new RegExp("(?<=詞:).*?(?=曲:|$)"));
      return match ? match[0].trim() : "";
    }
    getBpm() {
      var _a;
      const match = (_a = this.el.tkinfo) == null ? void 0 : _a.innerText.match(/\d+/);
      return match ? Number(match[0]) : 0;
    }
    getSheetText() {
      const formattedChordSheet = this.el.tone_z.innerText.replaceAll(/\s+?\n/g, "\n").replaceAll("\n\n", "\n").trim().replaceAll(/\s+/g, (match) => {
        return `{%${match.length}%}`;
      });
      return formattedChordSheet;
    }
  }
  class StoreHandler {
    constructor() {
      /** 當 `#store.transpose` 變動時,將譜面上的和弦進行移調 */
      __privateAdd(this, _watchTranspose);
      __privateAdd(this, _watchFontSize);
      // 命 `#store` 為私有屬性,在建立實例時再賦值,避免衝突
      __privateAdd(this, _store, void 0);
      __privateSet(this, _store, useStore());
    }
    initState() {
      const capoSelected = $(".capo .select").eq(0).text().trim();
      const originalCapo = +capoSelected.split(/\s*\/\s*/)[0];
      const originalKey = capoSelected.split(/\s*\/\s*/)[1];
      __privateGet(this, _store).originalCapo = originalCapo;
      __privateGet(this, _store).originalKey = originalKey;
      const fontSize = +$("#tone_z").css("font-size").match(/^\d+/)[0];
      const lineHeight = +$("#tone_z > p").css("line-height").match(/^\d+/)[0];
      __privateGet(this, _store).originalFontSize = fontSize;
      __privateGet(this, _store).originalLineHeight = lineHeight;
      const params = getQueryParams();
      if (params.transpose) {
        __privateGet(this, _store).transpose = params.transpose;
      }
    }
    start() {
      __privateMethod(this, _watchTranspose, watchTranspose_fn).call(this);
      __privateMethod(this, _watchFontSize, watchFontSize_fn).call(this);
      return this;
    }
    static handleKeydown(key) {
      const store = useStore();
      switch (key) {
        case " ": {
          store.toggleToolbars();
          break;
        }
        case "/": {
          if (!store.isToolbarsShow) {
            store.toggleToolbars();
            store.closePopups();
          }
          setTimeout(() => {
            $("#plus91-header input").get(0).focus();
          }, 0);
          break;
        }
        case "Escape": {
          if (store.isToolbarsShow) {
            store.toggleToolbars();
          }
          break;
        }
      }
      if (store.isPopupShow.sheet) {
        switch (key) {
          case "ArrowLeft": {
            store.plusTranspose(-1);
            break;
          }
          case "ArrowRight": {
            store.plusTranspose(1);
            break;
          }
          case "ArrowDown": {
            store.transpose = 0;
            break;
          }
        }
      }
    }
  }
  _store = new WeakMap();
  _watchTranspose = new WeakSet();
  watchTranspose_fn = function() {
    vue.watch(() => {
      return __privateGet(this, _store).transpose;
    }, (newValue, oldValue) => {
      ChordSheetElement.transposeSheet((newValue - oldValue) % 12);
    });
  };
  _watchFontSize = new WeakSet();
  watchFontSize_fn = function() {
    vue.watch(() => {
      return __privateGet(this, _store).fontSizeDelta;
    }, (newValue) => {
      const oFontSize = __privateGet(this, _store).originalFontSize;
      const oLineHeight = __privateGet(this, _store).originalLineHeight;
      $("#tone_z").css("font-size", `${oFontSize + newValue}px`);
      $("#tone_z > p").css("line-height", `${oLineHeight + newValue}px`);
    });
  };
  function redirect() {
    const currentUrl = window.location.href;
    if (/\/song\//.test(currentUrl)) {
      const sheetId = currentUrl.match(new RegExp("(?<=\\/)\\d+(?=\\.)"))[0];
      const newUrl = `https://www.91pu.com.tw/m/tone.shtml?id=${sheetId}`;
      window.location.replace(newUrl);
    }
  }
  function injectGtag() {
    const newScript = document.createElement("script");
    newScript.src = "https://www.googletagmanager.com/gtag/js?id=G-JF4S3HZY31";
    newScript.async = true;
    document.head.appendChild(newScript);
    newScript.onload = () => {
      window.dataLayer = window.dataLayer || [];
      function gtag() {
        window.dataLayer.push(arguments);
      }
      gtag("js", /* @__PURE__ */ new Date());
      gtag("config", "G-JF4S3HZY31");
    };
  }
  function getQueryParams() {
    const url = new URL(window.location.href);
    const params = {
      transpose: +url.searchParams.get("transpose"),
      darkMode: !!url.searchParams.get("darkmode")
    };
    return params;
  }
  function changeTitle() {
    const newTitle = $("#mtitle").text().trim();
    document.title = `${newTitle} | 91+`;
  }
  function archiveChordSheet() {
    const sheet = document.getElementById("tone_z");
    const chordSheetDocument = new ChordSheetDocument();
    try {
      const chordSheetElement = new ChordSheetElement(sheet);
      chordSheetElement.formatUnderlines();
      const formBody = {
        id: chordSheetDocument.getId(),
        title: chordSheetDocument.getTitle(),
        key: chordSheetDocument.getKey(),
        play: chordSheetDocument.getPlay(),
        capo: chordSheetDocument.getCapo(),
        singer: chordSheetDocument.getSinger(),
        composer: chordSheetDocument.getComposer(),
        lyricist: chordSheetDocument.getLyricist(),
        bpm: chordSheetDocument.getBpm(),
        sheet_text: chordSheetDocument.getSheetText()
      };
      chordSheetElement.unformatUnderlines();
      fetch("https://91-plus-plus-api.fly.dev/archive", {
        method: "POST",
        headers: {
          "Content-Type": "application/json"
        },
        body: JSON.stringify(formBody)
      }).then((response) => {
        console.log("[91 Plus] 雲端樂譜備份成功:", response);
      }).catch((error) => {
        console.error("[91 Plus] 雲端樂譜備份失敗:", error);
      });
    } catch {
      console.warn("[91 Plus] 樂譜解析失敗,無法備份");
      fetch(
        `https://91-plus-plus-api.fly.dev/report?id=${chordSheetDocument.getId()}`
      );
    }
  }
  function initMutationObserver() {
    return new MutationObserver((records, observer) => {
      const isMutationDone = !!document.querySelector("#tone_z").childElementCount;
      if (!isMutationDone) {
        return;
      }
      $("body").trigger("mutation.done");
      observer.disconnect();
    }).observe(document.body, { childList: true, subtree: true });
  }
  function onDomReady(callback) {
    $("body").on("mutation.done", callback);
  }
  function handleEvents() {
    $("html").on("keydown", (event) => {
      const excludedTags = ["input"];
      const tagName = event.target.tagName.toLowerCase();
      if (excludedTags.includes(tagName)) {
        return;
      }
      StoreHandler.handleKeydown(event.key);
    });
  }
  function switchInstrument(instrument) {
    switch (instrument) {
      case "guitar": {
        $(".schord").trigger("click");
        break;
      }
      case "ukulele": {
        $(".ukschord").trigger("click");
        break;
      }
      default: {
        $(".nsChord").trigger("click");
        break;
      }
    }
  }
  function getChordShapes() {
    const chordShapes = window.chord_shapes;
    return chordShapes;
  }
  function getChordList() {
    const chordList = [];
    $("#tone_z .tf").each(function() {
      chordList.push($(this).text());
    });
    return [...new Set(chordList)];
  }
  function convertChordName(chordName) {
    const root2 = chordName.match(/^[A-G]#?/)[0];
    const rest = chordName.replace(/^[A-G]#?/, "");
    return `${rest} ${root2}`;
  }
  const _hoisted_1$b = { id: "plus91-sheet-popup" };
  const _hoisted_2$a = { class: "sheet-popup-container" };
  const _hoisted_3$5 = { class: "text-capo" };
  const _hoisted_4$3 = ["innerHTML"];
  const _hoisted_5$1 = { class: "transpose-range-container" };
  const _hoisted_6$1 = ["value"];
  const _hoisted_7 = { class: "instrument-select-container" };
  const _sfc_main$c = {
    __name: "SheetPopup",
    setup(__props) {
      const store = useStore();
      return (_ctx, _cache) => {
        return vue.openBlock(), vue.createBlock(vue.Transition, { name: "slide-and-fade" }, {
          default: vue.withCtx(() => [
            vue.withDirectives(vue.createElementVNode("div", _hoisted_1$b, [
              vue.createElementVNode("div", _hoisted_2$a, [
                vue.createVNode(AdjustWidget, {
                  "onclick-left": () => {
                    vue.unref(store).plusTranspose(-1);
                  },
                  "onclick-middle": () => {
                    vue.unref(store).transpose = 0;
                  },
                  "onclick-right": () => {
                    vue.unref(store).plusTranspose(1);
                  }
                }, {
                  default: vue.withCtx(() => [
                    vue.createTextVNode(" CAPO:"),
                    vue.createElementVNode("span", _hoisted_3$5, vue.toDisplayString(vue.unref(store).currentCapo), 1),
                    vue.createTextVNode(" ("),
                    vue.createElementVNode("span", {
                      class: "text-key",
                      innerHTML: vue.unref(store).currentKey
                    }, null, 8, _hoisted_4$3),
                    vue.createTextVNode(") ")
                  ]),
                  _: 1
                }, 8, ["onclick-left", "onclick-middle", "onclick-right"]),
                vue.createElementVNode("div", _hoisted_5$1, [
                  vue.createElementVNode("input", {
                    type: "range",
                    min: "-11",
                    max: "11",
                    value: vue.unref(store).currentCapo,
                    onInput: _cache[0] || (_cache[0] = ($event) => {
                      vue.unref(store).transpose = $event.target.value - vue.unref(store).originalCapo;
                    })
                  }, null, 40, _hoisted_6$1)
                ]),
                vue.createElementVNode("div", _hoisted_7, [
                  vue.createElementVNode("button", {
                    class: "instrument-select-button",
                    onClick: _cache[1] || (_cache[1] = () => {
                      vue.unref(switchInstrument)("");
                    })
                  }, " 無 "),
                  vue.createElementVNode("button", {
                    class: "instrument-select-button",
                    onClick: _cache[2] || (_cache[2] = () => {
                      vue.unref(switchInstrument)("guitar");
                    })
                  }, " 吉他 "),
                  vue.createElementVNode("button", {
                    class: "instrument-select-button",
                    onClick: _cache[3] || (_cache[3] = () => {
                      vue.unref(switchInstrument)("ukulele");
                    })
                  }, " 烏克莉莉 ")
                ])
              ])
            ], 512), [
              [vue.vShow, vue.unref(store).isPopupShow.sheet]
            ])
          ]),
          _: 1
        });
      };
    }
  };
  const SheetPopup = /* @__PURE__ */ _export_sfc(_sfc_main$c, [["__scopeId", "data-v-f161c46c"]]);
  const methods$1 = {};
  const names = [];
  function registerMethods(name, m) {
    if (Array.isArray(name)) {
      for (const _name of name) {
        registerMethods(_name, m);
      }
      return;
    }
    if (typeof name === "object") {
      for (const _name in name) {
        registerMethods(_name, name[_name]);
      }
      return;
    }
    addMethodNames(Object.getOwnPropertyNames(m));
    methods$1[name] = Object.assign(methods$1[name] || {}, m);
  }
  function getMethodsFor(name) {
    return methods$1[name] || {};
  }
  function getMethodNames() {
    return [...new Set(names)];
  }
  function addMethodNames(_names) {
    names.push(..._names);
  }
  function map(array2, block) {
    let i;
    const il = array2.length;
    const result = [];
    for (i = 0; i < il; i++) {
      result.push(block(array2[i]));
    }
    return result;
  }
  function filter(array2, block) {
    let i;
    const il = array2.length;
    const result = [];
    for (i = 0; i < il; i++) {
      if (block(array2[i])) {
        result.push(array2[i]);
      }
    }
    return result;
  }
  function radians(d) {
    return d % 360 * Math.PI / 180;
  }
  function camelCase(s) {
    return s.toLowerCase().replace(/-(.)/g, function(m, g) {
      return g.toUpperCase();
    });
  }
  function unCamelCase(s) {
    return s.replace(/([A-Z])/g, function(m, g) {
      return "-" + g.toLowerCase();
    });
  }
  function capitalize(s) {
    return s.charAt(0).toUpperCase() + s.slice(1);
  }
  function proportionalSize(element2, width2, height2, box) {
    if (width2 == null || height2 == null) {
      box = box || element2.bbox();
      if (width2 == null) {
        width2 = box.width / box.height * height2;
      } else if (height2 == null) {
        height2 = box.height / box.width * width2;
      }
    }
    return {
      width: width2,
      height: height2
    };
  }
  function getOrigin(o, element2) {
    const origin = o.origin;
    let ox = o.ox != null ? o.ox : o.originX != null ? o.originX : "center";
    let oy = o.oy != null ? o.oy : o.originY != null ? o.originY : "center";
    if (origin != null) {
      [ox, oy] = Array.isArray(origin) ? origin : typeof origin === "object" ? [origin.x, origin.y] : [origin, origin];
    }
    const condX = typeof ox === "string";
    const condY = typeof oy === "string";
    if (condX || condY) {
      const {
        height: height2,
        width: width2,
        x: x2,
        y: y2
      } = element2.bbox();
      if (condX) {
        ox = ox.includes("left") ? x2 : ox.includes("right") ? x2 + width2 : x2 + width2 / 2;
      }
      if (condY) {
        oy = oy.includes("top") ? y2 : oy.includes("bottom") ? y2 + height2 : y2 + height2 / 2;
      }
    }
    return [ox, oy];
  }
  const svg = "http://www.w3.org/2000/svg";
  const html = "http://www.w3.org/1999/xhtml";
  const xmlns = "http://www.w3.org/2000/xmlns/";
  const xlink = "http://www.w3.org/1999/xlink";
  const svgjs = "http://svgjs.dev/svgjs";
  const globals = {
    window: typeof window === "undefined" ? null : window,
    document: typeof document === "undefined" ? null : document
  };
  class Base {
    // constructor (node/*, {extensions = []} */) {
    //   // this.tags = []
    //   //
    //   // for (let extension of extensions) {
    //   //   extension.setup.call(this, node)
    //   //   this.tags.push(extension.name)
    //   // }
    // }
  }
  const elements = {};
  const root = "___SYMBOL___ROOT___";
  function create(name, ns = svg) {
    return globals.document.createElementNS(ns, name);
  }
  function makeInstance(element2, isHTML = false) {
    if (element2 instanceof Base)
      return element2;
    if (typeof element2 === "object") {
      return adopter(element2);
    }
    if (element2 == null) {
      return new elements[root]();
    }
    if (typeof element2 === "string" && element2.charAt(0) !== "<") {
      return adopter(globals.document.querySelector(element2));
    }
    const wrapper = isHTML ? globals.document.createElement("div") : create("svg");
    wrapper.innerHTML = element2;
    element2 = adopter(wrapper.firstChild);
    wrapper.removeChild(wrapper.firstChild);
    return element2;
  }
  function nodeOrNew(name, node) {
    return node && node.ownerDocument && node instanceof node.ownerDocument.defaultView.Node ? node : create(name);
  }
  function adopt(node) {
    if (!node)
      return null;
    if (node.instance instanceof Base)
      return node.instance;
    if (node.nodeName === "#document-fragment") {
      return new elements.Fragment(node);
    }
    let className = capitalize(node.nodeName || "Dom");
    if (className === "LinearGradient" || className === "RadialGradient") {
      className = "Gradient";
    } else if (!elements[className]) {
      className = "Dom";
    }
    return new elements[className](node);
  }
  let adopter = adopt;
  function register(element2, name = element2.name, asRoot = false) {
    elements[name] = element2;
    if (asRoot)
      elements[root] = element2;
    addMethodNames(Object.getOwnPropertyNames(element2.prototype));
    return element2;
  }
  function getClass(name) {
    return elements[name];
  }
  let did = 1e3;
  function eid(name) {
    return "Svgjs" + capitalize(name) + did++;
  }
  function assignNewId(node) {
    for (let i = node.children.length - 1; i >= 0; i--) {
      assignNewId(node.children[i]);
    }
    if (node.id) {
      node.id = eid(node.nodeName);
      return node;
    }
    return node;
  }
  function extend(modules, methods2) {
    let key, i;
    modules = Array.isArray(modules) ? modules : [modules];
    for (i = modules.length - 1; i >= 0; i--) {
      for (key in methods2) {
        modules[i].prototype[key] = methods2[key];
      }
    }
  }
  function wrapWithAttrCheck(fn) {
    return function(...args) {
      const o = args[args.length - 1];
      if (o && o.constructor === Object && !(o instanceof Array)) {
        return fn.apply(this, args.slice(0, -1)).attr(o);
      } else {
        return fn.apply(this, args);
      }
    };
  }
  function siblings() {
    return this.parent().children();
  }
  function position() {
    return this.parent().index(this);
  }
  function next() {
    return this.siblings()[this.position() + 1];
  }
  function prev() {
    return this.siblings()[this.position() - 1];
  }
  function forward() {
    const i = this.position();
    const p = this.parent();
    p.add(this.remove(), i + 1);
    return this;
  }
  function backward() {
    const i = this.position();
    const p = this.parent();
    p.add(this.remove(), i ? i - 1 : 0);
    return this;
  }
  function front() {
    const p = this.parent();
    p.add(this.remove());
    return this;
  }
  function back() {
    const p = this.parent();
    p.add(this.remove(), 0);
    return this;
  }
  function before(element2) {
    element2 = makeInstance(element2);
    element2.remove();
    const i = this.position();
    this.parent().add(element2, i);
    return this;
  }
  function after(element2) {
    element2 = makeInstance(element2);
    element2.remove();
    const i = this.position();
    this.parent().add(element2, i + 1);
    return this;
  }
  function insertBefore(element2) {
    element2 = makeInstance(element2);
    element2.before(this);
    return this;
  }
  function insertAfter(element2) {
    element2 = makeInstance(element2);
    element2.after(this);
    return this;
  }
  registerMethods("Dom", {
    siblings,
    position,
    next,
    prev,
    forward,
    backward,
    front,
    back,
    before,
    after,
    insertBefore,
    insertAfter
  });
  const numberAndUnit = /^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i;
  const hex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i;
  const rgb = /rgb\((\d+),(\d+),(\d+)\)/;
  const reference = /(#[a-z_][a-z0-9\-_]*)/i;
  const transforms = /\)\s*,?\s*/;
  const whitespace = /\s/g;
  const isHex = /^#[a-f0-9]{3}$|^#[a-f0-9]{6}$/i;
  const isRgb = /^rgb\(/;
  const isBlank = /^(\s+)?$/;
  const isNumber = /^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i;
  const isImage = /\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i;
  const delimiter = /[\s,]+/;
  const isPathLetter = /[MLHVCSQTAZ]/i;
  function classes() {
    const attr2 = this.attr("class");
    return attr2 == null ? [] : attr2.trim().split(delimiter);
  }
  function hasClass(name) {
    return this.classes().indexOf(name) !== -1;
  }
  function addClass(name) {
    if (!this.hasClass(name)) {
      const array2 = this.classes();
      array2.push(name);
      this.attr("class", array2.join(" "));
    }
    return this;
  }
  function removeClass(name) {
    if (this.hasClass(name)) {
      this.attr("class", this.classes().filter(function(c) {
        return c !== name;
      }).join(" "));
    }
    return this;
  }
  function toggleClass(name) {
    return this.hasClass(name) ? this.removeClass(name) : this.addClass(name);
  }
  registerMethods("Dom", {
    classes,
    hasClass,
    addClass,
    removeClass,
    toggleClass
  });
  function css(style, val) {
    const ret = {};
    if (arguments.length === 0) {
      this.node.style.cssText.split(/\s*;\s*/).filter(function(el) {
        return !!el.length;
      }).forEach(function(el) {
        const t = el.split(/\s*:\s*/);
        ret[t[0]] = t[1];
      });
      return ret;
    }
    if (arguments.length < 2) {
      if (Array.isArray(style)) {
        for (const name of style) {
          const cased = camelCase(name);
          ret[name] = this.node.style[cased];
        }
        return ret;
      }
      if (typeof style === "string") {
        return this.node.style[camelCase(style)];
      }
      if (typeof style === "object") {
        for (const name in style) {
          this.node.style[camelCase(name)] = style[name] == null || isBlank.test(style[name]) ? "" : style[name];
        }
      }
    }
    if (arguments.length === 2) {
      this.node.style[camelCase(style)] = val == null || isBlank.test(val) ? "" : val;
    }
    return this;
  }
  function show() {
    return this.css("display", "");
  }
  function hide() {
    return this.css("display", "none");
  }
  function visible() {
    return this.css("display") !== "none";
  }
  registerMethods("Dom", {
    css,
    show,
    hide,
    visible
  });
  function data(a, v, r) {
    if (a == null) {
      return this.data(map(filter(this.node.attributes, (el) => el.nodeName.indexOf("data-") === 0), (el) => el.nodeName.slice(5)));
    } else if (a instanceof Array) {
      const data2 = {};
      for (const key of a) {
        data2[key] = this.data(key);
      }
      return data2;
    } else if (typeof a === "object") {
      for (v in a) {
        this.data(v, a[v]);
      }
    } else if (arguments.length < 2) {
      try {
        return JSON.parse(this.attr("data-" + a));
      } catch (e) {
        return this.attr("data-" + a);
      }
    } else {
      this.attr("data-" + a, v === null ? null : r === true || typeof v === "string" || typeof v === "number" ? v : JSON.stringify(v));
    }
    return this;
  }
  registerMethods("Dom", {
    data
  });
  function remember(k, v) {
    if (typeof arguments[0] === "object") {
      for (const key in k) {
        this.remember(key, k[key]);
      }
    } else if (arguments.length === 1) {
      return this.memory()[k];
    } else {
      this.memory()[k] = v;
    }
    return this;
  }
  function forget() {
    if (arguments.length === 0) {
      this._memory = {};
    } else {
      for (let i = arguments.length - 1; i >= 0; i--) {
        delete this.memory()[arguments[i]];
      }
    }
    return this;
  }
  function memory() {
    return this._memory = this._memory || {};
  }
  registerMethods("Dom", {
    remember,
    forget,
    memory
  });
  function sixDigitHex(hex2) {
    return hex2.length === 4 ? ["#", hex2.substring(1, 2), hex2.substring(1, 2), hex2.substring(2, 3), hex2.substring(2, 3), hex2.substring(3, 4), hex2.substring(3, 4)].join("") : hex2;
  }
  function componentHex(component) {
    const integer = Math.round(component);
    const bounded = Math.max(0, Math.min(255, integer));
    const hex2 = bounded.toString(16);
    return hex2.length === 1 ? "0" + hex2 : hex2;
  }
  function is(object2, space) {
    for (let i = space.length; i--; ) {
      if (object2[space[i]] == null) {
        return false;
      }
    }
    return true;
  }
  function getParameters(a, b) {
    const params = is(a, "rgb") ? {
      _a: a.r,
      _b: a.g,
      _c: a.b,
      _d: 0,
      space: "rgb"
    } : is(a, "xyz") ? {
      _a: a.x,
      _b: a.y,
      _c: a.z,
      _d: 0,
      space: "xyz"
    } : is(a, "hsl") ? {
      _a: a.h,
      _b: a.s,
      _c: a.l,
      _d: 0,
      space: "hsl"
    } : is(a, "lab") ? {
      _a: a.l,
      _b: a.a,
      _c: a.b,
      _d: 0,
      space: "lab"
    } : is(a, "lch") ? {
      _a: a.l,
      _b: a.c,
      _c: a.h,
      _d: 0,
      space: "lch"
    } : is(a, "cmyk") ? {
      _a: a.c,
      _b: a.m,
      _c: a.y,
      _d: a.k,
      space: "cmyk"
    } : {
      _a: 0,
      _b: 0,
      _c: 0,
      space: "rgb"
    };
    params.space = b || params.space;
    return params;
  }
  function cieSpace(space) {
    if (space === "lab" || space === "xyz" || space === "lch") {
      return true;
    } else {
      return false;
    }
  }
  function hueToRgb(p, q, t) {
    if (t < 0)
      t += 1;
    if (t > 1)
      t -= 1;
    if (t < 1 / 6)
      return p + (q - p) * 6 * t;
    if (t < 1 / 2)
      return q;
    if (t < 2 / 3)
      return p + (q - p) * (2 / 3 - t) * 6;
    return p;
  }
  class Color {
    constructor(...inputs) {
      this.init(...inputs);
    }
    // Test if given value is a color
    static isColor(color) {
      return color && (color instanceof Color || this.isRgb(color) || this.test(color));
    }
    // Test if given value is an rgb object
    static isRgb(color) {
      return color && typeof color.r === "number" && typeof color.g === "number" && typeof color.b === "number";
    }
    /*
    Generating random colors
    */
    static random(mode = "vibrant", t, u) {
      const {
        random,
        round,
        sin,
        PI: pi
      } = Math;
      if (mode === "vibrant") {
        const l = (81 - 57) * random() + 57;
        const c = (83 - 45) * random() + 45;
        const h = 360 * random();
        const color = new Color(l, c, h, "lch");
        return color;
      } else if (mode === "sine") {
        t = t == null ? random() : t;
        const r = round(80 * sin(2 * pi * t / 0.5 + 0.01) + 150);
        const g = round(50 * sin(2 * pi * t / 0.5 + 4.6) + 200);
        const b = round(100 * sin(2 * pi * t / 0.5 + 2.3) + 150);
        const color = new Color(r, g, b);
        return color;
      } else if (mode === "pastel") {
        const l = (94 - 86) * random() + 86;
        const c = (26 - 9) * random() + 9;
        const h = 360 * random();
        const color = new Color(l, c, h, "lch");
        return color;
      } else if (mode === "dark") {
        const l = 10 + 10 * random();
        const c = (125 - 75) * random() + 86;
        const h = 360 * random();
        const color = new Color(l, c, h, "lch");
        return color;
      } else if (mode === "rgb") {
        const r = 255 * random();
        const g = 255 * random();
        const b = 255 * random();
        const color = new Color(r, g, b);
        return color;
      } else if (mode === "lab") {
        const l = 100 * random();
        const a = 256 * random() - 128;
        const b = 256 * random() - 128;
        const color = new Color(l, a, b, "lab");
        return color;
      } else if (mode === "grey") {
        const grey = 255 * random();
        const color = new Color(grey, grey, grey);
        return color;
      } else {
        throw new Error("Unsupported random color mode");
      }
    }
    // Test if given value is a color string
    static test(color) {
      return typeof color === "string" && (isHex.test(color) || isRgb.test(color));
    }
    cmyk() {
      const {
        _a,
        _b,
        _c
      } = this.rgb();
      const [r, g, b] = [_a, _b, _c].map((v) => v / 255);
      const k = Math.min(1 - r, 1 - g, 1 - b);
      if (k === 1) {
        return new Color(0, 0, 0, 1, "cmyk");
      }
      const c = (1 - r - k) / (1 - k);
      const m = (1 - g - k) / (1 - k);
      const y2 = (1 - b - k) / (1 - k);
      const color = new Color(c, m, y2, k, "cmyk");
      return color;
    }
    hsl() {
      const {
        _a,
        _b,
        _c
      } = this.rgb();
      const [r, g, b] = [_a, _b, _c].map((v) => v / 255);
      const max = Math.max(r, g, b);
      const min = Math.min(r, g, b);
      const l = (max + min) / 2;
      const isGrey = max === min;
      const delta = max - min;
      const s = isGrey ? 0 : l > 0.5 ? delta / (2 - max - min) : delta / (max + min);
      const h = isGrey ? 0 : max === r ? ((g - b) / delta + (g < b ? 6 : 0)) / 6 : max === g ? ((b - r) / delta + 2) / 6 : max === b ? ((r - g) / delta + 4) / 6 : 0;
      const color = new Color(360 * h, 100 * s, 100 * l, "hsl");
      return color;
    }
    init(a = 0, b = 0, c = 0, d = 0, space = "rgb") {
      a = !a ? 0 : a;
      if (this.space) {
        for (const component in this.space) {
          delete this[this.space[component]];
        }
      }
      if (typeof a === "number") {
        space = typeof d === "string" ? d : space;
        d = typeof d === "string" ? 0 : d;
        Object.assign(this, {
          _a: a,
          _b: b,
          _c: c,
          _d: d,
          space
        });
      } else if (a instanceof Array) {
        this.space = b || (typeof a[3] === "string" ? a[3] : a[4]) || "rgb";
        Object.assign(this, {
          _a: a[0],
          _b: a[1],
          _c: a[2],
          _d: a[3] || 0
        });
      } else if (a instanceof Object) {
        const values = getParameters(a, b);
        Object.assign(this, values);
      } else if (typeof a === "string") {
        if (isRgb.test(a)) {
          const noWhitespace = a.replace(whitespace, "");
          const [_a2, _b2, _c2] = rgb.exec(noWhitespace).slice(1, 4).map((v) => parseInt(v));
          Object.assign(this, {
            _a: _a2,
            _b: _b2,
            _c: _c2,
            _d: 0,
            space: "rgb"
          });
        } else if (isHex.test(a)) {
          const hexParse = (v) => parseInt(v, 16);
          const [, _a2, _b2, _c2] = hex.exec(sixDigitHex(a)).map(hexParse);
          Object.assign(this, {
            _a: _a2,
            _b: _b2,
            _c: _c2,
            _d: 0,
            space: "rgb"
          });
        } else
          throw Error("Unsupported string format, can't construct Color");
      }
      const {
        _a,
        _b,
        _c,
        _d
      } = this;
      const components = this.space === "rgb" ? {
        r: _a,
        g: _b,
        b: _c
      } : this.space === "xyz" ? {
        x: _a,
        y: _b,
        z: _c
      } : this.space === "hsl" ? {
        h: _a,
        s: _b,
        l: _c
      } : this.space === "lab" ? {
        l: _a,
        a: _b,
        b: _c
      } : this.space === "lch" ? {
        l: _a,
        c: _b,
        h: _c
      } : this.space === "cmyk" ? {
        c: _a,
        m: _b,
        y: _c,
        k: _d
      } : {};
      Object.assign(this, components);
    }
    lab() {
      const {
        x: x2,
        y: y2,
        z
      } = this.xyz();
      const l = 116 * y2 - 16;
      const a = 500 * (x2 - y2);
      const b = 200 * (y2 - z);
      const color = new Color(l, a, b, "lab");
      return color;
    }
    lch() {
      const {
        l,
        a,
        b
      } = this.lab();
      const c = Math.sqrt(a ** 2 + b ** 2);
      let h = 180 * Math.atan2(b, a) / Math.PI;
      if (h < 0) {
        h *= -1;
        h = 360 - h;
      }
      const color = new Color(l, c, h, "lch");
      return color;
    }
    /*
    Conversion Methods
    */
    rgb() {
      if (this.space === "rgb") {
        return this;
      } else if (cieSpace(this.space)) {
        let {
          x: x2,
          y: y2,
          z
        } = this;
        if (this.space === "lab" || this.space === "lch") {
          let {
            l,
            a,
            b: b2
          } = this;
          if (this.space === "lch") {
            const {
              c,
              h
            } = this;
            const dToR = Math.PI / 180;
            a = c * Math.cos(dToR * h);
            b2 = c * Math.sin(dToR * h);
          }
          const yL = (l + 16) / 116;
          const xL = a / 500 + yL;
          const zL = yL - b2 / 200;
          const ct = 16 / 116;
          const mx = 8856e-6;
          const nm = 7.787;
          x2 = 0.95047 * (xL ** 3 > mx ? xL ** 3 : (xL - ct) / nm);
          y2 = 1 * (yL ** 3 > mx ? yL ** 3 : (yL - ct) / nm);
          z = 1.08883 * (zL ** 3 > mx ? zL ** 3 : (zL - ct) / nm);
        }
        const rU = x2 * 3.2406 + y2 * -1.5372 + z * -0.4986;
        const gU = x2 * -0.9689 + y2 * 1.8758 + z * 0.0415;
        const bU = x2 * 0.0557 + y2 * -0.204 + z * 1.057;
        const pow = Math.pow;
        const bd = 31308e-7;
        const r = rU > bd ? 1.055 * pow(rU, 1 / 2.4) - 0.055 : 12.92 * rU;
        const g = gU > bd ? 1.055 * pow(gU, 1 / 2.4) - 0.055 : 12.92 * gU;
        const b = bU > bd ? 1.055 * pow(bU, 1 / 2.4) - 0.055 : 12.92 * bU;
        const color = new Color(255 * r, 255 * g, 255 * b);
        return color;
      } else if (this.space === "hsl") {
        let {
          h,
          s,
          l
        } = this;
        h /= 360;
        s /= 100;
        l /= 100;
        if (s === 0) {
          l *= 255;
          const color2 = new Color(l, l, l);
          return color2;
        }
        const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
        const p = 2 * l - q;
        const r = 255 * hueToRgb(p, q, h + 1 / 3);
        const g = 255 * hueToRgb(p, q, h);
        const b = 255 * hueToRgb(p, q, h - 1 / 3);
        const color = new Color(r, g, b);
        return color;
      } else if (this.space === "cmyk") {
        const {
          c,
          m,
          y: y2,
          k
        } = this;
        const r = 255 * (1 - Math.min(1, c * (1 - k) + k));
        const g = 255 * (1 - Math.min(1, m * (1 - k) + k));
        const b = 255 * (1 - Math.min(1, y2 * (1 - k) + k));
        const color = new Color(r, g, b);
        return color;
      } else {
        return this;
      }
    }
    toArray() {
      const {
        _a,
        _b,
        _c,
        _d,
        space
      } = this;
      return [_a, _b, _c, _d, space];
    }
    toHex() {
      const [r, g, b] = this._clamped().map(componentHex);
      return `#${r}${g}${b}`;
    }
    toRgb() {
      const [rV, gV, bV] = this._clamped();
      const string2 = `rgb(${rV},${gV},${bV})`;
      return string2;
    }
    toString() {
      return this.toHex();
    }
    xyz() {
      const {
        _a: r255,
        _b: g255,
        _c: b255
      } = this.rgb();
      const [r, g, b] = [r255, g255, b255].map((v) => v / 255);
      const rL = r > 0.04045 ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92;
      const gL = g > 0.04045 ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92;
      const bL = b > 0.04045 ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92;
      const xU = (rL * 0.4124 + gL * 0.3576 + bL * 0.1805) / 0.95047;
      const yU = (rL * 0.2126 + gL * 0.7152 + bL * 0.0722) / 1;
      const zU = (rL * 0.0193 + gL * 0.1192 + bL * 0.9505) / 1.08883;
      const x2 = xU > 8856e-6 ? Math.pow(xU, 1 / 3) : 7.787 * xU + 16 / 116;
      const y2 = yU > 8856e-6 ? Math.pow(yU, 1 / 3) : 7.787 * yU + 16 / 116;
      const z = zU > 8856e-6 ? Math.pow(zU, 1 / 3) : 7.787 * zU + 16 / 116;
      const color = new Color(x2, y2, z, "xyz");
      return color;
    }
    /*
    Input and Output methods
    */
    _clamped() {
      const {
        _a,
        _b,
        _c
      } = this.rgb();
      const {
        max,
        min,
        round
      } = Math;
      const format = (v) => max(0, min(round(v), 255));
      return [_a, _b, _c].map(format);
    }
    /*
    Constructing colors
    */
  }
  class Point {
    // Initialize
    constructor(...args) {
      this.init(...args);
    }
    // Clone point
    clone() {
      return new Point(this);
    }
    init(x2, y2) {
      const base = {
        x: 0,
        y: 0
      };
      const source = Array.isArray(x2) ? {
        x: x2[0],
        y: x2[1]
      } : typeof x2 === "object" ? {
        x: x2.x,
        y: x2.y
      } : {
        x: x2,
        y: y2
      };
      this.x = source.x == null ? base.x : source.x;
      this.y = source.y == null ? base.y : source.y;
      return this;
    }
    toArray() {
      return [this.x, this.y];
    }
    transform(m) {
      return this.clone().transformO(m);
    }
    // Transform point with matrix
    transformO(m) {
      if (!Matrix.isMatrixLike(m)) {
        m = new Matrix(m);
      }
      const {
        x: x2,
        y: y2
      } = this;
      this.x = m.a * x2 + m.c * y2 + m.e;
      this.y = m.b * x2 + m.d * y2 + m.f;
      return this;
    }
  }
  function point(x2, y2) {
    return new Point(x2, y2).transformO(this.screenCTM().inverseO());
  }
  function closeEnough(a, b, threshold) {
    return Math.abs(b - a) < (threshold || 1e-6);
  }
  class Matrix {
    constructor(...args) {
      this.init(...args);
    }
    static formatTransforms(o) {
      const flipBoth = o.flip === "both" || o.flip === true;
      const flipX = o.flip && (flipBoth || o.flip === "x") ? -1 : 1;
      const flipY = o.flip && (flipBoth || o.flip === "y") ? -1 : 1;
      const skewX = o.skew && o.skew.length ? o.skew[0] : isFinite(o.skew) ? o.skew : isFinite(o.skewX) ? o.skewX : 0;
      const skewY = o.skew && o.skew.length ? o.skew[1] : isFinite(o.skew) ? o.skew : isFinite(o.skewY) ? o.skewY : 0;
      const scaleX = o.scale && o.scale.length ? o.scale[0] * flipX : isFinite(o.scale) ? o.scale * flipX : isFinite(o.scaleX) ? o.scaleX * flipX : flipX;
      const scaleY = o.scale && o.scale.length ? o.scale[1] * flipY : isFinite(o.scale) ? o.scale * flipY : isFinite(o.scaleY) ? o.scaleY * flipY : flipY;
      const shear = o.shear || 0;
      const theta = o.rotate || o.theta || 0;
      const origin = new Point(o.origin || o.around || o.ox || o.originX, o.oy || o.originY);
      const ox = origin.x;
      const oy = origin.y;
      const position2 = new Point(o.position || o.px || o.positionX || NaN, o.py || o.positionY || NaN);
      const px = position2.x;
      const py = position2.y;
      const translate = new Point(o.translate || o.tx || o.translateX, o.ty || o.translateY);
      const tx = translate.x;
      const ty = translate.y;
      const relative = new Point(o.relative || o.rx || o.relativeX, o.ry || o.relativeY);
      const rx2 = relative.x;
      const ry2 = relative.y;
      return {
        scaleX,
        scaleY,
        skewX,
        skewY,
        shear,
        theta,
        rx: rx2,
        ry: ry2,
        tx,
        ty,
        ox,
        oy,
        px,
        py
      };
    }
    static fromArray(a) {
      return {
        a: a[0],
        b: a[1],
        c: a[2],
        d: a[3],
        e: a[4],
        f: a[5]
      };
    }
    static isMatrixLike(o) {
      return o.a != null || o.b != null || o.c != null || o.d != null || o.e != null || o.f != null;
    }
    // left matrix, right matrix, target matrix which is overwritten
    static matrixMultiply(l, r, o) {
      const a = l.a * r.a + l.c * r.b;
      const b = l.b * r.a + l.d * r.b;
      const c = l.a * r.c + l.c * r.d;
      const d = l.b * r.c + l.d * r.d;
      const e = l.e + l.a * r.e + l.c * r.f;
      const f = l.f + l.b * r.e + l.d * r.f;
      o.a = a;
      o.b = b;
      o.c = c;
      o.d = d;
      o.e = e;
      o.f = f;
      return o;
    }
    around(cx2, cy2, matrix) {
      return this.clone().aroundO(cx2, cy2, matrix);
    }
    // Transform around a center point
    aroundO(cx2, cy2, matrix) {
      const dx2 = cx2 || 0;
      const dy2 = cy2 || 0;
      return this.translateO(-dx2, -dy2).lmultiplyO(matrix).translateO(dx2, dy2);
    }
    // Clones this matrix
    clone() {
      return new Matrix(this);
    }
    // Decomposes this matrix into its affine parameters
    decompose(cx2 = 0, cy2 = 0) {
      const a = this.a;
      const b = this.b;
      const c = this.c;
      const d = this.d;
      const e = this.e;
      const f = this.f;
      const determinant = a * d - b * c;
      const ccw = determinant > 0 ? 1 : -1;
      const sx = ccw * Math.sqrt(a * a + b * b);
      const thetaRad = Math.atan2(ccw * b, ccw * a);
      const theta = 180 / Math.PI * thetaRad;
      const ct = Math.cos(thetaRad);
      const st = Math.sin(thetaRad);
      const lam = (a * c + b * d) / determinant;
      const sy = c * sx / (lam * a - b) || d * sx / (lam * b + a);
      const tx = e - cx2 + cx2 * ct * sx + cy2 * (lam * ct * sx - st * sy);
      const ty = f - cy2 + cx2 * st * sx + cy2 * (lam * st * sx + ct * sy);
      return {
        // Return the affine parameters
        scaleX: sx,
        scaleY: sy,
        shear: lam,
        rotate: theta,
        translateX: tx,
        translateY: ty,
        originX: cx2,
        originY: cy2,
        // Return the matrix parameters
        a: this.a,
        b: this.b,
        c: this.c,
        d: this.d,
        e: this.e,
        f: this.f
      };
    }
    // Check if two matrices are equal
    equals(other) {
      if (other === this)
        return true;
      const comp = new Matrix(other);
      return closeEnough(this.a, comp.a) && closeEnough(this.b, comp.b) && closeEnough(this.c, comp.c) && closeEnough(this.d, comp.d) && closeEnough(this.e, comp.e) && closeEnough(this.f, comp.f);
    }
    // Flip matrix on x or y, at a given offset
    flip(axis, around) {
      return this.clone().flipO(axis, around);
    }
    flipO(axis, around) {
      return axis === "x" ? this.scaleO(-1, 1, around, 0) : axis === "y" ? this.scaleO(1, -1, 0, around) : this.scaleO(-1, -1, axis, around || axis);
    }
    // Initialize
    init(source) {
      const base = Matrix.fromArray([1, 0, 0, 1, 0, 0]);
      source = source instanceof Element ? source.matrixify() : typeof source === "string" ? Matrix.fromArray(source.split(delimiter).map(parseFloat)) : Array.isArray(source) ? Matrix.fromArray(source) : typeof source === "object" && Matrix.isMatrixLike(source) ? source : typeof source === "object" ? new Matrix().transform(source) : arguments.length === 6 ? Matrix.fromArray([].slice.call(arguments)) : base;
      this.a = source.a != null ? source.a : base.a;
      this.b = source.b != null ? source.b : base.b;
      this.c = source.c != null ? source.c : base.c;
      this.d = source.d != null ? source.d : base.d;
      this.e = source.e != null ? source.e : base.e;
      this.f = source.f != null ? source.f : base.f;
      return this;
    }
    inverse() {
      return this.clone().inverseO();
    }
    // Inverses matrix
    inverseO() {
      const a = this.a;
      const b = this.b;
      const c = this.c;
      const d = this.d;
      const e = this.e;
      const f = this.f;
      const det = a * d - b * c;
      if (!det)
        throw new Error("Cannot invert " + this);
      const na = d / det;
      const nb = -b / det;
      const nc = -c / det;
      const nd = a / det;
      const ne = -(na * e + nc * f);
      const nf = -(nb * e + nd * f);
      this.a = na;
      this.b = nb;
      this.c = nc;
      this.d = nd;
      this.e = ne;
      this.f = nf;
      return this;
    }
    lmultiply(matrix) {
      return this.clone().lmultiplyO(matrix);
    }
    lmultiplyO(matrix) {
      const r = this;
      const l = matrix instanceof Matrix ? matrix : new Matrix(matrix);
      return Matrix.matrixMultiply(l, r, this);
    }
    // Left multiplies by the given matrix
    multiply(matrix) {
      return this.clone().multiplyO(matrix);
    }
    multiplyO(matrix) {
      const l = this;
      const r = matrix instanceof Matrix ? matrix : new Matrix(matrix);
      return Matrix.matrixMultiply(l, r, this);
    }
    // Rotate matrix
    rotate(r, cx2, cy2) {
      return this.clone().rotateO(r, cx2, cy2);
    }
    rotateO(r, cx2 = 0, cy2 = 0) {
      r = radians(r);
      const cos = Math.cos(r);
      const sin = Math.sin(r);
      const {
        a,
        b,
        c,
        d,
        e,
        f
      } = this;
      this.a = a * cos - b * sin;
      this.b = b * cos + a * sin;
      this.c = c * cos - d * sin;
      this.d = d * cos + c * sin;
      this.e = e * cos - f * sin + cy2 * sin - cx2 * cos + cx2;
      this.f = f * cos + e * sin - cx2 * sin - cy2 * cos + cy2;
      return this;
    }
    // Scale matrix
    scale(x2, y2, cx2, cy2) {
      return this.clone().scaleO(...arguments);
    }
    scaleO(x2, y2 = x2, cx2 = 0, cy2 = 0) {
      if (arguments.length === 3) {
        cy2 = cx2;
        cx2 = y2;
        y2 = x2;
      }
      const {
        a,
        b,
        c,
        d,
        e,
        f
      } = this;
      this.a = a * x2;
      this.b = b * y2;
      this.c = c * x2;
      this.d = d * y2;
      this.e = e * x2 - cx2 * x2 + cx2;
      this.f = f * y2 - cy2 * y2 + cy2;
      return this;
    }
    // Shear matrix
    shear(a, cx2, cy2) {
      return this.clone().shearO(a, cx2, cy2);
    }
    shearO(lx, cx2 = 0, cy2 = 0) {
      const {
        a,
        b,
        c,
        d,
        e,
        f
      } = this;
      this.a = a + b * lx;
      this.c = c + d * lx;
      this.e = e + f * lx - cy2 * lx;
      return this;
    }
    // Skew Matrix
    skew(x2, y2, cx2, cy2) {
      return this.clone().skewO(...arguments);
    }
    skewO(x2, y2 = x2, cx2 = 0, cy2 = 0) {
      if (arguments.length === 3) {
        cy2 = cx2;
        cx2 = y2;
        y2 = x2;
      }
      x2 = radians(x2);
      y2 = radians(y2);
      const lx = Math.tan(x2);
      const ly = Math.tan(y2);
      const {
        a,
        b,
        c,
        d,
        e,
        f
      } = this;
      this.a = a + b * lx;
      this.b = b + a * ly;
      this.c = c + d * lx;
      this.d = d + c * ly;
      this.e = e + f * lx - cy2 * lx;
      this.f = f + e * ly - cx2 * ly;
      return this;
    }
    // SkewX
    skewX(x2, cx2, cy2) {
      return this.skew(x2, 0, cx2, cy2);
    }
    // SkewY
    skewY(y2, cx2, cy2) {
      return this.skew(0, y2, cx2, cy2);
    }
    toArray() {
      return [this.a, this.b, this.c, this.d, this.e, this.f];
    }
    // Convert matrix to string
    toString() {
      return "matrix(" + this.a + "," + this.b + "," + this.c + "," + this.d + "," + this.e + "," + this.f + ")";
    }
    // Transform a matrix into another matrix by manipulating the space
    transform(o) {
      if (Matrix.isMatrixLike(o)) {
        const matrix = new Matrix(o);
        return matrix.multiplyO(this);
      }
      const t = Matrix.formatTransforms(o);
      const current = this;
      const {
        x: ox,
        y: oy
      } = new Point(t.ox, t.oy).transform(current);
      const transformer = new Matrix().translateO(t.rx, t.ry).lmultiplyO(current).translateO(-ox, -oy).scaleO(t.scaleX, t.scaleY).skewO(t.skewX, t.skewY).shearO(t.shear).rotateO(t.theta).translateO(ox, oy);
      if (isFinite(t.px) || isFinite(t.py)) {
        const origin = new Point(ox, oy).transform(transformer);
        const dx2 = isFinite(t.px) ? t.px - origin.x : 0;
        const dy2 = isFinite(t.py) ? t.py - origin.y : 0;
        transformer.translateO(dx2, dy2);
      }
      transformer.translateO(t.tx, t.ty);
      return transformer;
    }
    // Translate matrix
    translate(x2, y2) {
      return this.clone().translateO(x2, y2);
    }
    translateO(x2, y2) {
      this.e += x2 || 0;
      this.f += y2 || 0;
      return this;
    }
    valueOf() {
      return {
        a: this.a,
        b: this.b,
        c: this.c,
        d: this.d,
        e: this.e,
        f: this.f
      };
    }
  }
  function ctm() {
    return new Matrix(this.node.getCTM());
  }
  function screenCTM() {
    if (typeof this.isRoot === "function" && !this.isRoot()) {
      const rect = this.rect(1, 1);
      const m = rect.node.getScreenCTM();
      rect.remove();
      return new Matrix(m);
    }
    return new Matrix(this.node.getScreenCTM());
  }
  register(Matrix, "Matrix");
  function parser() {
    if (!parser.nodes) {
      const svg2 = makeInstance().size(2, 0);
      svg2.node.style.cssText = ["opacity: 0", "position: absolute", "left: -100%", "top: -100%", "overflow: hidden"].join(";");
      svg2.attr("focusable", "false");
      svg2.attr("aria-hidden", "true");
      const path = svg2.path().node;
      parser.nodes = {
        svg: svg2,
        path
      };
    }
    if (!parser.nodes.svg.node.parentNode) {
      const b = globals.document.body || globals.document.documentElement;
      parser.nodes.svg.addTo(b);
    }
    return parser.nodes;
  }
  function isNulledBox(box) {
    return !box.width && !box.height && !box.x && !box.y;
  }
  function domContains(node) {
    return node === globals.document || (globals.document.documentElement.contains || function(node2) {
      while (node2.parentNode) {
        node2 = node2.parentNode;
      }
      return node2 === globals.document;
    }).call(globals.document.documentElement, node);
  }
  class Box {
    constructor(...args) {
      this.init(...args);
    }
    addOffset() {
      this.x += globals.window.pageXOffset;
      this.y += globals.window.pageYOffset;
      return new Box(this);
    }
    init(source) {
      const base = [0, 0, 0, 0];
      source = typeof source === "string" ? source.split(delimiter).map(parseFloat) : Array.isArray(source) ? source : typeof source === "object" ? [source.left != null ? source.left : source.x, source.top != null ? source.top : source.y, source.width, source.height] : arguments.length === 4 ? [].slice.call(arguments) : base;
      this.x = source[0] || 0;
      this.y = source[1] || 0;
      this.width = this.w = source[2] || 0;
      this.height = this.h = source[3] || 0;
      this.x2 = this.x + this.w;
      this.y2 = this.y + this.h;
      this.cx = this.x + this.w / 2;
      this.cy = this.y + this.h / 2;
      return this;
    }
    isNulled() {
      return isNulledBox(this);
    }
    // Merge rect box with another, return a new instance
    merge(box) {
      const x2 = Math.min(this.x, box.x);
      const y2 = Math.min(this.y, box.y);
      const width2 = Math.max(this.x + this.width, box.x + box.width) - x2;
      const height2 = Math.max(this.y + this.height, box.y + box.height) - y2;
      return new Box(x2, y2, width2, height2);
    }
    toArray() {
      return [this.x, this.y, this.width, this.height];
    }
    toString() {
      return this.x + " " + this.y + " " + this.width + " " + this.height;
    }
    transform(m) {
      if (!(m instanceof Matrix)) {
        m = new Matrix(m);
      }
      let xMin = Infinity;
      let xMax = -Infinity;
      let yMin = Infinity;
      let yMax = -Infinity;
      const pts = [new Point(this.x, this.y), new Point(this.x2, this.y), new Point(this.x, this.y2), new Point(this.x2, this.y2)];
      pts.forEach(function(p) {
        p = p.transform(m);
        xMin = Math.min(xMin, p.x);
        xMax = Math.max(xMax, p.x);
        yMin = Math.min(yMin, p.y);
        yMax = Math.max(yMax, p.y);
      });
      return new Box(xMin, yMin, xMax - xMin, yMax - yMin);
    }
  }
  function getBox(el, getBBoxFn, retry) {
    let box;
    try {
      box = getBBoxFn(el.node);
      if (isNulledBox(box) && !domContains(el.node)) {
        throw new Error("Element not in the dom");
      }
    } catch (e) {
      box = retry(el);
    }
    return box;
  }
  function bbox() {
    const getBBox = (node) => node.getBBox();
    const retry = (el) => {
      try {
        const clone = el.clone().addTo(parser().svg).show();
        const box2 = clone.node.getBBox();
        clone.remove();
        return box2;
      } catch (e) {
        throw new Error(`Getting bbox of element "${el.node.nodeName}" is not possible: ${e.toString()}`);
      }
    };
    const box = getBox(this, getBBox, retry);
    const bbox2 = new Box(box);
    return bbox2;
  }
  function rbox(el) {
    const getRBox = (node) => node.getBoundingClientRect();
    const retry = (el2) => {
      throw new Error(`Getting rbox of element "${el2.node.nodeName}" is not possible`);
    };
    const box = getBox(this, getRBox, retry);
    const rbox2 = new Box(box);
    if (el) {
      return rbox2.transform(el.screenCTM().inverseO());
    }
    return rbox2.addOffset();
  }
  function inside(x2, y2) {
    const box = this.bbox();
    return x2 > box.x && y2 > box.y && x2 < box.x + box.width && y2 < box.y + box.height;
  }
  registerMethods({
    viewbox: {
      viewbox(x2, y2, width2, height2) {
        if (x2 == null)
          return new Box(this.attr("viewBox"));
        return this.attr("viewBox", new Box(x2, y2, width2, height2));
      },
      zoom(level, point2) {
        let {
          width: width2,
          height: height2
        } = this.attr(["width", "height"]);
        if (!width2 && !height2 || typeof width2 === "string" || typeof height2 === "string") {
          width2 = this.node.clientWidth;
          height2 = this.node.clientHeight;
        }
        if (!width2 || !height2) {
          throw new Error("Impossible to get absolute width and height. Please provide an absolute width and height attribute on the zooming element");
        }
        const v = this.viewbox();
        const zoomX = width2 / v.width;
        const zoomY = height2 / v.height;
        const zoom = Math.min(zoomX, zoomY);
        if (level == null) {
          return zoom;
        }
        let zoomAmount = zoom / level;
        if (zoomAmount === Infinity)
          zoomAmount = Number.MAX_SAFE_INTEGER / 100;
        point2 = point2 || new Point(width2 / 2 / zoomX + v.x, height2 / 2 / zoomY + v.y);
        const box = new Box(v).transform(new Matrix({
          scale: zoomAmount,
          origin: point2
        }));
        return this.viewbox(box);
      }
    }
  });
  register(Box, "Box");
  class List extends Array {
    constructor(arr = [], ...args) {
      super(arr, ...args);
      if (typeof arr === "number")
        return this;
      this.length = 0;
      this.push(...arr);
    }
  }
  extend([List], {
    each(fnOrMethodName, ...args) {
      if (typeof fnOrMethodName === "function") {
        return this.map((el, i, arr) => {
          return fnOrMethodName.call(el, el, i, arr);
        });
      } else {
        return this.map((el) => {
          return el[fnOrMethodName](...args);
        });
      }
    },
    toArray() {
      return Array.prototype.concat.apply([], this);
    }
  });
  const reserved = ["toArray", "constructor", "each"];
  List.extend = function(methods2) {
    methods2 = methods2.reduce((obj, name) => {
      if (reserved.includes(name))
        return obj;
      if (name[0] === "_")
        return obj;
      obj[name] = function(...attrs2) {
        return this.each(name, ...attrs2);
      };
      return obj;
    }, {});
    extend([List], methods2);
  };
  function baseFind(query, parent) {
    return new List(map((parent || globals.document).querySelectorAll(query), function(node) {
      return adopt(node);
    }));
  }
  function find(query) {
    return baseFind(query, this.node);
  }
  function findOne(query) {
    return adopt(this.node.querySelector(query));
  }
  let listenerId = 0;
  const windowEvents = {};
  function getEvents(instance) {
    let n = instance.getEventHolder();
    if (n === globals.window)
      n = windowEvents;
    if (!n.events)
      n.events = {};
    return n.events;
  }
  function getEventTarget(instance) {
    return instance.getEventTarget();
  }
  function clearEvents(instance) {
    let n = instance.getEventHolder();
    if (n === globals.window)
      n = windowEvents;
    if (n.events)
      n.events = {};
  }
  function on(node, events, listener, binding, options) {
    const l = listener.bind(binding || node);
    const instance = makeInstance(node);
    const bag = getEvents(instance);
    const n = getEventTarget(instance);
    events = Array.isArray(events) ? events : events.split(delimiter);
    if (!listener._svgjsListenerId) {
      listener._svgjsListenerId = ++listenerId;
    }
    events.forEach(function(event) {
      const ev = event.split(".")[0];
      const ns = event.split(".")[1] || "*";
      bag[ev] = bag[ev] || {};
      bag[ev][ns] = bag[ev][ns] || {};
      bag[ev][ns][listener._svgjsListenerId] = l;
      n.addEventListener(ev, l, options || false);
    });
  }
  function off(node, events, listener, options) {
    const instance = makeInstance(node);
    const bag = getEvents(instance);
    const n = getEventTarget(instance);
    if (typeof listener === "function") {
      listener = listener._svgjsListenerId;
      if (!listener)
        return;
    }
    events = Array.isArray(events) ? events : (events || "").split(delimiter);
    events.forEach(function(event) {
      const ev = event && event.split(".")[0];
      const ns = event && event.split(".")[1];
      let namespace, l;
      if (listener) {
        if (bag[ev] && bag[ev][ns || "*"]) {
          n.removeEventListener(ev, bag[ev][ns || "*"][listener], options || false);
          delete bag[ev][ns || "*"][listener];
        }
      } else if (ev && ns) {
        if (bag[ev] && bag[ev][ns]) {
          for (l in bag[ev][ns]) {
            off(n, [ev, ns].join("."), l);
          }
          delete bag[ev][ns];
        }
      } else if (ns) {
        for (event in bag) {
          for (namespace in bag[event]) {
            if (ns === namespace) {
              off(n, [event, ns].join("."));
            }
          }
        }
      } else if (ev) {
        if (bag[ev]) {
          for (namespace in bag[ev]) {
            off(n, [ev, namespace].join("."));
          }
          delete bag[ev];
        }
      } else {
        for (event in bag) {
          off(n, event);
        }
        clearEvents(instance);
      }
    });
  }
  function dispatch(node, event, data2, options) {
    const n = getEventTarget(node);
    if (event instanceof globals.window.Event) {
      n.dispatchEvent(event);
    } else {
      event = new globals.window.CustomEvent(event, {
        detail: data2,
        cancelable: true,
        ...options
      });
      n.dispatchEvent(event);
    }
    return event;
  }
  class EventTarget extends Base {
    addEventListener() {
    }
    dispatch(event, data2, options) {
      return dispatch(this, event, data2, options);
    }
    dispatchEvent(event) {
      const bag = this.getEventHolder().events;
      if (!bag)
        return true;
      const events = bag[event.type];
      for (const i in events) {
        for (const j in events[i]) {
          events[i][j](event);
        }
      }
      return !event.defaultPrevented;
    }
    // Fire given event
    fire(event, data2, options) {
      this.dispatch(event, data2, options);
      return this;
    }
    getEventHolder() {
      return this;
    }
    getEventTarget() {
      return this;
    }
    // Unbind event from listener
    off(event, listener, options) {
      off(this, event, listener, options);
      return this;
    }
    // Bind given event to listener
    on(event, listener, binding, options) {
      on(this, event, listener, binding, options);
      return this;
    }
    removeEventListener() {
    }
  }
  register(EventTarget, "EventTarget");
  function noop() {
  }
  const timeline = {
    duration: 400,
    ease: ">",
    delay: 0
  };
  const attrs = {
    // fill and stroke
    "fill-opacity": 1,
    "stroke-opacity": 1,
    "stroke-width": 0,
    "stroke-linejoin": "miter",
    "stroke-linecap": "butt",
    fill: "#000000",
    stroke: "#000000",
    opacity: 1,
    // position
    x: 0,
    y: 0,
    cx: 0,
    cy: 0,
    // size
    width: 0,
    height: 0,
    // radius
    r: 0,
    rx: 0,
    ry: 0,
    // gradient
    offset: 0,
    "stop-opacity": 1,
    "stop-color": "#000000",
    // text
    "text-anchor": "start"
  };
  class SVGArray extends Array {
    constructor(...args) {
      super(...args);
      this.init(...args);
    }
    clone() {
      return new this.constructor(this);
    }
    init(arr) {
      if (typeof arr === "number")
        return this;
      this.length = 0;
      this.push(...this.parse(arr));
      return this;
    }
    // Parse whitespace separated string
    parse(array2 = []) {
      if (array2 instanceof Array)
        return array2;
      return array2.trim().split(delimiter).map(parseFloat);
    }
    toArray() {
      return Array.prototype.concat.apply([], this);
    }
    toSet() {
      return new Set(this);
    }
    toString() {
      return this.join(" ");
    }
    // Flattens the array if needed
    valueOf() {
      const ret = [];
      ret.push(...this);
      return ret;
    }
  }
  class SVGNumber {
    // Initialize
    constructor(...args) {
      this.init(...args);
    }
    convert(unit) {
      return new SVGNumber(this.value, unit);
    }
    // Divide number
    divide(number2) {
      number2 = new SVGNumber(number2);
      return new SVGNumber(this / number2, this.unit || number2.unit);
    }
    init(value, unit) {
      unit = Array.isArray(value) ? value[1] : unit;
      value = Array.isArray(value) ? value[0] : value;
      this.value = 0;
      this.unit = unit || "";
      if (typeof value === "number") {
        this.value = isNaN(value) ? 0 : !isFinite(value) ? value < 0 ? -34e37 : 34e37 : value;
      } else if (typeof value === "string") {
        unit = value.match(numberAndUnit);
        if (unit) {
          this.value = parseFloat(unit[1]);
          if (unit[5] === "%") {
            this.value /= 100;
          } else if (unit[5] === "s") {
            this.value *= 1e3;
          }
          this.unit = unit[5];
        }
      } else {
        if (value instanceof SVGNumber) {
          this.value = value.valueOf();
          this.unit = value.unit;
        }
      }
      return this;
    }
    // Subtract number
    minus(number2) {
      number2 = new SVGNumber(number2);
      return new SVGNumber(this - number2, this.unit || number2.unit);
    }
    // Add number
    plus(number2) {
      number2 = new SVGNumber(number2);
      return new SVGNumber(this + number2, this.unit || number2.unit);
    }
    // Multiply number
    times(number2) {
      number2 = new SVGNumber(number2);
      return new SVGNumber(this * number2, this.unit || number2.unit);
    }
    toArray() {
      return [this.value, this.unit];
    }
    toJSON() {
      return this.toString();
    }
    toString() {
      return (this.unit === "%" ? ~~(this.value * 1e8) / 1e6 : this.unit === "s" ? this.value / 1e3 : this.value) + this.unit;
    }
    valueOf() {
      return this.value;
    }
  }
  const hooks = [];
  function registerAttrHook(fn) {
    hooks.push(fn);
  }
  function attr(attr2, val, ns) {
    if (attr2 == null) {
      attr2 = {};
      val = this.node.attributes;
      for (const node of val) {
        attr2[node.nodeName] = isNumber.test(node.nodeValue) ? parseFloat(node.nodeValue) : node.nodeValue;
      }
      return attr2;
    } else if (attr2 instanceof Array) {
      return attr2.reduce((last, curr) => {
        last[curr] = this.attr(curr);
        return last;
      }, {});
    } else if (typeof attr2 === "object" && attr2.constructor === Object) {
      for (val in attr2)
        this.attr(val, attr2[val]);
    } else if (val === null) {
      this.node.removeAttribute(attr2);
    } else if (val == null) {
      val = this.node.getAttribute(attr2);
      return val == null ? attrs[attr2] : isNumber.test(val) ? parseFloat(val) : val;
    } else {
      val = hooks.reduce((_val, hook) => {
        return hook(attr2, _val, this);
      }, val);
      if (typeof val === "number") {
        val = new SVGNumber(val);
      } else if (Color.isColor(val)) {
        val = new Color(val);
      } else if (val.constructor === Array) {
        val = new SVGArray(val);
      }
      if (attr2 === "leading") {
        if (this.leading) {
          this.leading(val);
        }
      } else {
        typeof ns === "string" ? this.node.setAttributeNS(ns, attr2, val.toString()) : this.node.setAttribute(attr2, val.toString());
      }
      if (this.rebuild && (attr2 === "font-size" || attr2 === "x")) {
        this.rebuild();
      }
    }
    return this;
  }
  class Dom extends EventTarget {
    constructor(node, attrs2) {
      super();
      this.node = node;
      this.type = node.nodeName;
      if (attrs2 && node !== attrs2) {
        this.attr(attrs2);
      }
    }
    // Add given element at a position
    add(element2, i) {
      element2 = makeInstance(element2);
      if (element2.removeNamespace && this.node instanceof globals.window.SVGElement) {
        element2.removeNamespace();
      }
      if (i == null) {
        this.node.appendChild(element2.node);
      } else if (element2.node !== this.node.childNodes[i]) {
        this.node.insertBefore(element2.node, this.node.childNodes[i]);
      }
      return this;
    }
    // Add element to given container and return self
    addTo(parent, i) {
      return makeInstance(parent).put(this, i);
    }
    // Returns all child elements
    children() {
      return new List(map(this.node.children, function(node) {
        return adopt(node);
      }));
    }
    // Remove all elements in this container
    clear() {
      while (this.node.hasChildNodes()) {
        this.node.removeChild(this.node.lastChild);
      }
      return this;
    }
    // Clone element
    clone(deep = true, assignNewIds = true) {
      this.writeDataToDom();
      let nodeClone = this.node.cloneNode(deep);
      if (assignNewIds) {
        nodeClone = assignNewId(nodeClone);
      }
      return new this.constructor(nodeClone);
    }
    // Iterates over all children and invokes a given block
    each(block, deep) {
      const children = this.children();
      let i, il;
      for (i = 0, il = children.length; i < il; i++) {
        block.apply(children[i], [i, children]);
        if (deep) {
          children[i].each(block, deep);
        }
      }
      return this;
    }
    element(nodeName, attrs2) {
      return this.put(new Dom(create(nodeName), attrs2));
    }
    // Get first child
    first() {
      return adopt(this.node.firstChild);
    }
    // Get a element at the given index
    get(i) {
      return adopt(this.node.childNodes[i]);
    }
    getEventHolder() {
      return this.node;
    }
    getEventTarget() {
      return this.node;
    }
    // Checks if the given element is a child
    has(element2) {
      return this.index(element2) >= 0;
    }
    html(htmlOrFn, outerHTML) {
      return this.xml(htmlOrFn, outerHTML, html);
    }
    // Get / set id
    id(id) {
      if (typeof id === "undefined" && !this.node.id) {
        this.node.id = eid(this.type);
      }
      return this.attr("id", id);
    }
    // Gets index of given element
    index(element2) {
      return [].slice.call(this.node.childNodes).indexOf(element2.node);
    }
    // Get the last child
    last() {
      return adopt(this.node.lastChild);
    }
    // matches the element vs a css selector
    matches(selector) {
      const el = this.node;
      const matcher = el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector || null;
      return matcher && matcher.call(el, selector);
    }
    // Returns the parent element instance
    parent(type) {
      let parent = this;
      if (!parent.node.parentNode)
        return null;
      parent = adopt(parent.node.parentNode);
      if (!type)
        return parent;
      do {
        if (typeof type === "string" ? parent.matches(type) : parent instanceof type)
          return parent;
      } while (parent = adopt(parent.node.parentNode));
      return parent;
    }
    // Basically does the same as `add()` but returns the added element instead
    put(element2, i) {
      element2 = makeInstance(element2);
      this.add(element2, i);
      return element2;
    }
    // Add element to given container and return container
    putIn(parent, i) {
      return makeInstance(parent).add(this, i);
    }
    // Remove element
    remove() {
      if (this.parent()) {
        this.parent().removeElement(this);
      }
      return this;
    }
    // Remove a given child
    removeElement(element2) {
      this.node.removeChild(element2.node);
      return this;
    }
    // Replace this with element
    replace(element2) {
      element2 = makeInstance(element2);
      if (this.node.parentNode) {
        this.node.parentNode.replaceChild(element2.node, this.node);
      }
      return element2;
    }
    round(precision = 2, map2 = null) {
      const factor = 10 ** precision;
      const attrs2 = this.attr(map2);
      for (const i in attrs2) {
        if (typeof attrs2[i] === "number") {
          attrs2[i] = Math.round(attrs2[i] * factor) / factor;
        }
      }
      this.attr(attrs2);
      return this;
    }
    // Import / Export raw svg
    svg(svgOrFn, outerSVG) {
      return this.xml(svgOrFn, outerSVG, svg);
    }
    // Return id on string conversion
    toString() {
      return this.id();
    }
    words(text) {
      this.node.textContent = text;
      return this;
    }
    wrap(node) {
      const parent = this.parent();
      if (!parent) {
        return this.addTo(node);
      }
      const position2 = parent.index(this);
      return parent.put(node, position2).put(this);
    }
    // write svgjs data to the dom
    writeDataToDom() {
      this.each(function() {
        this.writeDataToDom();
      });
      return this;
    }
    // Import / Export raw svg
    xml(xmlOrFn, outerXML, ns) {
      if (typeof xmlOrFn === "boolean") {
        ns = outerXML;
        outerXML = xmlOrFn;
        xmlOrFn = null;
      }
      if (xmlOrFn == null || typeof xmlOrFn === "function") {
        outerXML = outerXML == null ? true : outerXML;
        this.writeDataToDom();
        let current = this;
        if (xmlOrFn != null) {
          current = adopt(current.node.cloneNode(true));
          if (outerXML) {
            const result = xmlOrFn(current);
            current = result || current;
            if (result === false)
              return "";
          }
          current.each(function() {
            const result = xmlOrFn(this);
            const _this = result || this;
            if (result === false) {
              this.remove();
            } else if (result && this !== _this) {
              this.replace(_this);
            }
          }, true);
        }
        return outerXML ? current.node.outerHTML : current.node.innerHTML;
      }
      outerXML = outerXML == null ? false : outerXML;
      const well = create("wrapper", ns);
      const fragment = globals.document.createDocumentFragment();
      well.innerHTML = xmlOrFn;
      for (let len = well.children.length; len--; ) {
        fragment.appendChild(well.firstElementChild);
      }
      const parent = this.parent();
      return outerXML ? this.replace(fragment) && parent : this.add(fragment);
    }
  }
  extend(Dom, {
    attr,
    find,
    findOne
  });
  register(Dom, "Dom");
  class Element extends Dom {
    constructor(node, attrs2) {
      super(node, attrs2);
      this.dom = {};
      this.node.instance = this;
      if (node.hasAttribute("svgjs:data")) {
        this.setData(JSON.parse(node.getAttribute("svgjs:data")) || {});
      }
    }
    // Move element by its center
    center(x2, y2) {
      return this.cx(x2).cy(y2);
    }
    // Move by center over x-axis
    cx(x2) {
      return x2 == null ? this.x() + this.width() / 2 : this.x(x2 - this.width() / 2);
    }
    // Move by center over y-axis
    cy(y2) {
      return y2 == null ? this.y() + this.height() / 2 : this.y(y2 - this.height() / 2);
    }
    // Get defs
    defs() {
      const root2 = this.root();
      return root2 && root2.defs();
    }
    // Relative move over x and y axes
    dmove(x2, y2) {
      return this.dx(x2).dy(y2);
    }
    // Relative move over x axis
    dx(x2 = 0) {
      return this.x(new SVGNumber(x2).plus(this.x()));
    }
    // Relative move over y axis
    dy(y2 = 0) {
      return this.y(new SVGNumber(y2).plus(this.y()));
    }
    getEventHolder() {
      return this;
    }
    // Set height of element
    height(height2) {
      return this.attr("height", height2);
    }
    // Move element to given x and y values
    move(x2, y2) {
      return this.x(x2).y(y2);
    }
    // return array of all ancestors of given type up to the root svg
    parents(until = this.root()) {
      const isSelector = typeof until === "string";
      if (!isSelector) {
        until = makeInstance(until);
      }
      const parents = new List();
      let parent = this;
      while ((parent = parent.parent()) && parent.node !== globals.document && parent.nodeName !== "#document-fragment") {
        parents.push(parent);
        if (!isSelector && parent.node === until.node) {
          break;
        }
        if (isSelector && parent.matches(until)) {
          break;
        }
        if (parent.node === this.root().node) {
          return null;
        }
      }
      return parents;
    }
    // Get referenced element form attribute value
    reference(attr2) {
      attr2 = this.attr(attr2);
      if (!attr2)
        return null;
      const m = (attr2 + "").match(reference);
      return m ? makeInstance(m[1]) : null;
    }
    // Get parent document
    root() {
      const p = this.parent(getClass(root));
      return p && p.root();
    }
    // set given data to the elements data property
    setData(o) {
      this.dom = o;
      return this;
    }
    // Set element size to given width and height
    size(width2, height2) {
      const p = proportionalSize(this, width2, height2);
      return this.width(new SVGNumber(p.width)).height(new SVGNumber(p.height));
    }
    // Set width of element
    width(width2) {
      return this.attr("width", width2);
    }
    // write svgjs data to the dom
    writeDataToDom() {
      this.node.removeAttribute("svgjs:data");
      if (Object.keys(this.dom).length) {
        this.node.setAttribute("svgjs:data", JSON.stringify(this.dom));
      }
      return super.writeDataToDom();
    }
    // Move over x-axis
    x(x2) {
      return this.attr("x", x2);
    }
    // Move over y-axis
    y(y2) {
      return this.attr("y", y2);
    }
  }
  extend(Element, {
    bbox,
    rbox,
    inside,
    point,
    ctm,
    screenCTM
  });
  register(Element, "Element");
  const sugar = {
    stroke: ["color", "width", "opacity", "linecap", "linejoin", "miterlimit", "dasharray", "dashoffset"],
    fill: ["color", "opacity", "rule"],
    prefix: function(t, a) {
      return a === "color" ? t : t + "-" + a;
    }
  };
  ["fill", "stroke"].forEach(function(m) {
    const extension = {};
    let i;
    extension[m] = function(o) {
      if (typeof o === "undefined") {
        return this.attr(m);
      }
      if (typeof o === "string" || o instanceof Color || Color.isRgb(o) || o instanceof Element) {
        this.attr(m, o);
      } else {
        for (i = sugar[m].length - 1; i >= 0; i--) {
          if (o[sugar[m][i]] != null) {
            this.attr(sugar.prefix(m, sugar[m][i]), o[sugar[m][i]]);
          }
        }
      }
      return this;
    };
    registerMethods(["Element", "Runner"], extension);
  });
  registerMethods(["Element", "Runner"], {
    // Let the user set the matrix directly
    matrix: function(mat, b, c, d, e, f) {
      if (mat == null) {
        return new Matrix(this);
      }
      return this.attr("transform", new Matrix(mat, b, c, d, e, f));
    },
    // Map rotation to transform
    rotate: function(angle, cx2, cy2) {
      return this.transform({
        rotate: angle,
        ox: cx2,
        oy: cy2
      }, true);
    },
    // Map skew to transform
    skew: function(x2, y2, cx2, cy2) {
      return arguments.length === 1 || arguments.length === 3 ? this.transform({
        skew: x2,
        ox: y2,
        oy: cx2
      }, true) : this.transform({
        skew: [x2, y2],
        ox: cx2,
        oy: cy2
      }, true);
    },
    shear: function(lam, cx2, cy2) {
      return this.transform({
        shear: lam,
        ox: cx2,
        oy: cy2
      }, true);
    },
    // Map scale to transform
    scale: function(x2, y2, cx2, cy2) {
      return arguments.length === 1 || arguments.length === 3 ? this.transform({
        scale: x2,
        ox: y2,
        oy: cx2
      }, true) : this.transform({
        scale: [x2, y2],
        ox: cx2,
        oy: cy2
      }, true);
    },
    // Map translate to transform
    translate: function(x2, y2) {
      return this.transform({
        translate: [x2, y2]
      }, true);
    },
    // Map relative translations to transform
    relative: function(x2, y2) {
      return this.transform({
        relative: [x2, y2]
      }, true);
    },
    // Map flip to transform
    flip: function(direction = "both", origin = "center") {
      if ("xybothtrue".indexOf(direction) === -1) {
        origin = direction;
        direction = "both";
      }
      return this.transform({
        flip: direction,
        origin
      }, true);
    },
    // Opacity
    opacity: function(value) {
      return this.attr("opacity", value);
    }
  });
  registerMethods("radius", {
    // Add x and y radius
    radius: function(x2, y2 = x2) {
      const type = (this._element || this).type;
      return type === "radialGradient" ? this.attr("r", new SVGNumber(x2)) : this.rx(x2).ry(y2);
    }
  });
  registerMethods("Path", {
    // Get path length
    length: function() {
      return this.node.getTotalLength();
    },
    // Get point at length
    pointAt: function(length2) {
      return new Point(this.node.getPointAtLength(length2));
    }
  });
  registerMethods(["Element", "Runner"], {
    // Set font
    font: function(a, v) {
      if (typeof a === "object") {
        for (v in a)
          this.font(v, a[v]);
        return this;
      }
      return a === "leading" ? this.leading(v) : a === "anchor" ? this.attr("text-anchor", v) : a === "size" || a === "family" || a === "weight" || a === "stretch" || a === "variant" || a === "style" ? this.attr("font-" + a, v) : this.attr(a, v);
    }
  });
  const methods = ["click", "dblclick", "mousedown", "mouseup", "mouseover", "mouseout", "mousemove", "mouseenter", "mouseleave", "touchstart", "touchmove", "touchleave", "touchend", "touchcancel"].reduce(function(last, event) {
    const fn = function(f) {
      if (f === null) {
        this.off(event);
      } else {
        this.on(event, f);
      }
      return this;
    };
    last[event] = fn;
    return last;
  }, {});
  registerMethods("Element", methods);
  function untransform() {
    return this.attr("transform", null);
  }
  function matrixify() {
    const matrix = (this.attr("transform") || "").split(transforms).slice(0, -1).map(function(str) {
      const kv = str.trim().split("(");
      return [kv[0], kv[1].split(delimiter).map(function(str2) {
        return parseFloat(str2);
      })];
    }).reverse().reduce(function(matrix2, transform2) {
      if (transform2[0] === "matrix") {
        return matrix2.lmultiply(Matrix.fromArray(transform2[1]));
      }
      return matrix2[transform2[0]].apply(matrix2, transform2[1]);
    }, new Matrix());
    return matrix;
  }
  function toParent(parent, i) {
    if (this === parent)
      return this;
    const ctm2 = this.screenCTM();
    const pCtm = parent.screenCTM().inverse();
    this.addTo(parent, i).untransform().transform(pCtm.multiply(ctm2));
    return this;
  }
  function toRoot(i) {
    return this.toParent(this.root(), i);
  }
  function transform(o, relative) {
    if (o == null || typeof o === "string") {
      const decomposed = new Matrix(this).decompose();
      return o == null ? decomposed : decomposed[o];
    }
    if (!Matrix.isMatrixLike(o)) {
      o = {
        ...o,
        origin: getOrigin(o, this)
      };
    }
    const cleanRelative = relative === true ? this : relative || false;
    const result = new Matrix(cleanRelative).transform(o);
    return this.attr("transform", result);
  }
  registerMethods("Element", {
    untransform,
    matrixify,
    toParent,
    toRoot,
    transform
  });
  class Container extends Element {
    flatten(parent = this, index) {
      this.each(function() {
        if (this instanceof Container) {
          return this.flatten().ungroup();
        }
      });
      return this;
    }
    ungroup(parent = this.parent(), index = parent.index(this)) {
      index = index === -1 ? parent.children().length : index;
      this.each(function(i, children) {
        return children[children.length - i - 1].toParent(parent, index);
      });
      return this.remove();
    }
  }
  register(Container, "Container");
  class Defs extends Container {
    constructor(node, attrs2 = node) {
      super(nodeOrNew("defs", node), attrs2);
    }
    flatten() {
      return this;
    }
    ungroup() {
      return this;
    }
  }
  register(Defs, "Defs");
  class Shape extends Element {
  }
  register(Shape, "Shape");
  function rx(rx2) {
    return this.attr("rx", rx2);
  }
  function ry(ry2) {
    return this.attr("ry", ry2);
  }
  function x$3(x2) {
    return x2 == null ? this.cx() - this.rx() : this.cx(x2 + this.rx());
  }
  function y$3(y2) {
    return y2 == null ? this.cy() - this.ry() : this.cy(y2 + this.ry());
  }
  function cx$1(x2) {
    return this.attr("cx", x2);
  }
  function cy$1(y2) {
    return this.attr("cy", y2);
  }
  function width$2(width2) {
    return width2 == null ? this.rx() * 2 : this.rx(new SVGNumber(width2).divide(2));
  }
  function height$2(height2) {
    return height2 == null ? this.ry() * 2 : this.ry(new SVGNumber(height2).divide(2));
  }
  var circled = {
    __proto__: null,
    rx,
    ry,
    x: x$3,
    y: y$3,
    cx: cx$1,
    cy: cy$1,
    width: width$2,
    height: height$2
  };
  class Ellipse extends Shape {
    constructor(node, attrs2 = node) {
      super(nodeOrNew("ellipse", node), attrs2);
    }
    size(width2, height2) {
      const p = proportionalSize(this, width2, height2);
      return this.rx(new SVGNumber(p.width).divide(2)).ry(new SVGNumber(p.height).divide(2));
    }
  }
  extend(Ellipse, circled);
  registerMethods("Container", {
    // Create an ellipse
    ellipse: wrapWithAttrCheck(function(width2 = 0, height2 = width2) {
      return this.put(new Ellipse()).size(width2, height2).move(0, 0);
    })
  });
  register(Ellipse, "Ellipse");
  class Fragment extends Dom {
    constructor(node = globals.document.createDocumentFragment()) {
      super(node);
    }
    // Import / Export raw xml
    xml(xmlOrFn, outerXML, ns) {
      if (typeof xmlOrFn === "boolean") {
        ns = outerXML;
        outerXML = xmlOrFn;
        xmlOrFn = null;
      }
      if (xmlOrFn == null || typeof xmlOrFn === "function") {
        const wrapper = new Dom(create("wrapper", ns));
        wrapper.add(this.node.cloneNode(true));
        return wrapper.xml(false, ns);
      }
      return super.xml(xmlOrFn, false, ns);
    }
  }
  register(Fragment, "Fragment");
  function from(x2, y2) {
    return (this._element || this).type === "radialGradient" ? this.attr({
      fx: new SVGNumber(x2),
      fy: new SVGNumber(y2)
    }) : this.attr({
      x1: new SVGNumber(x2),
      y1: new SVGNumber(y2)
    });
  }
  function to(x2, y2) {
    return (this._element || this).type === "radialGradient" ? this.attr({
      cx: new SVGNumber(x2),
      cy: new SVGNumber(y2)
    }) : this.attr({
      x2: new SVGNumber(x2),
      y2: new SVGNumber(y2)
    });
  }
  var gradiented = {
    __proto__: null,
    from,
    to
  };
  class Gradient extends Container {
    constructor(type, attrs2) {
      super(nodeOrNew(type + "Gradient", typeof type === "string" ? null : type), attrs2);
    }
    // custom attr to handle transform
    attr(a, b, c) {
      if (a === "transform")
        a = "gradientTransform";
      return super.attr(a, b, c);
    }
    bbox() {
      return new Box();
    }
    targets() {
      return baseFind("svg [fill*=" + this.id() + "]");
    }
    // Alias string conversion to fill
    toString() {
      return this.url();
    }
    // Update gradient
    update(block) {
      this.clear();
      if (typeof block === "function") {
        block.call(this, this);
      }
      return this;
    }
    // Return the fill id
    url() {
      return "url(#" + this.id() + ")";
    }
  }
  extend(Gradient, gradiented);
  registerMethods({
    Container: {
      // Create gradient element in defs
      gradient(...args) {
        return this.defs().gradient(...args);
      }
    },
    // define gradient
    Defs: {
      gradient: wrapWithAttrCheck(function(type, block) {
        return this.put(new Gradient(type)).update(block);
      })
    }
  });
  register(Gradient, "Gradient");
  class Pattern extends Container {
    // Initialize node
    constructor(node, attrs2 = node) {
      super(nodeOrNew("pattern", node), attrs2);
    }
    // custom attr to handle transform
    attr(a, b, c) {
      if (a === "transform")
        a = "patternTransform";
      return super.attr(a, b, c);
    }
    bbox() {
      return new Box();
    }
    targets() {
      return baseFind("svg [fill*=" + this.id() + "]");
    }
    // Alias string conversion to fill
    toString() {
      return this.url();
    }
    // Update pattern by rebuilding
    update(block) {
      this.clear();
      if (typeof block === "function") {
        block.call(this, this);
      }
      return this;
    }
    // Return the fill id
    url() {
      return "url(#" + this.id() + ")";
    }
  }
  registerMethods({
    Container: {
      // Create pattern element in defs
      pattern(...args) {
        return this.defs().pattern(...args);
      }
    },
    Defs: {
      pattern: wrapWithAttrCheck(function(width2, height2, block) {
        return this.put(new Pattern()).update(block).attr({
          x: 0,
          y: 0,
          width: width2,
          height: height2,
          patternUnits: "userSpaceOnUse"
        });
      })
    }
  });
  register(Pattern, "Pattern");
  class Image extends Shape {
    constructor(node, attrs2 = node) {
      super(nodeOrNew("image", node), attrs2);
    }
    // (re)load image
    load(url, callback) {
      if (!url)
        return this;
      const img = new globals.window.Image();
      on(img, "load", function(e) {
        const p = this.parent(Pattern);
        if (this.width() === 0 && this.height() === 0) {
          this.size(img.width, img.height);
        }
        if (p instanceof Pattern) {
          if (p.width() === 0 && p.height() === 0) {
            p.size(this.width(), this.height());
          }
        }
        if (typeof callback === "function") {
          callback.call(this, e);
        }
      }, this);
      on(img, "load error", function() {
        off(img);
      });
      return this.attr("href", img.src = url, xlink);
    }
  }
  registerAttrHook(function(attr2, val, _this) {
    if (attr2 === "fill" || attr2 === "stroke") {
      if (isImage.test(val)) {
        val = _this.root().defs().image(val);
      }
    }
    if (val instanceof Image) {
      val = _this.root().defs().pattern(0, 0, (pattern) => {
        pattern.add(val);
      });
    }
    return val;
  });
  registerMethods({
    Container: {
      // create image element, load image and set its size
      image: wrapWithAttrCheck(function(source, callback) {
        return this.put(new Image()).size(0, 0).load(source, callback);
      })
    }
  });
  register(Image, "Image");
  class PointArray extends SVGArray {
    // Get bounding box of points
    bbox() {
      let maxX = -Infinity;
      let maxY = -Infinity;
      let minX = Infinity;
      let minY = Infinity;
      this.forEach(function(el) {
        maxX = Math.max(el[0], maxX);
        maxY = Math.max(el[1], maxY);
        minX = Math.min(el[0], minX);
        minY = Math.min(el[1], minY);
      });
      return new Box(minX, minY, maxX - minX, maxY - minY);
    }
    // Move point string
    move(x2, y2) {
      const box = this.bbox();
      x2 -= box.x;
      y2 -= box.y;
      if (!isNaN(x2) && !isNaN(y2)) {
        for (let i = this.length - 1; i >= 0; i--) {
          this[i] = [this[i][0] + x2, this[i][1] + y2];
        }
      }
      return this;
    }
    // Parse point string and flat array
    parse(array2 = [0, 0]) {
      const points = [];
      if (array2 instanceof Array) {
        array2 = Array.prototype.concat.apply([], array2);
      } else {
        array2 = array2.trim().split(delimiter).map(parseFloat);
      }
      if (array2.length % 2 !== 0)
        array2.pop();
      for (let i = 0, len = array2.length; i < len; i = i + 2) {
        points.push([array2[i], array2[i + 1]]);
      }
      return points;
    }
    // Resize poly string
    size(width2, height2) {
      let i;
      const box = this.bbox();
      for (i = this.length - 1; i >= 0; i--) {
        if (box.width)
          this[i][0] = (this[i][0] - box.x) * width2 / box.width + box.x;
        if (box.height)
          this[i][1] = (this[i][1] - box.y) * height2 / box.height + box.y;
      }
      return this;
    }
    // Convert array to line object
    toLine() {
      return {
        x1: this[0][0],
        y1: this[0][1],
        x2: this[1][0],
        y2: this[1][1]
      };
    }
    // Convert array to string
    toString() {
      const array2 = [];
      for (let i = 0, il = this.length; i < il; i++) {
        array2.push(this[i].join(","));
      }
      return array2.join(" ");
    }
    transform(m) {
      return this.clone().transformO(m);
    }
    // transform points with matrix (similar to Point.transform)
    transformO(m) {
      if (!Matrix.isMatrixLike(m)) {
        m = new Matrix(m);
      }
      for (let i = this.length; i--; ) {
        const [x2, y2] = this[i];
        this[i][0] = m.a * x2 + m.c * y2 + m.e;
        this[i][1] = m.b * x2 + m.d * y2 + m.f;
      }
      return this;
    }
  }
  const MorphArray = PointArray;
  function x$2(x2) {
    return x2 == null ? this.bbox().x : this.move(x2, this.bbox().y);
  }
  function y$2(y2) {
    return y2 == null ? this.bbox().y : this.move(this.bbox().x, y2);
  }
  function width$1(width2) {
    const b = this.bbox();
    return width2 == null ? b.width : this.size(width2, b.height);
  }
  function height$1(height2) {
    const b = this.bbox();
    return height2 == null ? b.height : this.size(b.width, height2);
  }
  var pointed = {
    __proto__: null,
    MorphArray,
    x: x$2,
    y: y$2,
    width: width$1,
    height: height$1
  };
  class Line extends Shape {
    // Initialize node
    constructor(node, attrs2 = node) {
      super(nodeOrNew("line", node), attrs2);
    }
    // Get array
    array() {
      return new PointArray([[this.attr("x1"), this.attr("y1")], [this.attr("x2"), this.attr("y2")]]);
    }
    // Move by left top corner
    move(x2, y2) {
      return this.attr(this.array().move(x2, y2).toLine());
    }
    // Overwrite native plot() method
    plot(x1, y1, x2, y2) {
      if (x1 == null) {
        return this.array();
      } else if (typeof y1 !== "undefined") {
        x1 = {
          x1,
          y1,
          x2,
          y2
        };
      } else {
        x1 = new PointArray(x1).toLine();
      }
      return this.attr(x1);
    }
    // Set element size to given width and height
    size(width2, height2) {
      const p = proportionalSize(this, width2, height2);
      return this.attr(this.array().size(p.width, p.height).toLine());
    }
  }
  extend(Line, pointed);
  registerMethods({
    Container: {
      // Create a line element
      line: wrapWithAttrCheck(function(...args) {
        return Line.prototype.plot.apply(this.put(new Line()), args[0] != null ? args : [0, 0, 0, 0]);
      })
    }
  });
  register(Line, "Line");
  class Marker extends Container {
    // Initialize node
    constructor(node, attrs2 = node) {
      super(nodeOrNew("marker", node), attrs2);
    }
    // Set height of element
    height(height2) {
      return this.attr("markerHeight", height2);
    }
    orient(orient) {
      return this.attr("orient", orient);
    }
    // Set marker refX and refY
    ref(x2, y2) {
      return this.attr("refX", x2).attr("refY", y2);
    }
    // Return the fill id
    toString() {
      return "url(#" + this.id() + ")";
    }
    // Update marker
    update(block) {
      this.clear();
      if (typeof block === "function") {
        block.call(this, this);
      }
      return this;
    }
    // Set width of element
    width(width2) {
      return this.attr("markerWidth", width2);
    }
  }
  registerMethods({
    Container: {
      marker(...args) {
        return this.defs().marker(...args);
      }
    },
    Defs: {
      // Create marker
      marker: wrapWithAttrCheck(function(width2, height2, block) {
        return this.put(new Marker()).size(width2, height2).ref(width2 / 2, height2 / 2).viewbox(0, 0, width2, height2).attr("orient", "auto").update(block);
      })
    },
    marker: {
      // Create and attach markers
      marker(marker, width2, height2, block) {
        let attr2 = ["marker"];
        if (marker !== "all")
          attr2.push(marker);
        attr2 = attr2.join("-");
        marker = arguments[1] instanceof Marker ? arguments[1] : this.defs().marker(width2, height2, block);
        return this.attr(attr2, marker);
      }
    }
  });
  register(Marker, "Marker");
  function makeSetterGetter(k, f) {
    return function(v) {
      if (v == null)
        return this[k];
      this[k] = v;
      if (f)
        f.call(this);
      return this;
    };
  }
  const easing = {
    "-": function(pos) {
      return pos;
    },
    "<>": function(pos) {
      return -Math.cos(pos * Math.PI) / 2 + 0.5;
    },
    ">": function(pos) {
      return Math.sin(pos * Math.PI / 2);
    },
    "<": function(pos) {
      return -Math.cos(pos * Math.PI / 2) + 1;
    },
    bezier: function(x1, y1, x2, y2) {
      return function(t) {
        if (t < 0) {
          if (x1 > 0) {
            return y1 / x1 * t;
          } else if (x2 > 0) {
            return y2 / x2 * t;
          } else {
            return 0;
          }
        } else if (t > 1) {
          if (x2 < 1) {
            return (1 - y2) / (1 - x2) * t + (y2 - x2) / (1 - x2);
          } else if (x1 < 1) {
            return (1 - y1) / (1 - x1) * t + (y1 - x1) / (1 - x1);
          } else {
            return 1;
          }
        } else {
          return 3 * t * (1 - t) ** 2 * y1 + 3 * t ** 2 * (1 - t) * y2 + t ** 3;
        }
      };
    },
    // see https://www.w3.org/TR/css-easing-1/#step-timing-function-algo
    steps: function(steps, stepPosition = "end") {
      stepPosition = stepPosition.split("-").reverse()[0];
      let jumps = steps;
      if (stepPosition === "none") {
        --jumps;
      } else if (stepPosition === "both") {
        ++jumps;
      }
      return (t, beforeFlag = false) => {
        let step = Math.floor(t * steps);
        const jumping = t * step % 1 === 0;
        if (stepPosition === "start" || stepPosition === "both") {
          ++step;
        }
        if (beforeFlag && jumping) {
          --step;
        }
        if (t >= 0 && step < 0) {
          step = 0;
        }
        if (t <= 1 && step > jumps) {
          step = jumps;
        }
        return step / jumps;
      };
    }
  };
  class Stepper {
    done() {
      return false;
    }
  }
  class Ease extends Stepper {
    constructor(fn = timeline.ease) {
      super();
      this.ease = easing[fn] || fn;
    }
    step(from2, to2, pos) {
      if (typeof from2 !== "number") {
        return pos < 1 ? from2 : to2;
      }
      return from2 + (to2 - from2) * this.ease(pos);
    }
  }
  class Controller extends Stepper {
    constructor(fn) {
      super();
      this.stepper = fn;
    }
    done(c) {
      return c.done;
    }
    step(current, target, dt, c) {
      return this.stepper(current, target, dt, c);
    }
  }
  function recalculate() {
    const duration = (this._duration || 500) / 1e3;
    const overshoot = this._overshoot || 0;
    const eps = 1e-10;
    const pi = Math.PI;
    const os = Math.log(overshoot / 100 + eps);
    const zeta = -os / Math.sqrt(pi * pi + os * os);
    const wn = 3.9 / (zeta * duration);
    this.d = 2 * zeta * wn;
    this.k = wn * wn;
  }
  class Spring extends Controller {
    constructor(duration = 500, overshoot = 0) {
      super();
      this.duration(duration).overshoot(overshoot);
    }
    step(current, target, dt, c) {
      if (typeof current === "string")
        return current;
      c.done = dt === Infinity;
      if (dt === Infinity)
        return target;
      if (dt === 0)
        return current;
      if (dt > 100)
        dt = 16;
      dt /= 1e3;
      const velocity = c.velocity || 0;
      const acceleration = -this.d * velocity - this.k * (current - target);
      const newPosition = current + velocity * dt + acceleration * dt * dt / 2;
      c.velocity = velocity + acceleration * dt;
      c.done = Math.abs(target - newPosition) + Math.abs(velocity) < 2e-3;
      return c.done ? target : newPosition;
    }
  }
  extend(Spring, {
    duration: makeSetterGetter("_duration", recalculate),
    overshoot: makeSetterGetter("_overshoot", recalculate)
  });
  class PID extends Controller {
    constructor(p = 0.1, i = 0.01, d = 0, windup = 1e3) {
      super();
      this.p(p).i(i).d(d).windup(windup);
    }
    step(current, target, dt, c) {
      if (typeof current === "string")
        return current;
      c.done = dt === Infinity;
      if (dt === Infinity)
        return target;
      if (dt === 0)
        return current;
      const p = target - current;
      let i = (c.integral || 0) + p * dt;
      const d = (p - (c.error || 0)) / dt;
      const windup = this._windup;
      if (windup !== false) {
        i = Math.max(-windup, Math.min(i, windup));
      }
      c.error = p;
      c.integral = i;
      c.done = Math.abs(p) < 1e-3;
      return c.done ? target : current + (this.P * p + this.I * i + this.D * d);
    }
  }
  extend(PID, {
    windup: makeSetterGetter("_windup"),
    p: makeSetterGetter("P"),
    i: makeSetterGetter("I"),
    d: makeSetterGetter("D")
  });
  const segmentParameters = {
    M: 2,
    L: 2,
    H: 1,
    V: 1,
    C: 6,
    S: 4,
    Q: 4,
    T: 2,
    A: 7,
    Z: 0
  };
  const pathHandlers = {
    M: function(c, p, p0) {
      p.x = p0.x = c[0];
      p.y = p0.y = c[1];
      return ["M", p.x, p.y];
    },
    L: function(c, p) {
      p.x = c[0];
      p.y = c[1];
      return ["L", c[0], c[1]];
    },
    H: function(c, p) {
      p.x = c[0];
      return ["H", c[0]];
    },
    V: function(c, p) {
      p.y = c[0];
      return ["V", c[0]];
    },
    C: function(c, p) {
      p.x = c[4];
      p.y = c[5];
      return ["C", c[0], c[1], c[2], c[3], c[4], c[5]];
    },
    S: function(c, p) {
      p.x = c[2];
      p.y = c[3];
      return ["S", c[0], c[1], c[2], c[3]];
    },
    Q: function(c, p) {
      p.x = c[2];
      p.y = c[3];
      return ["Q", c[0], c[1], c[2], c[3]];
    },
    T: function(c, p) {
      p.x = c[0];
      p.y = c[1];
      return ["T", c[0], c[1]];
    },
    Z: function(c, p, p0) {
      p.x = p0.x;
      p.y = p0.y;
      return ["Z"];
    },
    A: function(c, p) {
      p.x = c[5];
      p.y = c[6];
      return ["A", c[0], c[1], c[2], c[3], c[4], c[5], c[6]];
    }
  };
  const mlhvqtcsaz = "mlhvqtcsaz".split("");
  for (let i = 0, il = mlhvqtcsaz.length; i < il; ++i) {
    pathHandlers[mlhvqtcsaz[i]] = function(i2) {
      return function(c, p, p0) {
        if (i2 === "H")
          c[0] = c[0] + p.x;
        else if (i2 === "V")
          c[0] = c[0] + p.y;
        else if (i2 === "A") {
          c[5] = c[5] + p.x;
          c[6] = c[6] + p.y;
        } else {
          for (let j = 0, jl = c.length; j < jl; ++j) {
            c[j] = c[j] + (j % 2 ? p.y : p.x);
          }
        }
        return pathHandlers[i2](c, p, p0);
      };
    }(mlhvqtcsaz[i].toUpperCase());
  }
  function makeAbsolut(parser2) {
    const command = parser2.segment[0];
    return pathHandlers[command](parser2.segment.slice(1), parser2.p, parser2.p0);
  }
  function segmentComplete(parser2) {
    return parser2.segment.length && parser2.segment.length - 1 === segmentParameters[parser2.segment[0].toUpperCase()];
  }
  function startNewSegment(parser2, token) {
    parser2.inNumber && finalizeNumber(parser2, false);
    const pathLetter = isPathLetter.test(token);
    if (pathLetter) {
      parser2.segment = [token];
    } else {
      const lastCommand = parser2.lastCommand;
      const small = lastCommand.toLowerCase();
      const isSmall = lastCommand === small;
      parser2.segment = [small === "m" ? isSmall ? "l" : "L" : lastCommand];
    }
    parser2.inSegment = true;
    parser2.lastCommand = parser2.segment[0];
    return pathLetter;
  }
  function finalizeNumber(parser2, inNumber) {
    if (!parser2.inNumber)
      throw new Error("Parser Error");
    parser2.number && parser2.segment.push(parseFloat(parser2.number));
    parser2.inNumber = inNumber;
    parser2.number = "";
    parser2.pointSeen = false;
    parser2.hasExponent = false;
    if (segmentComplete(parser2)) {
      finalizeSegment(parser2);
    }
  }
  function finalizeSegment(parser2) {
    parser2.inSegment = false;
    if (parser2.absolute) {
      parser2.segment = makeAbsolut(parser2);
    }
    parser2.segments.push(parser2.segment);
  }
  function isArcFlag(parser2) {
    if (!parser2.segment.length)
      return false;
    const isArc = parser2.segment[0].toUpperCase() === "A";
    const length2 = parser2.segment.length;
    return isArc && (length2 === 4 || length2 === 5);
  }
  function isExponential(parser2) {
    return parser2.lastToken.toUpperCase() === "E";
  }
  function pathParser(d, toAbsolute = true) {
    let index = 0;
    let token = "";
    const parser2 = {
      segment: [],
      inNumber: false,
      number: "",
      lastToken: "",
      inSegment: false,
      segments: [],
      pointSeen: false,
      hasExponent: false,
      absolute: toAbsolute,
      p0: new Point(),
      p: new Point()
    };
    while (parser2.lastToken = token, token = d.charAt(index++)) {
      if (!parser2.inSegment) {
        if (startNewSegment(parser2, token)) {
          continue;
        }
      }
      if (token === ".") {
        if (parser2.pointSeen || parser2.hasExponent) {
          finalizeNumber(parser2, false);
          --index;
          continue;
        }
        parser2.inNumber = true;
        parser2.pointSeen = true;
        parser2.number += token;
        continue;
      }
      if (!isNaN(parseInt(token))) {
        if (parser2.number === "0" || isArcFlag(parser2)) {
          parser2.inNumber = true;
          parser2.number = token;
          finalizeNumber(parser2, true);
          continue;
        }
        parser2.inNumber = true;
        parser2.number += token;
        continue;
      }
      if (token === " " || token === ",") {
        if (parser2.inNumber) {
          finalizeNumber(parser2, false);
        }
        continue;
      }
      if (token === "-") {
        if (parser2.inNumber && !isExponential(parser2)) {
          finalizeNumber(parser2, false);
          --index;
          continue;
        }
        parser2.number += token;
        parser2.inNumber = true;
        continue;
      }
      if (token.toUpperCase() === "E") {
        parser2.number += token;
        parser2.hasExponent = true;
        continue;
      }
      if (isPathLetter.test(token)) {
        if (parser2.inNumber) {
          finalizeNumber(parser2, false);
        } else if (!segmentComplete(parser2)) {
          throw new Error("parser Error");
        } else {
          finalizeSegment(parser2);
        }
        --index;
      }
    }
    if (parser2.inNumber) {
      finalizeNumber(parser2, false);
    }
    if (parser2.inSegment && segmentComplete(parser2)) {
      finalizeSegment(parser2);
    }
    return parser2.segments;
  }
  function arrayToString(a) {
    let s = "";
    for (let i = 0, il = a.length; i < il; i++) {
      s += a[i][0];
      if (a[i][1] != null) {
        s += a[i][1];
        if (a[i][2] != null) {
          s += " ";
          s += a[i][2];
          if (a[i][3] != null) {
            s += " ";
            s += a[i][3];
            s += " ";
            s += a[i][4];
            if (a[i][5] != null) {
              s += " ";
              s += a[i][5];
              s += " ";
              s += a[i][6];
              if (a[i][7] != null) {
                s += " ";
                s += a[i][7];
              }
            }
          }
        }
      }
    }
    return s + " ";
  }
  class PathArray extends SVGArray {
    // Get bounding box of path
    bbox() {
      parser().path.setAttribute("d", this.toString());
      return new Box(parser.nodes.path.getBBox());
    }
    // Move path string
    move(x2, y2) {
      const box = this.bbox();
      x2 -= box.x;
      y2 -= box.y;
      if (!isNaN(x2) && !isNaN(y2)) {
        for (let l, i = this.length - 1; i >= 0; i--) {
          l = this[i][0];
          if (l === "M" || l === "L" || l === "T") {
            this[i][1] += x2;
            this[i][2] += y2;
          } else if (l === "H") {
            this[i][1] += x2;
          } else if (l === "V") {
            this[i][1] += y2;
          } else if (l === "C" || l === "S" || l === "Q") {
            this[i][1] += x2;
            this[i][2] += y2;
            this[i][3] += x2;
            this[i][4] += y2;
            if (l === "C") {
              this[i][5] += x2;
              this[i][6] += y2;
            }
          } else if (l === "A") {
            this[i][6] += x2;
            this[i][7] += y2;
          }
        }
      }
      return this;
    }
    // Absolutize and parse path to array
    parse(d = "M0 0") {
      if (Array.isArray(d)) {
        d = Array.prototype.concat.apply([], d).toString();
      }
      return pathParser(d);
    }
    // Resize path string
    size(width2, height2) {
      const box = this.bbox();
      let i, l;
      box.width = box.width === 0 ? 1 : box.width;
      box.height = box.height === 0 ? 1 : box.height;
      for (i = this.length - 1; i >= 0; i--) {
        l = this[i][0];
        if (l === "M" || l === "L" || l === "T") {
          this[i][1] = (this[i][1] - box.x) * width2 / box.width + box.x;
          this[i][2] = (this[i][2] - box.y) * height2 / box.height + box.y;
        } else if (l === "H") {
          this[i][1] = (this[i][1] - box.x) * width2 / box.width + box.x;
        } else if (l === "V") {
          this[i][1] = (this[i][1] - box.y) * height2 / box.height + box.y;
        } else if (l === "C" || l === "S" || l === "Q") {
          this[i][1] = (this[i][1] - box.x) * width2 / box.width + box.x;
          this[i][2] = (this[i][2] - box.y) * height2 / box.height + box.y;
          this[i][3] = (this[i][3] - box.x) * width2 / box.width + box.x;
          this[i][4] = (this[i][4] - box.y) * height2 / box.height + box.y;
          if (l === "C") {
            this[i][5] = (this[i][5] - box.x) * width2 / box.width + box.x;
            this[i][6] = (this[i][6] - box.y) * height2 / box.height + box.y;
          }
        } else if (l === "A") {
          this[i][1] = this[i][1] * width2 / box.width;
          this[i][2] = this[i][2] * height2 / box.height;
          this[i][6] = (this[i][6] - box.x) * width2 / box.width + box.x;
          this[i][7] = (this[i][7] - box.y) * height2 / box.height + box.y;
        }
      }
      return this;
    }
    // Convert array to string
    toString() {
      return arrayToString(this);
    }
  }
  const getClassForType = (value) => {
    const type = typeof value;
    if (type === "number") {
      return SVGNumber;
    } else if (type === "string") {
      if (Color.isColor(value)) {
        return Color;
      } else if (delimiter.test(value)) {
        return isPathLetter.test(value) ? PathArray : SVGArray;
      } else if (numberAndUnit.test(value)) {
        return SVGNumber;
      } else {
        return NonMorphable;
      }
    } else if (morphableTypes.indexOf(value.constructor) > -1) {
      return value.constructor;
    } else if (Array.isArray(value)) {
      return SVGArray;
    } else if (type === "object") {
      return ObjectBag;
    } else {
      return NonMorphable;
    }
  };
  class Morphable {
    constructor(stepper) {
      this._stepper = stepper || new Ease("-");
      this._from = null;
      this._to = null;
      this._type = null;
      this._context = null;
      this._morphObj = null;
    }
    at(pos) {
      return this._morphObj.morph(this._from, this._to, pos, this._stepper, this._context);
    }
    done() {
      const complete = this._context.map(this._stepper.done).reduce(function(last, curr) {
        return last && curr;
      }, true);
      return complete;
    }
    from(val) {
      if (val == null) {
        return this._from;
      }
      this._from = this._set(val);
      return this;
    }
    stepper(stepper) {
      if (stepper == null)
        return this._stepper;
      this._stepper = stepper;
      return this;
    }
    to(val) {
      if (val == null) {
        return this._to;
      }
      this._to = this._set(val);
      return this;
    }
    type(type) {
      if (type == null) {
        return this._type;
      }
      this._type = type;
      return this;
    }
    _set(value) {
      if (!this._type) {
        this.type(getClassForType(value));
      }
      let result = new this._type(value);
      if (this._type === Color) {
        result = this._to ? result[this._to[4]]() : this._from ? result[this._from[4]]() : result;
      }
      if (this._type === ObjectBag) {
        result = this._to ? result.align(this._to) : this._from ? result.align(this._from) : result;
      }
      result = result.toConsumable();
      this._morphObj = this._morphObj || new this._type();
      this._context = this._context || Array.apply(null, Array(result.length)).map(Object).map(function(o) {
        o.done = true;
        return o;
      });
      return result;
    }
  }
  class NonMorphable {
    constructor(...args) {
      this.init(...args);
    }
    init(val) {
      val = Array.isArray(val) ? val[0] : val;
      this.value = val;
      return this;
    }
    toArray() {
      return [this.value];
    }
    valueOf() {
      return this.value;
    }
  }
  class TransformBag {
    constructor(...args) {
      this.init(...args);
    }
    init(obj) {
      if (Array.isArray(obj)) {
        obj = {
          scaleX: obj[0],
          scaleY: obj[1],
          shear: obj[2],
          rotate: obj[3],
          translateX: obj[4],
          translateY: obj[5],
          originX: obj[6],
          originY: obj[7]
        };
      }
      Object.assign(this, TransformBag.defaults, obj);
      return this;
    }
    toArray() {
      const v = this;
      return [v.scaleX, v.scaleY, v.shear, v.rotate, v.translateX, v.translateY, v.originX, v.originY];
    }
  }
  TransformBag.defaults = {
    scaleX: 1,
    scaleY: 1,
    shear: 0,
    rotate: 0,
    translateX: 0,
    translateY: 0,
    originX: 0,
    originY: 0
  };
  const sortByKey = (a, b) => {
    return a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0;
  };
  class ObjectBag {
    constructor(...args) {
      this.init(...args);
    }
    align(other) {
      const values = this.values;
      for (let i = 0, il = values.length; i < il; ++i) {
        if (values[i + 1] === other[i + 1]) {
          if (values[i + 1] === Color && other[i + 7] !== values[i + 7]) {
            const space = other[i + 7];
            const color = new Color(this.values.splice(i + 3, 5))[space]().toArray();
            this.values.splice(i + 3, 0, ...color);
          }
          i += values[i + 2] + 2;
          continue;
        }
        if (!other[i + 1]) {
          return this;
        }
        const defaultObject = new other[i + 1]().toArray();
        const toDelete = values[i + 2] + 3;
        values.splice(i, toDelete, other[i], other[i + 1], other[i + 2], ...defaultObject);
        i += values[i + 2] + 2;
      }
      return this;
    }
    init(objOrArr) {
      this.values = [];
      if (Array.isArray(objOrArr)) {
        this.values = objOrArr.slice();
        return;
      }
      objOrArr = objOrArr || {};
      const entries = [];
      for (const i in objOrArr) {
        const Type = getClassForType(objOrArr[i]);
        const val = new Type(objOrArr[i]).toArray();
        entries.push([i, Type, val.length, ...val]);
      }
      entries.sort(sortByKey);
      this.values = entries.reduce((last, curr) => last.concat(curr), []);
      return this;
    }
    toArray() {
      return this.values;
    }
    valueOf() {
      const obj = {};
      const arr = this.values;
      while (arr.length) {
        const key = arr.shift();
        const Type = arr.shift();
        const num = arr.shift();
        const values = arr.splice(0, num);
        obj[key] = new Type(values);
      }
      return obj;
    }
  }
  const morphableTypes = [NonMorphable, TransformBag, ObjectBag];
  function registerMorphableType(type = []) {
    morphableTypes.push(...[].concat(type));
  }
  function makeMorphable() {
    extend(morphableTypes, {
      to(val) {
        return new Morphable().type(this.constructor).from(this.toArray()).to(val);
      },
      fromArray(arr) {
        this.init(arr);
        return this;
      },
      toConsumable() {
        return this.toArray();
      },
      morph(from2, to2, pos, stepper, context) {
        const mapper = function(i, index) {
          return stepper.step(i, to2[index], pos, context[index], context);
        };
        return this.fromArray(from2.map(mapper));
      }
    });
  }
  class Path extends Shape {
    // Initialize node
    constructor(node, attrs2 = node) {
      super(nodeOrNew("path", node), attrs2);
    }
    // Get array
    array() {
      return this._array || (this._array = new PathArray(this.attr("d")));
    }
    // Clear array cache
    clear() {
      delete this._array;
      return this;
    }
    // Set height of element
    height(height2) {
      return height2 == null ? this.bbox().height : this.size(this.bbox().width, height2);
    }
    // Move by left top corner
    move(x2, y2) {
      return this.attr("d", this.array().move(x2, y2));
    }
    // Plot new path
    plot(d) {
      return d == null ? this.array() : this.clear().attr("d", typeof d === "string" ? d : this._array = new PathArray(d));
    }
    // Set element size to given width and height
    size(width2, height2) {
      const p = proportionalSize(this, width2, height2);
      return this.attr("d", this.array().size(p.width, p.height));
    }
    // Set width of element
    width(width2) {
      return width2 == null ? this.bbox().width : this.size(width2, this.bbox().height);
    }
    // Move by left top corner over x-axis
    x(x2) {
      return x2 == null ? this.bbox().x : this.move(x2, this.bbox().y);
    }
    // Move by left top corner over y-axis
    y(y2) {
      return y2 == null ? this.bbox().y : this.move(this.bbox().x, y2);
    }
  }
  Path.prototype.MorphArray = PathArray;
  registerMethods({
    Container: {
      // Create a wrapped path element
      path: wrapWithAttrCheck(function(d) {
        return this.put(new Path()).plot(d || new PathArray());
      })
    }
  });
  register(Path, "Path");
  function array() {
    return this._array || (this._array = new PointArray(this.attr("points")));
  }
  function clear() {
    delete this._array;
    return this;
  }
  function move$2(x2, y2) {
    return this.attr("points", this.array().move(x2, y2));
  }
  function plot(p) {
    return p == null ? this.array() : this.clear().attr("points", typeof p === "string" ? p : this._array = new PointArray(p));
  }
  function size$1(width2, height2) {
    const p = proportionalSize(this, width2, height2);
    return this.attr("points", this.array().size(p.width, p.height));
  }
  var poly = {
    __proto__: null,
    array,
    clear,
    move: move$2,
    plot,
    size: size$1
  };
  class Polygon extends Shape {
    // Initialize node
    constructor(node, attrs2 = node) {
      super(nodeOrNew("polygon", node), attrs2);
    }
  }
  registerMethods({
    Container: {
      // Create a wrapped polygon element
      polygon: wrapWithAttrCheck(function(p) {
        return this.put(new Polygon()).plot(p || new PointArray());
      })
    }
  });
  extend(Polygon, pointed);
  extend(Polygon, poly);
  register(Polygon, "Polygon");
  class Polyline extends Shape {
    // Initialize node
    constructor(node, attrs2 = node) {
      super(nodeOrNew("polyline", node), attrs2);
    }
  }
  registerMethods({
    Container: {
      // Create a wrapped polygon element
      polyline: wrapWithAttrCheck(function(p) {
        return this.put(new Polyline()).plot(p || new PointArray());
      })
    }
  });
  extend(Polyline, pointed);
  extend(Polyline, poly);
  register(Polyline, "Polyline");
  class Rect extends Shape {
    // Initialize node
    constructor(node, attrs2 = node) {
      super(nodeOrNew("rect", node), attrs2);
    }
  }
  extend(Rect, {
    rx,
    ry
  });
  registerMethods({
    Container: {
      // Create a rect element
      rect: wrapWithAttrCheck(function(width2, height2) {
        return this.put(new Rect()).size(width2, height2);
      })
    }
  });
  register(Rect, "Rect");
  class Queue {
    constructor() {
      this._first = null;
      this._last = null;
    }
    // Shows us the first item in the list
    first() {
      return this._first && this._first.value;
    }
    // Shows us the last item in the list
    last() {
      return this._last && this._last.value;
    }
    push(value) {
      const item = typeof value.next !== "undefined" ? value : {
        value,
        next: null,
        prev: null
      };
      if (this._last) {
        item.prev = this._last;
        this._last.next = item;
        this._last = item;
      } else {
        this._last = item;
        this._first = item;
      }
      return item;
    }
    // Removes the item that was returned from the push
    remove(item) {
      if (item.prev)
        item.prev.next = item.next;
      if (item.next)
        item.next.prev = item.prev;
      if (item === this._last)
        this._last = item.prev;
      if (item === this._first)
        this._first = item.next;
      item.prev = null;
      item.next = null;
    }
    shift() {
      const remove = this._first;
      if (!remove)
        return null;
      this._first = remove.next;
      if (this._first)
        this._first.prev = null;
      this._last = this._first ? this._last : null;
      return remove.value;
    }
  }
  const Animator = {
    nextDraw: null,
    frames: new Queue(),
    timeouts: new Queue(),
    immediates: new Queue(),
    timer: () => globals.window.performance || globals.window.Date,
    transforms: [],
    frame(fn) {
      const node = Animator.frames.push({
        run: fn
      });
      if (Animator.nextDraw === null) {
        Animator.nextDraw = globals.window.requestAnimationFrame(Animator._draw);
      }
      return node;
    },
    timeout(fn, delay) {
      delay = delay || 0;
      const time = Animator.timer().now() + delay;
      const node = Animator.timeouts.push({
        run: fn,
        time
      });
      if (Animator.nextDraw === null) {
        Animator.nextDraw = globals.window.requestAnimationFrame(Animator._draw);
      }
      return node;
    },
    immediate(fn) {
      const node = Animator.immediates.push(fn);
      if (Animator.nextDraw === null) {
        Animator.nextDraw = globals.window.requestAnimationFrame(Animator._draw);
      }
      return node;
    },
    cancelFrame(node) {
      node != null && Animator.frames.remove(node);
    },
    clearTimeout(node) {
      node != null && Animator.timeouts.remove(node);
    },
    cancelImmediate(node) {
      node != null && Animator.immediates.remove(node);
    },
    _draw(now) {
      let nextTimeout = null;
      const lastTimeout = Animator.timeouts.last();
      while (nextTimeout = Animator.timeouts.shift()) {
        if (now >= nextTimeout.time) {
          nextTimeout.run();
        } else {
          Animator.timeouts.push(nextTimeout);
        }
        if (nextTimeout === lastTimeout)
          break;
      }
      let nextFrame = null;
      const lastFrame = Animator.frames.last();
      while (nextFrame !== lastFrame && (nextFrame = Animator.frames.shift())) {
        nextFrame.run(now);
      }
      let nextImmediate = null;
      while (nextImmediate = Animator.immediates.shift()) {
        nextImmediate();
      }
      Animator.nextDraw = Animator.timeouts.first() || Animator.frames.first() ? globals.window.requestAnimationFrame(Animator._draw) : null;
    }
  };
  const makeSchedule = function(runnerInfo) {
    const start = runnerInfo.start;
    const duration = runnerInfo.runner.duration();
    const end = start + duration;
    return {
      start,
      duration,
      end,
      runner: runnerInfo.runner
    };
  };
  const defaultSource = function() {
    const w = globals.window;
    return (w.performance || w.Date).now();
  };
  class Timeline extends EventTarget {
    // Construct a new timeline on the given element
    constructor(timeSource = defaultSource) {
      super();
      this._timeSource = timeSource;
      this._startTime = 0;
      this._speed = 1;
      this._persist = 0;
      this._nextFrame = null;
      this._paused = true;
      this._runners = [];
      this._runnerIds = [];
      this._lastRunnerId = -1;
      this._time = 0;
      this._lastSourceTime = 0;
      this._lastStepTime = 0;
      this._step = this._stepFn.bind(this, false);
      this._stepImmediate = this._stepFn.bind(this, true);
    }
    active() {
      return !!this._nextFrame;
    }
    finish() {
      this.time(this.getEndTimeOfTimeline() + 1);
      return this.pause();
    }
    // Calculates the end of the timeline
    getEndTime() {
      const lastRunnerInfo = this.getLastRunnerInfo();
      const lastDuration = lastRunnerInfo ? lastRunnerInfo.runner.duration() : 0;
      const lastStartTime = lastRunnerInfo ? lastRunnerInfo.start : this._time;
      return lastStartTime + lastDuration;
    }
    getEndTimeOfTimeline() {
      const endTimes = this._runners.map((i) => i.start + i.runner.duration());
      return Math.max(0, ...endTimes);
    }
    getLastRunnerInfo() {
      return this.getRunnerInfoById(this._lastRunnerId);
    }
    getRunnerInfoById(id) {
      return this._runners[this._runnerIds.indexOf(id)] || null;
    }
    pause() {
      this._paused = true;
      return this._continue();
    }
    persist(dtOrForever) {
      if (dtOrForever == null)
        return this._persist;
      this._persist = dtOrForever;
      return this;
    }
    play() {
      this._paused = false;
      return this.updateTime()._continue();
    }
    reverse(yes) {
      const currentSpeed = this.speed();
      if (yes == null)
        return this.speed(-currentSpeed);
      const positive = Math.abs(currentSpeed);
      return this.speed(yes ? -positive : positive);
    }
    // schedules a runner on the timeline
    schedule(runner, delay, when) {
      if (runner == null) {
        return this._runners.map(makeSchedule);
      }
      let absoluteStartTime = 0;
      const endTime = this.getEndTime();
      delay = delay || 0;
      if (when == null || when === "last" || when === "after") {
        absoluteStartTime = endTime;
      } else if (when === "absolute" || when === "start") {
        absoluteStartTime = delay;
        delay = 0;
      } else if (when === "now") {
        absoluteStartTime = this._time;
      } else if (when === "relative") {
        const runnerInfo2 = this.getRunnerInfoById(runner.id);
        if (runnerInfo2) {
          absoluteStartTime = runnerInfo2.start + delay;
          delay = 0;
        }
      } else if (when === "with-last") {
        const lastRunnerInfo = this.getLastRunnerInfo();
        const lastStartTime = lastRunnerInfo ? lastRunnerInfo.start : this._time;
        absoluteStartTime = lastStartTime;
      } else {
        throw new Error('Invalid value for the "when" parameter');
      }
      runner.unschedule();
      runner.timeline(this);
      const persist = runner.persist();
      const runnerInfo = {
        persist: persist === null ? this._persist : persist,
        start: absoluteStartTime + delay,
        runner
      };
      this._lastRunnerId = runner.id;
      this._runners.push(runnerInfo);
      this._runners.sort((a, b) => a.start - b.start);
      this._runnerIds = this._runners.map((info) => info.runner.id);
      this.updateTime()._continue();
      return this;
    }
    seek(dt) {
      return this.time(this._time + dt);
    }
    source(fn) {
      if (fn == null)
        return this._timeSource;
      this._timeSource = fn;
      return this;
    }
    speed(speed) {
      if (speed == null)
        return this._speed;
      this._speed = speed;
      return this;
    }
    stop() {
      this.time(0);
      return this.pause();
    }
    time(time) {
      if (time == null)
        return this._time;
      this._time = time;
      return this._continue(true);
    }
    // Remove the runner from this timeline
    unschedule(runner) {
      const index = this._runnerIds.indexOf(runner.id);
      if (index < 0)
        return this;
      this._runners.splice(index, 1);
      this._runnerIds.splice(index, 1);
      runner.timeline(null);
      return this;
    }
    // Makes sure, that after pausing the time doesn't jump
    updateTime() {
      if (!this.active()) {
        this._lastSourceTime = this._timeSource();
      }
      return this;
    }
    // Checks if we are running and continues the animation
    _continue(immediateStep = false) {
      Animator.cancelFrame(this._nextFrame);
      this._nextFrame = null;
      if (immediateStep)
        return this._stepImmediate();
      if (this._paused)
        return this;
      this._nextFrame = Animator.frame(this._step);
      return this;
    }
    _stepFn(immediateStep = false) {
      const time = this._timeSource();
      let dtSource = time - this._lastSourceTime;
      if (immediateStep)
        dtSource = 0;
      const dtTime = this._speed * dtSource + (this._time - this._lastStepTime);
      this._lastSourceTime = time;
      if (!immediateStep) {
        this._time += dtTime;
        this._time = this._time < 0 ? 0 : this._time;
      }
      this._lastStepTime = this._time;
      this.fire("time", this._time);
      for (let k = this._runners.length; k--; ) {
        const runnerInfo = this._runners[k];
        const runner = runnerInfo.runner;
        const dtToStart = this._time - runnerInfo.start;
        if (dtToStart <= 0) {
          runner.reset();
        }
      }
      let runnersLeft = false;
      for (let i = 0, len = this._runners.length; i < len; i++) {
        const runnerInfo = this._runners[i];
        const runner = runnerInfo.runner;
        let dt = dtTime;
        const dtToStart = this._time - runnerInfo.start;
        if (dtToStart <= 0) {
          runnersLeft = true;
          continue;
        } else if (dtToStart < dt) {
          dt = dtToStart;
        }
        if (!runner.active())
          continue;
        const finished = runner.step(dt).done;
        if (!finished) {
          runnersLeft = true;
        } else if (runnerInfo.persist !== true) {
          const endTime = runner.duration() - runner.time() + this._time;
          if (endTime + runnerInfo.persist < this._time) {
            runner.unschedule();
            --i;
            --len;
          }
        }
      }
      if (runnersLeft && !(this._speed < 0 && this._time === 0) || this._runnerIds.length && this._speed < 0 && this._time > 0) {
        this._continue();
      } else {
        this.pause();
        this.fire("finished");
      }
      return this;
    }
  }
  registerMethods({
    Element: {
      timeline: function(timeline2) {
        if (timeline2 == null) {
          this._timeline = this._timeline || new Timeline();
          return this._timeline;
        } else {
          this._timeline = timeline2;
          return this;
        }
      }
    }
  });
  class Runner extends EventTarget {
    constructor(options) {
      super();
      this.id = Runner.id++;
      options = options == null ? timeline.duration : options;
      options = typeof options === "function" ? new Controller(options) : options;
      this._element = null;
      this._timeline = null;
      this.done = false;
      this._queue = [];
      this._duration = typeof options === "number" && options;
      this._isDeclarative = options instanceof Controller;
      this._stepper = this._isDeclarative ? options : new Ease();
      this._history = {};
      this.enabled = true;
      this._time = 0;
      this._lastTime = 0;
      this._reseted = true;
      this.transforms = new Matrix();
      this.transformId = 1;
      this._haveReversed = false;
      this._reverse = false;
      this._loopsDone = 0;
      this._swing = false;
      this._wait = 0;
      this._times = 1;
      this._frameId = null;
      this._persist = this._isDeclarative ? true : null;
    }
    static sanitise(duration, delay, when) {
      let times = 1;
      let swing = false;
      let wait = 0;
      duration = duration || timeline.duration;
      delay = delay || timeline.delay;
      when = when || "last";
      if (typeof duration === "object" && !(duration instanceof Stepper)) {
        delay = duration.delay || delay;
        when = duration.when || when;
        swing = duration.swing || swing;
        times = duration.times || times;
        wait = duration.wait || wait;
        duration = duration.duration || timeline.duration;
      }
      return {
        duration,
        delay,
        swing,
        times,
        wait,
        when
      };
    }
    active(enabled) {
      if (enabled == null)
        return this.enabled;
      this.enabled = enabled;
      return this;
    }
    /*
    Private Methods
    ===============
    Methods that shouldn't be used externally
    */
    addTransform(transform2, index) {
      this.transforms.lmultiplyO(transform2);
      return this;
    }
    after(fn) {
      return this.on("finished", fn);
    }
    animate(duration, delay, when) {
      const o = Runner.sanitise(duration, delay, when);
      const runner = new Runner(o.duration);
      if (this._timeline)
        runner.timeline(this._timeline);
      if (this._element)
        runner.element(this._element);
      return runner.loop(o).schedule(o.delay, o.when);
    }
    clearTransform() {
      this.transforms = new Matrix();
      return this;
    }
    // TODO: Keep track of all transformations so that deletion is faster
    clearTransformsFromQueue() {
      if (!this.done || !this._timeline || !this._timeline._runnerIds.includes(this.id)) {
        this._queue = this._queue.filter((item) => {
          return !item.isTransform;
        });
      }
    }
    delay(delay) {
      return this.animate(0, delay);
    }
    duration() {
      return this._times * (this._wait + this._duration) - this._wait;
    }
    during(fn) {
      return this.queue(null, fn);
    }
    ease(fn) {
      this._stepper = new Ease(fn);
      return this;
    }
    /*
    Runner Definitions
    ==================
    These methods help us define the runtime behaviour of the Runner or they
    help us make new runners from the current runner
    */
    element(element2) {
      if (element2 == null)
        return this._element;
      this._element = element2;
      element2._prepareRunner();
      return this;
    }
    finish() {
      return this.step(Infinity);
    }
    loop(times, swing, wait) {
      if (typeof times === "object") {
        swing = times.swing;
        wait = times.wait;
        times = times.times;
      }
      this._times = times || Infinity;
      this._swing = swing || false;
      this._wait = wait || 0;
      if (this._times === true) {
        this._times = Infinity;
      }
      return this;
    }
    loops(p) {
      const loopDuration = this._duration + this._wait;
      if (p == null) {
        const loopsDone = Math.floor(this._time / loopDuration);
        const relativeTime = this._time - loopsDone * loopDuration;
        const position2 = relativeTime / this._duration;
        return Math.min(loopsDone + position2, this._times);
      }
      const whole = Math.floor(p);
      const partial = p % 1;
      const time = loopDuration * whole + this._duration * partial;
      return this.time(time);
    }
    persist(dtOrForever) {
      if (dtOrForever == null)
        return this._persist;
      this._persist = dtOrForever;
      return this;
    }
    position(p) {
      const x2 = this._time;
      const d = this._duration;
      const w = this._wait;
      const t = this._times;
      const s = this._swing;
      const r = this._reverse;
      let position2;
      if (p == null) {
        const f = function(x3) {
          const swinging = s * Math.floor(x3 % (2 * (w + d)) / (w + d));
          const backwards = swinging && !r || !swinging && r;
          const uncliped = Math.pow(-1, backwards) * (x3 % (w + d)) / d + backwards;
          const clipped = Math.max(Math.min(uncliped, 1), 0);
          return clipped;
        };
        const endTime = t * (w + d) - w;
        position2 = x2 <= 0 ? Math.round(f(1e-5)) : x2 < endTime ? f(x2) : Math.round(f(endTime - 1e-5));
        return position2;
      }
      const loopsDone = Math.floor(this.loops());
      const swingForward = s && loopsDone % 2 === 0;
      const forwards = swingForward && !r || r && swingForward;
      position2 = loopsDone + (forwards ? p : 1 - p);
      return this.loops(position2);
    }
    progress(p) {
      if (p == null) {
        return Math.min(1, this._time / this.duration());
      }
      return this.time(p * this.duration());
    }
    /*
    Basic Functionality
    ===================
    These methods allow us to attach basic functions to the runner directly
    */
    queue(initFn, runFn, retargetFn, isTransform) {
      this._queue.push({
        initialiser: initFn || noop,
        runner: runFn || noop,
        retarget: retargetFn,
        isTransform,
        initialised: false,
        finished: false
      });
      const timeline2 = this.timeline();
      timeline2 && this.timeline()._continue();
      return this;
    }
    reset() {
      if (this._reseted)
        return this;
      this.time(0);
      this._reseted = true;
      return this;
    }
    reverse(reverse) {
      this._reverse = reverse == null ? !this._reverse : reverse;
      return this;
    }
    schedule(timeline2, delay, when) {
      if (!(timeline2 instanceof Timeline)) {
        when = delay;
        delay = timeline2;
        timeline2 = this.timeline();
      }
      if (!timeline2) {
        throw Error("Runner cannot be scheduled without timeline");
      }
      timeline2.schedule(this, delay, when);
      return this;
    }
    step(dt) {
      if (!this.enabled)
        return this;
      dt = dt == null ? 16 : dt;
      this._time += dt;
      const position2 = this.position();
      const running = this._lastPosition !== position2 && this._time >= 0;
      this._lastPosition = position2;
      const duration = this.duration();
      const justStarted = this._lastTime <= 0 && this._time > 0;
      const justFinished = this._lastTime < duration && this._time >= duration;
      this._lastTime = this._time;
      if (justStarted) {
        this.fire("start", this);
      }
      const declarative = this._isDeclarative;
      this.done = !declarative && !justFinished && this._time >= duration;
      this._reseted = false;
      let converged = false;
      if (running || declarative) {
        this._initialise(running);
        this.transforms = new Matrix();
        converged = this._run(declarative ? dt : position2);
        this.fire("step", this);
      }
      this.done = this.done || converged && declarative;
      if (justFinished) {
        this.fire("finished", this);
      }
      return this;
    }
    /*
    Runner animation methods
    ========================
    Control how the animation plays
    */
    time(time) {
      if (time == null) {
        return this._time;
      }
      const dt = time - this._time;
      this.step(dt);
      return this;
    }
    timeline(timeline2) {
      if (typeof timeline2 === "undefined")
        return this._timeline;
      this._timeline = timeline2;
      return this;
    }
    unschedule() {
      const timeline2 = this.timeline();
      timeline2 && timeline2.unschedule(this);
      return this;
    }
    // Run each initialise function in the runner if required
    _initialise(running) {
      if (!running && !this._isDeclarative)
        return;
      for (let i = 0, len = this._queue.length; i < len; ++i) {
        const current = this._queue[i];
        const needsIt = this._isDeclarative || !current.initialised && running;
        running = !current.finished;
        if (needsIt && running) {
          current.initialiser.call(this);
          current.initialised = true;
        }
      }
    }
    // Save a morpher to the morpher list so that we can retarget it later
    _rememberMorpher(method, morpher) {
      this._history[method] = {
        morpher,
        caller: this._queue[this._queue.length - 1]
      };
      if (this._isDeclarative) {
        const timeline2 = this.timeline();
        timeline2 && timeline2.play();
      }
    }
    // Try to set the target for a morpher if the morpher exists, otherwise
    // Run each run function for the position or dt given
    _run(positionOrDt) {
      let allfinished = true;
      for (let i = 0, len = this._queue.length; i < len; ++i) {
        const current = this._queue[i];
        const converged = current.runner.call(this, positionOrDt);
        current.finished = current.finished || converged === true;
        allfinished = allfinished && current.finished;
      }
      return allfinished;
    }
    // do nothing and return false
    _tryRetarget(method, target, extra) {
      if (this._history[method]) {
        if (!this._history[method].caller.initialised) {
          const index = this._queue.indexOf(this._history[method].caller);
          this._queue.splice(index, 1);
          return false;
        }
        if (this._history[method].caller.retarget) {
          this._history[method].caller.retarget.call(this, target, extra);
        } else {
          this._history[method].morpher.to(target);
        }
        this._history[method].caller.finished = false;
        const timeline2 = this.timeline();
        timeline2 && timeline2.play();
        return true;
      }
      return false;
    }
  }
  Runner.id = 0;
  class FakeRunner {
    constructor(transforms2 = new Matrix(), id = -1, done = true) {
      this.transforms = transforms2;
      this.id = id;
      this.done = done;
    }
    clearTransformsFromQueue() {
    }
  }
  extend([Runner, FakeRunner], {
    mergeWith(runner) {
      return new FakeRunner(runner.transforms.lmultiply(this.transforms), runner.id);
    }
  });
  const lmultiply = (last, curr) => last.lmultiplyO(curr);
  const getRunnerTransform = (runner) => runner.transforms;
  function mergeTransforms() {
    const runners = this._transformationRunners.runners;
    const netTransform = runners.map(getRunnerTransform).reduce(lmultiply, new Matrix());
    this.transform(netTransform);
    this._transformationRunners.merge();
    if (this._transformationRunners.length() === 1) {
      this._frameId = null;
    }
  }
  class RunnerArray {
    constructor() {
      this.runners = [];
      this.ids = [];
    }
    add(runner) {
      if (this.runners.includes(runner))
        return;
      const id = runner.id + 1;
      this.runners.push(runner);
      this.ids.push(id);
      return this;
    }
    clearBefore(id) {
      const deleteCnt = this.ids.indexOf(id + 1) || 1;
      this.ids.splice(0, deleteCnt, 0);
      this.runners.splice(0, deleteCnt, new FakeRunner()).forEach((r) => r.clearTransformsFromQueue());
      return this;
    }
    edit(id, newRunner) {
      const index = this.ids.indexOf(id + 1);
      this.ids.splice(index, 1, id + 1);
      this.runners.splice(index, 1, newRunner);
      return this;
    }
    getByID(id) {
      return this.runners[this.ids.indexOf(id + 1)];
    }
    length() {
      return this.ids.length;
    }
    merge() {
      let lastRunner = null;
      for (let i = 0; i < this.runners.length; ++i) {
        const runner = this.runners[i];
        const condition = lastRunner && runner.done && lastRunner.done && (!runner._timeline || !runner._timeline._runnerIds.includes(runner.id)) && (!lastRunner._timeline || !lastRunner._timeline._runnerIds.includes(lastRunner.id));
        if (condition) {
          this.remove(runner.id);
          const newRunner = runner.mergeWith(lastRunner);
          this.edit(lastRunner.id, newRunner);
          lastRunner = newRunner;
          --i;
        } else {
          lastRunner = runner;
        }
      }
      return this;
    }
    remove(id) {
      const index = this.ids.indexOf(id + 1);
      this.ids.splice(index, 1);
      this.runners.splice(index, 1);
      return this;
    }
  }
  registerMethods({
    Element: {
      animate(duration, delay, when) {
        const o = Runner.sanitise(duration, delay, when);
        const timeline2 = this.timeline();
        return new Runner(o.duration).loop(o).element(this).timeline(timeline2.play()).schedule(o.delay, o.when);
      },
      delay(by, when) {
        return this.animate(0, by, when);
      },
      // this function searches for all runners on the element and deletes the ones
      // which run before the current one. This is because absolute transformations
      // overwrite anything anyway so there is no need to waste time computing
      // other runners
      _clearTransformRunnersBefore(currentRunner) {
        this._transformationRunners.clearBefore(currentRunner.id);
      },
      _currentTransform(current) {
        return this._transformationRunners.runners.filter((runner) => runner.id <= current.id).map(getRunnerTransform).reduce(lmultiply, new Matrix());
      },
      _addRunner(runner) {
        this._transformationRunners.add(runner);
        Animator.cancelImmediate(this._frameId);
        this._frameId = Animator.immediate(mergeTransforms.bind(this));
      },
      _prepareRunner() {
        if (this._frameId == null) {
          this._transformationRunners = new RunnerArray().add(new FakeRunner(new Matrix(this)));
        }
      }
    }
  });
  const difference = (a, b) => a.filter((x2) => !b.includes(x2));
  extend(Runner, {
    attr(a, v) {
      return this.styleAttr("attr", a, v);
    },
    // Add animatable styles
    css(s, v) {
      return this.styleAttr("css", s, v);
    },
    styleAttr(type, nameOrAttrs, val) {
      if (typeof nameOrAttrs === "string") {
        return this.styleAttr(type, {
          [nameOrAttrs]: val
        });
      }
      let attrs2 = nameOrAttrs;
      if (this._tryRetarget(type, attrs2))
        return this;
      let morpher = new Morphable(this._stepper).to(attrs2);
      let keys = Object.keys(attrs2);
      this.queue(function() {
        morpher = morpher.from(this.element()[type](keys));
      }, function(pos) {
        this.element()[type](morpher.at(pos).valueOf());
        return morpher.done();
      }, function(newToAttrs) {
        const newKeys = Object.keys(newToAttrs);
        const differences = difference(newKeys, keys);
        if (differences.length) {
          const addedFromAttrs = this.element()[type](differences);
          const oldFromAttrs = new ObjectBag(morpher.from()).valueOf();
          Object.assign(oldFromAttrs, addedFromAttrs);
          morpher.from(oldFromAttrs);
        }
        const oldToAttrs = new ObjectBag(morpher.to()).valueOf();
        Object.assign(oldToAttrs, newToAttrs);
        morpher.to(oldToAttrs);
        keys = newKeys;
        attrs2 = newToAttrs;
      });
      this._rememberMorpher(type, morpher);
      return this;
    },
    zoom(level, point2) {
      if (this._tryRetarget("zoom", level, point2))
        return this;
      let morpher = new Morphable(this._stepper).to(new SVGNumber(level));
      this.queue(function() {
        morpher = morpher.from(this.element().zoom());
      }, function(pos) {
        this.element().zoom(morpher.at(pos), point2);
        return morpher.done();
      }, function(newLevel, newPoint) {
        point2 = newPoint;
        morpher.to(newLevel);
      });
      this._rememberMorpher("zoom", morpher);
      return this;
    },
    /**
     ** absolute transformations
     **/
    //
    // M v -----|-----(D M v = F v)------|----->  T v
    //
    // 1. define the final state (T) and decompose it (once)
    //    t = [tx, ty, the, lam, sy, sx]
    // 2. on every frame: pull the current state of all previous transforms
    //    (M - m can change)
    //   and then write this as m = [tx0, ty0, the0, lam0, sy0, sx0]
    // 3. Find the interpolated matrix F(pos) = m + pos * (t - m)
    //   - Note F(0) = M
    //   - Note F(1) = T
    // 4. Now you get the delta matrix as a result: D = F * inv(M)
    transform(transforms2, relative, affine) {
      relative = transforms2.relative || relative;
      if (this._isDeclarative && !relative && this._tryRetarget("transform", transforms2)) {
        return this;
      }
      const isMatrix = Matrix.isMatrixLike(transforms2);
      affine = transforms2.affine != null ? transforms2.affine : affine != null ? affine : !isMatrix;
      const morpher = new Morphable(this._stepper).type(affine ? TransformBag : Matrix);
      let origin;
      let element2;
      let current;
      let currentAngle;
      let startTransform;
      function setup() {
        element2 = element2 || this.element();
        origin = origin || getOrigin(transforms2, element2);
        startTransform = new Matrix(relative ? void 0 : element2);
        element2._addRunner(this);
        if (!relative) {
          element2._clearTransformRunnersBefore(this);
        }
      }
      function run(pos) {
        if (!relative)
          this.clearTransform();
        const {
          x: x2,
          y: y2
        } = new Point(origin).transform(element2._currentTransform(this));
        let target = new Matrix({
          ...transforms2,
          origin: [x2, y2]
        });
        let start = this._isDeclarative && current ? current : startTransform;
        if (affine) {
          target = target.decompose(x2, y2);
          start = start.decompose(x2, y2);
          const rTarget = target.rotate;
          const rCurrent = start.rotate;
          const possibilities = [rTarget - 360, rTarget, rTarget + 360];
          const distances = possibilities.map((a) => Math.abs(a - rCurrent));
          const shortest = Math.min(...distances);
          const index = distances.indexOf(shortest);
          target.rotate = possibilities[index];
        }
        if (relative) {
          if (!isMatrix) {
            target.rotate = transforms2.rotate || 0;
          }
          if (this._isDeclarative && currentAngle) {
            start.rotate = currentAngle;
          }
        }
        morpher.from(start);
        morpher.to(target);
        const affineParameters = morpher.at(pos);
        currentAngle = affineParameters.rotate;
        current = new Matrix(affineParameters);
        this.addTransform(current);
        element2._addRunner(this);
        return morpher.done();
      }
      function retarget(newTransforms) {
        if ((newTransforms.origin || "center").toString() !== (transforms2.origin || "center").toString()) {
          origin = getOrigin(newTransforms, element2);
        }
        transforms2 = {
          ...newTransforms,
          origin
        };
      }
      this.queue(setup, run, retarget, true);
      this._isDeclarative && this._rememberMorpher("transform", morpher);
      return this;
    },
    // Animatable x-axis
    x(x2, relative) {
      return this._queueNumber("x", x2);
    },
    // Animatable y-axis
    y(y2) {
      return this._queueNumber("y", y2);
    },
    dx(x2 = 0) {
      return this._queueNumberDelta("x", x2);
    },
    dy(y2 = 0) {
      return this._queueNumberDelta("y", y2);
    },
    dmove(x2, y2) {
      return this.dx(x2).dy(y2);
    },
    _queueNumberDelta(method, to2) {
      to2 = new SVGNumber(to2);
      if (this._tryRetarget(method, to2))
        return this;
      const morpher = new Morphable(this._stepper).to(to2);
      let from2 = null;
      this.queue(function() {
        from2 = this.element()[method]();
        morpher.from(from2);
        morpher.to(from2 + to2);
      }, function(pos) {
        this.element()[method](morpher.at(pos));
        return morpher.done();
      }, function(newTo) {
        morpher.to(from2 + new SVGNumber(newTo));
      });
      this._rememberMorpher(method, morpher);
      return this;
    },
    _queueObject(method, to2) {
      if (this._tryRetarget(method, to2))
        return this;
      const morpher = new Morphable(this._stepper).to(to2);
      this.queue(function() {
        morpher.from(this.element()[method]());
      }, function(pos) {
        this.element()[method](morpher.at(pos));
        return morpher.done();
      });
      this._rememberMorpher(method, morpher);
      return this;
    },
    _queueNumber(method, value) {
      return this._queueObject(method, new SVGNumber(value));
    },
    // Animatable center x-axis
    cx(x2) {
      return this._queueNumber("cx", x2);
    },
    // Animatable center y-axis
    cy(y2) {
      return this._queueNumber("cy", y2);
    },
    // Add animatable move
    move(x2, y2) {
      return this.x(x2).y(y2);
    },
    // Add animatable center
    center(x2, y2) {
      return this.cx(x2).cy(y2);
    },
    // Add animatable size
    size(width2, height2) {
      let box;
      if (!width2 || !height2) {
        box = this._element.bbox();
      }
      if (!width2) {
        width2 = box.width / box.height * height2;
      }
      if (!height2) {
        height2 = box.height / box.width * width2;
      }
      return this.width(width2).height(height2);
    },
    // Add animatable width
    width(width2) {
      return this._queueNumber("width", width2);
    },
    // Add animatable height
    height(height2) {
      return this._queueNumber("height", height2);
    },
    // Add animatable plot
    plot(a, b, c, d) {
      if (arguments.length === 4) {
        return this.plot([a, b, c, d]);
      }
      if (this._tryRetarget("plot", a))
        return this;
      const morpher = new Morphable(this._stepper).type(this._element.MorphArray).to(a);
      this.queue(function() {
        morpher.from(this._element.array());
      }, function(pos) {
        this._element.plot(morpher.at(pos));
        return morpher.done();
      });
      this._rememberMorpher("plot", morpher);
      return this;
    },
    // Add leading method
    leading(value) {
      return this._queueNumber("leading", value);
    },
    // Add animatable viewbox
    viewbox(x2, y2, width2, height2) {
      return this._queueObject("viewbox", new Box(x2, y2, width2, height2));
    },
    update(o) {
      if (typeof o !== "object") {
        return this.update({
          offset: arguments[0],
          color: arguments[1],
          opacity: arguments[2]
        });
      }
      if (o.opacity != null)
        this.attr("stop-opacity", o.opacity);
      if (o.color != null)
        this.attr("stop-color", o.color);
      if (o.offset != null)
        this.attr("offset", o.offset);
      return this;
    }
  });
  extend(Runner, {
    rx,
    ry,
    from,
    to
  });
  register(Runner, "Runner");
  class Svg extends Container {
    constructor(node, attrs2 = node) {
      super(nodeOrNew("svg", node), attrs2);
      this.namespace();
    }
    // Creates and returns defs element
    defs() {
      if (!this.isRoot())
        return this.root().defs();
      return adopt(this.node.querySelector("defs")) || this.put(new Defs());
    }
    isRoot() {
      return !this.node.parentNode || !(this.node.parentNode instanceof globals.window.SVGElement) && this.node.parentNode.nodeName !== "#document-fragment";
    }
    // Add namespaces
    namespace() {
      if (!this.isRoot())
        return this.root().namespace();
      return this.attr({
        xmlns: svg,
        version: "1.1"
      }).attr("xmlns:xlink", xlink, xmlns).attr("xmlns:svgjs", svgjs, xmlns);
    }
    removeNamespace() {
      return this.attr({
        xmlns: null,
        version: null
      }).attr("xmlns:xlink", null, xmlns).attr("xmlns:svgjs", null, xmlns);
    }
    // Check if this is a root svg
    // If not, call root() from this element
    root() {
      if (this.isRoot())
        return this;
      return super.root();
    }
  }
  registerMethods({
    Container: {
      // Create nested svg document
      nested: wrapWithAttrCheck(function() {
        return this.put(new Svg());
      })
    }
  });
  register(Svg, "Svg", true);
  let Symbol$1 = class Symbol2 extends Container {
    // Initialize node
    constructor(node, attrs2 = node) {
      super(nodeOrNew("symbol", node), attrs2);
    }
  };
  registerMethods({
    Container: {
      symbol: wrapWithAttrCheck(function() {
        return this.put(new Symbol$1());
      })
    }
  });
  register(Symbol$1, "Symbol");
  function plain(text) {
    if (this._build === false) {
      this.clear();
    }
    this.node.appendChild(globals.document.createTextNode(text));
    return this;
  }
  function length() {
    return this.node.getComputedTextLength();
  }
  function x$1(x2, box = this.bbox()) {
    if (x2 == null) {
      return box.x;
    }
    return this.attr("x", this.attr("x") + x2 - box.x);
  }
  function y$1(y2, box = this.bbox()) {
    if (y2 == null) {
      return box.y;
    }
    return this.attr("y", this.attr("y") + y2 - box.y);
  }
  function move$1(x2, y2, box = this.bbox()) {
    return this.x(x2, box).y(y2, box);
  }
  function cx(x2, box = this.bbox()) {
    if (x2 == null) {
      return box.cx;
    }
    return this.attr("x", this.attr("x") + x2 - box.cx);
  }
  function cy(y2, box = this.bbox()) {
    if (y2 == null) {
      return box.cy;
    }
    return this.attr("y", this.attr("y") + y2 - box.cy);
  }
  function center(x2, y2, box = this.bbox()) {
    return this.cx(x2, box).cy(y2, box);
  }
  function ax(x2) {
    return this.attr("x", x2);
  }
  function ay(y2) {
    return this.attr("y", y2);
  }
  function amove(x2, y2) {
    return this.ax(x2).ay(y2);
  }
  function build(build2) {
    this._build = !!build2;
    return this;
  }
  var textable = {
    __proto__: null,
    plain,
    length,
    x: x$1,
    y: y$1,
    move: move$1,
    cx,
    cy,
    center,
    ax,
    ay,
    amove,
    build
  };
  class Text extends Shape {
    // Initialize node
    constructor(node, attrs2 = node) {
      super(nodeOrNew("text", node), attrs2);
      this.dom.leading = new SVGNumber(1.3);
      this._rebuild = true;
      this._build = false;
    }
    // Set / get leading
    leading(value) {
      if (value == null) {
        return this.dom.leading;
      }
      this.dom.leading = new SVGNumber(value);
      return this.rebuild();
    }
    // Rebuild appearance type
    rebuild(rebuild) {
      if (typeof rebuild === "boolean") {
        this._rebuild = rebuild;
      }
      if (this._rebuild) {
        const self2 = this;
        let blankLineOffset = 0;
        const leading = this.dom.leading;
        this.each(function(i) {
          const fontSize = globals.window.getComputedStyle(this.node).getPropertyValue("font-size");
          const dy2 = leading * new SVGNumber(fontSize);
          if (this.dom.newLined) {
            this.attr("x", self2.attr("x"));
            if (this.text() === "\n") {
              blankLineOffset += dy2;
            } else {
              this.attr("dy", i ? dy2 + blankLineOffset : 0);
              blankLineOffset = 0;
            }
          }
        });
        this.fire("rebuild");
      }
      return this;
    }
    // overwrite method from parent to set data properly
    setData(o) {
      this.dom = o;
      this.dom.leading = new SVGNumber(o.leading || 1.3);
      return this;
    }
    // Set the text content
    text(text) {
      if (text === void 0) {
        const children = this.node.childNodes;
        let firstLine = 0;
        text = "";
        for (let i = 0, len = children.length; i < len; ++i) {
          if (children[i].nodeName === "textPath") {
            if (i === 0)
              firstLine = 1;
            continue;
          }
          if (i !== firstLine && children[i].nodeType !== 3 && adopt(children[i]).dom.newLined === true) {
            text += "\n";
          }
          text += children[i].textContent;
        }
        return text;
      }
      this.clear().build(true);
      if (typeof text === "function") {
        text.call(this, this);
      } else {
        text = (text + "").split("\n");
        for (let j = 0, jl = text.length; j < jl; j++) {
          this.newLine(text[j]);
        }
      }
      return this.build(false).rebuild();
    }
  }
  extend(Text, textable);
  registerMethods({
    Container: {
      // Create text element
      text: wrapWithAttrCheck(function(text = "") {
        return this.put(new Text()).text(text);
      }),
      // Create plain text element
      plain: wrapWithAttrCheck(function(text = "") {
        return this.put(new Text()).plain(text);
      })
    }
  });
  register(Text, "Text");
  class Tspan extends Shape {
    // Initialize node
    constructor(node, attrs2 = node) {
      super(nodeOrNew("tspan", node), attrs2);
      this._build = false;
    }
    // Shortcut dx
    dx(dx2) {
      return this.attr("dx", dx2);
    }
    // Shortcut dy
    dy(dy2) {
      return this.attr("dy", dy2);
    }
    // Create new line
    newLine() {
      this.dom.newLined = true;
      const text = this.parent();
      if (!(text instanceof Text)) {
        return this;
      }
      const i = text.index(this);
      const fontSize = globals.window.getComputedStyle(this.node).getPropertyValue("font-size");
      const dy2 = text.dom.leading * new SVGNumber(fontSize);
      return this.dy(i ? dy2 : 0).attr("x", text.x());
    }
    // Set text content
    text(text) {
      if (text == null)
        return this.node.textContent + (this.dom.newLined ? "\n" : "");
      if (typeof text === "function") {
        this.clear().build(true);
        text.call(this, this);
        this.build(false);
      } else {
        this.plain(text);
      }
      return this;
    }
  }
  extend(Tspan, textable);
  registerMethods({
    Tspan: {
      tspan: wrapWithAttrCheck(function(text = "") {
        const tspan = new Tspan();
        if (!this._build) {
          this.clear();
        }
        return this.put(tspan).text(text);
      })
    },
    Text: {
      newLine: function(text = "") {
        return this.tspan(text).newLine();
      }
    }
  });
  register(Tspan, "Tspan");
  class Circle extends Shape {
    constructor(node, attrs2 = node) {
      super(nodeOrNew("circle", node), attrs2);
    }
    radius(r) {
      return this.attr("r", r);
    }
    // Radius x value
    rx(rx2) {
      return this.attr("r", rx2);
    }
    // Alias radius x value
    ry(ry2) {
      return this.rx(ry2);
    }
    size(size2) {
      return this.radius(new SVGNumber(size2).divide(2));
    }
  }
  extend(Circle, {
    x: x$3,
    y: y$3,
    cx: cx$1,
    cy: cy$1,
    width: width$2,
    height: height$2
  });
  registerMethods({
    Container: {
      // Create circle element
      circle: wrapWithAttrCheck(function(size2 = 0) {
        return this.put(new Circle()).size(size2).move(0, 0);
      })
    }
  });
  register(Circle, "Circle");
  class ClipPath extends Container {
    constructor(node, attrs2 = node) {
      super(nodeOrNew("clipPath", node), attrs2);
    }
    // Unclip all clipped elements and remove itself
    remove() {
      this.targets().forEach(function(el) {
        el.unclip();
      });
      return super.remove();
    }
    targets() {
      return baseFind("svg [clip-path*=" + this.id() + "]");
    }
  }
  registerMethods({
    Container: {
      // Create clipping element
      clip: wrapWithAttrCheck(function() {
        return this.defs().put(new ClipPath());
      })
    },
    Element: {
      // Distribute clipPath to svg element
      clipper() {
        return this.reference("clip-path");
      },
      clipWith(element2) {
        const clipper = element2 instanceof ClipPath ? element2 : this.parent().clip().add(element2);
        return this.attr("clip-path", "url(#" + clipper.id() + ")");
      },
      // Unclip element
      unclip() {
        return this.attr("clip-path", null);
      }
    }
  });
  register(ClipPath, "ClipPath");
  class ForeignObject extends Element {
    constructor(node, attrs2 = node) {
      super(nodeOrNew("foreignObject", node), attrs2);
    }
  }
  registerMethods({
    Container: {
      foreignObject: wrapWithAttrCheck(function(width2, height2) {
        return this.put(new ForeignObject()).size(width2, height2);
      })
    }
  });
  register(ForeignObject, "ForeignObject");
  function dmove(dx2, dy2) {
    this.children().forEach((child, i) => {
      let bbox2;
      try {
        bbox2 = child.bbox();
      } catch (e) {
        return;
      }
      const m = new Matrix(child);
      const matrix = m.translate(dx2, dy2).transform(m.inverse());
      const p = new Point(bbox2.x, bbox2.y).transform(matrix);
      child.move(p.x, p.y);
    });
    return this;
  }
  function dx(dx2) {
    return this.dmove(dx2, 0);
  }
  function dy(dy2) {
    return this.dmove(0, dy2);
  }
  function height(height2, box = this.bbox()) {
    if (height2 == null)
      return box.height;
    return this.size(box.width, height2, box);
  }
  function move(x2 = 0, y2 = 0, box = this.bbox()) {
    const dx2 = x2 - box.x;
    const dy2 = y2 - box.y;
    return this.dmove(dx2, dy2);
  }
  function size(width2, height2, box = this.bbox()) {
    const p = proportionalSize(this, width2, height2, box);
    const scaleX = p.width / box.width;
    const scaleY = p.height / box.height;
    this.children().forEach((child, i) => {
      const o = new Point(box).transform(new Matrix(child).inverse());
      child.scale(scaleX, scaleY, o.x, o.y);
    });
    return this;
  }
  function width(width2, box = this.bbox()) {
    if (width2 == null)
      return box.width;
    return this.size(width2, box.height, box);
  }
  function x(x2, box = this.bbox()) {
    if (x2 == null)
      return box.x;
    return this.move(x2, box.y, box);
  }
  function y(y2, box = this.bbox()) {
    if (y2 == null)
      return box.y;
    return this.move(box.x, y2, box);
  }
  var containerGeometry = {
    __proto__: null,
    dmove,
    dx,
    dy,
    height,
    move,
    size,
    width,
    x,
    y
  };
  class G extends Container {
    constructor(node, attrs2 = node) {
      super(nodeOrNew("g", node), attrs2);
    }
  }
  extend(G, containerGeometry);
  registerMethods({
    Container: {
      // Create a group element
      group: wrapWithAttrCheck(function() {
        return this.put(new G());
      })
    }
  });
  register(G, "G");
  class A extends Container {
    constructor(node, attrs2 = node) {
      super(nodeOrNew("a", node), attrs2);
    }
    // Link target attribute
    target(target) {
      return this.attr("target", target);
    }
    // Link url
    to(url) {
      return this.attr("href", url, xlink);
    }
  }
  extend(A, containerGeometry);
  registerMethods({
    Container: {
      // Create a hyperlink element
      link: wrapWithAttrCheck(function(url) {
        return this.put(new A()).to(url);
      })
    },
    Element: {
      unlink() {
        const link = this.linker();
        if (!link)
          return this;
        const parent = link.parent();
        if (!parent) {
          return this.remove();
        }
        const index = parent.index(link);
        parent.add(this, index);
        link.remove();
        return this;
      },
      linkTo(url) {
        let link = this.linker();
        if (!link) {
          link = new A();
          this.wrap(link);
        }
        if (typeof url === "function") {
          url.call(link, link);
        } else {
          link.to(url);
        }
        return this;
      },
      linker() {
        const link = this.parent();
        if (link && link.node.nodeName.toLowerCase() === "a") {
          return link;
        }
        return null;
      }
    }
  });
  register(A, "A");
  class Mask extends Container {
    // Initialize node
    constructor(node, attrs2 = node) {
      super(nodeOrNew("mask", node), attrs2);
    }
    // Unmask all masked elements and remove itself
    remove() {
      this.targets().forEach(function(el) {
        el.unmask();
      });
      return super.remove();
    }
    targets() {
      return baseFind("svg [mask*=" + this.id() + "]");
    }
  }
  registerMethods({
    Container: {
      mask: wrapWithAttrCheck(function() {
        return this.defs().put(new Mask());
      })
    },
    Element: {
      // Distribute mask to svg element
      masker() {
        return this.reference("mask");
      },
      maskWith(element2) {
        const masker = element2 instanceof Mask ? element2 : this.parent().mask().add(element2);
        return this.attr("mask", "url(#" + masker.id() + ")");
      },
      // Unmask element
      unmask() {
        return this.attr("mask", null);
      }
    }
  });
  register(Mask, "Mask");
  class Stop extends Element {
    constructor(node, attrs2 = node) {
      super(nodeOrNew("stop", node), attrs2);
    }
    // add color stops
    update(o) {
      if (typeof o === "number" || o instanceof SVGNumber) {
        o = {
          offset: arguments[0],
          color: arguments[1],
          opacity: arguments[2]
        };
      }
      if (o.opacity != null)
        this.attr("stop-opacity", o.opacity);
      if (o.color != null)
        this.attr("stop-color", o.color);
      if (o.offset != null)
        this.attr("offset", new SVGNumber(o.offset));
      return this;
    }
  }
  registerMethods({
    Gradient: {
      // Add a color stop
      stop: function(offset, color, opacity) {
        return this.put(new Stop()).update(offset, color, opacity);
      }
    }
  });
  register(Stop, "Stop");
  function cssRule(selector, rule) {
    if (!selector)
      return "";
    if (!rule)
      return selector;
    let ret = selector + "{";
    for (const i in rule) {
      ret += unCamelCase(i) + ":" + rule[i] + ";";
    }
    ret += "}";
    return ret;
  }
  class Style extends Element {
    constructor(node, attrs2 = node) {
      super(nodeOrNew("style", node), attrs2);
    }
    addText(w = "") {
      this.node.textContent += w;
      return this;
    }
    font(name, src, params = {}) {
      return this.rule("@font-face", {
        fontFamily: name,
        src,
        ...params
      });
    }
    rule(selector, obj) {
      return this.addText(cssRule(selector, obj));
    }
  }
  registerMethods("Dom", {
    style(selector, obj) {
      return this.put(new Style()).rule(selector, obj);
    },
    fontface(name, src, params) {
      return this.put(new Style()).font(name, src, params);
    }
  });
  register(Style, "Style");
  class TextPath extends Text {
    // Initialize node
    constructor(node, attrs2 = node) {
      super(nodeOrNew("textPath", node), attrs2);
    }
    // return the array of the path track element
    array() {
      const track = this.track();
      return track ? track.array() : null;
    }
    // Plot path if any
    plot(d) {
      const track = this.track();
      let pathArray = null;
      if (track) {
        pathArray = track.plot(d);
      }
      return d == null ? pathArray : this;
    }
    // Get the path element
    track() {
      return this.reference("href");
    }
  }
  registerMethods({
    Container: {
      textPath: wrapWithAttrCheck(function(text, path) {
        if (!(text instanceof Text)) {
          text = this.text(text);
        }
        return text.path(path);
      })
    },
    Text: {
      // Create path for text to run on
      path: wrapWithAttrCheck(function(track, importNodes = true) {
        const textPath = new TextPath();
        if (!(track instanceof Path)) {
          track = this.defs().path(track);
        }
        textPath.attr("href", "#" + track, xlink);
        let node;
        if (importNodes) {
          while (node = this.node.firstChild) {
            textPath.node.appendChild(node);
          }
        }
        return this.put(textPath);
      }),
      // Get the textPath children
      textPath() {
        return this.findOne("textPath");
      }
    },
    Path: {
      // creates a textPath from this path
      text: wrapWithAttrCheck(function(text) {
        if (!(text instanceof Text)) {
          text = new Text().addTo(this.parent()).text(text);
        }
        return text.path(this);
      }),
      targets() {
        return baseFind("svg textPath").filter((node) => {
          return (node.attr("href") || "").includes(this.id());
        });
      }
    }
  });
  TextPath.prototype.MorphArray = PathArray;
  register(TextPath, "TextPath");
  class Use extends Shape {
    constructor(node, attrs2 = node) {
      super(nodeOrNew("use", node), attrs2);
    }
    // Use element as a reference
    use(element2, file) {
      return this.attr("href", (file || "") + "#" + element2, xlink);
    }
  }
  registerMethods({
    Container: {
      // Create a use element
      use: wrapWithAttrCheck(function(element2, file) {
        return this.put(new Use()).use(element2, file);
      })
    }
  });
  register(Use, "Use");
  const SVG = makeInstance;
  extend([Svg, Symbol$1, Image, Pattern, Marker], getMethodsFor("viewbox"));
  extend([Line, Polyline, Polygon, Path], getMethodsFor("marker"));
  extend(Text, getMethodsFor("Text"));
  extend(Path, getMethodsFor("Path"));
  extend(Defs, getMethodsFor("Defs"));
  extend([Text, Tspan], getMethodsFor("Tspan"));
  extend([Rect, Ellipse, Gradient, Runner], getMethodsFor("radius"));
  extend(EventTarget, getMethodsFor("EventTarget"));
  extend(Dom, getMethodsFor("Dom"));
  extend(Element, getMethodsFor("Element"));
  extend(Shape, getMethodsFor("Shape"));
  extend([Container, Fragment], getMethodsFor("Container"));
  extend(Gradient, getMethodsFor("Gradient"));
  extend(Runner, getMethodsFor("Runner"));
  List.extend(getMethodNames());
  registerMorphableType([SVGNumber, Color, Box, Matrix, SVGArray, PointArray, PathArray, Point]);
  makeMorphable();
  class ChordBox {
    // sel can be a selector or an element.
    constructor(sel, params) {
      this.sel = sel;
      this.params = {
        ...{
          numStrings: 6,
          numFrets: 5,
          x: 0,
          y: 0,
          width: 100,
          height: 120,
          strokeWidth: 1,
          showTuning: true,
          defaultColor: "#666",
          bgColor: "#fff",
          labelColor: "#fff",
          fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"',
          fontSize: void 0,
          fontStyle: "light",
          fontWeight: "100",
          labelWeight: "100"
        },
        ...params
      };
      ["bridgeColor", "stringColor", "fretColor", "strokeColor", "textColor"].forEach((param) => {
        this.params[param] = this.params[param] || this.params.defaultColor;
      });
      ["stringWidth", "fretWidth"].forEach((param) => {
        this.params[param] = this.params[param] || this.params.strokeWidth;
      });
      this.canvas = SVG().addTo(sel).size(this.params.width, this.params.height);
      this.width = this.params.width * 0.75;
      this.height = this.params.height * 0.75;
      this.x = this.params.x + this.params.width * 0.15;
      this.y = this.params.y + this.params.height * 0.15;
      this.numStrings = this.params.numStrings;
      this.numFrets = this.params.numFrets;
      this.spacing = this.width / this.numStrings;
      this.fretSpacing = this.height / (this.numFrets + 2);
      this.x += this.spacing / 2;
      this.y += this.fretSpacing;
      this.metrics = {
        circleRadius: this.width / 20,
        barreRadius: this.width / 25,
        fontSize: this.params.fontSize || Math.ceil(this.width / 8),
        barShiftX: this.width / 28,
        bridgeStrokeWidth: Math.ceil(this.height / 36)
      };
      this.position = 0;
      this.positionText = 0;
      this.chord = [];
      this.bars = [];
      this.tuning = ["E", "A", "D", "G", "B", "E"];
    }
    setNumFrets(numFrets) {
      this.numFrets = numFrets;
      this.fretSpacing = this.height / (this.numFrets + 1);
      return this;
    }
    setPositionText(position2) {
      this.positionText = position2;
      return this;
    }
    drawText(x2, y2, msg, attrs2) {
      const textAttrs = {
        ...{
          family: this.params.fontFamily,
          size: this.metrics.fontSize,
          style: this.params.fontStyle,
          weight: this.params.fontWeight
        },
        ...attrs2
      };
      const text = this.canvas.text(`${msg}`).stroke(this.params.textColor).fill(this.params.textColor).font(textAttrs);
      return text.move(x2 - text.length() / 2, y2);
    }
    drawLine(x2, y2, newX, newY) {
      return this.canvas.line(0, 0, newX - x2, newY - y2).move(x2, y2);
    }
    draw({
      chord,
      position: position2,
      barres,
      positionText,
      tuning
    }) {
      this.chord = chord;
      this.position = position2 || 0;
      this.positionText = positionText || 0;
      this.barres = barres || [];
      this.tuning = tuning || ["E", "A", "D", "G", "B", "E"];
      if (this.tuning.length === 0) {
        this.fretSpacing = this.height / (this.numFrets + 1);
      }
      const { spacing } = this;
      const { fretSpacing } = this;
      if (this.position <= 1) {
        const fromX = this.x;
        const fromY = this.y - this.metrics.bridgeStrokeWidth;
        this.canvas.rect(this.x + spacing * (this.numStrings - 1) - fromX, this.y - fromY).move(fromX, fromY).stroke({ width: 0 }).fill(this.params.bridgeColor);
      } else {
        this.drawText(this.x - this.spacing / 2 - this.spacing * 0.1, this.y + this.fretSpacing * this.positionText, this.position);
      }
      for (let i = 0; i < this.numStrings; i += 1) {
        this.drawLine(this.x + spacing * i, this.y, this.x + spacing * i, this.y + fretSpacing * this.numFrets).stroke({
          width: this.params.stringWidth,
          color: this.params.stringColor
        });
      }
      for (let i = 0; i < this.numFrets + 1; i += 1) {
        this.drawLine(this.x, this.y + fretSpacing * i, this.x + spacing * (this.numStrings - 1), this.y + fretSpacing * i).stroke({
          width: this.params.fretWidth,
          color: this.params.fretColor
        });
      }
      if (this.params.showTuning && this.tuning.length !== 0) {
        for (let i = 0; i < Math.min(this.numStrings, this.tuning.length); i += 1) {
          this.drawText(this.x + this.spacing * i, this.y + this.numFrets * this.fretSpacing + this.fretSpacing / 12, this.tuning[i]);
        }
      }
      for (let i = 0; i < this.chord.length; i += 1) {
        this.lightUp({
          string: this.chord[i][0],
          fret: this.chord[i][1],
          label: this.chord.length > 2 ? this.chord[i][2] : void 0
        });
      }
      for (let i = 0; i < this.barres.length; i += 1) {
        this.lightBar(this.barres[i].fromString, this.barres[i].toString, this.barres[i].fret);
      }
    }
    lightUp({ string: string2, fret, label }) {
      const stringNum = this.numStrings - string2;
      const shiftPosition = this.position === 1 && this.positionText === 1 ? this.positionText : 0;
      const mute = fret === "x";
      const fretNum = fret === "x" ? 0 : fret - shiftPosition;
      const x2 = this.x + this.spacing * stringNum;
      let y2 = this.y + this.fretSpacing * fretNum;
      if (fretNum === 0) {
        y2 -= this.metrics.bridgeStrokeWidth;
      }
      if (!mute) {
        this.canvas.circle().move(x2, y2 - this.fretSpacing / 2).radius(this.metrics.circleRadius).stroke({ color: this.params.strokeColor, width: this.params.strokeWidth }).fill(fretNum > 0 ? this.params.strokeColor : this.params.bgColor);
      } else {
        this.drawText(x2, y2 - this.fretSpacing, "X");
      }
      if (label) {
        const fontSize = this.metrics.fontSize * 0.55;
        const textYShift = fontSize * 0.66;
        this.drawText(x2, y2 - this.fretSpacing / 2 - textYShift, label, {
          weight: this.params.labelWeight,
          size: fontSize
        }).stroke({
          width: 0.7,
          color: fretNum !== 0 ? this.params.labelColor : this.params.strokeColor
        }).fill(fretNum !== 0 ? this.params.labelColor : this.params.strokeColor);
      }
      return this;
    }
    lightBar(stringFrom, stringTo, theFretNum) {
      let fretNum = theFretNum;
      if (this.position === 1 && this.positionText === 1) {
        fretNum -= this.positionText;
      }
      const stringFromNum = this.numStrings - stringFrom;
      const stringToNum = this.numStrings - stringTo;
      const x2 = this.x + this.spacing * stringFromNum - this.metrics.barShiftX;
      const xTo = this.x + this.spacing * stringToNum + this.metrics.barShiftX;
      const y2 = this.y + this.fretSpacing * (fretNum - 1) + this.fretSpacing / 4;
      const yTo = this.y + this.fretSpacing * (fretNum - 1) + this.fretSpacing / 4 * 3;
      this.canvas.rect(xTo - x2, yTo - y2).move(x2, y2).radius(this.metrics.barreRadius).fill(this.params.strokeColor);
      return this;
    }
  }
  const _hoisted_1$a = {
    key: 0,
    class: "chord-container"
  };
  const _hoisted_2$9 = { class: "chord-name" };
  const _hoisted_3$4 = ["chord-name"];
  const _sfc_main$b = {
    __name: "ChordChart",
    props: {
      chord: String
    },
    setup(__props) {
      const props = __props;
      const chordRef = vue.ref(void 0);
      const chordShapes = getChordShapes();
      const isChordExist = vue.ref(true);
      vue.onMounted(() => {
        var _a;
        const formattedChordKey = convertChordName(props.chord);
        const chordShape = chordShapes[formattedChordKey];
        if (!chordShape) {
          return isChordExist.value = false;
        }
        const chordObject = {
          ...chordShape,
          // position: chordShape.position,
          // positionText: chordShape.position_text,
          barres: (_a = chordShape.bars) == null ? void 0 : _a.map((barre) => {
            return {
              ...barre,
              fromString: barre.from_string,
              toString: barre.to_string
            };
          }),
          chord: chordShape.chord.map(([stringNum, fretNum]) => {
            const raw = [stringNum, fretNum];
            if (isNaN(+fretNum)) {
              return raw;
            }
            let newFretNum = fretNum;
            newFretNum += chordShape.position || 0;
            newFretNum -= chordShape.position_text || 0;
            return [stringNum, newFretNum];
          })
        };
        vue.nextTick(() => {
          const width2 = chordRef.value.clientWidth;
          const chordBoxSelector = `.chord-chart[chord-name="${props.chord}"]`;
          const chordBox = new ChordBox(chordBoxSelector, {
            width: width2,
            height: width2 * 1.25,
            circleRadius: 5,
            numStrings: 6,
            numFrets: 5,
            showTuning: false,
            defaultColor: "#444",
            bgColor: "transparent"
          });
          chordBox.draw(chordObject);
        });
      });
      return (_ctx, _cache) => {
        return isChordExist.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$a, [
          vue.createElementVNode("div", _hoisted_2$9, vue.toDisplayString(props.chord), 1),
          vue.createElementVNode("div", {
            class: "chord-chart",
            "chord-name": props.chord,
            ref_key: "chordRef",
            ref: chordRef
          }, null, 8, _hoisted_3$4)
        ])) : vue.createCommentVNode("", true);
      };
    }
  };
  const ChordChart = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["__scopeId", "data-v-1eb5094e"]]);
  const _withScopeId$1 = (n) => (vue.pushScopeId("data-v-84de48ae"), n = n(), vue.popScopeId(), n);
  const _hoisted_1$9 = { id: "plus91-chord-popup" };
  const _hoisted_2$8 = { class: "banner" };
  const _hoisted_3$3 = /* @__PURE__ */ _withScopeId$1(() => /* @__PURE__ */ vue.createElementVNode("section", null, "此處的和弦圖示僅供參考,尤其把位部分較常出現錯誤,請注意。", -1));
  const _hoisted_4$2 = { class: "chord-popup-container" };
  const _sfc_main$a = {
    __name: "ChordPopup",
    setup(__props) {
      const store = useStore();
      const chordList = vue.ref([]);
      vue.watch(store.isPopupShow, () => {
        if (!store.isPopupShow.chord) {
          return;
        }
        chordList.value = getChordList();
      });
      return (_ctx, _cache) => {
        return vue.openBlock(), vue.createBlock(vue.Transition, { name: "slide-and-fade" }, {
          default: vue.withCtx(() => [
            vue.withDirectives(vue.createElementVNode("div", _hoisted_1$9, [
              vue.createElementVNode("div", _hoisted_2$8, [
                vue.createVNode(BootstrapIcon, {
                  icon: "info-circle-fill",
                  color: "inherit",
                  size: "inherit"
                }),
                _hoisted_3$3
              ]),
              vue.createElementVNode("div", _hoisted_4$2, [
                (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(chordList.value, (chord) => {
                  return vue.openBlock(), vue.createBlock(ChordChart, {
                    key: `${chord}_${( new Date()).getTime()}`,
                    chord
                  }, null, 8, ["chord"]);
                }), 128))
              ])
            ], 512), [
              [vue.vShow, vue.unref(store).isPopupShow.chord]
            ])
          ]),
          _: 1
        });
      };
    }
  };
  const ChordPopup = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["__scopeId", "data-v-84de48ae"]]);
  const _hoisted_1$8 = { id: "plus91-font-popup" };
  const _hoisted_2$7 = { class: "font-popup-container" };
  const _sfc_main$9 = {
    __name: "FontSizePopup",
    setup(__props) {
      const store = useStore();
      const getFontSize = vue.computed(() => {
        return store.originalFontSize + store.fontSizeDelta;
      });
      return (_ctx, _cache) => {
        return vue.openBlock(), vue.createBlock(vue.Transition, { name: "slide-and-fade" }, {
          default: vue.withCtx(() => [
            vue.withDirectives(vue.createElementVNode("div", _hoisted_1$8, [
              vue.createElementVNode("div", _hoisted_2$7, [
                vue.createVNode(AdjustWidget, {
                  "onclick-left": () => {
                    vue.unref(store).fontSizeDelta--;
                  },
                  "onclick-middle": () => {
                    vue.unref(store).fontSizeDelta = 0;
                  },
                  "onclick-right": () => {
                    vue.unref(store).fontSizeDelta++;
                  },
                  "disabled-left": getFontSize.value <= 8,
                  "disabled-right": getFontSize.value >= 30
                }, {
                  default: vue.withCtx(() => [
                    vue.createTextVNode(vue.toDisplayString(getFontSize.value) + "px ", 1)
                  ]),
                  _: 1
                }, 8, ["onclick-left", "onclick-middle", "onclick-right", "disabled-left", "disabled-right"])
              ])
            ], 512), [
              [vue.vShow, vue.unref(store).isPopupShow.font]
            ])
          ]),
          _: 1
        });
      };
    }
  };
  const FontSizePopup = /* @__PURE__ */ _export_sfc(_sfc_main$9, [["__scopeId", "data-v-eff17405"]]);
  const _withScopeId = (n) => (vue.pushScopeId("data-v-e329f5af"), n = n(), vue.popScopeId(), n);
  const _hoisted_1$7 = { id: "plus91-settings-popup" };
  const _hoisted_2$6 = { class: "settings-popup-container" };
  const _hoisted_3$2 = { class: "setting-item" };
  const _hoisted_4$1 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("span", null, "深色模式", -1));
  const _hoisted_5 = { class: "setting-item" };
  const _hoisted_6 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("span", null, "協助測試雲端備份樂譜功能", -1));
  const _sfc_main$8 = {
    __name: "SettingsPopup",
    setup(__props) {
      const store = useStore();
      return (_ctx, _cache) => {
        return vue.openBlock(), vue.createBlock(vue.Transition, { name: "slide-and-fade" }, {
          default: vue.withCtx(() => [
            vue.withDirectives(vue.createElementVNode("div", _hoisted_1$7, [
              vue.createElementVNode("div", _hoisted_2$6, [
                vue.createElementVNode("label", _hoisted_3$2, [
                  _hoisted_4$1,
                  vue.withDirectives(vue.createElementVNode("input", {
                    type: "checkbox",
                    "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => vue.unref(store).isDarkMode = $event)
                  }, null, 512), [
                    [vue.vModelCheckbox, vue.unref(store).isDarkMode]
                  ])
                ]),
                vue.createElementVNode("label", _hoisted_5, [
                  _hoisted_6,
                  vue.withDirectives(vue.createElementVNode("input", {
                    type: "checkbox",
                    "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => vue.unref(store).agreeToArchiveSheet = $event)
                  }, null, 512), [
                    [vue.vModelCheckbox, vue.unref(store).agreeToArchiveSheet]
                  ])
                ])
              ])
            ], 512), [
              [vue.vShow, vue.unref(store).isPopupShow.settings]
            ])
          ]),
          _: 1
        });
      };
    }
  };
  const SettingsPopup = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["__scopeId", "data-v-e329f5af"]]);
  const _hoisted_1$6 = { class: "icon-button" };
  const _hoisted_2$5 = { class: "button-text" };
  const _sfc_main$7 = {
    __name: "MenuButton",
    props: {
      icon: String,
      name: String,
      color: String
    },
    setup(__props) {
      vue.useCssVars((_ctx) => ({
        "9047bc34": __props.color
      }));
      const props = __props;
      return (_ctx, _cache) => {
        return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$6, [
          vue.createVNode(ToolbarIcon, {
            icon: props.icon,
            color: props.color
          }, null, 8, ["icon", "color"]),
          vue.createElementVNode("div", _hoisted_2$5, vue.toDisplayString(props.name), 1)
        ]);
      };
    }
  };
  const MenuButton = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__scopeId", "data-v-e9902592"]]);
  const _hoisted_1$5 = { id: "plus91-menu-popup" };
  const _hoisted_2$4 = { class: "menu-popup-container" };
  const _sfc_main$6 = {
    __name: "MenuPopup",
    setup(__props) {
      const store = useStore();
      const searchOnYoutube = () => {
        const chordSheetDocument = new ChordSheetDocument();
        const title = chordSheetDocument.getTitle();
        const artist = chordSheetDocument.getSinger();
        const url = `https://www.youtube.com/results?search_query=${title}+${artist}`;
        window.open(url, "_blank").focus();
      };
      const goToGithubPage = () => {
        const url = "https://github.com/DonkeyBear/91Plus/blob/main/README.md";
        window.open(url, "_blank").focus();
      };
      return (_ctx, _cache) => {
        return vue.openBlock(), vue.createBlock(vue.Transition, { name: "slide-and-fade" }, {
          default: vue.withCtx(() => [
            vue.withDirectives(vue.createElementVNode("div", _hoisted_1$5, [
              vue.createElementVNode("div", _hoisted_2$4, [
                vue.createVNode(MenuButton, {
                  icon: "keyboard",
                  name: "快捷鍵",
                  color: "#555",
                  onClick: _cache[0] || (_cache[0] = () => {
                    vue.unref(store).togglePopup("hotkey");
                  })
                }),
                vue.createVNode(MenuButton, {
                  icon: "youtube",
                  name: "搜尋 YouTube",
                  color: "#555",
                  onClick: searchOnYoutube
                }),
                vue.createVNode(MenuButton, {
                  icon: "github",
                  name: "關於 91 Plus",
                  color: "#555",
                  onClick: goToGithubPage
                })
              ])
            ], 512), [
              [vue.vShow, vue.unref(store).isPopupShow.menu]
            ])
          ]),
          _: 1
        });
      };
    }
  };
  const MenuPopup = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["__scopeId", "data-v-d041b049"]]);
  const _hoisted_1$4 = { class: "hotkey-item" };
  const _hoisted_2$3 = {
    key: 0,
    class: "hotkeys"
  };
  const _hoisted_3$1 = {
    key: 1,
    class: "hr"
  };
  const _sfc_main$5 = {
    __name: "HotkeyItem",
    props: {
      hotkey: {
        type: String,
        required: false
      },
      desc: String
    },
    setup(__props) {
      const props = __props;
      const hotkeyList = props.hotkey.split(" ");
      return (_ctx, _cache) => {
        return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$4, [
          vue.createElementVNode("div", {
            class: vue.normalizeClass(["desc", { "title": !__props.hotkey }])
          }, vue.toDisplayString(__props.desc), 3),
          __props.hotkey ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_2$3, [
            (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(vue.unref(hotkeyList), (key) => {
              return vue.openBlock(), vue.createElementBlock("kbd", null, vue.toDisplayString(key), 1);
            }), 256))
          ])) : (vue.openBlock(), vue.createElementBlock("div", _hoisted_3$1))
        ]);
      };
    }
  };
  const HotkeyItem = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__scopeId", "data-v-9f1c2e95"]]);
  const hotkeysLeft = [
    {
      hotkey: "空白鍵",
      desc: "開啟 / 關閉功能選單"
    },
    {
      hotkey: "ESC",
      desc: "關閉功能選單"
    },
    {
      hotkey: "/",
      desc: "切換至搜尋框"
    }
  ];
  const hotkeysRight = [
    {
      hotkey: "",
      desc: "移調選單開啟時"
    },
    {
      hotkey: "← →",
      desc: "移調"
    },
    {
      hotkey: "↓",
      desc: "移回初始調"
    },
    {
      hotkey: "",
      desc: "在搜尋框內"
    },
    {
      hotkey: "Enter",
      desc: "搜尋"
    },
    {
      hotkey: "ESC",
      desc: "跳出搜尋框"
    }
  ];
  const hotkeyData = {
    hotkeysLeft,
    hotkeysRight
  };
  const _hoisted_1$3 = { id: "plus91-hotkey-popup" };
  const _hoisted_2$2 = { class: "hotkey-popup-container" };
  const _hoisted_3 = { class: "left-part" };
  const _hoisted_4 = { class: "right-part" };
  const _sfc_main$4 = {
    __name: "HotkeyPopup",
    setup(__props) {
      const store = useStore();
      return (_ctx, _cache) => {
        return vue.openBlock(), vue.createBlock(vue.Transition, { name: "slide-and-fade" }, {
          default: vue.withCtx(() => [
            vue.withDirectives(vue.createElementVNode("div", _hoisted_1$3, [
              vue.createElementVNode("div", _hoisted_2$2, [
                vue.createElementVNode("section", _hoisted_3, [
                  (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(vue.unref(hotkeyData).hotkeysLeft, (item) => {
                    return vue.openBlock(), vue.createBlock(HotkeyItem, {
                      hotkey: item.hotkey,
                      desc: item.desc
                    }, null, 8, ["hotkey", "desc"]);
                  }), 256))
                ]),
                vue.createElementVNode("section", _hoisted_4, [
                  (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(vue.unref(hotkeyData).hotkeysRight, (item) => {
                    return vue.openBlock(), vue.createBlock(HotkeyItem, {
                      hotkey: item.hotkey,
                      desc: item.desc
                    }, null, 8, ["hotkey", "desc"]);
                  }), 256))
                ])
              ])
            ], 512), [
              [vue.vShow, vue.unref(store).isPopupShow.hotkey]
            ])
          ]),
          _: 1
        });
      };
    }
  };
  const HotkeyPopup = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-a88e7568"]]);
  const _hoisted_1$2 = { id: "plus91-footer" };
  const _hoisted_2$1 = { class: "footer-container" };
  const _sfc_main$3 = {
    __name: "Footer",
    props: {
      active: Boolean
    },
    setup(__props) {
      const store = useStore();
      return (_ctx, _cache) => {
        return vue.openBlock(), vue.createBlock(vue.Transition, { name: "slide" }, {
          default: vue.withCtx(() => [
            vue.withDirectives(vue.createElementVNode("div", _hoisted_1$2, [
              vue.createElementVNode("div", _hoisted_2$1, [
                vue.createVNode(ToolbarIcon, {
                  icon: "music-note-beamed",
                  stroke: ".05rem",
                  active: vue.unref(store).isPopupShow.sheet,
                  onClick: _cache[0] || (_cache[0] = ($event) => vue.unref(store).togglePopup("sheet"))
                }, null, 8, ["active"]),
                vue.createVNode(ToolbarIcon, {
                  icon: "table",
                  active: vue.unref(store).isPopupShow.chord,
                  onClick: _cache[1] || (_cache[1] = ($event) => vue.unref(store).togglePopup("chord"))
                }, null, 8, ["active"]),
                vue.createVNode(ToolbarIcon, {
                  icon: "type",
                  stroke: ".05rem",
                  active: vue.unref(store).isPopupShow.font,
                  onClick: _cache[2] || (_cache[2] = ($event) => vue.unref(store).togglePopup("font"))
                }, null, 8, ["active"]),
                vue.createVNode(ToolbarIcon, {
                  icon: "gear-wide-connected",
                  active: vue.unref(store).isPopupShow.settings,
                  onClick: _cache[3] || (_cache[3] = ($event) => vue.unref(store).togglePopup("settings"))
                }, null, 8, ["active"]),
                vue.createVNode(ToolbarIcon, {
                  icon: "list",
                  stroke: ".05rem",
                  active: vue.unref(store).isPopupShow.menu,
                  onClick: _cache[4] || (_cache[4] = ($event) => vue.unref(store).togglePopup("menu"))
                }, null, 8, ["active"]),
                vue.createVNode(SheetPopup),
                vue.createVNode(ChordPopup),
                vue.createVNode(FontSizePopup),
                vue.createVNode(SettingsPopup),
                vue.createVNode(MenuPopup),
                vue.createVNode(HotkeyPopup)
              ])
            ], 512), [
              [vue.vShow, __props.active]
            ])
          ]),
          _: 1
        });
      };
    }
  };
  const Footer = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-a29224c8"]]);
  const _hoisted_1$1 = { id: "plus91-header" };
  const _hoisted_2 = { class: "header-container" };
  const _sfc_main$2 = {
    __name: "Header",
    props: {
      active: Boolean
    },
    setup(__props) {
      const searchText = vue.ref("");
      const search = () => {
        if (!searchText.value) {
          return;
        }
        const url = `https://www.91pu.com.tw/plus/search.php?keyword=${searchText.value}`;
        window.open(url, "_blank").focus();
      };
      const backToPreviousPage = () => {
        history.back();
      };
      return (_ctx, _cache) => {
        return vue.openBlock(), vue.createBlock(vue.Transition, { name: "slide" }, {
          default: vue.withCtx(() => [
            vue.withDirectives(vue.createElementVNode("div", _hoisted_1$1, [
              vue.createElementVNode("div", _hoisted_2, [
                vue.createVNode(ToolbarIcon, {
                  icon: "chevron-left",
                  stroke: ".04rem",
                  onClick: backToPreviousPage
                }),
                vue.withDirectives(vue.createElementVNode("input", {
                  type: "text",
                  placeholder: "91 Plus",
                  "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => searchText.value = $event),
                  onKeydown: [
                    vue.withKeys(search, ["enter"]),
                    _cache[1] || (_cache[1] = vue.withKeys((event) => {
                      event.target.blur();
                    }, ["esc"]))
                  ]
                }, null, 544), [
                  [
                    vue.vModelText,
                    searchText.value,
                    void 0,
                    { trim: true }
                  ]
                ]),
                vue.createVNode(ToolbarIcon, {
                  icon: "search",
                  stroke: ".03rem",
                  onClick: _cache[2] || (_cache[2] = ($event) => search())
                })
              ])
            ], 512), [
              [vue.vShow, __props.active]
            ])
          ]),
          _: 1
        });
      };
    }
  };
  const Header = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-265bcfd2"]]);
  const _hoisted_1 = { id: "dark-mode-overlay" };
  const _sfc_main$1 = {
    __name: "DarkModeOverlay",
    props: {
      active: Boolean
    },
    setup(__props) {
      return (_ctx, _cache) => {
        return vue.openBlock(), vue.createBlock(vue.Transition, { name: "fade" }, {
          default: vue.withCtx(() => [
            vue.withDirectives(vue.createElementVNode("div", _hoisted_1, null, 512), [
              [vue.vShow, __props.active]
            ])
          ]),
          _: 1
        });
      };
    }
  };
  const DarkModeOverlay = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-e9c78cc3"]]);
  const _sfc_main = {
    __name: "App",
    setup(__props) {
      const store = useStore();
      return (_ctx, _cache) => {
        return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [
          vue.createVNode(TriggerOverlay, {
            onClick: vue.unref(store).toggleToolbars
          }, null, 8, ["onClick"]),
          vue.createVNode(Header, {
            active: vue.unref(store).isToolbarsShow
          }, null, 8, ["active"]),
          vue.createVNode(Footer, {
            active: vue.unref(store).isToolbarsShow
          }, null, 8, ["active"]),
          vue.createVNode(DarkModeOverlay, {
            active: vue.unref(store).isDarkMode
          }, null, 8, ["active"])
        ], 64);
      };
    }
  };
  function init() {
    redirect();
    injectGtag();
    initMutationObserver();
    handleEvents();
    const storeHandler = new StoreHandler().start();
    onDomReady(() => {
      changeTitle();
      storeHandler.initState();
      const store = useStore();
      if (store.agreeToArchiveSheet) {
        archiveChordSheet();
      }
    });
  }
  const pinia = createPinia();
  pinia.use(src_default);
  vue.createApp(_sfc_main).use(pinia).mount(
    (() => {
      const app = document.createElement("div");
      app.id = "vue-91plus";
      document.body.append(app);
      return app;
    })()
  );
  init();

})(Vue);