93Akkord / google-search-extended

// ==UserScript==
// @name        google-search-extended
// @namespace   https://openuserjs.org/users/93Akkord
// @version     0.2.14
// @description Google Search Extended
// @license     MIT
// @author      93Akkord
// @namespace   https://github.com/93Akkord
// @match       https:\/\/*.google.com\/search?*
// @include     /^https?:\/\/(?:www|encrypted|ipv[46])\.google\.[^/]+/(?:$|[#?]|search|webhp)/
// @run-at      document-start
// @grant		unsafeWindow
// @grant       GM.registerMenuCommand
// @grant       GM_registerMenuCommand
// @grant       GM_unregisterMenuCommand
// @grant       GM_xmlhttpRequest
// @grant       GM_getValue
// @grant       GM_setValue
// @grant       GM_listValues
// @connect     *
// @require     https://code.jquery.com/jquery-3.2.1.min.js
// @require     https://cdn.jsdelivr.net/npm/arrive@2.4.1/src/arrive.min.js
// @require     https://openuserjs.org/src/libs/93Akkord/akkd-common.js
// @copyright   2022+, Michael Barros (https://openuserjs.org/users/93Akkord)
// @license     CC-BY-NC-SA-4.0; https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
// @license     GPL-3.0-or-later; https://www.gnu.org/licenses/gpl-3.0.txt
// @icon        https://www.google.com/favicon.ico
// @updateURL   https://openuserjs.org/meta/93Akkord/google-search-extended.meta.js
// @downloadURL https://openuserjs.org/install/93Akkord/google-search-extended.user.js
// ==/UserScript==

// Add `Available nearby` to any `shopping result`.  Add to following to the url: &tbs=local_avail:1

(async function () {
    const ls = new LocalStorageEx();
    const DEV_TAG = '[akkd]';

    let DEBUG = ls.get('google-search-extended-debug', false);

    // #region Helper Functions

    /**
     * Get difference in days between two dates.
     *
     * @param {Date} a
     * @param {Date} b
     * @returns
     */
    function dateDiffInDays(a, b) {
        let _MS_PER_DAY = 1000 * 60 * 60 * 24;

        // Discard the time and time-zone information.
        let utc1 = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());
        let utc2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());

        return Math.floor((utc1 - utc2) / _MS_PER_DAY);
    }

    /**
     *
     *
     * @author Michael Barros <michaelcbarros@gmail.com>
     * @param {any[]} msg
     */
    function logDebug(...msg) {
        if (DEBUG) {
            console.debug(DEV_TAG, ...msg);
        }
    }

    /**
     *
     *
     * @author Michael Barros <michaelcbarros@gmail.com>
     * @param {boolean} [init=false]
     */
    function registerDebugMenuCommand(init = false) {
        if (!init) {
            DEBUG = !DEBUG;

            ls.set('google-search-extended-debug', DEBUG);
        }

        let debugMenuCommandID = GM_registerMenuCommand(`Debug ${DEBUG ? 'on' : 'off'}`, () => {
            GM_unregisterMenuCommand(debugMenuCommandID);

            registerDebugMenuCommand();
        });
    }

    /**
     *
     *
     * @author Michael Barros <michaelcbarros@gmail.com>
     * @param {string} text
     * @param {string} [nodeType='div']
     * @returns {HTMLElement}
     */
    function getElementByTextContent(text, nodeType = 'div') {
        let xpath = `//${nodeType}[text()='${text}']`;

        /** @type {HTMLElement} */
        let elem = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

        return elem;
    }

    /**
     *
     *
     * @author Michael Barros <michaelcbarros@gmail.com>
     * @param {string} text
     * @param {string} [nodeType='div']
     * @returns {HTMLElement}
     */
    function getElementByTextContentContains(text, nodeType = 'div') {
        let xpath = `//${nodeType}[contains(text(),'${text}')]`;

        /** @type {HTMLElement} */
        let elem = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

        return elem;
    }

    // #endregion Helper Functions

    // #region Sites Menu

    // #region Icon Data URIs

    let pypiUri = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2NS44MTIiIGhlaWdodD0iNTgiIHZpZXdCb3g9IjAgMCA2NS44MTIwMzUgNTguMDAwMDAxIj48ZyBmaWxsPSIjYTI5ZDg2IiBzdHJva2U9IiNjY2MiIHN0cm9rZS13aWR0aD0iLjIxNCIgc3Ryb2tlLWxpbmVqb2luPSJiZXZlbCI+PHBhdGggZD0iTTE4LjkzIDE4LjgyNmw5LjMyMyAzLjM5NHYxMC45NTdsLTkuMzIzLTMuMzk0eiIgc3R5bGU9Imlzb2xhdGlvbjphdXRvO21peC1ibGVuZC1tb2RlOm5vcm1hbCIgY29sb3I9IiMwMDAiIG92ZXJmbG93PSJ2aXNpYmxlIiBmaWxsPSIjZTllOWZmIi8+PHBhdGggZD0iTTkuNDcgMjIuMjd2MTAuOTU3bDkuNDYtMy40NDRWMTguODI2eiIgc3R5bGU9Imlzb2xhdGlvbjphdXRvO21peC1ibGVuZC1tb2RlOm5vcm1hbCIgY29sb3I9IiMwMDAiIG92ZXJmbG93PSJ2aXNpYmxlIiBmaWxsPSIjMzUzNTY0Ii8+PHBhdGggZD0iTTkuNDcgMzMuMjI3bDkuMzIyIDMuMzkzIDkuNDYtMy40NDMtOS4zMjItMy4zOTR6IiBzdHlsZT0iaXNvbGF0aW9uOmF1dG87bWl4LWJsZW5kLW1vZGU6bm9ybWFsIiBjb2xvcj0iIzAwMCIgb3ZlcmZsb3c9InZpc2libGUiIGZpbGw9IiNhZmFmZGUiLz48cGF0aCBkPSJNOS40NyAyMi4yN2w5LjMyMiAzLjM5MyA5LjQ2LTMuNDQzLTkuMzIyLTMuMzk0eiIgZmlsbD0iI2Y3ZjdmNCIvPjxwYXRoIGQ9Ik0xOC43OTIgMjUuNjYzVjM2LjYybDkuNDYtMy40NDNWMjIuMjJ6IiBmaWxsPSIjZmZmIi8+PHBhdGggZD0iTTkuNDcgMjIuMjdsOS4zMjIgMy4zOTNWMzYuNjJMOS40NyAzMy4yMjd6IiBmaWxsPSIjZWZlZWVhIi8+PHBhdGggc3R5bGU9Imlzb2xhdGlvbjphdXRvO21peC1ibGVuZC1tb2RlOm5vcm1hbCIgZD0iTTI4LjI5MyAxMS4xNjZsOS4zMjMgMy4zOTN2MTAuOTU3bC05LjMyMy0zLjM5M3oiIGNvbG9yPSIjMDAwIiBvdmVyZmxvdz0idmlzaWJsZSIgZmlsbD0iI2U5ZTlmZiIvPjxwYXRoIHN0eWxlPSJpc29sYXRpb246YXV0bzttaXgtYmxlbmQtbW9kZTpub3JtYWwiIGQ9Ik0xOC44MzMgMTQuNjA5djEwLjk1N2w5LjQ2LTMuNDQzVjExLjE2NnoiIGNvbG9yPSIjMDAwIiBvdmVyZmxvdz0idmlzaWJsZSIgZmlsbD0iIzM1MzU2NCIvPjxwYXRoIHN0eWxlPSJpc29sYXRpb246YXV0bzttaXgtYmxlbmQtbW9kZTpub3JtYWwiIGQ9Ik0xOC44MzMgMjUuNTY2bDkuMzIyIDMuMzkzIDkuNDYxLTMuNDQzLTkuMzIzLTMuMzkzeiIgY29sb3I9IiMwMDAiIG92ZXJmbG93PSJ2aXNpYmxlIiBmaWxsPSIjYWZhZmRlIi8+PHBhdGggZD0iTTE4LjgzMyAxNC42MDlsOS4zMjIgMy4zOTMgOS40NjEtMy40NDMtOS4zMjMtMy4zOTN6IiBmaWxsPSIjZjdmN2Y0Ii8+PHBhdGggZD0iTTI4LjE1NSAxOC4wMDJWMjguOTZsOS40NjEtMy40NDNWMTQuNTU5eiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik0xOC44MzMgMTQuNjA5bDkuMzIyIDMuMzkzVjI4Ljk2bC05LjMyMi0zLjM5M3oiIGZpbGw9IiNlZmVlZWEiLz48cGF0aCBkPSJNOS41NjcgMzMuMjk3bDkuMzIyIDMuMzkzdjEwLjk1N2wtOS4zMjItMy4zOTN6IiBzdHlsZT0iaXNvbGF0aW9uOmF1dG87bWl4LWJsZW5kLW1vZGU6bm9ybWFsIiBjb2xvcj0iIzAwMCIgb3ZlcmZsb3c9InZpc2libGUiIGZpbGw9IiNlOWU5ZmYiLz48cGF0aCBkPSJNLjEwNiAzNi43NHYxMC45NTdsOS40Ni0zLjQ0M1YzMy4yOTd6IiBzdHlsZT0iaXNvbGF0aW9uOmF1dG87bWl4LWJsZW5kLW1vZGU6bm9ybWFsIiBjb2xvcj0iIzAwMCIgb3ZlcmZsb3c9InZpc2libGUiIGZpbGw9IiMzNTM1NjQiLz48cGF0aCBkPSJNLjEwNiA0Ny42OTdMOS40MyA1MS4wOWw5LjQ2LTMuNDQzLTkuMzIyLTMuMzkzeiIgc3R5bGU9Imlzb2xhdGlvbjphdXRvO21peC1ibGVuZC1tb2RlOm5vcm1hbCIgY29sb3I9IiMwMDAiIG92ZXJmbG93PSJ2aXNpYmxlIiBmaWxsPSIjYWZhZmRlIi8+PHBhdGggZD0iTS4xMDYgMzYuNzRsOS4zMjMgMy4zOTMgOS40Ni0zLjQ0My05LjMyMi0zLjM5M3oiIGZpbGw9IiNmN2Y3ZjQiLz48cGF0aCBkPSJNOS40MjkgNDAuMTMzVjUxLjA5bDkuNDYtMy40NDNWMzYuNjl6IiBmaWxsPSIjZmZmIi8+PHBhdGggZD0iTS4xMDYgMzYuNzRsOS4zMjMgMy4zOTNWNTEuMDlMLjEwNiA0Ny42OTd6IiBmaWxsPSIjZWZlZWVhIi8+PC9nPjxnIGZpbGw9IiNhMjlkODYiIHN0cm9rZT0iI2NjYyIgc3Ryb2tlLXdpZHRoPSIuMjE0IiBzdHJva2UtbGluZWpvaW49ImJldmVsIj48cGF0aCBzdHlsZT0iaXNvbGF0aW9uOmF1dG87bWl4LWJsZW5kLW1vZGU6bm9ybWFsIiBkPSJNMTguOTMgMzYuNzAybDkuMzIzIDMuMzkzdjEwLjk1N2wtOS4zMjMtMy4zOTN6IiBjb2xvcj0iIzAwMCIgb3ZlcmZsb3c9InZpc2libGUiIGZpbGw9IiNlOWU5ZmYiLz48cGF0aCBzdHlsZT0iaXNvbGF0aW9uOmF1dG87bWl4LWJsZW5kLW1vZGU6bm9ybWFsIiBkPSJNOS40NyA0MC4xNDV2MTAuOTU3bDkuNDYtMy40NDNWMzYuNzAyeiIgY29sb3I9IiMwMDAiIG92ZXJmbG93PSJ2aXNpYmxlIiBmaWxsPSIjMzUzNTY0Ii8+PHBhdGggc3R5bGU9Imlzb2xhdGlvbjphdXRvO21peC1ibGVuZC1tb2RlOm5vcm1hbCIgZD0iTTkuNDcgNTEuMTAybDkuMzIyIDMuMzkzIDkuNDYtMy40NDMtOS4zMjItMy4zOTN6IiBjb2xvcj0iIzAwMCIgb3ZlcmZsb3c9InZpc2libGUiIGZpbGw9IiNhZmFmZGUiLz48cGF0aCBkPSJNOS40NyA0MC4xNDVsOS4zMjIgMy4zOTMgOS40Ni0zLjQ0My05LjMyMi0zLjM5M3oiIGZpbGw9IiNmN2Y3ZjQiLz48cGF0aCBkPSJNMTguNzkyIDQzLjUzOHYxMC45NTdsOS40Ni0zLjQ0M1Y0MC4wOTV6IiBmaWxsPSIjZmZmIi8+PHBhdGggZD0iTTkuNDcgNDAuMTQ1bDkuMzIyIDMuMzkzdjEwLjk1N0w5LjQ3IDUxLjEwMnoiIGZpbGw9IiNlZmVlZWEiLz48L2c+PGcgZmlsbD0iI2EyOWQ4NiIgc3Ryb2tlPSIjY2NjIiBzdHJva2Utd2lkdGg9Ii4yMTQiIHN0cm9rZS1saW5lam9pbj0iYmV2ZWwiPjxwYXRoIGQ9Ik0xOC45MyAyNS42MzZsOS4zMjMgMy4zOTN2MTAuOTU3bC05LjMyMy0zLjM5M3oiIHN0eWxlPSJpc29sYXRpb246YXV0bzttaXgtYmxlbmQtbW9kZTpub3JtYWwiIGNvbG9yPSIjMDAwIiBvdmVyZmxvdz0idmlzaWJsZSIgZmlsbD0iI2U5ZTlmZiIvPjxwYXRoIGQ9Ik05LjQ3IDI5LjA4djEwLjk1Nmw5LjQ2LTMuNDQzVjI1LjYzNnoiIHN0eWxlPSJpc29sYXRpb246YXV0bzttaXgtYmxlbmQtbW9kZTpub3JtYWwiIGNvbG9yPSIjMDAwIiBvdmVyZmxvdz0idmlzaWJsZSIgZmlsbD0iIzM1MzU2NCIvPjxwYXRoIGQ9Ik05LjQ3IDQwLjAzNmw5LjMyMiAzLjM5NCA5LjQ2LTMuNDQ0LTkuMzIyLTMuMzkzeiIgc3R5bGU9Imlzb2xhdGlvbjphdXRvO21peC1ibGVuZC1tb2RlOm5vcm1hbCIgY29sb3I9IiMwMDAiIG92ZXJmbG93PSJ2aXNpYmxlIiBmaWxsPSIjYWZhZmRlIi8+PHBhdGggZD0iTTkuNDcgMjkuMDhsOS4zMjIgMy4zOTMgOS40Ni0zLjQ0NC05LjMyMi0zLjM5M3oiIGZpbGw9IiNmN2Y3ZjQiLz48cGF0aCBkPSJNMTguNzkyIDMyLjQ3M1Y0My40M2w5LjQ2LTMuNDQ0VjI5LjAzeiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik05LjQ3IDI5LjA4bDkuMzIyIDMuMzkzVjQzLjQzTDkuNDcgNDAuMDM2eiIgZmlsbD0iI2VmZWVlYSIvPjwvZz48ZyBmaWxsPSIjYTI5ZDg2IiBzdHJva2U9IiNjY2MiIHN0cm9rZS13aWR0aD0iLjIxNCIgc3Ryb2tlLWxpbmVqb2luPSJiZXZlbCI+PHBhdGggc3R5bGU9Imlzb2xhdGlvbjphdXRvO21peC1ibGVuZC1tb2RlOm5vcm1hbCIgZD0iTTU2LjM4MyAyOS44OTJsOS4zMjMgMy4zOTN2MTAuOTU3bC05LjMyMy0zLjM5M3oiIGNvbG9yPSIjMDAwIiBvdmVyZmxvdz0idmlzaWJsZSIgZmlsbD0iI2U5ZTlmZiIvPjxwYXRoIHN0eWxlPSJpc29sYXRpb246YXV0bzttaXgtYmxlbmQtbW9kZTpub3JtYWwiIGQ9Ik00Ni45MjMgMzMuMzM1djEwLjk1N2w5LjQ2LTMuNDQzVjI5Ljg5MnoiIGNvbG9yPSIjMDAwIiBvdmVyZmxvdz0idmlzaWJsZSIgZmlsbD0iIzM1MzU2NCIvPjxwYXRoIHN0eWxlPSJpc29sYXRpb246YXV0bzttaXgtYmxlbmQtbW9kZTpub3JtYWwiIGQ9Ik00Ni45MjMgNDQuMjkybDkuMzIyIDMuMzk0IDkuNDYtMy40NDQtOS4zMjItMy4zOTN6IiBjb2xvcj0iIzAwMCIgb3ZlcmZsb3c9InZpc2libGUiIGZpbGw9IiNhZmFmZGUiLz48cGF0aCBkPSJNNDYuOTIzIDMzLjMzNWw5LjMyMiAzLjM5NCA5LjQ2LTMuNDQ0LTkuMzIyLTMuMzkzeiIgZmlsbD0iI2Y3ZjdmNCIvPjxwYXRoIGQ9Ik01Ni4yNDUgMzYuNzI5djEwLjk1N2w5LjQ2LTMuNDQ0VjMzLjI4NXoiIGZpbGw9IiNmZmYiLz48cGF0aCBkPSJNNDYuOTIzIDMzLjMzNWw5LjMyMiAzLjM5NHYxMC45NTdsLTkuMzIyLTMuMzk0eiIgZmlsbD0iI2VmZWVlYSIvPjwvZz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTY4My42NiAtNTEzLjI3NSkgc2NhbGUoLjY1MTc3KSI+PGcgZmlsbD0iI2EyOWQ4NiIgc3Ryb2tlPSIjY2NjIiBzdHJva2Utd2lkdGg9Ii4zMjgiIHN0cm9rZS1saW5lam9pbj0iYmV2ZWwiPjxwYXRoIHN0eWxlPSJpc29sYXRpb246YXV0bzttaXgtYmxlbmQtbW9kZTpub3JtYWwiIGQ9Ik0yNjU1LjM0OSA4MzguNTk0bDE0LjMwMyA1LjIwNnYxNi44MTFsLTE0LjMwMy01LjIwNnoiIGNvbG9yPSIjMDAwIiBvdmVyZmxvdz0idmlzaWJsZSIgZmlsbD0iI2U5ZTlmZiIvPjxwYXRoIHN0eWxlPSJpc29sYXRpb246YXV0bzttaXgtYmxlbmQtbW9kZTpub3JtYWwiIGQ9Ik0yNjQwLjgzNCA4NDMuODc3djE2LjgxMWwxNC41MTUtNS4yODN2LTE2LjgxeiIgY29sb3I9IiMwMDAiIG92ZXJmbG93PSJ2aXNpYmxlIiBmaWxsPSIjMzUzNTY0Ii8+PHBhdGggc3R5bGU9Imlzb2xhdGlvbjphdXRvO21peC1ibGVuZC1tb2RlOm5vcm1hbCIgZD0iTTI2NDAuODM0IDg2MC42ODhsMTQuMzAzIDUuMjA2IDE0LjUxNS01LjI4My0xNC4zMDMtNS4yMDZ6IiBjb2xvcj0iIzAwMCIgb3ZlcmZsb3c9InZpc2libGUiIGZpbGw9IiNhZmFmZGUiLz48cGF0aCBkPSJNMjY0MC44MzQgODQzLjg3N2wxNC4zMDMgNS4yMDYgMTQuNTE1LTUuMjgzLTE0LjMwMy01LjIwNnoiIGZpbGw9IiNmN2Y3ZjQiLz48cGF0aCBkPSJNMjY1NS4xMzcgODQ5LjA4M3YxNi44MTFsMTQuNTE1LTUuMjgzdi0xNi44MXoiIGZpbGw9IiNmZmQyNDIiLz48cGF0aCBkPSJNMjY0MC44MzQgODQzLjg3N2wxNC4zMDMgNS4yMDZ2MTYuODExbC0xNC4zMDMtNS4yMDZ6IiBmaWxsPSIjZWZlZWVhIi8+PC9nPjxjaXJjbGUgdHJhbnNmb3JtPSJza2V3WSgtMjApIHNjYWxlKC45Mzk3IDEpIiBjeT0iMTgyMy44OTkiIGN4PSIyODM1LjIxOCIgcj0iMi45NjciIGZpbGw9IiNmZmYiLz48L2c+PGcgZmlsbD0iI2EyOWQ4NiIgc3Ryb2tlPSIjY2NjIiBzdHJva2Utd2lkdGg9Ii4yMTQiIHN0cm9rZS1saW5lam9pbj0iYmV2ZWwiPjxwYXRoIGQ9Ik0zNy42NTcgMzYuNzAybDkuMzIyIDMuMzkzdjEwLjk1N2wtOS4zMjItMy4zOTN6IiBzdHlsZT0iaXNvbGF0aW9uOmF1dG87bWl4LWJsZW5kLW1vZGU6bm9ybWFsIiBjb2xvcj0iIzAwMCIgb3ZlcmZsb3c9InZpc2libGUiIGZpbGw9IiNlOWU5ZmYiLz48cGF0aCBkPSJNMjguMTk2IDQwLjE0NXYxMC45NTdsOS40Ni0zLjQ0M1YzNi43MDJ6IiBzdHlsZT0iaXNvbGF0aW9uOmF1dG87bWl4LWJsZW5kLW1vZGU6bm9ybWFsIiBjb2xvcj0iIzAwMCIgb3ZlcmZsb3c9InZpc2libGUiIGZpbGw9IiMzNTM1NjQiLz48cGF0aCBkPSJNMjguMTk2IDUxLjEwMmw5LjMyMyAzLjM5MyA5LjQ2LTMuNDQzLTkuMzIyLTMuMzkzeiIgc3R5bGU9Imlzb2xhdGlvbjphdXRvO21peC1ibGVuZC1tb2RlOm5vcm1hbCIgY29sb3I9IiMwMDAiIG92ZXJmbG93PSJ2aXNpYmxlIiBmaWxsPSIjYWZhZmRlIi8+PHBhdGggZD0iTTI4LjE5NiA0MC4xNDVsOS4zMjMgMy4zOTMgOS40Ni0zLjQ0My05LjMyMi0zLjM5M3oiIGZpbGw9IiNmN2Y3ZjQiLz48cGF0aCBkPSJNMzcuNTE5IDQzLjUzOHYxMC45NTdsOS40Ni0zLjQ0M1Y0MC4wOTV6IiBmaWxsPSIjZmZkMjQyIi8+PHBhdGggZD0iTTI4LjE5NiA0MC4xNDVsOS4zMjMgMy4zOTN2MTAuOTU3bC05LjMyMy0zLjM5M3oiIGZpbGw9IiNlZmVlZWEiLz48L2c+PGcgZmlsbD0iI2EyOWQ4NiIgc3Ryb2tlPSIjY2NjIiBzdHJva2Utd2lkdGg9Ii4yMTQiIHN0cm9rZS1saW5lam9pbj0iYmV2ZWwiPjxwYXRoIHN0eWxlPSJpc29sYXRpb246YXV0bzttaXgtYmxlbmQtbW9kZTpub3JtYWwiIGQ9Ik0yOC4yOTMgNDAuMTA3bDkuMzIzIDMuMzkzdjEwLjk1N2wtOS4zMjMtMy4zOTN6IiBjb2xvcj0iIzAwMCIgb3ZlcmZsb3c9InZpc2libGUiIGZpbGw9IiNlOWU5ZmYiLz48cGF0aCBzdHlsZT0iaXNvbGF0aW9uOmF1dG87bWl4LWJsZW5kLW1vZGU6bm9ybWFsIiBkPSJNMTguODMzIDQzLjU1djEwLjk1N2w5LjQ2LTMuNDQzVjQwLjEwN3oiIGNvbG9yPSIjMDAwIiBvdmVyZmxvdz0idmlzaWJsZSIgZmlsbD0iIzM1MzU2NCIvPjxwYXRoIHN0eWxlPSJpc29sYXRpb246YXV0bzttaXgtYmxlbmQtbW9kZTpub3JtYWwiIGQ9Ik0xOC44MzMgNTQuNTA3bDkuMzIyIDMuMzkzIDkuNDYtMy40NDMtOS4zMjItMy4zOTN6IiBjb2xvcj0iIzAwMCIgb3ZlcmZsb3c9InZpc2libGUiIGZpbGw9IiNhZmFmZGUiLz48cGF0aCBkPSJNMTguODMzIDQzLjU1bDkuMzIyIDMuMzkzIDkuNDYtMy40NDMtOS4zMjItMy4zOTN6IiBmaWxsPSIjZjdmN2Y0Ii8+PHBhdGggZD0iTTI4LjE1NSA0Ni45NDNWNTcuOWw5LjQ2LTMuNDQzVjQzLjV6IiBmaWxsPSIjZmZmIi8+PHBhdGggZD0iTTE4LjgzMyA0My41NWw5LjMyMiAzLjM5M1Y1Ny45bC05LjMyMi0zLjM5M3oiIGZpbGw9IiNlZmVlZWEiLz48L2c+PGcgZmlsbD0iI2EyOWQ4NiIgc3Ryb2tlPSIjY2NjIiBzdHJva2Utd2lkdGg9Ii4yMTQiIHN0cm9rZS1saW5lam9pbj0iYmV2ZWwiPjxwYXRoIGQ9Ik01Ni4zODMgMTguODI2bDkuMzIzIDMuMzk0djEwLjk1N2wtOS4zMjMtMy4zOTR6IiBzdHlsZT0iaXNvbGF0aW9uOmF1dG87bWl4LWJsZW5kLW1vZGU6bm9ybWFsIiBjb2xvcj0iIzAwMCIgb3ZlcmZsb3c9InZpc2libGUiIGZpbGw9IiNlOWU5ZmYiLz48cGF0aCBkPSJNNDYuOTIzIDIyLjI3djEwLjk1N2w5LjQ2LTMuNDQ0VjE4LjgyNnoiIHN0eWxlPSJpc29sYXRpb246YXV0bzttaXgtYmxlbmQtbW9kZTpub3JtYWwiIGNvbG9yPSIjMDAwIiBvdmVyZmxvdz0idmlzaWJsZSIgZmlsbD0iIzM1MzU2NCIvPjxwYXRoIGQ9Ik00Ni45MjMgMzMuMjI3bDkuMzIyIDMuMzkzIDkuNDYtMy40NDMtOS4zMjItMy4zOTR6IiBzdHlsZT0iaXNvbGF0aW9uOmF1dG87bWl4LWJsZW5kLW1vZGU6bm9ybWFsIiBjb2xvcj0iIzAwMCIgb3ZlcmZsb3c9InZpc2libGUiIGZpbGw9IiNhZmFmZGUiLz48cGF0aCBkPSJNNDYuOTIzIDIyLjI3bDkuMzIyIDMuMzkzIDkuNDYtMy40NDMtOS4zMjItMy4zOTR6IiBmaWxsPSIjZjdmN2Y0Ii8+PHBhdGggZD0iTTU2LjI0NSAyNS42NjNWMzYuNjJsOS40Ni0zLjQ0M1YyMi4yMnoiIGZpbGw9IiNmZmQyNDIiLz48cGF0aCBkPSJNNDYuOTIzIDIyLjI3bDkuMzIyIDMuMzkzVjM2LjYybC05LjMyMi0zLjM5M3oiIGZpbGw9IiNlZmVlZWEiLz48L2c+PGcgZmlsbD0iI2EyOWQ4NiIgc3Ryb2tlPSIjY2NjIiBzdHJva2Utd2lkdGg9Ii4yMTQiIHN0cm9rZS1saW5lam9pbj0iYmV2ZWwiPjxwYXRoIHN0eWxlPSJpc29sYXRpb246YXV0bzttaXgtYmxlbmQtbW9kZTpub3JtYWwiIGQ9Ik01Ni4zODMgNy43Nmw5LjMyMyAzLjM5NFYyMi4xMWwtOS4zMjMtMy4zOTN6IiBjb2xvcj0iIzAwMCIgb3ZlcmZsb3c9InZpc2libGUiIGZpbGw9IiNlOWU5ZmYiLz48cGF0aCBzdHlsZT0iaXNvbGF0aW9uOmF1dG87bWl4LWJsZW5kLW1vZGU6bm9ybWFsIiBkPSJNNDYuOTIzIDExLjIwNHYxMC45NTdsOS40Ni0zLjQ0M1Y3Ljc2eiIgY29sb3I9IiMwMDAiIG92ZXJmbG93PSJ2aXNpYmxlIiBmaWxsPSIjMzUzNTY0Ii8+PHBhdGggc3R5bGU9Imlzb2xhdGlvbjphdXRvO21peC1ibGVuZC1tb2RlOm5vcm1hbCIgZD0iTTQ2LjkyMyAyMi4xNjFsOS4zMjIgMy4zOTMgOS40Ni0zLjQ0My05LjMyMi0zLjM5M3oiIGNvbG9yPSIjMDAwIiBvdmVyZmxvdz0idmlzaWJsZSIgZmlsbD0iI2FmYWZkZSIvPjxwYXRoIGQ9Ik00Ni45MjMgMTEuMjA0bDkuMzIyIDMuMzkzIDkuNDYtMy40NDMtOS4zMjItMy4zOTN6IiBmaWxsPSIjZmZjOTFkIi8+PHBhdGggZD0iTTU2LjI0NSAxNC41OTd2MTAuOTU3bDkuNDYtMy40NDNWMTEuMTU0eiIgZmlsbD0iI2ZmZDI0MiIvPjxwYXRoIGQ9Ik00Ni45MjMgMTEuMjA0bDkuMzIyIDMuMzkzdjEwLjk1N2wtOS4zMjItMy4zOTN6IiBmaWxsPSIjZWZlZWVhIi8+PC9nPjxnIGZpbGw9IiNhMjlkODYiIHN0cm9rZT0iI2NjYyIgc3Ryb2tlLXdpZHRoPSIuMjE0IiBzdHJva2UtbGluZWpvaW49ImJldmVsIj48cGF0aCBzdHlsZT0iaXNvbGF0aW9uOmF1dG87bWl4LWJsZW5kLW1vZGU6bm9ybWFsIiBkPSJNNDcuMDIgMjIuMjMxbDkuMzIyIDMuMzkzdjEwLjk1N2wtOS4zMjItMy4zOTN6IiBjb2xvcj0iIzAwMCIgb3ZlcmZsb3c9InZpc2libGUiIGZpbGw9IiNlOWU5ZmYiLz48cGF0aCBzdHlsZT0iaXNvbGF0aW9uOmF1dG87bWl4LWJsZW5kLW1vZGU6bm9ybWFsIiBkPSJNMzcuNTYgMjUuNjc1djEwLjk1N2w5LjQ2LTMuNDQ0VjIyLjIzMXoiIGNvbG9yPSIjMDAwIiBvdmVyZmxvdz0idmlzaWJsZSIgZmlsbD0iIzM1MzU2NCIvPjxwYXRoIHN0eWxlPSJpc29sYXRpb246YXV0bzttaXgtYmxlbmQtbW9kZTpub3JtYWwiIGQ9Ik0zNy41NiAzNi42MzJsOS4zMjIgMy4zOTMgOS40Ni0zLjQ0NC05LjMyMi0zLjM5M3oiIGNvbG9yPSIjMDAwIiBvdmVyZmxvdz0idmlzaWJsZSIgZmlsbD0iI2FmYWZkZSIvPjxwYXRoIGQ9Ik0zNy41NiAyNS42NzVsOS4zMjIgMy4zOTMgOS40Ni0zLjQ0NC05LjMyMi0zLjM5M3oiIGZpbGw9IiNmN2Y3ZjQiLz48cGF0aCBkPSJNNDYuODgyIDI5LjA2OHYxMC45NTdsOS40Ni0zLjQ0NFYyNS42MjR6IiBmaWxsPSIjZmZkMjQyIi8+PHBhdGggZD0iTTM3LjU2IDI1LjY3NWw5LjMyMiAzLjM5M3YxMC45NTdsLTkuMzIzLTMuMzkzeiIgZmlsbD0iI2VmZWVlYSIvPjwvZz48ZyBmaWxsPSIjYTI5ZDg2IiBzdHJva2U9IiNjY2MiIHN0cm9rZS13aWR0aD0iLjIxNCIgc3Ryb2tlLWxpbmVqb2luPSJiZXZlbCI+PHBhdGggZD0iTTQ3LjAyIDExLjE2Nmw5LjMyMiAzLjM5M3YxMC45NTdsLTkuMzIyLTMuMzkzeiIgc3R5bGU9Imlzb2xhdGlvbjphdXRvO21peC1ibGVuZC1tb2RlOm5vcm1hbCIgY29sb3I9IiMwMDAiIG92ZXJmbG93PSJ2aXNpYmxlIiBmaWxsPSIjZTllOWZmIi8+PHBhdGggZD0iTTM3LjU2IDE0LjYwOXYxMC45NTdsOS40Ni0zLjQ0M1YxMS4xNjZ6IiBzdHlsZT0iaXNvbGF0aW9uOmF1dG87bWl4LWJsZW5kLW1vZGU6bm9ybWFsIiBjb2xvcj0iIzAwMCIgb3ZlcmZsb3c9InZpc2libGUiIGZpbGw9IiMzNTM1NjQiLz48cGF0aCBkPSJNMzcuNTYgMjUuNTY2bDkuMzIyIDMuMzkzIDkuNDYtMy40NDMtOS4zMjItMy4zOTN6IiBzdHlsZT0iaXNvbGF0aW9uOmF1dG87bWl4LWJsZW5kLW1vZGU6bm9ybWFsIiBjb2xvcj0iIzAwMCIgb3ZlcmZsb3c9InZpc2libGUiIGZpbGw9IiNhZmFmZGUiLz48cGF0aCBkPSJNMzcuNTYgMTQuNjA5bDkuMzIyIDMuMzkzIDkuNDYtMy40NDMtOS4zMjItMy4zOTN6IiBmaWxsPSIjZjdmN2Y0Ii8+PHBhdGggZD0iTTQ2Ljg4MiAxOC4wMDJWMjguOTZsOS40Ni0zLjQ0M1YxNC41NTl6IiBmaWxsPSIjMzc3NWE5Ii8+PHBhdGggZD0iTTM3LjU2IDE0LjYwOWw5LjMyMiAzLjM5M1YyOC45NmwtOS4zMjMtMy4zOTN6IiBmaWxsPSIjZWZlZWVhIi8+PC9nPjxnIGZpbGw9IiNhMjlkODYiIHN0cm9rZT0iI2NjYyIgc3Ryb2tlLXdpZHRoPSIuMjE0IiBzdHJva2UtbGluZWpvaW49ImJldmVsIj48cGF0aCBzdHlsZT0iaXNvbGF0aW9uOmF1dG87bWl4LWJsZW5kLW1vZGU6bm9ybWFsIiBkPSJNNDcuMDIuMWw5LjMyMiAzLjM5M1YxNC40NWwtOS4zMjItMy4zOTN6IiBjb2xvcj0iIzAwMCIgb3ZlcmZsb3c9InZpc2libGUiIGZpbGw9IiNlOWU5ZmYiLz48cGF0aCBzdHlsZT0iaXNvbGF0aW9uOmF1dG87bWl4LWJsZW5kLW1vZGU6bm9ybWFsIiBkPSJNMzcuNTYgMy41NDNWMTQuNWw5LjQ2LTMuNDQzVi4xeiIgY29sb3I9IiMwMDAiIG92ZXJmbG93PSJ2aXNpYmxlIiBmaWxsPSIjMzUzNTY0Ii8+PHBhdGggc3R5bGU9Imlzb2xhdGlvbjphdXRvO21peC1ibGVuZC1tb2RlOm5vcm1hbCIgZD0iTTM3LjU2IDE0LjVsOS4zMjIgMy4zOTMgOS40Ni0zLjQ0My05LjMyMi0zLjM5M3oiIGNvbG9yPSIjMDAwIiBvdmVyZmxvdz0idmlzaWJsZSIgZmlsbD0iI2FmYWZkZSIvPjxwYXRoIGQ9Ik0zNy41NiAzLjU0M2w5LjMyMiAzLjM5MyA5LjQ2LTMuNDQzTDQ3LjAyLjF6IiBmaWxsPSIjMmY2NDkxIi8+PHBhdGggZD0iTTQ2Ljg4MiA2LjkzNnYxMC45NTdsOS40Ni0zLjQ0M1YzLjQ5M3oiIGZpbGw9IiMzNzc1YTkiLz48cGF0aCBkPSJNMzcuNTYgMy41NDNsOS4zMjIgMy4zOTN2MTAuOTU3TDM3LjU1OSAxNC41eiIgZmlsbD0iI2VmZWVlYSIvPjwvZz48ZyBmaWxsPSIjYTI5ZDg2IiBzdHJva2U9IiNjY2MiIHN0cm9rZS13aWR0aD0iLjIxNCIgc3Ryb2tlLWxpbmVqb2luPSJiZXZlbCI+PHBhdGggZD0iTTM3LjY1NyAyNS42MzZsOS4zMjIgMy4zOTN2MTAuOTU3bC05LjMyMi0zLjM5M3oiIHN0eWxlPSJpc29sYXRpb246YXV0bzttaXgtYmxlbmQtbW9kZTpub3JtYWwiIGNvbG9yPSIjMDAwIiBvdmVyZmxvdz0idmlzaWJsZSIgZmlsbD0iI2U5ZTlmZiIvPjxwYXRoIGQ9Ik0yOC4xOTYgMjkuMDh2MTAuOTU2bDkuNDYtMy40NDNWMjUuNjM2eiIgc3R5bGU9Imlzb2xhdGlvbjphdXRvO21peC1ibGVuZC1tb2RlOm5vcm1hbCIgY29sb3I9IiMwMDAiIG92ZXJmbG93PSJ2aXNpYmxlIiBmaWxsPSIjMzUzNTY0Ii8+PHBhdGggZD0iTTI4LjE5NiA0MC4wMzZsOS4zMjMgMy4zOTQgOS40Ni0zLjQ0NC05LjMyMi0zLjM5M3oiIHN0eWxlPSJpc29sYXRpb246YXV0bzttaXgtYmxlbmQtbW9kZTpub3JtYWwiIGNvbG9yPSIjMDAwIiBvdmVyZmxvdz0idmlzaWJsZSIgZmlsbD0iI2FmYWZkZSIvPjxwYXRoIGQ9Ik0yOC4xOTYgMjkuMDhsOS4zMjMgMy4zOTMgOS40Ni0zLjQ0NC05LjMyMi0zLjM5M3oiIGZpbGw9IiNmN2Y3ZjQiLz48cGF0aCBkPSJNMzcuNTE5IDMyLjQ3M1Y0My40M2w5LjQ2LTMuNDQ0VjI5LjAzeiIgZmlsbD0iI2ZmZDI0MiIvPjxwYXRoIGQ9Ik0yOC4xOTYgMjkuMDhsOS4zMjMgMy4zOTNWNDMuNDNsLTkuMzIzLTMuMzk0eiIgZmlsbD0iI2VmZWVlYSIvPjwvZz48ZyBmaWxsPSIjYTI5ZDg2IiBzdHJva2U9IiNjY2MiIHN0cm9rZS13aWR0aD0iLjIxNCIgc3Ryb2tlLWxpbmVqb2luPSJiZXZlbCI+PHBhdGggc3R5bGU9Imlzb2xhdGlvbjphdXRvO21peC1ibGVuZC1tb2RlOm5vcm1hbCIgZD0iTTM3LjY1NyAxNC41N2w5LjMyMiAzLjM5NFYyOC45MmwtOS4zMjItMy4zOTR6IiBjb2xvcj0iIzAwMCIgb3ZlcmZsb3c9InZpc2libGUiIGZpbGw9IiNlOWU5ZmYiLz48cGF0aCBzdHlsZT0iaXNvbGF0aW9uOmF1dG87bWl4LWJsZW5kLW1vZGU6bm9ybWFsIiBkPSJNMjguMTk2IDE4LjAxNFYyOC45N2w5LjQ2LTMuNDQ0VjE0LjU3eiIgY29sb3I9IiMwMDAiIG92ZXJmbG93PSJ2aXNpYmxlIiBmaWxsPSIjMzUzNTY0Ii8+PHBhdGggc3R5bGU9Imlzb2xhdGlvbjphdXRvO21peC1ibGVuZC1tb2RlOm5vcm1hbCIgZD0iTTI4LjE5NiAyOC45N2w5LjMyMyAzLjM5NCA5LjQ2LTMuNDQzLTkuMzIyLTMuMzk0eiIgY29sb3I9IiMwMDAiIG92ZXJmbG93PSJ2aXNpYmxlIiBmaWxsPSIjYWZhZmRlIi8+PHBhdGggZD0iTTI4LjE5NiAxOC4wMTRsOS4zMjMgMy4zOTMgOS40Ni0zLjQ0My05LjMyMi0zLjM5NHoiIGZpbGw9IiNmN2Y3ZjQiLz48cGF0aCBkPSJNMzcuNTE5IDIxLjQwN3YxMC45NTdsOS40Ni0zLjQ0M1YxNy45NjR6IiBmaWxsPSIjMzc3NWE5Ii8+PHBhdGggZD0iTTI4LjE5NiAxOC4wMTRsOS4zMjMgMy4zOTN2MTAuOTU3bC05LjMyMy0zLjM5M3oiIGZpbGw9IiNlZmVlZWEiLz48L2c+PGcgZmlsbD0iI2EyOWQ4NiIgc3Ryb2tlPSIjY2NjIiBzdHJva2Utd2lkdGg9Ii4yMTQiIHN0cm9rZS1saW5lam9pbj0iYmV2ZWwiPjxwYXRoIHN0eWxlPSJpc29sYXRpb246YXV0bzttaXgtYmxlbmQtbW9kZTpub3JtYWwiIGQ9Ik0yOC4yOTMgMjkuMDRsOS4zMjMgMy4zOTR2MTAuOTU3bC05LjMyMy0zLjM5M3oiIGNvbG9yPSIjMDAwIiBvdmVyZmxvdz0idmlzaWJsZSIgZmlsbD0iI2U5ZTlmZiIvPjxwYXRoIHN0eWxlPSJpc29sYXRpb246YXV0bzttaXgtYmxlbmQtbW9kZTpub3JtYWwiIGQ9Ik0xOC44MzMgMzIuNDg0djEwLjk1N2w5LjQ2LTMuNDQzVjI5LjA0eiIgY29sb3I9IiMwMDAiIG92ZXJmbG93PSJ2aXNpYmxlIiBmaWxsPSIjMzUzNTY0Ii8+PHBhdGggc3R5bGU9Imlzb2xhdGlvbjphdXRvO21peC1ibGVuZC1tb2RlOm5vcm1hbCIgZD0iTTE4LjgzMyA0My40NDFsOS4zMjIgMy4zOTMgOS40Ni0zLjQ0My05LjMyMi0zLjM5M3oiIGNvbG9yPSIjMDAwIiBvdmVyZmxvdz0idmlzaWJsZSIgZmlsbD0iI2FmYWZkZSIvPjxwYXRoIGQ9Ik0xOC44MzMgMzIuNDg0bDkuMzIyIDMuMzkzIDkuNDYtMy40NDMtOS4zMjItMy4zOTN6IiBmaWxsPSIjZjdmN2Y0Ii8+PHBhdGggZD0iTTI4LjE1NSAzNS44Nzd2MTAuOTU3bDkuNDYtMy40NDNWMzIuNDM0eiIgZmlsbD0iIzM3NzVhOSIvPjxwYXRoIGQ9Ik0xOC44MzMgMzIuNDg0bDkuMzIyIDMuMzkzdjEwLjk1N2wtOS4zMjItMy4zOTN6IiBmaWxsPSIjMmY2NDkxIi8+PC9nPjxnIGZpbGw9IiNhMjlkODYiIHN0cm9rZT0iI2NjYyIgc3Ryb2tlLXdpZHRoPSIuMjE0IiBzdHJva2UtbGluZWpvaW49ImJldmVsIj48cGF0aCBkPSJNMjguMjkzIDE3Ljk3NWw5LjMyMyAzLjM5M3YxMC45NTdsLTkuMzIzLTMuMzkzeiIgc3R5bGU9Imlzb2xhdGlvbjphdXRvO21peC1ibGVuZC1tb2RlOm5vcm1hbCIgY29sb3I9IiMwMDAiIG92ZXJmbG93PSJ2aXNpYmxlIiBmaWxsPSIjZTllOWZmIi8+PHBhdGggZD0iTTE4LjgzMyAyMS40MTl2MTAuOTU3bDkuNDYtMy40NDRWMTcuOTc1eiIgc3R5bGU9Imlzb2xhdGlvbjphdXRvO21peC1ibGVuZC1tb2RlOm5vcm1hbCIgY29sb3I9IiMwMDAiIG92ZXJmbG93PSJ2aXNpYmxlIiBmaWxsPSIjMzUzNTY0Ii8+PHBhdGggZD0iTTE4LjgzMyAzMi4zNzZsOS4zMjIgMy4zOTMgOS40Ni0zLjQ0NC05LjMyMi0zLjM5M3oiIHN0eWxlPSJpc29sYXRpb246YXV0bzttaXgtYmxlbmQtbW9kZTpub3JtYWwiIGNvbG9yPSIjMDAwIiBvdmVyZmxvdz0idmlzaWJsZSIgZmlsbD0iI2FmYWZkZSIvPjxwYXRoIGQ9Ik0xOC44MzMgMjEuNDE5bDkuMzIyIDMuMzkzIDkuNDYtMy40NDQtOS4zMjItMy4zOTN6IiBmaWxsPSIjMmY2NDkxIi8+PHBhdGggZD0iTTI4LjE1NSAyNC44MTJ2MTAuOTU3bDkuNDYtMy40NDRWMjEuMzY4eiIgZmlsbD0iIzM3NzVhOSIvPjxwYXRoIGQ9Ik0xOC44MzMgMjEuNDE5bDkuMzIyIDMuMzkzdjEwLjk1N2wtOS4zMjItMy4zOTN6IiBmaWxsPSIjMmY2NDkxIi8+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xNjgzLjY2IC01MTMuMjc1KSBzY2FsZSguNjUxNzcpIj48ZyBmaWxsPSIjYTI5ZDg2IiBzdHJva2U9IiNjY2MiIHN0cm9rZS13aWR0aD0iLjMyOCIgc3Ryb2tlLWxpbmVqb2luPSJiZXZlbCI+PHBhdGggc3R5bGU9Imlzb2xhdGlvbjphdXRvO21peC1ibGVuZC1tb2RlOm5vcm1hbCIgZD0iTTI2NDAuOTgzIDc5Mi44ODVsMTQuMzA0IDUuMjA2djE2LjgxMWwtMTQuMzA0LTUuMjA2eiIgY29sb3I9IiMwMDAiIG92ZXJmbG93PSJ2aXNpYmxlIiBmaWxsPSIjZTllOWZmIi8+PHBhdGggc3R5bGU9Imlzb2xhdGlvbjphdXRvO21peC1ibGVuZC1tb2RlOm5vcm1hbCIgZD0iTTI2MjYuNDY4IDc5OC4xNjh2MTYuODExbDE0LjUxNS01LjI4M3YtMTYuODExeiIgY29sb3I9IiMwMDAiIG92ZXJmbG93PSJ2aXNpYmxlIiBmaWxsPSIjMzUzNTY0Ii8+PHBhdGggc3R5bGU9Imlzb2xhdGlvbjphdXRvO21peC1ibGVuZC1tb2RlOm5vcm1hbCIgZD0iTTI2MjYuNDY4IDgxNC45NzlsMTQuMzA0IDUuMjA2IDE0LjUxNS01LjI4My0xNC4zMDQtNS4yMDZ6IiBjb2xvcj0iIzAwMCIgb3ZlcmZsb3c9InZpc2libGUiIGZpbGw9IiNhZmFmZGUiLz48cGF0aCBkPSJNMjYyNi40NjggNzk4LjE2OGwxNC4zMDQgNS4yMDYgMTQuNTE1LTUuMjgzLTE0LjMwNC01LjIwNnoiIGZpbGw9IiMyZjY0OTEiLz48cGF0aCBkPSJNMjY0MC43NzIgODAzLjM3NHYxNi44MTFsMTQuNTE1LTUuMjgzdi0xNi44MTF6IiBmaWxsPSIjMzc3NWE5Ii8+PHBhdGggZD0iTTI2MjYuNDY4IDc5OC4xNjhsMTQuMzA0IDUuMjA2djE2LjgxMWwtMTQuMzA0LTUuMjA2eiIgZmlsbD0iIzJmNjQ5MSIvPjwvZz48Y2lyY2xlIHRyYW5zZm9ybT0ic2tld1koLTIwKSBzY2FsZSguOTM5NyAxKSIgY3k9IjE3NzIuOTIyIiBjeD0iMjgxNi4wMTciIHI9IjIuOTY3IiBmaWxsPSIjZmZmIi8+PC9nPjwvc3ZnPg==';

    // #endregion Icon Data URIs

    class SitesMenu {
        constructor(init = true) {
            this.akkdSitesButtonId = 'akkd-sites-button';

            if (init) {
                this.init();
            }
        }

        init() {
            $(document).arrive(`form[action='/search']>div>div:first-child`, async (elem) => {
                this._createButtonCss();

                // this.container = $('.sKb6pb');
                this.container = [this._getButtonContainer()];
                this.sitesButton = this._createSitesButton();

                this.sitesButton.hide();

                // Append to main container if using mobile
                if (window.orientation != undefined) {
                    $(this.container[0]).append(this.sitesButton);
                } else {
                    $(this.container[0]).append(this.sitesButton);
                }

                let benchmark = new Benchmark({ logger: logDebug });
                let benchmarkName = 'menuItems creation';

                benchmark.start(benchmarkName);

                let icons = [this._getFavIcon('stackoverflow.com'), this._getFavIcon('gist.github.com'), this._getFavIcon('reddit.com'), this._getFavIcon('codepen.io'), this._getFavIcon('codesandbox.io'), this._getFavIcon('npmjs.com'), this._getFavIcon('forum.xda-developers.com')];

                // Pre-fetching icons all at once. This is faster if it's a fresh run.
                icons = await Promise.all(icons);

                let menuItems = [
                    //
                    this._createMenuItem('Clear', 'akkd-sites-clear', `<img alt="" src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=" />`),
                    this._createMenuItem('stackoverflow', 'akkd-sites-stackoverflow', `<img alt="" src="${await this._getFavIcon('stackoverflow.com')}" />`, 'stackoverflow.com'),
                    this._createMenuItem('gist', 'akkd-sites-gist', `<img alt="" src="${await this._getFavIcon('gist.github.com')}" />`, 'gist.github.com'),
                    this._createMenuItem('reddit', 'akkd-sites-reddit', `<img alt="" src="${await this._getFavIcon('reddit.com')}" />`, 'reddit.com'),
                    this._createMenuItem('codepen', 'akkd-sites-codepen', `<img alt="" src="${await this._getFavIcon('codepen.io')}" />`, 'codepen.io'),
                    this._createMenuItem('codesandbox', 'akkd-sites-codesandbox', `<img alt="" src="${await this._getFavIcon('codesandbox.io')}" />`, 'codesandbox.io'),
                    this._createMenuItem('npmjs', 'akkd-sites-npmjs', `<img alt="" src="${await this._getFavIcon('npmjs.com')}" />`, 'npmjs.com'),
                    this._createMenuItem('pypi', 'akkd-sites-pypi', `<img alt="" src="${pypiUri}" />`, 'pypi.org'),
                    this._createMenuItem('xda', 'akkd-sites-xda', `<img alt="" src="${await this._getFavIcon('forum.xda-developers.com')}" />`, 'forum.xda-developers.com'),
                ];

                benchmark.stop(benchmarkName);

                this._createSitesMenu(menuItems);

                this.menuContainer.hide();

                this.sitesButton.on('click', (ev) => {
                    ev.preventDefault();

                    this.show();
                });

                this._positionButtonContainer();

                this._setupResizeObserver();

                this.menu
                    .on('mousedown', (ev) => {
                        ev.preventDefault();
                    })
                    .on('blur', (ev) => {
                        this.menuContainer.hide();
                    });

                $(document.body).append(this.hiddenMenuContainer);

                this.sitesButton.show();
            });
        }

        _setupResizeObserver(maxTries = 10) {
            let tries = 0;

            let _worker = () => {
                tries++;

                try {
                    // this.resizeObserver = new ResizeObserver(this._positionButtonContainer).observe($('.logo')[0].nextElementSibling);
                    this.resizeObserver = new ResizeObserver(this._positionButtonContainer).observe($(`form[action='/search'][role='search']`).find(`button`)[0].parentElement);
                } catch (error) {
                    if (tries < maxTries) {
                        setTimeout(_worker, 100);
                    }
                }
            };

            _worker();
        }

        show() {
            let { left, top } = this._getLeftAndTop();

            this.menuContainer[0].style.top = `${top}px`;
            this.menuContainer[0].style.left = `${left}px`;

            this.menuContainer.show();

            /** @type {HTMLElement} */ (this.menu[0]).focus();
        }

        removeSitesButton() {
            $(`#${this.akkdSitesButtonId}`).remove();
        }

        _positionButtonContainer() {
            let tries = 0;

            let _worker = () => {
                tries++;

                try {
                    /** @type {HTMLElement} */
                    let buttonContainerElem = $('.akkd-button-container')[0];

                    /** @type {HTMLElement} */
                    // let searchBarElem = $('.logo')[0].nextElementSibling;
                    let searchBarElem = $(`div[jsname='RNNXgb']`)[0];

                    let searchBarWidth = $(searchBarElem).rect().width;
                    let searchBarHeight = $(searchBarElem).rect().height;

                    buttonContainerElem.style.height = `${searchBarHeight}px`;
                    buttonContainerElem.style.left = `${searchBarWidth + 40}px`;
                    buttonContainerElem.style.top = '0px'; // `${searchBarHeight * -1}px`;
                } catch (error) {
                    if (tries < maxTries) {
                        setTimeout(_worker, 100);
                    }
                }
            };

            _worker();
        }

        _getLeftAndTop() {
            /** @type {number} */
            let left = this.sitesButton.rect().left + getWindow().scrollX - this.sitesButton.width() / 2.7;

            left = left - Math.max(0, left + this.menuContainer.actual('width') + 20 - $(document.body).rect().width);

            /** @type {number} */
            let top = this.sitesButton.rect().top + getWindow().scrollY + $(this.sitesButton.children()[0]).rect().height + 1000;

            return {
                left,
                top,
            };
        }

        _createButtonCss() {
            let styleElem = document.createElement('style');

            styleElem.innerHTML = `html:not(.zAoYTe) [href]{outline:0}.akkd-button-container-2{display:inline-block;margin-left:6px;vertical-align:top}.akkd-button-container-2:first-of-type{margin-left:0}.akkd-button-container-2{height:100%}.akkd-button-container-3{box-sizing:border-box;flex-direction:row;-webkit-transition:background-color .1s;align-items:center;backdrop-filter:blur(4px);background-color:#fff;border:1px solid #dadce0;border-radius:20px;display:flex;height:100%;min-width:48px;padding:0 14px;text-align:center}.akkd-button-container-3:not(:focus-visible){outline:0}.akkd-button-container-3,.akkd-button-container-3:active,.akkd-button-container-3:hover,.akkd-button-container-3:link,.akkd-button-container-3:visited{color:#202124;text-decoration:none}.akkd-button-container-3:not(.OvGWO):hover{background-color:#f1f3f4;border-color:#dadce0}.akkd-button-text{font-family:Google Sans,Roboto,arial,sans-serif;font-size:14px;min-width:0;text-align:center}.akkd-button-text::first-letter{text-transform:uppercase}.akkd-button-svg{fill:#4285f4;height:18px;margin-right:6px;width:18px}.akkd-button-container-4{padding-left:12px}.akkd-button-container{display:inline-block;height:40px;margin-left:6px;vertical-align:top;position:absolute;top:-43px;left:705px}@font-face{font-family:'Google Sans';font-style:normal;font-weight:400;font-display:optional;src:url(//fonts.gstatic.com/s/googlesans/v14/4UaGrENHsxJlGDuGo1OIlL3Kwp5MKg.woff2) format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:'Google Sans';font-style:normal;font-weight:400;font-display:optional;src:url(//fonts.gstatic.com/s/googlesans/v14/4UaGrENHsxJlGDuGo1OIlL3Nwp5MKg.woff2) format('woff2');unicode-range:U+0370-03FF}@font-face{font-family:'Google Sans';font-style:normal;font-weight:400;font-display:optional;src:url(//fonts.gstatic.com/s/googlesans/v14/4UaGrENHsxJlGDuGo1OIlL3Bwp5MKg.woff2) format('woff2');unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:'Google Sans';font-style:normal;font-weight:400;font-display:optional;src:url(//fonts.gstatic.com/s/googlesans/v14/4UaGrENHsxJlGDuGo1OIlL3Awp5MKg.woff2) format('woff2');unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:'Google Sans';font-style:normal;font-weight:400;font-display:optional;src:url(//fonts.gstatic.com/s/googlesans/v14/4UaGrENHsxJlGDuGo1OIlL3Owp4.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Roboto;font-style:normal;font-weight:400;font-display:optional;src:url(//fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu72xKOzY.woff2) format('woff2');unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Roboto;font-style:normal;font-weight:400;font-display:optional;src:url(//fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu5mxKOzY.woff2) format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Roboto;font-style:normal;font-weight:400;font-display:optional;src:url(//fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu7mxKOzY.woff2) format('woff2');unicode-range:U+1F00-1FFF}@font-face{font-family:Roboto;font-style:normal;font-weight:400;font-display:optional;src:url(//fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu4WxKOzY.woff2) format('woff2');unicode-range:U+0370-03FF}@font-face{font-family:Roboto;font-style:normal;font-weight:400;font-display:optional;src:url(//fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu7WxKOzY.woff2) format('woff2');unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:Roboto;font-style:normal;font-weight:400;font-display:optional;src:url(//fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu7GxKOzY.woff2) format('woff2');unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Roboto;font-style:normal;font-weight:400;font-display:optional;src:url(//fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu4mxK.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Roboto;font-style:normal;font-weight:700;font-display:optional;src:url(//fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmWUlfCRc4EsA.woff2) format('woff2');unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Roboto;font-style:normal;font-weight:700;font-display:optional;src:url(//fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmWUlfABc4EsA.woff2) format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Roboto;font-style:normal;font-weight:700;font-display:optional;src:url(//fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmWUlfCBc4EsA.woff2) format('woff2');unicode-range:U+1F00-1FFF}@font-face{font-family:Roboto;font-style:normal;font-weight:700;font-display:optional;src:url(//fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmWUlfBxc4EsA.woff2) format('woff2');unicode-range:U+0370-03FF}@font-face{font-family:Roboto;font-style:normal;font-weight:700;font-display:optional;src:url(//fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmWUlfCxc4EsA.woff2) format('woff2');unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:Roboto;font-style:normal;font-weight:700;font-display:optional;src:url(//fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmWUlfChc4EsA.woff2) format('woff2');unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Roboto;font-style:normal;font-weight:700;font-display:optional;src:url(//fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmWUlfBBc4.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}.akkd-button-container-3.akkd-button-container-4:hover{cursor:pointer;user-select:none}.akkd-menu-item-text-01{margin-right:5px;vertical-align:text-bottom}.akkd-menu-item-text-02{display:inline-block;fill:currentColor}.akkd-menu-item-text-02 svg{display:block;height:100%;width:100%}.akkd-hide-focus-ring{outline:0}.akkd-hide-focus-ring:hover{background-color:rgba(0,0,0,.1)}.akkd-hidden-menu-container{z-index:1001;position:absolute;top:-1000px}.akkd-menu{background-color:#fff}.akkd-menu akkd-menu-item{display:block;font-size:14px;line-height:23px;white-space:nowrap}.akkd-menu akkd-menu-item a{display:block;padding-top:4px;padding-bottom:4px;cursor:pointer}.akkd-menu akkd-menu-item a,.akkd-menu akkd-menu-item a:hover,.akkd-menu akkd-menu-item a:visited{text-decoration:inherit;color:inherit}.akkd-menu-style-01 akkd-menu-item{color:#5f6368}.akkd-menu-style-01 akkd-menu-item a{line-height:16px;padding-top:8px;padding-bottom:8px}.akkd-menu-container{display:block;position:absolute;border-radius:8px;box-shadow:0 2px 10px 0 rgba(0,0,0,.2)}.akkd-menu-style-02{border:none;display:block;outline:0}.akkd-menu-style-02{border-radius:8px}.akkd-menu-style-02{padding:5px 0}.akkd-menu-item{display:block;position:relative}.akkd-menu-item-inner-01{overflow:hidden;padding:0 16px;text-overflow:ellipsis;vertical-align:middle;white-space:nowrap}.akkd-menu-item-inner-01.akkd-menu-item-inner-02{padding:0}.akkd-menu-item-inner-02>*{padding:0 16px}.akkd-menu-item:hover{cursor:pointer}.akkd-menu-item{cursor:default}.akkd-menu-item-inner-01{line-height:23px}.akkd-menu-item:active{background-color:rgba(0,0,0,.1)}.akkd-menu-item-text-01.akkd-menu-item-text-02>img{height:16px;width:16px}.akkd-btn .GOE98c,.akkd-btn a,.akkd-btn.hdtb-msel,.t2vtad{color:#5f6368;text-decoration:none;display:inline-block;padding:0 12px;padding:8px 16px 8px 16px;padding:17px 12px 11px 10px}.akkd-btn{margin:-5px 0 0 15px;display:inline-block;z-index:99999}.akkd-btn:hover{cursor:pointer}.akkd-btn a:active{color:#1a73e8}.akkd-btn.hdtb-msel{color:#1a73e8}.cCvmNd .akkd-btn.hdtb-msel{border-bottom:none}.akkd-btn.hdtb-msel:hover{cursor:pointer}.akkd-btn.hdtb-msel:active{background:0 0}.akkd-btn a{color:#5f6368}@media (max-width:1300px){div[jsname=RNNXgb]{width:538px}}.o6juZc{margin-left:0}`;

            document.head.appendChild(styleElem);

            let shouldUseDarkmode = window.matchMedia('(prefers-color-scheme: dark)').matches;

            if (shouldUseDarkmode && this._isDarkMode()) {
                let styleElemDark = document.createElement('style');

                styleElemDark.innerHTML = `.akkd-button-container-3 {
    background-color: #202124;
    border: 1px solid #3c4043;
    color: #f1f3f4;
}

.akkd-button-container-3:hover {
    background-color: #303134 !important;
    border: 1px solid #3c4043 !important;
    color: #f1f3f4 !important;
}

.akkd-menu {
    background-color: #202124;
}

.akkd-hide-focus-ring:hover {
    background-color: rgba(255,255,255,0.1)
}

.akkd-menu-style-01 akkd-menu-item {
    color: #bdc1c6;
}
`;

                document.head.appendChild(styleElemDark);
            }
        }

        _isDarkMode() {
            try {
                return document.querySelector('#logo > img').src.includes('light');
            } catch (error) {
                let metaElems = document.getElementsByTagName('meta');
                let metas = {};

                for (let i = 0; i < metaElems.length; i++) {
                    let metaElem = metaElems[i];

                    if (metaElem.name.trim() == '') {
                        continue;
                    }

                    let val = metaElem.getAttribute('content');

                    try {
                        val = JSON.parse(val);
                    } catch (error) {}

                    metas[metaElem.name] = val;
                }

                return 'color-scheme' in metas && metas['color-scheme'] === 'dark';
            }
        }

        /**
         *
         *
         * @author Michael Barros <michaelcbarros@gmail.com>
         * @returns {JQuery<JQuery.Node[]>}
         * @memberof SitesMenu
         */
        _createSitesButton() {
            // hdtb-mitem
            let htmlOld = `<div id="${this.akkdSitesButtonId}" class="discuss-btn hdtb-imb akkd-btn">
        <a class="q qs" href="#">
            <span class="MbEPDb z1asCe SaPW2b" style="height: 16px; line-height: 16px; width: 16px; margin-left: -20px">
                <svg focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                    <path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"></path>
                </svg>
            </span>Sites
        </a>
        </div>`;

            let html = `<div class="akkd-button-container" id="${this.akkdSitesButtonId}">
    <div class="akkd-button-container-2">
        <div class="akkd-button-container-3 akkd-button-container-4">
            <svg class="akkd-button-svg" focusable="false" viewBox="0 0 24 24">
                <path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"></path>
            </svg>
            <div class="akkd-button-text">Sites</div>
        </div>
    </div>
</div>`;

            let sitesButton = $($.parseHTML(html));

            return sitesButton;
        }

        /**
         *
         *
         * @author Michael Barros <michaelcbarros@gmail.com>
         * @returns {HTMLElement}
         * @memberof SitesMenu
         */
        _getButtonContainerOld() {
            let buttonContainer = getElementByTextContent('All', 'span').parentElement.parentElement.parentElement.children[1]; // .children[0].children[0]

            return buttonContainer;
        }

        /**
         *
         *
         * @author Michael Barros <michaelcbarros@gmail.com>
         * @returns {HTMLElement}
         * @memberof SitesMenu
         */
        _getButtonContainer() {
            /** @type {HTMLElement} */
            let buttonContainer = $(`form[action='/search']>div>div:first-child`)[0]; // $('div.eTnfyc')[0];

            // buttonContainer.style.position = 'absolute';

            return buttonContainer;
        }

        /**
         *
         *
         * @author Michael Barros <michaelcbarros@gmail.com>
         * @param {JQuery<JQuery.Node[]>[]} menuItems
         * @returns
         * @memberof SitesMenu
         */
        _createSitesMenu(menuItems) {
            let html = `<div class="akkd-hidden-menu-container">
    <div class="akkd-menu-container" style="z-index: 1;">
        <akkd-menu class="akkd-menu akkd-menu-style-01 akkd-menu-style-02" tabindex="0">

        </akkd-menu>
    </div>
    </div>`;

            this.hiddenMenuContainer = $($.parseHTML(html));
            this.menuContainer = $(this.hiddenMenuContainer[0].children[0]);
            this.menu = $(this.hiddenMenuContainer[0].children[0].children[0]);

            for (let i = 0; i < menuItems.length; i++) {
                let menuItem = menuItems[i];

                this.menu.append(menuItem);
            }

            getWindow().menuContainer = this.menuContainer;

            return {
                hiddenMenuContainer: this.hiddenMenuContainer,
                menuContainer: this.menuContainer,
                menu: this.menu,
            };
        }

        /**
         *
         *
         * @author Michael Barros <michaelcbarros@gmail.com>
         * @param {string} caption
         * @param {string} id
         * @param {string} svg
         * @param {string} url
         * @returns {JQuery<JQuery.Node[]>}
         * @memberof SitesMenu
         */
        _createMenuItem(caption, id, svg, url) {
            onclick = onclick || function () {};

            let html = `<akkd-menu-item id="${id}" class=".akkd-menu-item akkd-hide-focus-ring">
    <div class="akkd-menu-item-inner-01 akkd-menu-item-inner-02">
        <a tabindex="-1">
            <span class="akkd-menu-item-text-01 akkd-menu-item-text-02" style="height: 16px; width: 16px">
                ${svg}
            </span>${caption}
        </a>
    </div>
    </akkd-menu-item>`;

            let menuItem = $($.parseHTML(html));
            let self = this;

            menuItem.on('click', function (ev) {
                ev.preventDefault();

                let searchElem = self._getSearchInputElem();

                let value = url != null ? `${searchElem.value.replace(/site:.*$/g, '').trim()} site:${url}` : `${searchElem.value.replace(/site:.*$/g, '').trim()}`;

                searchElem.value = value;

                $(searchElem).closest('form')[0].submit();

                $(this).parent().parent().hide();
            });

            return menuItem;
        }

        /**
         *
         *
         * @author Michael Barros <michaelcbarros@gmail.com>
         * @param {string} url
         * @returns {string | null}
         * @memberof SitesMenu
         */
        _getCachedFavIcon(url) {
            let iconStorage = ls.get('icons', {});

            let now = new Date();

            try {
                let dateSaved = new Date(iconStorage[url].refreshDate);
                let diffDays = dateDiffInDays(now, dateSaved);

                if (diffDays > 15) {
                    return null;
                } else {
                    return iconStorage[url].icon;
                }
            } catch (error) {
                return null;
            }
        }

        /**
         *
         *
         * @author Michael Barros <michaelcbarros@gmail.com>
         * @param {string} url
         * @returns {Promise<string>}
         * @memberof SitesMenu
         */
        async _getFavIcon(url) {
            // Remove subdomain if present
            url = url.trim().replace(/^(?:[a-z]+\:\/{2})?(?:[\w-]+\.([\w-]+\.\w+))$/, '$1');

            let _url = `https://www.google.com/s2/favicons?domain=${url}`;

            let icon = this._getCachedFavIcon(url);

            if (icon) {
                return icon;
            }

            return new Promise(async (resolve, reject) => {
                let res = await GM_fetch(_url, {
                    // credentials: 'include',
                    headers: {
                        accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
                        'accept-language': 'en-US,en;q=0.9',
                    },
                    body: null,
                    method: 'GET',
                    // mode: 'cors',
                });

                let blob = await res.blob();

                let reader = new FileReader();

                reader.onload = function () {
                    let iconStorage = ls.get('icons', {});

                    iconStorage[url] = {
                        refreshDate: new Date().toISOString(),
                        icon: this.result,
                    };

                    ls.set('icons', iconStorage);

                    resolve(this.result);
                };

                reader.onerror = function (ev) {
                    console.error(DEV_TAG, 'Error:', ev);
                };

                reader.readAsDataURL(blob);
            });
        }

        /**
         *
         *
         * @author Michael Barros <michaelcbarros@gmail.com>
         * @returns {HTMLInputElement}
         * @memberof SitesMenu
         */
        _getSearchInputElem() {
            /** @type {HTMLInputElement} */
            let searchElem = $('[name="q"]')[0];

            return searchElem;
        }

        /**
         *
         *
         * @author Michael Barros <michaelcbarros@gmail.com>
         * @returns {HTMLElement}
         * @memberof SitesMenu
         */
        _getGoogleSearchButton() {
            let googleSearchButton = $('.Tg7LZd')[0];

            return googleSearchButton;
        }
    }

    function initSitesMenu() {
        let sitesMenu = new SitesMenu();
    }

    // #endregion Sites Menu

    /**
     *
     *
     * @author Michael Barros <michaelcbarros@gmail.com>
     */
    async function init() {
        // when, options, func, args) {
        const DEFAULT_OPTIONS = {
            use_vanilla: false,
        };

        let when = arguments[0];
        let options = typeof arguments[1] == 'object' ? arguments[1] : {};
        let func = typeof arguments[1] == 'object' ? arguments[2] : arguments[1];
        let args = typeof arguments[1] == 'object' ? arguments[3] : arguments[2];

        options = Object.assign(DEFAULT_OPTIONS, options);

        async function runCallback() {
            if (args && args.length > 0) {
                await func(...args);
            } else {
                await func();
            }
        }

        if (when == 'start') {
            await runCallback();
        } else if (when == 'ready') {
            if (!options.use_vanilla) {
                $(document).ready(async (e) => {
                    await runCallback();
                });
            } else {
                document.addEventListener('DOMContentLoaded', async (e) => {
                    await runCallback();
                });
            }
        } else if (when == 'loaded') {
            if (!options.use_vanilla) {
                $(document).on('readystatechange', async (e) => {
                    if (e.target.readyState == 'complete') {
                        await runCallback();
                    }
                });
            } else {
                document.addEventListener('readystatechange', async (e) => {
                    if (e.target.readyState === 'complete') {
                        await runCallback();
                    }
                });
            }
        }
    }

    registerDebugMenuCommand(true);
    exposeGlobalVariables([
        { name: 'GM_xmlhttpRequest', value: GM_xmlhttpRequest },
        { name: 'GM_getValue', value: GM_getValue },
        { name: 'GM_setValue', value: GM_setValue },
        { name: 'GM_listValues', value: GM_listValues },
        { name: 'SitesMenu', value: SitesMenu },
        { name: 'LocalStorageEx', value: LocalStorageEx },
        { name: 'ls', value: ls },

        { name: '$', value: $ },
    ]);

    await init('start', initSitesMenu);
})();