91 Plus

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

当前为 2025-01-16 提交的版本,查看 最新版本

在您安装前,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.8.4
// @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
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/zipson.min.js
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/html2canvas.min.js
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/vexchords.dev.min.js
// @grant        GM_addStyle
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        unsafeWindow
// @antifeature  tracking  使用 Google Analytics 了解使用情況
// ==/UserScript==

(e=>{if(typeof GM_addStyle=="function"){GM_addStyle(e);return}const a=document.createElement("style");a.textContent=e,document.head.append(a)})(' @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-6e52047a]{color:var(--2b53b793);font-size:var(--4bbf91d1);-webkit-text-stroke:var(--5ab9f408) var(--2b53b793)}.bi[data-v-6e52047a]:before{transition:text-shadow .2s}.bi[active=true][data-v-6e52047a]:before{text-shadow:0 0 .5rem rgb(75,156,169)}.toolbar-icon[data-v-3dbcd695]{cursor:pointer;padding:.25rem .75rem;display:flex;flex-direction:column;align-items:center;gap:.15rem}.toolbar-icon-text[data-v-3dbcd695]{color:color-mix(in srgb,var(--52bb32ad) 70%,rgba(75,156,169,.65));font-size:.5rem;letter-spacing:.15rem;margin-right:-.15rem}.adjust-widget[data-v-cb8ab81d]{display:flex}.adjust-widget .adjust-button[data-v-cb8ab81d]{border:0;border-radius:.25rem;background:transparent}.adjust-widget .adjust-button[data-v-cb8ab81d]:hover{background:rgba(0,0,0,.025)}.adjust-widget .adjust-button[data-v-cb8ab81d]:disabled{opacity:.25}.adjust-widget .adjust-button.adjust-button-middle[data-v-cb8ab81d]{flex-grow:1;color:var(--13e75dc8);font-size:calc(var(--10392328) * .75);font-weight:700}.adjust-widget .adjust-button.adjust-button-left[data-v-cb8ab81d]{padding-right:1rem}.adjust-widget .adjust-button.adjust-button-right[data-v-cb8ab81d]{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;max-height:50vh;overflow-y:scroll}#plus91-sheet-popup[data-v-f161c46c]::-webkit-scrollbar{display:none}.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-735734f6]{font-size:.5rem;font-weight:900;color:#666;text-align:center}.chord-container .chord-chart[data-v-735734f6]{margin:-.6rem 0 -.25rem}.slide-and-fade-enter-active[data-v-2210cdf0],.slide-and-fade-leave-active[data-v-2210cdf0]{transition:all .2s}.slide-and-fade-enter-from[data-v-2210cdf0],.slide-and-fade-leave-to[data-v-2210cdf0]{transform:translateY(10%);opacity:0}#plus91-chord-popup[data-v-2210cdf0]{position:absolute;left:0;right:0;bottom:100%;background:#fafafa;border:1px solid lightgray;border-radius:1rem;margin:.5rem 1rem;max-height:50vh;overflow-y:scroll;padding:1rem}#plus91-chord-popup[data-v-2210cdf0]::-webkit-scrollbar{display:none}#plus91-chord-popup .banner[data-v-2210cdf0]{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-2210cdf0]{flex-grow:1;margin-left:.5rem}#plus91-chord-popup .chord-popup-container[data-v-2210cdf0]{display:grid;grid-template-columns:repeat(6,1fr);column-gap:.5rem;padding-top:.4rem}#plus91-chord-popup.banner-only .banner[data-v-2210cdf0]{margin-bottom:0;background:rgba(246,210,102,.25);color:color-mix(in srgb,#f6d266 50%,black 35%)}#plus91-chord-popup.banner-only .chord-popup-container[data-v-2210cdf0]{padding-top:0}.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;max-height:50vh;overflow-y:scroll}#plus91-font-popup[data-v-eff17405]::-webkit-scrollbar{display:none}.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;max-height:50vh;overflow-y:scroll;padding:1rem}#plus91-settings-popup[data-v-e329f5af]::-webkit-scrollbar{display:none}#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-47af8eb5],.slide-and-fade-leave-active[data-v-47af8eb5]{transition:all .2s}.slide-and-fade-enter-from[data-v-47af8eb5],.slide-and-fade-leave-to[data-v-47af8eb5]{transform:translateY(10%);opacity:0}#plus91-menu-popup[data-v-47af8eb5]{position:absolute;left:0;right:0;bottom:100%;background:#fafafa;border:1px solid lightgray;padding:1rem 2rem;border-radius:1rem;margin:.5rem 1rem;max-height:50vh;overflow-y:scroll}#plus91-menu-popup[data-v-47af8eb5]::-webkit-scrollbar{display:none}#plus91-menu-popup .menu-popup-container[data-v-47af8eb5]{display:flex;justify-content:space-around}.hotkey-item[data-v-3c43f6cf]{display:flex;justify-content:space-between;align-items:center;padding:0 .25rem;border-radius:.25rem;height:1.4rem}.hotkey-item[data-v-3c43f6cf]:nth-child(odd){background:rgba(0,0,0,.025)}.desc.title[data-v-3c43f6cf]{font-size:.55rem;color:#999}.hotkeys[data-v-3c43f6cf]{display:flex}.hr[data-v-3c43f6cf]{display:flex;flex-grow:1;border-top:1px solid lightgray;margin-left:.25rem}kbd[data-v-3c43f6cf]{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-eb86b87c],.slide-and-fade-leave-active[data-v-eb86b87c]{transition:all .2s}.slide-and-fade-enter-from[data-v-eb86b87c],.slide-and-fade-leave-to[data-v-eb86b87c]{transform:translateY(10%);opacity:0}#plus91-hotkey-popup[data-v-eb86b87c]{position:absolute;left:0;right:0;bottom:100%;background:#fafafa;border:1px solid lightgray;padding:1rem 2rem;border-radius:1rem;margin:.5rem 1rem;max-height:50vh;overflow-y:scroll}#plus91-hotkey-popup[data-v-eb86b87c]::-webkit-scrollbar{display:none}#plus91-hotkey-popup .hotkey-popup-container[data-v-eb86b87c]{display:flex;color:#444}#plus91-hotkey-popup section[data-v-eb86b87c]{flex-grow:1;width:50%;margin:-.1rem 0}#plus91-hotkey-popup section.left-part[data-v-eb86b87c]{border-right:1px solid lightgray;margin-left:-.5rem;padding-right:.5rem}#plus91-hotkey-popup section.right-part[data-v-eb86b87c]{padding-left:.5rem;margin-right:-.5rem}#plus91-hotkey-popup kbd[data-v-eb86b87c]{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-4e274b3c],.slide-leave-active[data-v-4e274b3c]{transition:transform .2s}.slide-enter-from[data-v-4e274b3c],.slide-leave-to[data-v-4e274b3c]{transform:translateY(100%)}#plus91-footer[data-v-4e274b3c]{z-index:1000;display:flex;justify-content:center;position:fixed;left:0;right:0;bottom:0}.footer-container[data-v-4e274b3c]{width:min(100vw,768px);background:rgba(75,156,169,.65);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);padding:.25rem .75rem .75rem;display:flex;justify-content:space-between;align-items:center;border-top:1px solid rgb(90,140,160)}@media (min-width: 768px){.footer-container[data-v-4e274b3c]{border-radius:1rem 1rem 0 0}}.slide-enter-active[data-v-5ddafe3d],.slide-leave-active[data-v-5ddafe3d]{transition:transform .2s}.slide-enter-from[data-v-5ddafe3d],.slide-leave-to[data-v-5ddafe3d]{transform:translateY(-100%)}#plus91-header[data-v-5ddafe3d]{z-index:1000;display:flex;justify-content:center;position:fixed;left:0;right:0;top:0}.header-container[data-v-5ddafe3d]{width:min(100vw,768px);background:rgba(75,156,169,.65);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);padding:.25rem .75rem;display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid rgb(90,140,160)}@media (min-width: 768px){.header-container[data-v-5ddafe3d]{border-radius:0 0 1rem 1rem}}.header-container input[data-v-5ddafe3d]{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-5ddafe3d]:focus-visible{outline:0;opacity:1}.fade-enter-active[data-v-6cf58435],.fade-leave-active[data-v-6cf58435]{transition:opacity .2s}.fade-enter-from[data-v-6cf58435],.fade-leave-to[data-v-6cf58435]{opacity:0}#dark-mode-overlay[data-v-6cf58435]{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,[class^=AD2M],[id^=adGeek]{display:none!important} ');

(function (vue, zipson, vexchords, html2canvas) {
  '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 = () => {
  };
  function addSubscription(subscriptions, callback, detached, onCleanup = noop) {
    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
    );
    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 after(callback) {
          afterCallbackList.push(callback);
        }
        function onError(callback) {
          onErrorCallbackList.push(callback);
        }
        triggerSubscriptions(actionSubscriptions, {
          args,
          name,
          store,
          after,
          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(v) {
    return typeof v === "object" && v !== null;
  }
  function normalizeOptions(options, factoryOptions) {
    options = isObject(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)();
  var _unsafeWindow = /* @__PURE__ */ (() => typeof unsafeWindow != "undefined" ? unsafeWindow : 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);
      }
    }
  }
  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: zipson.parse,
      serialize: zipson.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) => ({
        "2b53b793": __props.color,
        "4bbf91d1": __props.size,
        "5ab9f408": __props.stroke
      }));
      const props = __props;
      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-6e52047a"]]);
  const _hoisted_1$d = { class: "toolbar-icon" };
  const _hoisted_2$c = { class: "toolbar-icon-text" };
  const _sfc_main$e = {
    __name: "ToolbarIcon",
    props: {
      icon: {
        type: String,
        required: true
      },
      text: {
        type: String,
        required: true
      },
      stroke: {
        type: String,
        default: "0"
      },
      active: {
        type: Boolean,
        default: false
      },
      color: {
        type: String,
        default: "whitesmoke"
      }
    },
    setup(__props) {
      vue.useCssVars((_ctx) => ({
        "52bb32ad": __props.color
      }));
      const props = __props;
      return (_ctx, _cache) => {
        return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$d, [
          vue.createVNode(BootstrapIcon, {
            size: "1.3rem",
            icon: props.icon,
            color: props.color,
            stroke: props.stroke,
            active: props.active
          }, null, 8, ["icon", "color", "stroke", "active"]),
          vue.createElementVNode("div", _hoisted_2$c, vue.toDisplayString(props.text), 1)
        ]);
      };
    }
  };
  const ToolbarIcon = /* @__PURE__ */ _export_sfc(_sfc_main$e, [["__scopeId", "data-v-3dbcd695"]]);
  const _hoisted_1$c = { class: "adjust-widget" };
  const _hoisted_2$b = ["disabled"];
  const _hoisted_3$5 = ["disabled"];
  const _hoisted_4$3 = ["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) => ({
        "13e75dc8": __props.color,
        "10392328": __props.size
      }));
      const props = __props;
      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$5),
          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$3)
        ]);
      };
    }
  };
  const AdjustWidget = /* @__PURE__ */ _export_sfc(_sfc_main$d, [["__scopeId", "data-v-cb8ab81d"]]);
  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`);
    });
  };
  var LIBVERSION = "2.0.0-beta.3", EMPTY = "", UNKNOWN = "?", FUNC_TYPE = "function", UNDEF_TYPE = "undefined", OBJ_TYPE = "object", STR_TYPE = "string", MAJOR = "major", MODEL = "model", NAME = "name", TYPE = "type", VENDOR = "vendor", VERSION = "version", ARCHITECTURE = "architecture", CONSOLE = "console", MOBILE = "mobile", TABLET = "tablet", SMARTTV = "smarttv", WEARABLE = "wearable", XR = "xr", EMBEDDED = "embedded", USER_AGENT = "user-agent", UA_MAX_LENGTH = 500, BRANDS = "brands", FORMFACTORS = "formFactors", FULLVERLIST = "fullVersionList", PLATFORM = "platform", PLATFORMVER = "platformVersion", BITNESS = "bitness", CH_HEADER = "sec-ch-ua", CH_HEADER_FULL_VER_LIST = CH_HEADER + "-full-version-list", CH_HEADER_ARCH = CH_HEADER + "-arch", CH_HEADER_BITNESS = CH_HEADER + "-" + BITNESS, CH_HEADER_FORM_FACTORS = CH_HEADER + "-form-factors", CH_HEADER_MOBILE = CH_HEADER + "-" + MOBILE, CH_HEADER_MODEL = CH_HEADER + "-" + MODEL, CH_HEADER_PLATFORM = CH_HEADER + "-" + PLATFORM, CH_HEADER_PLATFORM_VER = CH_HEADER_PLATFORM + "-version", CH_ALL_VALUES = [BRANDS, FULLVERLIST, MOBILE, MODEL, PLATFORM, PLATFORMVER, ARCHITECTURE, FORMFACTORS, BITNESS], UA_BROWSER = "browser", UA_CPU = "cpu", UA_DEVICE = "device", UA_ENGINE = "engine", UA_OS = "os", UA_RESULT = "result", AMAZON = "Amazon", APPLE = "Apple", ASUS = "ASUS", BLACKBERRY = "BlackBerry", GOOGLE = "Google", HUAWEI = "Huawei", LENOVO = "Lenovo", LG = "LG", MICROSOFT = "Microsoft", MOTOROLA = "Motorola", SAMSUNG = "Samsung", SHARP = "Sharp", SONY = "Sony", XIAOMI = "Xiaomi", ZEBRA = "Zebra", PREFIX_MOBILE = "Mobile ", SUFFIX_BROWSER = " Browser", CHROME = "Chrome", EDGE = "Edge", FIREFOX = "Firefox", OPERA = "Opera", FACEBOOK = "Facebook", SOGOU = "Sogou", WINDOWS = "Windows";
  var isWindow = typeof window !== UNDEF_TYPE, NAVIGATOR = isWindow && window.navigator ? window.navigator : void 0, NAVIGATOR_UADATA = NAVIGATOR && NAVIGATOR.userAgentData ? NAVIGATOR.userAgentData : void 0;
  var extend = function(defaultRgx, extensions) {
    var mergedRgx = {};
    var extraRgx = extensions;
    if (!isExtensions(extensions)) {
      extraRgx = {};
      for (var i in extensions) {
        for (var j in extensions[i]) {
          extraRgx[j] = extensions[i][j].concat(extraRgx[j] ? extraRgx[j] : []);
        }
      }
    }
    for (var k in defaultRgx) {
      mergedRgx[k] = extraRgx[k] && extraRgx[k].length % 2 === 0 ? extraRgx[k].concat(defaultRgx[k]) : defaultRgx[k];
    }
    return mergedRgx;
  }, enumerize = function(arr) {
    var enums = {};
    for (var i = 0; i < arr.length; i++) {
      enums[arr[i].toUpperCase()] = arr[i];
    }
    return enums;
  }, has = function(str1, str2) {
    if (typeof str1 === OBJ_TYPE && str1.length > 0) {
      for (var i in str1) {
        if (lowerize(str1[i]) == lowerize(str2))
          return true;
      }
      return false;
    }
    return isString(str1) ? lowerize(str2).indexOf(lowerize(str1)) !== -1 : false;
  }, isExtensions = function(obj, deep) {
    for (var prop in obj) {
      return /^(browser|cpu|device|engine|os)$/.test(prop) || (deep ? isExtensions(obj[prop]) : false);
    }
  }, isString = function(val) {
    return typeof val === STR_TYPE;
  }, itemListToArray = function(header) {
    if (!header)
      return void 0;
    var arr = [];
    var tokens = strip(/\\?\"/g, header).split(",");
    for (var i = 0; i < tokens.length; i++) {
      if (tokens[i].indexOf(";") > -1) {
        var token = trim(tokens[i]).split(";v=");
        arr[i] = { brand: token[0], version: token[1] };
      } else {
        arr[i] = trim(tokens[i]);
      }
    }
    return arr;
  }, lowerize = function(str) {
    return isString(str) ? str.toLowerCase() : str;
  }, majorize = function(version) {
    return isString(version) ? strip(/[^\d\.]/g, version).split(".")[0] : void 0;
  }, setProps = function(arr) {
    for (var i in arr) {
      var propName = arr[i];
      if (typeof propName == OBJ_TYPE && propName.length == 2) {
        this[propName[0]] = propName[1];
      } else {
        this[propName] = void 0;
      }
    }
    return this;
  }, strip = function(pattern, str) {
    return isString(str) ? str.replace(pattern, EMPTY) : str;
  }, stripQuotes = function(str) {
    return strip(/\\?\"/g, str);
  }, trim = function(str, len) {
    if (isString(str)) {
      str = strip(/^\s\s*/, str);
      return typeof len === UNDEF_TYPE ? str : str.substring(0, UA_MAX_LENGTH);
    }
  };
  var rgxMapper = function(ua, arrays) {
    if (!ua || !arrays)
      return;
    var i = 0, j, k, p, q, matches, match;
    while (i < arrays.length && !matches) {
      var regex = arrays[i], props = arrays[i + 1];
      j = k = 0;
      while (j < regex.length && !matches) {
        if (!regex[j]) {
          break;
        }
        matches = regex[j++].exec(ua);
        if (!!matches) {
          for (p = 0; p < props.length; p++) {
            match = matches[++k];
            q = props[p];
            if (typeof q === OBJ_TYPE && q.length > 0) {
              if (q.length === 2) {
                if (typeof q[1] == FUNC_TYPE) {
                  this[q[0]] = q[1].call(this, match);
                } else {
                  this[q[0]] = q[1];
                }
              } else if (q.length === 3) {
                if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) {
                  this[q[0]] = match ? q[1].call(this, match, q[2]) : void 0;
                } else {
                  this[q[0]] = match ? match.replace(q[1], q[2]) : void 0;
                }
              } else if (q.length === 4) {
                this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : void 0;
              }
            } else {
              this[q] = match ? match : void 0;
            }
          }
        }
      }
      i += 2;
    }
  }, strMapper = function(str, map) {
    for (var i in map) {
      if (typeof map[i] === OBJ_TYPE && map[i].length > 0) {
        for (var j = 0; j < map[i].length; j++) {
          if (has(map[i][j], str)) {
            return i === UNKNOWN ? void 0 : i;
          }
        }
      } else if (has(map[i], str)) {
        return i === UNKNOWN ? void 0 : i;
      }
    }
    return map.hasOwnProperty("*") ? map["*"] : str;
  };
  var windowsVersionMap = {
    "ME": "4.90",
    "NT 3.11": "NT3.51",
    "NT 4.0": "NT4.0",
    "2000": "NT 5.0",
    "XP": ["NT 5.1", "NT 5.2"],
    "Vista": "NT 6.0",
    "7": "NT 6.1",
    "8": "NT 6.2",
    "8.1": "NT 6.3",
    "10": ["NT 6.4", "NT 10.0"],
    "RT": "ARM"
  }, formFactorsMap = {
    "embedded": "Automotive",
    "mobile": "Mobile",
    "tablet": ["Tablet", "EInk"],
    "smarttv": "TV",
    "wearable": "Watch",
    "xr": ["VR", "XR"],
    "?": ["Desktop", "Unknown"],
    "*": void 0
  };
  var defaultRegexes = {
    browser: [
      [
        // Most common regardless engine
        /\b(?:crmo|crios)\/([\w\.]+)/i
        // Chrome for Android/iOS
      ],
      [VERSION, [NAME, PREFIX_MOBILE + "Chrome"]],
      [
        /edg(?:e|ios|a)?\/([\w\.]+)/i
        // Microsoft Edge
      ],
      [VERSION, [NAME, "Edge"]],
      [
        // Presto based
        /(opera mini)\/([-\w\.]+)/i,
        // Opera Mini
        /(opera [mobiletab]{3,6})\b.+version\/([-\w\.]+)/i,
        // Opera Mobi/Tablet
        /(opera)(?:.+version\/|[\/ ]+)([\w\.]+)/i
        // Opera
      ],
      [NAME, VERSION],
      [
        /opios[\/ ]+([\w\.]+)/i
        // Opera mini on iphone >= 8.0
      ],
      [VERSION, [NAME, OPERA + " Mini"]],
      [
        /\bop(?:rg)?x\/([\w\.]+)/i
        // Opera GX
      ],
      [VERSION, [NAME, OPERA + " GX"]],
      [
        /\bopr\/([\w\.]+)/i
        // Opera Webkit
      ],
      [VERSION, [NAME, OPERA]],
      [
        // Mixed
        /\bb[ai]*d(?:uhd|[ub]*[aekoprswx]{5,6})[\/ ]?([\w\.]+)/i
        // Baidu
      ],
      [VERSION, [NAME, "Baidu"]],
      [
        /(kindle)\/([\w\.]+)/i,
        // Kindle
        /(lunascape|maxthon|netfront|jasmine|blazer|sleipnir)[\/ ]?([\w\.]*)/i,
        // Lunascape/Maxthon/Netfront/Jasmine/Blazer/Sleipnir
        // Trident based
        /(avant|iemobile|slim)\s?(?:browser)?[\/ ]?([\w\.]*)/i,
        // Avant/IEMobile/SlimBrowser
        /(?:ms|\()(ie) ([\w\.]+)/i,
        // Internet Explorer
        // Webkit/KHTML based                                               // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon
        /(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|quark|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar)\/([-\w\.]+)/i,
        // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar
        /(heytap|ovi)browser\/([\d\.]+)/i,
        // HeyTap/Ovi
        /(weibo)__([\d\.]+)/i
        // Weibo
      ],
      [NAME, VERSION],
      [
        /\bddg\/([\w\.]+)/i
        // DuckDuckGo
      ],
      [VERSION, [NAME, "DuckDuckGo"]],
      [
        /(?:\buc? ?browser|(?:juc.+)ucweb)[\/ ]?([\w\.]+)/i
        // UCBrowser
      ],
      [VERSION, [NAME, "UCBrowser"]],
      [
        /microm.+\bqbcore\/([\w\.]+)/i,
        // WeChat Desktop for Windows Built-in Browser
        /\bqbcore\/([\w\.]+).+microm/i,
        /micromessenger\/([\w\.]+)/i
        // WeChat
      ],
      [VERSION, [NAME, "WeChat"]],
      [
        /konqueror\/([\w\.]+)/i
        // Konqueror
      ],
      [VERSION, [NAME, "Konqueror"]],
      [
        /trident.+rv[: ]([\w\.]{1,9})\b.+like gecko/i
        // IE11
      ],
      [VERSION, [NAME, "IE"]],
      [
        /ya(?:search)?browser\/([\w\.]+)/i
        // Yandex
      ],
      [VERSION, [NAME, "Yandex"]],
      [
        /slbrowser\/([\w\.]+)/i
        // Smart Lenovo Browser
      ],
      [VERSION, [NAME, "Smart " + LENOVO + SUFFIX_BROWSER]],
      [
        /(avast|avg)\/([\w\.]+)/i
        // Avast/AVG Secure Browser
      ],
      [[NAME, /(.+)/, "$1 Secure" + SUFFIX_BROWSER], VERSION],
      [
        /\bfocus\/([\w\.]+)/i
        // Firefox Focus
      ],
      [VERSION, [NAME, FIREFOX + " Focus"]],
      [
        /\bopt\/([\w\.]+)/i
        // Opera Touch
      ],
      [VERSION, [NAME, OPERA + " Touch"]],
      [
        /coc_coc\w+\/([\w\.]+)/i
        // Coc Coc Browser
      ],
      [VERSION, [NAME, "Coc Coc"]],
      [
        /dolfin\/([\w\.]+)/i
        // Dolphin
      ],
      [VERSION, [NAME, "Dolphin"]],
      [
        /coast\/([\w\.]+)/i
        // Opera Coast
      ],
      [VERSION, [NAME, OPERA + " Coast"]],
      [
        /miuibrowser\/([\w\.]+)/i
        // MIUI Browser
      ],
      [VERSION, [NAME, "MIUI" + SUFFIX_BROWSER]],
      [
        /fxios\/([\w\.-]+)/i
        // Firefox for iOS
      ],
      [VERSION, [NAME, PREFIX_MOBILE + FIREFOX]],
      [
        /\bqihu|(qi?ho?o?|360)browser/i
        // 360
      ],
      [[NAME, "360" + SUFFIX_BROWSER]],
      [
        /\b(qq)\/([\w\.]+)/i
        // QQ
      ],
      [[NAME, /(.+)/, "$1Browser"], VERSION],
      [
        /(oculus|sailfish|huawei|vivo|pico)browser\/([\w\.]+)/i
      ],
      [[NAME, /(.+)/, "$1" + SUFFIX_BROWSER], VERSION],
      [
        // Oculus/Sailfish/HuaweiBrowser/VivoBrowser/PicoBrowser
        /samsungbrowser\/([\w\.]+)/i
        // Samsung Internet
      ],
      [VERSION, [NAME, SAMSUNG + " Internet"]],
      [
        /(comodo_dragon)\/([\w\.]+)/i
        // Comodo Dragon
      ],
      [[NAME, /_/g, " "], VERSION],
      [
        /metasr[\/ ]?([\d\.]+)/i
        // Sogou Explorer
      ],
      [VERSION, [NAME, SOGOU + " Explorer"]],
      [
        /(sogou)mo\w+\/([\d\.]+)/i
        // Sogou Mobile
      ],
      [[NAME, SOGOU + " Mobile"], VERSION],
      [
        /(electron)\/([\w\.]+) safari/i,
        // Electron-based App
        /(tesla)(?: qtcarbrowser|\/(20\d\d\.[-\w\.]+))/i,
        // Tesla
        /m?(qqbrowser|2345Explorer)[\/ ]?([\w\.]+)/i
        // QQBrowser/2345 Browser
      ],
      [NAME, VERSION],
      [
        /(lbbrowser|rekonq)/i,
        // LieBao Browser/Rekonq
        /\[(linkedin)app\]/i
        // LinkedIn App for iOS & Android
      ],
      [NAME],
      [
        // WebView
        /((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w\.]+);)/i
        // Facebook App for iOS & Android
      ],
      [[NAME, FACEBOOK], VERSION],
      [
        /(Klarna)\/([\w\.]+)/i,
        // Klarna Shopping Browser for iOS & Android
        /(kakao(?:talk|story))[\/ ]([\w\.]+)/i,
        // Kakao App
        /(naver)\(.*?(\d+\.[\w\.]+).*\)/i,
        // Naver InApp
        /safari (line)\/([\w\.]+)/i,
        // Line App for iOS
        /\b(line)\/([\w\.]+)\/iab/i,
        // Line App for Android
        /(alipay)client\/([\w\.]+)/i,
        // Alipay
        /(twitter)(?:and| f.+e\/([\w\.]+))/i,
        // Twitter
        /(chromium|instagram|snapchat)[\/ ]([-\w\.]+)/i
        // Chromium/Instagram/Snapchat
      ],
      [NAME, VERSION],
      [
        /\bgsa\/([\w\.]+) .*safari\//i
        // Google Search Appliance on iOS
      ],
      [VERSION, [NAME, "GSA"]],
      [
        /musical_ly(?:.+app_?version\/|_)([\w\.]+)/i
        // TikTok
      ],
      [VERSION, [NAME, "TikTok"]],
      [
        /headlesschrome(?:\/([\w\.]+)| )/i
        // Chrome Headless
      ],
      [VERSION, [NAME, CHROME + " Headless"]],
      [
        / wv\).+(chrome)\/([\w\.]+)/i
        // Chrome WebView
      ],
      [[NAME, CHROME + " WebView"], VERSION],
      [
        /droid.+ version\/([\w\.]+)\b.+(?:mobile safari|safari)/i
        // Android Browser
      ],
      [VERSION, [NAME, "Android" + SUFFIX_BROWSER]],
      [
        /chrome\/([\w\.]+) mobile/i
        // Chrome Mobile
      ],
      [VERSION, [NAME, PREFIX_MOBILE + "Chrome"]],
      [
        /(chrome|omniweb|arora|[tizenoka]{5} ?browser)\/v?([\w\.]+)/i
        // Chrome/OmniWeb/Arora/Tizen/Nokia
      ],
      [NAME, VERSION],
      [
        /version\/([\w\.\,]+) .*mobile(?:\/\w+ | ?)safari/i
        // Safari Mobile
      ],
      [VERSION, [NAME, PREFIX_MOBILE + "Safari"]],
      [
        /iphone .*mobile(?:\/\w+ | ?)safari/i
      ],
      [[NAME, PREFIX_MOBILE + "Safari"]],
      [
        /version\/([\w\.\,]+) .*(safari)/i
        // Safari
      ],
      [VERSION, NAME],
      [
        /webkit.+?(mobile ?safari|safari)(\/[\w\.]+)/i
        // Safari < 3.0
      ],
      [NAME, [VERSION, "1"]],
      [
        /(webkit|khtml)\/([\w\.]+)/i
      ],
      [NAME, VERSION],
      [
        // Gecko based
        /(?:mobile|tablet);.*(firefox)\/([\w\.-]+)/i
        // Firefox Mobile
      ],
      [[NAME, PREFIX_MOBILE + FIREFOX], VERSION],
      [
        /(navigator|netscape\d?)\/([-\w\.]+)/i
        // Netscape
      ],
      [[NAME, "Netscape"], VERSION],
      [
        /(wolvic)\/([\w\.]+)/i
        // Wolvic
      ],
      [NAME, VERSION],
      [
        /mobile vr; rv:([\w\.]+)\).+firefox/i
        // Firefox Reality
      ],
      [VERSION, [NAME, FIREFOX + " Reality"]],
      [
        /ekiohf.+(flow)\/([\w\.]+)/i,
        // Flow
        /(swiftfox)/i,
        // Swiftfox
        /(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror)[\/ ]?([\w\.\+]+)/i,
        // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror
        /(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\/([-\w\.]+)$/i,
        // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix
        /(firefox)\/([\w\.]+)/i,
        // Other Firefox-based
        /(mozilla)\/([\w\.]+) .+rv\:.+gecko\/\d+/i,
        // Mozilla
        // Other
        /(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|obigo|mosaic|(?:go|ice|up)[\. ]?browser)[-\/ ]?v?([\w\.]+)/i,
        // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Obigo/Mosaic/Go/ICE/UP.Browser
        /(links) \(([\w\.]+)/i
        // Links
      ],
      [NAME, [VERSION, /_/g, "."]],
      [
        /(cobalt)\/([\w\.]+)/i
        // Cobalt
      ],
      [NAME, [VERSION, /[^\d\.]+./, EMPTY]]
    ],
    cpu: [
      [
        /\b(?:(amd|x|x86[-_]?|wow|win)64)\b/i
        // AMD64 (x64)
      ],
      [[ARCHITECTURE, "amd64"]],
      [
        /(ia32(?=;))/i,
        // IA32 (quicktime)
        /((?:i[346]|x)86)[;\)]/i
        // IA32 (x86)
      ],
      [[ARCHITECTURE, "ia32"]],
      [
        /\b(aarch64|arm(v?8e?l?|_?64))\b/i
        // ARM64
      ],
      [[ARCHITECTURE, "arm64"]],
      [
        /\b(arm(?:v[67])?ht?n?[fl]p?)\b/i
        // ARMHF
      ],
      [[ARCHITECTURE, "armhf"]],
      [
        // PocketPC mistakenly identified as PowerPC
        /windows (ce|mobile); ppc;/i
      ],
      [[ARCHITECTURE, "arm"]],
      [
        /((?:ppc|powerpc)(?:64)?)(?: mac|;|\))/i
        // PowerPC
      ],
      [[ARCHITECTURE, /ower/, EMPTY, lowerize]],
      [
        /(sun4\w)[;\)]/i
        // SPARC
      ],
      [[ARCHITECTURE, "sparc"]],
      [
        /((?:avr32|ia64(?=;))|68k(?=\))|\barm(?=v(?:[1-7]|[5-7]1)l?|;|eabi)|(?=atmel )avr|(?:irix|mips|sparc)(?:64)?\b|pa-risc)/i
        // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC
      ],
      [[ARCHITECTURE, lowerize]]
    ],
    device: [
      [
        //////////////////////////
        // MOBILES & TABLETS
        /////////////////////////
        // Samsung
        /\b(sch-i[89]0\d|shw-m380s|sm-[ptx]\w{2,4}|gt-[pn]\d{2,4}|sgh-t8[56]9|nexus 10)/i
      ],
      [MODEL, [VENDOR, SAMSUNG], [TYPE, TABLET]],
      [
        /\b((?:s[cgp]h|gt|sm)-\w+|sc[g-]?[\d]+a?|galaxy nexus)/i,
        /samsung[- ]([-\w]+)/i,
        /sec-(sgh\w+)/i
      ],
      [MODEL, [VENDOR, SAMSUNG], [TYPE, MOBILE]],
      [
        // Apple
        /(?:\/|\()(ip(?:hone|od)[\w, ]*)(?:\/|;)/i
        // iPod/iPhone
      ],
      [MODEL, [VENDOR, APPLE], [TYPE, MOBILE]],
      [
        /\((ipad);[-\w\),; ]+apple/i,
        // iPad
        /applecoremedia\/[\w\.]+ \((ipad)/i,
        /\b(ipad)\d\d?,\d\d?[;\]].+ios/i
      ],
      [MODEL, [VENDOR, APPLE], [TYPE, TABLET]],
      [
        /(macintosh);/i
      ],
      [MODEL, [VENDOR, APPLE]],
      [
        // Sharp
        /\b(sh-?[altvz]?\d\d[a-ekm]?)/i
      ],
      [MODEL, [VENDOR, SHARP], [TYPE, MOBILE]],
      [
        // Huawei
        /\b((?:ag[rs][23]?|bah2?|sht?|btv)-a?[lw]\d{2})\b(?!.+d\/s)/i
      ],
      [MODEL, [VENDOR, HUAWEI], [TYPE, TABLET]],
      [
        /(?:huawei|honor)([-\w ]+)[;\)]/i,
        /\b(nexus 6p|\w{2,4}e?-[atu]?[ln][\dx][012359c][adn]?)\b(?!.+d\/s)/i
      ],
      [MODEL, [VENDOR, HUAWEI], [TYPE, MOBILE]],
      [
        // Xiaomi
        /\b(poco[\w ]+|m2\d{3}j\d\d[a-z]{2})(?: bui|\))/i,
        // Xiaomi POCO
        /\b; (\w+) build\/hm\1/i,
        // Xiaomi Hongmi 'numeric' models
        /\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i,
        // Xiaomi Hongmi
        /\b(redmi[\-_ ]?(?:note|k)?[\w_ ]+)(?: bui|\))/i,
        // Xiaomi Redmi
        /oid[^\)]+; (m?[12][0-389][01]\w{3,6}[c-y])( bui|; wv|\))/i,
        // Xiaomi Redmi 'numeric' models
        /\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?(?:\d?\w?)[_ ]?(?:plus|se|lite)?)(?: bui|\))/i
        // Xiaomi Mi
      ],
      [[MODEL, /_/g, " "], [VENDOR, XIAOMI], [TYPE, MOBILE]],
      [
        /oid[^\)]+; (2\d{4}(283|rpbf)[cgl])( bui|\))/i,
        // Redmi Pad
        /\b(mi[-_ ]?(?:pad)(?:[\w_ ]+))(?: bui|\))/i
        // Mi Pad tablets
      ],
      [[MODEL, /_/g, " "], [VENDOR, XIAOMI], [TYPE, TABLET]],
      [
        // OPPO
        /; (\w+) bui.+ oppo/i,
        /\b(cph[12]\d{3}|p(?:af|c[al]|d\w|e[ar])[mt]\d0|x9007|a101op)\b/i
      ],
      [MODEL, [VENDOR, "OPPO"], [TYPE, MOBILE]],
      [
        /\b(opd2\d{3}a?) bui/i
      ],
      [MODEL, [VENDOR, "OPPO"], [TYPE, TABLET]],
      [
        // Vivo
        /vivo (\w+)(?: bui|\))/i,
        /\b(v[12]\d{3}\w?[at])(?: bui|;)/i
      ],
      [MODEL, [VENDOR, "Vivo"], [TYPE, MOBILE]],
      [
        // Realme
        /\b(rmx[1-3]\d{3})(?: bui|;|\))/i
      ],
      [MODEL, [VENDOR, "Realme"], [TYPE, MOBILE]],
      [
        // Motorola
        /\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\b[\w ]+build\//i,
        /\bmot(?:orola)?[- ](\w*)/i,
        /((?:moto[\w\(\) ]+|xt\d{3,4}|nexus 6)(?= bui|\)))/i
      ],
      [MODEL, [VENDOR, MOTOROLA], [TYPE, MOBILE]],
      [
        /\b(mz60\d|xoom[2 ]{0,2}) build\//i
      ],
      [MODEL, [VENDOR, MOTOROLA], [TYPE, TABLET]],
      [
        // LG
        /((?=lg)?[vl]k\-?\d{3}) bui| 3\.[-\w; ]{10}lg?-([06cv9]{3,4})/i
      ],
      [MODEL, [VENDOR, LG], [TYPE, TABLET]],
      [
        /(lm(?:-?f100[nv]?|-[\w\.]+)(?= bui|\))|nexus [45])/i,
        /\blg[-e;\/ ]+((?!browser|netcast|android tv)\w+)/i,
        /\blg-?([\d\w]+) bui/i
      ],
      [MODEL, [VENDOR, LG], [TYPE, MOBILE]],
      [
        // Lenovo
        /(ideatab[-\w ]+)/i,
        /lenovo ?(s[56]000[-\w]+|tab(?:[\w ]+)|yt[-\d\w]{6}|tb[-\d\w]{6})/i
      ],
      [MODEL, [VENDOR, LENOVO], [TYPE, TABLET]],
      [
        // Nokia
        /(?:maemo|nokia).*(n900|lumia \d+)/i,
        /nokia[-_ ]?([-\w\.]*)/i
      ],
      [[MODEL, /_/g, " "], [VENDOR, "Nokia"], [TYPE, MOBILE]],
      [
        // Google
        /(pixel c)\b/i
        // Google Pixel C
      ],
      [MODEL, [VENDOR, GOOGLE], [TYPE, TABLET]],
      [
        /droid.+; (pixel[\daxl ]{0,6})(?: bui|\))/i
        // Google Pixel
      ],
      [MODEL, [VENDOR, GOOGLE], [TYPE, MOBILE]],
      [
        // Sony
        /droid.+ (a?\d[0-2]{2}so|[c-g]\d{4}|so[-gl]\w+|xq-a\w[4-7][12])(?= bui|\).+chrome\/(?![1-6]{0,1}\d\.))/i
      ],
      [MODEL, [VENDOR, SONY], [TYPE, MOBILE]],
      [
        /sony tablet [ps]/i,
        /\b(?:sony)?sgp\w+(?: bui|\))/i
      ],
      [[MODEL, "Xperia Tablet"], [VENDOR, SONY], [TYPE, TABLET]],
      [
        // OnePlus
        / (kb2005|in20[12]5|be20[12][59])\b/i,
        /(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i
      ],
      [MODEL, [VENDOR, "OnePlus"], [TYPE, MOBILE]],
      [
        // Amazon
        /(alexa)webm/i,
        /(kf[a-z]{2}wi|aeo[c-r]{2})( bui|\))/i,
        // Kindle Fire without Silk / Echo Show
        /(kf[a-z]+)( bui|\)).+silk\//i
        // Kindle Fire HD
      ],
      [MODEL, [VENDOR, AMAZON], [TYPE, TABLET]],
      [
        /((?:sd|kf)[0349hijorstuw]+)( bui|\)).+silk\//i
        // Fire Phone
      ],
      [[MODEL, /(.+)/g, "Fire Phone $1"], [VENDOR, AMAZON], [TYPE, MOBILE]],
      [
        // BlackBerry
        /(playbook);[-\w\),; ]+(rim)/i
        // BlackBerry PlayBook
      ],
      [MODEL, VENDOR, [TYPE, TABLET]],
      [
        /\b((?:bb[a-f]|st[hv])100-\d)/i,
        /\(bb10; (\w+)/i
        // BlackBerry 10
      ],
      [MODEL, [VENDOR, BLACKBERRY], [TYPE, MOBILE]],
      [
        // Asus
        /(?:\b|asus_)(transfo[prime ]{4,10} \w+|eeepc|slider \w+|nexus 7|padfone|p00[cj])/i
      ],
      [MODEL, [VENDOR, ASUS], [TYPE, TABLET]],
      [
        / (z[bes]6[027][012][km][ls]|zenfone \d\w?)\b/i
      ],
      [MODEL, [VENDOR, ASUS], [TYPE, MOBILE]],
      [
        // HTC
        /(nexus 9)/i
        // HTC Nexus 9
      ],
      [MODEL, [VENDOR, "HTC"], [TYPE, TABLET]],
      [
        /(htc)[-;_ ]{1,2}([\w ]+(?=\)| bui)|\w+)/i,
        // HTC
        // ZTE
        /(zte)[- ]([\w ]+?)(?: bui|\/|\))/i,
        /(alcatel|geeksphone|nexian|panasonic(?!(?:;|\.))|sony(?!-bra))[-_ ]?([-\w]*)/i
        // Alcatel/GeeksPhone/Nexian/Panasonic/Sony
      ],
      [VENDOR, [MODEL, /_/g, " "], [TYPE, MOBILE]],
      [
        // Acer
        /droid.+; ([ab][1-7]-?[0178a]\d\d?)/i
      ],
      [MODEL, [VENDOR, "Acer"], [TYPE, TABLET]],
      [
        // Meizu
        /droid.+; (m[1-5] note) bui/i,
        /\bmz-([-\w]{2,})/i
      ],
      [MODEL, [VENDOR, "Meizu"], [TYPE, MOBILE]],
      [
        // Ulefone
        /; ((?:power )?armor(?:[\w ]{0,8}))(?: bui|\))/i
      ],
      [MODEL, [VENDOR, "Ulefone"], [TYPE, MOBILE]],
      [
        // MIXED
        /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron|infinix|tecno)[-_ ]?([-\w]*)/i,
        // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron
        /(hp) ([\w ]+\w)/i,
        // HP iPAQ
        /(asus)-?(\w+)/i,
        // Asus
        /(microsoft); (lumia[\w ]+)/i,
        // Microsoft Lumia
        /(lenovo)[-_ ]?([-\w]+)/i,
        // Lenovo
        /(jolla)/i,
        // Jolla
        /(oppo) ?([\w ]+) bui/i
        // OPPO
      ],
      [VENDOR, MODEL, [TYPE, MOBILE]],
      [
        /(kobo)\s(ereader|touch)/i,
        // Kobo
        /(archos) (gamepad2?)/i,
        // Archos
        /(hp).+(touchpad(?!.+tablet)|tablet)/i,
        // HP TouchPad
        /(kindle)\/([\w\.]+)/i
        // Kindle
      ],
      [VENDOR, MODEL, [TYPE, TABLET]],
      [
        /(surface duo)/i
        // Surface Duo
      ],
      [MODEL, [VENDOR, MICROSOFT], [TYPE, TABLET]],
      [
        /droid [\d\.]+; (fp\du?)(?: b|\))/i
        // Fairphone
      ],
      [MODEL, [VENDOR, "Fairphone"], [TYPE, MOBILE]],
      [
        /(shield[\w ]+) b/i
        // Nvidia Shield Tablets
      ],
      [MODEL, [VENDOR, "Nvidia"], [TYPE, TABLET]],
      [
        /(sprint) (\w+)/i
        // Sprint Phones
      ],
      [VENDOR, MODEL, [TYPE, MOBILE]],
      [
        /(kin\.[onetw]{3})/i
        // Microsoft Kin
      ],
      [[MODEL, /\./g, " "], [VENDOR, MICROSOFT], [TYPE, MOBILE]],
      [
        /droid.+; ([c6]+|et5[16]|mc[239][23]x?|vc8[03]x?)\)/i
        // Zebra
      ],
      [MODEL, [VENDOR, ZEBRA], [TYPE, TABLET]],
      [
        /droid.+; (ec30|ps20|tc[2-8]\d[kx])\)/i
      ],
      [MODEL, [VENDOR, ZEBRA], [TYPE, MOBILE]],
      [
        ///////////////////
        // SMARTTVS
        ///////////////////
        /smart-tv.+(samsung)/i
        // Samsung
      ],
      [VENDOR, [TYPE, SMARTTV]],
      [
        /hbbtv.+maple;(\d+)/i
      ],
      [[MODEL, /^/, "SmartTV"], [VENDOR, SAMSUNG], [TYPE, SMARTTV]],
      [
        /(nux; netcast.+smarttv|lg (netcast\.tv-201\d|android tv))/i
        // LG SmartTV
      ],
      [[VENDOR, LG], [TYPE, SMARTTV]],
      [
        /(apple) ?tv/i
        // Apple TV
      ],
      [VENDOR, [MODEL, APPLE + " TV"], [TYPE, SMARTTV]],
      [
        /crkey/i
        // Google Chromecast
      ],
      [[MODEL, CHROME + "cast"], [VENDOR, GOOGLE], [TYPE, SMARTTV]],
      [
        /droid.+aft(\w+)( bui|\))/i
        // Fire TV
      ],
      [MODEL, [VENDOR, AMAZON], [TYPE, SMARTTV]],
      [
        /\(dtv[\);].+(aquos)/i,
        /(aquos-tv[\w ]+)\)/i
        // Sharp
      ],
      [MODEL, [VENDOR, SHARP], [TYPE, SMARTTV]],
      [
        /(bravia[\w ]+)( bui|\))/i
        // Sony
      ],
      [MODEL, [VENDOR, SONY], [TYPE, SMARTTV]],
      [
        /(mitv-\w{5}) bui/i
        // Xiaomi
      ],
      [MODEL, [VENDOR, XIAOMI], [TYPE, SMARTTV]],
      [
        /Hbbtv.*(technisat) (.*);/i
        // TechniSAT
      ],
      [VENDOR, MODEL, [TYPE, SMARTTV]],
      [
        /\b(roku)[\dx]*[\)\/]((?:dvp-)?[\d\.]*)/i,
        // Roku
        /hbbtv\/\d+\.\d+\.\d+ +\([\w\+ ]*; *([\w\d][^;]*);([^;]*)/i
        // HbbTV devices
      ],
      [[VENDOR, trim], [MODEL, trim], [TYPE, SMARTTV]],
      [
        /\b(android tv|smart[- ]?tv|opera tv|tv; rv:)\b/i
        // SmartTV from Unidentified Vendors
      ],
      [[TYPE, SMARTTV]],
      [
        ///////////////////
        // CONSOLES
        ///////////////////
        /(ouya)/i,
        // Ouya
        /(nintendo) (\w+)/i
        // Nintendo
      ],
      [VENDOR, MODEL, [TYPE, CONSOLE]],
      [
        /droid.+; (shield) bui/i
        // Nvidia
      ],
      [MODEL, [VENDOR, "Nvidia"], [TYPE, CONSOLE]],
      [
        /(playstation \w+)/i
        // Playstation
      ],
      [MODEL, [VENDOR, SONY], [TYPE, CONSOLE]],
      [
        /\b(xbox(?: one)?(?!; xbox))[\); ]/i
        // Microsoft Xbox
      ],
      [MODEL, [VENDOR, MICROSOFT], [TYPE, CONSOLE]],
      [
        ///////////////////
        // WEARABLES
        ///////////////////
        /((pebble))app/i
        // Pebble
      ],
      [VENDOR, MODEL, [TYPE, WEARABLE]],
      [
        /(watch)(?: ?os[,\/]|\d,\d\/)[\d\.]+/i
        // Apple Watch
      ],
      [MODEL, [VENDOR, APPLE], [TYPE, WEARABLE]],
      [
        /droid.+; (wt63?0{2,3})\)/i
      ],
      [MODEL, [VENDOR, ZEBRA], [TYPE, WEARABLE]],
      [
        ///////////////////
        // XR
        ///////////////////
        /droid.+; (glass) \d/i
        // Google Glass
      ],
      [MODEL, [VENDOR, GOOGLE], [TYPE, XR]],
      [
        /(quest( \d| pro)?)/i
        // Oculus Quest
      ],
      [MODEL, [VENDOR, FACEBOOK], [TYPE, XR]],
      [
        ///////////////////
        // EMBEDDED
        ///////////////////
        /(tesla)(?: qtcarbrowser|\/[-\w\.]+)/i
        // Tesla
      ],
      [VENDOR, [TYPE, EMBEDDED]],
      [
        /(aeobc)\b/i
        // Echo Dot
      ],
      [MODEL, [VENDOR, AMAZON], [TYPE, EMBEDDED]],
      [
        ////////////////////
        // MIXED (GENERIC)
        ///////////////////
        /droid .+?; ([^;]+?)(?: bui|; wv\)|\) applew).+? mobile safari/i
        // Android Phones from Unidentified Vendors
      ],
      [MODEL, [TYPE, MOBILE]],
      [
        /droid .+?; ([^;]+?)(?: bui|\) applew).+?(?! mobile) safari/i
        // Android Tablets from Unidentified Vendors
      ],
      [MODEL, [TYPE, TABLET]],
      [
        /\b((tablet|tab)[;\/]|focus\/\d(?!.+mobile))/i
        // Unidentifiable Tablet
      ],
      [[TYPE, TABLET]],
      [
        /(phone|mobile(?:[;\/]| [ \w\/\.]*safari)|pda(?=.+windows ce))/i
        // Unidentifiable Mobile
      ],
      [[TYPE, MOBILE]],
      [
        /(android[-\w\. ]{0,9});.+buil/i
        // Generic Android Device
      ],
      [MODEL, [VENDOR, "Generic"]]
    ],
    engine: [
      [
        /windows.+ edge\/([\w\.]+)/i
        // EdgeHTML
      ],
      [VERSION, [NAME, EDGE + "HTML"]],
      [
        /webkit\/537\.36.+chrome\/(?!27)([\w\.]+)/i
        // Blink
      ],
      [VERSION, [NAME, "Blink"]],
      [
        /(presto)\/([\w\.]+)/i,
        // Presto
        /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna)\/([\w\.]+)/i,
        // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna
        /ekioh(flow)\/([\w\.]+)/i,
        // Flow
        /(khtml|tasman|links)[\/ ]\(?([\w\.]+)/i,
        // KHTML/Tasman/Links
        /(icab)[\/ ]([23]\.[\d\.]+)/i,
        // iCab
        /\b(libweb)/i
      ],
      [NAME, VERSION],
      [
        /rv\:([\w\.]{1,9})\b.+(gecko)/i
        // Gecko
      ],
      [VERSION, NAME]
    ],
    os: [
      [
        // Windows
        /microsoft (windows) (vista|xp)/i
        // Windows (iTunes)
      ],
      [NAME, VERSION],
      [
        /(windows (?:phone(?: os)?|mobile))[\/ ]?([\d\.\w ]*)/i
        // Windows Phone
      ],
      [NAME, [VERSION, strMapper, windowsVersionMap]],
      [
        /windows nt 6\.2; (arm)/i,
        // Windows RT
        /windows[\/ ]?([ntce\d\. ]+\w)(?!.+xbox)/i,
        /(?:win(?=3|9|n)|win 9x )([nt\d\.]+)/i
      ],
      [[VERSION, strMapper, windowsVersionMap], [NAME, WINDOWS]],
      [
        // iOS/macOS
        /ip[honead]{2,4}\b(?:.*os ([\w]+) like mac|; opera)/i,
        // iOS
        /(?:ios;fbsv\/|iphone.+ios[\/ ])([\d\.]+)/i,
        /cfnetwork\/.+darwin/i
      ],
      [[VERSION, /_/g, "."], [NAME, "iOS"]],
      [
        /(mac os x) ?([\w\. ]*)/i,
        /(macintosh|mac_powerpc\b)(?!.+haiku)/i
        // Mac OS
      ],
      [[NAME, "macOS"], [VERSION, /_/g, "."]],
      [
        // Mobile OSes
        /droid ([\w\.]+)\b.+(android[- ]x86|harmonyos)/i
        // Android-x86/HarmonyOS
      ],
      [VERSION, NAME],
      [
        // Android/WebOS/QNX/Bada/RIM/Maemo/MeeGo/Sailfish OS
        /(android|webos|qnx|bada|rim tablet os|maemo|meego|sailfish)[-\/ ]?([\w\.]*)/i,
        /(blackberry)\w*\/([\w\.]*)/i,
        // Blackberry
        /(tizen|kaios)[\/ ]([\w\.]+)/i,
        // Tizen/KaiOS
        /\((series40);/i
        // Series 40
      ],
      [NAME, VERSION],
      [
        /\(bb(10);/i
        // BlackBerry 10
      ],
      [VERSION, [NAME, BLACKBERRY]],
      [
        /(?:symbian ?os|symbos|s60(?=;)|series60)[-\/ ]?([\w\.]*)/i
        // Symbian
      ],
      [VERSION, [NAME, "Symbian"]],
      [
        /mozilla\/[\d\.]+ \((?:mobile|tablet|tv|mobile; [\w ]+); rv:.+ gecko\/([\w\.]+)/i
        // Firefox OS
      ],
      [VERSION, [NAME, FIREFOX + " OS"]],
      [
        /web0s;.+rt(tv)/i,
        /\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i
        // WebOS
      ],
      [VERSION, [NAME, "webOS"]],
      [
        /watch(?: ?os[,\/]|\d,\d\/)([\d\.]+)/i
        // watchOS
      ],
      [VERSION, [NAME, "watchOS"]],
      [
        // Google Chromecast
        /crkey\/([\d\.]+)/i
        // Google Chromecast
      ],
      [VERSION, [NAME, CHROME + "cast"]],
      [
        /(cros) [\w]+(?:\)| ([\w\.]+)\b)/i
        // Chromium OS
      ],
      [[NAME, "Chrome OS"], VERSION],
      [
        // Smart TVs
        /panasonic;(viera)/i,
        // Panasonic Viera
        /(netrange)mmh/i,
        // Netrange
        /(nettv)\/(\d+\.[\w\.]+)/i,
        // NetTV
        // Console
        /(nintendo|playstation) (\w+)/i,
        // Nintendo/Playstation
        /(xbox); +xbox ([^\);]+)/i,
        // Microsoft Xbox (360, One, X, S, Series X, Series S)
        // Other
        /\b(joli|palm)\b ?(?:os)?\/?([\w\.]*)/i,
        // Joli/Palm
        /(mint)[\/\(\) ]?(\w*)/i,
        // Mint
        /(mageia|vectorlinux)[; ]/i,
        // Mageia/VectorLinux
        /([kxln]?ubuntu|debian|suse|opensuse|gentoo|arch(?= linux)|slackware|fedora|mandriva|centos|pclinuxos|red ?hat|zenwalk|linpus|raspbian|plan 9|minix|risc os|contiki|deepin|manjaro|elementary os|sabayon|linspire)(?: gnu\/linux)?(?: enterprise)?(?:[- ]linux)?(?:-gnu)?[-\/ ]?(?!chrom|package)([-\w\.]*)/i,
        // Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware/Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus/Raspbian/Plan9/Minix/RISCOS/Contiki/Deepin/Manjaro/elementary/Sabayon/Linspire
        /(hurd|linux) ?([\w\.]*)/i,
        // Hurd/Linux
        /(gnu) ?([\w\.]*)/i,
        // GNU
        /\b([-frentopcghs]{0,5}bsd|dragonfly)[\/ ]?(?!amd|[ix346]{1,2}86)([\w\.]*)/i,
        // FreeBSD/NetBSD/OpenBSD/PC-BSD/GhostBSD/DragonFly
        /(haiku) (\w+)/i
        // Haiku
      ],
      [NAME, VERSION],
      [
        /(sunos) ?([\w\.\d]*)/i
        // Solaris
      ],
      [[NAME, "Solaris"], VERSION],
      [
        /((?:open)?solaris)[-\/ ]?([\w\.]*)/i,
        // Solaris
        /(aix) ((\d)(?=\.|\)| )[\w\.])*/i,
        // AIX
        /\b(beos|os\/2|amigaos|morphos|openvms|fuchsia|hp-ux|serenityos)/i,
        // BeOS/OS2/AmigaOS/MorphOS/OpenVMS/Fuchsia/HP-UX/SerenityOS
        /(unix) ?([\w\.]*)/i
        // UNIX
      ],
      [NAME, VERSION]
    ]
  };
  var defaultProps = function() {
    var props = { init: {}, isIgnore: {}, isIgnoreRgx: {}, toString: {} };
    setProps.call(props.init, [
      [UA_BROWSER, [NAME, VERSION, MAJOR, TYPE]],
      [UA_CPU, [ARCHITECTURE]],
      [UA_DEVICE, [TYPE, MODEL, VENDOR]],
      [UA_ENGINE, [NAME, VERSION]],
      [UA_OS, [NAME, VERSION]]
    ]);
    setProps.call(props.isIgnore, [
      [UA_BROWSER, [VERSION, MAJOR]],
      [UA_ENGINE, [VERSION]],
      [UA_OS, [VERSION]]
    ]);
    setProps.call(props.isIgnoreRgx, [
      [UA_BROWSER, / ?browser$/i],
      [UA_OS, / ?os$/i]
    ]);
    setProps.call(props.toString, [
      [UA_BROWSER, [NAME, VERSION]],
      [UA_CPU, [ARCHITECTURE]],
      [UA_DEVICE, [VENDOR, MODEL]],
      [UA_ENGINE, [NAME, VERSION]],
      [UA_OS, [NAME, VERSION]]
    ]);
    return props;
  }();
  var createIData = function(item, itemType) {
    var init_props = defaultProps.init[itemType], is_ignoreProps = defaultProps.isIgnore[itemType] || 0, is_ignoreRgx = defaultProps.isIgnoreRgx[itemType] || 0, toString_props = defaultProps.toString[itemType] || 0;
    function IData() {
      setProps.call(this, init_props);
    }
    IData.prototype.getItem = function() {
      return item;
    };
    IData.prototype.withClientHints = function() {
      if (!NAVIGATOR_UADATA) {
        return item.parseCH().get();
      }
      return NAVIGATOR_UADATA.getHighEntropyValues(CH_ALL_VALUES).then(function(res) {
        return item.setCH(new UACHData(res, false)).parseCH().get();
      });
    };
    IData.prototype.withFeatureCheck = function() {
      return item.detectFeature().get();
    };
    if (itemType != UA_RESULT) {
      IData.prototype.is = function(strToCheck) {
        var is = false;
        for (var i in this) {
          if (this.hasOwnProperty(i) && !has(is_ignoreProps, i) && lowerize(is_ignoreRgx ? strip(is_ignoreRgx, this[i]) : this[i]) == lowerize(is_ignoreRgx ? strip(is_ignoreRgx, strToCheck) : strToCheck)) {
            is = true;
            if (strToCheck != UNDEF_TYPE)
              break;
          } else if (strToCheck == UNDEF_TYPE && is) {
            is = !is;
            break;
          }
        }
        return is;
      };
      IData.prototype.toString = function() {
        var str = EMPTY;
        for (var i in toString_props) {
          if (typeof this[toString_props[i]] !== UNDEF_TYPE) {
            str += (str ? " " : EMPTY) + this[toString_props[i]];
          }
        }
        return str || UNDEF_TYPE;
      };
    }
    if (!NAVIGATOR_UADATA) {
      IData.prototype.then = function(cb) {
        var that = this;
        var IDataResolve = function() {
          for (var prop in that) {
            if (that.hasOwnProperty(prop)) {
              this[prop] = that[prop];
            }
          }
        };
        IDataResolve.prototype = {
          is: IData.prototype.is,
          toString: IData.prototype.toString
        };
        var resolveData = new IDataResolve();
        cb(resolveData);
        return resolveData;
      };
    }
    return new IData();
  };
  function UACHData(uach, isHttpUACH) {
    uach = uach || {};
    setProps.call(this, CH_ALL_VALUES);
    if (isHttpUACH) {
      setProps.call(this, [
        [BRANDS, itemListToArray(uach[CH_HEADER])],
        [FULLVERLIST, itemListToArray(uach[CH_HEADER_FULL_VER_LIST])],
        [MOBILE, /\?1/.test(uach[CH_HEADER_MOBILE])],
        [MODEL, stripQuotes(uach[CH_HEADER_MODEL])],
        [PLATFORM, stripQuotes(uach[CH_HEADER_PLATFORM])],
        [PLATFORMVER, stripQuotes(uach[CH_HEADER_PLATFORM_VER])],
        [ARCHITECTURE, stripQuotes(uach[CH_HEADER_ARCH])],
        [FORMFACTORS, itemListToArray(uach[CH_HEADER_FORM_FACTORS])],
        [BITNESS, stripQuotes(uach[CH_HEADER_BITNESS])]
      ]);
    } else {
      for (var prop in uach) {
        if (this.hasOwnProperty(prop) && typeof uach[prop] !== UNDEF_TYPE)
          this[prop] = uach[prop];
      }
    }
  }
  function UAItem(itemType, ua, rgxMap, uaCH) {
    this.get = function(prop) {
      if (!prop)
        return this.data;
      return this.data.hasOwnProperty(prop) ? this.data[prop] : void 0;
    };
    this.set = function(prop, val) {
      this.data[prop] = val;
      return this;
    };
    this.setCH = function(ch) {
      this.uaCH = ch;
      return this;
    };
    this.detectFeature = function() {
      if (NAVIGATOR && NAVIGATOR.userAgent == this.ua) {
        switch (this.itemType) {
          case UA_BROWSER:
            if (NAVIGATOR.brave && typeof NAVIGATOR.brave.isBrave == FUNC_TYPE) {
              this.set(NAME, "Brave");
            }
            break;
          case UA_DEVICE:
            if (!this.get(TYPE) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[MOBILE]) {
              this.set(TYPE, MOBILE);
            }
            if (this.get(MODEL) == "Macintosh" && NAVIGATOR && typeof NAVIGATOR.standalone !== UNDEF_TYPE && NAVIGATOR.maxTouchPoints && NAVIGATOR.maxTouchPoints > 2) {
              this.set(MODEL, "iPad").set(TYPE, TABLET);
            }
            break;
          case UA_OS:
            if (!this.get(NAME) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[PLATFORM]) {
              this.set(NAME, NAVIGATOR_UADATA[PLATFORM]);
            }
            break;
          case UA_RESULT:
            var data = this.data;
            var detect = function(itemType2) {
              return data[itemType2].getItem().detectFeature().get();
            };
            this.set(UA_BROWSER, detect(UA_BROWSER)).set(UA_CPU, detect(UA_CPU)).set(UA_DEVICE, detect(UA_DEVICE)).set(UA_ENGINE, detect(UA_ENGINE)).set(UA_OS, detect(UA_OS));
        }
      }
      return this;
    };
    this.parseUA = function() {
      if (this.itemType != UA_RESULT) {
        rgxMapper.call(this.data, this.ua, this.rgxMap);
      }
      if (this.itemType == UA_BROWSER) {
        this.set(MAJOR, majorize(this.get(VERSION)));
      }
      return this;
    };
    this.parseCH = function() {
      var uaCH2 = this.uaCH, rgxMap2 = this.rgxMap;
      switch (this.itemType) {
        case UA_BROWSER:
          var brands = uaCH2[FULLVERLIST] || uaCH2[BRANDS], prevName;
          if (brands) {
            for (var i in brands) {
              var brandName = strip(/(Google|Microsoft) /, brands[i].brand || brands[i]), brandVersion = brands[i].version;
              if (!/not.a.brand/i.test(brandName) && (!prevName || /chrom/i.test(prevName) && !/chromi/i.test(brandName))) {
                this.set(NAME, brandName).set(VERSION, brandVersion).set(MAJOR, majorize(brandVersion));
                prevName = brandName;
              }
            }
          }
          break;
        case UA_CPU:
          var archName = uaCH2[ARCHITECTURE];
          if (archName) {
            if (archName && uaCH2[BITNESS] == "64")
              archName += "64";
            rgxMapper.call(this.data, archName + ";", rgxMap2);
          }
          break;
        case UA_DEVICE:
          if (uaCH2[MOBILE]) {
            this.set(TYPE, MOBILE);
          }
          if (uaCH2[MODEL]) {
            this.set(MODEL, uaCH2[MODEL]);
          }
          if (uaCH2[MODEL] == "Xbox") {
            this.set(TYPE, CONSOLE).set(VENDOR, MICROSOFT);
          }
          if (uaCH2[FORMFACTORS]) {
            var ff;
            if (typeof uaCH2[FORMFACTORS] !== "string") {
              var idx = 0;
              while (!ff && idx < uaCH2[FORMFACTORS].length) {
                ff = strMapper(uaCH2[FORMFACTORS][idx++], formFactorsMap);
              }
            } else {
              ff = strMapper(uaCH2[FORMFACTORS], formFactorsMap);
            }
            this.set(TYPE, ff);
          }
          break;
        case UA_OS:
          var osName = uaCH2[PLATFORM];
          if (osName) {
            var osVersion = uaCH2[PLATFORMVER];
            if (osName == WINDOWS)
              osVersion = parseInt(majorize(osVersion), 10) >= 13 ? "11" : "10";
            this.set(NAME, osName).set(VERSION, osVersion);
          }
          if (this.get(NAME) == WINDOWS && uaCH2[MODEL] == "Xbox") {
            this.set(NAME, "Xbox").set(VERSION, void 0);
          }
          break;
        case UA_RESULT:
          var data = this.data;
          var parse2 = function(itemType2) {
            return data[itemType2].getItem().setCH(uaCH2).parseCH().get();
          };
          this.set(UA_BROWSER, parse2(UA_BROWSER)).set(UA_CPU, parse2(UA_CPU)).set(UA_DEVICE, parse2(UA_DEVICE)).set(UA_ENGINE, parse2(UA_ENGINE)).set(UA_OS, parse2(UA_OS));
      }
      return this;
    };
    setProps.call(this, [
      ["itemType", itemType],
      ["ua", ua],
      ["uaCH", uaCH],
      ["rgxMap", rgxMap],
      ["data", createIData(this, itemType)]
    ]);
    return this;
  }
  function UAParser(ua, extensions, headers) {
    if (typeof ua === OBJ_TYPE) {
      if (isExtensions(ua, true)) {
        if (typeof extensions === OBJ_TYPE) {
          headers = extensions;
        }
        extensions = ua;
      } else {
        headers = ua;
        extensions = void 0;
      }
      ua = void 0;
    } else if (typeof ua === STR_TYPE && !isExtensions(extensions, true)) {
      headers = extensions;
      extensions = void 0;
    }
    if (!(this instanceof UAParser)) {
      return new UAParser(ua, extensions, headers).getResult();
    }
    var userAgent2 = typeof ua === STR_TYPE ? ua : (
      // Passed user-agent string
      NAVIGATOR && NAVIGATOR.userAgent ? NAVIGATOR.userAgent : (
        // navigator.userAgent
        headers && headers[USER_AGENT] ? headers[USER_AGENT] : (
          // User-Agent from passed headers
          EMPTY
        )
      )
    ), httpUACH = new UACHData(headers, true), regexMap = extensions ? extend(defaultRegexes, extensions) : defaultRegexes, createItemFunc = function(itemType) {
      if (itemType == UA_RESULT) {
        return function() {
          return new UAItem(itemType, userAgent2, regexMap, httpUACH).set("ua", userAgent2).set(UA_BROWSER, this.getBrowser()).set(UA_CPU, this.getCPU()).set(UA_DEVICE, this.getDevice()).set(UA_ENGINE, this.getEngine()).set(UA_OS, this.getOS()).get();
        };
      } else {
        return function() {
          return new UAItem(itemType, userAgent2, regexMap[itemType], httpUACH).parseUA().get();
        };
      }
    };
    setProps.call(this, [
      ["getBrowser", createItemFunc(UA_BROWSER)],
      ["getCPU", createItemFunc(UA_CPU)],
      ["getDevice", createItemFunc(UA_DEVICE)],
      ["getEngine", createItemFunc(UA_ENGINE)],
      ["getOS", createItemFunc(UA_OS)],
      ["getResult", createItemFunc(UA_RESULT)],
      ["getUA", function() {
        return userAgent2;
      }],
      ["setUA", function(ua2) {
        if (isString(ua2))
          userAgent2 = ua2.length > UA_MAX_LENGTH ? trim(ua2, UA_MAX_LENGTH) : ua2;
        return this;
      }]
    ]).setUA(userAgent2);
    return this;
  }
  UAParser.VERSION = LIBVERSION;
  UAParser.BROWSER = enumerize([NAME, VERSION, MAJOR, TYPE]);
  UAParser.CPU = enumerize([ARCHITECTURE]);
  UAParser.DEVICE = enumerize([MODEL, VENDOR, TYPE, CONSOLE, MOBILE, SMARTTV, TABLET, WEARABLE, EMBEDDED]);
  UAParser.ENGINE = UAParser.OS = enumerize([NAME, VERSION]);
  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 = _unsafeWindow.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 root = chordName.match(/^[A-G]#?/)[0];
    const rest = chordName.replace(/^[A-G]#?/, "");
    return `${rest} ${root}`;
  }
  const userAgent = UAParser(navigator.userAgent);
  const _hoisted_1$b = { id: "plus91-sheet-popup" };
  const _hoisted_2$a = { class: "sheet-popup-container" };
  const _hoisted_3$4 = { class: "text-capo" };
  const _hoisted_4$2 = ["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$4, vue.toDisplayString(vue.unref(store).currentCapo), 1),
                    vue.createTextVNode(" ("),
                    vue.createElementVNode("span", {
                      class: "text-key",
                      innerHTML: vue.unref(store).currentKey
                    }, null, 8, _hoisted_4$2),
                    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 _hoisted_1$a = {
    key: 0,
    class: "chord-container"
  };
  const _hoisted_2$9 = { class: "chord-name" };
  const _hoisted_3$3 = ["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 width = chordRef.value.clientWidth;
          const chordBoxSelector = `.chord-chart[chord-name="${props.chord}"]`;
          const chordBox = new vexchords.ChordBox(chordBoxSelector, {
            width,
            height: width * 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$3)
        ])) : vue.createCommentVNode("", true);
      };
    }
  };
  const ChordChart = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["__scopeId", "data-v-735734f6"]]);
  const _hoisted_1$9 = { class: "banner" };
  const _hoisted_2$8 = { class: "chord-popup-container" };
  const _sfc_main$a = {
    __name: "ChordPopup",
    setup(__props) {
      const store = useStore();
      const canShowChord = vue.ref(true);
      if (userAgent.browser.name === "Mobile Safari") {
        canShowChord.value = false;
      }
      const bannerText = vue.ref("");
      const bannerTextList = [
        "此處的和弦圖示僅供參考!由於技術問題,目前尚無法準確繪製,尤其在把位較常出現錯誤,請注意。",
        "在 91 譜中沒有資料的和弦是畫不出來的呦!"
      ];
      const randomIndex = vue.ref(0);
      const refreshBanner = () => {
        if (!canShowChord.value) {
          bannerText.value = "很抱歉,由於技術問題,你所使用的瀏覽器目前尚無法繪製出和弦圖,開發者正在試著修正這個問題,敬請期待更新。";
        } else {
          randomIndex.value = Math.floor(Math.random() * bannerTextList.length);
          bannerText.value = bannerTextList[randomIndex.value];
        }
      };
      const chordList = vue.ref([]);
      vue.watch(store.isPopupShow, () => {
        if (!store.isPopupShow.chord) {
          return;
        }
        refreshBanner();
        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", {
              id: "plus91-chord-popup",
              class: vue.normalizeClass({ "banner-only": !chordList.value.length })
            }, [
              vue.createElementVNode("div", _hoisted_1$9, [
                vue.createVNode(BootstrapIcon, {
                  icon: "info-circle-fill",
                  color: "inherit",
                  size: "inherit"
                }),
                vue.createElementVNode("section", null, vue.toDisplayString(bannerText.value), 1)
              ]),
              vue.createElementVNode("div", _hoisted_2$8, [
                (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))
              ])
            ], 2), [
              [vue.vShow, vue.unref(store).isPopupShow.chord]
            ])
          ]),
          _: 1
        });
      };
    }
  };
  const ChordPopup = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["__scopeId", "data-v-2210cdf0"]]);
  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 BUTTON_COLOR = "#555";
  const _sfc_main$6 = {
    __name: "MenuPopup",
    setup(__props) {
      const store = useStore();
      const captureAsImage = () => {
        const content = document.querySelector("section.content");
        html2canvas(content).then((canvas) => {
          const newWindow = window.open();
          newWindow.document.write(`<img src="${canvas.toDataURL()}" />`);
        });
      };
      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: BUTTON_COLOR,
                  onClick: _cache[0] || (_cache[0] = () => {
                    vue.unref(store).togglePopup("hotkey");
                  })
                }),
                vue.createVNode(MenuButton, {
                  icon: "file-earmark-image",
                  name: "擷取為圖片",
                  color: BUTTON_COLOR,
                  onClick: captureAsImage
                }),
                vue.createVNode(MenuButton, {
                  icon: "youtube",
                  name: "搜尋 YouTube",
                  color: BUTTON_COLOR,
                  onClick: searchOnYoutube
                }),
                vue.createVNode(MenuButton, {
                  icon: "github",
                  name: "關於 91 Plus",
                  color: BUTTON_COLOR,
                  onClick: goToGithubPage
                })
              ])
            ], 512), [
              [vue.vShow, vue.unref(store).isPopupShow.menu]
            ])
          ]),
          _: 1
        });
      };
    }
  };
  const MenuPopup = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["__scopeId", "data-v-47af8eb5"]]);
  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", {
                key: `${key}_${__props.hotkey}_${__props.desc}`
              }, vue.toDisplayString(key), 1);
            }), 128))
          ])) : (vue.openBlock(), vue.createElementBlock("div", _hoisted_3$1))
        ]);
      };
    }
  };
  const HotkeyItem = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__scopeId", "data-v-3c43f6cf"]]);
  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, index) => {
                    return vue.openBlock(), vue.createBlock(HotkeyItem, {
                      key: `${item.hotkey}_${item.desc}_${index}`,
                      hotkey: item.hotkey,
                      desc: item.desc
                    }, null, 8, ["hotkey", "desc"]);
                  }), 128))
                ]),
                vue.createElementVNode("section", _hoisted_4, [
                  (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(vue.unref(hotkeyData).hotkeysRight, (item, index) => {
                    return vue.openBlock(), vue.createBlock(HotkeyItem, {
                      key: `${item.hotkey}_${item.desc}_${index}`,
                      hotkey: item.hotkey,
                      desc: item.desc
                    }, null, 8, ["hotkey", "desc"]);
                  }), 128))
                ])
              ])
            ], 512), [
              [vue.vShow, vue.unref(store).isPopupShow.hotkey]
            ])
          ]),
          _: 1
        });
      };
    }
  };
  const HotkeyPopup = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-eb86b87c"]]);
  const _hoisted_1$2 = { id: "plus91-footer" };
  const _hoisted_2$1 = { class: "footer-container" };
  const _sfc_main$3 = {
    __name: "AppFooter",
    props: {
      active: Boolean
    },
    setup(__props) {
      const store = useStore();
      const props = __props;
      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",
                  text: "譜面",
                  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",
                  text: "和弦",
                  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",
                  text: "字型",
                  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",
                  text: "設定",
                  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",
                  text: "其他",
                  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 AppFooter = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-4e274b3c"]]);
  const _hoisted_1$1 = { id: "plus91-header" };
  const _hoisted_2 = { class: "header-container" };
  const _sfc_main$2 = {
    __name: "AppHeader",
    props: {
      active: Boolean
    },
    setup(__props) {
      const props = __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();
        searchText.value = "";
      };
      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 AppHeader = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-5ddafe3d"]]);
  const _hoisted_1 = { id: "dark-mode-overlay" };
  const _sfc_main$1 = {
    __name: "DarkModeOverlay",
    props: {
      active: Boolean
    },
    setup(__props) {
      const props = __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-6cf58435"]]);
  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(AppHeader, {
            active: vue.unref(store).isToolbarsShow
          }, null, 8, ["active"]),
          vue.createVNode(AppFooter, {
            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, zipson, vexchords, html2canvas);