const FRAMEBRXC = {
    helpers: {
        getElementObject: function(id, forceStructure = false){

            const getElementObject = FRAMEBRXC.vueGlobalProp.$_getElementObject;
            const getDynamicElementById = FRAMEBRXC.vueGlobalProp.$_getDynamicElementById;
        
            if (typeof getElementObject === 'function') {
                return getElementObject(id);
            } else if (typeof getDynamicElementById === 'function') {
                const obj = getDynamicElementById(id);
                if(obj && obj.hasOwnProperty('cid')){
                    return FRAMEBRXC.vueGlobalProp.$_getComponentElementById(obj.cid);
                } else {
                    return obj;
                }
            } else {
                console.error("No suitable function available to get element object.");
                return null;
            }
            
        },
        getFinalObject: function(skipClass = false, skipComponent = false, forceStructure = false){
            if(!skipClass && FRAMEBRXC.helpers.isClassActive()){
                return FRAMEBRXC.vueState.globalClasses.find(el => el.id === FRAMEBRXC.vueState.activeClass.id);
            }

            if(!skipComponent && FRAMEBRXC.vueState.activeElement && FRAMEBRXC.vueState.activeElement.hasOwnProperty('cid') 
            ){
                return FRAMEBRXC.vueGlobalProp.$_getComponentElementById(FRAMEBRXC.vueState.activeElement.cid);
            }
            if(typeof FRAMEBRXC.vueState.activeElement === "object" && FRAMEBRXC.vueState.activeElement.hasOwnProperty('id')){
                return FRAMEBRXC.helpers.getElementObject(FRAMEBRXC.vueState.activeElement.id, forceStructure)
            }

            return false;
        },
    }
};

window.ADMINBRXC = {
    globalSettings: {
        generalCats: [],
        keyboardShortcuts: {
        },
        disableIDStyles: false,
        integrations:{
        },
        elements : [],
        styleControls: [],
        customComponentsElements: [
            {id: "frejij", label: "My Custom Element", icon: "ti-ruler-alt", category: 'ijefii', elements: '[{"id":"lvhrck","name":"block","parent":0,"children":["sqnrrm","jalqyd"],"settings":{}},{"id":"sqnrrm","name":"image","parent":"lvhrck","children":[],"settings":{}},{"id":"jalqyd","name":"div","parent":"lvhrck","children":["hxppvz","rsrldr","rsefif"],"settings":{}},{"id":"hxppvz","name":"heading","parent":"jalqyd","children":[],"settings":{"text":"I am a heading"}},{"id":"rsrldr","name":"text-basic","parent":"jalqyd","children":[],"settings":{"text":"Here goes your text ... Select any part of your text to access the formatting toolbar.","tag":"p"}},{"id":"rsefif","name":"button","parent":"jalqyd","children":[],"settings":{"text":"I am a button","style":"primary"}}]'}
        ],
        customComponentsCategories: [
            {id: "ijefii", label: "My Category"}
        ],
    },
    setupState: document.querySelector('.brx-body')._vnode.component.setupState,
    vue: document.querySelector('.brx-body').__vue_app__,
    vueGlobalProp: document.querySelector('.brx-body').__vue_app__.config.globalProperties,
    vueState: document.querySelector('.brx-body').__vue_app__.config.globalProperties.$_state,
    cssVariables: [],
    cssVariablesHints: [],
    nestableElements: [],
    sassInstances: [],
    helpers: {
        tiIcons: ["ti-arrow-up", "ti-arrow-right", "ti-arrow-left", "ti-arrow-down", "ti-arrows-vertical", "ti-arrows-horizontal", "ti-angle-up", "ti-angle-right", "ti-angle-left", "ti-angle-down", "ti-angle-double-up", "ti-angle-double-right", "ti-angle-double-left", "ti-angle-double-down", "ti-move", "ti-fullscreen", "ti-arrow-top-right", "ti-arrow-top-left", "ti-arrow-circle-up", "ti-arrow-circle-right", "ti-arrow-circle-left", "ti-arrow-circle-down", "ti-arrows-corner", "ti-split-v", "ti-split-v-alt", "ti-split-h", "ti-hand-point-up", "ti-hand-point-right", "ti-hand-point-left", "ti-hand-point-down", "ti-back-right", "ti-back-left", "ti-exchange-vertical", "ti-wand", "ti-save", "ti-save-alt", "ti-direction", "ti-direction-alt", "ti-user", "ti-link", "ti-unlink", "ti-trash", "ti-target", "ti-tag", "ti-desktop", "ti-tablet", "ti-mobile", "ti-email", "ti-star", "ti-spray", "ti-signal", "ti-shopping-cart", "ti-shopping-cart-full", "ti-settings", "ti-search", "ti-zoom-in", "ti-zoom-out", "ti-cut", "ti-ruler", "ti-ruler-alt-2", "ti-ruler-pencil", "ti-ruler-alt", "ti-bookmark", "ti-bookmark-alt", "ti-reload", "ti-plus", "ti-minus", "ti-close", "ti-pin", "ti-pencil", "ti-pencil-alt", "ti-paint-roller", "ti-paint-bucket", "ti-na", "ti-medall", "ti-medall-alt", "ti-marker", "ti-marker-alt", "ti-lock", "ti-unlock", "ti-location-arrow", "ti-layout", "ti-layers", "ti-layers-alt", "ti-key", "ti-image", "ti-heart", "ti-heart-broken", "ti-hand-stop", "ti-hand-open", "ti-hand-drag", "ti-flag", "ti-flag-alt", "ti-flag-alt-2", "ti-eye", "ti-import", "ti-export", "ti-cup", "ti-crown", "ti-comments", "ti-comment", "ti-comment-alt", "ti-thought", "ti-clip", "ti-check", "ti-check-box", "ti-camera", "ti-announcement", "ti-brush", "ti-brush-alt", "ti-palette", "ti-briefcase", "ti-bolt", "ti-bolt-alt", "ti-blackboard", "ti-bag", "ti-world", "ti-wheelchair", "ti-car", "ti-truck", "ti-timer", "ti-ticket", "ti-thumb-up", "ti-thumb-down", "ti-stats-up", "ti-stats-down", "ti-shine", "ti-shift-right", "ti-shift-left", "ti-shift-right-alt", "ti-shift-left-alt", "ti-shield", "ti-notepad", "ti-server", "ti-pulse", "ti-printer", "ti-power-off", "ti-plug", "ti-pie-chart", "ti-panel", "ti-package", "ti-music", "ti-music-alt", "ti-mouse", "ti-mouse-alt", "ti-money", "ti-microphone", "ti-menu", "ti-menu-alt", "ti-map", "ti-map-alt", "ti-location-pin", "ti-light-bulb", "ti-info", "ti-infinite", "ti-id-badge", "ti-hummer", "ti-home", "ti-help", "ti-headphone", "ti-harddrives", "ti-harddrive", "ti-gift", "ti-game", "ti-filter", "ti-files", "ti-file", "ti-zip", "ti-folder", "ti-envelope", "ti-dashboard", "ti-cloud", "ti-cloud-up", "ti-cloud-down", "ti-clipboard", "ti-calendar", "ti-book", "ti-bell", "ti-basketball", "ti-bar-chart", "ti-bar-chart-alt", "ti-archive", "ti-anchor", "ti-alert", "ti-alarm-clock", "ti-agenda", "ti-write", "ti-wallet", "ti-video-clapper", "ti-video-camera", "ti-vector", "ti-support", "ti-stamp", "ti-slice", "ti-shortcode", "ti-receipt", "ti-pin2", "ti-pin-alt", "ti-pencil-alt2", "ti-eraser", "ti-more", "ti-more-alt", "ti-microphone-alt", "ti-magnet", "ti-line-double", "ti-line-dotted", "ti-line-dashed", "ti-ink-pen", "ti-info-alt", "ti-help-alt", "ti-headphone-alt", "ti-gallery", "ti-face-smile", "ti-face-sad", "ti-credit-card", "ti-comments-smiley", "ti-time", "ti-share", "ti-share-alt", "ti-rocket", "ti-new-window", "ti-rss", "ti-rss-alt", "ti-control-stop", "ti-control-shuffle", "ti-control-play", "ti-control-pause", "ti-control-forward", "ti-control-backward", "ti-volume", "ti-control-skip-forward", "ti-control-skip-backward", "ti-control-record", "ti-control-eject", "ti-paragraph", "ti-uppercase", "ti-underline", "ti-text", "ti-Italic", "ti-smallcap", "ti-list", "ti-list-ol", "ti-align-right", "ti-align-left", "ti-align-justify", "ti-align-center", "ti-quote-right", "ti-quote-left", "ti-layout-width-full", "ti-layout-width-default", "ti-layout-width-default-alt", "ti-layout-tab", "ti-layout-tab-window", "ti-layout-tab-v", "ti-layout-tab-min", "ti-layout-slider", "ti-layout-slider-alt", "ti-layout-sidebar-right", "ti-layout-sidebar-none", "ti-layout-sidebar-left", "ti-layout-placeholder", "ti-layout-menu", "ti-layout-menu-v", "ti-layout-menu-separated", "ti-layout-menu-full", "ti-layout-media-right", "ti-layout-media-right-alt", "ti-layout-media-overlay", "ti-layout-media-overlay-alt", "ti-layout-media-overlay-alt-2", "ti-layout-media-left", "ti-layout-media-left-alt", "ti-layout-media-center", "ti-layout-media-center-alt", "ti-layout-list-thumb", "ti-layout-list-thumb-alt", "ti-layout-list-post", "ti-layout-list-large-image", "ti-layout-line-solid", "ti-layout-grid4", "ti-layout-grid3", "ti-layout-grid2", "ti-layout-grid2-thumb", "ti-layout-cta-right", "ti-layout-cta-left", "ti-layout-cta-center", "ti-layout-cta-btn-right", "ti-layout-cta-btn-left", "ti-layout-column4", "ti-layout-column3", "ti-layout-column2", "ti-layout-accordion-separated", "ti-layout-accordion-merged", "ti-layout-accordion-list", "ti-widgetized", "ti-widget", "ti-widget-alt", "ti-view-list", "ti-view-list-alt", "ti-view-grid", "ti-upload", "ti-download", "ti-loop", "ti-layout-sidebar-2", "ti-layout-grid4-alt", "ti-layout-grid3-alt", "ti-layout-grid2-alt", "ti-layout-column4-alt", "ti-layout-column3-alt", "ti-layout-column2-alt", "ti-flickr", "ti-flickr-alt", "ti-instagram", "ti-google", "ti-github", "ti-facebook", "ti-dropbox", "ti-dropbox-alt", "ti-dribbble", "ti-apple", "ti-android", "ti-yahoo", "ti-trello", "ti-stack-overflow", "ti-soundcloud", "ti-sharethis", "ti-sharethis-alt", "ti-reddit", "ti-microsoft", "ti-microsoft-alt", "ti-linux", "ti-jsfiddle", "ti-joomla", "ti-html5", "ti-css3", "ti-drupal", "ti-wordpress", "ti-tumblr", "ti-tumblr-alt", "ti-skype", "ti-youtube", "ti-vimeo", "ti-vimeo-alt", "ti-twitter", "ti-twitter-alt", "ti-linkedin", "ti-pinterest", "ti-pinterest-alt", "ti-themify-logo", "ti-themify-favicon", "ti-themify-favicon-alt"],
        bpIcons: function(device){
            let svg = '<span class="bricks-svg-wrapper"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14" class="bricks-svg"><g id="screen-1--screen-device-electronics-monitor-diplay-computer"><path id="Vector" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M13 1.5H1c-0.276142 0 -0.5 0.22386 -0.5 0.5v7.5c0 0.27614 0.223858 0.5 0.5 0.5h12c0.2761 0 0.5 -0.22386 0.5 -0.5V2c0 -0.27614 -0.2239 -0.5 -0.5 -0.5Z" stroke-width="1"></path><path id="Vector_2" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="m6 10 -1 2.5" stroke-width="1"></path><path id="Vector_3" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="m8 10 1 2.5" stroke-width="1"></path><path id="Vector_4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M4 12.5h6" stroke-width="1"></path></g></svg></span>';
            if( device === "desktop-3") {
                svg = '<span class="bricks-svg-wrapper"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14" class="bricks-svg"><g id="screen-2--screen-device-electronics-monitor-diplay-computer"><path id="Vector" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M4.09052 12.5c0.10594 -0.6957 0.4577 -1.3305 0.99148 -1.7892C5.61578 10.2522 6.29625 10 7.00002 10s1.38424 0.2522 1.91802 0.7108c0.53379 0.4587 0.88554 1.0935 0.99149 1.7892" stroke-width="1"></path><path id="Vector_2" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M13 1.5H1c-0.276142 0 -0.5 0.22386 -0.5 0.5v7.5c0 0.27614 0.223858 0.5 0.5 0.5h12c0.2761 0 0.5 -0.22386 0.5 -0.5V2c0 -0.27614 -0.2239 -0.5 -0.5 -0.5Z" stroke-width="1"></path></g></svg></span>';
            }
            if( device === "desktop-2") {
                svg = '<span class="bricks-svg-wrapper"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14" class="bricks-svg"><g id="screen-curve--screen-curved-device-electronics-monitor-diplay-computer"><path id="Vector" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M12.93 10.8466c-3.93345 -0.5601 -7.92646 -0.5601 -11.85996 0 -0.070445 0.0099 -0.142209 0.0048 -0.210494 -0.0152 -0.068284 -0.02 -0.131516 -0.0544 -0.185471 -0.1007 -0.053954 -0.0464 -0.097388 -0.1038 -0.1274 -0.1683 -0.030011 -0.0645 -0.045909 -0.1347 -0.046631 -0.2058V1.99658c-0.000963 -0.07167 0.013809 -0.14267 0.043274 -0.20801 0.029465 -0.06534 0.072905 -0.12342 0.127258 -0.17015 0.054352 -0.04672 0.118293 -0.08095 0.187315 -0.10027 0.069021 -0.01933 0.141441 -0.02328 0.212149 -0.01157 3.93421 0.55001 7.9258 0.55001 11.85996 0 0.0699 -0.01156 0.1415 -0.00784 0.2098 0.01091s0.1317 0.05209 0.1859 0.09771c0.0542 0.04562 0.0978 0.10245 0.1279 0.16656 0.0301 0.06412 0.0459 0.134 0.0464 0.20482v8.36002c0.0008 0.072 -0.0141 0.1433 -0.0435 0.209 -0.0294 0.0657 -0.0726 0.1243 -0.1267 0.1718 -0.0541 0.0475 -0.1179 0.0827 -0.1869 0.1033 -0.069 0.0205 -0.1416 0.026 -0.2129 0.0159v0Z" stroke-width="1"></path><path id="Vector_2" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M7 10.4297 7 12.5" stroke-width="1"></path><path id="Vector_3" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.5h5" stroke-width="1"></path></g></svg></span>';
            }
            if( device === "laptop") {
                svg = '<span class="bricks-svg-wrapper"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14" class="bricks-svg"><g id="laptop--device-laptop-electronics-computer-notebook"><path id="Vector" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M3.08 1.61H10.9136C11.4549 1.61 11.8936 2.0488 11.8936 2.59V7.98H2.1V2.59C2.1 2.002 2.492 1.61 3.08 1.61Z" stroke-width="1"></path><path id="Vector 3945" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M0.6957 11.2566L2.1 7.98H11.9L13.3042 11.2566C13.3477 11.3578 13.37 11.4667 13.37 11.5769C13.37 12.0259 13.0059 12.39 12.5569 12.39H1.4431C0.994 12.39 0.63 12.0259 0.63 11.5769C0.63 11.4667 0.6524 11.3578 0.6957 11.2566Z" stroke-width="1"></path></g></svg></span>';
            }
            if( device === "tablet-landscape") {
                svg = '<span class="bricks-svg-wrapper"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14" class="bricks-svg"><g id="ipad-tablet-screen"><path id="vector" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M12.2619 2H1.7381C1.05431 2 0.5 2.53256 0.5 3.18952v7.62098C0.5 11.4674 1.05431 12 1.7381 12h10.5238c0.6838 0 1.2381 -0.5326 1.2381 -1.1895V3.18952C13.5 2.53256 12.9457 2 12.2619 2Z" stroke-width="1"></path><path id="vector_2" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M4.33203 9.77588h5.33993" stroke-width="1"></path></g></svg></span>';
            }
            if( device === "tablet-portrait") {
                svg = '<span class="bricks-svg-wrapper"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14" class="bricks-svg"><g id="one-handed-holding-tablet-handheld"><path id="Rectangle 2038" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M9.64593 1.23658C9.47168 1.089 9.24623 1 9 1H2c-0.55228 0 -1 0.44771 -1 1v9.0938c0 0.5522 0.44772 1 1 1h3.75" stroke-width="1"></path><path id="vector 296" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="m12.3106 13 0.6383 -3.15223c0.0742 -0.36672 0.0675 -0.7452 -0.0197 -1.10906l-0.9088 -3.79119c-0.1682 -0.70134 -0.7013 -1.25797 -1.3954 -1.45681l-0.6221 -0.17821 -0.0002 5.23879c0 0.35407 -0.35839 0.59595 -0.68734 0.46392l-1.6994 -0.68209c-0.3105 -0.12463 -0.66467 -0.06608 -0.91839 0.15183 -0.3824 0.32842 -0.41818 0.90721 -0.07914 1.28012l1.24302 1.36723L8.89958 13" stroke-width="1"></path></g></svg></span>';
            }
            if( device === "phone-landscape") {
                svg = '<span class="bricks-svg-wrapper"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14" class="bricks-svg"><g id="phone-landscape--android-phone-mobile-device-smartphone-iphone-landscape"><path id="Vector" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="m13.5 10.5 0 -7c0 -0.55228 -0.4477 -1 -1 -1l-11 0c-0.552285 0 -1 0.44771 -1 1l0 7c0 0.5523 0.447714 1 1 1l11 0c0.5523 0 1 -0.4477 1 -1Z" stroke-width="1"></path><path id="Vector_2" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="m3 6.5 0 1" stroke-width="1"></path></g></svg></span>';
            }
            if( device === "phone-portrait") {
                svg = '<span class="bricks-svg-wrapper"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14" class="bricks-svg"><g id="phone-mobile-phone--android-phone-mobile-device-smartphone-iphone"><path id="Vector" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M10.5 0.5h-7c-0.55228 0 -1 0.447715 -1 1v11c0 0.5523 0.44772 1 1 1h7c0.5523 0 1 -0.4477 1 -1v-11c0 -0.552285 -0.4477 -1 -1 -1Z" stroke-width="1"></path><path id="Vector_2" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M6.5 11h1" stroke-width="1"></path></g></svg></span>';
            }
            return svg;
        },
        leftIcons: {
            "content":`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="bricks-svg"><path d="M12 22h9"></path><path d="M16.5 3.5l4.5 4.5L7.5 21H3v-4.5L16.5 3.5z" transform="translate(-0.5, -0.5) scale(1.05)" /></svg>`, 
            "_layout": `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="bricks-svg"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M1.5 2.99707V20.9971c0 0.8284 0.67157 1.5 1.5 1.5h18c0.8284 0 1.5 -0.6716 1.5 -1.5V2.99707c0 -0.82843 -0.6716 -1.5 -1.5 -1.5H3c-0.82843 0 -1.5 0.67157 -1.5 1.5Z" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M12.0029 22.4971V1.49707" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M12.0029 11.9971h10" stroke-width="2"></path></svg>`,
            "_typography": `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="bricks-svg"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M0.75 12.749h10.5" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.249h7.5" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M15.75 21.749V13.5c0 -0.9946 0.3951 -1.9484 1.0983 -2.6517 0.7033 -0.7032 1.6571 -1.0983 2.6517 -1.0983 0.9946 0 1.9484 0.3951 2.6517 1.0983 0.7032 0.7033 1.0983 1.6571 1.0983 2.6517v8.25" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M0.75 21.749V7.5c0 -1.39239 0.55312 -2.72774 1.53769 -3.71231C3.27226 2.80312 4.60761 2.25 6 2.25c1.39239 0 2.72774 0.55312 3.71231 1.53769C10.6969 4.77226 11.25 6.10761 11.25 7.5v14.25" stroke-width="2"></path></svg>`,
            "_background": `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="bricks-svg">tab-<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M21 16.5c-0.0002 -0.3372 0.0754 -0.6701 0.2213 -0.9741 0.146 -0.304 0.3584 -0.5712 0.6217 -0.7819 0.4394 -0.3526 0.7939 -0.7994 1.0374 -1.3074 0.2436 -0.508 0.3699 -1.0642 0.3696 -1.6276 0.0001 -0.4836 -0.1167 -0.96 -0.3405 -1.3886 -0.2237 -0.42873 -0.5477 -0.79697 -0.9445 -1.0734 -0.3164 -0.22008 -0.571 -0.51776 -0.7393 -0.8645 -0.1684 -0.34673 -0.2448 -0.73089 -0.222 -1.11565 0.0228 -0.38476 0.144 -0.75722 0.3521 -1.08166 0.2081 -0.32444 0.496 -0.58999 0.8362 -0.77119 0.3196 -0.17064 0.5868 -0.42487 0.7732 -0.73556 0.1863 -0.31069 0.2848 -0.66616 0.2848 -1.02844 0 -0.79565 -0.3161 -1.55871 -0.8787 -2.12132C21.8087 1.06607 21.0456 0.75 20.25 0.75c-0.3623 0.000049 -0.7178 0.098501 -1.0284 0.28484 -0.3107 0.18634 -0.565 0.45358 -0.7356 0.77316 -0.1751 0.32883 -0.4292 0.60903 -0.7393 0.81545 -0.3102 0.20641 -0.6667 0.33258 -1.0377 0.36717 -0.3709 0.0346 -0.7447 -0.02346 -1.0876 -0.16896 -0.343 -0.1455 -0.6445 -0.37388 -0.8774 -0.66466 -0.3526 -0.43937 -0.7994 -0.79391 -1.3074 -1.03744C12.9286 0.876031 12.3724 0.749734 11.809 0.75c-0.4836 -0.000087 -0.96 0.116716 -1.3886 0.34046 -0.42873 0.22374 -0.79697 0.54779 -1.0734 0.94454 -0.22008 0.31642 -0.51776 0.571 -0.8645 0.73933 -0.34673 0.16833 -0.73089 0.24477 -1.11565 0.22198 -0.38476 -0.02278 -0.75722 -0.14403 -1.08166 -0.35211 -0.32444 -0.20808 -0.58999 -0.49601 -0.77119 -0.8362 -0.17064 -0.31958 -0.42487 -0.58682 -0.73556 -0.77316C4.46775 0.848501 4.11228 0.750049 3.75 0.75c-0.79565 0 -1.55871 0.31607 -2.12132 0.87868C1.06607 2.19129 0.75 2.95435 0.75 3.75c0.000049 0.36228 0.098501 0.71775 0.28484 1.02844 0.18634 0.31069 0.45358 0.56492 0.77316 0.73556 0.32883 0.17513 0.60903 0.42917 0.81545 0.73932 0.20641 0.31015 0.33258 0.66671 0.36717 1.03766 0.0346 0.37095 -0.02346 0.74468 -0.16896 1.08765 -0.1455 0.34298 -0.37388 0.64445 -0.66466 0.87737 -0.43937 0.3526 -0.79391 0.7994 -1.03744 1.3074 -0.243529 0.508 -0.369826 1.0642 -0.36956 1.6276 -0.000087 0.4836 0.116716 0.96 0.34046 1.3886 0.22374 0.4287 0.54779 0.797 0.94454 1.0734 0.31642 0.2201 0.571 0.5178 0.73933 0.8645 0.16833 0.3467 0.24477 0.7309 0.22198 1.1157 -0.02278 0.3847 -0.14403 0.7572 -0.35211 1.0816 -0.20808 0.3245 -0.49601 0.59 -0.8362 0.7712 -0.31958 0.1706 -0.58682 0.4249 -0.77316 0.7356 -0.186339 0.3106 -0.284791 0.6661 -0.28484 1.0284 0 0.7956 0.31607 1.5587 0.87868 2.1213 0.56261 0.5626 1.32567 0.8787 2.12132 0.8787 0.36228 0 0.71775 -0.0985 1.02844 -0.2848 0.31069 -0.1864 0.56492 -0.4536 0.73556 -0.7732 0.17513 -0.3288 0.42917 -0.609 0.73932 -0.8154 0.31015 -0.2065 0.66671 -0.3326 1.03766 -0.3672 0.37095 -0.0346 0.74468 0.0234 1.08765 0.1689 0.34298 0.1455 0.64445 0.3739 0.87737 0.6647 0.3526 0.4394 0.7994 0.7939 1.3074 1.0374 0.508 0.2436 1.0642 0.3699 1.6276 0.3696 0.4836 0.0001 0.96 -0.1167 1.3886 -0.3405 0.4287 -0.2237 0.797 -0.5477 1.0734 -0.9445 0.2201 -0.3164 0.5178 -0.571 0.8645 -0.7393 0.3467 -0.1684 0.7309 -0.2448 1.1157 -0.222 0.3847 0.0228 0.7572 0.144 1.0816 0.3521 0.3245 0.2081 0.59 0.496 0.7712 0.8362 0.1706 0.3196 0.4249 0.5868 0.7356 0.7732 0.3106 0.1863 0.6661 0.2848 1.0284 0.2848 0.7956 0 1.5587 -0.3161 2.1213 -0.8787 0.5626 -0.5626 0.8787 -1.3257 0.8787 -2.1213 0 -0.3623 -0.0985 -0.7178 -0.2848 -1.0284 -0.1864 -0.3107 -0.4536 -0.565 -0.7732 -0.7356 -0.3602 -0.1918 -0.6614 -0.4779 -0.8713 -0.8277 -0.21 -0.3499 -0.3209 -0.7503 -0.3207 -1.1583Z" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M6.75 6.75h10.5v10.5H6.75V6.75Z" stroke-width="2"></path></svg>`,
            "_border": `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="bricks-svg"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M0.75 8.24805v-6c0 -0.39783 0.158035 -0.77936 0.43934 -1.06066C1.47064 0.906082 1.85218 0.748047 2.25 0.748047h6" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M23.25 8.24805v-6c0 -0.39783 -0.158 -0.77936 -0.4393 -1.06066 -0.2813 -0.281308 -0.6629 -0.439343 -1.0607 -0.439343h-6" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M0.75 15.748v6c0 0.3979 0.158035 0.7794 0.43934 1.0607 0.2813 0.2813 0.66284 0.4393 1.06066 0.4393h6" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M23.25 15.748v6c0 0.3979 -0.158 0.7794 -0.4393 1.0607s-0.6629 0.4393 -1.0607 0.4393h-6" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M5.25 5.24805h13.5V18.748H5.25V5.24805Z" stroke-width="2"></path></svg>`,
            "_gradient": `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="bricks-svg"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M0.881012 3.48596c0 0.68241 0.271088 1.33686 0.753618 1.81939 0.48253 0.48253 1.13698 0.75361 1.81938 0.75361 0.6824 0 1.33686 -0.27108 1.81939 -0.75361 0.48253 -0.48253 0.75361 -1.13698 0.75361 -1.81939 0 -0.33789 -0.06655 -0.67247 -0.19586 -0.98464 -0.1293 -0.31217 -0.31883 -0.59582 -0.55775 -0.83474 -0.23893 -0.23893 -0.52257 -0.42845 -0.83474 -0.55776C4.12649 0.979516 3.7919 0.912964 3.45401 0.912964s-0.67247 0.066552 -0.98464 0.195856c-0.31217 0.12931 -0.59582 0.31883 -0.83474 0.55776 -0.23893 0.23892 -0.42845 0.52257 -0.55776 0.83474 -0.129305 0.31217 -0.195858 0.64675 -0.195858 0.98464Z" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M0.881012 12c0 0.6824 0.271088 1.3369 0.753618 1.8194 0.48253 0.4825 1.13698 0.7536 1.81938 0.7536 0.6824 0 1.33686 -0.2711 1.81939 -0.7536 0.48253 -0.4825 0.75361 -1.137 0.75361 -1.8194 0 -0.3379 -0.06655 -0.6725 -0.19586 -0.9846 -0.1293 -0.3122 -0.31883 -0.5959 -0.55775 -0.8348 -0.23893 -0.23891 -0.52257 -0.42843 -0.83474 -0.55774 -0.31217 -0.12931 -0.64676 -0.19586 -0.98465 -0.19586s-0.67247 0.06655 -0.98464 0.19586c-0.31217 0.12931 -0.59582 0.31883 -0.83474 0.55774 -0.23893 0.2389 -0.42845 0.5226 -0.55776 0.8348 -0.129305 0.3121 -0.195858 0.6467 -0.195858 0.9846Z" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M0.881012 20.514c0 0.6824 0.271088 1.3369 0.753618 1.8194 0.48253 0.4826 1.13698 0.7536 1.81938 0.7536 0.6824 0 1.33686 -0.271 1.81939 -0.7536 0.48253 -0.4825 0.75361 -1.137 0.75361 -1.8194 0 -0.3379 -0.06655 -0.6724 -0.19586 -0.9846 -0.1293 -0.3122 -0.31883 -0.5958 -0.55775 -0.8347 -0.23893 -0.239 -0.52257 -0.4285 -0.83474 -0.5578 -0.31217 -0.1293 -0.64676 -0.1959 -0.98465 -0.1959s-0.67247 0.0666 -0.98464 0.1959c-0.31217 0.1293 -0.59582 0.3188 -0.83474 0.5578 -0.23893 0.2389 -0.42845 0.5225 -0.55776 0.8347 -0.129305 0.3122 -0.195858 0.6467 -0.195858 0.9846Z" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M9.27899 3.486c0 0.25398 0.05003 0.50547 0.14722 0.74011 0.09719 0.23465 0.23965 0.44785 0.41924 0.62744 0.17955 0.17959 0.39275 0.32204 0.62745 0.41924 0.2346 0.09719 0.4861 0.14721 0.7401 0.14721s0.5055 -0.05002 0.7401 -0.14721c0.2346 -0.0972 0.4478 -0.23965 0.6274 -0.41924 0.1796 -0.17959 0.3221 -0.39279 0.4193 -0.62744 0.0972 -0.23464 0.1472 -0.48613 0.1472 -0.74011 0 -0.25397 -0.05 -0.50546 -0.1472 -0.74011 -0.0972 -0.23464 -0.2397 -0.44784 -0.4193 -0.62743 -0.1796 -0.17959 -0.3928 -0.32205 -0.6274 -0.41924 -0.2346 -0.09719 -0.4861 -0.14722 -0.7401 -0.14722s-0.5055 0.05003 -0.7401 0.14722c-0.2347 0.09719 -0.4479 0.23965 -0.62745 0.41924 -0.17959 0.17959 -0.32205 0.39279 -0.41924 0.62743 -0.09719 0.23465 -0.14722 0.48614 -0.14722 0.74011Z" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M9.27899 12c0 0.254 0.05003 0.5055 0.14722 0.7401 0.09719 0.2347 0.23965 0.4479 0.41924 0.6275 0.17955 0.1796 0.39275 0.322 0.62745 0.4192 0.2346 0.0972 0.4861 0.1472 0.7401 0.1472s0.5055 -0.05 0.7401 -0.1472c0.2346 -0.0972 0.4478 -0.2396 0.6274 -0.4192 0.1796 -0.1796 0.3221 -0.3928 0.4193 -0.6275 0.0972 -0.2346 0.1472 -0.4861 0.1472 -0.7401 0 -0.2539 -0.05 -0.5054 -0.1472 -0.7401 -0.0972 -0.2346 -0.2397 -0.4478 -0.4193 -0.6274 -0.1796 -0.1796 -0.3928 -0.3221 -0.6274 -0.4192 -0.2346 -0.0972 -0.4861 -0.1473 -0.7401 -0.1473s-0.5055 0.0501 -0.7401 0.1473c-0.2347 0.0971 -0.4479 0.2396 -0.62745 0.4192 -0.17959 0.1796 -0.32205 0.3928 -0.41924 0.6274 -0.09719 0.2347 -0.14722 0.4862 -0.14722 0.7401Z" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M9.27899 20.514c0 0.2539 0.05003 0.5054 0.14722 0.7401 0.09719 0.2346 0.23965 0.4478 0.41924 0.6274 0.17955 0.1796 0.39275 0.322 0.62745 0.4192 0.2346 0.0972 0.4861 0.1473 0.7401 0.1473s0.5055 -0.0501 0.7401 -0.1473c0.2346 -0.0972 0.4478 -0.2396 0.6274 -0.4192 0.1796 -0.1796 0.3221 -0.3928 0.4193 -0.6274 0.0972 -0.2347 0.1472 -0.4862 0.1472 -0.7401 0 -0.254 -0.05 -0.5055 -0.1472 -0.7402 -0.0972 -0.2346 -0.2397 -0.4478 -0.4193 -0.6274 -0.1796 -0.1796 -0.3928 -0.322 -0.6274 -0.4192 -0.2346 -0.0972 -0.4861 -0.1472 -0.7401 -0.1472s-0.5055 0.05 -0.7401 0.1472c-0.2347 0.0972 -0.4479 0.2396 -0.62745 0.4192 -0.17959 0.1796 -0.32205 0.3928 -0.41924 0.6274 -0.09719 0.2347 -0.14722 0.4862 -0.14722 0.7402Z" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M16.398 3.48602c0 0.1761 0.0347 0.35048 0.1021 0.51318 0.0674 0.1627 0.1662 0.31053 0.2907 0.43505 0.1245 0.12452 0.2723 0.2233 0.435 0.29069s0.3371 0.10208 0.5132 0.10208c0.1761 0 0.3505 -0.03469 0.5132 -0.10208s0.3105 -0.16617 0.435 -0.29069c0.1246 -0.12452 0.2233 -0.27235 0.2907 -0.43505 0.0674 -0.1627 0.1021 -0.33708 0.1021 -0.51318 0 -0.1761 -0.0347 -0.35048 -0.1021 -0.51318 -0.0674 -0.1627 -0.1661 -0.31053 -0.2907 -0.43505 -0.1245 -0.12452 -0.2723 -0.2233 -0.435 -0.29069s-0.3371 -0.10208 -0.5132 -0.10208c-0.1761 0 -0.3505 0.03469 -0.5132 0.10208s-0.3105 0.16617 -0.435 0.29069c-0.1245 0.12452 -0.2233 0.27235 -0.2907 0.43505 -0.0674 0.1627 -0.1021 0.33708 -0.1021 0.51318Z" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M16.398 12.0001c0 0.1761 0.0347 0.3504 0.1021 0.5131 0.0674 0.1627 0.1662 0.3106 0.2907 0.4351 0.1245 0.1245 0.2723 0.2233 0.435 0.2907 0.1627 0.0674 0.3371 0.1021 0.5132 0.1021 0.1761 0 0.3505 -0.0347 0.5132 -0.1021 0.1627 -0.0674 0.3105 -0.1662 0.435 -0.2907 0.1246 -0.1245 0.2233 -0.2724 0.2907 -0.4351 0.0674 -0.1627 0.1021 -0.337 0.1021 -0.5131 0 -0.1761 -0.0347 -0.3505 -0.1021 -0.5132 -0.0674 -0.1627 -0.1661 -0.3105 -0.2907 -0.4351 -0.1245 -0.1245 -0.2723 -0.2233 -0.435 -0.2907 -0.1627 -0.0674 -0.3371 -0.102 -0.5132 -0.102 -0.1761 0 -0.3505 0.0346 -0.5132 0.102 -0.1627 0.0674 -0.3105 0.1662 -0.435 0.2907 -0.1245 0.1246 -0.2233 0.2724 -0.2907 0.4351 -0.0674 0.1627 -0.1021 0.3371 -0.1021 0.5132Z" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M16.398 20.514c0 0.1761 0.0347 0.3505 0.1021 0.5132 0.0674 0.1626 0.1662 0.3105 0.2907 0.435 0.1245 0.1245 0.2723 0.2233 0.435 0.2907 0.1627 0.0674 0.3371 0.1021 0.5132 0.1021 0.1761 0 0.3505 -0.0347 0.5132 -0.1021 0.1627 -0.0674 0.3105 -0.1662 0.435 -0.2907 0.1246 -0.1245 0.2233 -0.2724 0.2907 -0.435 0.0674 -0.1627 0.1021 -0.3371 0.1021 -0.5132 0 -0.1761 -0.0347 -0.3505 -0.1021 -0.5132 -0.0674 -0.1627 -0.1661 -0.3105 -0.2907 -0.4351 -0.1245 -0.1245 -0.2723 -0.2233 -0.435 -0.2906 -0.1627 -0.0674 -0.3371 -0.1021 -0.5132 -0.1021 -0.1761 0 -0.3505 0.0347 -0.5132 0.1021 -0.1627 0.0673 -0.3105 0.1661 -0.435 0.2906 -0.1245 0.1246 -0.2233 0.2724 -0.2907 0.4351 -0.0674 0.1627 -0.1021 0.3371 -0.1021 0.5132Z" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M22.7255 3.09302c-0.1967 0 -0.3935 0.19675 -0.3935 0.39348s0.1968 0.39342 0.3935 0.39342" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M22.7254 3.09302c0.1968 0 0.3935 0.19675 0.3935 0.39348s-0.1967 0.39342 -0.3935 0.39342" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M22.7255 11.6064c-0.1967 0 -0.3935 0.1968 -0.3935 0.3935 0 0.1968 0.1968 0.3935 0.3935 0.3935" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M22.7254 11.6064c0.1968 0 0.3935 0.1968 0.3935 0.3935 0 0.1968 -0.1967 0.3935 -0.3935 0.3935" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M22.7255 20.1201c-0.1967 0 -0.3935 0.1968 -0.3935 0.3935s0.1968 0.3934 0.3935 0.3934" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M22.7254 20.1201c0.1968 0 0.3935 0.1968 0.3935 0.3935s-0.1967 0.3934 -0.3935 0.3934" stroke-width="2"></path></svg>`,
            "_shapes": `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="bricks-svg"><path d="m1.816 2.8 8.428 19.072a0.75 0.75 0 0 0 1.411 -0.112l1.884 -7.158a1.5 1.5 0 0 1 1.068 -1.069l7.158 -1.884a0.75 0.75 0 0 0 0.113 -1.411L2.806 1.814a0.75 0.75 0 0 0 -0.99 0.986Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path></svg>`,
            "_transform": `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="bricks-svg"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M16.629 23.25c0.3975 -0.0001 0.7788 -0.158 1.06 -0.439l5.122 -5.122c0.281 -0.2812 0.4389 -0.6625 0.439 -1.06V2.25c0 -0.39782 -0.158 -0.77936 -0.4393 -1.06066C22.5294 0.908035 22.1478 0.75 21.75 0.75H7.371c-0.39755 0.000085 -0.7788 0.157982 -1.06 0.439L1.189 6.311c-0.281018 0.2812 -0.438915 0.66245 -0.439 1.06V21.75c0 0.3978 0.158035 0.7794 0.43934 1.0607 0.2813 0.2813 0.66284 0.4393 1.06066 0.4393h14.379Z" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M17.25 23.115V6.75" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M6.75 17.25h16.365" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M1.189 22.811 6.75 17.25" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="m17.25 6.74996 5.561 -5.561" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M17.25 6.75H0.88501" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M6.75 0.88501V17.25" stroke-width="2"></path></svg>`,
            "_filter": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="bricks-svg">
  <path d="M1 3h22" />
  <path d="M4 9h16" />
  <path d="M5 15h14" />
  <path d="M12 21V3" />
</svg>

`,
            "_animation" : `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="bricks-svg">
  <circle cx="12" cy="12" r="11" />
  <path d="M10 7L16 12L10 17V7z" />
</svg>
`,
            "_css": `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="bricks-svg"><path d="M19.629 19.238 12.739 23a1.5 1.5 0 0 1 -1.439 0l-6.89 -3.758a1.5 1.5 0 0 1 -0.762 -1.07L1.061 2.635A1.5 1.5 0 0 1 2.541 0.888H21.5a1.5 1.5 0 0 1 1.479 1.747L20.39 18.168a1.5 1.5 0 0 1 -0.761 1.07Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path><path d="m8.27 15.888 3.75 2.25 3.75 -2.25 0.75 -6 -6.75 0 7.5 -4.5 -10.5 0" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path></svg>`,
            "_classes": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" class="bricks-svg" fill="currentColor" stroke="currentColor" stroke-width="36">
  <path d="M622.353067 505.736533a385.672533 385.672533 0 0 1 124.027733 61.6448 24.9088 24.9088 0 0 1 11.502933 20.996267c0 13.781333-11.204267 24.9472-25.028266 24.9472a24.977067 24.977067 0 0 1-16.3712-6.08l-0.072534 0.085333c-53.9776-41.2416-119.031467-67.5072-187.042133-70.7712a224.554667 224.554667 0 0 1-36.949333 0.520534c-170.257067 13.013333-320.341333 170.858667-320.341334 342.6304 0 17.194667-4.514133 29.090133-21.7088 29.090133-17.198933 0-22.912-11.895467-22.912-29.090133 0-173.064533 113.966933-320.938667 270.818134-370.944C331.144533 470.621867 285.866667 398.464 285.866667 315.733333c0-122.5344 99.328-221.866667 221.866666-221.866666 122.5344 0 221.866667 99.332267 221.866667 221.866666 0 80.5888-42.9696 151.146667-107.246933 190.0032z m-23.808 282.432c-14.877867 0-26.939733-12.155733-26.939734-27.1488 0-14.997333 12.061867-27.153067 26.944-27.153066 14.882133 0 26.944 12.16 26.944 27.153066s-12.061867 27.1488-26.944 27.1488zM692.053333 733.866667h185.6c19.5584 0 31.146667 12.16 31.146667 27.153066s-11.588267 27.1488-31.146667 27.1488h-185.6c-19.5584 0-31.146667-12.155733-31.146666-27.1488 0-14.997333 11.588267-27.153067 31.146666-27.153066z m-93.44 179.2c-14.848 0-26.88-12.125867-26.88-27.0848s12.032-27.089067 26.88-27.089067 26.88 12.130133 26.88 27.089067c0 14.958933-12.032 27.0848-26.88 27.0848z m93.44-54.301867h185.6c19.5584 0 31.146667 12.155733 31.146667 27.1488 0 14.997333-11.588267 27.153067-31.146667 27.153067h-185.6c-19.5584 0-31.146667-12.16-31.146666-27.153067s11.588267-27.1488 31.146666-27.1488zM507.733333 490.666667c96.6016 0 174.933333-78.3232 174.933334-174.933334s-78.331733-174.933333-174.933334-174.933333c-96.622933 0-174.933333 78.3232-174.933333 174.933333s78.3104 174.933333 174.933333 174.933334z"/>
</svg>

`,
            "_attributes": `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="bricks-svg"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="m17.99325 17.622 -6.315833333333333 3.44575c-0.20203333333333334 0.110275 -0.42844999999999994 0.16802499999999998 -0.658625 0.16802499999999998 -0.230175 0 -0.4565916666666666 -0.057749999999999996 -0.658625 -0.16802499999999998l-6.315833333333333 -3.44575c-0.183205 -0.099825 -0.3413116666666667 -0.2399833333333333 -0.46233 -0.4099333333333333 -0.12101833333333332 -0.16985833333333333 -0.20177666666666666 -0.3651083333333333 -0.23616999999999996 -0.5709L0.9725833333333332 2.4025833333333333c-0.03274333333333333 -0.19696416666666666 -0.022201666666666665 -0.39870416666666664 0.03090083333333333 -0.5911858333333333 0.0531025 -0.19248166666666666 0.14749166666666666 -0.371085 0.27660416666666665 -0.5233983333333333 0.12910333333333332 -0.15231333333333333 0.2898408333333333 -0.2746791666666667 0.47101999999999994 -0.3586 0.18118833333333334 -0.08391074999999999 0.37847333333333333 -0.12735708333333334 0.5781416666666667 -0.12731583333333335H19.708333333333332c0.19955833333333334 0.00009166666666666667 0.3967333333333333 0.04363608333333333 0.5778666666666666 0.12760916666666666 0.18104166666666666 0.08396666666666666 0.3416416666666666 0.20636 0.4707083333333333 0.358655 0.12897499999999998 0.152295 0.2233 0.33085249999999994 0.276375 0.52327 0.05298333333333333 0.1924175 0.063525 0.394075 0.030799999999999998 0.5909658333333333L18.690833333333334 16.641166666666667c-0.033916666666666664 0.20579166666666665 -0.11439999999999999 0.4011333333333333 -0.2353083333333333 0.571175 -0.12081666666666666 0.16995 -0.27894166666666664 0.3101083333333333 -0.46227499999999994 0.40965833333333335Z" stroke-width="2"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M15.830833333333333 4.927083333333333H6.205833333333333l0.6875 4.125h8.25l-0.6875 5.5 -3.4375 2.0625 -3.4375 -2.0625" stroke-width="2"></path></svg>`,
            "_generated-code": `<svg xmlns="http://www.w3.org/2000/svg"  fill="none" viewBox="0 0 48 48" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="bricks-svg">
<path d="M16 4C14 4 11 5 11 9C11 13 11 15 11 18C11 21 6 23 6 23C6 23 11 25 11 28C11 31 11 35 11 39C11 43 14 44 16 44" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" id="element_59c94c49"></path>
<path d="M32 4C34 4 37 5 37 9C37 13 37 15 37 18C37 21 42 23 42 23C42 23 37 25 37 28C37 31 37 35 37 39C37 43 34 44 32 44" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" id="element_f726713d"></path>
</svg>`,
            "_pageTransition": `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="bricks-svg"><path d="M17.625 23.25h-13.5a1.5 1.5 0 0 1 -1.5 -1.5V5.625" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path><path d="M21.375 18.159A1.8 1.8 0 0 1 19.625 20H7.375a1.8 1.8 0 0 1 -1.75 -1.841V2.591A1.8 1.8 0 0 1 7.375 0.75h8.9a1.711 1.711 0 0 1 1.238 0.539l3.349 3.524a1.888 1.888 0 0 1 0.513 1.3Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path></svg>

`,
        },
        isComponentPanelOpen: function () {
            const activePanel = ADMINBRXC.vueState.activePanel === "element";
            const selector = !!document.querySelector('#bricks-panel-element.property, #bricks-panel-element.instance');
            return activePanel && selector;
        },
        getElementObject: function(id, forceStructure = false){

            const getElementObject = ADMINBRXC.vueGlobalProp.$_getElementObject;
            const getDynamicElementById = ADMINBRXC.vueGlobalProp.$_getDynamicElementById;
        
            if (typeof getElementObject === 'function') {
                return getElementObject(id);
            } else if (typeof getDynamicElementById === 'function') {
                const obj = getDynamicElementById(id);
                if(obj && obj.hasOwnProperty('cid') && !forceStructure){
                    return ADMINBRXC.vueGlobalProp.$_getComponentElementById(obj.cid);
                } else {
                    return obj;
                }
            } else {
                console.error("No suitable function available to get element object.");
                return null;
            }
            
        },
        getFinalObject: function(skipClass = false, skipComponent = false, forceStructure = false){
            if(!skipClass && ADMINBRXC.helpers.isClassActive()){
                return ADMINBRXC.vueState.globalClasses.find(el => el.id === ADMINBRXC.vueState.activeClass.id);
            }

            if(!skipComponent && ADMINBRXC.vueState.activeElement && ADMINBRXC.vueState.activeElement.hasOwnProperty('cid') 
            ){
                return ADMINBRXC.vueGlobalProp.$_getComponentElementById(ADMINBRXC.vueState.activeElement.cid);
            }
            if(typeof ADMINBRXC.vueState.activeElement === "object" && ADMINBRXC.vueState.activeElement.hasOwnProperty('id')){
                return ADMINBRXC.helpers.getElementObject(ADMINBRXC.vueState.activeElement.id, forceStructure)
            }

            return false;
        },
        getFinalSelector: function(){
            const dot = ADMINBRXC.helpers.isComponentActive() ? '.' : '#';
            const elementObj = ADMINBRXC.helpers.getFinalObject();
            return ADMINBRXC.helpers.isClassActive() ? `.${ADMINBRXC.vueState.activeClass.name}` : elementObj.settings.hasOwnProperty('_cssId') ? `${dot}${elementObj.settings._cssId}` : `${dot}brxe-${elementObj.id}`;
        },
            
        // Get keys settings divided by pseudo
        stylesByPseudo: function(settings){
            const arr = {};
            const hasPseudo = []
            const pseudos = ADMINBRXC.vueState.pseudoClasses;
            pseudos.forEach(pseudo => {
                const nestedArr = Object.keys(settings)
                    .filter(key => key && ADMINBRXC.helpers.isCSSControlKey(key.split(':')[0]) && key.includes(pseudo))
                    .sort();
                nestedArr.forEach(el => hasPseudo.push(el));
                arr[pseudo.replace(':', '')] = nestedArr
            })
            arr['no-pseudo'] = Object.keys(settings)
                .filter(key => key && ADMINBRXC.helpers.isCSSControlKey(key.split(':')[0]) && !hasPseudo.includes(key))
                .sort();
            return arr;
        },
        // Get unique keys settings divided by pseudo and
        uniqueKeysByPseudo: function(settings){
            arr = ADMINBRXC.helpers.stylesByPseudo(settings);
            for(const row of Object.keys(arr)){
                const newArr = arr[row].map(property => property.split(":")[0]);
                arr[row] = [...new Set(newArr)];
            }
            return arr;
        },
        // Global Colors
        isGlobalColorsTabActive: function(){
            return Object.values(ADMINBRXC.globalSettings.themeSettingsTabs).includes("global-colors");
        },
        // CSS Variables
        isCSSVariablesTabActive: function(option){
            return Object.values(ADMINBRXC.globalSettings.themeSettingsTabs).includes("css-variables");
        },
        // Classes & Styles
        isClassesAndStylesTabActive: function(option){
            return Object.values(ADMINBRXC.globalSettings.themeSettingsTabs).includes("classes-and-styles");
        },
        // Builder Tweaks
        isBuilderTweaksTabActive: function(option = false){
            return Object.values(ADMINBRXC.globalSettings.themeSettingsTabs).includes("builder-tweaks");
        },
        isStrictEditorViewTabActive: function(){
            return Object.values(ADMINBRXC.globalSettings.themeSettingsTabs).includes("strict-editor-view");
        },
        // AI
        isAIActive: function(){
            return Object.values(ADMINBRXC.globalSettings.themeSettingsTabs).includes("ai");
        },
        // Custom Elements
        isCustomElements: function(option){
            return ADMINBRXC.helpers.isBuilderTweaksTabActive('elements') && Object.values(ADMINBRXC.globalSettings.defaultElementFeatures).includes(option);
        },
        isCSSControlKey: function(key) {
            const baseKey = key.split(":")[0];
            return (
                ADMINBRXC.CSScontrolKeys.includes(baseKey) &&
                !ADMINBRXC.excludedControlKeyFromCSS.includes(baseKey)
            );
        },
        isClassActive: function(){
            const activeClass = ADMINBRXC.vueState.activeClass;
            return activeClass && typeof activeClass === "object" && activeClass.hasOwnProperty('id');
        },
        isComponentActive: function(){
            if(!ADMINBRXC.vueState.hasOwnProperty('components')) return false;
            const activeComponent = ADMINBRXC.vueState.activeComponent;
            if (typeof activeComponent === "undefined"
                || activeComponent === false
                || activeComponent === "" 
                || !activeComponent.hasOwnProperty('id')) return false;
            return true;
        },
        getTemplateType: function(){
            const templateType = ADMINBRXC.vueState.templateType;
            if(templateType === "section" || templateType === "archive" || templateType === "error" || templateType === "popup" || templateType === "search" || !ADMINBRXC.vueState.hasOwnProperty(templateType)){
                return "content";
            } else {
                return templateType;
            }
        },
        clampBuilder: function(minFontSize, maxFontSize, minWidthPx = false, maxWidthPx = false) {
            const minViewportWidth = minWidthPx ? minWidthPx : 'var(--min-viewport)';
            const maxViewportWidth = maxWidthPx ? maxWidthPx : 'var(--max-viewport)';
            
            return `clamp(calc(1rem * (${minFontSize} / var(--base-font))), calc(1rem * ((((-1 * ${minViewportWidth}) / var(--base-font)) * ((${maxFontSize} - ${minFontSize}) / var(--base-font)) / ((${maxViewportWidth} - ${minViewportWidth}) / var(--base-font))) + (${minFontSize} / var(--base-font)))) + (((${maxFontSize} - ${minFontSize}) / var(--base-font)) / ((${maxViewportWidth} - ${minViewportWidth}) / var(--base-font)) * 100) * var(--clamp-unit), calc(1rem * (${maxFontSize} / var(--base-font))));`
             
        },
        clampBuilderInline: function(obj){
            const stepNum = obj.step;
            const baseFont = parseInt(obj.baseFont)
            
            if( stepNum == 0 ) {
                var stepMin = obj.baseMin;
                var stepMax = obj.baseMax;
            } else {
                var stepMin = obj.baseMin * obj.minFactor;
                var stepMax = obj.baseMax * obj.maxFactor;
            }
            
            minWidthRem = obj.minViewport / baseFont;
            maxWidthRem = obj.maxViewport / baseFont;
            stepMinRem = stepMin / baseFont;
            stepMaxRem = stepMax / baseFont;

            const slope = (stepMaxRem - stepMinRem) / (maxWidthRem - minWidthRem);
            const yIntersection = (-1 * minWidthRem) * slope + stepMinRem;
            const slopeVW = slope * 100;

            return `clamp( ${stepMinRem}rem, ${yIntersection}rem + ${slopeVW}vw, ${stepMaxRem}rem)`;

        },
         isElementActive: function(){
            if(ADMINBRXC.vueState.activePanel === "element" && 
                (
                    (
                        ADMINBRXC.vueState.activeElement &&
                        ADMINBRXC.vueState.activeElement.hasOwnProperty('id')
                    ) || 
                    (
                        typeof ADMINBRXC.vueState.activeElement === "undefined" && 
                        ADMINBRXC.vueState.activeComponent &&
                        ADMINBRXC.vueState.activeComponent.hasOwnProperty('id')
                    )
                )
            ) return true
            return false;
         },
         isValidCSSClassName: function(className) {
            if (!/^[a-zA-Z_\-]/.test(className)) {
              return false;
            }
          
            if (!/^[a-zA-Z0-9_\-\s]*$/.test(className)) {
              return false;
            }
          
            return true;
        },
        createClassCategory: function(name){
            if(!name) return;
            if(ADMINBRXC.helpers.getClassCategoryIdByName(name.toLowerCase()) !== false) ADMINBRXC.vueGlobalProp.$_showMessage('ABORT: Category already exists!');
            ADMINBRXC.vueState.globalClassesCategories.push({
                id: ADMINBRXC.vueGlobalProp.$_generateId(),
                name: name,
            })
            ADMINBRXC.populateClassCategories();
        },
        checkClassName: function(classname, list = false){
            let format = classname.replaceAll('<span class="brxc_changes">', '');
            format = format.replaceAll('</span>', '')
            if(Array.from(ADMINBRXC.vueState.globalClasses).find(el => el && el.name === `${format}`)){
                if (list) return ADMINBRXC.helpers.checkClassName(`${classname}<span class="brxc_changes">-new</span>`, list);
                return ADMINBRXC.helpers.checkClassName(`${classname}-new`, list);
            } else {
                return `${classname}`;
            }
        },
        isFramework(id){
            if(id && id.startsWith('acss')) return true;
            return false;
        },
        setColorPrefix: function(name, isFramework, palettePrefix){
            if(!palettePrefix || palettePrefix === '' || palettePrefix === "0" || name.startsWith(palettePrefix) || isFramework) return name;
            return `${palettePrefix}${name}`;
        },
        getColorName: function(color, prefix = '') {
            if (color.name) return color.name;
            if (!color.raw) return '';
            let name = color.raw.replace(/^var\(--/, '').replace(/\)$/, '');
            if (prefix && name.startsWith(prefix)) {
                name = name.substring(prefix.length);
            }
            return name;
        },
        escapeHtmlSpecialChars: function(input) {
            const entityMap = {
                '&': '&amp;',
                '<': '&lt;',
                '>': '&gt;',
                '"': '&quot;',
                "'": '&#39;',
                '/': '&#47;',
                '`': '&#96;',
                '!': '&#33;',
                '@': '&#64;',
                '#': '&#35;',
                '$': '&#36;',
                '%': '&#37;',
                '^': '&#94;',
                '*': '&#42;',
                '(': '&#40;',
                ')': '&#41;',
                '+': '&#43;',
                '=': '&#61;',
                '{': '&#123;',
                '}': '&#125;',
                '[': '&#91;',
                ']': '&#93;',
                '|': '&#124;',
                '\\': '&#92;',
                ':': '&#58;',
                ';': '&#59;',
                ',': '&#44;',
                '.': '&#46;',
                '?': '&#63;',
                '~': '&#126;'
            };
        
            return input.replace(/[&<>"'\/`!@#$%^*()+=\{\}\[\]|\\:;,.<>?~]/g, (char) => entityMap[char]);
        },
        formatForClasses: function(input){
            return input.trim().replaceAll(/[^a-zA-Z0-9_-]+/g, '-').toLowerCase();
        },
        checkBreakpointFormat: function(property){
            const bpSettings = Array.from(ADMINBRXC.vueState.breakpoints).find(el => el && el.key === ADMINBRXC.vueState.breakpointActive);
            if(bpSettings.key !== "desktop"){
                property += `:${bpSettings.key}`;
            }
            return property;
        },
        isVarActiveOnPage: function(colorRaw){
            // content
            const content = ADMINBRXC.helpers.getContent();
            let string = (content) ? JSON.stringify(content) : '';

            // check if colorRaw is active
            if(string.includes(colorRaw)) return true;

            // theme settings
            const themeSettings = ADMINBRXC.vueState.themeStyleSettings;
            string = (themeSettings) ? JSON.stringify(themeSettings) : '';

            // check if colorRaw is active
            if(string.includes(colorRaw)) return true;

            // active classes
            let cls = [];
            string = "";
            if (Array.isArray(content) && content.length > 0) {
                cls = content.reduce((accumulator, el) => {
                    if (
                        el.settings.hasOwnProperty('_cssGlobalClasses') &&
                        el.settings._cssGlobalClasses.length > 0
                    ) {
                        accumulator.push(...el.settings._cssGlobalClasses);
                    }
                    return accumulator;
                }, cls);
            }
            cls = [...new Set(cls)];
            if(cls.length > 0){
                cls.forEach(el =>{
                    string += JSON.stringify(ADMINBRXC.vueGlobalProp.$_getGlobalClass(el));
                })
            }

            // check if colorRaw is active
            if(string.includes(colorRaw)) return true;

            return false;
        },
        setCursorToLastRowMinusOne: function(codeMirror) {
            const lineCount = codeMirror.lineCount();
            if(!lineCount) return;
            const lastLine = lineCount - 2;
            const getLine = codeMirror.getLine(lastLine);
            if(!getLine) return;
            const lastCh = getLine.length;
            codeMirror.setCursor({ line: lastLine, ch: lastCh });
        },
        replaceRWithRoot: function (codeMirror, event) {
            const self = this;
            const cursor = codeMirror.getCursor();
            const lineContent = codeMirror.getLine(cursor.line);
            const cursorPos = cursor.ch;
            let currentWord = codeMirror.getRange(...Object.values(codeMirror.findWordAt(cursor)));

            // r = %root%
            const precedingChar = cursorPos > 1 ? lineContent[cursorPos - 2] : ' ';
            const validPrecedingChars = [' ', '\t', '(', '[', '{'];

            if (cursorPos > 0 && lineContent[cursorPos - 1].toLowerCase() === 'r' && validPrecedingChars.includes(precedingChar)) {
                event.preventDefault();
                const pos = (lineContent[cursorPos - 1] === "R") ? ' {\n\t\n}' : '';

                codeMirror.replaceRange(`%root%${pos}`, { line: cursor.line, ch: cursorPos - 1 }, cursor);

                if (lineContent[cursorPos - 1] === "R") {
                    const newCursor = {
                        line: cursor.line + 1,
                        ch: cursorPos,
                    };

                    codeMirror.setCursor(newCursor);
                }

                return;
            }

            // rh = %root%:hover
            if (cursorPos > 1 && lineContent[cursorPos - 2].toLowerCase() === 'r' && lineContent[cursorPos - 1] === 'h') {
                event.preventDefault();
                const pos = (lineContent[cursorPos - 2] === "R") ? ' {\n\t\n}' : '';

                codeMirror.replaceRange(`%root%:hover${pos}`, { line: cursor.line, ch: cursorPos - 2 }, cursor);

                if((lineContent[cursorPos - 2] === "R")){
                    const newCursor = {
                        line: cursor.line + 1,
                        ch: cursorPos,
                    };
                    
                    codeMirror.setCursor(newCursor);
                }

                return;
            }

            // rb = %root%::before
            if (cursorPos > 1 && lineContent[cursorPos - 2].toLowerCase() === 'r' && lineContent[cursorPos - 1] === 'b') {
                event.preventDefault();
                const pos = (lineContent[cursorPos - 2] === "R") ? ' {\n\t\n}' : '';

                codeMirror.replaceRange(`%root%::before${pos}`, { line: cursor.line, ch: cursorPos - 2 }, cursor);

                if((lineContent[cursorPos - 2] === "R")){
                    const newCursor = {
                        line: cursor.line + 1,
                        ch: cursorPos,
                    };
                    
                    codeMirror.setCursor(newCursor);
                }

                return;
            }

            // ra = %root%::after
            if (cursorPos > 1 && lineContent[cursorPos - 2].toLowerCase() === 'r' && lineContent[cursorPos - 1] === 'a') {
                event.preventDefault();
                const pos = (lineContent[cursorPos - 2] === "R") ? ' {\n\t\n}' : '';

                codeMirror.replaceRange(`%root%::after${pos}`, { line: cursor.line, ch: cursorPos - 2 }, cursor);

                if((lineContent[cursorPos - 2] === "R")){
                    const newCursor = {
                        line: cursor.line + 1,
                        ch: cursorPos,
                    };
                    
                    codeMirror.setCursor(newCursor);
                }
                
                return;
            }

            // rf = %root%:focus
            if (cursorPos > 1 && lineContent[cursorPos - 2].toLowerCase() === 'r' && lineContent[cursorPos - 1] === 'f') {
                event.preventDefault();
                const pos = (lineContent[cursorPos - 2] === "R") ? ' {\n\t\n}' : '';

                codeMirror.replaceRange(`%root%:focus${pos}`, { line: cursor.line, ch: cursorPos - 2 }, cursor);

                if((lineContent[cursorPos - 2] === "R")){
                    const newCursor = {
                        line: cursor.line + 1,
                        ch: cursorPos,
                    };
                    
                    codeMirror.setCursor(newCursor);
                }
                
                return;
            }

            // rcf = %root%:first-child
            if (cursorPos > 2 && lineContent[cursorPos - 3].toLowerCase() === 'r' && lineContent[cursorPos - 2] === 'c' && lineContent[cursorPos - 1] === 'f') {
                event.preventDefault();
                const pos = (lineContent[cursorPos - 3] === "R") ? ' {\n\t\n}' : '';

                codeMirror.replaceRange(`%root%:first-child${pos}`, { line: cursor.line, ch: cursorPos - 3 }, cursor);

                if((lineContent[cursorPos - 3] === "R")){
                    const newCursor = {
                        line: cursor.line + 1,
                        ch: cursorPos,
                    };
                    
                    codeMirror.setCursor(newCursor);
                }
                
                return;
            }

            // rcl = %root%:last-child
            if (cursorPos > 2 && lineContent[cursorPos - 3].toLowerCase() === 'r' && lineContent[cursorPos - 2] === 'c' && lineContent[cursorPos - 1] === 'l') {
                event.preventDefault();
                const pos = (lineContent[cursorPos - 3] === "R") ? ' {\n\t\n}' : '';

                codeMirror.replaceRange(`%root%:last-child${pos}`, { line: cursor.line, ch: cursorPos - 3 }, cursor);

                if((lineContent[cursorPos - 3] === "R")){
                    const newCursor = {
                        line: cursor.line + 1,
                        ch: cursorPos,
                    };
                    
                    codeMirror.setCursor(newCursor);
                }
                
                return;
            }

            //rc1 = %root%:nth-child(1)
            if (currentWord.length > 2 && currentWord[0].toLowerCase() === "r" && currentWord[1].toLowerCase() === "c") {
                event.preventDefault();
                const pos = (lineContent[cursorPos - 3] === "R") ? ' {\n\t\n}' : '';
                const word = codeMirror.findWordAt(cursor);

                codeMirror.replaceRange(`%root%:nth-child(${currentWord.substring(2)})${pos}`,word.anchor, word.head);

                if((currentWord[0] === "R")){
                    const newCursor = {
                        line: cursor.line + 1,
                        ch: cursorPos,
                    };
                    
                    codeMirror.setCursor(newCursor);
                }
                
                return;
            }

            // rtf = %root%:first-of-type
            if (cursorPos > 2 && lineContent[cursorPos - 3].toLowerCase() === 'r' && lineContent[cursorPos - 2] === 't' && lineContent[cursorPos - 1] === 'f') {
                event.preventDefault();
                const pos = (lineContent[cursorPos - 3] === "R") ? ' {\n\t\n}' : '';

                codeMirror.replaceRange(`%root%:first-of-type${pos}`, { line: cursor.line, ch: cursorPos - 3 }, cursor);

                if((lineContent[cursorPos - 3] === "R")){
                    const newCursor = {
                        line: cursor.line + 1,
                        ch: cursorPos,
                    };
                    
                    codeMirror.setCursor(newCursor);
                }
                
                return;
            }

            // rtl = %root%:last-of-type
            if (cursorPos > 2 && lineContent[cursorPos - 3].toLowerCase() === 'r' && lineContent[cursorPos - 2] === 't' && lineContent[cursorPos - 1] === 'l') {
                event.preventDefault();
                const pos = (lineContent[cursorPos - 3] === "R") ? ' {\n\t\n}' : '';

                codeMirror.replaceRange(`%root%:last-of-type${pos}`, { line: cursor.line, ch: cursorPos - 3 }, cursor);

                if((lineContent[cursorPos - 3] === "R")){
                    const newCursor = {
                        line: cursor.line + 1,
                        ch: cursorPos,
                    };
                    
                    codeMirror.setCursor(newCursor);
                }
                
                return;
            }

            //rt1 = %root%:nth-of-type(1)
            if (currentWord.length > 2 && currentWord[0].toLowerCase() === "r" && currentWord[1].toLowerCase() === "t") {
                event.preventDefault();
                const pos = (currentWord[0] === "R") ? ' {\n\t\n}' : '';
                const word = codeMirror.findWordAt(cursor);

                codeMirror.replaceRange(`%root%:nth-of-type(${currentWord.substring(2)})${pos}`,word.anchor, word.head);

                if((currentWord[0] === "R")){
                    const newCursor = {
                        line: cursor.line + 1,
                        ch: cursorPos,
                    };
                    
                    codeMirror.setCursor(newCursor);
                }
                
                return;
            }

            //@media queuries
            if (currentWord.length > 1 && currentWord[0].toLowerCase() === "q" && currentWord[1].toLowerCase() === "c") {
                event.preventDefault();
                const mq = (ADMINBRXC.vueGlobalProp.$_isMobileFirst._value) ? 'min' : 'max';
                const word = codeMirror.findWordAt(cursor);
                const content = (currentWord[0] === "Q") ? '\n\t%root% {\n\t\t\n\t}\n' : '\n\t\n';
                const pos = (currentWord[0] === "Q") ? 2 : 1;

                codeMirror.replaceRange(`@media screen and (${mq}-width: ${ADMINBRXC.vueState.previewWidth}px) {${content}}`,word.anchor, word.head);

                const newCursor = {
                    line: cursor.line + pos,
                    ch: cursorPos,
                };
                
                codeMirror.setCursor(newCursor);
                return;

            } else if(currentWord.length > 1 && currentWord[0].toLowerCase() === "q"){
                event.preventDefault();
                const mq = (ADMINBRXC.vueGlobalProp.$_isMobileFirst._value) ? 'min' : 'max';
                const word = codeMirror.findWordAt(cursor);
                const content = (currentWord[0] === "Q") ? '\n\t%root% {\n\t\t\n\t}\n' : '\n\t\n';
                const pos = (currentWord[0] === "Q") ? 2 : 1;

                codeMirror.replaceRange(`@media screen and (${mq}-width: ${currentWord.substring(1)}) {${content}}`,word.anchor, word.head);

                const newCursor = {
                    line: cursor.line + pos,
                    ch: cursorPos,
                };
                
                codeMirror.setCursor(newCursor);
                return;
            }

            // Recipes
            const start = lineContent.slice(0, cursorPos).search(/[@\w-]+$/);
            const forwardSlice = lineContent.slice(cursorPos);
            const end = cursorPos + (forwardSlice.match(/^[\w-]+/) ? forwardSlice.match(/^[\w-]+/)[0].length : 0);
            currentWord = lineContent.slice(start, end);

            if(currentWord.length > 1 && currentWord[0] === "@"){
                event.preventDefault();
                const key = currentWord.substring(1);
                const obj = brxcAdvancedCSSDefault.find(el => el && el.typeLabel === "recipe" && el.label === key && el.contentCss && el.contentCss !== "");
                if(obj){
                    // Set value
                    let replacement = obj.contentCss;
                    codeMirror.replaceRange(replacement, { line: cursor.line, ch: start }, { line: cursor.line, ch: end });
                    codeMirror.setValue(css_beautify(codeMirror.getValue(), { indent_size: 2 }))

                    // Set cursor
                    const replacementLines = replacement.split('\n');
                    const lastLine = replacementLines.length - 1;
                    const lastCharPos = codeMirror.getLine(cursor.line + lastLine).length;
                    codeMirror.setCursor({ line: cursor.line + lastLine, ch: lastCharPos });
                    codeMirror.focus();
                }
                
            }
        },
        saveChanges: function(cat, modifiedClassId = false){
            if(Array.isArray(ADMINBRXC.vueState.unsavedChanges) && !ADMINBRXC.vueState.unsavedChanges.includes(cat)) {
                ADMINBRXC.vueState.unsavedChanges.push(cat);
            }

            // Modified Class Id
            if(modifiedClassId){
                if(!ADMINBRXC.vueState.globalChanges.modified.includes(modifiedClassId)) {
                    ADMINBRXC.vueState.globalChanges.modified.push(modifiedClassId);
                }
            }
        },
        createTarget: function (target){
            const bpSettings = Array.from(ADMINBRXC.vueState.breakpoints).find(el => el && el.key === ADMINBRXC.vueState.breakpointActive);
            if(bpSettings.key !== "desktop"){
                target += `:${bpSettings.key}`;
            }
            return target;
        },
        createTargetWithPseudo: function (target){
            const bpSettings = Array.from(ADMINBRXC.vueState.breakpoints).find(el => el && el.key === ADMINBRXC.vueState.breakpointActive);
            if(bpSettings.key !== "desktop"){
                target += `:${bpSettings.key}`;
            }
            if(ADMINBRXC.vueState.pseudoClassActive){
                target += ADMINBRXC.vueState.pseudoClassActive;
            }
            return target;
        },
        checkHigherBreakpoint: function(target, type){
            const currentBp = Array.from(ADMINBRXC.vueState.breakpoints).find(el => el && el.key === ADMINBRXC.vueState.breakpointActive);
            let indexBp = ADMINBRXC.vueState.breakpoints.indexOf(currentBp);
            let obj;
            type === "element" ? obj = ADMINBRXC.vueState.activeElement : obj = ADMINBRXC.vueState.activeClass;
            if (!obj || !obj.hasOwnProperty('settings')) return false;

            function checkBp(index){
                if(index - 1 === -1) return false;
                const key = ADMINBRXC.vueState.breakpoints[index - 1].key;
                const finalTarget = key === "desktop" ? target : `${target}:${key}`;
                if(obj.settings.hasOwnProperty(finalTarget)) {
                    return finalTarget;
                } else {
                    return checkBp(index - 1);
                }
            }
            return checkBp(parseInt(indexBp));

        },
        setActiveItem: function(selectors, event){
            const li = document.querySelectorAll(selectors);
            if(!li || li.length < 1) return; 
            const isActive = event.target.classList.contains('active');
            li.forEach(el => {
                el.classList.remove('active');
            })
            if(!isActive) {
                event.target.classList.add('active')
                return true;
            } else {
                ADMINBRXC.structureHelperStates.activeFilter = false;
                ADMINBRXC.structureHelperStates.filterArr = [];
                ADMINBRXC.setStructureHelper();
                return false;
            }
        },
        isThemeVariableActive: function(){
            if(ADMINBRXC.helpers.isCSSVariablesTabActive() && Array.isArray(ADMINBRXC.globalSettings.generalCats.cssVariables) && ADMINBRXC.globalSettings.generalCats.cssVariables.includes('theme-variables')) return true;
            return false;
        },
        themeHasVariables: function(){
            if(ADMINBRXC.vueState.themeStyleSettings && ADMINBRXC.vueState.themeStyleSettings.hasOwnProperty('general') && ADMINBRXC.vueState.themeStyleSettings.general.hasOwnProperty('_cssVariables')) return true;
            return false;
        },
        createThemeVariable: function(){
            if(!ADMINBRXC.vueState.themeStyleSettings.hasOwnProperty('general')) ADMINBRXC.vueState.themeStyleSettings.general = {};
            if(!ADMINBRXC.vueState.themeStyleSettings.general.hasOwnProperty('_cssVariables')) ADMINBRXC.vueState.themeStyleSettings.general._cssVariables = [];
        },
        getComponentClasses: function(tempClasses = [], id){
            const obj = ADMINBRXC.helpers.getElementObject(id);
            if(obj.settings.hasOwnProperty('_cssGlobalClasses') && obj.settings._cssGlobalClasses.length > 0){
                obj.settings._cssGlobalClasses.forEach(el => {
                    if(!tempClasses.includes(el)) tempClasses.push(el);
                })
            }
            if(obj.hasOwnProperty('children') && Array.isArray(obj.children) && obj.children.length > 0){
                obj.children.forEach(el =>{
                    ADMINBRXC.helpers.getComponentClasses(tempClasses, el);
                })
            }

            return JSON.parse(JSON.stringify(tempClasses));
        },
        getComponentElements: function(content = [], id){
            const obj = ADMINBRXC.helpers.getElementObject(id);
            content.push(obj);
            if(obj.hasOwnProperty('children') && Array.isArray(obj.children) && obj.children.length > 0){
                obj.children.forEach(el =>{
                    ADMINBRXC.helpers.getComponentElements(content, el);
                })
            }

            return content;
        },
        hasGlobalClass: function(id){
            const el = ADMINBRXC.helpers.getElementObject(id);
            return el && el.settings.hasOwnProperty('_cssGlobalClasses') && el.settings._cssGlobalClasses.length > 0 && el.settings._cssGlobalClasses.some(id => ADMINBRXC.vueGlobalProp.$_getGlobalClass(id));
        },
        hasUnlockedGlobalClass: function(id){
            const el = ADMINBRXC.helpers.getElementObject(id);
            return el && el.settings.hasOwnProperty('_cssGlobalClasses') && el.settings._cssGlobalClasses.length > 0 && el.settings._cssGlobalClasses.some(id => {
                const obj = ADMINBRXC.vueGlobalProp.$_getGlobalClass(id);
                return obj && !ADMINBRXC.vueGlobalProp.$_isLocked(obj.id)
            });
        },
        removeTrailingNewlines: function(String) {
            const pattern = /\n+$/;
            return String.replace(pattern, '');
        },
        keyMatchBreakpoint: function(key, bpKey){
            if(bpKey === "desktop"){
                let found = false;
                ADMINBRXC.vueState.breakpoints.forEach(el => {
                    if(el.key !== "desktop" && key.indexOf(`:${el.key}`) > -1) found = true;
                })

                if(found){
                    return false;
                } else {
                    return true;
                }
            } else {
                if(key.indexOf(`:${bpKey}`) > -1) return true;
            }
            
            return false;
        },

        keyMatchPseudo: function(key, pseudo){
            if(pseudo === ""){
                let found = false;
                ADMINBRXC.vueState.pseudoClasses.forEach(el => {
                    if(el !== "" && key.indexOf(`${el}`) > -1) found = true;
                })

                if(found){
                    return false;
                } else {
                    return true;
                }
            } else {
                if(key.indexOf(`${pseudo}`) > -1) return true;
            }
            
            return false;
        },
        getClassKeysFromGlobalSettings: function(classesIds) {
            let classesKeys = [];
            
            classesIds.forEach((id) => {
                const globalClass = ADMINBRXC.vueGlobalProp.$_getGlobalClass(id);
    
                if (typeof globalClass !== "undefined" && globalClass.hasOwnProperty("settings")) {
                    const settings = globalClass.settings;
    
                    for (const key in settings) {
                        if (key.startsWith("_") && settings[key] !== "") classesKeys.push(key);
                    }
                }
            });
            
            return [...new Set(classesKeys)];
        },
        easeInQuad: function(x){
            return x * x;
        },
        rgbStringToArray: function(rgbString){
            const rgbValues = rgbString.match(/\d+/g);
            return rgbValues.map(Number);
        },
        getElementTag: function(obj){
            let tag;
            if(!bricksData.elements[obj.name]) return false;
            if(typeof obj !== "undefined" && obj.name === "button" && obj.settings.hasOwnProperty('link') && typeof obj.settings.link === "object"){
                tag = "a";
            } else if (typeof obj !== "undefined" && obj.name === "image" && obj.hasOwnProperty('settings') && !obj.settings.hasOwnProperty('tag') ) {
                tag = "img";
            } else if (typeof obj !== "undefined" && obj.name === "image" && obj.hasOwnProperty('settings') && obj.settings.hasOwnProperty('tag') ) {
                tag = `${obj.settings.tag} > img`;
            } else if (typeof obj !== "undefined" && obj.name === "code" && obj.hasOwnProperty('settings') && obj.settings.hasOwnProperty('noRoot') && obj.settings.noRoot === true) {
                tag = "none"
            } else if (typeof obj !== "undefined" && obj.hasOwnProperty('settings') && obj.settings.hasOwnProperty('tag') && obj.settings.tag === "custom" && obj.settings.hasOwnProperty('customTag')) {
                tag = obj.settings.customTag
            } else if (typeof obj !== "undefined" && obj.hasOwnProperty('settings') && obj.settings.hasOwnProperty('tag')) {
                tag = obj.settings.tag
            } else {
                if(!bricksData.elements[obj.name].hasOwnProperty('tag')) return;
                tag = bricksData.elements[obj.name].tag
            }
            return tag;
        },
        getClassCategoryNameById: function(id){
            const obj = Array.from(ADMINBRXC.vueState.globalClassesCategories).find(el => el && el.id === id);
            if(!obj) return false;
            return obj.name;
        },
        getClassCategoryObjById: function(id){
            const obj = Array.from(ADMINBRXC.vueState.globalClassesCategories).find(el => el && el.id === id);
            if(!obj) return false;
            return obj;
        },
        getClassCategoryIdByName: function(name){
            const obj = Array.from(ADMINBRXC.vueState.globalClassesCategories).find(el => el && el.name.toLowerCase() === name.toLowerCase());
            if(!obj) return false;
            return obj.id;
        },
        getClassCategoryObjByName: function(name){
            const obj = Array.from(ADMINBRXC.vueState.globalClassesCategories).find(el => el && el.name.toLowerCase() === name.toLowerCase());
            if(!obj) return false;
            return obj;
        },
        getQueryCategoryNameById: function(id){
            const obj = Array.from(ADMINBRXC.globalSettings.generalCats.queryManagerCats).find(el => el && el.id === id);
            if(!obj) return false;
            return obj.name;
        },
        getQueryCategoryObjById: function(id){
            const obj = Array.from(ADMINBRXC.globalSettings.generalCats.queryManagerCats).find(el => el && el.id === id);
            if(!obj) return false;
            return obj;
        },
        getQueryCategoryIdByName: function(name){
            const obj = Array.from(ADMINBRXC.globalSettings.generalCats.queryManagerCats).find(el => el && el.name.toLowerCase() === name.toLowerCase());
            if(!obj) return false;
            return obj.id;
        },
        getQueryCategoryObjByName: function(name){
            const obj = Array.from(ADMINBRXC.globalSettings.generalCats.queryManagerCats).find(el => el && el.name.toLowerCase() === name.toLowerCase());
            if(!obj) return false;
            return obj;
        },
        getAdvancedCSSObjByName: function(label){
            const obj = Object.entries(brxcAdvancedCSSDefault).find(([key,o]) => o && o.label === label);
            if(!obj) return false;
            return obj;
        },
        convertToPhpArrowFunction: function(jsonString) {
            const jsonObject = JSON.parse(jsonString);
            const indentedPhpString = JSON.stringify(jsonObject, null, 4)
                .replace(/(?<!")\{/g, '[')
                .replace(/\}(?!\")/g, ']')
                .replace(/"([^"]+)":/g, '"$1" =>');

            return `return ${indentedPhpString};`;
        },
        // convertToPhpArrowFunction: function(jsonString) {
        //     const jsonObject = JSON.parse(jsonString);
        //     const indentedPhpString = JSON.stringify(jsonObject, null, 4)
        //         .replace(/(\{)/g, '[')  // Replace all `{` with `[`
        //         .replace(/(\})/g, ']')  // Replace all `}` with `]`
        //         .replace(/"([^"]+)":/g, '"$1" =>'); // Convert JSON keys to PHP associative array keys
        
        //     return `return ${indentedPhpString};`;
        // },
        isValidUrl: function(urlString){
            var urlPattern = new RegExp('^(https?:\\/\\/)?' + // validate protocol (http or https)
                '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // validate domain name
                '((\\d{1,3}\\.){3}\\d{1,3}))' + // validate OR ip (v4) address
                '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // validate port and path
                '(\\?[;&a-z\\d%_.~+=-]*)?' + // validate query string
                '(\\#[-a-z\\d_]*)?$', 'i'); // validate fragment locator
            return !!urlPattern.test(urlString);
        },
        getGlobalVariableNameById: function(id){
            const arr = ADMINBRXC.helpers.isThemeVariableActive() && ADMINBRXC.helpers.themeHasVariables() ? ADMINBRXC.vueState.globalVariables.concat(ADMINBRXC.vueState.themeStyleSettings.general._cssVariables) : ADMINBRXC.vueState.globalVariables;
            const obj = Array.from(arr).find(el => el && el.id === id);
            if(!obj || !obj.hasOwnProperty('name')) return false;
            return obj.name;
        },
        getGlobalVariableIdByName: function(name){
            const arr = ADMINBRXC.helpers.isThemeVariableActive() && ADMINBRXC.helpers.themeHasVariables() ? ADMINBRXC.vueState.globalVariables.concat(ADMINBRXC.vueState.themeStyleSettings.general._cssVariables) : ADMINBRXC.vueState.globalVariables;
            const obj = Array.from(arr).find(el => el && el.name === name);
            if(!obj || !obj.hasOwnProperty('id')) return false;
            return obj.id;
        },
        getGlobalVariableObjById: function(id){
            const arr = ADMINBRXC.helpers.isThemeVariableActive() && ADMINBRXC.helpers.themeHasVariables() ? ADMINBRXC.vueState.globalVariables.concat(ADMINBRXC.vueState.themeStyleSettings.general._cssVariables) : ADMINBRXC.vueState.globalVariables;
            const obj = Array.from(arr).find(el => el && el.id === id);
            if(!obj) return false;
            return obj;
        },
        getGlobalVariableCategoryNameById: function(id, arr = ADMINBRXC.vueState.globalVariablesCategories){
            const obj = Array.from(arr).find(el => el && el.id === id);
            if(!obj || !obj.hasOwnProperty('name')) return false;
            return obj.name;
        },
        getGlobalVariableCategoryIdByName: function(name){
            const obj = Array.from(ADMINBRXC.vueState.globalVariablesCategories).find(el => el && el.name.toLowerCase() === name.toLowerCase());
            if(!obj || !obj.hasOwnProperty('id')) return false;
            return obj.id;
        },
        getGlobalVariableCategoryObjById: function(id){
            const obj = Array.from(ADMINBRXC.vueState.globalVariablesCategories).find(el => el && el.id === id);
            if(!obj) return false;
            return obj;
        },
        getGlobalVariableCategoryObjByName: function(name){
            const obj = Array.from(ADMINBRXC.vueState.globalVariablesCategories).find(el => el && el.name.toLowerCase() === name.toLowerCase());
            if(!obj) return false;
            return obj;
        },
        getRootFontSize: function(){
            return parseInt(window.getComputedStyle(FRAMEBRXC.content.querySelector('html')).getPropertyValue('font-size').replace('px',''));
        },
        getCustomComponentObjById: function(id){
            const obj = Array.from(brxcNestedElementsDefault.concat(ADMINBRXC.globalSettings.customComponentsElements)).find(el => el && el.id === id);
            if(!obj) return false;
            return obj;
        },
        getCustomComponentCatObjById: function(id){
            const obj = Array.from(ADMINBRXC.customComponentStates.defaultCategory.concat(ADMINBRXC.globalSettings.customComponentsCategories)).find(el => el && el.id === id);
            if(!obj) return false;
            return obj;
        },
        getCustomComponentCatObjByName: function(name){
            const obj = Array.from(ADMINBRXC.customComponentStates.defaultCategory.concat(ADMINBRXC.globalSettings.customComponentsCategories)).find(el => el && el.label.toLowerCase() === name.toLowerCase());
            if(!obj) return false;
            return obj;
        },
        isVariableUncategorized: function(varObj){
            if(!varObj || !varObj.hasOwnProperty('category')) return true;
            const catObj = Array.from(ADMINBRXC.vueState.globalVariablesCategories).find(el => el && el.id === varObj.category);
            if(!catObj) return true;
            return false;

        },
        isClassUncategorized: function(varObj){
            if(!varObj || !varObj.hasOwnProperty('category')) return true;
            const catObj = Array.from(ADMINBRXC.vueState.globalClassesCategories).find(el => el && el.id === varObj.category);
            if(!catObj) return true;
            return false;

        },
        isCustomComponentUncategorized: function(varObj){
            if(!varObj || !varObj.hasOwnProperty('category')) return true;
            const catObj = Array.from(ADMINBRXC.customComponentStates.defaultCategory.concat(ADMINBRXC.globalSettings.customComponentsCategories)).find(el => el && el.id === varObj.category);
            if(!catObj) return true;
            return false;

        },
        moveArr: function (arr, from, to, on = 1) {
            return arr.splice(to, 0, ...arr.splice(from, on)), arr;
        },
        elementHasStyle: function(obj) {
            return obj && Object.keys(obj).some(key => ADMINBRXC.helpers.isCSSControlKey(key.split(':')[0]));
        },
        elementHasClass: function(obj) {
            if (!obj) return false;
            if (obj._cssClasses && obj._cssClasses.length > 0) return true;
            if (obj._cssGlobalClasses && obj._cssGlobalClasses.length > 0) {
                return obj._cssGlobalClasses.some(cls => ADMINBRXC.vueGlobalProp.$_getGlobalClass(cls));
            }
            return false;
        },
        createTagBtn: function(sibling, tag){
            const wrapper = document.createElement('div');;
            wrapper.setAttribute("class", "brxc-tag-btn-wrapper");
            const btn = document.createElement('button')
            btn.setAttribute('class', 'brxc-tag-btn')
            btn.textContent = tag
            wrapper.appendChild(btn);
            sibling.after(wrapper);
        },
        convertCSSToVariables: function (cssString, variableSelector = ':root') {
            const variableMap = new Map();
            const propertyCounters = new Map();

            function createVariableName(property, value) {
                let baseName = property.replace(/[^a-zA-Z0-9-]/g, '');
                let variableName = `--${baseName}`;
                
                const key = `${property}:${value.trim()}`;
                
                if (variableMap.has(key)) {
                return variableMap.get(key);
                }

                if (propertyCounters.has(baseName)) {
                const counter = propertyCounters.get(baseName) + 1;
                propertyCounters.set(baseName, counter);
                variableName = `--${baseName}-${counter}`;
                } else {
                propertyCounters.set(baseName, 1);
                }

                variableMap.set(key, variableName);
                return variableName;
            }

            const blockRegex = /([^{]+)\{([^}]+)\}/g;
            const propertyRegex = /([a-zA-Z-]+)\s*:\s*([^;\n]+)/g;

            const convertedBlocks = [];
            const variables = new Map();

            let match;
            while ((match = blockRegex.exec(cssString)) !== null) {
                const [fullMatch, selector, block] = match;
                const convertedBlock = block.replace(propertyRegex, (propMatch, property, value) => {
                
                // Ignore existing variables & scoped variables
                if (property.startsWith('--') || value.trim().startsWith('var(--')) {
                    return propMatch;
                }

                const variableName = createVariableName(property, value);
                variables.set(variableName, value.trim());
                return `${property}: var(${variableName})`;
                });

                convertedBlocks.push(`${selector.trim()} {${convertedBlock}}`);
            }

            const sortedVariables = Array.from(variables.entries()).sort((a,b) => a[0].localeCompare(b[0]));
            const variableDeclarations = sortedVariables
                .map(([name, value]) => `  ${name}: ${value};`)
                .join('\n');

            const variableBlock = `${variableSelector} {\n${variableDeclarations}\n}`;

            return `${variableBlock}\n\n${convertedBlocks.join('\n\n')}`;
        },
        resetStyles: function(obj){
            // Remove styles on ID
            for (const [key, value] of Object.entries(obj.settings)){
                if (ADMINBRXC.helpers.isCSSControlKey(key)) delete obj.settings[key];
            }
        },
        isValidFileUrl(url){
            try {
                const parsedUrl = new URL(url);
                return parsedUrl;
            } catch (error) {
                return false;
            }
        },
        getFilenameURLFromUrl: function(url){
            const parsedUrl = ADMINBRXC.helpers.isValidFileUrl(url);
            if(!parsedUrl){
                return ADMINBRXC.globalSettings.placeholderImg;
            } else {
                return url;
            }
        },
        getFilenameFromUrl: function(url) {
            const parsedUrl = ADMINBRXC.helpers.isValidFileUrl(url);
            if(!parsedUrl){
                return 'placeholder-image-png';
            } else {
                const path = parsedUrl.pathname;
                const filename = path.split('/').pop();
                
                return filename;
            }
        },
        elementTagbyHTMLTag: function(parsedElement, tag) {
            if(tag.startsWith("b-")){
                return tag.replace("b-","");
            }
            // Define the complete mapping that includes all possible elements
            const completeMapping = {
                'section': ['section'],
                'div': ['div', 'a', 'article', 'nav', 'ol', 'ul', 'li', 'aside'],
                'text-basic': ['p', 'span', 'figcaption', 'address'],
                'heading': ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
                'image': ['img', 'picture'],
                'video': ['video'],
                'button': ['button'],
                'code': ['style', 'script']
            };
        
            // The specific keys for elements with text content and no children
            const textOnlyKeys = ['text-basic', 'heading', 'button', 'code'];
        
            // Check if the element has text content and no children
            if (parsedElement.textContent && typeof parsedElement.textContent === "string" && parsedElement.textContent.length > 0 && parsedElement.children.length === 0) {
                for (const key of textOnlyKeys) {
                    if (completeMapping[key].includes(tag)) {
                        return key; // Return the corresponding key
                    }
                }
                return 'text-basic';
            }
        
            // If the element has children or no text, check the full mapping
            for (const key in completeMapping) {
                if (completeMapping[key].includes(tag)) {
                    return key;
                }
            }
        
            return 'div';
        },
        setIdFromParsedHTML: function (parsedElement, obj, codepenStates){
            const id = parsedElement.id;

            // Excluded
            if (codepenStates.excludeIds !== '' && codepenStates.excludeIds.replaceAll(' ', '').split(',').some(item => id.trim().toLowerCase().includes(item.trim().toLowerCase()))) {
                return obj;
            }          
            if(!id && obj.settings.hasOwnProperty('_cssId')){
                delete obj.settings._cssId;
            } else if (id && id !== `brxe-${obj.id}`){
                obj.settings._cssId = id;
            }
            return obj;
        },
        setClassesFromParsedHTML: function(parsedElement, obj, codepenStates){
            const classes = parsedElement.className;
            if(classes && typeof classes === "string"){
                const classesArr = classes.split(' ');
                const globalClasses = [];
                const cssClasses = [];
                classesArr.forEach(tempCls => {
                    // Excluded
                    if (codepenStates.excludeClasses !== '' && codepenStates.excludeClasses.replaceAll(' ', '').split(',').some(item => tempCls.trim().toLowerCase().includes(item.trim().toLowerCase()))) {
                        return;
                    }
                    
                    const existingGlobalClass = ADMINBRXC.vueState.globalClasses.find(el => el && el.name === tempCls);
                    if(existingGlobalClass) {
                        globalClasses.push(existingGlobalClass.id);
                    } else {
                        if(codepenStates.createGlobalClasses){
                            const newId = ADMINBRXC.vueGlobalProp.$_generateId();
                            ADMINBRXC.vueState.globalClasses.push({
                                id: newId,
                                name: tempCls,
                                settings: {},
                            })
                            globalClasses.push(newId);
                        } else {
                            cssClasses.push(tempCls)
                        }
                    }
                })
                if(globalClasses.length > 0){
                    obj.settings._cssGlobalClasses = globalClasses;
                } else {
                    delete obj.settings._cssGlobalClasses;
                }
                if(cssClasses.length > 0){
                    obj.settings._cssClasses = cssClasses.join(' ');
                } else {
                    delete obj.settings._cssClasses;
                }
            } else {
                delete obj.settings._cssGlobalClasses;
                delete obj.settings._cssClasses;
            }

            return obj;
        },
        setTextFromParsedHTML: function(parsedElement, obj, objConfig){
            const innerText = parsedElement.innerHTML.trim();
            const tagName = parsedElement.tagName.toLowerCase();

            // Exceptions
            if(innerText && tagName === "style"){
                obj.settings.cssCode = innerText;
                obj.settings.noRoot = true;
                return obj;
            }
            if(innerText && tagName === "script"){
                obj.settings.javascriptCode = innerText;
                obj.settings.noRoot = true;
                return obj;
            }

            //Global
            if(!innerText && objConfig.controls.hasOwnProperty('text')){
                delete obj.settings.text;
            } else if(objConfig.controls.hasOwnProperty('text') && innerText && typeof innerText === "string" && innerText.length > 0){
                obj.settings.text = innerText;
            }

            return obj
        },
        setAttributesFromParsedHTML: function(parsedElement, obj, codepenStates) {
            const attributes = [];
        
            for (const attr of parsedElement.attributes) {
                const attrName = attr.name.toLowerCase();
                const attrValue = attr.value.trim();
        
                // Exclude unwanted attributes
                if (attrName === "id" || attrName === "class" || 
                    codepenStates.excludeAttributes.replaceAll(' ', '').split(',').some(item => item.trim().toLowerCase() === attrName)) {
                    continue;
                }

                // Handle src (image)
                if (attrName === "src") {
                    obj.settings.image = {
                        url: ADMINBRXC.helpers.getFilenameURLFromUrl(attrValue),
                        external: true,
                        filename: ADMINBRXC.helpers.getFilenameFromUrl(attrValue)
                    };
                }

                // Bricks Label
                else if(attrName === "data-bricks-label"){
                    obj.label = ADMINBRXC.helpers.capitalizeString(attrValue);
                }
        
                // Handle href (link)
                else if (attrName === "href") {
                    obj.settings.link = "url";
                    obj.settings.url = obj.settings.url || {};
                    obj.settings.url.url = attrValue;
                    obj.settings.url.type = "external";
                }
        
                // Handle rel
                else if (attrName === "rel") {
                    obj.settings.url = obj.settings.url || {};
                    obj.settings.url.rel = attrValue;
                }
        
                // Handle title
                else if (attrName === "title") {
                    obj.settings.url = obj.settings.url || {};
                    obj.settings.url.title = attrValue;
                }
        
                // Handle aria-label
                else if (attrName === "aria-label") {
                    obj.settings.url = obj.settings.url || {};
                    obj.settings.url.ariaLabel = attrValue;
                }
        
                // Handle target (newTab)
                else if (attrName === "target" && attrValue === "_blank") {
                    obj.settings.url = obj.settings.url || {};
                    obj.settings.url.newTab = true;
                }
        
                // Handle alt (image alt text)
                else if (attrName === "alt") {
                    obj.settings.altText = attrValue;
                }
        
                // Handle loading
                else if (attrName === "loading") {
                    obj.settings.loading = attrValue;
                }
        
                // Handle other attributes
                else {
                    const attrObj = {
                        id: ADMINBRXC.vueGlobalProp.$_generateId(),
                        name: attrName,
                        value: attrValue
                    };
                    attributes.push(attrObj);
                }
            }
        
            // Set _attributes if any custom attributes were found, or clean it if empty
            if (attributes.length > 0) {
                obj.settings._attributes = attributes;
            } else if (obj.settings.hasOwnProperty('_attributes')) {
                delete obj.settings._attributes;
            }
        
            return obj;
        },
        wrapTextNodesInSpan: function (node){
            node.childNodes.forEach(child => {
                if (child.nodeType === Node.TEXT_NODE && child.textContent.trim()) {
                  // Wrap text node in a <span>
                  const span = document.createElement('span');
                  span.textContent = child.textContent.trim();
                  node.replaceChild(span, child);
                }
            });
        },
        parseHtmlStringToObjectArray: function(rootId, parentId, cmValues, codepenStates){
            // Parse the HTML string into a DOM structure
            const parser = new DOMParser();
            const doc = parser.parseFromString(cmValues.html, 'text/html');
            
            // Wrap text nodes without tags into span tags
            doc.body.querySelectorAll('*').forEach(el => {
                const childNodes = Array.from(el.childNodes);
                const hasText = childNodes.some(n => n.nodeType === Node.TEXT_NODE && n.textContent.trim());
                const hasElements = childNodes.some(n => n.nodeType === Node.ELEMENT_NODE);
                
                // Only wrap text nodes if this element contains both text and element nodes
                if (hasText && hasElements) {
                    ADMINBRXC.helpers.wrapTextNodesInSpan(el);
                }
            })

            
            // This will store the final array of objects
            const elementsArray = [];
            const rootChildren = [];  // To store top-level child IDs
        
            function setDefaultTag(elementObj, tag, hasCustomTag){
                if(hasCustomTag){
                    elementObj.settings.tag = 'custom';
                    elementObj.settings.customTag = tag;
                } else {
                    elementObj.settings.tag = tag;
                }
            }
        
            // Function to recursively walk through the DOM and generate objects
            function traverseElement(element, parentId = rootId) {
                // Generate a unique ID for the current element
                const id = ADMINBRXC.vueGlobalProp.$_generateId();
                const tagName = element.tagName.toLowerCase();
                const bricksName = ADMINBRXC.helpers.elementTagbyHTMLTag(element, tagName);
                const elementConfig = ADMINBRXC.vueGlobalProp.$_getElementConfig(bricksName);
        
                // Create the object for the current element
                let elementObj = {
                    id: id,
                    name: bricksName,
                    parent: parentId,
                    children: [],
                    settings: {},
                };

                const isNestable = ADMINBRXC.vueGlobalProp.$_isNestable(elementObj);
        
                if(elementConfig.tag !== tagName){
                    if(tagName === "img" || tagName.startsWith('b-')){
                        // silence
                    } else{
                        let isOption = false;
                        if(elementConfig.controls.hasOwnProperty('tag') && !elementConfig.controls.tag.hasOwnProperty('customTag')){
                            // can't change the tag
                        }
                        if(elementConfig.controls.hasOwnProperty('tag') && elementConfig.controls.tag.hasOwnProperty('options')){
                            for(const key in elementConfig.controls.tag.options){
                                if(key == tagName) isOption = true;
                            }
                        }
        
                        if(isOption){
                            elementObj.settings.tag = tagName;
                        } else {
                            setDefaultTag(elementObj, tagName, elementConfig.controls.hasOwnProperty('customTag'));
                        }
                    }
                }
            
        
                // id
                if(codepenStates.includesIds) elementObj = ADMINBRXC.helpers.setIdFromParsedHTML(element, elementObj, codepenStates);
        
                // Classes
                if(codepenStates.includesClasses) elementObj = ADMINBRXC.helpers.setClassesFromParsedHTML(element, elementObj, codepenStates);
        
                // Text
                if(codepenStates.includesTexts) elementObj = ADMINBRXC.helpers.setTextFromParsedHTML(element, elementObj, elementConfig);
        
                // Attributes
                if(codepenStates.includesAttributes) elementObj = ADMINBRXC.helpers.setAttributesFromParsedHTML(element, elementObj, codepenStates);
                
                // If the element has children, process them recursively
                const children = [...element.children];
                if (children.length > 0 && isNestable) {
                    children.forEach((child) => {
                        const childObj = traverseElement(child, id);
                        elementObj.children.push(childObj.id); // Add child id to parent's "children" array
                    });
                }
               
        
                // Add the current element object to the final array
                elementsArray.push(elementObj);
                
                return elementObj; // Return the current object
            }
        
            // Traverse the top-level elements in the parsed document body
            [...doc.body.children].forEach((element) => {
                const topLevelElement = traverseElement(element);
                rootChildren.push(topLevelElement.id); // Store top-level children IDs
            });

            if(cmValues.css || cmValues.js){
                const codeId = ADMINBRXC.vueGlobalProp.$_generateId();
                const codeObj = {
                    id: codeId,
                    name: 'code',
                    label: 'CSS/JS Code',
                    parent: rootId,
                    children: [], // Set the correct top-level children here
                    settings: {},
                }
                if(cmValues.css){
                    codeObj.settings.cssCode = css_beautify(cmValues.css, { indent_size: 2 });
                }
                if(cmValues.js){
                    codeObj.settings.javascriptCode = cmValues.js;
                }
                elementsArray.splice(0, 0, codeObj);
                rootChildren.splice(0, 0, codeId);
            }
            const parentObj = {
                id: rootId,
                name: 'div',
                label: 'Generated By Structure Generator',
                parent: parentId,
                children: rootChildren, // Set the correct top-level children here
                settings: {},
            }
            // Add the root element with its updated children array
            elementsArray.push(parentObj);
            return elementsArray;
        },
        commentCMCode: function(cm){
            cm.CodeMirror.toggleComment();
            var event = new Event('keyup');
            cm.CodeMirror.getInputField().dispatchEvent(event);
        },
        getCSSSelector: function(element) {
            const ignoredSelectors = ['bricks-preview', 'iframe', 'mounted'];
            const ignoredClasses = ['brxe-', 'brx-', 'bricks', 'is-active-element'];
            let currentElement = element;
            let selector = '';

            // Helper function to check if a class should be ignored
            function shouldIgnore(term, arr) {
                return arr.some(prefix => term.startsWith(prefix));
            }

            // Traverse the DOM up until body or html, or when an ID or class is found
            while (currentElement && currentElement.tagName.toLowerCase() !== 'body') {

                // Check if the element has an ID
                
                if (currentElement.classList.length > 0) {

                    // Check if the current element matches any ignored selectors
                    if ([...currentElement.classList].filter(className => shouldIgnore(className, ignoredSelectors)).length > 0) {
                        ADMINBRXC.vueGlobalProp.$_showMessage('ABORT: this element belongs to the builder only!')
                        continue;
                    }
                    // Filter out ignored classes
                    const validClasses = [...currentElement.classList].filter(className => !shouldIgnore(className, ignoredClasses));

                    // BEM
                    const hasBEMClass = validClasses.some(el => el.indexOf('__') > -1);
                    if (validClasses.length > 0 && hasBEMClass){
                            selector = `.${validClasses.find(el => el.indexOf('__') > -1)}` + selector;
                            break;
                    }

                    // If no BEM class but has valid classes, prioritize ID
                    if(validClasses.length > 0){
                        if (currentElement.id) {
                            if(bricksData.loadData.globalSettings.elementAttsAsNeeded && currentElement.id.startsWith('brxe-')){
                                const obj = ADMINBRXC.helpers.getElementObject(currentElement.id.replace('brxe-',''));
                                if(obj && ADMINBRXC.helpers.elementHasStyle(obj.settings)){
                                    selector = `#${currentElement.id}` + selector;
                                    break;
                                } 
                            } else {
                                selector = `#${currentElement.id}` + selector;
                                break
                            }
                        }

                        // If valid classes but no ID, join the classes.
                        selector = `.${validClasses.join('.')}` + selector;
                    }
                } 
                
                
                if (currentElement.id) {
                    if(bricksData.loadData.globalSettings.elementAttsAsNeeded && currentElement.id.startsWith('brxe-')){
                        const obj = ADMINBRXC.helpers.getElementObject(currentElement.id.replace('brxe-',''));
                        if(obj && ADMINBRXC.helpers.elementHasStyle(obj.settings)){
                            selector = `#${currentElement.id}` + selector;
                            break;
                        } 
                    } else {
                        selector = `#${currentElement.id}` + selector;
                        break
                    }
                } 
                
                // If no ID or class, add the tag name and nth-child
                const tagName = currentElement.tagName.toLowerCase();
                if (currentElement.parentNode) {
                    const siblings = currentElement.parentNode.children;
                    if (siblings.length > 1) {
                        const index = Array.prototype.indexOf.call(siblings, currentElement) + 1;
                        selector = ` > ${`${tagName}:nth-child(${index})`}` + selector;
                    } else {
                        selector = ` > ${tagName}` + selector;
                    }
                } else {
                    selector = ` > ${tagName}` + selector;
                }

                // Move to the parent element
                currentElement = currentElement.parentElement;
            }

            return selector;
        },
        textAreaAutoGrow: function(element, size) {
            element.style.height = size;
            element.style.height = element.scrollHeight + "px";
        },
        removeCommentedCSS: function(string){
            if (!string) return '';
            return string.replace(/\/\*[\s\S]*?\*\//g, '').replace(/^\s*[\r\n]/gm, '');
        },
        removeCharsetCSS: function(string){
            if(!string) return false;
            return string.replace(/^@charset\s+["'][^"']+["'];\s*/i, '');
        },
        childThemeCommentReadOnly: function(MyCM){
            const content = MyCM.getValue();
            const commentRegex = /\/\*[\s\S]*?\*\//;
            const match = commentRegex.exec(content);
            if(match){
                const startPos = MyCM.posFromIndex(match.index);
                const endPos = MyCM.posFromIndex(match.index + match[0].length);
                MyCM.markText(startPos, endPos, {readOnly: true, className: 'readonly-comment2'});
            }
        },
        classNametoLabel: function(clsName){
            const temp = clsName.includes('__') 
                    ? clsName.split('__')[1]  // Get the part after '__'
                    : clsName;  // Use the whole name if '__' is not present

            const result = temp
                .replaceAll('__', ' ')
                .replaceAll('_', ' ')
                .replaceAll('--', ' ')
                .replaceAll('-', ' ')
                .split(' ')
                .filter(Boolean);  // Remove empty strings from the array

            return result.map(el => el.charAt(0).toUpperCase() + el.slice(1).toLowerCase()).join(' ');
        },
        insertAfterNthParent(originalArray, newElements, targetParentPosition) {
            // Clone the original array to avoid mutations
            const array = JSON.parse(JSON.stringify(originalArray));

            if (targetParentPosition === 0) {
                // If target position is 0, insert newElements at the beginning
                array.unshift(...newElements);
                return array;
            }

            let parentCount = 0;
            let insertIndex = -1;

            // Find the position after the nth parent
            for (let i = 0; i < array.length; i++) {
                if (array[i].parent === 0) {
                    parentCount++;
                    if (parentCount === targetParentPosition) {
                        insertIndex = i + 1;
                        break;
                    }
                }
            }

            if (insertIndex !== -1) {
                array.splice(insertIndex, 0, ...newElements); // Insert at the calculated position
            } else {
                array.push(...newElements); // Append to the end if no position found
            }

            return array;
        },
        isElementOnRoot: function(parent){
            return parent === 0 || (ADMINBRXC.helpers.isComponentActive() && ADMINBRXC.helpers.isComponentRoot(parent));
        },
        getContent: function(forceStructure = false){
            if(ADMINBRXC.helpers.isComponentActive() && !forceStructure){
                return ADMINBRXC.vueState.activeComponent.elements;
            }
            const contentType = ADMINBRXC.helpers.getTemplateType();
            return ADMINBRXC.vueState[contentType];
        },
        getContentWithComponents: function(){
            const contentType = ADMINBRXC.helpers.getTemplateType();
            const mainElements = ADMINBRXC.vueState[contentType].filter(el => !el.hasOwnProperty('cid'));
            const componentElements = ADMINBRXC.vueState.components?.flatMap(el => el.elements) || [];
            return [...mainElements, ...componentElements];
        },
        getPageContentAndPageComponents: function(){
            const template = ADMINBRXC.helpers.getTemplateType();
            let fullArr = [];

            if (ADMINBRXC.vueState.hasOwnProperty('components')) {
                // Create a lookup set for better performance
                const templateCIDs = new Set(
                    ADMINBRXC.vueState[template]
                        .filter(el => el.hasOwnProperty('cid'))
                        .map(el => el.cid)
                );

                // Filter active components and associate them with their IDs
                const activeComponentsObjs = ADMINBRXC.vueState.components
                    .filter(el => templateCIDs.has(el.id))
                    .map(el => ({
                        obj: el,
                        component: el.id
                    })) || [];

                // Extract elements from active components and associate them with their parent component ID
                const activeElements = activeComponentsObjs.flatMap(el =>
                    el.obj.elements.map(el3 => ({
                        obj: el3,
                        component: el.component
                    }))
                );

                // Combine template elements, active components, and active elements
                fullArr = [
                    ...ADMINBRXC.vueState[template]
                        .filter(el => !el.hasOwnProperty('cid')) // Elements without 'cid'
                        .map(el => ({ obj: el })),
                    ...activeComponentsObjs,
                    ...activeElements
                ];

            } else {
                // If no components exist, fallback to the template array
                fullArr = ADMINBRXC.vueState[template];
            }


            return fullArr;
        },
        countCharacter: function(string, char) {
            const escapedChar = char.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
            const regex = new RegExp(escapedChar, "g");
            const matches = string.match(regex);
            return matches ? matches.length : 0;
        },
        capitalizeString: function(string){
            return string.toLowerCase().split('_').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' ');
        },
        capitalizeStrings: function(string){
            return string.toLowerCase().split(' ').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' ');
        },
        camelCaseToHumanReadable: function(key) {
            // Remove leading underscore, if present
            const cleanedKey = key.startsWith("_") ? key.slice(1) : key;
            // Insert spaces before uppercase letters and make the first letter lowercase
            return cleanedKey
                .replace(/([A-Z])/g, ' $1') // Add space before uppercase letters
                .toLowerCase(); // Capitalize the first letter
        },
        isComponentRoot: function(id){
            if(!ADMINBRXC.vueState.hasOwnProperty('components')) return false;
            const obj = ADMINBRXC.vueGlobalProp.$_getComponentById(id);
            return obj && typeof obj === "object" && obj.hasOwnProperty('id');
        },
        isElementInComponent: function(id) {
            if (!ADMINBRXC.vueState.hasOwnProperty('components')) return false;
            const allElements = ADMINBRXC.vueState.components.flatMap(component => component.elements || []);
            return allElements.some(element => element.id === id);
        },
        getComponentByElementId: function(id) {
            if (!ADMINBRXC.vueState.hasOwnProperty('components')) return false;
            return ADMINBRXC.vueState.components.find(component =>
                (component.elements || []).some(element => element.id === id)
            );
        },
        elementHasGrid: function(){
            const obj = ADMINBRXC.helpers.getFinalObject();
            const target = ADMINBRXC.helpers.createTargetWithPseudo('_display');
            if(obj.settings.hasOwnProperty(target) && obj.settings[target] === "grid") return true;

            const structureObj = ADMINBRXC.helpers.getFinalObject(true);
            if(FRAMEBRXC.vueGlobalProp.$_elementHasCssGrid(structureObj.id)) return true;
            
            return false;
        },
        getUsedPostsFromClassObj: function(globalClassObj) {
            const usedPosts = ADMINBRXC.states.classManagerUsedClasses["posts"];

            return usedPosts.filter(item => {
                const global = item.classes?.global;
                const css = item.classes?.css;

                return (Array.isArray(global) && global.includes(globalClassObj.id)) ||
                    (Array.isArray(css) && css.includes(globalClassObj.name));
            });
        },

        getUsedComponentsFromClassObj: function(globalClassObj) {
            const matchingItems = [];

            // Components
            ADMINBRXC.states.classManagerUsedClasses["components"].forEach(item => {
                let hasGlobal = false;
                if (item.classes?.global && Array.isArray(item.classes.global) && item.classes.global.includes(globalClassObj.id)) {
                    matchingItems.push(item);
                    hasGlobal = true;
                }
                if (!hasGlobal && item.classes?.css && Array.isArray(item.classes.css) && item.classes.css.includes(globalClassObj.name)) {
                    matchingItems.push(item);
                }
            });
        
            return matchingItems;
        },
        convertArrayToPHPString: function(array) {
            return `[\n` + array.map(item => {
                let properties = Object.entries(item).map(([key, value]) => {
                    return `        "${key}" => "${value}"`;
                }).join(",\n");
        
                return `    [\n${properties}\n    ]`;
            }).join(",\n") + `\n];`;
        },
        isValidCSSVar: function (str) {
            return /^var\(--[a-zA-Z0-9-_]+(,\s*[^)]+)?\)$/.test(str.trim());
        },
        selectControl: function(select, callback) {
            if (!select) return;
        
            const onSelectClick = (e) => {
                const target = e.target;
        
                if (target.dataset.value && !target.classList.contains('active')) {
                    if (callback) callback(target);
                    Array.from(select.querySelectorAll('.brxc-select-new__wrapper > *')).forEach(el => el.classList.remove('active'));
                    target.classList.add('active');
                }
    
                const isHidden = select.classList.contains('hidden');
        
                if (isHidden) {
                    select.classList.remove('hidden');
                    select.classList.add('visible');

                    setTimeout(() => {
                        const onClickOutside = (event) => {
                            if (!select.contains(event.target)) {
                                select.classList.remove('visible');
                                select.classList.add('hidden');
                                window.removeEventListener('click', onClickOutside);
                            }
                        };
                        window.addEventListener('click', onClickOutside);
                    }, 0);
        
                } else {
                    select.classList.remove('visible');
                    select.classList.add('hidden');
                }
            };
        
            select.addEventListener('click', onSelectClick);
        },
        getAllParentsMatching: function(element, selector) {
            const parents = [];
            let current = element.parentElement;
        
            while (current) {
                if (current.matches(selector)) {
                    parents.push(current);
                }
                current = current.parentElement;
            }
        
            return parents;
        },
        getHighestFrameworkVersion(arr) {
            const validVersions = arr
                .map(obj => obj.at_version || (obj.settings && obj.settings.at_version))
                .filter(Boolean);
        
            if (validVersions.length === 0) return null;
        
            return validVersions.reduce((max, current) => {
                const toParts = v => v.split('.').map(Number);
                const [a1, a2, a3] = toParts(max);
                const [b1, b2, b3] = toParts(current);
        
                if (b1 > a1 || (b1 === a1 && b2 > a2) || (b1 === a1 && b2 === a2 && b3 > a3)) {
                    return current;
                }
                return max;
            });
        },
        getChildrenColorsByParentId: function(parentId) {
            const palette = ADMINBRXC.vueState.colorPalette.find(p => p.id === ADMINBRXC.colorStates.activePalette);
            if (!palette || !palette.colors) return [];
            return palette.colors.filter(el => el.shadeParent === parentId);
        },
        stringKeyframesToObj: function(cssString) {
            const nameMatch = cssString.match(/@keyframes\s+([a-zA-Z0-9_-]+)\s*\{/);
            if (!nameMatch) return null;
          
            const name = nameMatch[1];
            const body = cssString.slice(nameMatch.index).replace(/^[^{]*\{|\}$/g, '').trim();
          
            const keyframeRegex = /(\d+%)\s*\{([^}]+)\}/g;
            const propertyRegex = /([\w-]+)\s*:\s*([^;]+);?/g;
          
            const keyframes = [];
            let match;
          
            while ((match = keyframeRegex.exec(body))) {
              const offset = match[1];
              const declarations = match[2];
          
              const properties = [];
              let propMatch;
              while ((propMatch = propertyRegex.exec(declarations))) {
                properties.push({
                  key: propMatch[1].trim(),
                  value: propMatch[2].trim()
                });
              }
          
              keyframes.push({ offset, properties });
            }
          
            return { name, keyframes };
        },
        ObjkeyframesToString: function(keyframeObj) {
            if (!keyframeObj || !keyframeObj.name || !Array.isArray(keyframeObj.keyframes)) {
              return '';
            }
          
            let css = `@keyframes ${keyframeObj.name} {\n`;
          
            keyframeObj.keyframes.forEach(frame => {
              css += `  ${frame.offset} {\n`;
              frame.properties.forEach(prop => {
                css += `    ${prop.key}: ${prop.value};\n`;
              });
              css += `  }\n`;
            });
          
            css += `}`;
            return css;
        },
        areElementsSelected: function(){
            return ADMINBRXC.vueState.selectedElements?.length > 0;
        },
        currentObjGeneratedCSS: function(){
            const type = ADMINBRXC.builderStates.isClassActive ? "globalClass" : "element";
            const elementObj = ADMINBRXC.builderStates.activeElement;
            const finalObj = ADMINBRXC.builderStates.activeObject;
            if(!elementObj) return;

            let previewCSS = ADMINBRXC.vueGlobalProp.$_generateCss(type, finalObj, [elementObj.name]).replaceAll(`.brxe-${elementObj.name}`, '');
            
            if(ADMINBRXC.helpers.isComponentActive()) previewCSS = previewCSS.replaceAll('#brxe-', '.brxe-')
            const beautifiedCSS = css_beautify(previewCSS, { indent_size: 2 });
            const finalCode = beautifiedCSS === "" ? "/* No Style applied */" : beautifiedCSS;
            return finalCode;
        },
        getElementRootIndex: function(id){
            if(!id) return false;

            let element = document.querySelector(`#bricks-structure .element[data-id="${id}"]`);
            if(!element) return false;

            const isRoot = element.dataset.parentId === "0";
            element = isRoot ? element : element.closest('.element[data-parent-id="0"]');
            const index = parseInt(element.dataset.index);
            return index;
        },
        assignNewIdsToElements: function(elArray) {
            if(!Array.isArray(elArray)) return [];

            let json = JSON.stringify(elArray);
        
            elArray.forEach(el => {
                const oldId = el.id;
                const newId = ADMINBRXC.vueGlobalProp.$_generateId();
                json = json.replaceAll(oldId, newId);
            });
        
            return JSON.parse(json);
        },
        getLocalStorage: function(){
            const storage = localStorage.getItem('brxc-builder-states');
            try {
              return JSON.parse(storage ?? []);
            } catch (e) {
                console.log(e)
              return {};
            }
        },
        setLocalStorage: function(key, value){
            const storedState = ADMINBRXC.helpers.getLocalStorage()
            storedState[key] = value;
            localStorage.setItem('brxc-builder-states', JSON.stringify(storedState));
            ADMINBRXC.helpers.saveLocalStorageToDB();
        },
        saveLocalStorageToDB: function(){
            const saveToDB = ADMINBRXC.globalSettings.saveUXSettingsToDB;
            if(!saveToDB) return;

            jQuery.ajax({
                type: 'POST',
                url: openai_ajax_req.ajax_url,
                data: {
                    action: 'save_builder_settings_ajax_function',
                    nonce: openai_ajax_req.nonce,
                    local_storage: localStorage.getItem('brxc-builder-states'),
                },
                success: function() {
                    ADMINBRXC.helpers.showSaveConfirmation({
                        success: true,
                        message: 'UX Settings Saved!'
                    });
                },
                error: function(response) {
                    ADMINBRXC.helpers.showSaveConfirmation({
                        success: false,
                        message: `UX Settings not saved - Error: "${response}"`
                    });
                },
            });
        },
        showSaveConfirmation: function(obj){
            const existing = document.querySelector('#brxcUXSettingSaved');
            if(existing) existing.remove();

            const msg = document.createElement('div');
            msg.id = 'brxcUXSettingSaved';
            msg.innerHTML = `<span>${obj.message}</span>`
            if(!obj.success) msg.setAttribute('class', 'error');
            document.body.appendChild(msg);
            setTimeout(() => {
                if(msg) msg.remove();
            }, 2000)
        },
        isBulkEdit: function(){
            return ADMINBRXC.vueState.selectedElements.length > 0;
        }
        
    },
    debounceTimer: null,
    populateCSSVariables: function () {
        const self = this;
        const iframe = document.querySelector('#bricks-builder-iframe');
        if(!iframe?.contentWindow) return;
        const x = iframe.contentWindow;
        let temp = Array.from(x.document.styleSheets)
            .filter(sheet => {
                if(!sheet) return false;
                return sheet.href === null || sheet.href.startsWith(window.location.origin);
            })
            .reduce((acc, sheet) => {
                let rules;
                try { rules = Array.from(sheet.cssRules); } catch(e) { return acc; }
                return [
                    ...acc,
                    ...rules.reduce(
                        (def, rule) =>
                            (def =
                                rule.selectorText && rule.selectorText.includes(":root")
                                    ? [
                                        ...def,
                                        ...Array.from(rule.style).filter(name =>
                                            name && name.startsWith("--") && !name.startsWith("--builder")
                                        )
                                    ]
                                    : def),
                        []
                    )
                ];
            }, []);

        // Include inline CSS variables defined on the :root element
        const rootElement = x.document.querySelector(":root");
        if (rootElement) {
            Array.from(rootElement.style).forEach(variable => {
                if (variable.startsWith("--") && !variable.startsWith("--builder")) {
                    temp.push(variable);
                }
            });
        }
        temp = [...new Set(temp)];
        self.cssVariables = Array.from(temp.sort()).map(el => `var(${el})`);
    },
    
    states:{
        // Class Manager
        classManagerType: 'global',
        classManagerFilterLocked: false,
        classManagerFilterActive: false,
        classManagerFilterStyle: false,
        classManagerSearch: '',
        classManagerActiveClass: '',
        classManagerMaxClasses: 50,
        classManagerUnusedClasses: false,
        classManagerView: 'class',
        classManagerExportCSS: false,
        classManagerOnDrag: false,
        // Bulk Actions
        classManagerActiveCategory: 'All',
        classManagerisAIopen: false,
        classManagerBulkActionType: 'Rename',
        classManagerBulkActionTargetContain: '',
        classManagerBulkActionTargetExclude: '',
        classManagerBulkActionTargetGroup: 'All',
        classManagerBulkActionLock: 'All',
        classManagerBulkActionHasStyles: 'All',
        classManagerBulkActionIsActive: 'All',
        classManagerBulkActionOld: '',
        classManagerBulkActionNew: '',
        classManagerBulkActionPrefix: '',
        classManagerBulkActionSuffix: '',
        classManagerBulkActionNewGroup: '',
        classManagerBulkAssignElements: true,
        classManagerBulkRemoveOldClass: false,
        classManagerBulkDeleteOldClass: false,
        classManagerBulkConvertLogical: true,
        classManagerUnusedTargetContain: '',
        classManagerUnusedTargetExclude: '',
        classManagerUnusedTargetGroup: 'All',
        classManagerUnusedLock: 'All',
        classManagerUnusedHasStyles: 'All',
        // Class Converter
        classConverterBasename: '',
        classConverterDelimiter: '__',
        classConverterCategory: false,
        classConverterCopyStyles: true,
        classConverterEraseStyles: false, 
    },
    loremSentences: [
        'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
        'Integer nec odio. Praesent libero uctus non, massa.',
        'Sed cursus ante dapibus diam. Sed nisi.',
        'Nulla quis sem at nibh elementum imperdiet.',
        'Duis sagittis ipsum. Praesent mauris himenaeos.',
        'Fusce nec tellus sed augue semper porta.',
        'Vestibulum lacinia arcu eget nulla per conubia.',
        'Class aptent taciti sociosqu ad litora torquent.',
        'Curabitur sodales ligula in libero euismod in, nibh.',
        'Sed dignissim lacinia nunc nostra, per inceptos.',
        'Curabitur tortor pellentesque nibh aenean quam.',
        'In scelerisque sem at dolor maecenas mattis.',
        'Sed convallis tristique sem mauris massa.',
        'Proin ut ligula vel nunc egestas porttitor.',
        'Morbi lectus risus, iaculis vel, suscipit quis.',
        'Fusce ac turpis quis ligula lacinia aliquet.',
        'Mauris ipsum mam nec ante Nulla facilisi adipiscing diam.',
        'Nulla metus metus, ullamcorper vel, tincidunt sed.',
        'Quisque volutpat condimentum velit ante quis turpis.',
        'Class aptent taciti sociosqu ad litora torquent per conubia.',
        'Sed lacinia, urna non tincidunt mattis, tortor neque.',
        'Ut fringilla. Suspendisse potenti a cursus ipsum.',
        'Nunc feugiat mi a tellus consequat imperdiet.',
        'Vestibulum sapien. Proin quam. Etiam ultrices.',
        'Suspendisse in justo eu magna luctus suscipit.',
    ],
    CSScontrolKeys: [],
    excludedControlKeyFromCSS: [
        '_cssGlobalClasses',
        '_conditions',
        '_interactions',
        '_cssClasses',
        '_cssId',
        '_attributes',
        'style',
        'size',
        'circle',
        'outline',
        'icon'
    ],
    fields: {
        CSSVariabe : {
            includedFields: [
                'div[data-control="number"]',
                {
                    selector: 'div[data-control="text"]',
                    hasChild: [
                        '#_backdropFilter',
                        '#_pointerEvents',
                        '#_aspectRatio',
                        '#_perspectiveOrigin',
                        '#_cssTransition',
                        '#_transformOrigin',
                        '#_flexBasis',
                        '#_overflow',
                        '#_gridTemplateColumns',
                        '#_gridTemplateRows',
                        '#_gridAutoColumns',
                        '#_gridAutoRows',
                        '#_objectPosition',
                        '[id^="raw-"]'
                    ]
                }
            ],
            excludedFields: [
                // Query loop
                '.control-query',
                // Slider
                '[data-controlkey="start"]',
                '[data-controlkey="perPage"]',
                '[data-controlkey="perMove"]',
                '[data-controlkey="speed"]',
                '[data-controlkey="rating"]',
                '[data-controlkey="maxRating"]',
            ],
        },
        colors : {
            includedFields: [
                'div[data-control="color"]',
            ],
            excludedFields: [],
        },
        loremIpsum : {
            includedFields: [
                'div[data-control="textarea"]',
                {
                    selector:
                        '[data-controlkey="text"] div[data-control="text"][type="text"],[data-controlkey="title"] div[data-control="text"][type="text"], [data-controlkey="fields"] div[data-control="text"][type="text"], [data-controlkey="prefix"] div[data-control="text"][type="text"], [data-controlkey="suffix"] div[data-control="text"][type="text"], [data-controlkey="logoText"] div[data-control="text"][type="text"], [data-controlkey="actionText"] div[data-control="text"][type="text"], [data-controlkey="titleCustom"] div[data-control="text"][type="text"], [data-control-key="text"] div[data-control="text"][type="text"], [data-control-key="title"] div[data-control="text"][type="text"], [data-control-key="subtitle"] div[data-control="text"][type="text"], [data-control-key="name"] div[data-control="text"][type="text"], [data-control-key="buttonText"] div[data-control="text"][type="text"]',
                    hasChild: '.dynamic-tag-picker-button',
                }
            ],
            excludedFields: [
                '.control-query',
                'div[data-control="conditions"]',
                'div[data-control="interactions"]',
                '#transition',
                'div[data-controlkey="speed"]',
                '[data-controlkey="shortcode"]',
                'div[data-control-key="format"]',
                '[data-controlkey="_cssSuperPowerCSS"]',
                '[data-controlkey="_cssStickyCSS"]'
            ],
        },
        openAI : {
            includedFields: [
                'div[data-control="textarea"]',
                {
                    selector:
                        '[data-controlkey="text"] div[data-control="text"][type="text"], [data-controlkey="title"] div[data-control="text"][type="text"], [data-controlkey="fields"] div[data-control="text"][type="text"], [data-controlkey="prefix"] div[data-control="text"][type="text"], [data-controlkey="suffix"] div[data-control="text"][type="text"], [data-controlkey="logoText"] div[data-control="text"][type="text"], [data-controlkey="actionText"] div[data-control="text"][type="text"], [data-controlkey="titleCustom"] div[data-control="text"][type="text"], [data-control-key="text"] div[data-control="text"][type="text"], [data-control-key="title"] div[data-control="text"][type="text"], [data-control-key="subtitle"] div[data-control="text"][type="text"], [data-control-key="name"] div[data-control="text"][type="text"], [data-control-key="buttonText"] div[data-control="text"][type="text"]',
                    hasChild: '.dynamic-tag-picker-button',
                }
            ],
            excludedFields: [
                '.control-query',
                'div[data-control="conditions"]',
                'div[data-control="interactions"]',
                '#transition',
                'div[data-controlkey="speed"]',
                '[data-controlkey="shortcode"]',
                'div[data-control-key="format"]',
                '[data-controlkey="_cssSuperPowerCSS"]',
                '[data-controlkey="_cssStickyCSS"]'
            ],
        },
        dynamicDataModal: {
            includedFields: [
                '.dynamic-tag-picker-button:not([data-listening="true"])',
            ],
            excludedFields: [
                '.control.control-code',
                '[data-control="color"] > .dynamic-tag-picker-button',
                '.palette-actions .dynamic-tag-picker-button'
            ],
        },
        colorsOnHover : {
            includedFields: [
                'ul.color-palette > li.color',
            ],
            excludedFields: [
            ],
        },
        classesOnHover : {
            includedFields: [
                'div.bricks-control-popup > div.css-classes > ul:nth-of-type(2) > li > div.actions',
            ],
            excludedFields: [
            ],
        }
    },
    aihistory:[
    ],
    handleGlobalClassesOnLoad: function(){
        const self = this;
        let globalClasses = self.vueState.globalClasses || [];
        let globalClassesLocked = self.vueState.globalClassesLocked || [];
        let globalClassesCategories = self.vueState.globalClassesCategories || [];
        let hasChangesGlobalClasses = false, hasChangesGlobalClassesLocked = false, hasChangesGlobalClassesCategories = false, hasChangesContent = false;
    
        const lockedClassIds = new Set(globalClassesLocked);
        const importedClassIds = new Set(); // To collect imported class IDs for locking
    
        // Batch save function
        const saveChangesIfNeeded = () => {
            if (hasChangesGlobalClasses) self.helpers.saveChanges('globalClasses');
            if (hasChangesGlobalClassesLocked) self.helpers.saveChanges('globalClassesLocked');
            if (hasChangesGlobalClassesCategories) self.helpers.saveChanges('globalClassesCategories');
            if (hasChangesContent) self.helpers.saveChanges('content');
        };
    
        // Iterate over globalClasses once and handle all conditions
        globalClasses = globalClasses.reduce((accumulatedClasses, item) => {
            if (!item || !item.id) return accumulatedClasses;
    
            // Collect imported IDs for locking
            const isImportedClass = item.id.startsWith("brxc_imported");
            if (isImportedClass) {
                importedClassIds.add(item.id);
            }
    
            // Ensure settings object exists
            if (!item.hasOwnProperty('settings')) {
                item.settings = {};
                hasChangesGlobalClasses = true;
            }
    
            // Fix class categories
            if (item.cat) {
                const categoryFound = self.helpers.getClassCategoryObjByName(item.cat);
                if (categoryFound) {
                    item.category = categoryFound.id;
                } else {
                    const newCategoryId = self.vueGlobalProp.$_generateId();
                    globalClassesCategories.push({
                        id: newCategoryId,
                        name: item.cat
                    });
                    item.category = newCategoryId;
                    hasChangesGlobalClassesCategories = true;
                }
                delete item.cat;
                hasChangesGlobalClasses = true;
            }
    
            // Add the item to the final array
            accumulatedClasses.push(JSON.parse(JSON.stringify(item)));
            return accumulatedClasses;
        }, []);
    
        self.vueState.globalClasses = globalClasses;
    
        // Lock imported classes if not already locked
        importedClassIds.forEach(id => {
            if (!lockedClassIds.has(id)) {
                globalClassesLocked.push(id);
                hasChangesGlobalClassesLocked = true;
            }
        });
    
        // Sanitize classes for inexistent ones in content elements
        if (Object.values(self.globalSettings.classFeatures).includes("clean-deleted-classes")) {
            const content = self.helpers.getContent() || [];
            content.forEach(el => {
                if (el?.settings?._cssGlobalClasses?.length) {
                    const originalGlobalClasses = el.settings._cssGlobalClasses;
                    el.settings._cssGlobalClasses = el.settings._cssGlobalClasses.filter(cls =>
                        globalClasses.some(globalClass => globalClass.id === cls)
                    );
    
                    // Add to unsaved Changes
                    if (originalGlobalClasses.length !== el.settings._cssGlobalClasses.length) hasChangesContent = true;
    
                    // Remove property if Global Class array is empty
                    if (el.settings._cssGlobalClasses.length === 0) delete el.settings._cssGlobalClasses;
                }
            });
        }
    
        // Save all changes at once
        saveChangesIfNeeded();
    },
    qry: (el) => {
        return document.querySelector(el);
    },
    qryAll: (els) => {
        return document.querySelectorAll(els);
    },
    initAcc: (elems, option) => {
        elems.forEach(elem => {
            elem.addEventListener('click', (e) => {
                if (!e.target.matches('.brxc-accordion-btn')) return;
    
                const container = e.target.parentElement;
    
                if (!container.classList.contains('active')) {
                    if (option === true) {
                        elem.querySelectorAll('.brxc-accordion-container').forEach(container => {
                            container.classList.remove('active');
                        });
                    }
                    container.classList.add('active');
                } else {
                    container.classList.remove('active');
                }
            });
        });
    },
    minimizeModal: function(overlay){
        const inner = document.querySelector(`${overlay} .brxc-overlay__inner`);
        (inner.classList.contains('brxc-large')) ? inner.classList.remove('brxc-large') : '';
        inner.classList.add('brxc-medium');
    },
    maximizeModal: function(icon, overlay){
        const modal = document.querySelector(overlay);
        const inner = document.querySelector(`${overlay} .brxc-overlay__inner`);
        const icons = modal.querySelectorAll('.brxc-overlay__resize-icons i')
        const btn  = modal.querySelector('.brxc-overlay__close-btn')
        modal.classList.remove(...['sidebar', 'left', 'right']);
        inner.style.width = '';
        btn.style.left = '';
        btn.style.right = '';
        if(icon.classList.contains('active')) {
            icons.forEach(el => el.classList.remove('active'));
            inner.classList.remove('brxc-large');
            inner.classList.add('brxc-medium')
        } else {
            icons.forEach(el => el.classList.remove('active'));
            icon.classList.add('active');
            inner.classList.add('brxc-large');
            inner.classList.remove('brxc-medium')
        }
    },
    rightSidebarModal: function(icon, overlay){
        const self = this;
        const modal = document.querySelector(overlay);
        const inner = modal.querySelector(`.brxc-overlay__inner`);
        const btn  = modal.querySelector('.brxc-overlay__close-btn')
        const icons = modal.querySelectorAll('.brxc-overlay__resize-icons i')
        modal.classList.remove(...['sidebar', 'left', 'right']);
        inner.style.width = '';
        btn.style.left = '';
        btn.style.right = '';
        if(icon.classList.contains('active')) {
            icons.forEach(el => el.classList.remove('active'));
            const max = modal.querySelector('.brxc-overlay__resize-icons .fa-window-maximize');
            (inner.classList.contains('brxc-large')) ? max.classList.add('active') : '';
            return;
        };
        icons.forEach(el => el.classList.remove('active'));

        self.calculatePanelWidth('right', inner, btn);
        modal.classList.add(...['sidebar', 'right']);
        icon.classList.add('active');

    },
    calculatePanelWidth: function(position, inner, btn, forced = false){
        let panel, width;
        if(position === 'left'){
            panel = document.querySelector('#bricks-panel');
            width = window.getComputedStyle( panel ,null).getPropertyValue('width');
            if(forced) width = forced;
            btn.style.left = `calc(${width} + 8px)`;
        } else if(position === 'right') {
            panel = document.querySelector('#bricks-structure');
            width = window.getComputedStyle( panel ,null).getPropertyValue('width');
            if(forced) width = forced;
            btn.style.right = `calc(${width} + 16px)`;
        }
        inner.style.width = width;
    },
    leftSidebarModal: function(icon, overlay){
        const self = this;
        const modal = document.querySelector(overlay);
        const inner = modal.querySelector(`.brxc-overlay__inner`);
        const btn  = modal.querySelector('.brxc-overlay__close-btn')
        const icons = modal.querySelectorAll('.brxc-overlay__resize-icons i')
        modal.classList.remove(...['sidebar', 'left', 'right']);
        inner.style.width = '';
        btn.style.left = '';
        btn.style.right = '';
        if(icon.classList.contains('active')) {
            icons.forEach(el => el.classList.remove('active'));
            const max = modal.querySelector('.brxc-overlay__resize-icons .fa-window-maximize');
            (inner.classList.contains('brxc-large')) ? max.classList.add('active') : '';
            return;
        }
        icons.forEach(el => el.classList.remove('active'));
        self.calculatePanelWidth('left', inner, btn);
        modal.classList.add(...['sidebar', 'left']);
        icon.classList.add('active');

    },
    autocomplete: function (inp, arr, type, ignorePreview = false) {
        const self = this;
        let currentFocus = 0;
    
        if (inp.dataset.autocomplete === "true") return;
        inp.setAttribute("data-autocomplete", "true");
    
        // Array to track event listeners for cleanup
        const eventListeners = [];
    
        // Named function to handle keyup
        function handleKeyup(e) {
            if (e.keyCode === 40 || e.keyCode === 38 || e.keyCode === 13) return;
            let a, b, i, j, ul, val = inp.value;
            closeAllLists();
    
            if (!val) return false;
            currentFocus = -1;
    
            a = document.createElement("DIV");
            a.setAttribute("id", inp.id + "autocomplete-list");
            a.setAttribute("class", "autocomplete-items bricks-control-popup bottom");
            inp.parentNode.appendChild(a);
    
            ul = document.createElement("ul");
            a.appendChild(ul);
    
            for (i = 0, j = 0; i < arr.length; i++) {
                if (arr[i].toUpperCase().includes(val.toUpperCase())) {
                    j++;
                    b = document.createElement("li");
                    b.innerHTML += arr[i];
                    b.innerHTML += `<input type='hidden' value='${arr[i]}'>`;
    
                    // Named function for click
                    function handleClick() {
                        inp.value = this.querySelector("input").value;
                        const event = new Event("input", { bubbles: true, cancelable: true });
                        inp.dispatchEvent(event);
                        closeAllLists();
                        removeEventListeners();
                    }
                    b.addEventListener("click", handleClick);
                    eventListeners.push({ element: b, type: "click", listener: handleClick });
    
                    if (Object.values(self.globalSettings.classFeatures).includes("autocomplete-variable-preview-hover") && !ignorePreview) {
                        let isMouseMoving = false;
    
                        function handleMouseMove() {
                            isMouseMoving = true;
                        }
                        b.addEventListener("mousemove", handleMouseMove);
                        eventListeners.push({ element: b, type: "mousemove", listener: handleMouseMove });
    
                        function handleMouseLeave() {
                            setTimeout(() => {
                                inp.value = inp.dataset.autocompleteInitial;
                                const event = new Event("input", { bubbles: false, cancelable: true });
                                inp.dispatchEvent(event);
                                inp.removeAttribute("data-autocomplete-initial");
                            }, 0);
                        }
                        b.addEventListener("mouseleave", handleMouseLeave);
                        eventListeners.push({ element: b, type: "mouseleave", listener: handleMouseLeave });
    
                        function handleMouseEnter() {
                            setTimeout(() => {
                                inp.setAttribute("data-autocomplete-initial", inp.value);
                                if (!isMouseMoving) return;
                                inp.value = this.querySelector("input").value;
                                const event = new Event("input", { bubbles: false, cancelable: true });
                                inp.dispatchEvent(event);
                                isMouseMoving = false;
                            }, 0);
                        }
                        b.addEventListener("mouseenter", handleMouseEnter);
                        eventListeners.push({ element: b, type: "mouseenter", listener: handleMouseEnter });
                    }
    
                    ul.appendChild(b);
                }
            }
    
            if (j === 0) closeAllLists();
        }
    
        inp.addEventListener("keyup", handleKeyup);
        eventListeners.push({ element: inp, type: "keyup", listener: handleKeyup });
    
        // Named function to handle keydown
        function handleKeydown(e) {
            const x = document.getElementById(inp.id + "autocomplete-list");
            if (!x) return;
    
            const items = x.getElementsByTagName("li");
            if (e.key === "ArrowDown") {
                currentFocus++;
                addActive(items);
            } else if (e.key === "ArrowUp") {
                currentFocus--;
                addActive(items);
            } else if (e.key === "Enter") {
                e.preventDefault();
                if (currentFocus > -1 && items[currentFocus]) items[currentFocus].click();
            } else if (e.key === "Tab" || e.key === "Escape") {
                closeAllLists();
            }
        }
    
        inp.addEventListener("keydown", handleKeydown);
        eventListeners.push({ element: inp, type: "keydown", listener: handleKeydown });
    
        // Named function to close all lists
        function closeAllLists(elmnt) {
            const items = document.getElementsByClassName("autocomplete-items");
            for (let i = 0; i < items.length; i++) {
                if (elmnt !== items[i] && elmnt !== inp) {
                    items[i].parentNode.removeChild(items[i]);
                }
            }
        }
    
        // Attach event listener for clicks outside the autocomplete
        function handleClickOutside(e) {
            closeAllLists(e.target);
        }
        document.addEventListener("click", handleClickOutside);
        eventListeners.push({ element: document, type: "click", listener: handleClickOutside });
    
        // Utility functions
        function addActive(x) {
            if (!x) return;
            removeActive(x);
            if (currentFocus >= x.length) currentFocus = 0;
            if (currentFocus < 0) currentFocus = x.length - 1;
            x[currentFocus].classList.add("selected");
        }
    
        function removeActive(x) {
            for (let i = 0; i < x.length; i++) {
                x[i].classList.remove("selected");
            }
        }
    
        // Cleanup function to remove all event listeners
        function removeEventListeners() {
            eventListeners.forEach(({ element, type, listener }) => {
                element.removeEventListener(type, listener);
            });
            eventListeners.length = 0;
            inp.removeAttribute("data-autocomplete");
        }
    },
    
    debounce: (fn, threshold) => {
        var timeout;
        threshold = threshold || 200;
        return function debounced() {
            clearTimeout(timeout);
            var args = arguments;
            var _this = this;
        
            function delayed() {
                fn.apply(_this, args);
            }
            timeout = setTimeout(delayed, threshold);
        };
    },
    randomize: (length) => {
        let result = '';
        const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
        const charactersLength = characters.length;
        let counter = 0;
        while (counter < length) {
          result += characters.charAt(Math.floor(Math.random() * charactersLength));
          counter += 1;
        }
        return result;
    },
    openModalObj: function (html, target) {
        const template = document.createElement('template');
        template.innerHTML = html.trim();
        target.appendChild(template.content.cloneNode(true));
    },
    openModal: function(settings){
        const self = this;
        // Close open modals
        if(!settings.hasOwnProperty('closeActiveModals') || settings.closeActiveModals === true){
            const openModals = document.querySelectorAll('.brxc-overlay__wrapper');
            if(openModals && openModals.length > 0){
                openModals.forEach(el => el.remove());
            }
        }

        const template = document.createElement('template');
        const html = Object.values(brxcModals).find(el => el.id === settings.id.slice(1)).html;
        template.innerHTML = html
        document.body.appendChild(template.content.cloneNode(true));

        if(settings.callback){
            settings.callback
            settings.callback();
        }

        const wrapper = document.querySelector(settings.id);
        wrapper.setAttribute('data-active','true');

        // Close Modal
        function handleEscapeKey(e) {
            if (e.key === "Escape") {
                self.closeTemplateModal();
                self.closeModal(settings.target, settings.target.target, settings.id);
                document.removeEventListener('keydown', handleEscapeKey);
            }
        }
        document.addEventListener('keydown', handleEscapeKey);

        if(settings.focus) setTimeout(() => {
            const focusEl = document.querySelector(settings.focus)
            focusEl.focus();
            focusEl.setSelectionRange(0, focusEl.value.length)

        }, 10);

        // Resize
        const inner = wrapper.querySelector(`.brxc-overlay__inner`);
        const btn = wrapper.querySelector('.brxc-overlay__close-btn')
        inner.style.width = '';
        btn.style.left = '';
        btn.style.right = '';
        if (wrapper.classList.contains('left')) {
            self.calculatePanelWidth('left', inner, btn, settings.forced)
        } else if(wrapper.classList.contains('right')) {
            self.calculatePanelWidth('right', inner, btn, settings.forced)
        } 

        // Refresh panels
        const activePanel = wrapper.querySelector('.brxc-overlay__pannels-wrapper');
        if(activePanel){
            activePanel.style.display = "none";
            setTimeout(()=> {activePanel.style.display = "flex"}, 0);
            Array.from(wrapper.querySelector('.brxc-overlay__pannels-wrapper')?.children || []).forEach(el => {
                self.trapFocus(el);
              });
        }

        // Accordions
        const accordions = wrapper.querySelectorAll('.accordion.v1');
        if(accordions.length > 0){
            self.initAcc(accordions, true)
        }
    },
    trapFocus: function(container) {
        if (!container) return;
      
        const focusableSelectors = 'a, input:not([disabled]), textarea:not([disabled]), button:not([disabled]), [tabindex]:not([tabindex="-1"]), [contenteditable]';
      
        const keydownHandler = (e) => {
          if (e.key !== 'Tab') return;
      
          const focusableElements = Array.from(container.querySelectorAll(focusableSelectors));
          if (focusableElements.length === 0) return;
      
          const firstEl = focusableElements[0];
          const lastEl = focusableElements[focusableElements.length - 1];
      
          if (e.shiftKey) {
            if (document.activeElement === firstEl) {
              e.preventDefault();
              lastEl.focus();
            }
          } else {
            if (document.activeElement === lastEl) {
              e.preventDefault();
              firstEl.focus();
            }
          }
        };
      
        container.addEventListener('keydown', keydownHandler);
    },
    variablePickerToggleExtandCats: function(event,id){
        const self = this;
        event.preventDefault();
        event.stopPropagation();

        const isIncluded = self.variablePickerStates.extendedCategories.includes(id);

        if(isIncluded){
            self.variablePickerStates.extendedCategories = self.variablePickerStates.extendedCategories.filter(el => el && el !== id);

        } else {
            self.variablePickerStates.extendedCategories.push(id);
        }

        self.refreshVariablePickerList(false);
    },
    calculateContextualCategory: function () {
        const self = this;
        const target = self.variablePickerStates.target;
        const controlKey = target.closest('[data-controlkey]');
        if (!controlKey) return;
    
        const results = [];
    
        const mappings = [
            {
                selectors: ['[data-controlKey*="_border"]', '[data-controlKey*="_boxShadow"]'],
                categories: ['_border']
            },
            {
                selectors: ['[data-controlKey*="Gap"]'],
                categories: ['_gap']
            },
            {
                selectors: ['[data-controlKey*="_grid"]'],
                categories: ['_grid']
            },
            {
                selectors: ['[data-control="spacing"]'],
                categories: ['_spacing']
            }
        ];
    
        for (const { selectors, categories } of mappings) {
            if (selectors.some(sel => target.closest(sel))) {
                results.push(...categories);
                break;
            }
        }
    
        // Add panel group or tab fallback
        results.push(
            self.vueState.activePanelTab === 'content'
                ? 'content'
                : self.vueState.activePanelGroup
        );
    
        return results;
    },
    calculateContextualCategories: function(){
        const self = this;
        if(self.variablePickerStates.contextualCategory.length < 1) return [];

        self.variablePickerStates.contextualCategories = ! self.variablePickerStates.localStorage ? self.vueState.globalVariablesCategories.filter(el => self.variablePickerStates.contextualCategory.includes(el.cssCategory)).map(el => el.id) : [];
    },
    variablePopulateGroups: function(firstRun){
        const self = this;
        self.variablePickerStates.contextualCategory = self.calculateContextualCategory();
        self.calculateContextualCategories();
        let content = '<div id="sortableWrapper">';
        let isExpanded = false;
        let isExpandedDefault = false;
        let arr = self.helpers.isCSSVariablesTabActive('theme-variables') && self.helpers.themeHasVariables() ? self.vueState.globalVariables.concat(self.vueState.themeStyleSettings.general._cssVariables) : self.vueState.globalVariables;
        if (self.variablePickerStates.search !== '') {
            const search = self.variablePickerStates.search.toLowerCase();
        
            // First, find all scaleIds that match via customLabel
            const matchingScaleIds = new Set(
                arr
                    .filter(el => el?.customLabel?.toLowerCase().includes(search))
                    .map(el => el.scaleId)
                    .filter(Boolean)
            );
        
            // Now filter the array
            arr = arr.filter(el =>
                el &&
                (
                    el.name?.toLowerCase().includes(search) ||
                    el.label?.toLowerCase().includes(search) ||
                    el.customLabel?.toLowerCase().includes(search) ||
                    (el.scaleId && matchingScaleIds.has(el.scaleId))
                )
            );
        }
        
        function printCategory(group, variables, isExpandedDefault, isExpanded, isContextual) {
            const scaleVariables = variables.filter(el => el.type === "scale");
            const groupVariables = variables.filter(el => el.group);
            const otherVariables = variables.filter(el => el.type !== "scale" && !el.group);
        
            // Group scale variables by scaleId
            const scaleGroups = scaleVariables.reduce((acc, variable) => {
                if (!acc[variable.scaleId]) acc[variable.scaleId] = [];
                acc[variable.scaleId].push(variable);
                return acc;
            }, {});

            // Groups variables by group
            const groups = groupVariables.reduce((acc, variable) => {
                if (!acc[variable.group]) acc[variable.group] = [];
                acc[variable.group].push(variable);
                return acc;
            }, {});
        
            // === SCALE SECTION ===
            const scaleContent = isExpanded && Object.keys(scaleGroups).length > 0
                ? Object.entries(scaleGroups).map(([scaleId, groupVars]) => {
                    const baseVar = self.vueState.globalVariables.find(v => v.scaleId === scaleId && v.base);
                    const scaleLabel = `${baseVar?.customLabel || baseVar?.label} (Scale)` || 'Scale';
        
                    const buttons = groupVars.sort((a, b) => a.step - b.step).map(variable => {
                        const balloon = variable.min && variable.max 
                            ? `${variable.min} to ${variable.max} (px)` 
                            : `${Math.round(baseVar.min * (variable.multiplierMin ?? variable.multiplier))} to ${Math.round(baseVar.max * variable.multiplier)} (px)`;
        
                        const name = `var(--${self.helpers.formatForClasses(variable.name)})`;
                        const global = !!self.vueState.globalVariables.find(el => el.id === variable.id);
                        const isActive = name === self.variablePickerStates.target.value;
        
                        return `
                            <div class="brxc-overlay__action-btn isotope-selector ${global ? 'global' : 'theme'}${isActive ? ' active' : ''}${variable.base === true ? ' base' : ''}" 
                                 data-variable="${name}" 
                                 ${balloon ? `data-balloon="${balloon}" data-balloon-pos="top"` : ''}>
                                ${variable.suffix}${!global ? '<span class="type-indicator"></span>' : ''}
                            </div>
                        `;
                    }).join('');
        
                    return `
                        <div class="brxc-scale-label">${scaleLabel}</div>
                        <div class="brxc-overlay__action-btn-wrapper isotope-container scale">
                            ${buttons}
                        </div>
                    `;
                }).join('')
                : '';

            // === Group SECTION ===
            const groupContent = isExpanded && Object.keys(groups).length > 0
                ? Object.entries(groups).map(([group, groupVars]) => {
                    const baseVar = self.vueState.globalVariables.find(v => v.group === group && v.groupBase);
                    const groupLabel = baseVar?.groupName || 'Group';
        
                    const buttons = groupVars.sort((a, b) => a.step - b.step).map(variable => {
                        const balloon = variable.min && variable.max 
                            ? `${variable.min} to ${variable.max} (px)` 
                            : variable.value;
        
                        const name = `var(--${self.helpers.formatForClasses(variable.name)})`;
                        const global = !!self.vueState.globalVariables.find(el => el.id === variable.id);
                        const isActive = name === self.variablePickerStates.target.value;
        
                        return `
                            <div class="brxc-overlay__action-btn isotope-selector ${global ? 'global' : 'theme'}${isActive ? ' active' : ''}" 
                                 data-variable="${name}" 
                                 ${balloon ? `data-balloon="${balloon}" data-balloon-pos="top"` : ''}>
                                ${variable.label || variable.name}${!global ? '<span class="type-indicator"></span>' : ''}
                            </div>
                        `;
                    }).join('');
        
                    return `
                        <div class="brxc-scale-label">${groupLabel}</div>
                        <div class="brxc-overlay__action-btn-wrapper isotope-container scale">
                            ${buttons}
                        </div>
                    `;
                }).join('')
                : '';
        
            // === OTHER SECTION ===
            let othersContent = ``;
            if (isExpanded) {
                if (otherVariables.length > 0) {
                    othersContent += scaleVariables.length > 0 || groupVariables.length > 0 ? `<div class="brxc-other-label">Single Variables</div>` : '';
                    othersContent += `
                        <div class="brxc-overlay__action-btn-wrapper isotope-container others">
                            ${otherVariables.map((variable, index) => {
                                const balloon = ['clamp'].includes(variable.type) && variable.min && variable.max 
                                    ? `${variable.min} to ${variable.max} (px)` 
                                    : variable.value || false;

                                const name = `var(--${self.helpers.formatForClasses(variable.name)})`;
                                const global = !!self.vueState.globalVariables.find(el => el.id === variable.id);
                                const isActive = name === self.variablePickerStates.target.value;

                                return `
                                    <div class="brxc-overlay__action-btn isotope-selector ${global ? 'global' : 'theme'}${isActive ? ' active' : ''}" 
                                        data-variable="${name}" 
                                        ${balloon ? `data-balloon="${balloon}" data-balloon-pos="top"` : ''}>
                                        ${variable.type === "color" ? `<span class="color-variable-preview" style="background-color:${variable.value}"></span>` : ''}
                                        ${variable.label || variable.name}${!global ? '<span class="type-indicator"></span>' : ''}
                                    </div>
                                    ${self.helpers.isCSSVariablesTabActive('theme-variables') && index === otherVariables.length - 1 
                                        ? `<div class="add-new-variable" data-group="${group.id}" 
                                            data-balloon="Add a new Global Variable" data-balloon-pos="top">
                                            <i class="fas fa-plus"></i>
                                        </div>` 
                                        : ''
                                    }
                                `;
                            }).join('')}
                        </div>
                    `;
                } else if(self.variablePickerStates.search === ''){
                    // No other variables, show empty state
                    othersContent += scaleVariables.length > 0 || groupVariables.length > 0 ? `<div class="brxc-other-label">Single Variables</div>` : '';
                    othersContent += `
                        <div class="brxc-overlay__action-btn-wrapper isotope-container others">
                            <p class="brxc-variable-picker__category-empty" data-control="info">
                                No single variable found.
                            </p>
                            <div class="add-new-variable" data-group="${group.id}" 
                                data-balloon="Add a new Global Variable" data-balloon-pos="top-right">
                                <i class="fas fa-plus"></i>
                            </div>
                        </div>
                    `;
                }
            }
        
            // === MAIN CATEGORY BLOCK ===
            const printContent = `
                <div class="brxc-variable-picker__category${isContextual ? ' contextual': ''}" data-id="${group.id}" 
                     onmousedown="ADMINBRXC.variablePickerToggleExtandCats(event, '${group.id}')">
                    <label class="brxc-input__label has-tooltip${isExpanded ? ' expanded' : ''}">
                        ${self.variablePickerStates.search === '' 
                            ? `<div class="handle"><i class="fas fa-grip-vertical"></i></div>` 
                            : ''
                        }
                        <div class="title">
                            ${group.name} <span class="brxc-variable-count">(${variables.length})</span>
                        </div>
                        <div class="show-in-manager" data-balloon="Open in CSS Variable Manager" data-balloon-pos="top"
                             onmousedown="ADMINBRXC.openVariableCategory('${group.id}')">
                            <i class="fas fa-external-link-alt"></i>
                        </div>
                        <div class="default-expand${isExpandedDefault ? ' expanded' : ''}" 
                             data-balloon="${isExpandedDefault ? 'Expanded' : 'Collapsed'} by default" data-balloon-pos="top"
                             onmousedown="ADMINBRXC.toggleExpandVariableCategory(event, '${group.id}')">
                            <i class="fas fa-expand-alt"></i>
                        </div>
                        ${self.variablePickerStates.search === '' 
                            ? `<div class="brxc-collapse-icon down" data-balloon="${isExpanded ? 'Collapse' : 'Expand'}" data-balloon-pos="top-right">
                                 <i class="fas fa-chevron-${isExpanded ? 'down' : 'right'}"></i>
                               </div>` 
                            : ''
                        }
                    </label>
                    ${scaleContent}
                    ${groupContent}
                    ${othersContent}
                </div>
            `;
        
            return printContent;
        }        

        // Contextual
        self.vueState.globalVariablesCategories.filter(el => self.variablePickerStates.contextualCategories.includes(el.id)).forEach(group => {
            const variables = Array.from(arr).filter(el => el && el.category === group.id);
            isExpandedDefault = group.hasOwnProperty('defaultExpanded');
            if(firstRun) self.variablePickerStates.extendedCategories.push(group.id);
            isContextual = true;
            isExpanded = self.variablePickerStates.extendedCategories.includes(group.id) || self.variablePickerStates.search !== '';
            if (self.variablePickerStates.search === '' || variables.length > 0) {
                content += printCategory(group, variables, isExpandedDefault, isExpanded, isContextual);
            }
        })

        // No contextual
        self.vueState.globalVariablesCategories.filter(el => !self.variablePickerStates.contextualCategories.includes(el.id)).forEach(group => {
            const variables = Array.from(arr).filter(el => el && el.category === group.id);
            isExpandedDefault = group.hasOwnProperty('defaultExpanded');
            if(firstRun && group.hasOwnProperty('defaultExpanded')) self.variablePickerStates.extendedCategories.push(group.id);
            isExpanded = self.variablePickerStates.extendedCategories.includes(group.id) || self.variablePickerStates.search !== '';
            isContextual = false;
            if (self.variablePickerStates.search === '' || variables.length > 0) {
                content += printCategory(group, variables, isExpandedDefault, isExpanded, isContextual);
            }
        })
        content += `</div>`; // end sortable wrapper
        const uncategorizedVars = Array.from(arr).filter(el => el && self.helpers.isVariableUncategorized(el));
        if(uncategorizedVars.length > 0){
            isExpanded = self.variablePickerStates.extendedCategories.includes('uncategorized') || self.variablePickerStates.search !== '';
            content += `<div class="brxc-variable-picker__category no-handle" onmousedown="ADMINBRXC.variablePickerToggleExtandCats(event,'uncategorized')">`; 
            content += `<label class="brxc-input__label has-tooltip${isExpanded ? ' expanded' : ''}">`
            if(self.variablePickerStates.search === '') content += `<div class="handle" style="opacity: 0;"><i class="fas fa-grip-vertical"></i></div>`;
            content += `<div class="title">Uncategorized <span class="brxc-variable-count">(${uncategorizedVars.length})</span></div>`;
            content += `<div class="show-in-manager" data-balloon="Open in CSS Variable Manager" data-balloon-pos="top" onmousedown="ADMINBRXC.openVariableCategory('uncategorized')"><i class="fas fa-external-link-alt"></i></div>`;
            if(self.variablePickerStates.search === '') content += `<div class="brxc-collapse-icon down" data-balloon="${isExpanded ? 'Collapse' : 'Expand'}" data-balloon-pos="top-right"><i class="fas fa-chevron-${isExpanded ? 'down' : 'right'}"></i></div>`
            content += `</label>`;
            content += `<div class="brxc-overlay__action-btn-wrapper isotope-container">`;
            if(isExpanded && uncategorizedVars.length > 0){
                uncategorizedVars.forEach((variable, index) => {
                    let balloon = false;
                    
                    if(variable.hasOwnProperty('type') && variable.type === "clamp" && variable.hasOwnProperty('min') && variable.hasOwnProperty('max')) {
                        balloon = `${variable.min} to ${variable.max} (px)`;
                    } else if(variable.hasOwnProperty('value')) {
                        balloon = variable.value;
                    }
                    const name = `var(--${self.helpers.formatForClasses(variable.name)})`;
                    const global = self.vueState.globalVariables.find(el => el.id === variable.id) ? true : false;
                    const isActive = name === self.variablePickerStates.target.value;
                    
                    content += `<div class="brxc-overlay__action-btn isotope-selector ${global ? 'global' : 'theme'}${isActive ? ' active' : ''}" data-variable="${name}"${balloon ? ` data-balloon="${balloon}" data-balloon-pos="top"` : ''}>${variable.name}${!global ? '<span class="type-indicator"></span>' : ''}</div>`;
                    if(self.helpers.isCSSVariablesTabActive('theme-variables') && index === uncategorizedVars.length - 1){
                        content += `<div class="add-new-variable" data-group="uncategorized" data-balloon="Add a new Global Variable" data-balloon-pos="top"><i class="fas fa-plus"></i></div>`;
                    }
                })
            }
        }
        
        content += `</div></div>`
        
        return content;
            
    },
    colorsPopulateGroups: function(firstRun) {
        // Filter and apply search to color palette
        const filteredPalettes = this.getFilteredPalettes();
        console.log(filteredPalettes)
        
        // Build complete content by combining different sections
        return `
            <div id="sortableWrapper">
                ${this.generatePaletteCategories(filteredPalettes, firstRun)}
            </div>
            ${this.generateVariableManagerContent(firstRun)}
        `;
    },
    
    getFilteredPalettes: function() {
        return this.vueState.colorPalette
            .filter(el => !el.hasOwnProperty('status') || el.status !== "disabled")
            .map(palette => {
                // Apply search filter to colors if needed
                let filteredColors = Array.isArray(palette.colors) ? palette.colors : [];
                if (this.variablePickerStates.search !== '') {
                    filteredColors = filteredColors.filter(el =>
                        el && (this.helpers.getColorName(el, palette.prefix).includes(this.variablePickerStates.search) ||
                        el.raw?.includes(this.variablePickerStates.search))
                    );
                }
                
                return {
                    ...palette,
                    colors: filteredColors
                };
            });
    },
    
    generatePaletteCategories: function(palettes, firstRun) {
        return palettes
            .filter(palette => palette.colors && Array.isArray(palette.colors) && palette.colors.length > 0)
            .map(palette => {
                const isExpandedDefault = palette.hasOwnProperty('defaultExpanded');
                const view = palette.view || 'column';
                
                // Handle default expansion for first run
                if (firstRun && isExpandedDefault) {
                    this.variablePickerStates.extendedCategories.push(palette.id);
                }
                
                const isExpanded = this.variablePickerStates.extendedCategories.includes(palette.id) || 
                                this.variablePickerStates.search !== '';
                
                return `
                    <div class="brxc-variable-picker__category color" data-id="${palette.id}" 
                         onmousedown="ADMINBRXC.variablePickerToggleExtandCats(event,'${palette.id}')">
                        ${this.generateCategoryHeader(palette, isExpanded, isExpandedDefault, view)}
                        <div class="isotope-container brxc-color-container ${view}">
                            ${isExpanded ? this.generateExpandedColorContent(palette.colors, view, palette.prefix) : ''}
                        </div>
                    </div>
                `;
            }).join('');
    },
    
    generateCategoryHeader: function(palette, isExpanded, isExpandedDefault, view) {
        return `
            <label class="brxc-input__label has-tooltip${isExpanded ? ' expanded' : ''}">
                ${this.variablePickerStates.search === '' ? 
                    '<div class="handle"><i class="fas fa-grip-vertical"></i></div>' : ''}
                <div class="title">${palette.name} <span class="brxc-variable-count">(${palette.colors.length})</span></div>
                <div class="show-in-manager" data-balloon="Open in Color Manager" data-balloon-pos="top" 
                     onmousedown="ADMINBRXC.openColorCategory('${palette.id}')"><i class="fas fa-external-link-alt"></i></div>
                <div class="default-expand${isExpandedDefault ? ' expanded' : ''}" 
                     data-balloon="${isExpandedDefault ? ' Expanded' : 'Collapsed'} by default" data-balloon-pos="top" 
                     onmousedown="ADMINBRXC.toggleExpandColorCategory(event,'${palette.id}')"><i class="fas fa-expand-alt"></i></div>
                ${this.generateViewControls(palette.id, view)}
                ${this.variablePickerStates.search === '' ? 
                    `<div class="brxc-collapse-icon down" data-balloon="${isExpanded ? 'Collapse' : 'Expand'}" 
                          data-balloon-pos="top-right"><i class="fas fa-chevron-${isExpanded ? 'down' : 'right'}"></i></div>` : ''}
            </label>
        `;
    },
    
    generateViewControls: function(paletteId, activeView) {
        const views = [
            { type: 'column', icon: 'ti-layout-column3-alt' },
            { type: 'list', icon: 'ti-menu-alt' },
            { type: 'grid', icon: 'ti-layout-grid2-alt' }
        ];
        
        return `
            <div class="brxc-color-views">
                ${views.map(view => `
                    <div class="view${activeView === view.type ? ' active' : ''}" 
                         data-balloon="${view.type.charAt(0).toUpperCase() + view.type.slice(1)} View" data-balloon-pos="top" 
                         onmousedown="ADMINBRXC.toggleViewColorCategory(event,'${paletteId}', '${view.type}')">
                        <i class="${view.icon}"></i>
                    </div>
                `).join('')}
            </div>
        `;
    },
    
    generateExpandedColorContent: function(colors, view, prefix = '') {
        if (colors.length === 0) {
            return '<p class="brxc-variable-picker__category-empty" data-control="info">This category is empty.</p>';
        }

        // Group colors
        const parentColors = colors.filter(el => el.hasOwnProperty('shadeChildren') &&
                                              Array.isArray(el.shadeChildren) &&
                                              el.shadeChildren.length > 0);

        const otherColors = colors.filter(el => (!el.hasOwnProperty('shadeChildren') && !el.hasOwnProperty('shadeParent')) ||
                                            (el.hasOwnProperty('shadeChildren') && Array.isArray(el.shadeChildren) && el.shadeChildren.length < 1));

        return `
            ${parentColors.length > 0 ? this.generateParentColorsSection(parentColors, colors, view, prefix) : ''}
            ${otherColors.length > 0 ? this.generateOtherColorsSection(otherColors, parentColors, view, prefix) : ''}
        `;
    },
    
    generateParentColorsSection: function(parentColors, allColors, view, prefix = '') {
        return parentColors.map(parent => {
            const parentColor = parent.raw || parent.hex || parent.rgb || parent.hsl;
            const parentName = this.helpers.getColorName(parent, prefix);
            const childrenColors = allColors.filter(el => el.hasOwnProperty('shadeParent') && el.shadeParent === parent.id);
            const uniqueShadeTypes = [...new Set(childrenColors.map(el => el.shadeType))];
            return `
                <div>
                    <div class="brxc-color-label">${parentName}</div>
                    <div class="brxc-parent-color-container ${view}" style="--column-number:${uniqueShadeTypes.length}">
                        <div class="brxc-color-category-wrapper">
                            <div class="brxc-color-label">${parentName}</div>
                            <div class="brxc-color-wrapper">
                                <div class="brxc-color-item" data-variable="${parent.raw}">
                                    <div class="brxc-overlay__action-btn isotope-selector"
                                        ${view !== 'list' ? ` data-balloon="${parentName}" data-balloon-pos="top"` : ''}
                                        style="--color:${parentColor}">
                                    </div>
                                    ${view === "list" ? `<div class="brxc-color-list-label">${parentName}</div>` : ''}
                                </div>
                            </div>
                        </div>
                        ${this.generateChildColorSections(childrenColors, parentName, view, prefix)}
                    </div>
                    <div class="brxc-nested-color-container">
                        ${this.generateNestedColorSection(childrenColors, allColors, parentName, view, prefix)}
                    </div>
                </div>
            `;
        }).join('');
    },
    generateNestedColorSection: function(childrenColors, allColors, parentName, view, prefix = '') {
        if (!childrenColors || childrenColors.length === 0) return '';

        const shadeTypes = ["Light", "Dark", "Transparent"];
        const hasCustomShades = childrenColors.some(el => el.shadeMode === "custom");
        if (hasCustomShades) {
            shadeTypes.push("Custom");
        }

        let output = '';

        childrenColors.forEach(color => {
            const colorName = this.helpers.getColorName(color, prefix);
            const nestedChildren = allColors.filter(child => child.shadeParent === color.id);

            if (nestedChildren.length > 0) {
                shadeTypes.forEach(shadeType => {
                    const filteredChildren = nestedChildren.filter(child =>
                        shadeType === "Custom" ? child.shadeMode === "custom" : child.shadeType === shadeType
                    );

                    if (filteredChildren.length > 0) {
                        output += this.generateShadeTypeSection(shadeType, filteredChildren, colorName, view, prefix);
                    }
                });

                // Recursively collect deeper levels
                output += this.generateNestedColorSection(nestedChildren, allColors, colorName, view, prefix);
            }
        });

        return output;
    },
    generateChildColorSections: function(childrenColors, parentName, view, prefix = '') {
        if (!childrenColors || childrenColors.length === 0) return '';

        const shadeTypes = ["Light", "Dark", "Transparent"];

        // Add Custom if any child has shadeMode === "custom"
        const hasCustomShades = childrenColors.some(el => el.shadeMode === "custom");
        if (hasCustomShades) {
            shadeTypes.push("Custom");
        }

        return shadeTypes.map(shadeType => {
            let shadeColors = shadeType === "Custom"
                ? childrenColors.filter(el => el.shadeMode === "custom")
                : childrenColors.filter(el => el.shadeType === shadeType);

            if (shadeColors.length === 0) return '';

            return this.generateShadeTypeSection(shadeType, shadeColors, parentName, view, prefix);
        }).join('');
    },
    
    generateShadeTypeSection: function(shadeType, colors, parentName, view, prefix = '') {
        const isTransparent = shadeType === "Transparent";
        const bgStyle = isTransparent ? ` style="--bg: url(${this.globalSettings.transparencyCheckboard})"` : '';

        return `
            <div class="brxc-color-category-wrapper"${bgStyle}>
                ${view !== "column" ? `<div class="brxc-color-label">${parentName} - ${shadeType}</div>` : ''}
                <div class="brxc-color-wrapper"${(view === "column" && isTransparent) ? ` style="background-image: var(--bg);"` : ''}>
                    ${colors.map(el => {
                        const childColor = el.raw || el.hex || el.rgb || el.hsl;
                        const elName = this.helpers.getColorName(el, prefix);
                        return `
                            <div class="brxc-color-item" data-variable="${childColor}">
                                <div class="brxc-overlay__action-btn isotope-selector"
                                    ${view !== 'list' ? ` data-balloon="${elName}" data-balloon-pos="top"` : ''}
                                    style="--color:${childColor}">
                                </div>
                                ${view === "list" ? `<div class="brxc-color-list-label">${elName}</div>` : ''}
                            </div>
                        `;
                    }).join('')}
                </div>
            </div>
        `;
    },

    generateOtherColorsSection: function(otherColors, parentColors, view, prefix = '') {
        return `
            <div style="--bg: url(${this.globalSettings.transparencyCheckboard})">
                <div class="brxc-color-others ${view}">
                    ${parentColors.length > 0 ? '<div class="brxc-color-label">other colors</div>' : ''}
                    <div class="brxc-color-wrapper">
                        ${otherColors.map(el => {
                            const color = el.raw || el.hex || el.rgb || el.hsl;
                            const elName = this.helpers.getColorName(el, prefix);
                            return `
                                <div class="brxc-color-item" data-variable="${color}">
                                    <div class="brxc-overlay__action-btn isotope-selector"
                                        ${view !== 'list' ? ` data-balloon="${elName}" data-balloon-pos="top"` : ''}
                                        style="--color:${color}">
                                    </div>
                                    ${view === "list" ? `<div class="brxc-color-list-label">${elName}</div>` : ''}
                                </div>
                            `;
                        }).join('')}
                    </div>
                </div>
            </div>
        `;
    },
    
    generateVariableManagerContent: function(firstRun) {
        const categories = this.vueState.globalVariablesCategories;
        const validCategoryIds = categories.map(cat => cat.id);
        const search = this.variablePickerStates.search;
    
        let content = categories.map(category => {
            // Filter colors for this category
            let colors = this.vueState.globalVariables.filter(variable =>
                variable.category === category.id && variable.type === "color"
            );
    
            // Apply search filter
            if (search !== '') {
                colors = colors.filter(el => el && (el.name || '').includes(search));
            }
    
            if (colors.length < 1) return '';
    
            // Handle default expansion
            if (firstRun && category.hasOwnProperty('defaultExpanded')) {
                this.variablePickerStates.extendedCategories.push(category.id);
            }
    
            const isExpandedDefault = category.hasOwnProperty('defaultExpanded');
            const isExpanded = this.variablePickerStates.extendedCategories.includes(category.id) || search !== '';
    
            return `
                <div class="brxc-variable-picker__category color variable" data-id="${category.id}" 
                     onmousedown="ADMINBRXC.variablePickerToggleExtandCats(event,'${category.id}')">
                    <label class="brxc-input__label has-tooltip${isExpanded ? ' expanded' : ''}">
                        <div class="title">${category.name} <span class="brxc-variable-count">(${colors.length})</span></div>
                        <div class="show-in-manager" data-balloon="Open in CSS Variable Manager" data-balloon-pos="top" 
                             onmousedown="ADMINBRXC.openVariableCategory('${category.id}')"><i class="fas fa-external-link-alt"></i></div>
                        <div class="default-expand${isExpandedDefault ? ' expanded' : ''}" 
                             data-balloon="${isExpandedDefault ? ' Expanded' : 'Collapsed'} by default" data-balloon-pos="top" 
                             onmousedown="ADMINBRXC.toggleExpandColorCategory(event,'${category.id}', 'variable')">
                            <i class="fas fa-expand-alt"></i>
                        </div>
                        <div class="brxc-collapse-icon down" data-balloon="Expand" data-balloon-pos="top-right">
                            <i class="fas fa-chevron-right"></i>
                        </div>
                    </label>
                    ${isExpanded ? this.generateVariableColorList(colors) : ''}
                </div>
            `;
        }).join('');
    
        // UNCATEGORIZED variables
        let uncategorized = this.vueState.globalVariables.filter(variable =>
            variable.type === "color" && (
                !variable.hasOwnProperty('category') || 
                !validCategoryIds.includes(variable.category)
            )
        );
    
        // Apply search filter
        if (search !== '') {
            uncategorized = uncategorized.filter(el => el && (el.name || '').includes(search));
        }
    
        if (uncategorized.length) {
            const uncategorizedId = 'Uncategorized';
            const isExpanded = this.variablePickerStates.extendedCategories.includes(uncategorizedId) || search !== '';
        
            content += `
                <div class="brxc-variable-picker__category color variable" data-id="${uncategorizedId}" 
                     onmousedown="ADMINBRXC.variablePickerToggleExtandCats(event,'${uncategorizedId}')">
                    <label class="brxc-input__label has-tooltip${isExpanded ? ' expanded' : ''}">
                        <div class="title">Uncategorized <span class="brxc-variable-count">(${uncategorized.length})</span></div>
                        <div class="show-in-manager" data-balloon="Open in CSS Variable Manager" data-balloon-pos="top" 
                             onmousedown="ADMINBRXC.openVariableCategory('all')"><i class="fas fa-external-link-alt"></i></div>
                        <div class="brxc-collapse-icon down" data-balloon="Expand" data-balloon-pos="top-right">
                            <i class="fas fa-chevron-right"></i>
                        </div>
                    </label>
                    ${isExpanded ? this.generateVariableColorList(uncategorized) : ''}
                </div>
            `;
        }
    
        return content;
    },
    
    generateVariableColorList: function(colors) {
        return `
            <div class="isotope-container brxc-color-container list">
                ${colors.map(el => {
                    const varName = el.name || '';
                    return `
                    <div>
                        <div class="brxc-parent-color-container list">
                            <div class="brxc-color-category-wrapper" style="--bg: url(${this.globalSettings.transparencyCheckboard})">
                                <div class="brxc-color-wrapper">
                                    <div class="brxc-color-item" data-variable="var(--${varName})">
                                        <div class="brxc-overlay__action-btn isotope-selector" style="--color:var(--${varName})"></div>
                                        <div class="brxc-color-list-label">${varName}</div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                `}).join('')}
            </div>
        `;
    },
    variablePickerStates: {
        search: '',
        extendedCategories: [],
        contextualCategory: '',
        contextualCategories: [],
        target: false,
        controlKey: false,
        clickTarget: false,
        id: false,
        type: 'variable',
        localStorage: false
    },
    refreshVariablePickerList: function(firstRun){
        const self = this;
        const wrapper = document.querySelector('#brxcVariableOverlay');
        if(!wrapper) return;
        
        const canvas = wrapper.querySelector('#brxcVariablePickrAT');
        if(canvas){
            content = self.variablePickerStates.type === "variable" ? self.variablePopulateGroups(firstRun) : self.colorsPopulateGroups(firstRun);
            canvas.innerHTML = content;
        }

        // Add Listeners
        const sortableWrapper = wrapper.querySelector('#sortableWrapper');
        const allWrappers = wrapper.querySelectorAll('#brxcVariablePickrAT > div, #brxcVariablePickrCF, .brxc-variable-picker__category.custom-fw');

        allWrappers.forEach(el => {
            const initialValue = self.variablePickerStates.target.value;

            let wasClicked = false;

            let hoverTimeout;

            el.addEventListener('mouseover', event => {
                const btn = event.target.closest('[data-variable]');
                if (!btn || !el.contains(btn)) return;

                const variable = btn.dataset.variable;
                if (!variable || self.variablePickerStates.target.value === variable) return;

                clearTimeout(hoverTimeout);
                hoverTimeout = setTimeout(() => {
                    self.variablePickerStates.target.value = variable;
                    const inputEvent = new Event('input', { bubbles: true, cancelable: true });
                    self.variablePickerStates.target.dispatchEvent(inputEvent);
                }, 50); // Slight debounce to avoid flickering
            });

            el.addEventListener('mouseout', event => {
                const btn = event.target.closest('[data-variable]');
                if (!btn || !el.contains(btn) || wasClicked) return;

                clearTimeout(hoverTimeout);
                hoverTimeout = setTimeout(() => {
                    if (self.variablePickerStates.target.value !== initialValue) {
                        self.variablePickerStates.target.value = initialValue;
                        const inputEvent = new Event('input', { bubbles: true, cancelable: true });
                        self.variablePickerStates.target.dispatchEvent(inputEvent);
                    }
                }, 50);

                wasClicked = false;
            });

            el.addEventListener('mousedown', (event) => {

                // Variable
                const btn = event.target.dataset.variable ? event.target : event.target.closest('[data-variable]');
                if (btn && el.contains(btn)) {
                    wasClicked = true;

                    const dataset = btn.dataset.variable;

                    self.variablePickerStates.target.value = dataset;
                    const inputEvent = new Event('input', { bubbles: true, cancelable: true });
                    self.variablePickerStates.target.dispatchEvent(inputEvent);

                    self.variablePickerStates.clickTarget.click();

                    // localStorage
                    const storage = self.helpers.getLocalStorage();
                    if(!storage.variablePicker) storage.variablePicker = {};
                    storage.variablePicker[self.variablePickerStates.controlKey] = self.variablePickerStates.extendedCategories;
                    self.helpers.setLocalStorage('variablePicker', storage.variablePicker);

                    self.closeModal(
                        self.variablePickerStates.target,
                        self.variablePickerStates.target.target,
                        self.variablePickerStates.id
                    );
              
                } 

                // Add new
                const addNewBtn = event.target.closest('.add-new-variable');
                if (addNewBtn && el.contains(addNewBtn)) {
                    event.preventDefault();
                    event.stopPropagation();
                    self.setaddVariableFromPicker(event, self.variablePickerStates.target);;
              
                } 

            }, true);
        })

        //Drag and drop

        if(sortableWrapper){
            const handles = sortableWrapper.querySelectorAll('.handle');
            if (!handles || handles.length < 2) return;

            // Prevent event propagation when clicking on the handle
            handles.forEach(handle => {
                handle.addEventListener('mousedown', event => {
                    event.stopPropagation();
                });
            });

            new Sortable(sortableWrapper, {
                multiDrag: true,
                selectedClass: "sortable-selected",
                animation: 150,
                handle: ".handle",
                helper: 'clone',
                filter: ".no-handle",
                onEnd: () => {
                    const vars = self.variablePickerStates.type === 'variable' ? self.vueState.globalVariablesCategories : self.vueState.colorPalette;
                    const items = canvas.querySelectorAll('.brxc-variable-picker__category:not(.no-handle)');
                    items.forEach((item, index) => {
                        const target = Array.from(vars).find(el => el && el.hasOwnProperty('id') && el.id === item.dataset.id);
                        if (!target) return;

                        self.helpers.moveArr(vars, vars.indexOf(target), index);
                    });

                    self.refreshVariablePickerList(false);
                },
            });
        }

    },
    //openVariableModal: function(target, clickTarget, id, focus = false, type = 'variable'){
    openVariableModal: function(settings){
        const self = this;
        const storage = self.helpers.getLocalStorage();
        const controlKey = settings.target.closest('[data-controlkey]')?.dataset?.controlkey
        const isStored = storage.variablePicker && storage.variablePicker[controlKey]
        const storageKey = isStored ? storage.variablePicker[controlKey] : [];

        // Reset States & Search
        self.variablePickerStates.search = '';
        self.variablePickerStates.target = settings.target;
        self.variablePickerStates.controlKey = controlKey;
        self.variablePickerStates.clickTarget = settings.clickTarget;
        self.variablePickerStates.id = settings.id;
        self.variablePickerStates.extendedCategories = storageKey;
        self.variablePickerStates.contextualCategory = [];
        self.variablePickerStates.contextualCategories = [];
        self.variablePickerStates.type = settings.type;
        self.variablePickerStates.localStorage = isStored;

        // Open Modal
        const template = document.createElement('template');
        const html = Object.values(brxcModals).find(el => el.id === settings.id.slice(1)).html;
        template.innerHTML = html
        document.body.appendChild(template.content.cloneNode(true));

        if(settings.callback){
            settings.callback
            settings.callback();
        }

        const wrapper = document.querySelector(settings.id);
        wrapper.setAttribute('data-active', 'true');

        document.addEventListener('keydown', function(e) {
            (e.key === "Escape") ? self.closeModal(settings.target, settings.target.target, settings.id) : '';
        });
        if(settings.focus) {
            const focusEl = document.querySelector(settings.focus);
            focusEl.focus()
        }

        // Resize
        const inner = wrapper.querySelector(`.brxc-overlay__inner`);
        const btn = wrapper.querySelector('.brxc-overlay__close-btn')
        inner.style.width = '';
        btn.style.left = '';
        btn.style.right = '';
        if (wrapper.classList.contains('left')) {
            self.calculatePanelWidth('left', inner, btn)
        } else if(wrapper.classList.contains('right')) {
            self.calculatePanelWidth('right', inner, btn)
        } 
        
        // Refresh panels
        const activePanel = wrapper.querySelector('.brxc-overlay__pannels-wrapper');
        activePanel.style.display = "none";
        setTimeout(()=> {activePanel.style.display = "flex"}, 0);


        // Populate the groups
        self.refreshVariablePickerList(true);
        
    },
    openVariableCategory: function(id){
        const self = this;
        self.cssVariablesStates.activeCategory = id;
        self.cssVariablesStates.search = "";
        self.cssVariablesStates.view = "full"
        self.openModal({target: false, id: "#brxcCSSVariableManagerOverlay", callback: () => self.setCSSVariableManager()});
    },
    openColorCategory: function(id){
        const self = this;
        self.colorStates.activePalette = id;
        self.openModal({target: false, id: '#brxcColorManagerOverlay', callback: () => {self.setColorManager();}});
    },
    plainClassesStates: {
        search: '',
        existingClasses: [], 
        extendedCategories: [],
        target: false,
        id: false,
        
    },
    setCodeMirrorPlainClasses: function() {
        const self = this;
        const PlainClasses = document.querySelector("#plainClassesInput");

        // Plain Classes
        [PlainClasses].forEach(textarea => {
            if (!textarea) return;
            const myCodeMirror = CodeMirror(function(elt) {
                textarea.parentNode.replaceChild(elt, textarea);
            }, self.codeMirrorOptions(textarea));

            
                document.querySelector('#brxcPlainClassesOverlay .CodeMirror').CodeMirror.getMode().name = "text/x-markdown";
                myCodeMirror.setOption('lineNumbers', false);
                myCodeMirror.setOption('autoCloseBrackets', false);
                myCodeMirror.setOption('matchBrackets', false);
                myCodeMirror.setOption('gutters', false);
                myCodeMirror.setOption('highlightSelectionMatches', false);
                myCodeMirror.setOption("placeholder",'Type your classes here...');
                myCodeMirror.on("keydown", function (cm, event) {
                    if (!cm.state.completionActive &&
                        ((event.key >= '0' && event.key <= '9') ||    // Digits 0-9
                         (event.key >= 'a' && event.key <= 'z') ||    // Letters a-z
                         event.key === '-') &&                        // Dash
                        !event.metaKey && !event.altKey && event.key !== '{' && event.key !== '}' &&
                        !event.ctrlKey) {
                        CodeMirror.commands.autocomplete(cm, null, { completeSingle: false });
                    } 
                    else if(event.key === "Enter"){
                        const saveBtn = document.querySelector('#brxcSavePlainClasses');
                        const existingHint = document.querySelector('.CodeMirror-hints');
                        if(!existingHint) self.savePlainClasses(saveBtn, cm.getValue());

                    }
                });
                myCodeMirror.on("beforeChange", function(cm, changeObj) {
                    var typedNewLine = changeObj.origin == '+input' && typeof changeObj.text == "object" && changeObj.text.join("") == "";
                    if (typedNewLine) {
                        return changeObj.cancel();
                    }
                
                    var pastedNewLine = changeObj.origin == 'paste' && typeof changeObj.text == "object" && changeObj.text.length > 1;
                    if (pastedNewLine) {
                        var newText = changeObj.text.join(" ");
                        return changeObj.update(null, null, [newText]);
                    }
                
                    return null;
                });
            

        });
    },
    openPlainClassesModal: function(target, id){
        const self = this;
        self.plainClassesStates.search = '';
        self.plainClassesStates.extendedCategories = [];

        // Open Modal
        const template = document.createElement('template');
        const html = Object.values(brxcModals).find(el => el.id === id.slice(1)).html;
        template.innerHTML = html
        document.body.appendChild(template.content.cloneNode(true));


        const wrapper = document.querySelector(id);
        const mostUsedCanvas = wrapper.querySelector('#plainClassesMostUsedCanvas');
        const saveBtn = wrapper.querySelector('#brxcSavePlainClasses');
        
        self.setCodeMirrorPlainClasses();
        const cm = wrapper.querySelector('#brxcPlainClassesOverlay .CodeMirror').CodeMirror;
        const elementObj = self.builderStates.activeElement;
        let finalClasses = [];
        if(elementObj.settings.hasOwnProperty('_cssGlobalClasses')) {
            elementObj.settings._cssGlobalClasses.forEach(cls => {
                const obj = Array.from(self.vueState.globalClasses).find(el => el && el.id === cls);
                if(!obj) return;
                finalClasses.push(obj.name);
            })
        }
        self.plainClassesStates.existingClasses = finalClasses;

        const existingClasses = finalClasses.length === 0 ? '' : finalClasses.join(' ') + ' ';
        cm.setValue(existingClasses);
        wrapper.setAttribute('data-active', 'true');

        cm.on("keyup", function (cm, event) {
            self.plainClassesRefreshHighlight();
        });

        document.addEventListener('keydown', function(e) {
            (e.key === "Escape") ? self.closeModal(target, target.target, id) : '';
        });

        // Resize
        const inner = wrapper.querySelector(`.brxc-overlay__inner`);
        const btn = wrapper.querySelector('.brxc-overlay__close-btn')
        inner.style.width = '';
        btn.style.left = '';
        btn.style.right = '';
        if (wrapper.classList.contains('left')) {
            self.calculatePanelWidth('left', inner, btn)
        } else if(wrapper.classList.contains('right')) {
            self.calculatePanelWidth('right', inner, btn)
        } 

        // Refresh panels
        const activePanel = wrapper.querySelector('.brxc-overlay__pannels-wrapper');
        if(activePanel){
            activePanel.style.display = "none";
            setTimeout(()=> {activePanel.style.display = "flex"}, 0);
        }
        
        // Most used Classes;
        let content = '<div class="brxc-overlay__action-btn-wrapper">';
        const mostUsedClasses = self.mostUsedClasses();
        
        if(mostUsedClasses.length > 0){
            content += `<div id="brxcMostUsed"><span>Most Used: </span>${mostUsedClasses.slice(0, 10)
                .filter(el => self.vueGlobalProp.$_getGlobalClass(el))
                .map(el => `<a data-value="${self.vueGlobalProp.$_getGlobalClass(el).name}">.${self.vueGlobalProp.$_getGlobalClass(el).name}</a>`)
                .join('<span>, </span>')}</div>`
        }
        
        content += "</div>";
        mostUsedCanvas.innerHTML = content;

        // // reset values
        
        self.plainClassesRender(true, cm);

        // Event Listeners for Most Used
        const btns = mostUsedCanvas.querySelectorAll('#brxcMostUsed a');
        btns.forEach(btn => {
            btn.addEventListener('click', (e) => {
                e.preventDefault();
                e.stopPropagation();
                const value = btn.dataset.value;
                const existing = cm.getValue();
                cm.setValue(`${existing} ${value}`);
                if(e.shiftKey){
                    self.plainClassesRefreshHighlight();
                } else {
                    self.savePlainClasses(saveBtn, cm.getValue());
                }
            })
        })
        
        // Search

        const searchTerm = document.querySelector('#plainClassesSearchWrapper input');
        searchTerm.value = '';
        searchTerm.addEventListener('keyup', () => {
            self.plainClassesStates.search = searchTerm.value;
            self.plainClassesRender(false);
        })


        setTimeout(() => {
            cm.focus();
            cm.setCursor(cm.lineCount(), 0);
        }, 50)
    },

    plainClassesToggleExtandCats: function(event,id){
        const self = this;
        event.preventDefault();
        event.stopPropagation();
        const isIncluded = self.plainClassesStates.extendedCategories.includes(id);
        if(isIncluded){
            self.plainClassesStates.extendedCategories = self.plainClassesStates.extendedCategories.filter(el => el && el !== id);
        } else {
            self.plainClassesStates.extendedCategories.push(id);
        }
        self.plainClassesRender(false);
    },
    plainClassesRender: function(firstRun = false){
        const self = this;
        const overlay = document.querySelector('#brxcPlainClassesOverlay');
        const saveBtn = overlay.querySelector('#brxcSavePlainClasses');
        const cm = overlay.querySelector('.CodeMirror').CodeMirror;
        const searchCanvas = overlay.querySelector('#plainClassesSearchResultsCanvas');
        searchCanvas.innerHTML = self.classesPopulateGroups(firstRun);

        // Event Listeners
        const categories = searchCanvas.querySelectorAll('.brxc-overlay__action-btn-wrapper');
        categories.forEach(category => {
            category.addEventListener('click', handleEvent);
            category.addEventListener('keyup', handleEvent);
        });

        function handleEvent(e) {
            e.stopPropagation();
            e.preventDefault();

            const target = e.target.closest('[data-value]');
            if (!target) return;

            if (e.type === 'keyup' && e.key !== 'Enter') return;

            const newClass = target.dataset.value;
            const existingClasses = cm.getValue().split(' ');
            if(existingClasses.includes(newClass)){
                const index = existingClasses.indexOf(newClass);
                existingClasses.splice(index, 1);
            } else {
                existingClasses.push(newClass);
            }
            cm.setValue(`${existingClasses.join(' ')}`);

            // Check if the Shift key is pressed
            if (e.shiftKey) {
                self.plainClassesRefreshHighlight();
                const searchTerm = document.querySelector('#plainClassesSearchWrapper input');
                if (searchTerm) {
                    searchTerm.focus();
                    searchTerm.setSelectionRange(0, searchTerm.value.length);
                }
            } else {
                self.savePlainClasses(saveBtn, cm.getValue());
            }
        }

        //Drag and drop

        const sortableWrapper = searchCanvas.querySelector('#sortableWrapper');
        const handles = sortableWrapper.querySelectorAll('.handle');
        if (!handles || handles.length < 2) return;


        new Sortable(sortableWrapper, {
            multiDrag: true,
            selectedClass: "sortable-selected",
            animation: 150,
            handle: ".handle",
            helper: 'clone',
            filter: ".no-handle",
            onEnd: () => {
                const vars = self.vueState.globalClassesCategories;
                const items = searchCanvas.querySelectorAll('.brxc-variable-picker__category:not(.no-handle)');
                items.forEach((item, index) => {
                    const target = Array.from(vars).find(el => el && el.hasOwnProperty('id') && el.id === item.dataset.id);
                    if (!target) return;

                    self.helpers.moveArr(vars, vars.indexOf(target), index);
                });

                self.plainClassesRender(false);
            },
        });
    },
    toggleExpandClassCategory: function(e,id){
        e.preventDefault();
        e.stopPropagation();
        const self = this;
        const obj = self.helpers.getClassCategoryObjById(id);
        if(!obj) return;

        if(obj.hasOwnProperty('defaultExpanded')){
            delete obj['defaultExpanded'];
        } else {
            obj['defaultExpanded'] = true;
        };

        self.plainClassesRender();
    },
    classesPopulateGroups: function(firstRun){
        const self = this;
        let content = '<div id="sortableWrapper">';
        let isExpanded = false;
        let isExpandedDefault = false;
        let arr = self.vueState.globalClasses;
        if(self.plainClassesStates.search !== '') arr = arr.filter(el => el && el.name.includes(self.plainClassesStates.search));
        self.vueState.globalClassesCategories.forEach(group => {
            const clsArr = Array.from(arr).filter(el => el && el.category === group.id);
            isExpandedDefault = group.hasOwnProperty('defaultExpanded');
            if(firstRun && group.hasOwnProperty('defaultExpanded')) self.plainClassesStates.extendedCategories.push(group.id);
            isExpanded = self.plainClassesStates.extendedCategories.includes(group.id) || self.plainClassesStates.search !== '';
            if(self.plainClassesStates.search === '' || clsArr.length > 0){
                content += `<div class="brxc-variable-picker__category" data-id="${group.id}" onclick="ADMINBRXC.plainClassesToggleExtandCats(event,'${group.id}')">`; 
                content += `<label class="brxc-input__label has-tooltip${isExpanded ? ' expanded' : ''}">`
                if(self.plainClassesStates.search === '') content += `<div class="handle"><i class="fas fa-grip-vertical"></i></div>`;
                content += `<div class="title">${group.name} <span class="brxc-variable-count">(${clsArr.length})</span></div>`;
                content += `<div class="show-in-manager" data-balloon="Open in the Class Manager" data-balloon-pos="top" onclick="ADMINBRXC.states.classManagerActiveCategory = '${group.id}';ADMINBRXC.openClassManager('global');"><i class="fas fa-external-link-alt"></i></div>`;
                content += `<div class="default-expand${isExpandedDefault ? ' expanded' : ''}" data-balloon="${isExpandedDefault ? ' Expanded' : 'Collapsed'} by default" data-balloon-pos="top" onclick="ADMINBRXC.toggleExpandClassCategory(event,'${group.id}')"><i class="fas fa-expand-alt"></i></div>`;
                if(self.plainClassesStates.search === '') content += `<div class="brxc-collapse-icon down" data-balloon="${isExpanded ? 'Collapse' : 'Expand'}" data-balloon-pos="top-right"><i class="fas fa-chevron-${isExpanded ? 'down' : 'right'}"></i></div>`
                content += `</label>`;
                content += `<div class="brxc-overlay__action-btn-wrapper isotope-container">`;
                if (isExpanded && clsArr && clsArr.length > 0){
                    clsArr.forEach(cls => {
                        const isLocked = self.vueGlobalProp.$_isLocked(cls.id);
                        const existingClass = self.plainClassesStates.existingClasses.includes(cls.name);
                        content += `<div class="brxc-overlay__action-btn isotope-selector${existingClass ? ' active' : ''}" data-value="${cls.name}" tabindex="0">${isLocked ? `<i class="fas fa-lock"></i>`: ''}.${cls.name}</div>`;
                    })
                } else if(isExpanded && (!clsArr || clsArr.length < 1)){
                    content += `<p class="brxc-variable-picker__category-empty" data-control="info">This category is empty.</p>`
                }
                content += `</div></div>`;
            }
            
        })
        content += `</div>`; // end sortable wrapper
        const uncategorizedVars = Array.from(arr).filter(el => el && self.helpers.isClassUncategorized(el));
        if(uncategorizedVars.length > 0){
            isExpanded = self.plainClassesStates.extendedCategories.includes('uncategorized') || self.plainClassesStates.search !== '';
            content += `<div class="brxc-variable-picker__category no-handle" onclick="ADMINBRXC.plainClassesToggleExtandCats(event,'uncategorized')">`; 
            content += `<label class="brxc-input__label has-tooltip${isExpanded ? ' expanded' : ''}">`
            if(self.plainClassesStates.search === '') content += `<div class="handle" style="opacity: 0;"><i class="fas fa-grip-vertical"></i></div>`;
            content += `<div class="title">Uncategorized <span class="brxc-variable-count">(${uncategorizedVars.length})</span></div>`;
            content += `<div class="show-in-manager" data-balloon="Open in CSS Variable Manager" data-balloon-pos="top" onclick="ADMINBRXC.states.classManagerActiveCategory = 'Uncategorized';ADMINBRXC.openClassManager('global');"><i class="fas fa-external-link-alt"></i></div>`;
            if(self.plainClassesStates.search === '') content += `<div class="brxc-collapse-icon down" data-balloon="${isExpanded ? 'Collapse' : 'Expand'}" data-balloon-pos="top-right"><i class="fas fa-chevron-${isExpanded ? 'down' : 'right'}"></i></div>`
            content += `</label>`;
            content += `<div class="brxc-overlay__action-btn-wrapper isotope-container">`;
            if(isExpanded && uncategorizedVars.length > 0){
                uncategorizedVars.forEach(cls => {
                    const isLocked = self.vueGlobalProp.$_isLocked(cls.id);
                    const existingClass = self.plainClassesStates.existingClasses.includes(cls.name);
                    content += `<div class="brxc-overlay__action-btn isotope-selector${existingClass ? ' active' : ''}" data-value="${cls.name}" tabindex="0">${isLocked ? `<i class="fas fa-lock"></i>`: ''}.${cls.name}</div>`;
                })
            }
        }
        
        content += `</div></div>`
        
        return content;
            
    },
    plainClassesRefreshHighlight: function(){
        const self = this;
        const cm = document.querySelector('#brxcPlainClassesOverlay .CodeMirror').CodeMirror;
        const existingClasses = cm.getValue().split(' ');
        self.plainClassesStates.existingClasses = existingClasses;
        const actives = document.querySelectorAll('#brxcPlainClassesOverlay .brxc-overlay__action-btn.isotope-selector.active');
        actives.forEach(el => el.classList.remove('active'));
        existingClasses.forEach(cls => {
            const target = document.querySelector(`#brxcPlainClassesOverlay .brxc-overlay__action-btn.isotope-selector[data-value="${cls}"]`);
            if(!target) return;
            target.classList.add('active');
        }) 

    },
    openAIModal: function(prefix, global = false, target, id){
        const self = this;

        // Open Modal
        const existing = document.querySelector(id);
        if(existing) existing.remove();
        
        const template = document.createElement('template');
        const html = Object.values(brxcModals).find(el => el.id === id.slice(1)).html;
        template.innerHTML = html
        document.body.appendChild(template.content.cloneNode(true));

        if (global === false){
            // Completion
            const chatMore = document.querySelector('#brxcopenAIOverlay #' + prefix + 'ChatMore');
            const existingInsertBtn = document.querySelector('#brxcopenAIOverlay #' + prefix + 'InsertContent');
            const existingReplaceBtn = document.querySelector('#brxcopenAIOverlay #' + prefix + 'ReplaceContent');
            if(existingInsertBtn) existingInsertBtn.remove();
            if(existingReplaceBtn) existingReplaceBtn.remove();
            chatMore.insertAdjacentHTML(
                'afterend',
                '<div id="' + prefix + 'InsertContent" class="brxc-overlay__action-btn"><span>Insert Content</span></div><div id="' + prefix + 'ReplaceContent" class="brxc-overlay__action-btn primary"><span>Replace Content</span></div>'
            );

            const insertBtn = document.querySelector('#brxcopenAIOverlay #' + prefix + 'InsertContent');
            insertBtn.addEventListener('click', () =>{
                const value = document.querySelector('#brxcopenAIOverlay input[name="openai-results"]:checked + label .message.assistant').textContent;
                target.value += value.replaceAll(/\n/g,'<br>');
                const event = new Event('input', {
                    bubbles: true,
                    cancelable: true,
                });
                target.dispatchEvent(event);
                self.closeModal(target, target.target, id);
                self.vueGlobalProp.$_showMessage('AI Content Inserted');
            })
            const replaceBtn = document.querySelector('#brxcopenAIOverlay #' + prefix + 'ReplaceContent');
            replaceBtn.addEventListener('click', () =>{
                const value = document.querySelector('#brxcopenAIOverlay input[name="openai-results"]:checked + label .message.assistant').textContent;
                target.value = value.replaceAll(/\n/g,'<br>');
                const event = new Event('input', {
                    bubbles: true,
                    cancelable: true,
                });
                target.dispatchEvent(event);
                self.closeModal(target, target.target, id);
                self.vueGlobalProp.$_showMessage('AI Content Inserted');
            })

            // Edit
            const editTextArea = document.querySelector('#brxcopenAIOverlay #' + prefix + 'EditText');
            const editbtnwrapper = document.querySelector('#brxcopenAIOverlay #' + prefix + 'InsertEditContentWrapper')
            const existingInsertEditBtn = document.querySelector('#brxcopenAIOverlay #' + prefix + 'InsertEditContent');
            const existingReplaceEditBtn = document.querySelector('#brxcopenAIOverlay #' + prefix + 'ReplaceEditContent');
            if(existingInsertEditBtn) existingInsertEditBtn.remove();
            if(existingReplaceEditBtn) existingReplaceEditBtn.remove();
            editTextArea.value = target.value.replaceAll('<br>', '\n');
            editbtnwrapper.innerHTML += '<div id="' + prefix + 'InsertEditContent" class="brxc-overlay__action-btn"><span>Insert Content</span></div>';
            editbtnwrapper.innerHTML += '<div id="' + prefix + 'ReplaceEditContent" class="brxc-overlay__action-btn primary"><span>Replace Content</span></div>';
            const insertEditBtn = document.querySelector('#brxcopenAIOverlay #' + prefix + 'InsertEditContent');
            insertEditBtn.addEventListener('click', () =>{
                const value = document.querySelector('#brxcopenAIOverlay input[name="openai-edit-results"]:checked + label .message.assistant').textContent;
                target.value += value.replaceAll(/\n/g,'<br>');
                const event = new Event('input', {
                    bubbles: true,
                    cancelable: true,
                });
                target.dispatchEvent(event);
                self.closeModal(target, target.target, id);
                //self.showMessage('AI Content Inserted')
                self.vueGlobalProp.$_showMessage('AI Content Inserted');
            })
            const replaceEditBtn = document.querySelector('#brxcopenAIOverlay #' + prefix + 'ReplaceEditContent');
            replaceEditBtn.addEventListener('click', () =>{
                const value = document.querySelector('#brxcopenAIOverlay input[name="openai-edit-results"]:checked + label .message.assistant').textContent;
                target.value = value.replaceAll(/\n/g,'<br>');
                const event = new Event('input', {
                    bubbles: true,
                    cancelable: true,
                });
                target.dispatchEvent(event);
                self.closeModal(target, target.target, id);
                //self.showMessage('AI Content Inserted')
                self.vueGlobalProp.$_showMessage('AI Content Inserted');
            })
        }

        // Open modal
        const wrapper = document.querySelector(id);
        wrapper.setAttribute('data-active', 'true');
        document.addEventListener('keydown', function(e) {
            (e.key === "Escape") ? self.closeModal(target, target.target, id) : '';
        });
    },
    openExtendClassModal: function(target,id){
        const self = this;
        
        function init(){
            // Categories
            self.mountElementCategorySelect({
                modal: '#brxcExtendModal',
                element: '#brxc-extendcategoryOptions'
            })
            const elementObj = self.builderStates.activeElement;
            const select = document.querySelector(`#brxcExtendModal #brxc-extendcategoryOptions .brxc-select-new__wrapper [data-value="${elementObj.name}"]`);
            if(select) {
                document.querySelectorAll(`#brxcExtendModal #brxc-extendcategoryOptions .brxc-select-new__wrapper [data-value]`).forEach(el => el.classList.remove('active'));
                select.classList.add('active')
            }

            // CSS Properties
            self.mountCSSPropertiesSelect({
                modal: '#brxcExtendModal',
                element: '#brxc-extendpropertyOptions'
            })
    
            // Radios
            const radios = document.querySelectorAll('[name="brxc-extend-styles"]');
            const targetNew = document.querySelector('#brxc-extend-css-property');
            const eraseClass = document.querySelector('#brxc-extend-erase-classes');
            radios.forEach(radio => {
                radio.addEventListener('change', () =>{
                    const radio = document.querySelector('#brxc-extend-style');
                    (radio.checked == true) ? targetNew.style.display = 'block' : targetNew.style.display = 'none';
                    (radio.checked == true) ? eraseClass.style.display = 'none' : eraseClass.style.display = 'block';
                })
            })
        }   

        self.openModal({target: false, id: id, callback: () => {init()}});
    },
    applyExtendClass: function(){
        const self = this;
        const stylesValue = document.querySelector('#brxcExtendModal input[name=brxc-extend-styles]:checked')?.value;
        const propertyOptions = document.querySelector('#brxc-extendpropertyOptions [data-value].active')?.dataset?.value;
        const categoryOptions = document.querySelector('#brxc-extendcategoryOptions [data-value].active')?.dataset?.value;
        const positionValue = document.querySelector('#brxcExtendModal input[name=brxc-extend-position]:checked').value;
        const eraseValue = document.querySelector('#brxcExtendModal input[name=brxc-extend-erase]:checked')?.value;

        self.expandClass(
            stylesValue,
            propertyOptions,
            categoryOptions,
            positionValue,
            eraseValue
        );

        self.closeModal({target: true}, true, '#brxcExtendModal');
    },
    mountElementCategorySelect: function(obj){
        const self = this;
        const options = Object.values(bricksData.elements)
            .map(el => [el.name, el.label])
            .sort((a, b) => a[1].localeCompare(b[1]))
            .map(([value, label]) => `<div data-value="${value}"><span>${label}</span></div>`)
            .join('');

        document.querySelectorAll(`${obj.modal} ${obj.element} .brxc-select-new__wrapper`)
            .forEach(category => {
                let content = '';
                content += '<div class="active" data-value="all"><span>All</span></div>';
                content += options;
                category.innerHTML = content;
                self.helpers.selectControl(category.parentElement, false)
            });
    },
    mountCSSPropertiesSelect: function(obj){
        const self = this;

        const specialLabels = {
            _flexDirection: "Flex direction",
            _innerContainerMargin: "Inner Container margin",
            _innerContainerPadding: "Inner Container padding",
            _rowGapColors: "Row gap (Colors)",
            _gridGap: "Grid gap",
        };

        const allControls = Object.values(bricksData.elements)
            .filter(el => typeof el.controls === 'object')
            .flatMap(el =>
                Object.entries(el.controls)
                    .filter(([key, val]) => val?.css && key.startsWith('_'))
                    .map(([key, val]) => {
                        const label =
                            specialLabels[key] ||
                            val.label ||
                            (val.type ? val.type.charAt(0).toUpperCase() + val.type.slice(1) : key);
                        return [key, label];
                    })
            );

        const uniqueControls = [...new Map(allControls.map(([k, v]) => [k + v, [k, v]])).values()]
            .sort((a, b) => a[1].localeCompare(b[1]));

        const html = uniqueControls
            .map(([value, label]) => `<div data-value="${value}"><span>${label}</span></div>`)
            .join('');

        document.querySelectorAll(`${obj.modal} ${obj.element} .brxc-select-new__wrapper`)
            .forEach(wrapper => {
                let content = '';
                content += '<div class="active" data-value="all"><span>All</span></div>';
                content += html
                wrapper.innerHTML = content;
                self.helpers.selectControl(wrapper.parentElement, false)
            });
        
    },
    openFindReplaceModal: function(target,global, id){
        const self = this;

        function setModalMode(global, elementObj) {
            const select = document.querySelector('#brxcFindReplaceModal #brxc-findreplacecategoryOptions');
            const posRadios = document.querySelectorAll('#brxcFindReplaceModal [name=brxc-findreplacePosition]');
            const alert = document.querySelector('#brxcFindReplaceModal .alert');

            if (global) {
                select.value = 'all';
                document.querySelector('#brxcFindReplaceModal #brxc-findreplace-page')
                    .dispatchEvent(new MouseEvent('click'));
                posRadios.forEach(radio => radio.setAttribute('disabled', true));
                alert.classList.add('active');
            } else {
                select.value = elementObj.name;
                document.querySelector('#brxcFindReplaceModal #brxc-findreplace-siblings')
                    .dispatchEvent(new MouseEvent('click'));
                posRadios.forEach(radio => radio.removeAttribute('disabled'));
                alert.classList.remove('active');
            }
        }

        function init() {
            const elementObj = self.builderStates.activeElement;
            self.mountElementCategorySelect({
                modal: '#brxcFindReplaceModal',
                element: '#brxc-findreplacecategoryOptions'
            })
            self.mountCSSPropertiesSelect({
                modal: '#brxcFindReplaceModal',
                element: '#brxc-findreplacepropertyOptions'
            })
            setModalMode(global, elementObj);
        }
        self.openModal({target: false, id: id, callback: () => {init()}});
    },
    generateGlobalClass: function(prefix,name, cat, id = false){
        const self = this;
        const newId = id !== false ? id : self.vueGlobalProp.$_generateId();
        const obj = {
            id: prefix + newId,
            name: name,
            settings: {},
        }
        if(cat && typeof self.vueState.globalClassesCategories !== "undefined"){
            if(self.helpers.getClassCategoryIdByName(cat)){
                obj.category = self.helpers.getClassCategoryIdByName(cat);
            } else {
                const catId = self.vueGlobalProp.$_generateId();
                self.vueState.globalClassesCategories.push({
                    id: catId,
                    name: cat,
                })
                obj.category = catId;
            }
        }
        self.vueState.globalClasses.push(obj)
        self.populateClassCategories();

        return id;
    },
    importedClasses: function(){
        const self = this;
        let settingsHaveChanged = false;
        let existingClassesId = [];
        const globalClasses = self.vueState.globalClasses;
        const importedClasses = brxcImportedClasses || [];
        if (importedClasses.length > 0){
            importedClasses.forEach(e => {
                const existingCls = globalClasses.find(el => {
                    return el.name === e; 
                });
                if(existingCls){
                    existingClassesId.push({id: existingCls.id,name: existingCls.name});
               
                }
            })

            const importedClassesToCreate = importedClasses.filter(str => str && !existingClassesId.some(obj => obj && obj.hasOwnProperty('name') && obj.name === str));
            if (importedClassesToCreate.length > 0){
                importedClassesToCreate.forEach( e => {
                    self.generateGlobalClass('brxc_imported_',e,false);
                    settingsHaveChanged = true;

                })
            }
        }

        //Remove classes

        for (let i = 0; i < globalClasses.length; i++) { 
            const obj = globalClasses[i]; 
            const isImported = obj.id.includes('brxc_imported');  
            const isIncluded = importedClasses.includes(obj.name);
            if (isImported && isIncluded) {
                continue;
            } 
            if (isImported && !isIncluded) { 
                self.vueState.globalClasses.splice(i, 1);
                settingsHaveChanged = true;
                i--; 
            }
        }

        // Update DB
        if (settingsHaveChanged === true) {
            self.helpers.saveChanges('globalClasses');
            self.helpers.saveChanges('globalClassesLocked');
        }
    },
    gridUtilityAddNewClass: function(){
        const self = this;

        // Create Category
        const existingCategory = self.vueState.globalClassesCategories.find(el => el.id === "brxc_grid_utility_classes");
        if(!existingCategory){
            self.vueState.globalClassesCategories.push({
                id: 'brxc_grid_utility_classes',
                name: 'Grid Utility Classes'
            })
            self.helpers.saveChanges('globalClassesCategories');
        }

        // Add to global classes
        const classId = `brxc_grid_${self.vueGlobalProp.$_generateId()}`;
        const customCSS = `/* SCOPED VARIABLES */\n.new-grid-class {\n\t--grid-column-count: 3;\n\t--grid-item--min-width: 280px;\n\t--grid-layout-gap: 2rem;\n\tgrid-template-columns: repeat(auto-fit, minmax(min(100%, var(--grid-item--min-width)), 1fr))\n}\n\n/* RESPONSIVE CODE */\n@media screen and (min-width: 781px){\n\tbody .new-grid-class {\n\t\t--gap-count: calc(var(--grid-column-count) - 1);\n\t\t--total-gap-width: calc(var(--gap-count) * var(--grid-layout-gap));\n\t\t--grid-item--max-width: calc((100% - var(--total-gap-width)) / var(--grid-column-count));\n\t\tgrid-template-columns: repeat(auto-fill, minmax(max(var(--grid-item--min-width), var(--grid-item--max-width)), 1fr));\n\t}\n}`;

        self.vueState.globalClasses.push({
            id: classId,
            name: 'new-grid-class',
            category: 'brxc_grid_utility_classes',
            gridUtility: true,
            settings: {
                gridUtilityGap: '2rem',
                gridUtilityCols: '3',
                gridUtilityWidth: '280',
                _display: 'grid',
                _gridGap: 'var(--grid-layout-gap)',
                _cssCustom: customCSS,
            },
        })
        self.vueState.globalClassesLocked.push(classId);

        // Save to db
        self.helpers.saveChanges('globalClasses');
        self.helpers.saveChanges('globalClassesLocked');
        self.gridUtilityMount();
        
    },
    gridUtilityMount: function(){
        const self = this;
        const canvas = document.querySelector('#brxcGridUlilityCanvas');
        if(!canvas) return;
        
        const utilityClasses = self.vueState.globalClasses.filter(el => el.gridUtility === true);

        const content = utilityClasses.map(el => {
            const setings = el.settings;
            return `<tr data-id="${el.id}">
                <td><input type='text' value='${el.name}'></input></td>
                <td><input type='text' value='${setings.gridUtilityGap}'></input></td>
                <td><input type='number' value='${setings.gridUtilityCols}'></input></td>
                <td><input type='number' value='${setings.gridUtilityWidth}'></input></td>
                <td data-balloon='Move to Trash' data-balloon-pos='left'><i class='ti-trash' onclick='ADMINBRXC.deleteClass("${el.id}");ADMINBRXC.gridUtilityMount();'></i></td>
            </tr>`
        }).join('')

        canvas.innerHTML = content;

        // Listeners
        canvas.querySelectorAll('tr').forEach(row => {
            row.addEventListener('input', () => {
                const values = {
                    'id': row.dataset.id,
                    'name': self.helpers.formatForClasses(row.querySelectorAll('input')[0].value),
                    'gap': row.querySelectorAll('input')[1].value,
                    'cols': row.querySelectorAll('input')[2].value,
                    'width': row.querySelectorAll('input')[3].value,
                }
                const customCSS = `/* SCOPED VARIABLES */\n.${values.name} {\n\t--grid-column-count: ${values.cols};\n\t--grid-item--min-width: ${values.width}px;\n\t--grid-layout-gap: ${values.gap};\n\tgrid-template-columns: repeat(auto-fit, minmax(min(100%, var(--grid-item--min-width)), 1fr))\n}\n\n/* RESPONSIVE CODE */\n@media screen and (min-width: 781px){\n\tbody .${values.name} {\n\t\t--gap-count: calc(var(--grid-column-count) - 1);\n\t\t--total-gap-width: calc(var(--gap-count) * var(--grid-layout-gap));\n\t\t--grid-item--max-width: calc((100% - var(--total-gap-width)) / var(--grid-column-count));\n\t\tgrid-template-columns: repeat(auto-fill, minmax(max(var(--grid-item--min-width), var(--grid-item--max-width)), 1fr));\n\t}\n}`;
                const clsObj = utilityClasses.find(el => el.id === values.id);
                if (clsObj) {
                    Object.assign(clsObj, { name: values.name });
                    Object.assign(clsObj.settings, {
                        gridUtilityGap: values.gap,
                        gridUtilityCols: values.cols,
                        gridUtilityWidth: values.width,
                        _cssCustom: customCSS
                    });
                }
            })
        })
    },
    savePlainClasses: function(target,classes) {
        const self = this;
        let finalClasses = []
        let newClasses = [];
        const globalClasses = self.vueState.globalClasses;
        if (classes) {
           newClasses = classes.split(/\s+/).filter(word => word.trim() !== '').filter((value, index, array) => array.indexOf(value) === index);
        }
  
        if (newClasses.length > 0){
            newClasses.forEach(e => {
                const existingClass = Array.from(globalClasses).find(el => el && el.hasOwnProperty('id') && el.hasOwnProperty('name') && el.name === e);
                if(existingClass) {
                    finalClasses.push(existingClass.id);
                    return;
                }

                const id = self.vueGlobalProp.$_generateId();
                self.generateGlobalClass('', e, false, id);
                finalClasses.push(id)
            })
        }

        if(self.helpers.areElementsSelected()){
            self.vueState.selectedElements.forEach(el => {
                el.settings._cssGlobalClasses = [...new Set(finalClasses)];        
            })
        } else {
            self.builderStates.activeElement.settings._cssGlobalClasses = [...new Set(finalClasses)]; 
        }

        self.closeModal(target, target.target, '#brxcPlainClassesOverlay');

        self.stickyCssStates.forceMount = true;
        self.stickyCssStates.timeoutMount = true;

        setTimeout(() => {
            self.vueState.rerenderControls = Date.now();   
        }, 10);

        self.vueGlobalProp.$_showMessage('Classes updated!');
    },
    resetClasses: function(target){
        const self = this;
        self.savePlainClasses(target, '');
        const elementObj = self.builderStates.activeElement;
        if (typeof elementObj.settings !== "undefined" && elementObj.settings?.hasOwnProperty('_cssGlobalClasses')) delete elementObj.settings._cssGlobalClasses;
        self.closeModal(target, target.target, '#brxcPlainClassesOverlay');
        self.vueGlobalProp.$_showMessage('Classes reset successfully!');
    },
    mostUsedClasses: function(){
        const self = this;

        const counts = {};
        const contentArray = self.helpers.getContent() || [];
        const inputArray = [].concat(...contentArray.filter(el => el.settings?.hasOwnProperty('_cssGlobalClasses')).map(el => [...el.settings._cssGlobalClasses]));
        
        inputArray.forEach((element) => {
            counts[element] = (counts[element] || 0) + 1;
        });

        const sortedArray = inputArray.sort((a, b) => counts[b] - counts[a]);

        return [...new Set(sortedArray)];
    },
    closeModal: function(event, target, id, closeAllBtns = false){

        const self = this;
        if( event.target !== target ) {
            return;
        }
        if (typeof event.preventDefault === 'function') event.preventDefault();
        if (typeof event.stopPropagation === 'function') event.stopPropagation();
        const wrapper = document.querySelector(id);
        if(wrapper) wrapper.remove();
        self.closeTemplateModal();

        // Advanced CSS
        if( id === "#brxcCSSOverlay"){
            self.disableSelectorPicker();
        }

    },
    closeTemplateModal: function(){
        const self = this;
        const overlay = document.querySelector('#brxcRemoteTemplatesOverlay');
        if(overlay) {
            document.body.classList.remove('at-quick-remote-template');
            if(overlay) overlay.remove();
            self.topbarStates.tweaks.includes('zoom-out') ? self.zoomOut(false,true) : '';
        }
    },
    addLorem: function(target, btn) {
        const self = this;
        let used = parseInt(btn.dataset.used);
        let tempArr;
        let arr;
        (self.globalSettings['loremIpsumtype'] === 'human') ? tempArr = ADMINBRXC.globalSettings.customDummyContent.split('\n') : tempArr = ADMINBRXC.loremSentences;
        (used === tempArr.length) ? arr = tempArr : arr = tempArr.slice(used);
        
        target.value = `${target.value} ${arr[0]}`;
        
        (used === tempArr.length) ? btn.setAttribute('data-used', 1) : btn.setAttribute('data-used', used + 1);
        const event = new Event('input', {
            bubbles: true,
            cancelable: true,
        });
          
        target.dispatchEvent(event);
    },
    completionAPIRequest: function(prefix, global, overlay, target, history, n, json, type){
        const self = this;
        jQuery.ajax({
            type: 'POST',
            url: openai_ajax_req.ajax_url,
            data: {
                action: 'openai_ajax_function',
                nonce: openai_ajax_req.nonce
            },
            success: function(response) {
                const post = async () => {
                    const rawResponse = await fetch('https://api.openai.com/v1/chat/completions', {
                      method: 'POST',
                      headers: {
                          'Content-Type': 'application/json',
                          'Authorization' : 'Bearer '+ response,
                        },
                      body: JSON.stringify(json)
                    });
                    const content = await rawResponse.json();
                    if(content.error){
                        self.insertErrorMessage(prefix, global, overlay, content.error.message);
                        target.classList.remove('disable');
                    } else {
                        for(i=0; i<n;i++){
                            if(type === "chat"){
                                self.insertAIResponse(prefix, global, overlay, content.choices[i].message.content.trim(), i);
                            } else if(type === "edit"){
                                self.insertAIEditResponse(prefix, global, overlay, content.choices[i].message.content.trim(), i);
                            } else if(type === "code"){
                                self.insertAICodeResponse(prefix, global, overlay, content.choices[i].message.content.trim(), i);
                            }
                        }
                        target.classList.remove('disable');
                        history['assistant'] = content;
                        self.aihistory.push(history);
                    }
                };
                post();
            },
            error: function(response){
                console.log('Something went wrong with the OpenAI AJAX request: ' + response);
                target.classList.remove('disable');
            }
        });

    },
    whisperAPIRequest: function(prefix, global, overlay, target, history, audioBlob, ext, callback){
        const self = this;

        const formData = new FormData();
        formData.append('file', audioBlob, `audio.${ext}`);
        formData.append('model', 'whisper-1');
        formData.append('language', language);
        formData.append('temp', temp);

        jQuery.ajax({
            type: 'POST',
            url: openai_ajax_req.ajax_url,
            data: {
                action: 'openai_ajax_function',
                nonce: openai_ajax_req.nonce
            },
            success: function(response) {
                const post = async () => {
                    const rawResponse = await fetch('https://api.openai.com/v1/audio/transcriptions', {
                    method: 'POST',
                    headers: {
                        'Authorization' : 'Bearer '+ response,
                        },
                    body: formData
                    });
                    const content = await rawResponse.json();
                    if(content.error){
                        self.insertErrorMessage(prefix, global, overlay, content.error.message);
                        target.classList.remove('disable');
                    } else {
                        callback(content.text);
                        target.classList.remove('disable');
                        history['assistant']['text'] = content.text;
                        self.aihistory.push(history);
                    }
                };
                post();
            },
            error: function(response){
                console.log('Something went wrong with the OpenAI AJAX request: ' + response);
                target.classList.remove('disable');
            }
        });

    },
    TTSAPIRequest: function(prefix, global, overlay, target, history, input, voice, speed, callback){
        const self = this;
        const audioPlayer = document.querySelector('#brxcAudioPlayer');
        const finalVoice = voice || 'alloy';
        const finalSpeed = speed || 1;
        let json = {
            "model": "tts-1-hd", 
            "input": input,
            "voice": finalVoice,
            "speed": finalSpeed,
            "response_format": "mp3",
        };
        jQuery.ajax({
            type: 'POST',
            url: openai_ajax_req.ajax_url,
            data: {
                action: 'openai_ajax_function',
                nonce: openai_ajax_req.nonce
            },
            success: function(response) {
                callback(response, json);
            },
            error: function(response){
                console.log('Something went wrong with the OpenAI AJAX request: ' + response);
                target.classList.remove('disable');
            }
        });

    },
    generateAudioTranscription: function(prefix, target, global, overlay, language, temp){
        const self = this;
        const fileInput = document.querySelector('#brxcTTSInput');
        let history = [];

        target.classList.add('disable');
        function handleFileInput() {
            if (fileInput.files.length > 0) {
                const audioFile = fileInput.files[0];
                const filename = audioFile.name
                let last_dot = filename.lastIndexOf('.')
                let ext = filename.slice(last_dot + 1)
        
                // Read the contents of the selected file as a Blob
                const reader = new FileReader();
        
                reader.onload = function (loadEvent) {
                    const audioBlob = new Blob([loadEvent.target.result], { type: audioFile.type });

                    // API Request
                    history['user'] = {
                        date: Date.now(),
                        type: 'audio',
                        language: language,
                        temperature: temp,
                        message: 'Requested Audio Transcription.',
                    }  
                    history['assistant'] = {
                        text: '',
                    } 
                    self.whisperAPIRequest(prefix, global, overlay, target, history, language, temp, audioBlob, ext,  function (transcription) {
                        // Handle the transcription result, e.g., display it on the UI
                        const canvas = document.querySelector('#brxcTTSCanvas');
                        if(!canvas) return;
        
                        let content =  `<div class="brxc-ai-response-wrapper remove-on-reset">
                                            <input type="radio" id="brxc3SIfHu" name="global-openai-results">
                                            <label for="brxc3SIfHu" class="brxc-input__label">
                                                <p>OpenAI Assistant</p>
                                                <pre name="global-openai-prompt-response" class="message assistant" id="global-openaiPromptResponse">
                                                    <code>${transcription}</code>
                                                </pre>
                                            </label>
                                        </div>`;
                        canvas.innerHTML = content;
                    });
                };
        
                reader.readAsArrayBuffer(audioFile);
            }
        }
        handleFileInput()
    },
    generateAudioSpeech: function(prefix, target, global, overlay, input, voice, speed){
        const self = this;
        const audioPlayer = document.querySelector('#brxcAudioPlayer');
        let history = [];

        target.classList.add('disable');
        
        self.TTSAPIRequest(prefix, global, overlay, target, history, input, voice, speed, function (response, json) {
            var oHttp = new XMLHttpRequest();
                oHttp.open("POST", "https://api.openai.com/v1/audio/speech");
                oHttp.setRequestHeader("Accept", "audio/mp3");
                oHttp.setRequestHeader("Content-Type", "application/json");
                oHttp.setRequestHeader("Authorization", "Bearer " + response);

                oHttp.onload = function () {
                    if (oHttp.readyState === 4) {

                        var oBlob = new Blob([this.response], { "type": "audio/mp3" });
                        var audioURL = window.URL.createObjectURL(oBlob);
                        audioPlayer.src = audioURL;
                        audioPlayer.play();
                        target.classList.remove('disable');
                    }
                };

                oHttp.responseType = "arraybuffer";
                oHttp.send(JSON.stringify(json));
        });
    },
    getAIResponse: function(prefix, target, global = false, overlay, voiceTones, customToneVal, temp = 0, maxTokens = 15, n = 1, topP = 1, pres = 0, freq = 0, model){
        const self = this;
        target.classList.add('disable');
        let message = [];
        let history = [];
        let tones = [];
        let tone = '';
        if (voiceTones.length > 0){
            if(customToneVal && Array.from(voiceTones).filter(el => el && el.dataset.tone == 'custom').length > 0 && voiceTones.length === 1){
                tone = customToneVal;
            } else {
                let customTone = '';
                if(customToneVal && Array.from(voiceTones).filter(el => el && el.dataset.tone == 'custom').length > 0){
                    customTone = ' ' + customToneVal;
                };
                Array.from(voiceTones).filter(el => {
                    if (el.dataset.tone != 'custom'){
                        tones.push(el.dataset.tone);
                    }
                });
                tone = 'Adjust the tone of the text to be ' + tones.join(" and ") + '.' + customTone;
            }
            message.push({"role": "system", "content": tone});
        }
        const fmessages = document.querySelectorAll(overlay + ' .brxc-overlay__pannel.completion .message');
        fmessages.forEach(fmessage => {
            if(fmessage.classList.contains('user')){
                message.push({"role": "user", "content": fmessage.value});
            } else {
                message.push({"role": "assistant", "content": fmessage.textContent});
            }
        })
        history['user'] = {
                date: Date.now(),
                type: 'completion',
                system: tone,
                message: message[message.length - 1].content,
                maxTokens: maxTokens,
                choices: n,
                temperature: temp,
                top_p: topP,
                presence_penalty: pres,
                frequency_penalty: freq,
        }

        let json = {
            "model": model, 
            "messages": message,
            "max_tokens": maxTokens,
        };

        if (n != 1) json.n = n;
        if (temp != 1) json.temperature = Number.parseFloat(temp);
        if (topP != 1) json.top_p = Number.parseFloat(topP);
        if (pres != 0) json.presence_penalty = Number.parseFloat(pres);
        if (freq != 0) json.frequency_penalty = Number.parseFloat(freq);

        self.completionAPIRequest(prefix, global, overlay, target, history, n, json, 'chat');
    },
    getEditAIResponse: function(prefix, target, global = false, overlay, voiceTones, customToneVal, temp = 0, maxTokens, n = 1, topP = 1, pres = 0, freq = 0, model){
        const self = this;
        target.classList.add('disable');
        const instruction = document.querySelector(overlay + ' .brxc-overlay__pannel.edit .instruction').value;
        let message = [];
        let history = [];
        let tones = [];
        let tone = 'You are an helpful assistant.';
        if (voiceTones.length > 0){
            Array.from(voiceTones).filter(el => {
                if (el.dataset.tone != 'custom'){
                    tones.push(el.dataset.tone);
                }
            });
            tone += 'Adjust the tone of the text to be ' + tones.join(" and ") + '.';
        }
        message.push({"role": "system", "content": tone});

        const fmessages = document.querySelectorAll(overlay + ' .brxc-overlay__pannel.edit .message');
        fmessages.forEach(fmessage => {
            if(fmessage.classList.contains('user')){
                message.push({"role": "user", "content": `Here is the content: "${fmessage.value}". Here are the instructions: "${instruction}."`});
            } else if (fmessage.classList.contains('assistant')){
                message.push({"role": "assistant", "content": fmessage.textContent});
            }
        })
        history['user'] = {
                date: Date.now(),
                type: 'completion',
                system: tone,
                message: message[message.length - 1].content,
                maxTokens: maxTokens,
                choices: n,
                temperature: temp,
                top_p: topP,
                presence_penalty: pres,
                frequency_penalty: freq,
        }

        let json = {
            "model": model, 
            "messages": message,
            "max_tokens": maxTokens,
        };

        if (n != 1) json.n = n;
        if (temp != 1) json.temperature = Number.parseFloat(temp);
        if (topP != 1) json.top_p = Number.parseFloat(topP);
        if (pres != 0) json.presence_penalty = Number.parseFloat(pres);
        if (freq != 0) json.frequency_penalty = Number.parseFloat(freq);

        self.completionAPIRequest(prefix, global, overlay, target, history, n, json, 'edit');
    },
    getImageAIResponse: function(prefix, target,global = false, overlay, n = 1, size = "256x256"){
        const self = this;
        target.classList.add('disable');
        const prompt = document.querySelector(overlay + ' .brxc-overlay__pannel.image .message.input').value;
        let history = [];
        history['user'] = {
            date: Date.now(),
            type: 'images',
            message: prompt,
            choices: parseInt(n),
            sizes: size,
        }
        const api = () => {
            jQuery.ajax({
                type: 'POST',
                url: openai_ajax_req.ajax_url,
                data: {
                    action: 'openai_ajax_function',
                    nonce: openai_ajax_req.nonce
                },
                success: function(response) {
                    const post = async () => {
                        const rawResponse = await fetch('https://api.openai.com/v1/images/generations', {
                          method: 'POST',
                          headers: {
                              'Content-Type': 'application/json',
                              'Authorization' : 'Bearer '+ response,
                            },
                          body: JSON.stringify({
                            "prompt": prompt,
                            "n": n,
                            "size": size,
                            "response_format": "b64_json"
                            })
                        });
                        const content = await rawResponse.json();
                        if(content.error){
                            self.insertErrorMessage(prefix, global, overlay, content.error.message);
                            target.classList.remove('disable');
                        } else {
                            self.insertAIImagesResponse(prefix, global, overlay, content.data, n);
                            target.classList.remove('disable');
                            history['assistant'] = content;
                            self.aihistory.push(history);
                        }
                    };
                    post();
                },
                error: function(response){
                    console.log('Something went wrong with the OpenAI ImageAJAX request: ' + response);
                    target.classList.remove('disable');
                }
            });
        }
        api();
    },
    getCodeAIResponse: function(prefix, target, global = false, overlay, temp = 0, maxTokens, n = 1, topP = 1, pres = 0, freq = 0, model){
        const self = this;
        target.classList.add('disable');
        //const input = "/* Write The following request using CSS only (No HTML, Javavascript, SCSS or SASS). The request: " + document.querySelector(overlay + ' .brxc-overlay__pannel.code .input').value + " */";
        let history = [];
        let message = [{"role": "system", "content": "You are an helpful assistant and a CSS Expert. You just write vanilla CSS codes only (No HTML, Javavascript). Your entire response need to be valid CSS code, because the result is automatically inserted in CSS stylesheet."}];
        const fmessages = document.querySelectorAll(overlay + ' .brxc-overlay__pannel.code .message');
        fmessages.forEach(fmessage => {
            if(fmessage.classList.contains('user')){
                message.push({"role": "user", "content": `/* The following request is meant to be pasted in a CSS file AS IT, so comment any text accordingly. Here is the request: ${fmessage.value} */`});
            }
        })
        history['user'] = {
            date: Date.now(),
            type: 'code',
            message: message[message.length - 1].content,
            maxTokens: 4000,
            choices: n,
            temperature: temp,
            top_p: topP,
            presence_penalty: pres,
            frequency_penalty: freq,
        }

        let json = {
            "model": model, 
            "messages": message,
            "max_tokens": maxTokens,
        };

        if (n != 1) json.n = n;
        if (temp != 1) json.temperature = Number.parseFloat(temp);
        if (topP != 1) json.top_p = Number.parseFloat(topP);
        if (pres != 0) json.presence_penalty = Number.parseFloat(pres);
        if (freq != 0) json.frequency_penalty = Number.parseFloat(freq);

        self.completionAPIRequest(prefix, global, overlay, target, history, n, json, 'code');
    },
    insertErrorMessage: function(prefix, global, overlay, response){
        const self = this;
  
        const wrapper = document.querySelector(overlay + ' .brxc-overlay__error-message-wrapper');
        let inner = `<div class="brxc-ai-response-wrapper remove-on-reset">`;
        inner += `<div name="${prefix}-prompt-response" class="error-message" id="${prefix}ErrorMsg"><i class="bricks-svg ti-close" onClick="this.parentElement.parentElement.remove()"></i>OpenAI API returned an error with the following message: "${response}"</div></div>`;

        wrapper.innerHTML = inner;
        
    },
    saveAIImagetoMediaLibrary: function(target,imageUrl) {
        target.classList.add('disable');
        const api = () => {
            jQuery.ajax({
                type: 'POST',
                url: openai_ajax_req.ajax_url,
                data: {
                    action: 'openai_save_image_to_media_library',
                    nonce: openai_ajax_req.nonce,
                    image_url: imageUrl,
                },
                success: function(response) {
                    target.classList.remove('disable');
                    target.textContent = 'Image saved successfully!';
                    setTimeout(() => {
                            target.textContent = 'Save to Media Library';
                    }, 1000)
                },
                error: function(response) {
                    target.classList.remove('disable');
                    target.textContent = 'Error - Something went wrong!';
                    setTimeout(() => {
                            target.textContent = 'Save to Media Library';
                    }, 1000)
                },
            });
        }
        api();
    },
    downloadAIImage: function (src){
        const a = document.createElement("a");
        a.href = src;
        a.download = "AI-Image.png";
        a.click();
        a.remove();
    },
    resizeResourceImg: function(target){
        const panel = target.closest('.brxc-overlay__pannel');
        const img = panel.querySelector('.brxc-overlay__img img');
        img.style.scale = parseFloat(target.value);
    },
    movePanel: (wrapper, value) => {
        wrapper.style.transform = 'translateX(' + value + ')';
    },
    insertAIResponse: function (prefix, global, overlay, response, n){
        const self = this;
        const randClass = self.randomize(6);
        const wrapper = document.querySelector(overlay + ' .brxc-overlay__pannel.completion #' + prefix + 'InsertContentWrapper')
        const generateWrapper = document.querySelector(overlay + ' .brxc-overlay__pannel.completion #' + prefix + 'GenerateContentWrapper');
        generateWrapper.classList.toggle('active');
        let inner = `<div class="brxc-ai-response-wrapper remove-on-reset"><input type="radio" id="brxc${randClass}" name="openai-results"><label for="brxc${randClass}" class="brxc-input__label">`;
        if (n === 0 ) {
            inner += "<p>OpenAI Assistant</p>";
        }
        inner += `<pre name="${prefix}-prompt-response" class="message assistant" id="${prefix}PromptResponse"><code>${response}</code></pre></label></div>`;

        wrapper.insertAdjacentHTML(
            'beforebegin',
            inner
        );
        const radios = document.querySelectorAll('input[name="openai-results"]')
        radios[radios.length - 1].checked = true;
    },
    insertAIEditResponse: function (prefix, global, overlay, response, n){
        const self = this;
        const randClass = self.randomize(6);
        const wrapper = document.querySelector(overlay + ' .brxc-overlay__pannel.edit #' + prefix + 'InsertEditContentWrapper');
        const generateWrapper = document.querySelector(overlay + ' .brxc-overlay__pannel.edit #' + prefix + 'GenerateEditContentWrapper');
        generateWrapper.classList.toggle('active');
        let inner = `<div class="brxc-ai-response-wrapper remove-on-reset"><input type="radio" id="brxc${randClass}" name="${prefix}-edit-results"><label for="brxc${randClass}" class="brxc-input__label">`;
        if (n === 0 ) {
            inner += "<p>OpenAI Assistant</p>";
        }
        inner += `<pre name="${prefix}-prompt-response" class="message assistant" id="${prefix}PromptResponse"><code>${response}</code></pre></label></div>`;
        wrapper.insertAdjacentHTML(
            'beforebegin',
            inner
        );
        const radios = document.querySelectorAll('input[name="' + prefix + '-edit-results"]')
        radios[radios.length - 1].checked = true;
    },
    insertAIImagesResponse: function (prefix, global, overlay, response, n){
        const self = this;
        const wrapper = document.querySelector(overlay + ' .brxc-overlay__pannel.image #' + prefix + 'InsertImagesContentWrapper')
        const generateWrapper = document.querySelector(overlay + ' .brxc-overlay__pannel.image #' + prefix + 'GenerateImagesContentWrapper');
        generateWrapper.classList.toggle('active');
        inner = `<div class="brxc-ai-response-wrapper remove-on-reset">
                 <label class="brxc-input__label">OpenAI Assistant</label>
                 <div class='brxc__img-wrapper'>`;
        for(i = 0; i<n; i++){
            const randClass = self.randomize(6);
            inner += `<input type="radio" id="brxc${randClass}" name="${prefix}-images-results">
                  <label for="brxc${randClass}" class="brxc-input__label">
                    <img src="data:image/png;base64,${response[i].b64_json}" alt="" class="brxc__image" />
                  </label>`;         
        }
        inner += "</div></div>";
        wrapper.insertAdjacentHTML(
            'beforebegin',
            inner
        );
        const radios = document.querySelectorAll('input[name="' + prefix + '-images-results"]')
        radios[radios.length - 1].checked = true;
    },
    chatMoreAIResponse: function (prefix, global = false, overlay){
        const wrapper = document.querySelector(overlay + ' #' + prefix + 'InsertContentWrapper')
        wrapper.insertAdjacentHTML(
            'beforebegin',
            `<label for="${prefix}PromptText" class="brxc-input__label remove-on-reset">User Prompt (Required)</label><textarea name="${prefix}-prompt-text" id="${prefix}PromptText" class="${prefix}-prompt-text message user remove-on-reset" placeholder="Type your prompt text here..." cols="30" rows="3" spellcheck="false"></textarea>`
        );
        const container = document.querySelector(overlay + ' .brxc-overlay__pannel.completion')
        const btns = document.querySelector(overlay + ' .brxc-overlay__pannel.completion #' + prefix + 'GenerateContentWrapper')
        btns.classList.toggle('active');
        container.insertBefore(btns, wrapper);

    },
    resetAIresponses: (resets, removes, generate) => {
        resets.forEach(reset => {reset.value = ''});
        removes.forEach(el => {el.remove()});
        const generateWrapper = generate;
        generateWrapper.classList.add('active');
    },
    toggleCustomToneVoice: (prefix, custom) => {
        let input = document.querySelector('#' + prefix + 'System');
        if ( custom.checked==true ) {
            input.style.display = 'block';
        } else {
            input.style.display = 'none';
        }

    },
    mounAIHistory: function(prefix, overlay){
        const self = this;

        const canvas = document.querySelector(overlay + ' .brxc-overlay__pannel.history .brxc-canvas');
        if(!canvas) return;

        if (self.aihistory.length === 0) return canvas.innerHTML = "<p class='brxc__no-record'>No records yet. Please come back here after you generated some AI content.</p>"
        // wrapper
        canvas.classList.remove('empty');
        let inner = '<div class="isotope-wrapper--late" data-gutter="20" data-filter-layout="fitRows" style="--col:1">';
        //search
        inner += '<div class="brxc-overlay__search-box"><input type="text" class="iso-search" name="typography-search" placeholder="Type here to filter the history list" data-type="textContent"><div class="iso-search-icon"><i class="bricks-svg ti-search"></i></div><div class="iso-reset"><i class="bricks-svg ti-close"></i></div></div>';
        //container
        inner += '<div class="isotope-container">';
        if(self.aihistory.length < 1) return;
        const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });
        for(let i=0; i<self.aihistory.length; i++){
            const diff = self.aihistory[i]['user']['date'] - Date.now();
            let unit = "second";
            let divider = 1000;
            if (diff / 1000 < -59) {
                unit = "minute";
                divider = 60000;
            }
            if (diff / 1000 / 60 < -59) {
                unit = "hour";
                divider = 3600000;
            }
            if (diff / 1000 / 60 / 60 < -23) {
                unit = "day";
                divider = 86400000;
            }
            const time = rtf.format(Math.round(diff / divider), unit);
            inner += `
            <div class="brxc-ai-response-wrapper isotope-selector brxc-isotope__col">
                <input type="radio" id="brxcHistoryUser${i}" name="openai-results">
                <label for="brxcHistoryUser${i}" class="brxc-input__label">
                    <div class="brxc-history__header-wrapper">
                        <div class="brxc-history__header-wrapper--left">
                            <span><i class="fas fa-user"></i>You <span class="brxc__light">(${time})</span></span>
                        </div>
                        <div class="brxc-history__header-wrapper--right">`;
                            if(self.aihistory[i]['user']['type']){
                                inner += `
                                <div class="brxc-history__header-block" data-balloon="Category" data-balloon-pos="top">
                                    <i class="bricks-svg fas fa-tag"></i>
                                    <span>${self.aihistory[i]['user']['type']}</span>
                                </div>`;
                            }
                            if(self.aihistory[i]['user']['choices']){
                                inner += `
                                <div class="brxc-history__header-block" data-balloon="Choices" data-balloon-pos="top">
                                    <i class="bricks-svg fas fa-list-ul"></i>
                                    <span>${self.aihistory[i]['user']['choices']}</span>
                                </div>`;
                            }
                            if (self.aihistory[i]['user']['maxTokens']){
                                inner += `<div class="brxc-history__header-block" data-balloon="Max Tokens" data-balloon-pos="top">
                                    <i class="bricks-svg fas fa-traffic-light"></i>
                                    <span>${self.aihistory[i]['user']['maxTokens']} tokens</span>
                                </div>`;
                            }
                            if (typeof self.aihistory[i]['assistant']['usage'] != 'undefined'){
                                if(self.aihistory[i]['assistant']['usage']['prompt_tokens']){
                                inner += `<div class="brxc-history__header-block" data-balloon="Tokens used" data-balloon-pos="top">
                                    <i class="bricks-svg fas fa-dollar-sign"></i>
                                    <span>${self.aihistory[i]['assistant']['usage']['prompt_tokens']} tokens</span>
                                </div>`;
                                }
                            }
                        inner +=`</div>
                    </div>`;
                    
                    inner +=` <div name="${prefix}-prompt-response" class="message assistant">${self.aihistory[i]['user']['message']}</div>`;
                    
                inner +=`</label>`;
                if(self.aihistory[i]['user']['instruction']){
                    inner += `
                    <input type="radio" id="brxcHistoryInstruction${i}" name="openai-results">
                    <label for="brxcHistoryInstruction${i}" class="brxc-input__label">
                        <div name="${prefix}-prompt-response" class="message assistant">${self.aihistory[i]['user']['instruction']}</div>
                    </label>`;
                }
            inner += `</div>`;
            inner += '<div class="brxc-ai-response-wrapper isotope-selector brxc-isotope__col">';
            if(typeof self.aihistory[i]['assistant']['choices'] != 'undefined'){  
                for(let j=0; j<self.aihistory[i]['assistant']['choices'].length; j++){
                    
                    inner += `
                        <input type="radio" id="brxcHistoryAssistant${i + "c" +  j}" name="openai-results">
                        <label for="brxcHistoryAssistant${i + "c" +  j}" class="brxc-input__label">
                            <div class="brxc-history__header-wrapper">
                                <div class="brxc-history__header-wrapper--left">`
                                if(j===0) inner +=`<span><i class="fas fa-robot"></i>AI assistant <span class="brxc__light">(${time})</span></span>`;
                                inner +=`</div>
                                <div class="brxc-history__header-wrapper--right">`;
                                    if(j===0 && self.aihistory[i]['user']['temperature']){
                                        inner += `
                                        <div class="brxc-history__header-block" data-balloon="Temperature" data-balloon-pos="top">
                                            <i class="bricks-svg fas fa-temperature-empty"></i>
                                            <span>${self.aihistory[i]['user']['temperature']}</span>
                                        </div>`;
                                    }
                                    if(j===0 && self.aihistory[i]['user']['top_p']){
                                        inner += `
                                        <div class="brxc-history__header-block" data-balloon="Top Probability" data-balloon-pos="top">
                                            <i class="bricks-svg fas fa-arrow-up-1-9"></i>
                                            <span>${self.aihistory[i]['user']['top_p']}</span>
                                        </div>`;
                                    }
                                    if(j===0 && self.aihistory[i]['user']['presence_penalty']){
                                        inner += `
                                        <div class="brxc-history__header-block" data-balloon="Presence Penalty" data-balloon-pos="top">
                                            <i class="bricks-svg fas fa-signal"></i>
                                            <span>${self.aihistory[i]['user']['presence_penalty']}</span>
                                        </div>`;
                                    }
                                    if(j===0 && self.aihistory[i]['user']['frequency_penalty']){
                                        inner += `
                                        <div class="brxc-history__header-block" data-balloon="Frequency Penalty" data-balloon-pos="top">
                                            <i class="bricks-svg fas fa-wave-square"></i>
                                            <span>${self.aihistory[i]['user']['frequency_penalty']}</span>
                                        </div>`;
                                    }
                                    if (j===0 && typeof self.aihistory[i]['assistant']['usage'] != 'undefined' && self.aihistory[i]['assistant']['usage']['completion_tokens']){
                                        inner += `
                                        <div class="brxc-history__header-block" data-balloon="Tokens used" data-balloon-pos="top">
                                            <i class="bricks-svg fas fa-dollar-sign"></i>
                                            <span>${self.aihistory[i]['assistant']['usage']['completion_tokens']} tokens</span>
                                        </div>`;
                                    }
                                    inner += `</div>
                            </div>`;
                            if(self.aihistory[i]['user']['type'] === "completion" || self.aihistory[i]['user']['type'] === "code" || self.aihistory[i]['user']['type'] === "edit"){
                                inner += `<div name="${prefix}-prompt-response" class="message assistant">${self.aihistory[i]['assistant']['choices'][j]['message']['content'].trim()}</div>`;
                            } else {
                                inner += `<div name="${prefix}-prompt-response" class="message assistant">${self.aihistory[i]['assistant']['choices'][j]['text'].trim()}</div>`;
                            }
                        inner += '</label>';
                    
                }
            }
            if(self.aihistory[i]['user']['type'] === "images"){
                inner += `
                <input type="radio" id="brxcHistoryAssistant${i}" name="openai-results">
                <label for="brxcHistoryAssistant${i}" class="brxc-input__label">
                <div class="brxc-history__header-wrapper">
                    <div class="brxc-history__header-wrapper--left">
                        <span>AI assistant <span class="brxc__light">(${time})</span></span>
                    </div>
                </div>
                <div name="${prefix}-prompt-response" class="message assistant">I successfully generated ${self.aihistory[i]['user']['choices']} image(s)</div>`;
            }
            if(self.aihistory[i]['user']['type'] === "audio"){
                inner += `
                <input type="radio" id="brxcHistoryAssistant${i}" name="openai-results">
                <label for="brxcHistoryAssistant${i}" class="brxc-input__label">
                <div class="brxc-history__header-wrapper">
                    <div class="brxc-history__header-wrapper--left">
                        <span>AI assistant <span class="brxc__light">(${time})</span></span>
                    </div>`;
                    if(self.aihistory[i]['user']['temperature']){
                        inner += `
                        <div class="brxc-history__header-wrapper--right">
                            <div class="brxc-history__header-block" data-balloon="Temperature" data-balloon-pos="top">
                                <i class="bricks-svg fas fa-temperature-empty"></i>
                                <span>${self.aihistory[i]['user']['temperature']}</span>
                            </div>
                        </div>`;
                    }
                inner += `</div>
                <div name="${prefix}-prompt-response" class="message assistant">${self.aihistory[i]['assistant']['text']}</div>`;
            }
            inner += '</div>';
        }
        //end of container and wrapper
        inner += '</div></div>';

        canvas.innerHTML = inner;


        let filterRes = true;
        let filterSearch = true;
        let qsRegex
        let isotopeGutter;
        let isotopeLayoutHelper;
        const isotopeWrappers = document.querySelectorAll(overlay + ' .isotope-wrapper--late')
        isotopeWrappers.forEach(wrapper => {
            const isotopeContainers = wrapper.querySelectorAll('.isotope-container');
            isotopeContainers.forEach(isotopeContainer => {
                const isotopeSelector = wrapper.querySelectorAll('.isotope-selector');
                const isoSearch = wrapper.querySelector('input[type="text"].iso-search');
                const isoSearchType = isoSearch.dataset.type;
                const isoSearchReset = wrapper.querySelector('.iso-reset');
                if (wrapper.dataset.gutter) {
                    isotopeGutter = parseInt(wrapper.dataset.gutter);
                    wrapper.style.setProperty('--gutter', isotopeGutter + 'px');
                    isotopeSelector.forEach(elm => elm.style.paddingBottom = isotopeGutter + 'px');
                } else {
                    isotopeGutter = 0;
                };

                if (wrapper.dataset.filterLayout) {
                    isotopeLayoutHelper = wrapper.dataset.filterLayout;
                } else {
                    isotopeLayoutHelper = 'fitRows';
                };
                

                // init Isotope
                const isotopeOptions = {
                    itemSelector: '.isotope-selector',
                    layoutMode: isotopeLayoutHelper,
                    transitionDuration: 0,
                    filter: function(itemElem1, itemElem2) {
                        const itemElem = itemElem1 || itemElem2;
                        if(isoSearchType === "textContent") {
                            return qsRegex ? itemElem.textContent.match(qsRegex) : true;
                        } else {
                            filterSearch = qsRegex ? itemElem.getAttribute('title').match(qsRegex) : true;
                            return filterRes;
                        }
                    },
                };


                // Set the correct layout
                switch (isotopeLayoutHelper) {
                    case 'fitRows':
                    isotopeOptions.fitRows = {
                        gutter: isotopeGutter
                    };
                    break;
                    case 'masonry':
                    isotopeOptions.masonry = {
                        gutter: isotopeGutter
                    };
                    break;
                }

                // Search Filter
                const iso = new Isotope(isotopeContainer, isotopeOptions);
                
                if (isoSearch) {
                    isoSearch.addEventListener('keyup', self.debounce(() => {
                        qsRegex = new RegExp(isoSearch.value, 'gi');
                        iso.arrange();
                    }, 100));
                }
                if (isoSearchReset) {
                    isoSearchReset.onclick = () => {
                        isoSearch.value = '';
                        const clickEvent = new Event('keyup');
                        isoSearch.dispatchEvent(clickEvent);
                    }
                }



            })
            
        })
    },
    initGridGuide: function() {
        const self = this;
        const x = document.querySelector('#bricks-builder-iframe').contentWindow;
        const xGridWrapper = document.createElement('section');
        xGridWrapper.classList.add(...['brxc-grid-guide__wrapper','brxe-section']);
        const xGridContainer = document.createElement('div');
        xGridContainer.classList.add('brxe-container');
        const div = '<div></div>';
        xGridContainer.innerHTML += div.repeat(12);
        xGridWrapper.appendChild(xGridContainer);
        x.document.body.after(xGridWrapper);
        return xGridWrapper
    },
    gridGuide: function() {
        const self = this;
        const x = document.querySelector('#bricks-builder-iframe').contentWindow;
        let xGridWrapper = x.document.querySelector('.brxc-grid-guide__wrapper');
        
        if(!xGridWrapper) {
            xGridWrapper = self.initGridGuide()
        };

        const gridGuideActive = self.topbarStates.tweaks.includes('grid-guides')
        gridGuideActive === true ? xGridWrapper.classList.add('active') : xGridWrapper.classList.remove('active');
        
        self.initToolbar();
    },
    setGridGuideOptions: function(item){
        const self = this;
        const defaultObj = {
            col: 12,
            gap: "2rem",
            color: "#ff000024",
        }
        item.classList.contains('open') ? item.classList.remove('open') : item.classList.add('open');
        if(item.classList.contains('open')){
            const wrapper = document.createElement('div');
            wrapper.setAttribute('id', 'brxc-grid-guide-options__wrapper');
            let content = '';
            content += `<ul><div class="header"><span class="title">Grid Guide Options</span><span class="bricks-svg-wrapper save" data-balloon="Save" data-balloon-pos="top"><i class="fas fa-floppy-disk"></i></span><span class="bricks-svg-wrapper close" data-balloon="Close" data-balloon-pos="top"><svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><path d="M400,145.49l-33.49,-33.49l-110.51,110.51l-110.51,-110.51l-33.49,33.49l110.51,110.51l-110.51,110.51l33.49,33.49l110.51,-110.51l110.51,110.51l33.49,-33.49l-110.51,-110.51l110.51,-110.51Z" fill="currentColor"></path></svg></span></div>`;
            content += `<li class="head"><div class="empty"></div><span class="title-col">Columns</span><span class="title-gap">Gap</span><span class="title-color">Color</span></li>`;
            self.vueState.breakpoints.forEach(bp => {
                const arr = self.globalSettings.generalCats.gridGuide ? self.globalSettings.generalCats.gridGuide : [];
                const existing = arr.find(el => el && el.device === bp.key);
                const obj = existing ? existing : defaultObj;
                content += `<li data-device="${bp.key}">
                                <div class="input-grid-guide-device" data-balloon="${bp.label}" data-balloon-pos="top-left">${self.helpers.bpIcons(bp.icon)}</div>
                                <input type="number" min="1" max="12" value="${obj.col}"class="input-grid-guide col">
                                <input type="text" value="${obj.gap}" class="input-grid-guide gap">
                                <div class="input-grid-guide color-wrapper"><div style="background-color:${obj.color}" class="input-grid-guide color" data-color="${obj.color}"></div></div>
                            </li>`
            })
            content += `</ul>`
            wrapper.innerHTML = content
            const toolbar = document.querySelector('.brx-body.main')
            toolbar.appendChild(wrapper)
        } else{
            const wrapper = document.querySelector('#brxc-grid-guide-options__wrapper');
            wrapper?.remove();
            return;
        }

        // Close popup
        const wrapper = document.querySelector('#brxc-grid-guide-options__wrapper');
        const close = wrapper?.querySelector('.close');
        close?.addEventListener('click', () => {
            wrapper?.remove();
            item.classList.remove('open')
        })

        // Save
        const save = wrapper?.querySelector('.save');
        save?.addEventListener('click', () => {
            self.saveGridGuide();
        })

        // Color Picker
        const colors = wrapper.querySelectorAll('.input-grid-guide.color');
        colors.forEach(el => {
            let picker = new ColorPicker(el, el.dataset.color);
            el.addEventListener('colorChange', self.debounce((event) => {
                const color = event.detail.color.hsla;
                el.setAttribute('data-color', color);
                self.generateGridGuideArr();
                self.generateGridGuideCSS();
            }, 100))
        })

        // generate css
        const inputs = wrapper.querySelectorAll('input');
        inputs.forEach(input => {
            input.addEventListener('input', () => {
                self.generateGridGuideArr();
                self.generateGridGuideCSS();
            })
        })
        
    },
    saveGridGuide: function(){
        const self = this;
        const obj = self.globalSettings.generalCats.gridGuide;
        jQuery.ajax({
            url: openai_ajax_req.ajax_url,
            data: {
                action: 'save_grid_guide_ajax_function',
                nonce: openai_ajax_req.nonce,
                grid: obj,
            },
            method: "POST",
            success: function(data) {
                self.vueGlobalProp.$_showMessage('Grid options saved successfully!')
            },
            error: function(data) {
                self.vueGlobalProp.$_showMessage('Something went wrong - Grid options not saved.')
            }
        });
    },
    generateGridGuideArr: function(){
        const self = this;
        const wrapper = document.querySelector('#brxc-grid-guide-options__wrapper');
        if(!wrapper) return;
        const rows = wrapper.querySelectorAll('li:not(.head)');
        const arr = [];
        
        rows.forEach(row => {
            const col = row.querySelector('input[type="number"]').value;
            const gap = row.querySelector('input[type="text"]').value;
            const color = row.querySelector('.input-grid-guide.color').dataset.color;
            arr.push({
                device: row.dataset.device,
                col: col,
                gap: gap,
                color: color,
            })
        })
        self.globalSettings.generalCats.gridGuide = arr;
        return arr;
    },
    generateGridGuideCSS: function(){
        const self = this;
        let css = '';
        let arr = self.globalSettings.generalCats.gridGuide;
        const defaultObj = {
            col: 12,
            gap: "2rem",
            color: "#ff000024",
        }

        // Default values
        if(!arr){
            arr = [];
            self.vueState.breakpoints.forEach(bp => {
                defaultObj.device = bp.key;
                arr.push(defaultObj);
            })
            self.globalSettings.generalCats.gridGuide = JSON.stringify(arr);
        }
        if(typeof self.globalSettings.generalCats.gridGuide === "string") self.globalSettings.generalCats.gridGuide = JSON.parse(self.globalSettings.generalCats.gridGuide);
        arr = self.globalSettings.generalCats.gridGuide;
        self.vueState.breakpoints.forEach((bp,index) => {
            const existing = arr.find(el => el && el.device === bp.key)
            const item = existing ? existing : defaultObj;
            if(index === 0){
                css += `.brxc-grid-guide__wrapper>.brxe-container {
                    grid-template-columns: repeat(${item.col},1fr);
                    gap: ${item.gap};
                }
                .brxc-grid-guide__wrapper.active>.brxe-container>div {
                    background-color: ${item.color};
                }`;
            } else {
                const media = self.vueGlobalProp.$_isMobileFirst._value ? 'min' : 'max';
                const mediaValue = self.vueState.breakpoints[index].width;
                css += ` @media screen and (${media}-width: ${mediaValue}px){
                    .brxc-grid-guide__wrapper>.brxe-container {
                        grid-template-columns: repeat(${item.col},1fr);
                        gap: ${item.gap};
                    }
                    .brxc-grid-guide__wrapper.active>.brxe-container>div {
                        background-color: ${item.color};
                    }
                }`;
            }
        })
        const x = document.querySelector('#bricks-builder-iframe').contentWindow;
        let xStylesheet = x.document.querySelector('#brxc-grid-guide-css');
        if(!xStylesheet){
            const el = document.createElement('style');
            el.id = 'brxc-grid-guide-css';
            const xHead = x.document.head;
            xHead.appendChild(el);
        }
        xStylesheet = x.document.querySelector('#brxc-grid-guide-css');
        xStylesheet.innerHTML = css;
    },
    XCode: function() {
        const self = this;
        const x = document.querySelector('#bricks-builder-iframe').contentWindow;
        const els = x.document.querySelectorAll('body main *, body footer *, body header *, body .brx-popup.builder *');
        const xCodeActive = self.topbarStates.tweaks.includes('x-mode')
        if(xCodeActive){
            els.forEach(el=> {
                el.classList.add('x-mode-enabled');
            })
        } else {
            els.forEach(el=> {
                el.classList.remove('x-mode-enabled');
            })
        }
        self.initToolbar();
    },
    contrast: function() {
        const self = this;
        const x = document.querySelector('#bricks-builder-iframe').contentWindow;
        const contrastActive = self.topbarStates.tweaks.includes('contrast-checker')
        if(contrastActive){
            try { contrast.check(); } catch(e) { console.warn('Contrast checker error:', e); }
        } else {
            const failedEls = x.document.querySelectorAll('.brxc-contrast-failed');
            failedEls.forEach(el => el.classList.remove('brxc-contrast-failed'))
        }
        self.initToolbar();
    },
    darkMode: function (){
        const self = this;
        const darkmodeActive = self.colorStates.colorManagerMode === 'dark'
        self.colorStates.colorManagerMode = darkmodeActive ? 'light' : 'dark';
        
        self.generateColorCSS();
        self.generateBuilderCSS();
        self.setColorManager();
        const x = document.querySelector('#bricks-builder-iframe').contentWindow;
        const html = x.document.documentElement;
        (html && !darkmodeActive) ? html.setAttribute('data-theme', 'light') : html.setAttribute('data-theme', 'dark')
        self.initToolbar();
    },
    toggleStrictEditorView: function(){
        const self = this;
        self.strictEditorState = !self.strictEditorState;
        self.vueState.rerenderControls = Date.now();
        self.initToolbar();
    },
    addIconToFields: (tag, classes, attrArr, balloonText, balloonPosition, onClickFunction, dataUsed, htmlEl, target, appendMethod) => {
        const li = document.createElement(tag);
        li.classList.add(...classes.split(' '));
        if(balloonText) li.setAttribute('data-balloon', balloonText);
        if(balloonPosition) li.setAttribute('data-balloon-pos',balloonPosition);
        if(attrArr && attrArr.length > 0){
            attrArr.forEach(attr => {
                const label = attr[0];
                const value = attr[1];
                li.setAttribute(label, value);
            })
        }
        // if (attr) li.setAttribute(attr, attrValue);
        li.setAttribute('onclick', onClickFunction);
        (dataUsed === true) ? li.setAttribute('data-used', 0) : '';
        li.innerHTML = htmlEl;
        if(appendMethod === 'after'){
            target ? target.after(li) : console.log('No target to append child.') ;
        } else if (appendMethod === 'before'){
            target ? target.before(li) : console.log('No target to append child.') ;
        } else if (appendMethod === 'child'){
            target ? target.appendChild(li) : console.log('No target to append child.') ;
        } 
    },
    strictEditorState: false,
    setStrictEditorView: function() {
        const self = this;
        if(!self.builderStates.isElementActive) return;
        if(self.strictEditorState !== true || self.vueState.activePanelTab !== "content") {
            const existingCSS = document.querySelector('#brxcFullAccessStyles');
            if(existingCSS) existingCSS.remove();
            let icons = document.querySelectorAll('.brxc-toggle-strict-editor');
            icons.forEach(icon => icon.remove())
            icons = document.querySelectorAll('.brxc-toggle-strict-editor-disabled');
            icons.forEach(icon => icon.remove())
            return;
        };

        const elementObj = self.builderStates.activeElement;
        
        Promise.resolve().then(() => {
            const controls = self.vueGlobalProp.$_getElementConfig(elementObj.name).controls;
            const existingCSS = document.querySelector('#brxcFullAccessStyles');

            // Create style
            if(!existingCSS){
                const style = document.createElement('style');
                style.id = 'brxcFullAccessStyles';
                style.innerHTML =`[data-controlkey]{position: relative;}.control-inner:not(.control-inner .control-inner) > *:not(.has-setting, .brxc-toggle-strict-editor, label + [data-control]), .control > .description{margin-left: 22px;}.bricks-panel-controls .control{margin-right: 32px!important;}`;
                document.head.appendChild(style);
            }

            // Loop through all controls
            for(const key of Object.keys(controls)){
                if(controls[key].tab === "content" && !controls[key].hasOwnProperty('css')) {
                    // Query Target
                    const target = document.querySelector(`#bricks-panel-element [data-controlkey="${key}"] .control:not(.control-separator) .control-inner`);
                    if(!target) continue;

                    // Remove existing Icon
                    const icon = target.querySelector('.brxc-toggle-strict-editor');
                    if (icon) icon.remove();

                    const isFullAccess = controls[key].hasOwnProperty('fullAccess') && controls[key].fullAccess === true ? true : false
                    const toggle = isFullAccess === true ? `<div><i class="fas fa-toggle-off"></i></div>` : `<div><i class="fas fa-toggle-on"></i></div>`;
                    const balloon = isFullAccess === true ? 'Global Control OFF' : 'Global Control ON';

                    // Add Icon
                    self.addIconToFields(
                        'div',
                        'brxc-toggle-strict-editor',
                        false,
                        balloon,
                        'top-left',
                        `ADMINBRXC.toggleFullAccess('${key}')`,
                        false,
                        toggle,
                        target,
                        'child'
                    );

                    // Remove existing Icon
                    const iconVisible = target.querySelector('.brxc-toggle-strict-editor-disabled');
                    if (iconVisible) iconVisible.remove();

                    if(!isFullAccess){
                        const obj = elementObj.settings;

                        function isDisabled(){
                            return obj.hasOwnProperty('fullAccessDisable') && Array.isArray(obj.fullAccessDisable) && obj.fullAccessDisable.includes(key) === true ? true : false;
                        }

                        const isFullAccessDisable = isDisabled() ? true : false
                        const toggleVisible = isFullAccessDisable === true ? `<div><i class="fas fa-eye-slash"></i></div>` : `<div><i class="fas fa-eye"></i></div>`;
                        const balloonVisible = isFullAccessDisable === true ? 'Control Disabled' : 'Control Enabled';

                        // Add Icon
                        self.addIconToFields(
                            'div',
                            'brxc-toggle-strict-editor-disabled',
                            false,
                            balloonVisible,
                            'top-right',
                            `ADMINBRXC.toggleFullAccessVisibility('${key}')`,
                            false,
                            toggleVisible,
                            target,
                            'child'
                        );
                    }
                }
            }
        })     
    },
    toggleFullAccess: function(ctrlKey){
        const self = this;
        const elementObj = self.builderStates.activeElement;
        const name = elementObj.name;
        const control = self.vueGlobalProp.$_getElementConfig(name).controls[ctrlKey];
        const newValue = control.hasOwnProperty('fullAccess') && control.fullAccess === true ? 'false' : 'true';
        newValue === 'true' ? control.fullAccess = true : delete control.fullAccess;
        self.saveFullAccessBuilder(name, ctrlKey, newValue);
        self.vueState.rerenderControls = Date.now();

    },
    toggleFullAccessVisibility: function(ctrlKey){
        const self = this;
        const elementObj = self.builderStates.activeElement;
        const obj = elementObj.settings;

        function isDisabled(){
            return obj.hasOwnProperty('fullAccessDisable') && Array.isArray(obj.fullAccessDisable) && obj.fullAccessDisable.includes(ctrlKey) === true ? true : false;
        }

        if(isDisabled()){
            const index = obj.fullAccessDisable.indexOf(ctrlKey);
            obj.fullAccessDisable.splice(index, 1);
        } else {
            if(!obj.hasOwnProperty('fullAccessDisable')) obj.fullAccessDisable = [];
            obj.fullAccessDisable.push(ctrlKey)
        }

        self.vueState.rerenderControls = Date.now();

    },
    saveFullAccessBuilder: function(name, key, value){
        const self = this;
        if(!self.globalSettings.generalCats.hasOwnProperty('fullAccess')) self.globalSettings.generalCats.fullAccess = {};
        if(!self.globalSettings.generalCats.fullAccess.hasOwnProperty(name)) self.globalSettings.generalCats.fullAccess[name]= {};
        self.globalSettings.generalCats.fullAccess[name][key] = value;
    },
    saveFullAccessOptions: function(){
        const self = this;
        const obj = self.globalSettings.generalCats.fullAccess;
        jQuery.ajax({
            url: openai_ajax_req.ajax_url,
            data: {
                action: 'save_full_access_ajax_function',
                nonce: openai_ajax_req.nonce,
                fullAccess: obj,
            },
            method: "POST",
            success: function(data) {
                self.vueGlobalProp.$_showMessage('Strict Editor settings saved successfully!')
            },
            error: function(data) {
                self.vueGlobalProp.$_showMessage('Something went wrong - Strict Editor settings not saved.')
            }
        });
    },
    autoformat: function(input, control){
        const self = this;
        if(typeof input === "undefined" || typeof input.value === "undefined") return;

        let values, operators;
        const rootFontSize = self.helpers.getRootFontSize();

        // Clamp()
        if(
            Object.values(self.globalSettings.autoFormatFunctions).includes("clamp") &&
            input.value.includes('|') &&
            Number.isFinite(Number(input.value.split('|')[0])) &&
            Number.isFinite(Number(input.value.split('|')[1]))
        ){
            const arr = input.value.split('|');
            const minSize = parseInt(arr[0]);
            const maxSize = parseInt(arr[1]);
            const minWidthPx = (arr[2] && typeof parseInt(arr[2]) === "number") ? parseInt(arr[2]) : false;
            const maxWidthPx = (arr[3] && typeof parseInt(arr[3]) === "number") ? parseInt(arr[3]) : false;
            input.value = self.helpers.clampBuilder(minSize, maxSize, minWidthPx, maxWidthPx);

            return;
        }

        // Autoclose Brackets for Variables
        if(Object.values(self.globalSettings.autoFormatFunctions).includes("close-var-bracket") && !input.value.includes('clamp(')){
            const countOpenBrackets = self.helpers.countCharacter(input.value, '(');
            const countCloseBrackets = self.helpers.countCharacter(input.value, ')');
            if(countOpenBrackets !== countCloseBrackets){
                values = input.value.split(' ');
                for (let i = 0; i < values.length; i++) {
                    const value = values[i];
                    if (value.includes('var(') && !(value.endsWith(')') || value.endsWith(')!important'))) {
                        values[i] = `${value})`;
                    }
                }
                input.value = values.join(' ');
            }
        }

        // Var()
        if(Object.values(self.globalSettings.autoFormatFunctions).includes("var") && !input.value.includes('clamp(')){
            values = input.value.split(' ');
            for (let i = 0; i < values.length; i++) {
                const value = values[i];
                if (!value.includes('var(') && value.includes('--') && !(value.endsWith(')') || value.endsWith(')!important'))) {
                    values[i] = `${value.replace('--', 'var(--')})`;
                }
            }
            input.value = values.join(' ');
        }

        // Px to rem
        if(Object.values(self.globalSettings.autoFormatFunctions).includes("px-to-rem") && !input.value.includes('clamp(')){
            if(input.value.includes('r:') ){
                values = input.value.split(' ');
                for (let i = 0; i < values.length; i++) {
                    if(values[i].includes("r:") ){
                        const valueToConvert = values[i].split(':')[1].replace('px','');
                        values[i] = `${(valueToConvert / rootFontSize).toFixed(3).toString().replace(/(\.[0-9]*[1-9])0+$|\.0*$/, '$1')}rem`;
                    }
                }
                input.value = values.join(' ');
            }
        }

        // Min()
        if(Object.values(self.globalSettings.autoFormatFunctions).includes("min") && !input.value.includes('clamp(')){
            if(input.value.includes(' < ') ){
                values = input.value.split(' ');
                for (let i = 0; i < values.length; i++) {
                    if(values[i] === "<" && values[i-1] && values[i+1]){
                        const min = values[i-1];
                        const max = values[i+1];
                        values[i] = `min(${min},${max})`;
                        values[i-1] = '';
                        values[i+1] = '';
                    }
                }
                input.value = values.join(' ').replace(/ min\(([^)]*)\) /g, "min($1)");
            }
        }

        // Max()
        if(Object.values(self.globalSettings.autoFormatFunctions).includes("max") && !input.value.includes('clamp(')){
            if(input.value.includes(' > ') ){
                values = input.value.split(' ');
                for (let i = 0; i < values.length; i++) {
                    if(values[i] === ">" && values[i-1] && values[i+1]){
                        const min = values[i-1];
                        const max = values[i+1];
                        values[i] = `max(${min},${max})`;
                        values[i-1] = '';
                        values[i+1] = '';
                    }
                }
                input.value = values.join(' ').replace(/ max\(([^)]*)\) /g, "max($1)");
            }  
        }
        
        // Calc()
        const excludedControls = ['_gridItemColumnSpan', '_gridItemRowSpan'];
        if(Object.values(self.globalSettings.autoFormatFunctions).includes("calc") && !input.value.includes('clamp(') && (control === "custom" || !excludedControls.includes(control.dataset.controlkey))){
            operators = [' + ',' - ',' * ',' / '];
            function formatCalc(expression) {
                const containsOperator = operators.some(operator => operator && expression.includes(operator));
                if (expression.includes('calc(') || expression.includes('clamp(') ) {
                    return expression;
                }

                if (containsOperator) {
                    return `calc(${expression})`;
                }
            
                return expression;
            }

            input.value = formatCalc(input.value);
        }
    },
    setTextShortcutsWrapper: function(){
        const self = this;
        const panel = document.querySelector("#bricks-panel-element");

        if(
            self.vueState.activePanel === "element"
            && self.vueState.activePanelTab === "content"
            && (
                Object.values(self.globalSettings.elementFeatures).includes("lorem-ipsum") // lorem
                || self.helpers.isAIActive() && self.globalSettings.isAIApiKeyEmpty !== "" // AI
            )
        ){
            Promise.resolve().then(() => {
                self.fields['loremIpsum']['includedFields'].forEach(field => {
                    let elements;
                    if (typeof field === 'string') {
                        elements = Array.from(document.querySelectorAll(field));
                    } else {
                        const filteredElements = Array.from(document.querySelectorAll(field.selector));
                        elements = filteredElements.filter(el =>
                            el && el.querySelector(field.hasChild)
                        );
                    }
        
                    const wrappers = elements.filter(
                        item => item &&
                            !item.parentNode.querySelector(self.fields['loremIpsum']['excludedFields']) &&
                            !item.parentNode.closest(self.fields['loremIpsum']['excludedFields'])
                    );
                    if (wrappers.length < 1) return;
                    let padding = 30;
                    if (Object.values(self.globalSettings.elementFeatures).includes("lorem-ipsum")) padding += 25;
                    if (self.helpers.isAIActive() && self.globalSettings.isAIApiKeyEmpty !== "") padding += 25;
                    wrappers.forEach(wrapper => {
                        if(!wrapper.querySelector('.brxc-icon-wrapper')){
                            const div = document.createElement('DIV');
                            div.classList.add('brxc-icon-wrapper');
                            wrapper.appendChild(div);
                            const input = wrapper.querySelector('input');
                            if (input) input.style.paddingRight = `${padding}px`;
                        } 
                        
                    })
                })
            })
        }
    },
    addDynamicLoremIcon: function() {
        const self = this;
        Promise.resolve().then().then(() => {
            self.fields['loremIpsum']['includedFields'].forEach(field => {
                let elements;
                if (typeof field === 'string') {
                    elements = Array.from(document.querySelectorAll(field));
                } else {
                    // Get elements with the selector
                    const filteredElements = Array.from(document.querySelectorAll(field.selector));
    
                    // Check if they have the specified child element
                    elements = filteredElements.filter(el =>
                        el && el.querySelector(field.hasChild)
                    );
                }
    
                const wrappers = elements.filter(
                    item => item &&
                        !item.parentNode.querySelector(self.fields['loremIpsum']['excludedFields']) &&
                        !item.parentNode.closest(self.fields['loremIpsum']['excludedFields'])
                );
                if (wrappers.length < 1) return;
                wrappers.forEach(wrapper => {
                    const inputs = wrapper.querySelectorAll('.brxc-toggle-lorem');
                    if (inputs.length > 0) return;
                    const textWrapper = wrapper.querySelector('.brxc-icon-wrapper')
                    if (!textWrapper) return;
                    self.addIconToFields(
                        'div',
                        'brxc-toggle-lorem',
                        false,
                        'Add Dummy Content',
                        'top-right',
                        'ADMINBRXC.addLorem(event.target.parentElement.parentElement.querySelector("textarea,input"), this)',
                        true,
                        "<div class='lorem-wrapper'><div class='lorem-line lorem-line-1'></div><div class='lorem-line lorem-line-2'></div><div class='lorem-line lorem-line-3'></div>",
                        textWrapper,
                        'child'
                    );
                });
            });
        });
    },
    addDynamicAIIcon: function() {
        const self = this;
        Promise.resolve().then().then(() => {
            self.fields['openAI']['includedFields'].forEach(field => {
                let elements;
                if (typeof field === 'string') {
                    elements = Array.from(document.querySelectorAll(field));
                } else {
                    // Get elements with the selector
                    const filteredElements = Array.from(document.querySelectorAll(field.selector));
    
                    // Check if they have the specified child element
                    elements = filteredElements.filter(el =>
                        el && el.querySelector(field.hasChild)
                    );
                }
    
                const wrappers = elements.filter(
                    item => item &&
                        !item.parentNode.querySelector(self.fields['openAI']['excludedFields']) &&
                        !item.parentNode.closest(self.fields['openAI']['excludedFields'])
                );
                if (wrappers.length < 1) return;
                wrappers.forEach(wrapper => {
                    const inputs = wrapper.querySelectorAll('.brxc-toggle-ai');
                    if (inputs.length > 0) return;
                    const textWrapper = wrapper.querySelector('.brxc-icon-wrapper')
                    if (!textWrapper) return;
                    self.addIconToFields(
                        'div',
                        'brxc-toggle-ai',
                        false,
                        'Add AI Content',
                        'top-right',
                        'ADMINBRXC.openAIModal("openai",false,event.target.parentElement.parentElement.querySelector("textarea,input"), "#brxcopenAIOverlay" )',
                        false,
                        "<div class='ai-wrapper'><span class='ai-text'>AI</span></div>",
                        textWrapper,
                        'child'
                    );
                });
            });
        });
    },
    headerIconsState: function(){
        const self = this;
        if(!self.builderStates.isElementActive) return;

        const action = document.querySelector('#bricks-panel-element .actions');
        const elementObj = self.builderStates.activeElement;
        const activeElSettings = self.builderStates.isClassActive ? self.vueState.globalClasses.find(el => el && el.id === self.vueState.activeClass.id)?.settings :  elementObj.settings;
        const isActive = (string, obj) => {
            for (const key in obj) {
                if (JSON.parse(JSON.stringify(key)).indexOf(string) !== -1) {
                  return true;
                }
            }
            return false;
        }
        const states = ['hover', 'before', 'active', 'focus', 'after'];
        states.forEach(state => {
            const item = action.querySelector(`.brxc-header-icon.brxc-header-icon__${state}`);
            if(!item) return;
            item.classList.remove('highlight');
            if(isActive(`:${state}`, activeElSettings)) item.classList.add('highlight');
        })

        //css Icon
        const cssIcon = action.querySelector(`.brxc-header-icon.brxc-header-icon__css-shortcut`);
        if(!cssIcon) return;
        //cssIcon.classList.remove('highlight');

        let hasSettings = false;
        for(const key of Object.keys(activeElSettings)){
            if(key.startsWith('_cssCustom')) hasSettings = true;
        }
        hasSettings ? cssIcon.classList.add('highlight') : cssIcon.classList.remove('highlight');

    },
    addPanelHeaderIcons: function(){
        const self = this;

        // Const
        const wrapper = document.querySelector('#bricks-panel-inner #bricks-panel-header ul.actions')
        if (!wrapper) return;

        const icons = wrapper.querySelectorAll('li.brxc-header-icon');

        // Component
        if(self.helpers.isComponentPanelOpen()){
            icons.forEach(icon => icon.remove());
            return;
        }

        if(!self.builderStates.isElementActive) return;

        const elementObj = self.builderStates.activeElement;

        const extendIcon = wrapper.querySelector('.brxc-header-icon__extend');
        const findReplaceIcon = wrapper.querySelector('.brxc-header-icon__find-replace');
        const cssIcon = wrapper.querySelector('.brxc-header-icon__css-shortcut');
        const styleOverviewIcon = wrapper.querySelector('.brxc-header-icon__style-overview');
        const openClassIcon = wrapper.querySelector('.brxc-header-icon__show-class-manager');
        const modifiedModeIcon = wrapper. querySelector('.brxc-header-icon__modified-mode')
        const goToParentIcon = wrapper.querySelector('.brxc-header-icon__parent');
        const pseudoState = self.vueState.pseudoClassActive;

        // Remove Icons
        if(openClassIcon) openClassIcon.remove();
        if(goToParentIcon) goToParentIcon.remove();
        if(modifiedModeIcon) modifiedModeIcon.remove();


        // Active State
        icons.forEach(icon => {
            icon.classList.remove('active');
            icon.dataset.balloon === pseudoState ? icon.classList.add('active') : '';
        });

        // Extend Styles & Classes
        if (!extendIcon && Object.values(self.globalSettings.elementShortcutIcons).includes("extend-classes")) {
            wrapper ? self.addIconToFields('li','brxc-skip-remount brxc-header-icon brxc-header-icon__extend', false, 'Extend Classes & Styles', 'bottom-right', 'ADMINBRXC.openExtendClassModal(event,"#brxcExtendModal")', true, '<span class="bricks-svg-wrapper"><svg xmlns="http://www.w3.org/2000/svg" class="bricks-svg" viewBox="0 96 960 960"><path d="M145 1022v-95h670v95H145Zm337-125L311 726l58-59 72 72V413l-72 72-58-59 171-171 172 171-59 59-72-72v326l72-72 59 59-172 171ZM145 225v-95h670v95H145Z"/></svg></span>', wrapper, 'child') : '';
        }

        // Find & replace
        if (!findReplaceIcon && Object.values(self.globalSettings.elementShortcutIcons).includes("find-and-replace")) {
            wrapper ? self.addIconToFields('li','brxc-skip-remount brxc-header-icon brxc-header-icon__find-replace', false, 'Find & Replace Styles', 'bottom-right', 'ADMINBRXC.openFindReplaceModal(event,false, "#brxcFindReplaceModal")', true, '<span class="bricks-svg-wrapper"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 96 960 960" class="bricks-svg"><path xmlns="http://www.w3.org/2000/svg" d="M138 484q18-110 103.838-182T440 230q75 0 133 30.5t98 82.5v-98h72v239H503v-71h100q-27-42-70.5-65T440 325q-72.187 0-130.093 43.5Q252 412 234 484h-96Zm674 492L615 780q-34 27-78 43.5T440.217 840Q367 840 308.5 813 250 786 209 734v93h-72V588h240v71H271q28.269 41.15 72.541 64.075Q387.812 746 440 746q72.102 0 127.444-44.853T642 588h96q-5 33-19 65.5T684 713l197 196-69 67Z"/></svg></span>', wrapper, 'child') : '';
        }

        
        // Pseudo Icons
        if(Object.values(self.globalSettings.elementShortcutIcons).includes("pseudo-shortcut") && self.globalSettings.shortcutsIcons.length > 0){
            if (Object.values(self.globalSettings.shortcutsIcons).includes('hover')){
                if(!self.vueState.pseudoClasses.includes(':hover')) self.vueState.pseudoClasses.push(':hover')
                const hoverIcon = document.querySelector('#bricks-panel-inner #bricks-panel-header ul.actions .brxc-header-icon__hover');
                if (!hoverIcon) {
                    self.addIconToFields('li','brxc-skip-remount brxc-header-icon brxc-header-icon__hover', false, ':hover', 'bottom-right', 'ADMINBRXC.setHeaderState("li.brxc-header-icon__hover", ":hover");', true, '<span class="bricks-svg-wrapper"><i class="fas fa-arrow-pointer"></i></span>', wrapper, 'child');
                }
            }
            if (Object.values(self.globalSettings.shortcutsIcons).includes('before')){
                if(!self.vueState.pseudoClasses.includes(':before')) self.vueState.pseudoClasses.push(':before')
                const beforeIcon = document.querySelector('#bricks-panel-inner #bricks-panel-header ul.actions .brxc-header-icon__before');
                if (!beforeIcon) {
                    self.addIconToFields('li','brxc-skip-remount brxc-header-icon brxc-header-icon__before', false, ':before', 'bottom-right', 'ADMINBRXC.setHeaderState("li.brxc-header-icon__before", ":before");', true, '<span class="bricks-svg-wrapper"><svg class="bricks-svg" viewBox="0 0 24 24"><path d="M5 20h14v-2H5v2zM19 9h-4V3H9v6H5l7 7 7-7z"></path></svg></span>', wrapper, 'child');
                }
            }
            if (Object.values(self.globalSettings.shortcutsIcons).includes('after')){
                if(!self.vueState.pseudoClasses.includes(':after')) self.vueState.pseudoClasses.push(':after')
                const afterIcon = document.querySelector('#bricks-panel-inner #bricks-panel-header ul.actions .brxc-header-icon__after');
                if (!afterIcon) {
                    self.addIconToFields('li','brxc-skip-remount brxc-header-icon brxc-header-icon__after', false, ':after', 'bottom-right', 'ADMINBRXC.setHeaderState("li.brxc-header-icon__after", ":after");', true, '<span class="bricks-svg-wrapper"><svg class="bricks-svg" viewBox="0 0 24 24"><path d="M5 20h14v-2H5v2zM19 9h-4V3H9v6H5l7 7 7-7z"></path></svg></span>', wrapper, 'child');
                }
            }
            if (Object.values(self.globalSettings.shortcutsIcons).includes('active')){
                if(!self.vueState.pseudoClasses.includes(':active')) self.vueState.pseudoClasses.push(':active')
                const activeIcon = document.querySelector('#bricks-panel-inner #bricks-panel-header ul.actions .brxc-header-icon__active');
                if (!activeIcon) {
                    self.addIconToFields('li','brxc-skip-remount brxc-header-icon brxc-header-icon__active', false, ':active', 'bottom-right', 'ADMINBRXC.setHeaderState("li.brxc-header-icon__active", ":active");', true, '<span class="bricks-svg-wrapper"><i class="fas fa-toggle-on"></span>', wrapper, 'child');
                }
            }
            if (Object.values(self.globalSettings.shortcutsIcons).includes('focus')){
                if(!self.vueState.pseudoClasses.includes(':focus')) self.vueState.pseudoClasses.push(':focus')
                const focusIcon = document.querySelector('#bricks-panel-inner #bricks-panel-header ul.actions .brxc-header-icon__focus');
                if (!focusIcon) {
                    self.addIconToFields('li','brxc-skip-remount brxc-header-icon brxc-header-icon__focus', false, ':focus', 'bottom-right', 'ADMINBRXC.setHeaderState("li.brxc-header-icon__focus", ":focus");', true, '<span class="bricks-svg-wrapper"><i class="fas fa-crosshairs"></span>', wrapper, 'child');
                }
            }
        }

        // CSS Shortcut
        if(!cssIcon && Object.values(self.globalSettings.elementShortcutIcons).includes("css-shortcut")){
            wrapper ? self.addIconToFields('li',`brxc-skip-remount brxc-header-icon brxc-header-icon__css-shortcut`, false, 'Element\s CSS', 'bottom-right', 'ADMINBRXC.cssShortcut()', true, '<span class="bricks-svg-wrapper"><i class="fab fa-css3-alt"></i></span>', wrapper, 'child') : '';
        }

        // Style Overview
        if (!styleOverviewIcon && Object.values(self.globalSettings.elementShortcutIcons).includes("style-overview-shortcut")) {
            wrapper ? self.addIconToFields('li','brxc-skip-remount brxc-header-icon brxc-header-icon__style-overview', false, 'Open in Style Overview', 'bottom-right', `ADMINBRXC.openModal({target: false, id: "#brxcStyleOverviewOverlay", focus: "#brxcStyleOverviewOverlay input[type=text]", callback: () => {ADMINBRXC.styleOverviewInit(ADMINBRXC.helpers.getFinalObject(true),true);}});`, true, '<span class="bricks-svg-wrapper"><i class="fas fa-table-list"></span>', wrapper, 'child') : '';
        }

        // Modified Mode
        if (Object.values(self.globalSettings.elementShortcutIcons).includes("modified-mode")) {
            self.addIconToFields('li',`brxc-skip-remount brxc-header-icon brxc-header-icon__modified-mode${self.modifiedModeStates.active? ' active' : ''}`, false, 'Modified Mode', 'bottom-right', `ADMINBRXC.toggleModifiedMode()`, true, '<span class="bricks-svg-wrapper"><i class="ti-settings"></span>', wrapper, 'child');
        }

        // Open in Class Manager
        if (self.builderStates.isClassActive && Object.values(self.globalSettings.elementShortcutIcons).includes("class-manager-shortcut")) {
            self.addIconToFields('li','brxc-skip-remount brxc-header-icon brxc-header-icon__show-class-manager', false, 'Show Class in Manager', 'bottom-right', `ADMINBRXC.openClassInManager('${self.vueState.activeClass.id}')`, true, '<span class="bricks-svg-wrapper"><i class="ion-md-options"></span>', wrapper, 'child');
        }

        // Go to Parent
        if (Object.values(self.globalSettings.elementShortcutIcons).includes("parent-shortcut") && typeof elementObj !== "undefined" && elementObj.hasOwnProperty('parent') && elementObj.parent != 0) {
            self.addIconToFields('li','brxc-skip-remount brxc-header-icon brxc-header-icon__parent', false, 'Go to Parent Element', 'bottom-right', 'ADMINBRXC.goToParentElement()', true, '<span class="bricks-svg-wrapper"><i class="fas fa-arrow-turn-up"></span>', wrapper, 'child');
        }
    },
    modifiedModeStates: {
        active: 0,
    },
    modifiedMode: function(){
        const self = this;
        if(!self.modifiedModeStates.active) return;

        self.vueState.searchControlModified = true;
    },
    toggleModifiedMode: function(){
        const self = this;
        self.modifiedModeStates.active = !self.modifiedModeStates.active;
        if(!self.modifiedModeStates.active){
            self.vueState.searchControlModified = false;
        }
        self.vueState.rerenderControls = Date.now();
    },
    openClassInManager: function(classId){
        const self = this;
        self.states.classManagerActiveClass = classId;
        const obj = self.vueGlobalProp.$_getGlobalClass(classId);
        self.states.classManagerActiveCategory = obj && obj.hasOwnProperty('category') && obj.category ? obj.category : 'All';
        self.openClassManager("global");
    },
    cssShortcut: function(){
        const self = this;

        // Remove panels
        self.vueState.showConditions = false;
        self.vueState.showInteractions = false;

        // Set panel
        self.vueState.activePanelTab = "style";
        setTimeout(() => self.vueState.activePanelGroup = "_css", 0);
    },
    goToParentElement: function(){
        const self = this;
        if(!self.builderStates.isElementActive) return;

        const parentId = self.vueState.activeElement.parent;
        const isComponent = self.vueGlobalProp.$_getComponentById(parentId);

        if(typeof isComponent === "object"){
            document.querySelector('#bricks-structure .structure-item').click();
        } else {
            self.vueState.activeId = parentId; 
        }
    },
    setHeaderState: function(target, text) {
        const self = this;
        if(!self.builderStates.isElementActive) return;
        const icons = document.querySelectorAll('#bricks-panel-header ul.actions li')
        const icon = document.querySelector('#bricks-panel-header ' + target);

        // Remove panels
        self.vueState.showConditions = false;
        self.vueState.showInteractions = false;

        // If icon is active
        if (icon.classList.contains('active')){
            self.vueState.pseudoClassPopup = undefined;
            self.vueState.pseudoClassActive = undefined;
            icons.forEach(li => li.classList.remove('active'));
            return;
        }

        // If Icon is inactive
        icons.forEach(li => li.classList.remove('active'));
        icon.classList.add('active');
        const pseudoList = self.vueState.pseudoClasses;
        let isPseudoMatching = false;
        for(var i=0; i<pseudoList.length; i++) {
            if(pseudoList[i].indexOf(text)!=-1) {
                isPseudoMatching = true;
            }
        }
        if (isPseudoMatching === true){
            self.vueState.pseudoClassPopup = true;
            self.vueState.pseudoClassActive = text
        }
    },
    setDynamicColorOnHover: function(){
        const self = this;

        if(!self.builderStates.isElementActive) return;

        const elementObj = self.builderStates.activeElement;
        if(!elementObj || !elementObj.hasOwnProperty('settings')) return;

        function setColor(actives) {
            const controls = [['typography', 'color'], ['background', 'backgroundColor'], ['border', 'borderColor']];
        
            self.fields['colorsOnHover']['includedFields'].forEach(field => {
                const colors = document.querySelectorAll(field);
        
                colors.forEach(color => {
                    color.addEventListener('mouseenter', () => {
                        controls.forEach(control => {
                            const closestControl = color.closest(`[data-control=${control[0]}]`);
                            if (closestControl) {
                                const rgb = window.getComputedStyle(color.childNodes[0], null).getPropertyValue('background-color');
                                applyColor(actives, control[1], rgb);
                            }
                        });
                    });
        
                    color.addEventListener('mouseleave', () => {
                        controls.forEach(control => {
                            const closestControl = color.closest(`[data-control=${control[0]}]`);
                            if (closestControl) {
                                applyColor(actives, control[1], '');
                            }
                        });
                    });
                });
            });
        }
        
        function applyColor(actives, property, value) {
            if (Array.isArray(actives)) {
                actives.forEach(active => {
                    active.style[property] = value;
                });
            } else {
                actives.style[property] = value;
            }
        }

        const active = FRAMEBRXC.vueGlobalProp.$_getElementNode(elementObj);
        if(!active) return;
        setTimeout(()=> setColor(active),0)
        
    },
    setDynamicClassOnHover: function () {
        const self = this;
        const x = document.querySelector('#bricks-builder-iframe').contentWindow;
        
        if (!self.builderStates.isElementActive || !self.vueState.showElementClasses) {
          const previewStyle = x.document.querySelector('#at-preview-global-classes');
          if (previewStyle) {
            previewStyle.remove();
          }
          return;
        }
        
        const elementObjs = self.helpers.isBulkEdit() ? self.vueState.selectedElements : [self.builderStates.activeElement];

        const previewStyle = x.document.querySelector('#at-preview-global-classes') || document.createElement('style');
        previewStyle.id = 'at-preview-global-classes';
        
        const globalClasses = self.vueState.globalClasses;
        
        if (!Array.isArray(globalClasses) || globalClasses.length < 1) {
            if (previewStyle.parentNode) {
                previewStyle.parentNode.removeChild(previewStyle);
            } 
        
            return;
        }
        
        const filteredClasses = globalClasses.filter(el => el && el.hasOwnProperty('settings') && Object.keys(el.settings).length > 0);
        
        if (filteredClasses.length > 0) {
            
            let css = '';
            filteredClasses.forEach(cls => {
                let tempCSS = self.vueGlobalProp.$_generateCss("globalClass", cls, [elementObjs[0].name]);
                css += tempCSS;
            });

            previewStyle.innerHTML = css;
            x.document.head.appendChild(previewStyle);
        } else if (previewStyle.parentNode) {
            previewStyle.parentNode.removeChild(previewStyle);
        }

        function previewClass(actives, item, clsName){
            item.onmouseenter = () => {
                actives.forEach(active => {
                    active.classList.add(clsName);
                })
            };
            
            item.onmouseleave = () => {
                actives.forEach(active => {
                    active.classList.remove(clsName);
                })
            };
            
            item.onclick = () => {
                actives.forEach(active => {
                    active.classList.remove(clsName);
                })
            };
           
            
        }

        setTimeout(() => {
            const actives = elementObjs.map(obj => {
                return FRAMEBRXC.vueGlobalProp.$_getElementNode(obj)
            })
            
            const items = document.querySelectorAll('div.bricks-control-popup > div.css-classes [data-class-id]');
            items.forEach(item => {
                const classId = item.dataset.classId;
                const classObj = self.vueGlobalProp.$_getGlobalClass(classId)
                if(!classObj) return;

                const classLabel = classObj.name;
                previewClass(actives, item, classLabel)
            })
        }, 0);
    
            
    },

    setIsotope: function(selector) {
        const self = this;
        let filterRes = true;
        let filterSelector = "*";
        let filterSearch = true;
        let qsRegex
        let isotopeGutter;
        let isotopeLayoutHelper;
        const base = document.querySelector(selector);
        if(!base) return;
        const isotopeWrappers = base.querySelectorAll('.isotope-wrapper')
        if(!isotopeWrappers || isotopeWrappers.length < 1) return;
        isotopeWrappers.forEach(wrapper => {
            const isotopeContainers = wrapper.querySelectorAll('.isotope-container');
            if(!isotopeContainers || isotopeContainers.length < 0) return;

            isotopeContainers.forEach(isotopeContainer => {
                const isotopeSelector = wrapper.querySelectorAll('.isotope-selector');
                const isoSearch = wrapper.querySelector('input[type="text"].iso-search');
                const isoSearchType = isoSearch.dataset.type;
                const isoSearchReset = wrapper.querySelector('.iso-reset');
                if (wrapper.dataset.gutter) {
                    isotopeGutter = parseInt(wrapper.dataset.gutter);
                    wrapper.style.setProperty('--gutter', isotopeGutter + 'px');
                    isotopeSelector.forEach(elm => elm.style.paddingBottom = isotopeGutter + 'px');
                } else {
                    isotopeGutter = 0;
                };

                if (wrapper.dataset.filterLayout) {
                    isotopeLayoutHelper = wrapper.dataset.filterLayout;
                } else {
                    isotopeLayoutHelper = 'fitRows';
                };
                

                // init Isotope
                const isotopeOptions = {
                    itemSelector: '.isotope-selector',
                    layoutMode: isotopeLayoutHelper,
                    transitionDuration: 0,
                    filter: function(itemElem1, itemElem2) {
                        const itemElem = itemElem1 || itemElem2;
                        if(isoSearchType === "textContent") {
                            return qsRegex ? itemElem.textContent.match(qsRegex) : true;
                        } else {
                            filterSearch = qsRegex ? itemElem.getAttribute('title').match(qsRegex) : true;
                            filterRes = filterSelector != '*' ? itemElem.dataset.filter.includes(filterSelector) : true;
                            return filterSearch && filterRes;
                        }
                    },
                };


                // Set the correct layout
                switch (isotopeLayoutHelper) {
                    case 'fitRows':
                    isotopeOptions.fitRows = {
                        gutter: isotopeGutter
                    };
                    break;
                    case 'masonry':
                    isotopeOptions.masonry = {
                        gutter: isotopeGutter
                    };
                    break;
                }

                // Search Filter
                const iso = new Isotope(isotopeContainer, isotopeOptions);
                
                if (isoSearch) {
                    isoSearch.addEventListener('keyup', self.debounce(() => {
                        qsRegex = new RegExp(isoSearch.value, 'gi');
                        iso.arrange();
                    }, 100));
                }
                if (isoSearchReset) {
                    isoSearchReset.onclick = () => {
                        isoSearch.value = '';
                        const clickEvent = new Event('keyup');
                        isoSearch.dispatchEvent(clickEvent);
                    }
                }

                // Buttons Filters
                const filtersElem = wrapper.querySelectorAll(".filterbtn");
                if (filtersElem.length > 0) {
                    filtersElem.forEach(elem => elem.addEventListener("click", function (event) {
                        event.preventDefault();
                        var filterValue = event.target.getAttribute("data-filter");
                        filterSelector = filterValue;
                        iso.arrange();
                    }));
                };

                const radioButtonGroup = (buttonGroup) => {
                    buttonGroup.addEventListener("click", function (event) {
                    filtersElem.forEach(btn => btn.classList.remove("active"));
                    event.target.classList.add("active");
                    });
                };

                for (var i = 0, len = filtersElem.length; i < len; i++) {
                    var buttonGroup = filtersElem[i];
                    radioButtonGroup(buttonGroup);
                };

                // Hide if empty
                iso.on('arrangeComplete', (event) => {
                    if (event.length === 0 ) {
                        isotopeContainer.style.display = "none";
                        (isotopeContainer.previousElementSibling) ? isotopeContainer.parentElement.style.display = "none" : '';
                    } else {
                        isotopeContainer.style.display = "flex";
                        (isotopeContainer.previousElementSibling) ? isotopeContainer.parentElement.style.display = "block" : '';
                    }
                })



            })
            
        })
    },
    openInnerWindow: (wrapper) => {
        wrapper.classList.toggle('inner');
    },
    setInnerContent: (el) => {
        const imgCanvas = document.querySelector('#brxcResourcesOverlay .brxc-overlay__pannel-2 .brxc-overlay__img');
        const titleCanvas = document.querySelector('#brxcResourcesOverlay .brxc-overlay__pannel-2 .brxc-overlay__header-title');
        const srcImg = el.childNodes[1].src;
        const titleText = el.getAttribute('title');
        imgCanvas.innerHTML = '<img src="' + srcImg + '" class="inner__img">';
        titleCanvas.textContent = titleText;
    },
    copytoClipboardSimple: function(text, successMsg) {
        const self = this;
        if (window.isSecureContext && navigator.clipboard) {
           navigator.clipboard.writeText(text);
           self.vueGlobalProp.$_showMessage(successMsg)
        } else {
            self.unsecuredCopyToClipboardSimple(text, successMsg);
        }
     },
     unsecuredCopyToClipboardSimple: function(text, successMsg) {
        const self = this;
        const textArea = document.createElement("textarea");
        textArea.value = text;
        document.body.appendChild(textArea);
        textArea.focus({
           preventScroll: true
        });
        textArea.select();
        try {
           document.execCommand('copy');
           self.vueGlobalProp.$_showMessage(successMsg);
        } catch (err) {
            alert('Unable to copy to clipboard - Use a secure environment.')
        }
        document.body.removeChild(textArea);
     },
    copytoClipboard: function(btn,target, copytext, resestText) {
        const self = this;
        if (window.isSecureContext && navigator.clipboard) {
           navigator.clipboard.writeText(target);
           btn.textContent = copytext;
           setTimeout(() => {
                btn.textContent = resestText;
           }, 1000)
        } else {
            self.unsecuredCopyToClipboard(btn,target,copytext, resestText);
        }
     },
     unsecuredCopyToClipboard: (btn,text,copytext, resestText) => {
        const textArea = document.createElement("textarea");
        textArea.value = text;
        document.body.appendChild(textArea);
        textArea.focus({
           preventScroll: true
        });
        textArea.select();
        try {
           document.execCommand('copy');
           btn.textContent = copytext;
           setTimeout(() => {
                btn.textContent = resestText;
           }, 1000)
        } catch (err) {
            alert('Unable to copy to clipboard - Use a secure environment.')
        }
        document.body.removeChild(textArea);
     },
    codeMirrorOptions: (textarea) => {
        let builderTheme;
        (typeof bricksData["loadData"] !== "undefined" && bricksData["loadData"].hasOwnProperty("globalClasses") && bricksData["loadData"]['globalSettings'].hasOwnProperty("builderMode") && bricksData['loadData']['globalSettings']['builderMode'] === 'light') ? builderTheme = 'default' : builderTheme = 'one-dark';
        const obj = {
            value: '',
            mode: "css",
            theme: builderTheme,
            readOnly: false,
            styleActiveLine: true,
            tabSize: 2,
            lineNumbers: true,
            lineWrapping: !0,
            autoRefresh: true,
            autofocus: true,
            suppressErrorLogging: !1,
            autoCloseBrackets: true,
            matchBrackets: true,
            selfContain: true,
            comment: true,
            iewportMargin: Infinity,
            extraKeys: { Tab: "emmetExpandAbbreviation", Esc: "emmetResetAbbreviation", Enter: "emmetInsertLineBreak" },
        };
        if(textarea !== false) obj.value = textarea.value;
        return obj;
    },
    CMautocompleteState: {
        isVar: false,
        isProperty: false,
    },
    setCodeMirror: function() {
        const self = this;

        CodeMirror.hint.anyword = function (editor) {
            var list = self.vueState.globalClasses.map(el => `${el.name} `);
            var cursor = editor.getCursor();
            var currentLine = editor.getLine(cursor.line);
            var start = cursor.ch;
            var end = start;
            var reg = /[\w\-$]+/;
            
            while (end < currentLine.length && reg.test(currentLine.charAt(end))) ++end;
            while (start && reg.test(currentLine.charAt(start - 1))) --start;
            
            var curWord = start !== end ? currentLine.slice(start, end) : "";
            var regex = new RegExp(curWord, 'i'); // Removed `^`
        
            var result = {
                list: (!curWord ? list : list.filter(item => regex.test(item))).sort(),
                from: CodeMirror.Pos(cursor.line, start),
                to: CodeMirror.Pos(cursor.line, end)
            };
        
            return result;
        };

        const cssHinter = CodeMirror.hint.css;

        CodeMirror.hint.css = async function (editor) {
            const cursor = editor.getCursor();
            const token = editor.getTokenAt(cursor);
            const currentLine = editor.getLine(cursor.line);
            const beforeCursor = currentLine.slice(0, cursor.ch);
            const nestedVar = /var\([^)]*$/.test(beforeCursor);
            const curChar = currentLine.charAt(cursor.ch - 1);
            let start = cursor.ch;
            let end = start;
            const rex = /[\w\-$!]+/;
            
            while (end < currentLine.length && rex.test(currentLine.charAt(end))) ++end;
            while (start && rex.test(currentLine.charAt(start - 1))) --start;
            
            const curWord = start !== end && currentLine.slice(start, end);
            const dflt = cssHinter(editor);
            const result = dflt || { list: [] };
            result.to = CodeMirror.Pos(cursor.line, end);
            result.from = CodeMirror.Pos(cursor.line, start);
            var inner = CodeMirror.innerMode(editor.getMode(), token.state);
            const hintCondition = ["prop", "parens", "params"].includes(inner.state.state);
        
            // Handle the '@' character and async loading of recipes
            if (self.globalSettings.classFeatures.advancedCSSCommunityRecipes && !self.advancedCSSStates.communityRecipesLoaded && curChar === "@") {
                // Await the async task to ensure it completes before continuing
                await self.getCommunityRecipes(false);
                self.advancedCSSStates.communityRecipesLoaded = true;
            }
        
            // Process the hints depending on state
            if (inner.state.state === "at") {
                result.list = brxcAdvancedCSSDefault
                    .filter(el => el.typeLabel === "recipe" && el.status == 1 && el.label.includes(curWord) && el.contentCss && el.contentCss !== "")
                    .map(el => ({
                        "text": el.label,
                        "displayText": el.label,
                    }));
            } else if (hintCondition) {

                if(curWord && curWord.startsWith("$")){
                    sassVariables = self.advancedCSSStates.partialVariables.filter(variable => variable && variable.includes(curWord));
                    result.list = sassVariables.map(h => 
                        (typeof h === "string") 
                            ? { "text": h, "displayText": h }
                            : h
                    );
                } else {

                    cssVariables = self.cssVariables.reduce((result, variable) => {
                        if (variable && variable.includes(curWord)) {
                            if (nestedVar) {
                                const cleanedVariable = variable.replace(/^var\(|\)$/g, '');
                                result.push(cleanedVariable);
                            } else {
                                result.push(variable);
                            }
                        }
                        return result;
                    }, []);
                    
                    result.list = result.list.concat(cssVariables);
                    result.list = result.list.map(h => 
                        (typeof h === "string") 
                            ? { "text": `${h}`, "displayText": h }
                            : h
                    );
                }
            } else {
                result.list = result.list.map(h => 
                    (typeof h === "string") 
                        ? { "text": `${h}: ;`, "displayText": h }
                        : h
                );
            }
            
            result.list.sort((a, b) => {
                const textA = a.text.replace(':', '').toLowerCase();
                const textB = b.text.replace(':', '').toLowerCase();
                
                // First, compare by length
                const lengthDifference = textA.length - textB.length;
                if (lengthDifference !== 0) {
                    return lengthDifference;
                }
            
                // If lengths are equal, then sort alphabetically
                return textA.localeCompare(textB);
            });
        
            return result;
        };
        

        const htmlHinter = CodeMirror.hint.html; // Store the original hint function

        CodeMirror.hint.html = function (editor) {
            const cursor = editor.getCursor();
            const currentLine = editor.getLine(cursor.line);
        
            let start = cursor.ch;
            let end = start;
            
            // New regex to match words, optionally allowing < or /
            const rex = /<\/?|\/|<[\w\-$!]+|<\/[\w\-$!]+|[\w\-$!]+/;
        
            // Find end of the current "word" at the cursor
            while (end < currentLine.length && rex.test(currentLine.charAt(end))) ++end;
            // Find the beginning of the current "word" at the cursor
            while (start && rex.test(currentLine.charAt(start - 1))) --start;
        
            // Get the current word based on the updated rex
            const curWord = start !== end && currentLine.slice(start, end);
        
            // Get the default hint results from the original HTML hinter
            const dflt = htmlHinter(editor);
        
            // Create a result list, either from default hinter or empty list
            const result = dflt || { list: [] };

            // Set the start/end of the replacement range
            result.to = CodeMirror.Pos(cursor.line, end);
            result.from = CodeMirror.Pos(cursor.line, start);
        
            // Filter the list based on the current word typed by the user (curWord)
            if (curWord) {
                result.list = result.list.concat(Object.values(bricksData.elements)
                    .filter(el => !el.deprecated)
                    .map(el => `<b-${el.name}`)
                ).filter(item => {
                    const displayText = (typeof item === 'string') ? item : item.displayText;
                    return displayText.includes(curWord);
                });
            }
        
            return result;
        };
        CodeMirror.commands.autocomplete = function(cm) {  
            var doc = cm.getDoc();
            var POS = doc.getCursor();
            var mode = CodeMirror.innerMode(cm.getMode(), cm.getTokenAt(POS).state).mode.name;
            
            if (mode == 'css' || mode === "myMode" || mode == "text/x-scss") { 
                var repositionCursor = function() {
                    var currentPos = cm.getCursor();
                    var line = cm.getLine(currentPos.line);
                    
                    if (currentPos.ch > 2 && line.charAt(currentPos.ch - 1) === ';'
                        && line.charAt(currentPos.ch - 2) === ' '
                        && line.charAt(currentPos.ch - 3) === ':') {
                        cm.setCursor({line: currentPos.line, ch: currentPos.ch - 1});
                    }
                    
                    cm.off('endCompletion', repositionCursor);
                };
                
                cm.on('endCompletion', repositionCursor);
                cm.showHint({
                    hint: CodeMirror.hint.css,
                    completeSingle: false,
                    closeOnUnfocus: true,

                });
            } else if(mode == 'text/x-markdown') {
                cm.showHint(
                    {
                        hint: CodeMirror.hint.anyword,
                        completeSingle: false,
                    }
                )
            } else if(mode == 'cssVariables') {
                cm.showHint(
                    {
                        hint: CodeMirror.hint.cssVariables,
                        completeSingle: true,
                    }
                )
            } else if(mode === "xml"){
                cm.showHint(
                    {
                        hint: CodeMirror.hint.html,
                        completeSingle: false,
                    }
                )
            }
        };
    },
    addRootTag: function(event, closest){
        const self = this;
        const target = event.target;
        const controlKey = target.closest(closest);
        if(!controlKey) return;
        const cm = controlKey.querySelector('.CodeMirror[data-type="at"]')
        if(!cm) return;

        const value = cm.CodeMirror.getValue();
        const result = (value === '') ? '%root% {\n\t\n}' : value + '\n\n%root% {\n\t\n}';
        cm.CodeMirror.setValue(result);

        cm.CodeMirror.focus();
        self.helpers.setCursorToLastRowMinusOne(cm.CodeMirror);
    },
    beautifyCSS: function(closest){
        const self = this;
        const cm = document.querySelector(closest + ' .CodeMirror[data-type="at"]')
        if(!cm) return;

        // Return Value
        const dataOptions = { indent_size: 2 }
        const result = css_beautify(cm.CodeMirror.getValue(), dataOptions);
        cm.CodeMirror.setValue(result);
        var event = new Event('keyup');
        cm.CodeMirror.getInputField().dispatchEvent(event);
    },
    commentCode: function(closest){
        const self = this;
        const cm = document.querySelector(closest + ' .CodeMirror[data-type="at"]')
        if(!cm) return;

        self.helpers.commentCMCode(cm);
    },
    addComponentSelectors: function(closest){
        const self = this;

        const cm = document.querySelector(closest + ' .CodeMirror[data-type="at"]')
        if(!cm) return;

        // Function
        let existingSelector = [];
        let selector = false;
        const elementObj = self.builderStates.activeElement;
        const dot = self.helpers.isComponentActive() ? '.' : '#';

        function createSelector(obj,existingSelector){
            if (obj.settings.hasOwnProperty('_cssGlobalClasses') && obj.settings._cssGlobalClasses.length > 0) {
                const unlocked = [];
                const locked = [];
                obj.settings._cssGlobalClasses.forEach(el => {
                    (self.vueGlobalProp.$_isLocked(el)) ? locked.push(el) : unlocked.push(el);
                });
                const ids = (unlocked.length > 0) ? unlocked : locked;
                if (ids.length > 0) {
                    let classes = [] 
                    ids.forEach(id => {
                        const classObj = self.vueGlobalProp.$_getGlobalClass(id);
                        if(classObj && classObj.hasOwnProperty('name')){
                            classes.push(classObj.name);
                        }
                    })
                    selector = `.${classes.join('.')}`;
                } else {
                    selector = false;
                }
            } else {
                selector = `${dot}${self.vueGlobalProp.$_getElementId(obj)}`;
            } 
            if(selector === false || existingSelector.includes(selector)) return "";
            existingSelector.push(selector);
            return `${selector}{\n\t\n}\n\n`;
        }

        let css = "";

        function checkChildren(obj, first){
            if(first === true) existingSelector = [];
            css += createSelector(obj, existingSelector);
            if(!obj.children || obj.children.length < 1) return;
            obj.children.forEach(child =>{
                checkChildren(self.helpers.getElementObject(child), false);
            })
        }

        checkChildren(elementObj, true);

        const finalSelector = self.helpers.getFinalSelector();
        const calculatedValue = self.vueGlobalProp.$_replaceCustomCssRoot(finalSelector, '%root%', css)

        // Return Value
        const value = cm.CodeMirror.getValue();
        const result = (value === '') ? calculatedValue : value + `\n\n${calculatedValue}`;
        cm.CodeMirror.setValue(result);
        var event = new Event('keyup');
        cm.CodeMirror.getInputField().dispatchEvent(event);
        cm.CodeMirror.focus();
        self.helpers.setCursorToLastRowMinusOne(cm.CodeMirror);
    },
    variabilizeCSS: function(closest, selector){
        const self = this;
        const cm = document.querySelector(closest + ' .CodeMirror[data-type="at"]')
        if(!cm) return;

        const value = cm.CodeMirror.getValue();
        const result = (value === '') ? value : self.helpers.convertCSSToVariables(value, selector);
        
        // Advanced CSS
        if(selector === ":root"){
            return cm.CodeMirror.setValue(result);
        }

        // SuperPowerCSS
        const elementObj = self.builderStates.activeObject;
        const finalSelector = self.helpers.getFinalSelector();

        self.stickyCssStates.forceMount = true;
        self.stickyCssStates.timeoutMount = true;
        // Apply Changes;
        setTimeout(() => {
            const target = self.globalSettings.superPowerCSSEnableSass === "1"? self.helpers.createTarget('_cssCustomSass') : self.helpers.createTarget('_cssCustom');
            elementObj.settings[target] = self.vueGlobalProp.$_replaceCustomCssRoot(finalSelector,'%root%', result);
            self.vueState.rerenderControls = Date.now();
        }, 100)
    },
    convertUXinCSS: function(closest){
        const self = this;
        let cm = document.querySelector(closest + ' .CodeMirror[data-type="at"]')
        if(!cm) return;
        
        const type = self.builderStates.isClassActive ? "globalClass" : "element";
        const structureObj = self.builderStates.activeElement;
        const elementObj = self.builderStates.activeObject;
        const finalSelector = self.helpers.getFinalSelector();

        let generatedCSS = self.vueGlobalProp.$_generateCss(type, elementObj, [structureObj.name]);
        if(self.helpers.isComponentActive()) generatedCSS = generatedCSS.replaceAll('#brxe-', '.brxe-')
        const previewCSS = generatedCSS.replaceAll(`.brxe-${structureObj.name}`, '');
        const beautifiedCSS = css_beautify(previewCSS, { indent_size: 2 });

        // Reset Styles
        self.helpers.resetStyles(elementObj);

        self.stickyCssStates.forceMount = true;
        self.stickyCssStates.timeoutMount = true;
        // Apply Changes;
        setTimeout(() => {
            elementObj.settings._cssCustom = self.vueGlobalProp.$_replaceCustomCssRoot(finalSelector,'%root%', beautifiedCSS);
            self.vueState.rerenderControls = Date.now();
        }, 100)
        
    },
    setGeneratedCSS: function(){
        const self = this;
        setTimeout(() => {

            if(!self.builderStates.isElementActive || (self.showControlSearch === false && self.vueState.activePanelTab !== "style") || (self.vueState.showControlSearch === false && self.vueState.activePanelGroup !== "_generated-code") || self.vueState.showInteractions === true || self.vueState.showConditions === true) return;
        
            const panel = document.querySelector('#bricks-panel');

            // Mount CM
            const elmntTarget = panel.querySelector('[data-controlkey="_generatedCSS"]');
            if(!elmntTarget) return;

            const textAreaTarget = elmntTarget.querySelector('textarea');

            if(textAreaTarget){
                self.mountGeneratedCSSCM(textAreaTarget, false);

            } else {
                const observer = new MutationObserver(() => {
                    const textAreaTarget = elmntTarget.querySelector('textarea')
                    if (!textAreaTarget) {
                        return;
                    }
                    
                    self.mountGeneratedCSSCM(textAreaTarget, observer);
                })
                observer.observe(elmntTarget, { subtree: true, childList: true });
    
            }
        }, 125)
    },
    mountGeneratedCSSCM: function(textAreaTarget, observer){
        const self = this;

        function generateCSS(){
            const type = self.builderStates.isClassActive ? "globalClass" : "element";
            const elementObj = self.builderStates.activeElement;
            const finalObj = self.builderStates.activeObject;
            if(!elementObj) return;

            let previewCSS = self.vueGlobalProp.$_generateCss(type, finalObj, [elementObj.name]).replaceAll(`.brxe-${elementObj.name}`, '');
            if(self.helpers.isComponentActive()) previewCSS = previewCSS.replaceAll('#brxe-', '.brxe-')
            const beautifiedCSS = css_beautify(previewCSS, { indent_size: 2 });
            const finalCode = beautifiedCSS === "" ? "/* No Style applied */" : beautifiedCSS;
            return finalCode;
        }

        if(textAreaTarget.dataset.mounted === "true") return;
        textAreaTarget.setAttribute("data-mounted", "true");
        const options = self.codeMirrorOptions(false);
        options.readOnly = true;
        options.styleActiveLine = true;
        options.autofocus = false
        options.search = { bottom: false };
        const MyCM = CodeMirror.fromTextArea(textAreaTarget, options)
        MyCM.setValue(generateCSS());
    
        if(observer) observer.disconnect();


    },
    setGeneratedHTML: function(){
        const self = this;
        setTimeout(() => {

            if(!self.builderStates.isElementActive || (self.showControlSearch === false && self.vueState.activePanelTab !== "style") || (self.vueState.showControlSearch === false && self.vueState.activePanelGroup !== "_generated-code") || self.vueState.showInteractions === true || self.vueState.showConditions === true) return;
        
            const panel = document.querySelector('#bricks-panel');

            // Mount CM
            const elmntTarget = panel.querySelector('[data-controlkey="_generatedHTML"]');
            if(!elmntTarget) return;

            const textAreaTarget = elmntTarget.querySelector('textarea');
            const parseHTMLbtn = panel.querySelector('[data-controlkey="_generatedHTMLApply"] button');

            if(textAreaTarget && parseHTMLbtn){
                self.mountGeneratedHTMLCM(textAreaTarget, false);
                self.setParseHTMLbtn(parseHTMLbtn);

            } else {
                const observer = new MutationObserver(() => {
                    const textAreaTarget = elmntTarget.querySelector('textarea')
                    const parseHTMLbtn = panel.querySelector('[data-controlkey="_generatedHTMLApply"] button');
                    if (!textAreaTarget || !parseHTMLbtn) {
                        return;
                    }
                    
                    self.mountGeneratedHTMLCM(textAreaTarget, observer);
                    self.setParseHTMLbtn(parseHTMLbtn);
                })
                observer.observe(elmntTarget, { subtree: true, childList: true });
    
            }
        }, 125)
    },
    getGeneratedHTMLMultipleElements: function(elementID){
        const self = this;
        function generateHTML(elementArr){
            return new Promise((resolve, reject) => {
                jQuery.ajax({
                    url: openai_ajax_req.ajax_url,
                    data: {
                        action: 'generated_html_multiple_elements_ajax_function',
                        nonce: openai_ajax_req.nonce,
                        elements: elementArr,
                    },
                    method: "POST",
                    success: function (response) {
                        resolve(
                            console.log(response.data)
                        );
                    },
                    error: function (data) {
                        reject('Something went wrong.');
                    }
                });
            });
        }
        function createArray(id, arr = []){
            let obj = self.helpers.getElementObject(id);
            arr.push(obj);
            if (obj.hasOwnProperty('children') && Array.isArray(obj.children) && obj.children.length > 0) {
                obj.children.forEach(childrenId => {
                    createArray(childrenId, arr);
                })
            }
            return arr;
        }

        const elements = createArray(elementID);
        generateHTML(elements);
    },
    mountGeneratedHTMLCM: function(textAreaTarget, observer){
        const self = this;
        const elementObj = self.builderStates.activeElement;

        function generateHTML(){
            return new Promise((resolve, reject) => {
                jQuery.ajax({
                    url: openai_ajax_req.ajax_url,
                    data: {
                        action: 'generated_html_ajax_function',
                        nonce: openai_ajax_req.nonce,
                        element: elementObj,
                    },
                    method: "POST",
                    success: function (response) {
                        resolve(
                            MyCM.setValue(response.data)
                        );
                    },
                    error: function (data) {
                        reject('Something went wrong.');
                    }
                });
            });
        }

        if(textAreaTarget.dataset.mounted === "true") return;
        textAreaTarget.setAttribute("data-mounted", "true");
        const options = self.codeMirrorOptions(false);
        options.mode = "htmlmixed";
        options.readOnly = false;
        options.styleActiveLine = true;
        options.autofocus = false
        options.search = { bottom: false };
        options.autoCloseTags = true;
        const MyCM = CodeMirror.fromTextArea(textAreaTarget, options)
        generateHTML(MyCM);
        
        MyCM.on("keyup", function(cm, event) {
            event.stopPropagation();
            elementObj.settings._generatedHTML = cm.getValue();
        });
        
        
        if(observer) observer.disconnect();
    },
    setParseHTMLbtn: function(btn){
        const self = this;
        if(btn.dataset.mounted === "true") return;
        btn.setAttribute("data-mounted", "true");
        btn.addEventListener('mousedown', (e) => {
            e.preventDefault();
            e.stopPropagation();
            let activeElement = self.builderStates.activeElement;
            const customHTML = activeElement.settings.hasOwnProperty('_generatedHTML') ? activeElement.settings._generatedHTML : false;
            if(customHTML) {
                let tempDiv = document.createElement('div');
                tempDiv.innerHTML = customHTML;
                const element = tempDiv.firstElementChild;
                const elementConfig = self.vueGlobalProp.$_getElementConfig(activeElement.name);

                //Tagname
                const tagName = element.tagName.toLowerCase();
                if(tagName && tagName !== elementConfig.tag){
                    if(!elementConfig.controls.hasOwnProperty('tag')){
                        return self.vueGlobalProp.$_showMessage('ABORT: This element doesn\'t accept custom HTML tags');
                    }
                    // Exceptions
                    if(tagName === "img"){
                        //silence
                    } else {
                        if(tagName in elementConfig.controls.tag.options){
                            activeElement.settings.tag = tagName;
                        } else {
                            activeElement.settings.tag = "custom";
                            activeElement.settings.customTag = tagName;
                        }
                    }
                }

                const parsingStates =  {
                    includesIds: true,
                    excludeIds: 'brxe-',
                    includesClasses: true,
                    excludeClasses: 'brxe-',
                    createGlobalClasses: false,
                    includesTexts: true,
                    includesAttributes: true,
                    excludeAttributes: '',
                }

                //id
                activeElement = self.helpers.setIdFromParsedHTML(element, activeElement, parsingStates);

                //Classes
                activeElement = self.helpers.setClassesFromParsedHTML(element, activeElement, parsingStates);

                // Text
                activeElement = self.helpers.setTextFromParsedHTML(element, activeElement, elementConfig, parsingStates);

                // Attributes
                activeElement = self.helpers.setAttributesFromParsedHTML(element, activeElement, parsingStates);

                tempDiv.innerHTML = '';
                tempDiv = null;
                delete activeElement.settings._generatedHTML;
                setTimeout(() => {
                    delete activeElement.settings._generatedHTML;
                    self.vueState.forceRender = Date.now();
                }, 10)
            };
        })
    },
    superPowerStates: {
        mounting: false,
        fullScreen: true,
        isActiveClass: false,
        selector: null,
        obj: null,
        mixins: '',
        sassInstances: [],
        hasValue: false,
        AIprompt : '',
        AIbackup: '',
        editAI: false,
        isAIRunning: false,
        showBookmark: false,
        searchBookmark: '',
        
    },
    setSuperPowerCSS: function() {
        const self = this;
    
        if (!self.helpers.isElementActive() || 
            (self.showControlSearch === false && self.vueState.activePanelTab !== "style") || 
            (self.vueState.showControlSearch === false && self.vueState.activePanelGroup !== "_css") || 
            self.vueState.showInteractions === true || 
            self.vueState.showConditions === true) {
            return;
        }
        const panel = document.querySelector('#bricks-panel');
        if (!panel) return;
    
        const elmntTarget = panel.querySelector('[data-controlkey="_cssSuperPowerCSS"]');
        if (!elmntTarget) return;
    
        let observer;

        setTimeout(() => {
            const tryMount = (textareaTarget) => {
                if (textareaTarget) {
                    self.mountSuperPowerCSSCM(textareaTarget, observer);
                    const description = elmntTarget.querySelector('.description');
                    if (description) self.addFullSizeCSSState();
                    if (observer) observer.disconnect();
                }
            }
        
            const initialTextarea = elmntTarget.querySelector('textarea');
            if (initialTextarea) {
                tryMount(initialTextarea);
            } else {
                observer = new MutationObserver(() => {
                    const textareaTarget = elmntTarget.querySelector('textarea');
                    if (textareaTarget) {
                        tryMount(textareaTarget);
                    }
                });
                observer.observe(elmntTarget, { subtree: true, childList: true });
            }
        },0)
    },
    
    mountSuperPowerCSSCM: function(textAreaTarget){
        const self = this;
        if(textAreaTarget.dataset.mounted === "true") return;
        textAreaTarget.setAttribute("data-mounted", "true");
        const options = self.codeMirrorOptions(false);
        options.mode = self.globalSettings.superPowerCSSEnableSass === "1" ? 'text/x-scss' : 'css';
        options.readOnly = false;
        options.styleActiveLine = true;
        options.autoCloseBrackets = true;
        options.matchBrackets = true;
        options.selfContain = true;
        options.autofocus = false
        options.search = { bottom: false };
        options.profile = "xhtml";
        const MyCM = CodeMirror.fromTextArea(textAreaTarget, options);
        emmetCodeMirror(MyCM);
        MyCM.getWrapperElement().setAttribute("data-type", "at");
        MyCM.setOption('gutters', []);
        self.updateSuperPowerCSS(MyCM);
        // Expand
        setTimeout(() => {
            if(bricksData.disablePanelAutoExpand === "" && self.vueState.activePanelGroup === "_css") self.vueState.isPanelExpanded = true;
            self.addIconsToSuperpowerCSS();
            self.addMessageToSuperpowerCSS();
            self.populateCSSVariables();
            self.addListenersToSuperPowerCSS(MyCM);
            MyCM.scrollIntoView({ line: MyCM.lineCount() - 1, ch: 0 });
            MyCM.scrollIntoView({ line: 0, ch: 0 });
            self.superPowerStates.AIbackup = '';
            self.superPowerStates.editAI = false;
            self.superPowerStates.AIprompt = '';
            self.superPowerStates.searchBookmark = '';
            self.superPowerCSSAIMount(textAreaTarget, MyCM, 'css');
            
        },120);

        setTimeout(() => {
            MyCM.refresh();
        },300)
    },
    superPowerCSSAIMount: function(textarea, cm, type){
        const self = this;
        if(!self.helpers.isAIActive() || self.globalSettings.isAIApiKeyEmpty === "") return;
        
        const existing = textarea.parentElement.querySelector('#brxcSuperPowerCSSAIpromptContainer');
        if(existing) existing.remove();
        const parent = textarea.parentElement
        const AIprompt = document.createElement('DIV');
        AIprompt.id = "brxcSuperPowerCSSAIpromptContainer"
        let content = '';
        content += `<div id="brxcSuperPowerCSSAIpromptWrapper">
                        <div id="brxcSuperPowerCSSAIEdit"${self.superPowerStates.editAI ? ' class="active"' : ''} data-balloon="Edit existing code" data-balloon-pos="top-left"><i class="fas fa-edit"></i></div>
                        <textarea id="brxcSuperPowerCSSAIprompt" placeholder="Message AI">${self.superPowerStates.AIprompt}</textarea>
                        <div id="brxcSuperPowerCSSAIPlus"${self.superPowerStates.showBookmark ? ' class="active"' : ''} data-balloon="Choose a global prompt" data-balloon-pos="top-right"><i class="fas fa-bookmark"></i></div>
                        <div id="brxcSuperPowerCSSAISendRequest"${self.superPowerStates.isAIRunning ? ' class="disable"' : ' onclick="ADMINBRXC.superPowerCSSAIRequest(this);"'} data-balloon="Send" data-balloon-pos="top-right"><i class="fas fa-arrow-up"></i></div>`
    if(self.superPowerStates.AIbackup !== '') content += `<div id="brxcSuperPowerCSSAIUndo" data-balloon="Undo AI changes" data-balloon-pos="top-right"><i class="fas fa-undo"></i></div>`
    if(self.superPowerStates.showBookmark) {
        self.superPowerStates.searchBookmark = ''
        content += `<div id="brxcSuperPowerCSSAIPopup" class="bricks-control-popup bottom">
                        <div class="css-classes">
                            <h6 class="title"><span>Global AI Prompts</span></h6>
                            <ul id="brxcPrompListLiCanvas">
                                ${(Array.isArray(brxcPromptManager) ? brxcPromptManager.filter(el => el.category === type).map(obj => `
                                    <li data-id="${obj.id}">
                                        <span class="name">${obj.label}</span>
                                    </li>`).join('') : '')}
                            </ul>
                        </div>
                        <div class="input-wrapper">
                            <input type="text" autocomplete="off" spellcheck="false" placeholder="Search for a prompt ..." oninput="ADMINBRXC.superPowerStates.searchBookmark = this.value;ADMINBRXC.superPowerCSSUpdateBookmarkList();">
                        </div>
                    </div>`;
        }
        content +=`</div>`; // end wrapper


        AIprompt.innerHTML = content;
        parent.appendChild(AIprompt);

        // Listeners
        const inputText = parent.querySelector('#brxcSuperPowerCSSAIprompt');
        if(inputText){
            self.helpers.textAreaAutoGrow(inputText, '30px')
            inputText.addEventListener('keyup', (e) => {
                self.superPowerStates.AIprompt = e.target.value;
                self.helpers.textAreaAutoGrow(e.target, '30px')
            })
        }

        const editBtn = parent.querySelector('#brxcSuperPowerCSSAIEdit');
        if(editBtn){
            editBtn.addEventListener('click', () => {
                self.superPowerStates.editAI = !self.superPowerStates.editAI;
                self.superPowerCSSAIMount(textarea, cm, 'css');
            })
        }

        const bookmark = parent.querySelector('#brxcSuperPowerCSSAIPlus');
        if(bookmark){
            bookmark.addEventListener('click', () => {
                self.superPowerStates.showBookmark = !self.superPowerStates.showBookmark;
                self.superPowerCSSAIMount(textarea, cm, 'css');
            })
        }

        const popup = parent.querySelector('#brxcSuperPowerCSSAIPopup');
        if(popup){
            popup.addEventListener('click', (e) => {
                if(e.target.dataset.id){
                    self.superPowerCSSPlusSelect(e.target.dataset.id);
                }
            })
        }

        const undo = parent.querySelector('#brxcSuperPowerCSSAIUndo');
        if(undo){
            undo.addEventListener('click', (e) => {
                cm.setValue(self.superPowerStates.AIbackup);
                self.superPowerStates.AIbackup = '';
                self.superPowerCSSAIMount(textarea, cm, 'css');
            })
        }

    },
    superPowerCSSUpdateBookmarkList: function(){
        const self = this;
        const parent = document.querySelector('#brxcPrompListLiCanvas');
        Array.from(parent.children).forEach(item => {
            if(self.superPowerStates.searchBookmark === '' || item.textContent.toLowerCase().includes(self.superPowerStates.searchBookmark.toLowerCase())){
                item.style.display = 'flex';
            } else {
                item.style.display = 'none';
            }
        })
    },
    superPowerCSSPlusSelect: function(id){
        const self = this;
        const obj = brxcPromptManager.find(el => el.id === id);
        self.superPowerStates.AIprompt = obj.prompt;
        self.superPowerStates.showBookmark = false;

        const textarea = document.querySelector('#bricks-panel [data-controlkey="_cssSuperPowerCSS"] textarea');
        const cm = document.querySelector('#bricks-panel [data-controlkey="_cssSuperPowerCSS"] .CodeMirror').CodeMirror;
        self.superPowerCSSAIMount(textarea, cm, 'css');
    },
    superPowerCSSAIRequest: function(currentElement){
        const self = this;
        const elmntTarget = document.querySelector('#bricks-panel [data-controlkey="_cssSuperPowerCSS"]');
        if(!elmntTarget) return;

        const cm = currentElement.closest('[data-controlkey="_cssSuperPowerCSS"]').querySelector('.CodeMirror').CodeMirror;
        if(!cm) return;

        const textAreaTarget = elmntTarget.querySelector('textarea')
        let cssString = cm.getValue();
        const promptRequest = currentElement.parentElement.querySelector('textarea').value;
        const type = self.superPowerStates.sassInstances.length === 0 ? "css" : "scss";
        let systemtContent = '';
        if(self.superPowerStates.editAI){
            systemtContent = `You are an expert ${type} developer. You will receive a ${type} string, a user prompt, and a target selector. Your task is to edit or improve the existing ${type} string based on the prompt. The target selector that is provided represents the root selector of the component you're modifiying. Return only the raw ${type} code without any additional comments, explanations, or text. The output must be valid, executable ${type} code, with no formatting, comments, or non-${type} elements. Don't start with "${type}". Do not include any text that is not part of a valid ${type} declaration. Example of expected output format: "${self.superPowerStates.selector}{color: red;}". Note that complex/compound selectors are allowed if required (example: "${self.superPowerStates.selector} img, ${self.superPowerStates.selector} > div + p{color: red;}").`
        } else {
            systemtContent = `You are an expert ${type} developer. You will receive an existing ${type} string for context, a user prompt, and a target selector. Your task is to generate new ${type} code based on the prompt and append it to the existing ${type} code. The target selector that is provided represents the root selector of the component you're modifiying. Do not repeat or modify the existing ${type} code. Output only the new rules without any additional comments, explanations, or text. Don't start with "${type}". The response should contain only valid, executable ${type} declarations and nothing else. Example of expected output format: "${self.superPowerStates.selector}{color: red;}". Note that complex/compound selectors are allowed if required (example: "${self.superPowerStates.selector} img, ${self.superPowerStates.selector} > div + p{color: red;}").`
        }

        const requestBody = {
            model: self.globalSettings.defaultAIModel,
            stream: true,
            messages: [
                {
                    role: "system",
                    content: systemtContent,
                },
                {
                    role: "user",
                    content: `Target Selector:"${self.superPowerStates.selector}\n"Existing ${type}:"${cssString}"\nUser Request:"${promptRequest}"`
                }
            ]
        };

        self.superPowerStates.AIprompt = '';
        self.superPowerStates.isAIRunning = true;
        self.superPowerCSSAIMount(textAreaTarget, cm, 'css')

        jQuery.ajax({
            type: 'POST',
            url: openai_ajax_req.ajax_url,
            data: {
                action: 'openai_ajax_function',
                nonce: openai_ajax_req.nonce
            },
            success: function(response) {
                const fetchDescription = async () => {
                    const rawResponse = await fetch('https://api.openai.com/v1/chat/completions', {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                            'Authorization' : 'Bearer ' + response,
                        },
                        body: JSON.stringify(requestBody)
                    });
 
                    if(!rawResponse.ok){
                        const statusText = rawResponse.status === 401 ? "Unauthorized. Double-check you correctly inserted the OpenAI API key inside the Theme Settings." : rawResponse.statusText;
                        self.superPowerStates.isAIRunning = false;
                        self.superPowerCSSAIMount(textAreaTarget, cm, 'css')
                    } else {
                        // Create a reader to read the streamed response
                        const reader = rawResponse.body.getReader();
                        const decoder = new TextDecoder();
                        let newCssCode = `/* CSS generated by AI on: ${new Date().toLocaleString()} */\n\n`;
                        let index = 0;
                        self.superPowerStates.AIbackup = cssString;
                
                        // Function to handle each chunk of data
                        const processChunk = async () => {
                            const { done, value } = await reader.read();
                            if (done) {
                                // All chunks have been read
                                return;
                            }
                
                            // Decode and parse the JSON chunk
                            const chunkText = decoder.decode(value);


                            // Split the chunk text into lines and process each one
                            const lines = chunkText.split('\n').filter(line => line.trim() !== '');
                            for (let line of lines) {
                                // Check if the line starts with "data: "
                                if (line.startsWith("data: ")) {
                                    const jsonLine = line.replace("data: ", "").trim();
                                    if (jsonLine !== "[DONE]") {
                                        try {
                                            // Parse the JSON and get the new CSS content
                                            const parsedData = JSON.parse(jsonLine);
                                            if (parsedData.choices && parsedData.choices[0].delta && parsedData.choices[0].delta.content) {
                                                let cssChunk = parsedData.choices[0].delta.content;
                                
                                                // Remove any code block symbols and formatting hints
                                                cssChunk = cssChunk.replace(/```/g, '');
                                                // Append the clean CSS content
                                                if (!(index === 0 && cssChunk.toLowerCase() === type)) {
                                                    newCssCode += cssChunk;
                                                }

                                                // Apply the new CSS live to the document
                                                const cmValue = self.superPowerStates.editAI ? newCssCode : cssString + newCssCode;
                                                const finalValue = self.vueGlobalProp.$_replaceCustomCssRoot(self.superPowerStates.selector, '%root%', cmValue);
                                                cm.setValue(css_beautify(finalValue, { indent_size: 2 }));
                                            }
                                        } catch (e) {
                                            console.error('Failed to parse JSON chunk:', e, jsonLine);
                                            self.superPowerStates.isAIRunning = false;
                                            self.superPowerCSSAIMount(textAreaTarget, cm, 'css')
                                        }
                                    } else {
                                        self.superPowerStates.isAIRunning = false;
                                        self.superPowerCSSAIMount(textAreaTarget, cm, 'css')
                                    }
                                    index++;
                                }
                            }
                
                            // Continue reading the next chunk
                            processChunk();
                        };
                
                        // Start processing chunks
                        await processChunk();
                    }
                };
                fetchDescription();
            },
            error: function(response){
                self.vueGlobalProp.$_showMessage('Something went wrong with the OpenAI AJAX request: ' + response);
            }
        }); 
    },
    setSuperPowerCSSObject: function(){
        const self = this;
        if (!self.builderStates.isClassActive) {
            self.superPowerStates.obj = self.builderStates.activeElement;
            self.superPowerStates.isActiveClass = false;
            self.superPowerStates.selector = self.helpers.getFinalSelector();
        } else {
            self.superPowerStates.isActiveClass = true;
            self.superPowerStates.selector = `.${self.vueState.activeClass.name}`;
            self.superPowerStates.obj = self.vueState.activeClass;
        }
        self.compilePartials(self.advancedCSSStates);
        self.compilePartialsVariables(self.advancedCSSStates);
    },
    addIconsToSuperpowerCSS: function(selector = "[data-controlkey=_cssSuperPowerCSS]"){
        const self = this;
        const controlKey = document.querySelector(selector);
        let action = '';
        let existing = '';
        (controlKey) ? existing = controlKey.querySelector('.CodeMirror[data-type="at"]') : existing = false;
        (controlKey) ? action = controlKey.querySelector('.brxc-action') : action = false;
        (existing && !action) ? existing.insertAdjacentHTML('beforeBegin', '<div class="brxc-action"></div>') : '';
        action = controlKey.querySelector('.brxc-action')
        if(action){
            const options = {
                "wrapper": action,
                "selector": selector,
                "root": true,
                "comment": true,
                "fullscreen": true,
                "contextualSuperpowercss": {
                    "component-selectors": true,
                    "beautify-css": true,
                    "variabilize-css": true,
                    "extract-global-classes": true,
                    "extract-global-variables": true,
                    "convert-UX-values": true,
                    "fullsize": true,
                },
                "collapse": true,
                "rootSelector": '%root%',
            }
            self.superPowerCSSIcons(options);
        }
    },
    addIconsToStickyCSS: function(selector = "[data-controlkey=_cssStickyCSS]"){
        const self = this;
        const controlKey = document.querySelector(selector);
        if(!controlKey) return;
        let action = controlKey.querySelector('.brxc-action');
        const existing = controlKey.querySelector('.CodeMirror[data-type="at"]');
        if(existing && !action) existing.insertAdjacentHTML('beforeBegin', '<div class="brxc-action"></div>');
        action = controlKey.querySelector('.brxc-action');
        if(!action) return;

        let options = {
            "wrapper": action,
            "selector": selector,
            "root": false,
            "fullscreen": true,
            "computed-values": true,
        }
        if(!self.stickyCssStates.computedValues === true){
            options = {
                "wrapper": action,
                "selector": selector,
                "root": true,
                "fullscreen": true,
                "computed-values": true,
                "contextualSuperpowercss": {
                    "component-selectors": true,
                    "beautify-css": true,
                    "variabilize-css": true,
                    "extract-global-classes": true,
                    "extract-global-variables": true,
                    "convert-UX-values": true
                },
                "rootSelector": '%root%',
            }
        }
        self.superPowerCSSIcons(options);
    },
    addMessageToSuperpowerCSS: function(){
        const self = this;
        const controlKey = document.querySelector('[data-controlkey="_cssSuperPowerCSS"]');
        let action = '';
        let existing = '';
        (controlKey) ? existing = controlKey.querySelector('.CodeMirror[data-type="at"]') : existing = false;
        (controlKey) ? action = controlKey.querySelector('.brxc-error-handling') : action = false;
        (existing && !action) ? existing.insertAdjacentHTML('afterend', '<div class="brxc-skip-remount brxc-error-handling"></div>') : '';
    },
    superPowerCSSIcons: function(options){
        const self = this;
        const optionKeys = Object.keys(options);
        // remove icons
        Array.from(options.wrapper.children).forEach(el => el.remove())

        // Root icon
        if(optionKeys.includes('root') && options['root']){
            self.addIconToFields(
                'div',
                'brxc-toggle-root',
                false,
                'Add %root% {}',
                'bottom-right',
                `ADMINBRXC.addRootTag(event,'${options.selector}')`,
                true,
                `<span class="bricks-svg-wrapper"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" class="brxc__svg-path"><path d="M28.5 40v-3h6q1.05 0 1.775-.725Q37 35.55 37 34.5v-5q0-1.85 1.125-3.3 1.125-1.45 2.875-2v-.4q-1.75-.5-2.875-1.975T37 18.5v-5q0-1.05-.725-1.775Q35.55 11 34.5 11h-6V8h6q2.3 0 3.9 1.6t1.6 3.9v5q0 1.05.725 1.775Q41.45 21 42.5 21H44v6h-1.5q-1.05 0-1.775.725Q40 28.45 40 29.5v5q0 2.3-1.6 3.9T34.5 40Zm-15 0q-2.3 0-3.9-1.6T8 34.5v-5q0-1.05-.725-1.775Q6.55 27 5.5 27H4v-6h1.5q1.05 0 1.775-.725Q8 19.55 8 18.5v-5q0-2.3 1.6-3.9T13.5 8h6v3h-6q-1.05 0-1.775.725Q11 12.45 11 13.5v5q0 1.85-1.125 3.325T7 23.8v.4q1.75.55 2.875 2T11 29.5v5q0 1.05.725 1.775Q12.45 37 13.5 37h6v3Z"></path></svg></span>`,
                options.wrapper,
                'child'
            );
        }

        // Comment
        if(optionKeys.includes('comment') && options['comment']){
            self.addIconToFields(
                'div',
                'brxc-toggle-comment',
                false,
                'Comment Selected Code',
                'bottom-right',
                `ADMINBRXC.commentCode('${options.selector}')`,
                true,
                `<span class="bricks-svg-wrapper"><i class="fas fa-eye"></i></span>`,
                options.wrapper,
                'child'
            );
        }

        // Full screen
        if(optionKeys.includes('fullscreen') && options['fullscreen']){
            self.addIconToFields(
                'div',
                'brxc-toggle-fullscreen',
                false,
                'Fullscreen',
                'bottom-right',
                `ADMINBRXC.addFullScreenCSS(event,'${options.selector}')`,
                true,
                `<span class="bricks-svg-wrapper"><i class="fas fa-display"></i></span>`,
                options.wrapper,
                'child'
            );
        }

        // Computed Values
        const iconComputedValuesClasses = self.stickyCssStates.computedValues ? 'brxc-toggle-computed active' : 'brxc-toggle-computed';
        if(optionKeys.includes('computed-values') && options['computed-values']){
            self.addIconToFields(
                'div',
                iconComputedValuesClasses,
                false,
                'Computed CSS',
                'bottom-right',
                `ADMINBRXC.toggleComputedValues()`,
                true,
                `<span class="bricks-svg-wrapper"><i class="fas fa-calculator"></i></span>`,
                options.wrapper,
                'child'
            );
        }

        // Selector Picker
        const iconSelectorPickerClasses = self.selectorPickerState.active ? "brxc-toggle-selector-picker active" : "brxc-toggle-selector-picker";
        if(optionKeys.includes('selector-picker') && options['selector-picker']){
            self.addIconToFields(
                'div',
                iconSelectorPickerClasses,
                false,
                'Selector Picker',
                'bottom-right',
                `ADMINBRXC.toggleSelectorPicker(event,'${options.selector}')`,
                true,
                `<span class="bricks-svg-wrapper"><i class="fas fa-crosshairs"></i></span>`,
                options.wrapper,
                'child'
            );
        }

        // advanced features
        if(optionKeys.includes('contextualSuperpowercss') && options['contextualSuperpowercss']){
            self.addIconToFields(
                'div',
                'brxc-toggle-advanced',
                false,
                'Advanced Features',
                'bottom-right',
                `event.stopPropagation();ADMINBRXC.sscsOpenAdvancedFeatures(event,'${options.selector}', '${options.rootSelector}', '${JSON.stringify(options['contextualSuperpowercss'])}')`,
                true,
                `<span class="bricks-svg-wrapper"><i class="fas fa-ellipsis"></i></span>`,
                options.wrapper,
                'child'
            );
        }
        
        //Collapse
        if(optionKeys.includes('collapse') && options['collapse']){
            let balloon = self.vueState.isPanelExpanded ? 'Collapse' : 'Expand';
            let icon = self.vueState.isPanelExpanded ? `<svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><path d="M217.9,256l127.1,-127c9.4,-9.4 9.4,-24.6 0,-33.9c-9.4,-9.4 -24.6,-9.3 -34,0l-144,143.9c-9.1,9.1 -9.3,23.7 -0.7,33.1l144.6,144.9c4.7,4.7 10.9,7 17,7c6.1,0 12.3,-2.3 17,-7c9.4,-9.4 9.4,-24.6 0,-33.9l-127,-127.1Z" fill="currentColor"></path></svg>` : `<svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><path d="M294.1,256l-127.1,-127c-9.4,-9.4 -9.4,-24.6 0,-33.9c9.4,-9.3 24.6,-9.3 34,0l144,143.9c9.1,9.1 9.3,23.7 0.7,33.1l-144.6,144.9c-4.7,4.7 -10.9,7 -17,7c-6.1,0 -12.3,-2.3 -17,-7c-9.4,-9.4 -9.4,-24.6 0,-33.9l127,-127.1Z" fill="currentColor"></path></svg>`; 
            self.addIconToFields(
                'div',
                'brxc-toggle-collapse',
                false,
                balloon,
                'bottom-right',
                `ADMINBRXC.addResizeCSS(this,'${options.selector}')`,
                true,
                icon,
                options.wrapper,
                'child'
            );
        }
    },
    addFullSizeCSSState: function(){
        const self = this;
        if(!self.builderStates.isElementActive || self.vueState.activePanelTab !== "style" || self.vueState.activePanelGroup !== "_css" ) return;
        
        const description = document.querySelector('body.at-superpower-css #bricks-panel-element [data-controlkey="_cssSuperPowerCSS"] .description');
        if(!description) return;
        self.superPowerStates.fullScreen !== true ? description.classList.add('visible') : description.classList.remove('visible');
    },
    addFullSizeCSS: function(){
        const self = this;
        self.superPowerStates.fullScreen === true ? self.superPowerStates.fullScreen = false : self.superPowerStates.fullScreen = true;
        self.vueState.rerenderControls = Date.now();

    },
    addResizeCSS: function(target,  closest){
        const self = this;
        self.vueState.isPanelExpanded = !self.vueState.isPanelExpanded;
        let balloon = self.vueState.isPanelExpanded ? 'Collapse' : 'Expand';
        let icon = self.vueState.isPanelExpanded ? `<svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><path d="M217.9,256l127.1,-127c9.4,-9.4 9.4,-24.6 0,-33.9c-9.4,-9.4 -24.6,-9.3 -34,0l-144,143.9c-9.1,9.1 -9.3,23.7 -0.7,33.1l144.6,144.9c4.7,4.7 10.9,7 17,7c6.1,0 12.3,-2.3 17,-7c9.4,-9.4 9.4,-24.6 0,-33.9l-127,-127.1Z" fill="currentColor"></path></svg>` : `<svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><path d="M294.1,256l-127.1,-127c-9.4,-9.4 -9.4,-24.6 0,-33.9c9.4,-9.3 24.6,-9.3 34,0l144,143.9c9.1,9.1 9.3,23.7 0.7,33.1l-144.6,144.9c-4.7,4.7 -10.9,7 -17,7c-6.1,0 -12.3,-2.3 -17,-7c-9.4,-9.4 -9.4,-24.6 0,-33.9l127,-127.1Z" fill="currentColor"></path></svg>`; 
        target.setAttribute('data-balloon', balloon);
        target.innerHTML = icon;

        //refresh
        const cm = document.querySelector(`${closest} .CodeMirror`).CodeMirror;
        if(!cm) return;
        setTimeout(() => {
            cm.refresh();
        },250)
    },
    addFullScreenCSS: function(event, closest){
        const self = this;
        const target = event.target;
        const controlKey = target.closest(closest);
        if(!controlKey) return;
        controlKey.classList.toggle('at-full-screen');
        document.body.classList.toggle('at-full-screen')

        const cm = controlKey.querySelector('.CodeMirror[data-type="at"]')
        if(!cm) return;

        cm.CodeMirror.refresh()

    },
    toggleComputedValues: function(){
        const self = this;
        
        self.stickyCssStates.computedValues = !self.stickyCssStates.computedValues;
        self.stickyCssStates.forceMount = true;
        
        // Local Storage
        self.helpers.setLocalStorage('stickyCssComputed', self.stickyCssStates.computedValues )

        self.setStickyCSSObject()
    },
    selectorPickerState: {
        active: false,
        cm: false
    },
    toggleSelectorPicker: function(event, closest){
        const self = this;
        const wrapper = document.querySelector('#brxcCSSOverlay');
        const target = event.target;
        const controlKey = target.closest(closest);
        if(!controlKey) return;
        const cm = controlKey.querySelector('.CodeMirror[data-type="at"]')
        if(!cm) return;

        self.selectorPickerState.active = !self.selectorPickerState.active;
        self.selectorPickerState.cm = self.selectorPickerState.active ? cm.CodeMirror : false;

        // Disable Selector Picker 
        if(!self.selectorPickerState.active){
            self.advancedCSSInit();

        // Enable Selector Picker
        } else {
            FRAMEBRXC.content.body.classList.add('at-selector-picker');
            wrapper.classList.add('at-selector-picker');
            target.classList.add('active');
        }
    },
    disableSelectorPicker: function(){
        const self = this;
        
        self.selectorPickerState.active = false;
        FRAMEBRXC.content.body.classList.remove('at-selector-picker');
        
        const wrapper = document.querySelector('#brxcCSSOverlay');
        if(wrapper) wrapper.classList.remove('at-selector-picker');
    },
    selectorPickerInit: function() {
        const self = this;

        FRAMEBRXC.content.body.addEventListener('click', (event) => {
            if(!self.selectorPickerState.active || !self.selectorPickerState.cm) return;
            const existingValue = self.selectorPickerState.cm.getValue();
            let separator = '\n\n'
            if(existingValue === '' || existingValue.endsWith('\n\n')){
                separator = ''
            } else if(existingValue.endsWith('\n')){
                separator = '\n'
            }

            const selector = self.helpers.getCSSSelector(event.target);
            if(selector) self.selectorPickerState.cm.setValue(`${self.selectorPickerState.cm.getValue()}${separator}${selector} {\n  \n}`);
        })
        
    },
    sscsOpenAdvancedFeatures: function(event, closest, selector, json){
        const self = this;
        const rect = event.target.getBoundingClientRect();
        const existingModal = document.querySelector('#sscsOpenAdvancedFeatures');
        if(existingModal) existingModal.remove();

        const a = document.createElement('DIV');
        a.id = "sscsOpenAdvancedFeatures";
        a.classList.add('brxc-context-menu');
        a.classList.add('show');
        const options = JSON.parse(json);
        let fullSizeLabel = self.superPowerStates.fullScreen === false ? 'Hide Shortcuts Cheatsheet' : 'Show Shortcuts Cheatsheet';
        let content = `<ul>`
        options.hasOwnProperty('component-selectors') && options["component-selectors"] ? content += `<li ${self.builderStates.isElementActive ? `onclick="ADMINBRXC.addComponentSelectors('${closest}')"` : 'class="disabled"'}>Add Component Selectors</li>` : '';
        options.hasOwnProperty('beautify-css') && options["beautify-css"] ? content +=`<li onclick="ADMINBRXC.beautifyCSS('${closest}')"><span class="label">Beautify CSS</span><span class="shortcut">${self.vueState.isMac ? 'CMD + B' : 'CTRL + B'}</span></li>` : '';
        options.hasOwnProperty('variabilize-css') && options["variabilize-css"] ? content += `<li onclick="ADMINBRXC.variabilizeCSS('${closest}', '${selector}')">Variabilize CSS</li>` : '';
        options.hasOwnProperty('extract-global-classes') && options["extract-global-classes"] ? content += `<li onclick="ADMINBRXC.parseGlobalCSS('${closest}')">Extract Classes & Add them as Global Classes</li>` : '';
        options.hasOwnProperty('extract-global-variables') && options["extract-global-variables"] ? content += `<li onclick="ADMINBRXC.extractGlobalVariables('${closest}')">Extract Variables & Add them as Global Variables</li>` : '';
        options.hasOwnProperty('convert-UX-values') && options["convert-UX-values"] ? content += `<li onclick="ADMINBRXC.convertUXinCSS('${closest}')">Convert UX values to CSS</li>` : '';
        options.hasOwnProperty('fullsize') && options["fullsize"] ? content += `<li class="sep"></li><li onclick="ADMINBRXC.addFullSizeCSS()">${fullSizeLabel}</li>` : '';
        content +=`</ul>`;
        a.innerHTML = content;
        document.body.appendChild(a);
        const rectMenu = a.getBoundingClientRect();
        a.style.top = `${rect.top}px`;
        a.style.left = `max(0px, calc(${rect.left}px + ${rect.width}px - ${rectMenu.width}px))`;


        // Listeners
        const x = document.querySelector('#bricks-builder-iframe').contentWindow;
        function openMenu() {
            window.addEventListener('click', windowClickListener);
            x.document.addEventListener('click', windowClickListener);
        }
        
        function closeMenu() {
            window.removeEventListener('click', windowClickListener);
            x.document.removeEventListener('click', windowClickListener);
            if(a) a.classList.remove('show');

        }
        
        function windowClickListener(event) {
            closeMenu();
        }
        openMenu();
    },
    destroySassInstances: function(type){
        const self = this;
        const arr = type === 'advancedCss' ? self.sassInstances : self.superPowerStates.sassInstances;
        arr.forEach(sassInstance => {
            sassInstance.destroy();
        })
        self.sassInstances.length = 0; 
    },
    createSassInstance: function(type){
        const self = this;
        const sass = new Sass();
        type === 'advancedCss' ? self.sassInstances.push(sass) : self.superPowerStates.sassInstances.push(sass);
        return sass;
    },
    addListenersToSuperPowerCSS: function(MyCM, selector = `[data-controlkey=_cssSuperPowerCSS]`) {
        const self = this;
        const target = self.helpers.createTarget('_cssCustom');
        const targetSass = self.helpers.createTarget('_cssCustomSass');
        const metaKey = (e) => self.vueState.isMac ? e.metaKey : e.ctrlKey;
        let sass = false;
        if (self.globalSettings.superPowerCSSEnableSass === "1"){
            self.destroySassInstances();
            sass = self.createSassInstance();
        }

        function handleCSSChangePromise(cm, obj) {
            return new Promise(function(resolve, reject) {
                try {
                    handleCSSChange(cm, obj);
                    resolve();
                } catch (e) {
                    reject(e);
                }
            });
        }
        
        function saveChangesPromise(className) {
            return new Promise(function(resolve, reject) {
                try {
                    self.helpers.saveChanges(className);
                    resolve();
                } catch (e) {
                    reject(e);
                }
            });
        }

        function handleCSSChange(cm, settingsObj) {
            const newValue = self.vueGlobalProp.$_replaceCustomCssRoot('%root%', self.superPowerStates.selector, cm.getValue());
             if (newValue === "") {
                self.advancedCSSRemoveError(document.querySelector('[data-controlkey="_cssSuperPowerCSS"]'));
                 setTimeout(() => {
                     delete settingsObj.settings[target];
                     if (self.globalSettings.superPowerCSSEnableSass === "1") delete settingsObj.settings[targetSass];
                    
                 }, 10);
             } else {
                 if (self.globalSettings.superPowerCSSEnableSass === "1") {
                     const dataOptions = { indent_size: 2 };
                     settingsObj.settings[targetSass] = newValue;

                     // Compiled CSS
                     if(sass){
                        sass.compile(self.advancedCSSStates.partials+newValue, function(result) {
                            if (result.status === 0) {
                                self.advancedCSSRemoveError(document.querySelector('[data-controlkey="_cssSuperPowerCSS"]'));
                                const strippedComment = self.helpers.removeCommentedCSS(result.text) || false;
                                const removedCharset = strippedComment && self.helpers.removeCharsetCSS(strippedComment) || false;

                                if (removedCharset) {
                                    settingsObj.settings[target] = css_beautify(removedCharset, dataOptions);
                                }

                            } else {
                               self.advancedCSSHandleError(result, document.querySelector('[data-controlkey="_cssSuperPowerCSS"]'))
                            }
                        });
                     }
                 } else {
                     // APPLY THE VALUE INSIDE THE ELEMENT/GLOBAL CLASS OBJECT
                     settingsObj.settings[target] = newValue;
                 }
             }

            // Add as modified
            if(self.superPowerStates.isActiveClass){
                settingsObj.modified = Date.now();
                settingsObj.user_id = bricksData.loadData.currentUserId
                self.helpers.saveChanges('globalClasses');
                if(!self.vueState.globalChanges.modified.includes(self.vueState.activeClass.id)) self.vueState.globalChanges.modified.push(self.vueState.activeClass.id);
            } else if(self.helpers.isComponentActive()){
                self.helpers.saveChanges('components');
            } else {
                self.helpers.saveChanges(self.helpers.getTemplateType());
            }
        }
         MyCM.on("keydown", function (cm, event) {  

            // Save
            if(metaKey(event) && event.key === "s" ){
                event.preventDefault();
                event.stopPropagation();
                handleCSSChangePromise(cm, self.superPowerStates.obj)
                    .then(function() {
                        if (self.superPowerStates.isActiveClass) {
                            return saveChangesPromise('globalClasses');
                        } else {
                            return saveChangesPromise('content');
                        }
                    })
                    .then(function() {
                        self.vueGlobalProp.$_savePost();
                    })
                    .catch(function(error) {
                        self.vueGlobalProp.$_showMessage('Error while saving:', error);
                    });
                return;
            } 

            // Beautify
            if(metaKey(event) && event.key === "b" ){
                event.preventDefault();
                event.stopPropagation();
                return self.beautifyCSS(selector)
            }

            // Search
            if(metaKey(event) && event.key === "f" ){
                event.preventDefault();
                event.stopPropagation();
                return cm.execCommand('find');
            }

            // Comments
            if(metaKey(event) && event.shiftKey && event.key === "7" ){
                return cm.toggleComment();
            }

            // Tabs
            if (event.key === 'Tab') {
                return self.helpers.replaceRWithRoot(MyCM, event)
               
            }

            // Autocomplete

            const keyCondition = (
                (event.key >= '0' && event.key <= '9') ||    // Digits 0-9
                (event.key >= 'a' && event.key <= 'z') ||    // Letters a-z
                event.key === '(' ||                         // Opening parenthesis (
                event.key === '!' ||                         // Exclamation mark
                event.key === '-' ||                         // Dash
                event.key === '@' ||                         // At symbol
                event.key === '$' ||                         // Dollar sign
                event.key === 'Backspace'                       // Delete key
            ) &&
            !event.metaKey && !event.altKey && !event.ctrlKey &&
            event.key !== '{' && event.key !== '}';
            if (!cm.state.completionActive && keyCondition) {
                CodeMirror.commands.autocomplete(cm, null, { completeSingle: false });
                return;
            }
         })
         const debouncedCSSChange = self.debounce(function(cm, activeObj) {
            handleCSSChange(cm, activeObj);
        }, 100);
        
        MyCM.on("change", function(cm, event) {
            debouncedCSSChange(cm, self.superPowerStates.obj);
        });
    },
    updateSuperPowerCSS: function(MyCM, computedValues = false){
        const self = this;

        // Computed Values
        if(computedValues){
            function generateCSS(){
                const type = self.builderStates.isClassActive ? "globalClass" : "element";
                const elementObj = self.builderStates.activeElement;
                const finalObj = self.builderStates.activeObject;
                if(!elementObj) return;

                let previewCSS = self.vueGlobalProp.$_generateCss(type, finalObj, [elementObj.name]).replaceAll(`.brxe-${elementObj.name}`, '');
                
                if(self.helpers.isComponentActive()) previewCSS = previewCSS.replaceAll('#brxe-', '.brxe-')
                const beautifiedCSS = css_beautify(previewCSS, { indent_size: 2 });
                const finalCode = beautifiedCSS === "" ? "/* No Style applied */" : beautifiedCSS;
                return finalCode;
            }
            const finalCode = generateCSS();
            MyCM.setValue(finalCode);
            return
        }

        // Custom CSS
        self.setSuperPowerCSSObject();
        const activeEl = self.superPowerStates.obj;
        if(!activeEl || !activeEl.hasOwnProperty('settings')) return;
        
        const maybeSassTarget = self.helpers.createTarget('_cssCustomSass');
        let target = self.globalSettings.superPowerCSSEnableSass === "1" && activeEl.settings.hasOwnProperty(maybeSassTarget) ? maybeSassTarget : self.helpers.createTarget('_cssCustom');
        const settings = (activeEl.settings.hasOwnProperty(target)) ? activeEl.settings[target] : '';
        const finalValue = self.vueGlobalProp.$_replaceCustomCssRoot(self.superPowerStates.selector, '%root%', settings)
        MyCM.setValue(finalValue);
        if(finalValue !== '') self.superPowerStates.hasValue = true;
    },
    forceClassStlyesStates: {
        showLock: true,
        lastElementId: ''
    },
    forceClassStlyes: function (){
        const self = this;
        if(!self.builderStates.isElementActive) return;

        const panel = document.querySelector('#bricks-panel-element');
        if(!panel) return;

        const contentControls = panel.querySelectorAll('.bricks-panel-controls ul.controls li');
        const elementObj = self.builderStates.activeElement;
        if(!elementObj) return;

        if(contentControls.length > 0){
            const name = elementObj.name;
            contentControls.forEach(el => {
                const data = el.dataset.controlkey;
                if(bricksData.elements[name]?.controls[data] && bricksData.elements[name].controls[data].hasOwnProperty('css')) el.style.display = "block";
            })
        }
        const tabs = panel.querySelector('ul#bricks-panel-tabs');
        if (!tabs) return;

        if (self.builderStates.isClassActive || (self.globalSettings.classFeatures.lockIdWithClasses === "1" && !self.helpers.hasUnlockedGlobalClass(elementObj.id) ) ) {
            self.forceClassStlyesStates.showLock = false;
            self.forceClassStlyesStates.lastElementId = '';
        } else if (self.forceClassStlyesStates.lastElementId !== elementObj.id){
            self.forceClassStlyesStates.showLock = true
            self.forceClassStlyesStates.lastElementId = elementObj.id;
        }
        const styleTab = tabs.querySelectorAll('li')[1];
        const icon = panel.querySelector('.disabled-style-icon');
        (icon) ? icon.remove() : '';

        panel.setAttribute("data-has-class", "true")
        styleTab.classList.remove('brxc-style-tab-disabled')

        //if state brxc.showLock is true
        if(self.forceClassStlyesStates.showLock === true) {
            if(contentControls.length > 0){
                const name = elementObj.name;
                contentControls.forEach(el => {
                    const data = el.dataset.controlkey;
                    if(bricksData.elements[name]?.controls[data] && bricksData.elements[name].controls[data].hasOwnProperty('css')) el.style.display = "none";
                })
            }
            panel.removeAttribute("data-has-class");
            self.vueState.activePanelTab = "content";
            styleTab.classList.add('brxc-style-tab-disabled')
            self.addIconToFields('div','disabled-style-icon', false, 'Click to unlock styling on ID level', 'top-right', false, false,  '<span class="bricks-svg-wrapper"><i class="fas fa-lock"></span>', tabs, 'child');
            const icon = panel.querySelector('.disabled-style-icon')
            icon.addEventListener('click', () =>{
                self.forceClassStlyesStates.showLock = false;
                icon.remove();
            })

        }

    },
    classContextualMenu: function(){
        const self = this;
        const shortcutPrefix = self.vueState.isMac ? 'CTRL + CMD' : 'CTRL + SHIFT';
        const activeObj = self.builderStates.activeElement
        let content = "";

        function isElementHidden(){
            const target = self.helpers.createTarget('_display');
            if(typeof activeObj === "undefined" || !activeObj.hasOwnProperty('settings') || !activeObj.settings.hasOwnProperty(target) || activeObj.settings[target] !== "none") {
                return false;
            }
            return true;
        }

        function isRootComponent(){
            if(activeObj.settings.hasOwnProperty('classConverterComponent') && activeObj.settings.classConverterComponent === true){
                return true;
            } 
            return false;
        }
        let globalContent = `<li class="sep"></li>
                                <li onclick="ADMINBRXC.openPlainClassesModal(event, &quot;#brxcPlainClassesOverlay&quot;)">
                                    <span class="label">Plain Classes</span>
                                    <span class="shortcut">${shortcutPrefix} + ${self.globalSettings.keyboardShortcuts.plainClasses}</span>
                                </li>
                                <li onclick="ADMINBRXC.openFindReplaceModal(event,false, &quot;#brxcFindReplaceModal&quot;)">
                                    <span class="label">Find &amp; Replace Styles</span>
                                    <span class="shortcut">${shortcutPrefix} + ${self.globalSettings.keyboardShortcuts.findAndReplace}</span>
                                </li>
                                <li onclick="ADMINBRXC.openModal({target: false, id: &quot;#brxcStyleOverviewOverlay&quot;, focus: &quot;#brxcStyleOverviewOverlay input[type=text]&quot;, callback: () => {ADMINBRXC.styleOverviewInit(ADMINBRXC.helpers.getFinalObject(true),true);}});">Style Overview</li>`
        globalContent += `<li onclick="ADMINBRXC.openModal({target: false, id: &quot;#brxcClassConverterOverlay&quot;, callback: () => {ADMINBRXC.setClassConverter();}})" ;'=""><span class="label">Class Converter</span><div class="buttons"><span class="action" data-balloon="${isRootComponent() ? 'Disable Root Component' : 'Enable Root Component'}" data-balloon-pos="top" onclick="event.stopPropagation();ADMINBRXC.rootClassComponentToggle()"><i class="fas fa-toggle-${isRootComponent() ? 'on' : 'off'}"></i></span></div></li>`;
        if(!self.builderStates.isClassActive){
            content += `<ul>`
            content += `<li onclick="ADMINBRXC.hideElement()"><span class="label">${isElementHidden() ? 'Show' : 'Hide'} Element</span>`;
            content += `<span class="bricks-svg-wrapper action frontend${activeObj.settings.hasOwnProperty('_hideElementFrontend') && activeObj.settings._hideElementFrontend === true ? ' active' : ''}" data-balloon="Remove on Frontend" data-balloon-pos="top-right" onclick="event.stopPropagation();ADMINBRXC.removeElementFrontend();ADMINBRXC.openContextualMenu(false, () => {return ADMINBRXC.classContextualMenu()});">F</span>`;
            content += `<span class="bricks-svg-wrapper action builder${activeObj.settings.hasOwnProperty('_hideElementBuilder') && activeObj.settings._hideElementBuilder === true ? ' active' : ''}" data-balloon="Hide in Builder" data-balloon-pos="top-right" onclick="event.stopPropagation();ADMINBRXC.hideElementBuilder();ADMINBRXC.openContextualMenu(false, () => {return ADMINBRXC.classContextualMenu()});">B</span>`;
            content += `</li>`;
        
            content += `<li class="sep"></li>
                    <li onclick="ADMINBRXC.exportIDStylestoClass()">Export ID Styles to Class</li>
                    <li onclick="ADMINBRXC.openExtendClassModal(event,&quot;#brxcExtendModal&quot;)">Extend Classes &amp; Styles</li>`
            if(self.globalSettings.defaultElementFeatures.includes('logical-properties')) {
                content += `<li onclick="ADMINBRXC.convertObjToLogical()">
                                <span class="label">Convert ID Styles & Classes to Logical Properties</span>
                                <div class="buttons">
                                    <span class="action" data-balloon="Include Children" data-balloon-pos="top" onclick="event.stopPropagation();ADMINBRXC.convertObjToLogical(true)"><i class="fas fa-repeat"></i></span>
                                </div>
                            </li>`;
            }
            content += `<li class="sep"></li>
                    <li onclick="ADMINBRXC.copyAllClasses()">Copy All Classes</li>
                    <li onclick="ADMINBRXC.pasteAllClasses()">Paste All Classes</li>
                    <li onclick="ADMINBRXC.mergeClasses()">Merge All Classes</li>
                    <li onclick="ADMINBRXC.resetAllClasses()"class="delete">Reset All Classes</li>
                    <li class="sep"></li>
                    <li onclick="ADMINBRXC.openClassManager(&quot;component&quot;);">Component Class Manager</li>`
            content += globalContent;
            content += `</ul>`;
        } else {
            content += `<ul>`
            content += `<li onclick="ADMINBRXC.hideElement()"><span class="label">${isElementHidden() ? 'Show' : 'Hide'} Element</span>`;
            if(Object.values(self.globalSettings.defaultElementFeatures).includes('hide-remove-element')) {
                content += `<span class="bricks-svg-wrapper action frontend${activeObj.settings.hasOwnProperty('_hideElementFrontend') && activeObj.settings._hideElementFrontend === true ? ' active' : ''}" data-balloon="Remove on Frontend" data-balloon-pos="top-right" onclick="event.stopPropagation();ADMINBRXC.removeElementFrontend();ADMINBRXC.openContextualMenu(false, () => {return ADMINBRXC.classContextualMenu()});">F</span>`;
                content += `<span class="bricks-svg-wrapper action builder${activeObj.settings.hasOwnProperty('_hideElementBuilder') && activeObj.settings._hideElementBuilder === true ? ' active' : ''}"" data-balloon="Hide in Builder" data-balloon-pos="top-right" onclick="event.stopPropagation();ADMINBRXC.hideElementBuilder();ADMINBRXC.openContextualMenu(false, () => {return ADMINBRXC.classContextualMenu()});">B</span>`;
            }
            content += `</li>`;
            content +=`<li class="sep"></li>
                    <li onclick="ADMINBRXC.importIDStylestoClass()">Import ID Styles to Class</li>
                    <li onclick="ADMINBRXC.openExtendClassModal(event,&quot;#brxcExtendModal&quot;)">Extend Classes &amp; Styles</li>`
            if(self.globalSettings.defaultElementFeatures.includes('logical-properties')) {
                content += `<li onclick="ADMINBRXC.convertObjToLogical()">
                                <span class="label">Convert ID Styles & Classes to Logical Properties</span>
                                <div class="buttons">
                                    <span class="action" data-balloon="Include Children" data-balloon-pos="top" onclick="event.stopPropagation();ADMINBRXC.convertObjToLogical(true)"><i class="fas fa-repeat"></i></span>
                                </div>
                            </li>`;
            }
            content += `<li class="sep"></li>
                    <li onclick="ADMINBRXC.cloneClass()">Clone Class</li>
                    <li onclick="ADMINBRXC.copytoClipboardSimple('${self.vueState.activeClass.name}','${self.vueState.activeClass.name} successfully copied to clipboard')">Copy ${self.vueState.activeClass.name} to Clipboard</li>
                    <li onclick="ADMINBRXC.removeCurrentClass('${self.vueState.activeClass.id}', true)">Remove Class from Element</li>
                    <li onclick="ADMINBRXC.deleteCurrentClass('${self.vueState.activeClass.id}')"class="delete">${self.vueState.globalClassesTrash && Array.isArray(self.vueState.globalClassesTrash) ? 'Move Class to Trash' : 'Delete Class'}</li>
                    <li class="sep"></li>
                    <li onclick="ADMINBRXC.copyAllClasses()">Copy All Classes</li>
                    <li onclick="ADMINBRXC.pasteAllClasses()">Paste All Classes</li>
                    <li onclick="ADMINBRXC.mergeClasses()">Merge All Classes</li>
                    <li onclick="ADMINBRXC.resetAllClasses()"class="delete">Reset All Classes</li>
                    <li class="sep"></li>
                    <li onclick="ADMINBRXC.openClassInManager('${self.vueState.activeClass.id}')">
                        <span class="label">Open Class in Class Manager</span>
                        <span class="shortcut">${shortcutPrefix} + ${self.globalSettings.keyboardShortcuts.classManager}</span>
                    </li>
                    <li onclick="ADMINBRXC.openClassManager(&quot;component&quot;);">Component Class Manager</li>`
            content += globalContent;
            content += `</ul>`;

        }

        return content;
    },
    structureContextualMenu: function(){
        const self = this;
        let content = '';

        function printItem(item){
            const shortcut = self.vueState.isMac ? "CMD + CTRL" : "CTRL + SHIFT"
            if(item.condition === false) return '';
            if(item.label === "sep"){
                return `<li class="sep"></<li>`
            }
            return `<li onclick="${item.onClick}">
                        <span>
                            ${item.icon ? `<div class="brxc-item-icon">${item.icon}</div>` : ''}
                            ${item.label}
                            <div class="brxc-item-doc" data-balloon="documentation" onClick="event.stopPropagation();window.open('${item.url}', '_blank');">
                                <i class="fas fa-external-link-alt"></i>
                            </div>
                        </span>
                        <div class="action-wrapper">
                        ${item.shortcut ? `<span class="shortcut">${shortcut} + ${item.shortcut}</span>`: ''}
                        ${item.icons.map(el => {
                            return `<span class="bricks-svg-wrapper action${el.isActive ? ' active': ''}" data-balloon="${el.balloon}" data-balloon-pos="${el.pos}" onclick="event.stopPropagation();${el.onClick}"><i class="${el.icon}"></i></span>`
                        }).join('')}
                        </div>
                    </li>`
        }

        function printTweak(item){
            const isActive = self.structurePanelStates.tweaks.includes(item.key);
            return `<li onclick="event.stopPropagation();${item.onClick}">
                        <span>
                            ${item.label}
                            <div class="brxc-item-doc" data-balloon="documentation" onClick="event.stopPropagation();window.open('${item.url}', '_blank');">
                                <i class="fas fa-external-link-alt"></i>
                            </div>
                        </span>
                        <span class="bricks-svg-wrapper action active" ><i class="fas fa-toggle-${isActive ? 'on': 'off'}"></i></span>
                    </li>`
        }

        function checkShortcutState(key){
            return self.structurePanelStates.icons.includes(key);
        }
        
        // Tag Label
        let tagLabel = "Tag Manager <span class='error'>(disabled)</span>";
        if (self.elementsTagStates.mode !== '') tagLabel = `Tag Manager <span class='success'>(mode: ${self.elementsTagStates.mode})</span>`

        // Note Label
        let notesLabel = "Notes <span class='error'>(disabled)</span>"
        if(self.noteStates.active === 'adminNotes') notesLabel = "Notes <span class='success'>(for admins)</span>";
        if(self.noteStates.active === 'editorNotes') notesLabel = "Notes <span class='success'>(for editors)</span>";
        
        // Elements Order Label
        let elementsOrderLabel = "Elements Order <span class='error'>(unlocked)</span>"
        if(self.lockDraggableElementsStates.active) elementsOrderLabel = "Elements Order <span class='success'>(locked)</span>"

        // StickyCSS Label
        let stickyCSSLabel = "Sticky CSS <span class='error'>(disabled)</span>"
        if(self.stickyCssStates.active) stickyCSSLabel = "Sticky CSS <span class='success'>(enabled)</span>"

        // Visibility Floating Bar Label
        let visibilityLabel = "Visibility Floating Bar <span class='error'>(disabled)</span>"
        if( self.hideElementStates.active) visibilityLabel = "Visibility Floating Bar <span class='success'>(enabled)</span>"

        const modals = [
            {
                label: "Structure Generator",
                url: 'https://advancedthemer.com/features/structure-generator/',
                icon: '<i class="bricks-svg fas fa-bars-staggered"></i>',
                shortcut: self.globalSettings.keyboardShortcuts.codepenConverter,
                onClick: "ADMINBRXC.openModal({target: false, id: '#brxcCodePenImporter', callback: () => {ADMINBRXC.codepenImporterInit();}});",
                icons: [
                    {
                        key: "structure-generator",
                        icon: "fas fa-star",
                        balloon: "Add to Structure header",
                        pos: "top-right",
                        onClick: "ADMINBRXC.toggleStructureHeaderIcon('structure-generator')",
                        isActive: checkShortcutState('structure-generator')
                    }
                ]
            },
            {
                label: "Structure Helper",
                url: 'https://advancedthemer.com/features/structure-panel-helper/',
                icon: '<i class="fas fa-circle-question"></i>',
                shortcut: self.globalSettings.keyboardShortcuts.structureHelper,
                onClick: "ADMINBRXC.openModal({target: false, id: '#brxcStructureHelper', callback: () => {ADMINBRXC.setStructureHelper();}});",
                icons: [
                    {
                        key: "structure-helper",
                        icon: "fas fa-star",
                        balloon: "Add to Structure header",
                        pos: "top-right",
                        onClick: "ADMINBRXC.toggleStructureHeaderIcon('structure-helper')",
                        isActive: checkShortcutState('structure-helper')
                    }
                ]
            },
            {
                label: "Nested Elements Library",
                url: 'https://advancedthemer.com/features/nested-elements-library/',
                icon: '<i class="fas fa-address-card"></i>',
                shortcut: self.globalSettings.keyboardShortcuts.nestedElemenets,
                onClick: "ADMINBRXC.openModal({target: false, id: '#brxcCustomComponentsOverlay', callback: () => {ADMINBRXC.setCustomComponents();}});",
                icons: [
                    {
                        key: "nested-elements-library",
                        icon: "fas fa-star",
                        balloon: "Add to Structure header",
                        pos: "top-right",
                        onClick: "ADMINBRXC.toggleStructureHeaderIcon('nested-elements-library')",
                        isActive: checkShortcutState('nested-elements-library')
                    }
                ]
            }
        ];

        const states = [
            {
                label: tagLabel,
                url: 'https://advancedthemer.com/features/tag-manager-inside-the-structure-panel/',
                icon: '<i class="fas fa-tag"></i>',
                onClick: "event.stopPropagation();ADMINBRXC.toggleTagsState();ADMINBRXC.toggleStructureMode();",
                icons: [
                    {
                        key: "tag-manager",
                        icon: "fas fa-star",
                        balloon: "Add to Structure header",
                        pos: "top-right",
                        onClick: "ADMINBRXC.toggleStructureHeaderIcon('tag-manager')",
                        isActive: checkShortcutState('tag-manager')
                    }
                ]
            },
            {
                label: notesLabel,
                url: 'https://advancedthemer.com/features/admin-editor-notes/',
                icon: '<i class="ti-comment-alt"></i>',
                onClick: "event.stopPropagation();ADMINBRXC.toggleNotesState();ADMINBRXC.toggleStructureMode();",
                icons: [
                    {
                        key: "notes",
                        icon: "fas fa-star",
                        balloon: "Add to Structure header",
                        pos: "top-right",
                        onClick: "ADMINBRXC.toggleStructureHeaderIcon('notes')",
                        isActive: checkShortcutState('notes')
                    }
                ]
            },
            {
                label: elementsOrderLabel,
                url: 'https://advancedthemer.com/features/lock-elements-order/',
                icon: '<i class="ti-lock"></i>',
                onClick: "event.stopPropagation();ADMINBRXC.toggleLockElementsState();ADMINBRXC.toggleStructureMode();",
                icons: [
                    {
                        key: "elements-order",
                        icon: "fas fa-star",
                        balloon: "Add to Structure header",
                        pos: "top-right",
                        onClick: "ADMINBRXC.toggleStructureHeaderIcon('elements-order')",
                        isActive: checkShortcutState('elements-order')
                    }
                ]
            },
            {
                label: stickyCSSLabel,
                url: 'https://advancedthemer.com/features/sticky-css/',
                icon: '<i class="fab fa-css3-alt"></i>',
                onClick: "event.stopPropagation();ADMINBRXC.toggleStickyCSS();ADMINBRXC.toggleStructureMode();",
                icons: [
                    {
                        key: "sticky-css",
                        icon: "fas fa-star",
                        balloon: "Add to Structure header",
                        pos: "top-right",
                        onClick: "ADMINBRXC.toggleStructureHeaderIcon('sticky-css')",
                        isActive: checkShortcutState('sticky-css')
                    }
                ]
            },
            {
                label: visibilityLabel,
                url: 'https://advancedthemer.com/features/visibility-floating-bar/',
                icon: '<i class="fas fa-window-maximize" style="rotate:180deg;"></i>',
                onClick: "event.stopPropagation();ADMINBRXC.toggleHideFloatingBar();ADMINBRXC.toggleStructureMode();",
                icons: [
                    {
                        key: "visibility-floating-bar",
                        icon: "fas fa-star",
                        balloon: "Add to Structure header",
                        pos: "top-right",
                        onClick: "ADMINBRXC.toggleStructureHeaderIcon('visibility-floating-bar')",
                        isActive: checkShortcutState('visibility-floating-bar')
                    }
                ]
            },
        ]

        const tweaks = [
            {
                label: "Right Elements Shortcuts",
                url: 'https://advancedthemer.com/features/add-elements-to-your-structure-panel-on-the-fly/',
                onClick: "ADMINBRXC.toggleStructureTweak('right-elements-shortcuts')",
                key: 'right-elements-shortcuts',
            },
            {
                label: "Styles & Classes Indicators",
                url: 'https://advancedthemer.com/features/style-classes-indicators-inside-the-structure-panel/',
                onClick: "ADMINBRXC.toggleStructureTweak('styles-and-classes-indicators')",
                key: 'styles-and-classes-indicators',
            },
            {
                label: "Expand All Children Elements",
                url: 'https://advancedthemer.com/features/expand-all-children-elements/',
                onClick: "ADMINBRXC.toggleStructureTweak('expand-all-children')",
                key: 'expand-all-children',
            },
            {
                label: "Draggable Structure Panel",
                url: 'https://advancedthemer.com/features/draggable-structure-panel/',
                onClick: "ADMINBRXC.toggleStructureTweak('draggable-structure-panel')",
                key: 'draggable-structure-panel',
            },
            {
                label: "Link Indicator",
                url: 'https://advancedthemer.com/features/link-indicator-inside-the-structure-panel/',
                onClick: "ADMINBRXC.toggleStructureTweak('link')",
                key: 'link',
            },
            {
                label: "Focus Mode",
                url: 'https://advancedthemer.com/features/focus-mode/',
                onClick: "ADMINBRXC.toggleStructureTweak('focus-mode')",
                key: 'focus-mode',
            },
            {
                label: "Filterable Structure Panel",
                url: 'https://advancedthemer.com/features/filterable-structure-panel/',
                onClick: "ADMINBRXC.toggleStructureTweak('filterable-structure')",
                key: 'filterable-structure',
            },
            {
                label: "Double-click to Edit Components",
                url: 'https://advancedthemer.com/features/double-click-to-edit-components/',
                onClick: "ADMINBRXC.toggleStructureTweak('db-click-edit-component')",
                key: 'db-click-edit-component',
            },
            {
                label: "Highlight Global Classes",
                url: 'https://advancedthemer.com/features/class-highlight-indicator-in-the-structure-panel/',
                onClick: "ADMINBRXC.toggleStructureTweak('highlight-classes')",
                key: 'highlight-classes',
            },
            {
                label: "Highlight Nestable Elements",
                url: 'https://advancedthemer.com/features/highlight-nested-elements/',
                onClick: "ADMINBRXC.toggleStructureTweak('highlight-nestable-elements')",
                key: 'highlight-nestable-elements',
            },
            {
                label: "Highlight Parent Elements",
                url: 'https://advancedthemer.com/features/highlight-parent-elements/',
                onClick: "ADMINBRXC.toggleStructureTweak('highlight-parent-elements')",
                key: 'highlight-parent-elements',
            },
            {
                label: "Highlight Hidden/Removed Elements",
                url: 'https://advancedthemer.com/features/hide-remove-element/',
                onClick: "ADMINBRXC.toggleStructureTweak('hide-remove-highlights')",
                key: 'hide-remove-highlights',
            }

        ]

        function printGroup(arr, title, print){
            const callback = print === "tweak" ? arr.map(item => printTweak(item)).join('') : arr.map(item => printItem(item)).join('')
            return `<div class="brxc-context-menu__block">
                            <div class="title">${title}</div>
                            ${callback}
                        </div>`
        }

         
        content += `<ul>`;
        content += printGroup(tweaks, 'Tweaks', "tweak")
        content += `</ul>`

        content += `<ul>`;
        content += printGroup(modals, 'Modals', "item")
        content += printGroup(states, 'States', "item")
        content += `</ul>`

        return content;
    },
    toggleStructureMode: function (){
        const self = this;
        self.openContextualMenu(false, () => {return ADMINBRXC.structureContextualMenu()}, "left", "structure", "2")
    },
    toggleStructureHeaderIcon: function(key) {
        const self = this;
        const index = self.structurePanelStates.icons.indexOf(key);

        if (index !== -1) {
            self.structurePanelStates.icons.splice(index, 1);
        } else {
            self.structurePanelStates.icons.push(key);
        }

        self.helpers.setLocalStorage('structureIcons', self.structurePanelStates.icons);
        self.openContextualMenu(false, () => {return ADMINBRXC.structureContextualMenu()}, "left", "structure", "2")
        self.setHeaderStructurePanel();
    },
    toggleStructureTweak: function(key){
        const self = this;
        const index = self.structurePanelStates.tweaks.indexOf(key);

        if (index !== -1) {
            self.structurePanelStates.tweaks.splice(index, 1);
        } else {
            self.structurePanelStates.tweaks.push(key);
        }

        self.helpers.setLocalStorage('structureTweaks', self.structurePanelStates.tweaks);

        switch(key){
            case 'right-elements-shortcuts':
                self.setRightShortcutCol();
                break;
            case 'styles-and-classes-indicators':
                self.setColorsforStructureIndicators();
                break;
            case 'highlight-parent-elements':
                self.setColorsforStructureParents();
                break;
            case 'draggable-structure-panel':
                document.body.classList.remove('draggable-structure')
                break;
            case 'focus-mode':
                if(!self.structurePanelStates.tweaks.includes('focus-mode')){
                    let alert = document.querySelector('#brxcFocusModeAlert');
                    document.body.classList.remove('at-focus-mode');
                    FRAMEBRXC.content.body.classList.remove('at-focus-iframe-mode');
                    if(alert) alert.remove();
                }
                break;
            case 'filterable-structure':
                self.setSearchStructure();
                break;
            case 'hide-remove-highlights':
                break;
        }

        self.openContextualMenu(false, () => {return ADMINBRXC.structureContextualMenu()}, "left", "structure", "2")
        setTimeout(() => {
            self.runStructureHighlights();
        })
    },
    contextualMenuStates: {
        top: false,
        left: false,
        width: false,
    },
    openContextualMenu: function(event, callback, position = "right", dataType = "class", cols = "1"){
        const self = this;
        const existingMenu = document.querySelector('#brxc-class-context-menu');

        if(existingMenu) existingMenu.remove();
        const menu = document.createElement('DIV');
        menu.id = "brxc-class-context-menu";
        menu.setAttribute('class', 'brxc-context-menu');
        menu.setAttribute('data-type', dataType);
        menu.innerHTML = `<div id="brxc-class-context-menu-canvas" class="col-${cols}"></div>`;
        document.body.appendChild(menu);
        const menuCanvas = document.querySelector('#brxc-class-context-menu-canvas');
    
        const content = callback();
        menuCanvas.innerHTML = content;

        if(event){
            const rect = event.target.getBoundingClientRect();
            self.contextualMenuStates.top = event.clientY;
            self.contextualMenuStates.left = event.clientX;
            self.contextualMenuStates.width = rect.width;
        }

        menu.style.top = `${self.contextualMenuStates.top}px`;
        menu.style.left = position === "right" ? `${self.contextualMenuStates.left}px` : `calc(${self.contextualMenuStates.left}px - var(--at-menu-width) + 20px)`;;
        menu.classList.add('show');
        

        // Listeners
        const x = document.querySelector('#bricks-builder-iframe').contentWindow;
        function openMenu() {
            window.addEventListener('click', windowClickListener);
            x.document.addEventListener('click', windowClickListener);
        }
        
        function closeMenu() {
            window.removeEventListener('click', windowClickListener);
            x.document.removeEventListener('click', windowClickListener);
            menu.classList.remove('show');

        }
        
        function windowClickListener(event) {
            closeMenu();
        }
        setTimeout(() => {
            openMenu();
        }, 10)
    },
    openPaletteMenu: function(icon){
        const self = this;
        const existingMenu = document.querySelector('#brxc-color-context-menu');
        let content = '';

        // remove header dropdown
        const headerDropdown = document.querySelector('#colorHeaderCanvas .list-palette');
        if(headerDropdown && !headerDropdown.classList.contains('hidden')) headerDropdown.classList.add('hidden')

        // Create Canvas
        if(existingMenu) {
            //window.dispatchEvent(new Event('click'));
            existingMenu.remove();
            
        }
        const menu = document.createElement('DIV');
        menu.id = "brxc-color-context-menu";
        menu.setAttribute('class', 'brxc-context-menu');
        menu.innerHTML = `<div id="brxc-color-context-menu-canvas"></div>`;
        document.body.appendChild(menu);
        const menuCanvas = document.querySelector('#brxc-color-context-menu-canvas');

        // Inner Content
        content += `<ul>`
         content += `
                <li onclick="ADMINBRXC.colorStates.colorManagerRenamePalette = true;ADMINBRXC.setColorManagerHeader()">Rename Current Palette</li>
                <li onclick="ADMINBRXC.duplicatePalette();">Duplicate Palette</li>
                <li onclick="ADMINBRXC.colorManagerToggleCSSView();">Switch to ${self.colorStates.viewCSS ? 'Palette' : 'Export'} View</li>
                <li class="sep"></li>
                <li onclick="ADMINBRXC.colorStates.colorManagerAddPalette = true;ADMINBRXC.setColorManagerHeader()">Add New Palette</li>
                <li class="sep"></li>
                <li class="delete" onclick="ADMINBRXC.deletePalette();">Delete Palette</li>`
        content += `</ul>`;
        
        menuCanvas.innerHTML = content;
        const rect = icon.getBoundingClientRect();
        menu.style.top = `${rect.top}px`;
        menu.style.left = `calc(${rect.left}px - 220px)`;
        menu.classList.add('show');

        // Listeners
        const x = document.querySelector('#bricks-builder-iframe').contentWindow;
        function openMenu() {
            window.addEventListener('click', windowClickListener);
            x.document.addEventListener('click', windowClickListener);
        }
        
        function closeMenu() {
            window.removeEventListener('click', windowClickListener);
            x.document.removeEventListener('click', windowClickListener);
            menu.classList.remove('show');

        }
        
        function windowClickListener(event) {
            closeMenu();
        }
        openMenu();
    },
    copiedAllClasses: null,
    copyAllClasses: function(){
        const self = this;
        const elementObj = self.builderStates.activeElement;
        if(!elementObj.settings.hasOwnProperty('_cssGlobalClasses') || elementObj.settings._cssGlobalClasses.length < 1) return self.vueGlobalProp.$_showMessage('Abort - No Global Class found!');
        
        self.copiedAllClasses = elementObj.settings._cssGlobalClasses;
        self.vueGlobalProp.$_showMessage('Global Classes correctly copied!');
        self.vueState.rerenderControls = Date.now();
    },
    pasteAllClasses: function(){
        const self = this;
        const elementObj = self.builderStates.activeElement;
        if(!Array.isArray(self.copiedAllClasses)){
            return self.vueGlobalProp.$_showMessage('Abort - No Global Classes have been copied!');
        } 
        if(!elementObj.settings.hasOwnProperty('_cssGlobalClasses')) elementObj.settings._cssGlobalClasses = [];
        elementObj.settings._cssGlobalClasses = [...new Set(elementObj.settings._cssGlobalClasses.concat(self.copiedAllClasses))];
        self.vueGlobalProp.$_showMessage('Global Classes correctly pasted!');
        self.vueState.rerenderControls = Date.now();
    },
    resetAllClasses: function(){
        const self = this;
        const elementObj = self.builderStates.activeElement;
        if(!elementObj.settings.hasOwnProperty('_cssGlobalClasses') || elementObj.settings._cssGlobalClasses.length < 1 ) return self.vueGlobalProp.$_showMessage('Abort - No Global Classes found!');
        
        delete elementObj.settings._cssGlobalClasses;
        self.vueGlobalProp.$_showMessage('Global Classes correctly removed!');
        self.vueState.rerenderControls = Date.now();
    },
    removeCurrentClass: function(id, message){
        const self = this;
        const elementObj = self.builderStates.activeElement;
        const index = elementObj.settings._cssGlobalClasses.indexOf(id);
        elementObj.settings._cssGlobalClasses.splice(index, 1);
        message === true ? self.vueGlobalProp.$_showMessage('Global Class correctly removed!') : '';
        self.vueState.rerenderControls = Date.now();
    },
    deleteCurrentClass: function(id){
        const self = this;

        // Remove Class from all elements
        const content = self.helpers.getContent() || [];
        const filteredEls = Array.from(content).filter(el => el && el.settings.hasOwnProperty('_cssGlobalClasses') && el.settings._cssGlobalClasses.includes(id));
        if(filteredEls && filteredEls.length > 0){
            filteredEls.forEach(element => {
                const index = element.settings._cssGlobalClasses.indexOf(id);
                element.settings._cssGlobalClasses.splice(index, 1);
            })
        }

        // Remove Global Class
        const activeClass = Array.from(self.vueState.globalClasses).find(el => el.id === id);
        if(!activeClass) return self.vueGlobalProp.$_showMessage('Abort - Global Class not found!');
        const index = self.vueState.globalClasses.indexOf(activeClass);
        self.vueState.globalClasses.splice(index,1);
        if(self.states.classManagerActiveClass === id) self.states.classManagerActiveClass = '';
        let showMessage = 'Global Class correctly deleted!';

        // Move to Trash
        if(self.vueState.globalClassesTrash && Array.isArray(self.vueState.globalClassesTrash)){
            activeClass.deletedAt = Date.now();
            activeClass.originalIndex = index;
            activeClass.user_id = bricksData.loadData.currentUserId;

            self.vueState.globalClassesTrash.push(activeClass);
            showMessage = 'Global Class correctly moved to trash!';
        }

        self.vueGlobalProp.$_showMessage(showMessage);
        self.vueState.rerenderControls = Date.now();
    },
    cloneClass: function(){
        const self = this;
        const els = document.querySelector('#bricks-panel-element-classes')
        if (!els) return;

        const wrapper = els.querySelector('.brxc-clone-class-wrapper')
        if(wrapper) return wrapper.remove();

        const activeClass = els.querySelector('.active-class, .active-selector');

        const inputHTML = `<div class="brxc-clone-class-wrapper"><input type="text" id="brxc-clone-class-input" size="999" autocomplete="off" spellcheck="false" placeholder="Type your class name here" value="${self.vueState.activeClass.name}-new"><span class="bricks-svg-wrapper create" data-balloon="Clone class (SHIFT + ENTER)" data-balloon-pos="left"><!--?xml version="1.0" encoding="UTF-8"?--><svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><path d="M362.7,64h-256c-23.7,0 -42.7,19.2 -42.7,42.7v298.7c0,23.5 19,42.7 42.7,42.7h298.7c23.5,0 42.7,-19.2 42.7,-42.7v-256l-85.4,-85.4Zm-106.7,341.3c-35.4,0 -64,-28.6 -64,-64c0,-35.4 28.6,-64 64,-64c35.4,0 64,28.6 64,64c0,35.4 -28.6,64 -64,64Zm64,-213.3h-213.3v-85.3h213.3v85.3Z" fill="currentColor"></path></svg></span><span class="bricks-svg-wrapper cancel" data-balloon="Cancel" data-balloon-pos="left"><i class="fas fa-xmark"></i></span></span><div>`
        activeClass.insertAdjacentHTML('afterend', inputHTML);

        const newWrapper = els.querySelector('.brxc-clone-class-wrapper')
        const newInput = newWrapper.querySelector('#brxc-clone-class-input');
        if(!newInput) return;
        newInput.focus();
        newInput.setSelectionRange(newInput.value.length, newInput.value.length)

        self.autocomplete(newInput, self.vueState.globalClasses.map(el => el.name), false);
        const saveBtn = document.querySelector('.brxc-clone-class-wrapper .bricks-svg-wrapper.create')
        const cancelBtn = document.querySelector('.brxc-clone-class-wrapper .bricks-svg-wrapper.cancel')
        const elementObj = self.builderStates.activeElement;

        function cloneClass(){
            // Create CSS Settings
            const newInputValue = self.helpers.formatForClasses(newInput.value);
            const oldSettings = self.vueState.activeClass.settings;
            const oldCat = (self.vueState.activeClass.hasOwnProperty('category')) ? self.vueState.activeClass.category : false;
            const newSettings = JSON.parse(JSON.stringify(oldSettings).replaceAll(self.vueState.activeClass.name,newInputValue));
            let isUnique = true;
            let idClass;

            const addClass = (id, message, newWrapper) =>{
                // Add class to the element
                if (typeof elementObj.settings !== "undefined" && elementObj.settings.hasOwnProperty('_cssGlobalClasses')) {
                    if (!elementObj.settings._cssGlobalClasses.includes(id)) elementObj.settings._cssGlobalClasses.push(id)
                } else {
                    elementObj.settings._cssGlobalClasses = [];
                    elementObj.settings._cssGlobalClasses.push(id);
                }


                newWrapper.remove();
                self.vueGlobalProp.$_showMessage(message);
            }

            // Check if class exists
            self.vueState.globalClasses.forEach(obj => {
                if (obj.name === newInputValue){
                    isUnique = false;
                    idClass = obj.id;
                } 
            })


            if(isUnique === false) {
                addClass(idClass, 'Aborted: the class already exists!', newWrapper)
                return;
            }

            // Generate unique ID
            idClass = self.vueGlobalProp.$_generateId()

            // Create the class object
            const newGlobalClass = {
                id: idClass,
                name: newInputValue,
                settings: newSettings,
            };
            if(oldCat) newGlobalClass.category = oldCat;

            self.vueState.globalClasses.push(newGlobalClass);
            addClass(idClass, 'Class Successfully Created!', newWrapper)
        }

        saveBtn.addEventListener("click", function() {
            if(newInput.value === ''){
                return self.vueGlobalProp.$_showMessage('Abort - No Class Name Given');
            }
            cloneClass()
        });

        cancelBtn.addEventListener("click", function() {
            newWrapper.remove();
        });

        newInput.addEventListener('keyup', function(event) {
            if (event.shiftKey && event.keyCode === 13) cloneClass();
        });
    },
    exportIDStylestoClass: function(type){
        const self = this;
        const els = document.querySelector('#bricks-panel-element-classes')
        if (!els) return;

        const wrapper = els.querySelector('.brxc-copy-id-to-class-wrapper')
        if(wrapper) return wrapper.remove();

        const activeClass = els.querySelector('.active-class, .active-selector');

        let inputHTML = `<div class="brxc-copy-id-to-class-wrapper"><input type="text" id="brxc-copy-id-to-class-input" size="999" autocomplete="off" spellcheck="false" placeholder="Type your class name here"><span class="bricks-svg-wrapper create" data-balloon="Create/Update (SHIFT + ENTER)" data-balloon-pos="left"><!--?xml version="1.0" encoding="UTF-8"?--><svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><path d="M362.7,64h-256c-23.7,0 -42.7,19.2 -42.7,42.7v298.7c0,23.5 19,42.7 42.7,42.7h298.7c23.5,0 42.7,-19.2 42.7,-42.7v-256l-85.4,-85.4Zm-106.7,341.3c-35.4,0 -64,-28.6 -64,-64c0,-35.4 28.6,-64 64,-64c35.4,0 64,28.6 64,64c0,35.4 -28.6,64 -64,64Zm64,-213.3h-213.3v-85.3h213.3v85.3Z" fill="currentColor"></path></svg></span><span class="bricks-svg-wrapper cancel" data-balloon="Cancel" data-balloon-pos="left"><i class="fas fa-xmark"></i></span></span>`;
        if(typeof self.vueState.globalClassesCategories !== "undefined") inputHTML +=`<input type="text" id="brxc-copy-id-to-class-input-cat" size="999" autocomplete="off" spellcheck="false" placeholder="Type the class category here (optional)">`;
        inputHTML += `</div>`;
        activeClass.insertAdjacentHTML('afterend', inputHTML);

        const newWrapper = els.querySelector('.brxc-copy-id-to-class-wrapper')
        const newInput = newWrapper.querySelector('#brxc-copy-id-to-class-input');
        const newCategory = newWrapper.querySelector('#brxc-copy-id-to-class-input-cat');
        if(!newInput) return;
        newInput.focus();

        self.autocomplete(newInput, Array.from(self.vueState.globalClasses).map(el => el && el.name), false);
        if(newCategory) self.autocomplete(newCategory, self.states.classManagerCategories, false);
        const saveBtn = document.querySelector('.brxc-copy-id-to-class-wrapper .bricks-svg-wrapper.create');
        const cancelBtn = document.querySelector('.brxc-copy-id-to-class-wrapper .bricks-svg-wrapper.cancel');

        const elementObj = self.builderStates.activeElement;

        function exportSettings(){
            // Create CSS Settings
            const settings = {};
            const excludedKeys = ['icon'];
            for (const [key, value] of Object.entries(elementObj.settings)){
                const prop = key.split(':')[0];

                if(['_cssCustom','_cssCustomSass'].includes(prop)){
                    const dot = self.helpers.isComponentActive() ? '.' : '#';
                    let id = typeof elementObj.settings !== "undefined" && elementObj.settings.hasOwnProperty('_cssId') ? `${dot}${elementObj.settings._cssId}` : `${dot}brxe-${elementObj.id}`;
                    settings[key] = value.replaceAll(id, '.' + self.helpers.formatForClasses(newInput.value))
                } else if (!excludedKeys.includes(prop) && self.helpers.isCSSControlKey(key)) {
                    // Object
                    if( typeof elementObj.settings[key] === "object"){
                        for (const [key1, value1] of Object.entries(elementObj.settings[key])){
                            if(!settings.hasOwnProperty(key)) settings[key] = {};
                            settings[key][key1] = JSON.parse(JSON.stringify(elementObj.settings[key][key1]));
                        }
                    // Sring
                    } else {
                        settings[key] = JSON.parse(JSON.stringify(value));
                    }
                }
            }
            let isLocked;
            let isUnique = true;
            let idClass;
            let category;
            if(newCategory && newCategory.value.length > 0) {
                const relatedCat = self.helpers.getClassCategoryIdByName(newCategory.value)
                if(relatedCat){
                    category = relatedCat;
                } else {
                    const catId = self.vueGlobalProp.$_generateId();
                    self.vueState.globalClassesCategories.push({
                        id: catId,
                        name: newCategory.value,
                    })
                    category = catId
                }
            } 

            const addClass = (id, message, newWrapper) =>{
                // Add class to the element
                if (typeof elementObj.settings !== "undefined" && elementObj.settings.hasOwnProperty('_cssGlobalClasses')) {
                    if (!elementObj.settings._cssGlobalClasses.includes(id)) elementObj.settings._cssGlobalClasses.push(id)
                } else {
                    elementObj.settings._cssGlobalClasses = [];
                    elementObj.settings._cssGlobalClasses.push(id);
                }

                // Remove styles on ID
                for (const [key, value] of Object.entries(settings)){
                    if (self.helpers.isCSSControlKey(key)) delete elementObj.settings[key];
                }

                newWrapper.remove();
                self.vueGlobalProp.$_showMessage(message);
            }

            // Check if class exists
            const targetClass = Array.from(self.vueState.globalClasses).find(el => el && el.hasOwnProperty('name') && el.name === self.helpers.formatForClasses(newInput.value));
            if(targetClass){
                isUnique = false;
                idClass = targetClass.id;
                isLocked = self.vueGlobalProp.$_isLocked(targetClass.id);
                if (!isLocked) for (const [key, value] of Object.entries(settings)){
                    //object
                    if(typeof settings[key] === "object"){
                        if(!targetClass.settings.hasOwnProperty(key)) targetClass.settings[key] = {};
                        for (const [key1, value1] of Object.entries(settings[key])){
                            if(!settings.hasOwnProperty(key)) settings[key] = {};
                            targetClass.settings[key][key1] = JSON.parse(JSON.stringify(settings[key][key1]));
                        }
                    } else {
                        //string
                        targetClass.settings[key] = value;
                    }
                }
            }

            if(isLocked === true){
                newWrapper.remove();
                self.vueGlobalProp.$_showMessage('Abort: the class is locked');
                return;
            }

            if(isUnique === false) {
                addClass(idClass, 'Class Successfully Updated!', newWrapper)
                self.vueState.activeClass = JSON.parse(JSON.stringify(self.vueGlobalProp.$_getGlobalClass(idClass)));
                return;
            }

            // Generate unique ID
            idClass = self.vueGlobalProp.$_generateId()


            // Create the class object
            const newGlobalClass = {
                id: idClass,
                name: self.helpers.formatForClasses(newInput.value),
                settings: settings,
            };
            if(category) newGlobalClass.category = category;

            self.vueState.globalClasses.push(newGlobalClass);
            self.vueState.activeClass = self.vueGlobalProp.$_getGlobalClass(idClass);
            self.vueState.rerenderControls = Date.now();
            addClass(idClass, 'Class Successfully Created!', newWrapper);
            self.helpers.saveChanges('globalClasses');
        }

        newInput.addEventListener('keyup', function(event) {
            if (event.shiftKey && event.keyCode === 13) exportSettings();
        });

        saveBtn.addEventListener('click', function(event) {
            if(newInput.value === ''){
                return self.vueGlobalProp.$_showMessage('Abort - No Class Name Given');
            }
            exportSettings()
        }); 
        cancelBtn.addEventListener('click', function(event) {
            newWrapper.remove();
        }); 
    },
    mergeClasses: function(){
        const self = this;
        const els = document.querySelector('#bricks-panel-element-classes')
        if (!els) return;

        const wrapper = els.querySelector('.brxc-copy-id-to-class-wrapper')
        if(wrapper) return wrapper.remove();

        const activeClass = els.querySelector('.active-class, .active-selector');

        let inputHTML = `<div class="brxc-copy-id-to-class-wrapper">
                            <input type="text" id="brxc-copy-id-to-class-input" size="999" autocomplete="off" spellcheck="false" placeholder="Type your class name here"><span class="bricks-svg-wrapper create" data-balloon="Create/Update (SHIFT + ENTER)" data-balloon-pos="left"><!--?xml version="1.0" encoding="UTF-8"?--><svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><path d="M362.7,64h-256c-23.7,0 -42.7,19.2 -42.7,42.7v298.7c0,23.5 19,42.7 42.7,42.7h298.7c23.5,0 42.7,-19.2 42.7,-42.7v-256l-85.4,-85.4Zm-106.7,341.3c-35.4,0 -64,-28.6 -64,-64c0,-35.4 28.6,-64 64,-64c35.4,0 64,28.6 64,64c0,35.4 -28.6,64 -64,64Zm64,-213.3h-213.3v-85.3h213.3v85.3Z" fill="currentColor"></path></svg></span><span class="bricks-svg-wrapper cancel" data-balloon="Cancel" data-balloon-pos="left"><i class="fas fa-xmark"></i></span></span>`;
        if(typeof self.vueState.globalClassesCategories !== "undefined") inputHTML +=`<input type="text" id="brxc-copy-id-to-class-input-cat" size="999" autocomplete="off" spellcheck="false" placeholder="Type the class category here (optional)">`;
        inputHTML += `<div class="control control-checkbox">
                        <div class="control-inner control-inline control-small">
                            <label for="removeExistingClasses" data-balloon-break="">
                                <span>Remove existing classes from element?</span>
                            </label>
                            <div data-control="checkbox" type="checkbox" class="">
                                <input type="checkbox" id="removeExistingClasses" name="removeExistingClasses">
                            </div>
                        </div>
                    </div>
                    <div class="control control-checkbox">
                        <div class="control-inner control-inline control-small">
                            <label for="deleteExistingClasses" data-balloon-break="">
                                <span>Delete existing classes permanently?</span>
                            </label>
                            <div data-control="checkbox" type="checkbox" class="">
                                <input type="checkbox" id="deleteExistingClasses" name="deleteExistingClasses">
                            </div>
                        </div>
                    </div>`;
        inputHTML += `</div>`;
        activeClass.insertAdjacentHTML('afterend', inputHTML);

        const newWrapper = els.querySelector('.brxc-copy-id-to-class-wrapper')
        const newInput = newWrapper.querySelector('#brxc-copy-id-to-class-input');
        const newCategory = newWrapper.querySelector('#brxc-copy-id-to-class-input-cat');
        const removeClasses = newWrapper.querySelector('#removeExistingClasses');
        const deleteClasses = newWrapper.querySelector('#deleteExistingClasses');
        if(!newInput) return;
        newInput.focus();

        self.autocomplete(newInput, Array.from(self.vueState.globalClasses).map(el => el && el.name), false);
        if(newCategory) self.autocomplete(newCategory, self.states.classManagerCategories, false);
        const saveBtn = document.querySelector('.brxc-copy-id-to-class-wrapper .bricks-svg-wrapper.create');
        const cancelBtn = document.querySelector('.brxc-copy-id-to-class-wrapper .bricks-svg-wrapper.cancel');
        const elementObj = self.builderStates.activeElement;

        function mergeSettings(){
            // Create CSS Settings
            const settings = {};
            const globalClasses = elementObj.settings._cssGlobalClasses;
            if(globalClasses && globalClasses.length > 0){
                globalClasses.forEach(globalClass => {
                    const globalClassObj = self.vueGlobalProp.$_getGlobalClass(globalClass);
                    if(!globalClassObj || !globalClassObj.settings) return;

                    for (const [key, value] of Object.entries(globalClassObj.settings)){
                        if( key.startsWith('_cssCustom') || key.startsWith('_cssCustomSass')){
                            const initialValue = settings[key] || '';
                            settings[key] = `${initialValue}${initialValue === '' ? '' : '\n\n'}/* Custom CSS from .${globalClassObj.name} */\n${value.replaceAll(globalClassObj.name, '.' + self.helpers.formatForClasses(newInput.value))}`
                        } else if (self.helpers.isCSSControlKey(key)) {
                            // Object
                            if(typeof globalClassObj.settings[key] === "object"){
                                for (const [key1, value1] of Object.entries(globalClassObj.settings[key])){
                                    if(!settings.hasOwnProperty(key)) settings[key] = {};
                                    settings[key][key1] = JSON.parse(JSON.stringify(globalClassObj.settings[key][key1]));
                                }
                            // Sring
                            } else {
                                settings[key] = JSON.parse(JSON.stringify(value));
                            }
                        }
                    }

                })
            }
            let isLocked;
            let isUnique = true;
            let idClass;
            let category;
            if(newCategory && newCategory.value.length > 0) {
                const relatedCat = self.helpers.getClassCategoryIdByName(newCategory.value)
                if(relatedCat){
                    category = relatedCat;
                } else {
                    const catId = self.vueGlobalProp.$_generateId();
                    self.vueState.globalClassesCategories.push({
                        id: catId,
                        name: newCategory.value,
                    })
                    category = catId
                }
            } 

            const addClass = (id, message, newWrapper) =>{
                // Add class to the element
                if (typeof elementObj.settings !== "undefined" && elementObj.settings.hasOwnProperty('_cssGlobalClasses')) {
                    if (!elementObj.settings._cssGlobalClasses.includes(id)) elementObj.settings._cssGlobalClasses.push(id)
                } else {
                    elementObj.settings._cssGlobalClasses = [];
                    elementObj.settings._cssGlobalClasses.push(id);
                }

                // Remove styles on ID
                for (const [key, value] of Object.entries(elementObj.settings)){
                    if (self.helpers.isCSSControlKey(key)) delete elementObj.settings[key];
                }

                newWrapper.remove();
                self.vueGlobalProp.$_showMessage(message);
            }

            // Check if class exists
            const targetClass = Array.from(self.vueState.globalClasses).find(el => el && el.hasOwnProperty('name') && el.name === self.helpers.formatForClasses(newInput.value));
            if(targetClass){
                isUnique = false;
                idClass = targetClass.id;
                isLocked = self.vueGlobalProp.$_isLocked(targetClass.id);
                if (!isLocked) for (const [key, value] of Object.entries(settings)){
                    //object
                    if(typeof settings[key] === "object"){
                        if(!targetClass.settings.hasOwnProperty(key)) targetClass.settings[key] = {};
                        for (const [key1, value1] of Object.entries(settings[key])){
                            if(!settings.hasOwnProperty(key)) settings[key] = {};
                            targetClass.settings[key][key1] = JSON.parse(JSON.stringify(settings[key][key1]));
                        }
                    } else {
                        //string
                        targetClass.settings[key] = value;
                    }
                }
            }

            if(isLocked === true){
                newWrapper.remove();
                self.vueGlobalProp.$_showMessage('Abort: the class is locked');
                return;
            }

            if(isUnique === false) {
                addClass(idClass, 'Class Successfully Created!', newWrapper)
                self.vueState.activeClass = JSON.parse(JSON.stringify(self.vueGlobalProp.$_getGlobalClass(idClass)));
                return;
            }

            // Generate unique ID
            idClass = self.vueGlobalProp.$_generateId()


            // Create the class object
            const newGlobalClass = {
                id: idClass,
                name: self.helpers.formatForClasses(newInput.value),
                settings: settings,
            };
            if(category) newGlobalClass.category = category;

            if(deleteClasses.checked === true){
                elementObj.settings._cssGlobalClasses.forEach(el => {
                    self.vueState.globalClasses = self.vueState.globalClasses.filter(el2 => el2 && el2.hasOwnProperty('id') && !elementObj.settings._cssGlobalClasses.includes(el2.id))
                    elementObj.settings._cssGlobalClasses = [];
                });
            } else if(removeClasses.checked === true){
                elementObj.settings._cssGlobalClasses = [];
            }
            setTimeout(() => {
                self.vueState.globalClasses.push(newGlobalClass);
                addClass(idClass, 'Class Successfully Created!', newWrapper);
                self.vueState.activeClass = newGlobalClass;
                self.vueState.rerenderControls = Date.now();
                self.helpers.saveChanges('globalClasses');
            },5)
        }

        newInput.addEventListener('keyup', function(event) {
            if (event.shiftKey && event.keyCode === 13) mergeSettings();
        });

        saveBtn.addEventListener('click', function(event) {
            if(newInput.value === ''){
                return self.vueGlobalProp.$_showMessage('Abort - No Class Name Given');
            }
            mergeSettings()
        }); 
        cancelBtn.addEventListener('click', function(event) {
            newWrapper.remove();
        });
    },
    importIDStylestoClass: function(){
        const self = this;
        
        const activeClass = Array.from(self.vueState.globalClasses).find(el => el && el.hasOwnProperty('id') && el.id === self.vueState.activeClass.id);
        const elementObj = self.builderStates.activeElement;

        // Create CSS Settings
        const settings = {};
        for (const [key, value] of Object.entries(elementObj.settings)){

            if( key.startsWith('_cssCustom') ){
                const dot = self.helpers.isComponentActive() ? '.' : '#';
                let id = typeof elementObj.settings !== "undefined" && elementObj.settings.hasOwnProperty('_cssId') ? `${dot}${elementObj.settings._cssId}` : `${dot}brxe-${elementObj.id}`;
                settings[key] = JSON.parse(JSON.stringify(value.replaceAll(id, '.' + activeClass.name)));
            } else if (self.helpers.isCSSControlKey(key)) {
                // Object
                if(typeof elementObj.settings[key] === "object"){
                    for (const [key1, value1] of Object.entries(elementObj.settings[key])){
                        if(!settings.hasOwnProperty(key)) settings[key] = {};
                        settings[key][key1] = JSON.parse(JSON.stringify(elementObj.settings[key][key1]));
                    }
                // Sring
                } else {
                    settings[key] = JSON.parse(JSON.stringify(value));
                }
            }

            
        }

        const addClass = (message) =>{

            // Import Styles from ID
            for (const [key, value] of Object.entries(settings)){


                //object
                if(typeof settings[key] === "object"){
                    for (const [key1, value1] of Object.entries(settings[key])){
                        if(!activeClass.settings.hasOwnProperty(key)) activeClass.settings[key] = {};
                        activeClass.settings[key][key1] = JSON.parse(JSON.stringify(settings[key][key1]));
                    }
                } else {
                    //string
                    activeClass.settings[key] = value;
                }
                delete elementObj.settings[key]
            }

            self.vueGlobalProp.$_showMessage(message);
        }

        addClass('Styles Successfully Imported to the Class!');
        self.vueState.activeClass = JSON.parse(JSON.stringify(activeClass));
        self.vueState.rerenderControls = Date.now();
        //self.helpers.saveChanges('globalClasses');



    },
    setActiveStyleTabs: function(){
        const self = this;
        if(!self.builderStates.isElementActive) return;

        let panelGroup = self.vueState.activePanelGroup;

        const elementObj = self.builderStates.activeElement;

        if(self.vueState.activePanelTab === "content" && panelGroup && panelGroup !== '' && bricksData.elements[elementObj.name]?.controlGroups[panelGroup]?.tab === "style") {
            self.vueState.activePanelGroup = '';
        }
    },
    setBorderAndBoxShadow: function(){
        const self = this;
        if(!self.builderStates.isElementActive) return;

        const x = document.querySelector('#bricks-builder-iframe').contentWindow;
        const els = x.document.querySelectorAll('.has-border-settings');
        if(els && els.length > 0) els.forEach(el => el.classList.remove('has-border-settings'))

        if(self.vueState.activePanelGroup !== "_border") return;

        const elementObj = self.builderStates.activeElement;
        const activeEl = FRAMEBRXC.vueGlobalProp.$_getElementNode(elementObj);
        if(!activeEl) return;
        
        activeEl.classList.add('has-border-settings');
    },
    topbarStates: {
        icons: ['main-menu', 'quick-remote-template', 'class-manager', 'color-manager', 'variable-manager', 'advanced-css', 'zoom-out'],
        tweaks: [],
    },
    initToolbar: function(){
        const self = this;
        const toolbar = document.querySelector('#bricks-toolbar')
        if(!toolbar) return;

        function addMenuItemtoToolbar (obj) {
            const li = document.createElement('li');
            obj.classes.split(' ').forEach(el => li.classList.add(el));
            li.setAttribute('data-balloon', obj.balloon);
            li.setAttribute('data-balloon-pos', obj.balloonPos);
            li.setAttribute('onClick',obj.function)
            const span = document.createElement('span');
            span.classList.add('bricks-svg-wrapper');
            span.innerHTML += obj.icon;
            li.appendChild(span);
            if(obj.position === 'before') obj.container.insertBefore(li,obj.elements);
            if(obj.position === 'after') obj.elements.parentNode.insertBefore(li, obj.elements.nextSibling);
        }

        function setActiveClass(key){
            if(self.topbarStates.tweaks.includes(key)){
                return ' enabled';
            }
            return '';
        }

        const leftToolbar = toolbar.querySelector('ul.group-wrapper.left, ul.group-wrapper.start');
        const rightToolbar = toolbar.querySelector('ul.group-wrapper.right, ul.group-wrapper.end');
        const middleToolbar = toolbar.querySelector('ul.group-wrapper.breakpoints');
        let elements;
        let structure;
        let dimensions;
        let dimensionsWidth;
        if (leftToolbar){
            elements = leftToolbar.querySelector('.elements');
        }
        if (middleToolbar){
            dimensionsWidth = middleToolbar.querySelector('.preview-dimension.width');
            dimensions = middleToolbar.querySelectorAll('.preview-dimension')[2];
        }

        if (rightToolbar){
            structure = rightToolbar.querySelector('.structure');
        }
        // Builder Tweaks - Global Features
        const ATIcons = toolbar.querySelectorAll('.brxc-icon');
        ATIcons.forEach(el => el.remove());

        if (self.helpers.isBuilderTweaksTabActive('global-features') ){
            const settingsIcons =  self.topbarStates.icons;
            const settingsTweaks =  self.topbarStates.tweaks;

            // Left

            // Grid Guides
            if (settingsIcons.includes('grid-guides')) {
                 addMenuItemtoToolbar({
                    classes: `brxc-icon grid-guide${setActiveClass('grid-guides')}`,
                    balloon: `Grid Guides`,
                    balloonPos:'bottom',
                    function: 'ADMINBRXC.toggleTopbarTweaks(["grid-guides"], false)',
                    icon: '<i class="bricks-svg ti-layout-grid4-alt" style="opacity: .75;"></i>',
                    container: leftToolbar,
                    elements: elements,
                    position: 'before'
                 })
                 addMenuItemtoToolbar({
                    classes: `brxc-icon grid-guide-options`,
                    balloon: `Grid Guides options`,
                    balloonPos:'bottom',
                    function: 'ADMINBRXC.setGridGuideOptions(this)',
                    icon: '<svg version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg" style="rotate: 90deg;"><path d="M3,9.5l-6.55671e-08,-1.77636e-15c-0.828427,-3.62117e-08 -1.5,-0.671573 -1.5,-1.5c3.62117e-08,-0.828427 0.671573,-1.5 1.5,-1.5l-6.55671e-08,1.77636e-15c0.828427,-3.62117e-08 1.5,0.671573 1.5,1.5c3.62117e-08,0.828427 -0.671573,1.5 -1.5,1.5Zm5,0l-6.55671e-08,-1.77636e-15c-0.828427,-3.62117e-08 -1.5,-0.671573 -1.5,-1.5c3.62117e-08,-0.828427 0.671573,-1.5 1.5,-1.5l-6.55671e-08,1.77636e-15c0.828427,-3.62117e-08 1.5,0.671573 1.5,1.5c3.62117e-08,0.828427 -0.671573,1.5 -1.5,1.5Zm5,0l-6.55671e-08,-1.77636e-15c-0.828427,-3.62117e-08 -1.5,-0.671573 -1.5,-1.5c3.62117e-08,-0.828427 0.671573,-1.5 1.5,-1.5l-6.55671e-08,1.77636e-15c0.828427,-3.62117e-08 1.5,0.671573 1.5,1.5c3.62117e-08,0.828427 -0.671573,1.5 -1.5,1.5Z" fill="currentColor" fill-rule="evenodd"></path></svg>',
                    container: leftToolbar,
                    elements: elements,
                    position: 'before'
                 })
            }

            // X-mode
            if(settingsIcons.includes('x-mode')){
                addMenuItemtoToolbar({
                    classes: `brxc-icon x-mode${setActiveClass('x-mode')}`,
                    balloon: `X-Mode`,
                    balloonPos:'bottom',
                    function: 'ADMINBRXC.toggleTopbarTweaks(["x-mode"], false)',
                    icon: '<i class="bricks-svg fas fa-border-top-left" style="opacity: .75;"></i>',
                    container: leftToolbar,
                    elements: elements,
                    position: 'before'
                })
            }

            // Contrast Checker
            if(settingsIcons.includes('contrast-checker')){
                addMenuItemtoToolbar({
                    classes: `brxc-icon constrast${setActiveClass('contrast-checker')}`,
                    balloon: `Contrast Checker`,
                    balloonPos:'bottom',
                    function: 'ADMINBRXC.toggleTopbarTweaks(["contrast-checker"], false)',
                    icon: '<i class="bricks-svg ion-ios-contrast" style="opacity: .75;"></i>',
                    container: leftToolbar,
                    elements: elements,
                    position: 'before'
                })
            }
            
            // Darkmode
            if(settingsIcons.includes('darkmode')){
                addMenuItemtoToolbar({
                    classes: `brxc-icon darkmode${setActiveClass('darkmode')}`,
                    balloon: `Darkmode`,
                    balloonPos:'bottom',
                    function: 'ADMINBRXC.toggleTopbarTweaks(["darkmode"], false)',
                    icon: '<i class="bricks-svg fas fa-moon" style="opacity: .75;"></i>',
                    container: leftToolbar,
                    elements: elements,
                    position: 'before'
                })
            } 

            // Global Class Manager
            if(settingsIcons.includes('class-manager')){
                addMenuItemtoToolbar({
                    classes: 'brxc-icon class-manager',
                    balloon: `Class Manager`,
                    balloonPos:'bottom',
                    function: 'ADMINBRXC.openClassManager("global")',
                    icon: '<i class="bricks-svg ion-md-options" style="opacity: .75;"></i>',
                    container: leftToolbar,
                    elements: elements,
                    position: 'before'
                })
            }

            // Global Query Manager
            if(settingsIcons.includes('global-query')){
                addMenuItemtoToolbar({
                    classes: 'brxc-icon query-manager',
                    balloon: `Query Manager`,
                    balloonPos:'bottom',
                    function: 'ADMINBRXC.openModal({target: false, id: "#brxcQueryManagerOverlay", callback: () => {ADMINBRXC.queryManagerInit();}});',
                    icon: '<i class="bricks-svg fas fa-infinity" style="opacity: .75;"></i>',
                    container: leftToolbar,
                    elements: elements,
                    position: 'before'
                })
            }

            // ATF
            if(settingsIcons.includes('at-framework')){
                addMenuItemtoToolbar({
                    classes: 'brxc-icon at-framework',
                    balloon: `AT Framework`,
                    balloonPos:'bottom',
                    function: 'ADMINBRXC.setFrameworkOptions();',
                    icon: '<i class="bricks-svg ti-text" style="opacity: .75;"></i>',
                    container: leftToolbar,
                    elements: elements,
                    position: 'before'
                })
            }

            // Advanced CSS
            if(settingsIcons.includes('advanced-css')){
                addMenuItemtoToolbar({
                    classes: 'brxc-icon custom-css',
                    balloon: `Advanced CSS`,
                    balloonPos:'bottom',
                    function: 'ADMINBRXC.openModal({target: false, id: "#brxcCSSOverlay", focus: "#brxcCSSOverlay input.class-filter", callback: () => {ADMINBRXC.advancedCSSInit();}});',
                    icon: '<i class="bricks-svg fas fa-code" style="opacity: .75;"></i>',
                    container: leftToolbar,
                    elements: elements,
                    position: 'before'
                })
            }

            // Find & Replace (Global)
            if(settingsIcons.includes('find-and-replace')){
                addMenuItemtoToolbar({
                    classes: 'brxc-icon find-and-replace',
                    balloon: `Find & Replace (Global)`,
                    balloonPos:'bottom',
                    function: "ADMINBRXC.openFindReplaceModal(event,true, '#brxcFindReplaceModal');",
                    icon: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 96 960 960" class="bricks-svg"><path xmlns="http://www.w3.org/2000/svg" d="M138 484q18-110 103.838-182T440 230q75 0 133 30.5t98 82.5v-98h72v239H503v-71h100q-27-42-70.5-65T440 325q-72.187 0-130.093 43.5Q252 412 234 484h-96Zm674 492L615 780q-34 27-78 43.5T440.217 840Q367 840 308.5 813 250 786 209 734v93h-72V588h240v71H271q28.269 41.15 72.541 64.075Q387.812 746 440 746q72.102 0 127.444-44.853T642 588h96q-5 33-19 65.5T684 713l197 196-69 67Z"></path></svg>',
                    container: leftToolbar,
                    elements: elements,
                    position: 'before'
                })
            }

            // Quick Remote Template
            if(settingsIcons.includes('quick-remote-template')){
                addMenuItemtoToolbar({
                    classes: 'brxc-icon quick-remote-template',
                    balloon: `Quick Remote Template`,
                    balloonPos:'bottom',
                    function: 'ADMINBRXC.openRemoteTemplatesModal();',
                    icon: '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="bricks-svg"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 1L3 14h9l-2 9 10-13h-9l3-9Z"/></svg>',
                    container: leftToolbar,
                    elements: elements,
                    position: 'before'
                })
            }
            
            // Middle

            // Responsive Slider
            if(settingsIcons.includes('responsive-slider')){
                addMenuItemtoToolbar({
                    classes: `brxc-icon responsive-slider${setActiveClass('responsive-slider')}`,
                    balloon: 'Responsive Slider',
                    balloonPos:'bottom',
                    function: 'ADMINBRXC.toggleTopbarTweaks(["responsive-slider"], false)',
                    icon: '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14" class="bricks-svg"><g id="vertical-menu--navigation-vertical-three-circle-button-menu-dots"><path id="Vector" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M7 3.5c0.82843 0 1.5 -0.67157 1.5 -1.5S7.82843 0.5 7 0.5 5.5 1.17157 5.5 2 6.17157 3.5 7 3.5Z" stroke-width="1"></path><path id="Vector_2" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M7 8.5c0.82843 0 1.5 -0.67157 1.5 -1.5S7.82843 5.5 7 5.5 5.5 6.17157 5.5 7 6.17157 8.5 7 8.5Z" stroke-width="1"></path><path id="Vector_3" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M7 13.5c0.82843 0 1.5 -0.6716 1.5 -1.5s-0.67157 -1.5 -1.5 -1.5 -1.5 0.6716 -1.5 1.5 0.67157 1.5 1.5 1.5Z" stroke-width="1"></path></g></svg>',
                    container: middleToolbar,
                    elements: dimensionsWidth,
                    position: 'before'
                })
            }

            if(settingsIcons.includes('zoom-out')){
                addMenuItemtoToolbar({
                    classes: 'brxc-icon zoom-out',
                    balloon: 'Zoom-out',
                    balloonPos:'bottom',
                    function: 'ADMINBRXC.toggleTopbarTweaks(["zoom-out"], false)',
                    icon: '<i class="bricks-svg ti-zoom-out" style="opacity: .75;"></i>',
                    container: middleToolbar,
                    elements: dimensionsWidth,
                    position: 'after'
                })
            }
             
            // Right

            // Openai
            if(settingsIcons.includes('openai')){
                addMenuItemtoToolbar({
                    classes: `brxc-icon openai`,
                    balloon: `OpenAI Assistant`,
                    balloonPos:'bottom',
                    function: 'ADMINBRXC.openModal({target: false, id: "#brxcGlobalOpenAIOverlay"})',
                    icon: '<i class="bricks-svg fas fa-robot" style="opacity: .75;"></i>',
                    container: rightToolbar,
                    elements: structure,
                    position: 'before'
                })
            }

            // AI Prompt Manager
            if(settingsIcons.includes('ai-prompt-manager')){
                addMenuItemtoToolbar({
                    classes: `brxc-icon ai-prompt-manager`,
                    balloon: `AI Prompt Manager`,
                    balloonPos:'bottom',
                    function: 'ADMINBRXC.openModal({target: false, id: "#brxcPromptManagerOverlay", callback: () => {ADMINBRXC.promptManagerInit();}})',
                    icon: '<i class="bricks-svg fas fa-comment" style="opacity: .75;"></i>',
                    container: rightToolbar,
                    elements: structure,
                    position: 'before'
                })
            }

            // Variable Manager
            if(settingsIcons.includes('variable-manager')){
                addMenuItemtoToolbar({
                    classes: 'brxc-icon CSSVariableManager',
                    balloon: `CSS Variable Manager`,
                    balloonPos:'bottom',
                    function: 'ADMINBRXC.openModal({target: false, id: "#brxcCSSVariableManagerOverlay", focus: "#brxcCSSVariableManagerOverlay input[type=text].class-filter", callback: () => {ADMINBRXC.cssVariablesStates.search = "";ADMINBRXC.cssVariablesStates.view = "full";ADMINBRXC.setCSSVariableManager();}});',
                    icon: '<i class="bricks-svg fas fa-square-root-variable" style="opacity: .75;"></i>',
                    container: rightToolbar,
                    elements: structure,
                    position: 'before'
                })
            }

            // Color Manager
            if(settingsIcons.includes('color-manager')){
                addMenuItemtoToolbar({
                    classes: 'brxc-icon colorManager',
                    balloon: `Color Manager`,
                    balloonPos:'bottom',
                    function: 'ADMINBRXC.openModal({target: false, id: "#brxcColorManagerOverlay", focus: "#brxcColorManagerOverlay input[type=text].class-filter", callback: () => {ADMINBRXC.setColorManager();}});',
                    icon: '<i class="bricks-svg fas fa-palette" style="opacity: .75;"></i>',
                    container: rightToolbar,
                    elements: structure,
                    position: 'before'
                })
            }

            // Quick Search
            if(settingsIcons.includes('quick-search')){
                addMenuItemtoToolbar({
                    classes: 'brxc-icon quick-search',
                    balloon: `Quick Search`,
                    balloonPos:'bottom',
                    function: 'ADMINBRXC.openQuickSearch()',
                    icon: '<i class="bricks-svg fas fa-magnifying-glass" style="opacity: .75;"></i>',
                    container: rightToolbar,
                    elements: structure,
                    position: 'before'
                })
            }

            // Resources
            if(settingsIcons.includes('resources')){
                addMenuItemtoToolbar({
                    classes: 'brxc-icon resources',
                    balloon: `Resources`,
                    balloonPos:'bottom',
                    function: 'ADMINBRXC.openModal({target: false, id: "#brxcResourcesOverlay", closeActiveModals: false})',
                    icon: '<i class="bricks-svg fas fa-images" style="opacity: .75;"></i>',
                    container: rightToolbar,
                    elements: structure,
                    position: 'before'
                })
            }

            // Brickslabs
            if(settingsIcons.includes('brickslabs')){
                addMenuItemtoToolbar({
                    classes: 'brxc-icon brickslabs',
                    balloon: `BricksLabs`,
                    balloonPos:'bottom',
                    function: 'ADMINBRXC.openModal({target: false, id: "#brxcBricksLabsOverlay", callback: () => {ADMINBRXC.bricksLabsAPI(false, false, true);}})',
                    icon: '<i class="bricks-svg fas fa-flask" style="opacity: .75;"></i>',
                    container: rightToolbar,
                    elements: structure,
                    position: 'before'
                })
            }

            // Strict Editor View
            if(settingsIcons.includes('strict-editor-settings')){
                addMenuItemtoToolbar({
                    classes: `brxc-icon strict-editor-settings${setActiveClass('strict-editor-settings')}`,
                    balloon: `Strict Editor Settings`,
                    balloonPos:'bottom',
                    function: 'ADMINBRXC.toggleTopbarTweaks(["strict-editor-settings"], false)',
                    icon: '<i class="bricks-svg fas fa-unlock-keyhole" style="opacity: .75;"></i>',
                    container: rightToolbar,
                    elements: structure,
                    position: 'before'
                })
            }
            
            // Main AT Menu
            addMenuItemtoToolbar({
                classes: `brxc-icon main-at-menu`,
                balloon: `AT Main Menu`,
                balloonPos:'bottom',
                function: 'event.stopPropagation();ADMINBRXC.openMainMenu(this, true);',
                icon: '<i style="opacity:.75""><span class="brxc-AT-menu-icon">AT</span></i>',
                container: leftToolbar,
                elements: elements,
                position: 'before'
            })
        }
    },
    toggleTopbarIcons: function(key){
        const self = this;
        if(!key) return;

        const index = self.topbarStates.icons.indexOf(key);
        if(index === -1){
            self.topbarStates.icons.push(key)
        } else{
            self.topbarStates.icons.splice(index, 1)
        }

        self.helpers.setLocalStorage('topbarIcons', self.topbarStates.icons);
        self.initToolbar();
        self.openMainMenu(false, false)

    },
    toggleTopbarTweaks: function(keys, open = true){
        const self = this;
        if(!Array.isArray(keys)) return;

        keys.forEach(key => {
            const index = self.topbarStates.tweaks.indexOf(key);
            if(index === -1){
                self.topbarStates.tweaks.push(key)
            } else{
                self.topbarStates.tweaks.splice(index, 1)
            }
            self.runTopbarTweaks(key);
        })   
        self.helpers.setLocalStorage('topbarTweaks', self.topbarStates.tweaks);
        if(open) self.openMainMenu(false, false)
    },
    runTopbarTweaks: function(key){
        const self = this;
        switch(key){
            case 'grid-guides':
                self.generateGridGuideCSS();
                self.gridGuide();
                break;
            case 'x-mode':
                self.XCode();
                break;
            case 'contrast-checker':
                self.contrast();
                break;
            case 'darkmode':
                self.darkMode();
                break;
            case 'responsive-helper':
                if(!self.topbarStates.tweaks.includes('responsive-helper')){
                    document.body.classList.remove('at-responsive-helper');
                    const activeItems = document.querySelectorAll('#bricks-toolbar li.breakpoint[data-click]');
                    activeItems.forEach(el => el.removeAttribute('data-click'))
                } else {
                     document.body.classList.add('at-responsive-helper');
                }
                break;
            case 'responsive-slider':
                self.toggleResponsiveSlider();
                break;
            case 'zoom-out':
                self.zoomOut();
                break;
            case 'strict-editor-settings':
                self.toggleStrictEditorView()
                break;
        }
    },
    mainMenuStates: {
        left: 0,
    },
    buildMainMenu: function(close){
        const self = this;
        const menuIcon = document.querySelector('li.main-at-menu');
        if(!menuIcon) return;
        menuIcon.classList.add('active')
        const menuIconPos = menuIcon.getBoundingClientRect();
        const shortcut = self.vueState.isMac ? 'CTRL + CMD' : 'CTRL + SHIFT';

        let menu = document.createElement('div');
        menu.id = 'brxc-main-at-menu';
        menu.classList.add('show');
        if(close){
            self.mainMenuStates.left = menuIconPos.left;
        }
        menu.style.left = `${self.mainMenuStates.left}px`;

        function isTopBarIconActive(key){
            return self.topbarStates.icons.includes(key);
        }

        function isTopBarTweakActive(key){
            return self.topbarStates.tweaks.includes(key);
        }

        function printGroup(group){
            return `<div class="brxc-main-menu__block">
                        <div class="title">${group.label}</div>
                        ${group.items.map(item => {
                            return `<li onclick="ADMINBRXC.closeMainMenu();${item.onClick}">
                                        <div class="brxc-main-menu__label-wrapper">
                                            <span class="bricks-svg-wrapper">${item.icon}</span>
                                            <div class="brxc-label-wrapper">
                                                <span class="label">${item.label}</span>
                                                <div class="brxc-item-doc" data-balloon="doc" data-balloon-pos="right" onClick="event.stopPropagation();window.open('${item.url}', '_blank');">
                                                    <i class="fas fa-external-link-alt"></i>
                                                </div>
                                            </div>
                                        </div>
                                        <div class="action">
                                            <span class="shortcut">${item.shortcut}</span>
                                            <div class="topbar-icon${item.topbar ? ' active' : ''}" data-key="${item.key}" data-balloon="Add to Topbar" onclick="event.stopPropagation();ADMINBRXC.toggleTopbarIcons(this.dataset.key)"><i class="fas fa-star"></i></div>
                                        </div>
                                    </li>`
                        }).join('')}
                    </div>`
        }
        function printTweak(group){
            return `<div class="brxc-main-menu__block">
                        <div class="title">${group.label}</div>
                        ${group.items.map(item => {
                            return `<li onclick="event.stopPropagation();${item.onClick}">
                                        <div class="brxc-main-menu__label-wrapper">
                                            <span class="bricks-svg-wrapper">${item.icon}</span>
                                            <div class="brxc-label-wrapper">
                                                <span class="label">${item.label}</span>
                                                ${item.settings ? item.settings : ''}
                                                <div class="brxc-item-doc" data-balloon="doc" data-balloon-pos="right" onClick="event.stopPropagation();window.open('${item.url}', '_blank');">
                                                    <i class="fas fa-external-link-alt"></i>
                                                </div>
                                            </div>
                                        </div>
                                        <div class="action">
                                            <span class="shortcut">${item.shortcut}</span>
                                            <div class="toggle"><i class="fas fa-toggle-${item.isEnabled === true? 'on' : 'off'}"></i></div>
                                            ${item.hasTopbar ? `<div class="topbar-icon${item.topbar ? ' active' : ''}" data-key="${item.key}" data-balloon="Add to Topbar" onclick="event.stopPropagation();ADMINBRXC.toggleTopbarIcons(this.dataset.key)"><i class="fas fa-star"></i></div>`: ''}
                                        </div>
                                    </li>`
                        }).join('')}
                    </div>`
        }
        let content = "";
        const groupManager = {
            label: "Managers",
            items: [
                {
                    key: 'class-manager',
                    label: "Global Class Manager",
                    url: 'https://advancedthemer.com/features/class-manager/',
                    icon: '<i class="bricks-svg ion-md-options"></i>',
                    shortcut: `${shortcut} + ${self.globalSettings.keyboardShortcuts.classManager}`,
                    onClick: "ADMINBRXC.openClassManager('global');",
                    topbar: isTopBarIconActive('class-manager'),
                },
                {
                    key: 'color-manager',
                    label: "Color Manager",
                    url: 'https://advancedthemer.com/features/all-your-palettes-well-organized-inside-the-builder/',
                    icon: '<i class="bricks-svg fas fa-palette"></i>',
                    shortcut: `${shortcut} + ${self.globalSettings.keyboardShortcuts.colorManager}`,
                    onClick: "ADMINBRXC.openModal({target: false, id: '#brxcColorManagerOverlay', callback: () => {ADMINBRXC.setColorManager();}});",
                    topbar: isTopBarIconActive('color-manager'),
                },
                {
                    key: 'global-query',
                    label: "Query Loop Manager",
                    url: 'https://advancedthemer.com/features/global-query-manager/',
                    icon: '<i class="bricks-svg fas fa-infinity"></i>',
                    shortcut: `${shortcut} + ${self.globalSettings.keyboardShortcuts.queryLoopManager}`,
                    onClick: "ADMINBRXC.openModal({target: false,id: '#brxcQueryManagerOverlay', callback: () => {ADMINBRXC.queryManagerInit();}});",
                    topbar: isTopBarIconActive('global-query'),
                },
                {
                    key: 'variable-manager',
                    label: "Variable Manager",
                    url: 'https://advancedthemer.com/features/variable-manager/',
                    icon: '<i class="bricks-svg fas fa-square-root-variable"></i>',
                    shortcut: `${shortcut} + ${self.globalSettings.keyboardShortcuts.variableManager}`,
                    onClick: "ADMINBRXC.openModal({target: false, id: '#brxcCSSVariableManagerOverlay', focus: '#brxcCSSVariableManagerOverlay input[type=text].class-filter', callback: () => {ADMINBRXC.cssVariablesStates.search = '';ADMINBRXC.cssVariablesStates.view = 'full';ADMINBRXC.setCSSVariableManager();}});",
                    topbar: isTopBarIconActive('variable-manager'),
                }
            ]
        }
        const groupStyles = {
            label: "Styles & CSS",
            items: [
                {
                    key: 'at-framework',
                    label: "AT Framework<span class='version'>v1.2</span>",
                    url: 'https://advancedthemer.com/features/at-css-framework/',
                    icon: '<i class="bricks-svg ti-text"></i>',
                    shortcut: `${shortcut} + ${self.globalSettings.keyboardShortcuts.ATFramework}`,
                    onClick: "ADMINBRXC.setFrameworkOptions();",
                    topbar: isTopBarIconActive('at-framework'),
                },
                {
                    key: 'advanced-css',
                    label: "Advanced CSS",
                    url: 'https://advancedthemer.com/features/advanced-css-editor/',
                    icon: '<i class="bricks-svg fas fa-code"></i>',
                    shortcut: `${shortcut} + ${self.globalSettings.keyboardShortcuts.cssStylesheets}`,
                    onClick: "ADMINBRXC.openModal({target: false, id: '#brxcCSSOverlay', focus: '#brxcCSSOverlay input.class-filter', callback: () => {ADMINBRXC.advancedCSSInit();}});",
                    topbar: isTopBarIconActive('advanced-css'),
                },
                {
                    key: 'find-and-replace',
                    label: "Find & Replace (Global)",
                    url: 'https://advancedthemer.com/features/find-replace-any-style-value/',
                    icon: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 96 960 960" class="bricks-svg"><path xmlns="http://www.w3.org/2000/svg" d="M138 484q18-110 103.838-182T440 230q75 0 133 30.5t98 82.5v-98h72v239H503v-71h100q-27-42-70.5-65T440 325q-72.187 0-130.093 43.5Q252 412 234 484h-96Zm674 492L615 780q-34 27-78 43.5T440.217 840Q367 840 308.5 813 250 786 209 734v93h-72V588h240v71H271q28.269 41.15 72.541 64.075Q387.812 746 440 746q72.102 0 127.444-44.853T642 588h96q-5 33-19 65.5T684 713l197 196-69 67Z"></path></svg>',
                    shortcut: `${shortcut} + ${self.globalSettings.keyboardShortcuts.findAndReplace}`,
                    onClick: "ADMINBRXC.openFindReplaceModal(event,true, '#brxcFindReplaceModal');",
                    topbar: isTopBarIconActive('find-and-replace'),
                }
            ]
        }
        const groupTemplates = {
            label: "Templates",
            items: [
                {
                    key: 'quick-remote-template',
                    label: "Quick Remote Templates",
                    url: 'https://advancedthemer.com/features/quick-remote-templates/',
                    icon: '<i class="bricks-svg ti-layout"></i>',
                    shortcut: `${shortcut} + ${self.globalSettings.keyboardShortcuts.remoteTemplate}`,
                    onClick: "ADMINBRXC.openRemoteTemplatesModal()",
                    topbar: isTopBarIconActive('quick-remote-template'),
                }
            ]
        }
        const groupAI = {
            label: "AI",
            items: [
                {
                    key: 'openai',
                    label: `AI Assistant`,
                    url: 'https://advancedthemer.com/category/ai-integration/',
                    icon: '<i class="bricks-svg fas fa-robot"></i>',
                    shortcut: `${shortcut} + ${self.globalSettings.keyboardShortcuts.openai}`,
                    onClick: "ADMINBRXC.openModal({target: false, id: '#brxcGlobalOpenAIOverlay'})",
                    topbar: isTopBarIconActive('openai'),
                },
                {
                    key: 'ai-prompt-manager',
                    label: `AI Prompt Manager`,
                    url: 'https://advancedthemer.com/features/ai-prompt-manager/',
                    icon: '<i class="bricks-svg fas fa-comment"></i>',
                    shortcut: `${shortcut} + ${self.globalSettings.keyboardShortcuts.promptManager}`,
                    onClick: "ADMINBRXC.openModal({target: false, id: &quot;#brxcPromptManagerOverlay&quot;, callback: () => {ADMINBRXC.promptManagerInit();}})",
                    topbar: isTopBarIconActive('ai-prompt-manager'),
                }
            ]
        }
        const groupExtra = {
            label: "Extra",
            items: [
                {
                    key: 'quick-search',
                    label: "Quick Search",
                    url: 'https://advancedthemer.com/features/quick-search/',
                    icon: '<i class="bricks-svg fas fa-magnifying-glass"></i>',
                    shortcut: `${self.vueState.isMac ? 'CMD' : 'CTRL'} + ${self.globalSettings.keyboardShortcuts.quickSearch}`,
                    onClick: "ADMINBRXC.openQuickSearch()",
                    topbar: isTopBarIconActive('quick-search'),
                },
                {
                    key: 'resources',
                    label: "Resources Panel",
                    url: 'https://advancedthemer.com/features/new-resources-panel/',
                    icon: '<i class="bricks-svg fas fa-images"></i>',
                    shortcut: `${shortcut} + ${self.globalSettings.keyboardShortcuts.resources}`,
                    onClick: "ADMINBRXC.openModal({target: false, id: '#brxcResourcesOverlay', closeActiveModals: false})",
                    topbar: isTopBarIconActive('resources'),
                },
                {
                    key: 'brickslabs',
                    label: "BricksLabs Center",
                    url: 'https://advancedthemer.com/features/brickslabs-integration/',
                    icon: '<i class="bricks-svg fas fa-flask"></i>',
                    shortcut: `${shortcut} + ${self.globalSettings.keyboardShortcuts.brickslabs}`,
                    onClick: "ADMINBRXC.openModal({target: false, id: '#brxcBricksLabsOverlay', callback: () => {ADMINBRXC.bricksLabsAPI(false, false, true);}})",
                    topbar: isTopBarIconActive('brickslabs'),
                }
            ]
        }
        const groupTweaks = {
            label: "Builder Tweaks",
            items: [
                {
                    key: 'grid-guides',
                    label: "Grid Guides",
                    url: 'https://advancedthemer.com/features/grid-guides/',
                    settings: `<div class='settings' data-balloon='Settings' data-balloon-pos='right' onclick='event.stopPropagation();ADMINBRXC.closeMainMenu();ADMINBRXC.setGridGuideOptions(this);'><i class='fas fa-gear'></i></div>`,
                    icon: '<i class="bricks-svg ti-layout-grid4-alt"></i>',
                    shortcut: `${shortcut} + ${self.globalSettings.keyboardShortcuts.gridGuides}`,
                    onClick: "ADMINBRXC.toggleTopbarTweaks(['grid-guides'])",
                    hasTopbar: true,
                    topbar: isTopBarIconActive('grid-guides'),
                    isEnabled: isTopBarTweakActive('grid-guides'),
                },
                {
                    key: 'x-mode',
                    label: "X-mode",
                    url: 'https://advancedthemer.com/features/x-mode/',
                    icon: '<i class="bricks-svg fas fa-border-top-left"></i>',
                    shortcut: `${shortcut} + ${self.globalSettings.keyboardShortcuts.xMode}`,
                    onClick: "ADMINBRXC.toggleTopbarTweaks(['x-mode'])",
                    hasTopbar: true,
                    topbar: isTopBarIconActive('x-mode'),
                    isEnabled: isTopBarTweakActive('x-mode'),
                },
                {
                    key: 'contrast-checker',
                    label: "Contrast Checker",
                    url: 'https://advancedthemer.com/features/contrast-checker/',
                    icon: '<i class="bricks-svg ion-ios-contrast"></i>',
                    shortcut: `${shortcut} + ${self.globalSettings.keyboardShortcuts.contrastChecker}`,
                    onClick: "ADMINBRXC.toggleTopbarTweaks(['contrast-checker'])",
                    hasTopbar: true,
                    topbar: isTopBarIconActive('contrast-checker'),
                    isEnabled: isTopBarTweakActive('contrast-checker'),
                },
                {
                    key: 'darkmode',
                    label: "Darkmode",
                    url: 'https://advancedthemer.com/features/darkmode-toggle/',
                    icon: '<i class="bricks-svg fas fa-moon"></i>',
                    shortcut: `${shortcut} + ${self.globalSettings.keyboardShortcuts.darkmode}`,
                    onClick: "ADMINBRXC.toggleTopbarTweaks(['darkmode'])",
                    hasTopbar: true,
                    topbar: isTopBarIconActive('darkmode'),
                    isEnabled: isTopBarTweakActive('darkmode'),
                },
                {
                    key: 'zoom-out',
                    label: "Zoom-out",
                    url: 'https://advancedthemer.com/features/zoom-out/',
                    icon: '<i class="bricks-svg ti-zoom-out"></i>',
                    shortcut: ``,
                    onClick: "ADMINBRXC.toggleTopbarTweaks(['zoom-out'])",
                    hasTopbar: true,
                    topbar: isTopBarIconActive('zoom-out'),
                    isEnabled: isTopBarTweakActive('zoom-out'),
                },
                {
                    key: 'responsive-slider',
                    label: "Responsive Slider",
                    url: 'https://advancedthemer.com/features/responsive-helper/',
                    icon: '<i class="bricks-svg fas fa-arrows-left-right-to-line"></i>',
                    shortcut: ``,
                    onClick: "ADMINBRXC.toggleTopbarTweaks(['responsive-slider'])",
                    hasTopbar: true,
                    topbar: isTopBarIconActive('responsive-slider'),
                    isEnabled: isTopBarTweakActive('responsive-slider'),
                },
                {
                    key: 'responsive-helper',
                    label: "Responsive Helper",
                    url: 'https://advancedthemer.com/features/responsive-helper/',
                    icon: '<i class="bricks-svg fas fa-mobile"></i>',
                    shortcut: ``,
                    onClick: "ADMINBRXC.toggleTopbarTweaks(['responsive-helper'])",
                    hasTopbar: false,
                    topbar: isTopBarIconActive('responsive-helper'),
                    isEnabled: isTopBarTweakActive('responsive-helper'),
                }
            ]
        }
        content += `<ul>
                        ${printGroup(groupManager)}
                        ${printGroup(groupStyles)}
                        ${printGroup(groupTemplates)}
                        ${printGroup(groupAI)}
                    </ul>
                    <ul>
                        ${printGroup(groupExtra)}
                        ${self.helpers.isStrictEditorViewTabActive() ? `
                        <div class="brxc-main-menu__block">
                            <div class="title">Strict Editor View</div>
                            <li onclick="event.stopPropagation();ADMINBRXC.toggleTopbarTweaks(['strict-editor-settings']);">
                                <div class="brxc-main-menu__label-wrapper">
                                    <span class="bricks-svg-wrapper"><i class="bricks-svg fas fa-unlock-keyhole" style="opacity: .75;"></i></span>
                                    <div class="brxc-label-wrapper">
                                        <span class="label">Strict Editor Settings</span>
                                        <div class="brxc-item-doc" data-balloon="doc" data-balloon-pos="right" onClick="event.stopPropagation();window.open('https://advancedthemer.com/features/select-the-controls-your-clients-can-see-for-each-element-type/', '_blank');">
                                            <i class="fas fa-external-link-alt"></i>
                                        </div>
                                    </div>
                                </div>
                                <div class="action">
                                    <span class="save"><span class="bricks-svg-wrapper" data-balloon="Save Settings" data-balloon-pos="top" onclick="event.stopPropagation();ADMINBRXC.saveFullAccessOptions()"><i class="fas fa-floppy-disk"></i></span></span>
                                    <div class="toggle"><i class="fas fa-toggle-${self.strictEditorState === true? 'on' : 'off'}"></i></div>
                                    <div class="topbar-icon${isTopBarIconActive('strict-editor-settings') ? ' active' : ''}" data-key="strict-editor-settings" data-balloon="Add to Topbar" onclick="event.stopPropagation();ADMINBRXC.toggleTopbarIcons(this.dataset.key)"><i class="fas fa-star"></i></div>
                                </div>
                            </li>
                        </div>` : ''}
                        ${self.helpers.isBuilderTweaksTabActive() ? printTweak(groupTweaks) : ''}
                        </ul>
                        <ul style="background-color:var(--builder-bg-2);">
                        ${self.helpers.isBuilderTweaksTabActive() ? `
                        <div class="brxc-main-menu__block">
                            <div class="title">Quick Edits</div>
                            <li onclick="ADMINBRXC.closeMainMenu();ADMINBRXC.toggleQuickEditOption(ADMINBRXC.globalSettings.classFeatures, 'disable-id-styles', 'at-disable-styles');">
                                <span class="label">Lock ID Styles</span>
                                <div class="action">
                                    <div class="toggle" onclick="event.stopPropagation();ADMINBRXC.toggleQuickEditOption(ADMINBRXC.globalSettings.classFeatures, 'disable-id-styles', 'at-disable-styles');ADMINBRXC.openMainMenu(false, false);"><i class="fas fa-toggle-${self.globalSettings.classFeatures.includes('disable-id-styles') ? 'on' : 'off'}"></i></div>
                                </div>
                            </li>
                            <li onclick="ADMINBRXC.closeMainMenu();ADMINBRXC.toggleQuickEditOption(ADMINBRXC.globalSettings.classFeatures, 'focus-on-first-class');">
                                <span class="label">Focus on First Unlocked Class</span>
                                <div class="action">
                                    <div class="toggle" onclick="event.stopPropagation();ADMINBRXC.toggleQuickEditOption(ADMINBRXC.globalSettings.classFeatures, 'focus-on-first-class');ADMINBRXC.openMainMenu(false, false);"><i class="fas fa-toggle-${self.globalSettings.classFeatures.includes('focus-on-first-class') ? 'on' : 'off'}"></i></div>
                                </div>
                            </li>
                            <li onclick="ADMINBRXC.closeMainMenu();ADMINBRXC.toggleQuickEditOption(ADMINBRXC.globalSettings.classFeatures, 'autoformat-field-values');">
                                <span class="label">Autoformat Control Values</span>
                                <div class="action">
                                    <div class="toggle" onclick="event.stopPropagation();ADMINBRXC.toggleQuickEditOption(ADMINBRXC.globalSettings.classFeatures, 'autoformat-field-values');ADMINBRXC.openMainMenu(false, false);"><i class="fas fa-toggle-${self.globalSettings.classFeatures.includes('autoformat-field-values') ? 'on' : 'off'}"></i></div>
                                </div>
                            </li>
                            <li onclick="ADMINBRXC.closeMainMenu();ADMINBRXC.toggleQuickEditOption(ADMINBRXC.globalSettings.classFeatures, 'autocomplete-variable');">
                                <span class="label">Suggestions Dropdown for CSS Variables</span>
                                <div class="action">
                                    <div class="toggle" onclick="event.stopPropagation();ADMINBRXC.toggleQuickEditOption(ADMINBRXC.globalSettings.classFeatures, 'autocomplete-variable');ADMINBRXC.openMainMenu(false, false);"><i class="fas fa-toggle-${self.globalSettings.classFeatures.includes('autocomplete-variable') ? 'on' : 'off'}"></i></div>
                                </div>
                            </li>
                            <li onclick="ADMINBRXC.closeMainMenu();ADMINBRXC.toggleQuickEditOption(ADMINBRXC.globalSettings.classFeatures, 'sync-label');">
                                <span class="label">Sync Element's Label with the First Global Class Name</span>
                                <div class="action">
                                    <div class="toggle" onclick="event.stopPropagation();ADMINBRXC.toggleQuickEditOption(ADMINBRXC.globalSettings.classFeatures, 'sync-label');ADMINBRXC.openMainMenu(false, false);"><i class="fas fa-toggle-${self.globalSettings.classFeatures.includes('sync-label') ? 'on' : 'off'}"></i></div>
                                </div>
                            </li>
                            <li onclick="ADMINBRXC.closeMainMenu();ADMINBRXC.toggleQuickEditOption(ADMINBRXC.globalSettings.elementFeatures, 'superpower-custom-css', 'at-superpower-css');">
                                <span class="label">SuperPowerCSS</span>
                                <div class="action">
                                    <div class="toggle" onclick="event.stopPropagation();ADMINBRXC.toggleQuickEditOption(ADMINBRXC.globalSettings.elementFeatures, 'superpower-custom-css', 'at-superpower-css');ADMINBRXC.openMainMenu(false, false);"><i class="fas fa-toggle-${self.globalSettings.elementFeatures.includes('superpower-custom-css') ? 'on' : 'off'}"></i></div>
                                </div>
                            </li>
                            <li onclick="ADMINBRXC.closeMainMenu();ADMINBRXC.toggleQuickEditOption(ADMINBRXC.globalSettings.elementFeatures, 'dynamic-data-modal', 'at-dynamic-data-modal');">
                                <span class="label">Dynamic Data Modal</span>
                                <div class="action">
                                    <div class="toggle" onclick="event.stopPropagation();ADMINBRXC.toggleQuickEditOption(ADMINBRXC.globalSettings.elementFeatures, 'dynamic-data-modal', 'at-dynamic-data-modal');ADMINBRXC.openMainMenu(false, false);"><i class="fas fa-toggle-${self.globalSettings.elementFeatures.includes('dynamic-data-modal') ? 'on' : 'off'}"></i></div>
                                </div>
                            </li>
                            <li onclick="ADMINBRXC.closeMainMenu();ADMINBRXC.toggleQuickEditOption(ADMINBRXC.globalSettings.elementFeatures, 'disable-borders-boxshadows');">
                                <span class="label">Disable Borders & Box-shadow Outlines</span>
                                <div class="action">
                                    <div class="toggle" onclick="event.stopPropagation();ADMINBRXC.toggleQuickEditOption(ADMINBRXC.globalSettings.elementFeatures, 'disable-borders-boxshadows');ADMINBRXC.openMainMenu(false, false);"><i class="fas fa-toggle-${self.globalSettings.elementFeatures.includes('disable-borders-boxshadows') ? 'on' : 'off'}"></i></div>
                                </div>
                            </li>
                        </div>    
                        ` : ''}
                    </ul>`;

        menu.innerHTML = content;
        document.body.appendChild(menu);
    },
    toggleQuickEditOption: function(arr,value, bodyClass = false){
        const self = this;
        if(arr.includes(value)){
            const index = arr.indexOf(value);
            arr.splice(index,1);
            if(bodyClass) document.body.classList.remove(bodyClass);
            switch(value){
                case 'disable-id-styles':
                    self.forceClassStlyesStates.lastElementId = '';
                    self.forceClassStlyesStates.showLock = !self.forceClassStlyesStates.showLock;
                    const icon = document.querySelector('.disabled-style-icon');
                    if(icon) icon.remove();
                case 'disable-borders-boxshadows':
                    const iframeBorderItems = FRAMEBRXC.content.body.querySelectorAll('.is-active-element.has-border-settings');
                    if(iframeBorderItems && iframeBorderItems.length > 0){
                        iframeBorderItems.forEach(el => el.classList.remove('has-border-settings'));
                    }
                default:
                    // silence
            }
        } else {
            arr.push(value);
            if(bodyClass) document.body.classList.add(bodyClass);
        }
        self.vueState.rerenderControls = Date.now();
    },
    openMainMenu: function(target, close = true){
        const self = this;
        const x = document.querySelector('#bricks-builder-iframe').contentWindow;
        const existingMenu = document.querySelector('#brxc-main-at-menu');
        if(existingMenu){
            existingMenu.remove();
            if(close === true){
                if(target) target.classList.remove('active');
                return;
            }
        }
        function openMenu() {
            window.addEventListener('click', menuClickListener);
            x.document.addEventListener('click', menuClickListener);
            self.buildMainMenu(close);
        }
        
        function closeMenu() {
            window.removeEventListener('click', menuClickListener);
            x.document.removeEventListener('click', menuClickListener);
            self.closeMainMenu();
        }
        
        function menuClickListener(event) {
            closeMenu();
        }
        openMenu();
    },
    closeMainMenu: function(){
        const existingMenu = document.querySelector('#brxc-main-at-menu');
        if(existingMenu) existingMenu.remove();
        const menuIcon = document.querySelector('li.main-at-menu');
        if(!menuIcon) return;
        menuIcon.classList.remove('active')
    },
    // CSS Variable Manager
    cssVariablesStates:{
        activeCategory: 'all',
        renameCategory: false,
        addCategory: false,
        importGlobalVariables: false,
        importThemeVariables: false,
        search: '',
        showGlobal: true,
        showTheme: true,
        generatedCSSTheme: false,
        view: 'full',
        exportCSS: false,
        onDrag: false,
        skipValues: false,
    },
    generateBuilderCSS: function(){
        const self = this;
        const x = document.querySelector('#bricks-builder-iframe').contentWindow;
        var stylesheet1 = x.document.querySelector(':root');
        var stylesheet2 = document.querySelector(':root');

        let css = '';
        if(self.colorStates.generatedCSS) css += self.colorStates.generatedCSS;
        if(self.helpers.isCSSVariablesTabActive('theme-variables') && self.cssVariablesStates.generatedCSSTheme) css += self.cssVariablesStates.generatedCSSTheme;
        [stylesheet1,stylesheet2].forEach(root => {
            root.removeAttribute('style');
            root.style = css;
        }) 
    },
    generateVariableCSS: function() {
        const self = this;
        if(!self.helpers.isCSSVariablesTabActive('theme-variables')) return;

        const theme = self.vueState.themeStyleSettings;
        if(!theme) return;

        const general = theme.hasOwnProperty('general') ? theme.general : false;
        if(!general) return;


        const vars = general.hasOwnProperty('_cssVariables') ? general._cssVariables : false;
        if(!vars || !Array.isArray(vars) || vars.length < 1) return;

        const css = vars
            .filter(variable => variable.hasOwnProperty('name') && variable.hasOwnProperty('value'))
            .map(variable => `--${variable.name}:${variable.value};`)
            .join('');

        self.cssVariablesStates.generatedCSSTheme = css;

    },
    setCSSVariableManager: function(){
        const self = this;
        self.setCSSVariableManagerHeader();
        self.setCSSVariableManagerSearch();
        self.setCSSVariableManagerBody();
    },
    setCSSVariableManagerHeader: function(){
        const self = this;
        self.cssVariablesStates.view === "sidebar" ? self.setCSSVariableManagerHeaderSidebar() : self.setCSSVariableManagerHeaderFull();
    },
    setCSSVariableManagerHeaderSidebar: function(){
        const self = this;
        const canvas = document.querySelector('#CSSVariableHeaderCanvas')
        if(!canvas) return;

        let content = '';
        content += `<div class="brxc-select">`;
        
        // set default active category
        if(self.cssVariablesStates.activeCategory === false && self.vueState.globalVariablesCategoriesSelected.length === 0){
            self.cssVariablesStates.activeCategory = 'all';
        }
        
        
        if(self.cssVariablesStates.renameCategory === false && self.cssVariablesStates.addCategory === false && self.cssVariablesStates.activeCategory){
            const categories = [{'id': 'all', 'name': 'All'},{'id': 'uncategorized', 'name': 'Uncategorized'}].concat(self.vueState.globalVariablesCategories);
            const uneditableCategories = ['all', 'uncategorized'];

            content += `<div class="brxc-select-new rounded hidden" name="brxc-cssVariablesOptions" id="cssVariablesOptions">
                            <div class="brxc-select-new__wrapper">
                                ${categories.map(cat => {
                                    return `<div data-value="${cat.id}"${cat.id === self.cssVariablesStates.activeCategory ? ' class="active"' : ''}><span>${cat.name}</span></div>`;
                                }).join('')}
                            </div>
                        </div>`
            content += '<div class="brxc-icon-container">'
            content += !uneditableCategories.includes(self.cssVariablesStates.activeCategory) ? `<div class="brxc-icon" data-balloon="Rename Category" data-balloon-pos="bottom-right" onClick="ADMINBRXC.cssVariablesStates.renameCategory = true;ADMINBRXC.setCSSVariableManagerHeader()"><span class="bricks-svg-wrapper"><i class="fas fa-pen"></i></span></div>` : '';
            content += `<div class="brxc-icon" data-balloon="Add New Category" data-balloon-pos="bottom-right" onClick="ADMINBRXC.cssVariablesStates.addCategory = true;ADMINBRXC.setCSSVariableManagerHeader()"><span class="bricks-svg-wrapper"><i class="fas fa-plus"></i></span></div>`;
            content += !uneditableCategories.includes(self.cssVariablesStates.activeCategory) ? `<div class="brxc-icon" data-balloon="Delete Category" data-balloon-pos="bottom-right" onClick="ADMINBRXC.setDeleteVariable(this, 'ADMINBRXC.deleteVariableCategory()');"><span class="bricks-svg-wrapper"><i class="ti-trash"></i></span></div>` : '';
            content += `</div>`;
            
        } else if(self.cssVariablesStates.renameCategory === true){
            content += `<input type="text" id="brxcRenameCategory" value="${self.helpers.getGlobalVariableCategoryNameById(self.cssVariablesStates.activeCategory)}" />`;
        } else if(self.cssVariablesStates.addCategory === true){
            content += `<input type="text" id="brxcAddCategory" placeholder="Type the category's name here and hit ENTER." value="" />`;
        }
        content += `</div>`;

        canvas.innerHTML = content;

        // Select Contextual Category
        const select = canvas.querySelector('#cssVariablesOptions');
        self.helpers.selectControl(select, (target) => {
            self.cssVariablesStates.search = '';
            self.cssVariablesStates.activeCategory = target.dataset.value;
            self.setCSSVariableManager()
        })

        // Add
        if (self.cssVariablesStates.addCategory === true || !self.cssVariablesStates.activeCategory) {
            self.cssVariablesStates.addCategory = false;
            const input = canvas.querySelector('#brxcAddCategory');
            if (!input) return;
            const end = input.value.length;
            input.setSelectionRange(end, end);
            input.focus();

            const onBlur = () => {
                input.removeEventListener("blur", onBlur);
                input.removeEventListener("keydown", onKeyDown);
                setTimeout(() => {
                    self.setCSSVariableManagerHeader();
                }, 10);
            };

            const onKeyDown = (event) => {
                if (event.key === "Enter") {
                    self.addVariableCategory(input);
                    input.removeEventListener("blur", onBlur);
                    input.removeEventListener("keydown", onKeyDown);
                }
            };

            input.addEventListener("blur", onBlur);
            input.addEventListener("keydown", onKeyDown);
        }

        // Rename
        if (self.cssVariablesStates.renameCategory === true) {
            self.cssVariablesStates.renameCategory = false;
            const input = canvas.querySelector('#brxcRenameCategory');
            if (!input) return;
            const end = input.value.length;
            input.setSelectionRange(end, end);
            input.focus();

            function renameName(input) {

                const name = input.value.toLowerCase();
                const existingCategory = self.helpers.getGlobalVariableCategoryIdByName(name);
                if(existingCategory) return self.vueGlobalProp.$_showMessage('ABORT: category name already exists!');

                const obj = self.helpers.getGlobalVariableCategoryObjById(self.cssVariablesStates.activeCategory);
                if(!obj) return;

                obj.name = input.value;
                self.vueGlobalProp.$_showMessage('Category successfully renamed!');
                self.setCSSVariableManager();
            }

            const onBlur = () => {
                input.removeEventListener("blur", onBlur);
                input.removeEventListener("keydown", onKeyDown);
                setTimeout(() => {
                    self.setCSSVariableManagerHeader();
                }, 10);
            };

            const onKeyDown = (event) => {
                if (event.key === "Enter") {
                    renameName(input);
                    input.removeEventListener("blur", onBlur);
                    input.removeEventListener("keydown", onKeyDown);
                }
            };

            input.addEventListener("blur", onBlur);
            input.addEventListener("keydown", onKeyDown);
        }
    },
    addVariableCategory: function(input, event){
        if(event && event.key !== "Enter") return;

        const self = this;
        let count = 0;
        let id;
        const names = input.value.split(',').map(item => item.trim());
        names.forEach(el => {
            const name = el.toLowerCase();
            if(!self.vueState.globalVariablesCategories) self.vueState.globalVariablesCategories = [];
            const existingCategory = self.helpers.getGlobalVariableCategoryIdByName(name);
            if(!existingCategory){
                id = self.vueGlobalProp.$_generateId();
                self.vueState.globalVariablesCategories.push({
                    id: id,
                    name: el
                });
                count++;
            } else {
                id = existingCategory;
            }
        })
        if(count > 0) self.vueGlobalProp.$_showMessage('Category successfully added!');
        
        self.cssVariablesStates.activeCategory = id;
        self.setCSSVariableManager();
    },
    setCSSVariableManagerHeaderFull: function(){
        const self = this;
        const canvas = document.querySelector('#CSSVariableHeaderCanvas');
        if(!canvas) return;

        let cats = `<div class="brxc-top-actions">
                        <div id="brxcGenerateContextualCategories" class="brxc-icon" onclick="ADMINBRXC.generateContextualCategories()" data-balloon="Generate Contextual Categories" data-balloon-pos="left"><i class="fas fa-wand-magic-sparkles"></i></div>
                        <div id="brxcGenerateClampSettings" class="brxc-icon" onclick="ADMINBRXC.generateClampSettings()" data-balloon="Generate Clamp Settings" data-balloon-pos="left"><i class="fas fa-text-height"></i></div>
                    </div>`;
        cats += '<ul>';
        let count;
        let isCatActive;
        const arr = self.helpers.isCSSVariablesTabActive('theme-variables') && self.helpers.themeHasVariables() ? self.vueState.globalVariables.concat(self.vueState.themeStyleSettings.general._cssVariables) : self.vueState.globalVariables;

        function isActive (name) {
            if(self.helpers.getGlobalVariableCategoryIdByName(name) === self.cssVariablesStates.activeCategory) return true;
            return false;
        }

        function exportBtn(isCatActive){
            if(!isCatActive) return '';
            return `${isCatActive ? `<div class="export${self.cssVariablesStates.exportCSS ? ' active' : ''}" data-balloon="View Category CSS" data-balloon-pos="top-right"><i class="fab fa-css3-alt"></i></div>` : ''}`
        }

        // All
        count = arr.length;
        isCatActive = self.cssVariablesStates.activeCategory === "all";
        cats += `<li class="category ignore-drag${isCatActive ? ' active' : ''}"${isCatActive ? ' data-active="true"' : ''} data-id="all"><input type="text" value="All" readonly/><div class="action">${exportBtn(isCatActive)}<span class="count">${count}</span></div></li>`
        
        // Uncategorized
        count = Array.from(arr).filter(el => el && self.helpers.isVariableUncategorized(el)).length;
        isCatActive = self.cssVariablesStates.activeCategory === "uncategorized";
        cats += `<li class="category ignore-drag${isCatActive ? ' active' : ''}"${isCatActive ? ' data-active="true"' : ''} data-id="uncategorized"><input type="text" value="Uncategorized" readonly/><div class="action">${exportBtn(isCatActive)}<span class="count">${count}</span></li></div>`

        // Categories
        cats += `<div id="sortableWrapper">`;
        self.vueState.globalVariablesCategories.forEach(catObj => {
            isExpandedDefault = catObj.hasOwnProperty('defaultExpanded');
            count = Array.from(arr).filter(el => el && el.hasOwnProperty('category') && catObj.id === el.category).length;
            isCatActive = catObj.id === self.cssVariablesStates.activeCategory;
            cats += `<li class="category custom${isActive(catObj.name) ? ' active' : ''}"${isActive(catObj.name) ? ' data-active="true"' : ''} data-id="${catObj.id}">
                        <div class="handle"><i class="fas fa-grip-vertical"></i></div>
                        <input type="text" data-initial="${catObj.name}" value="${catObj.name}"${catObj.id !== self.cssVariablesStates.activeCategory ? ' readonly' : ''}/>
                        <div class="action">`;
            if(isCatActive){
                    cats += exportBtn(isCatActive)
                    cats += `<div class="expandedCat${isExpandedDefault ? ' expanded' : ''}" onClick="ADMINBRXC.toggleExpandVariableCategory(event,'${self.cssVariablesStates.activeCategory}')" data-balloon="${isExpandedDefault ? 'Expanded' : 'Collapsed'} inside the Variable Picker" data-balloon-pos="top-right"><span class="bricks-svg-wrapper"><i class="fas fa-expand-alt"></i></span></div>
                             <div class="deleteCat" onClick="event.stopPropagation();ADMINBRXC.deleteVariableCategory('${self.cssVariablesStates.activeCategory}')" data-balloon="Delete category" data-balloon-pos="top-right"><span class="bricks-svg-wrapper"><i class="ti-trash"></i></span></div>`;
            }
                    cats += `<span class="count">${count}</span>
                        </div>
                    </li>`;
        })
        cats += '</div>'; // end of sortable wrapper
        cats += '</ul><input type="text" id="addNewCat" placeholder="+ New category" onkeyup="ADMINBRXC.addVariableCategory(this, event);" />';

        if(canvas && cats) canvas.innerHTML = cats;

        // Listeners
        const lists = canvas.querySelectorAll('li.category')
        lists.forEach(el => {
            el.addEventListener('click', (event) => {
                if(event.target.classList.contains('export')){
                    self.cssVariablesStates.exportCSS = !self.cssVariablesStates.exportCSS;
                    self.setCSSVariableManager();
                    return;
                }
                self.variableManagerFilterCat(event);
            })
            if(el.classList.contains('custom')){
                el.addEventListener('dragover', (event) => {
                    event.preventDefault()
                })
                el.addEventListener('dragenter', (event) => {
                    el.classList.add('dragged');
                })
                el.addEventListener('dragleave', (event) => {
                    el.classList.remove('dragged');
                })
                el.addEventListener('drop', (event) => {
                    event.preventDefault();
                    self.onDropVariableCatList(el);
                }) 
            }
        })

        // rename cat
        const input = canvas.querySelector('li.active input');
        if(input){
            input.addEventListener('keyup', (event) => {
                if(event.key !== "Enter") return;
                if(event.target.value === event.target.dataset.initial) return self.setCSSVariableManagerHeaderFull();
                if(self.vueState.globalVariablesCategories.map(el => el && el.name).includes(event.target.value)) return self.vueGlobalProp.$_showMessage(`ABORT: category "${event.target.value}" already exists`);
                const activeObj = self.helpers.getGlobalVariableCategoryObjById(event.target.parentElement.dataset.id);
                if(!activeObj) return;
                activeObj.name = event.target.value;
                self.vueGlobalProp.$_showMessage(`Category correctly renamed to ${event.target.value}`)
                self.setCSSVariableManagerHeaderFull();
            })
        }

        //Drag and drop
        const rows = canvas.querySelectorAll('ul li .handle');
        if (!rows || rows.length < 1) return;

        const headerWrapper = canvas.querySelector('#sortableWrapper');
        new Sortable(headerWrapper, {
            selectedClass: "sortable-selected",
            animation: 150,
            filter: ".ignore-drag",
            handle: "li .handle",
            helper: 'clone',
            onStart: function (evt) {
                self.cssVariablesStates.onDrag = [{
                    id: evt.item.dataset.id,
                    type: "cat"
                }];
            },
            onEnd: (e) => {
                const originalObj = self.vueState.globalVariablesCategories.find(el => el.id === self.cssVariablesStates.onDrag[0].id);
                const originalIndex = self.vueState.globalVariablesCategories.indexOf(originalObj)
                self.helpers.moveArr(self.vueState.globalVariablesCategories, originalIndex, e.newIndex);

                self.setCSSVariableManager();
            },
        });
    },
    generateContextualCategories: function(){
        const self = this;
        const excludeKeys = ['_typography','_css', '_classes', '_generated-code', '_attributes'];
        const cssCategories = [{key: 'content', title: 'Content'},{key: '_spacing', title: 'Spacing'}, {key: '_typography', title: 'Typography'},
            ...new Map(
                Object.values(bricksData.elements)
                    .map(el => el.controlGroups)
                    .flatMap(el => el) 
                    .flatMap(obj => Object.entries(obj))
                    .filter(([key, value]) => 
                        value.tab === "style" && 
                        !excludeKeys.some(exclude => key.includes(exclude))
                    )
                    .map(([key, value]) => [key, { key, title: value.title }])
            ).values()
        ];

        let count = 0;
        cssCategories.forEach(el => {
            const vars = self.vueState.globalVariablesCategories;
            const existingCat = vars.find(obj => obj.id === `at_${el.key}`);
            if(existingCat) return;

            vars.push({
                id: `at_${el.key}`,
                name: el.title,
                cssCategory: el.key,
            })
            count++;
        })
        if(count === 0){
            self.vueGlobalProp.$_showMessage('ABORT: NO NEW CATEGORY FOUND!')
        } else {
            self.vueGlobalProp.$_showMessage(`${count} NEW CATEGORIES CREATED SUCCESSFULLY!`)
        }
        self.setCSSVariableManager();
    },
    toggleExpandVariableCategory: function(e,id){
        e.preventDefault();
        e.stopPropagation();
        const self = this;
        const obj = self.helpers.getGlobalVariableCategoryObjById(id);
        if(!obj) return;

        if(obj.hasOwnProperty('defaultExpanded')){
            delete obj['defaultExpanded'];
        } else {
            obj['defaultExpanded'] = true;
        };

        self.setCSSVariableManager();
        self.refreshVariablePickerList(false);
    },
    toggleExpandColorCategory: function(e,id, type = "color"){
        e.preventDefault();
        e.stopPropagation();
        const self = this;
        const obj = type === "variable" ? self.vueState.globalVariablesCategories.find(el => el.id === id) : self.vueState.colorPalette.find(el => el.id === id);
        if(!obj) return;

        if(obj.hasOwnProperty('defaultExpanded')){
            delete obj['defaultExpanded'];
        } else {
            obj['defaultExpanded'] = true;
        };
        self.refreshVariablePickerList(false);
        
    },
    toggleViewColorCategory: function(e,id,value, type = "color"){
        e.preventDefault();
        e.stopPropagation();
        const self = this;
        const obj = type === "variable" ? self.vueState.globalVariablesCategories.find(el => el.id === id) : self.vueState.colorPalette.find(el => el.id === id);
        if(!obj) return;

        obj['view'] = value;

        self.refreshVariablePickerList(false);
    },
    variableManagerFilterCat: function(event){
        const self = this;
        target = (event.target.dataset.id) ? event.target : event.target.closest('[data-id]');
        if(target.dataset.active === 'true') return;
        self.cssVariablesStates.activeCategory = target.dataset.id;
        self.setCSSVariableManager();
    },
    setDeleteVariable: function(target,newFunction){
        const oldContent = target.innerHTML;
        const oldBalloon = target.dataset.balloon;
        const oldFunction = target.getAttribute('onclick');
        const newContent = '<span class="bricks-svg-wrapper"><i class="fas fa-check"></i></span>';
        const newBalloon = 'Confirm?';

        target.setAttribute("onClick", 'event.stopPropagation();' + newFunction);
        target.setAttribute("data-balloon", newBalloon);
        target.innerHTML = newContent;
        setTimeout(() => {
            target.setAttribute("onClick", oldFunction);
            target.setAttribute("data-balloon", oldBalloon);
            target.innerHTML = oldContent;
        }, 2000)
    },
    setDeleteVariableSingle: function(type, target, id){
        const oldContent = target.innerHTML;
        const oldBalloon = target.dataset.balloon;
        const oldFunction = `ADMINBRXC.setDeleteVariableSingle('${type}', this, '${id}')`;
        const newContent = '<span class="bricks-svg-wrapper"><i class="fas fa-check"></i></span>';
        const newBalloon = 'Confirm?';
        const newFunction = `ADMINBRXC.deleteVariable('${type}', '${id}')`;

        target.setAttribute("onClick", newFunction);
        target.setAttribute("data-balloon", newBalloon);
        target.innerHTML = newContent;
        setTimeout(() => {
            target.setAttribute("onClick", oldFunction);
            target.setAttribute("data-balloon", oldBalloon);
            target.innerHTML = oldContent;
        }, 2000)
    },
    deleteVariableCategory: function(){
        const self = this;
        const arrs = self.helpers.isCSSVariablesTabActive('theme-variables') && self.helpers.themeHasVariables() ? [self.vueState.globalVariables, self.vueState.themeStyleSettings.general._cssVariables] : [self.vueState.globalVariables];
        
        arrs.forEach(arr => {
            const match = arr.filter(el => el && el.hasOwnProperty('category') && el.category === self.cssVariablesStates.activeCategory);
            match.forEach(variable => {
                delete variable.category;
            })
        })

        const indexObj = self.vueState.globalVariablesCategories.find(el => el.id === self.cssVariablesStates.activeCategory);
        const index = self.vueState.globalVariablesCategories.indexOf(indexObj);
        self.vueState.globalVariablesCategories.splice(index, 1);
        self.cssVariablesStates.activeCategory = 'all';

        self.setCSSVariableManager();
    },
    setCSSVariableManagerSearch: function(){
        const self = this;
        const canvas = document.querySelector('#CSSVariableSearchCanvas');
        if(bricksData.disableVariablesManager === "1" || !canvas) return;
        if(self.cssVariablesStates.exportCSS) {
            return canvas.innerHTML = '';
        }

        const arr = self.helpers.isCSSVariablesTabActive('theme-variables') && self.helpers.themeHasVariables() ? self.vueState.globalVariables.concat(self.vueState.themeStyleSettings.general._cssVariables) : self.vueState.globalVariables;
        let vars;

        if(self.cssVariablesStates.activeCategory === 'all'){
            vars = arr;
        } else if(self.cssVariablesStates.activeCategory === 'uncategorized'){
            vars = arr.filter(el => el && self.helpers.isVariableUncategorized(el));
        } else {
            vars = Array.from(arr).filter(el => el && el.hasOwnProperty('category') && el.category === self.cssVariablesStates.activeCategory)
        }
        
        if(self.cssVariablesStates.view === "sidebar" && (!vars || !Array.isArray(vars) || vars.length < 2)) return canvas.innerHTML = '';
        let content = `<div class="brxc-overlay__search-box">
                        <input type="text" class="class-filter" name="class-search" placeholder="Filter by variable name" data-type="title" value="${self.cssVariablesStates.search}" oninput="ADMINBRXC.cssVariablesStates.search = this.value;ADMINBRXC.setCSSVariableManagerBody();">
                        <div class="iso-search-icon">
                            <i class="bricks-svg ti-search"></i>
                        </div>
                        <div class="iso-reset" data-balloon="Reset Filter" data-balloon-pos="bottom-right" onclick="ADMINBRXC.cssVariablesStates.search = '';ADMINBRXC.setCSSVariableManager();">
                            <i class="bricks-svg ti-close"></i>
                        </div>
                      </div>`;
        canvas.innerHTML = content;
    },
    setCSSVariableManagerBody: function() {
        const self = this;
        const canvas = document.querySelector('#CSSVariableBodyCanvas');
        if(!canvas) return;

        // Variable Manager Disabled
        if(bricksData.disableVariablesManager === "1"){
            canvas.innerHTML = `<p class="varable-manager-disabled" data-control="info">The variable manager is actually disabled in the Bricks Settings -> General -> Miscellaneous. Please activate it in order to manage your variables.</p>`;
            return;
        }

        if(self.cssVariablesStates.exportCSS){
            let content = '';
            content = `<div class="brxc-class-manager__content-css">`;

            //Generated CSS
            let globalVariables = self.vueState.globalVariables;
            let cssContent = '';
            if(self.cssVariablesStates.activeCategory === "all"){
                globalVariables.forEach(obj => {
                    cssContent += `--${obj.name}:${obj.value}${obj.value.trim().endsWith(';') ? '' : ';'}`;
                })
            } else if(self.cssVariablesStates.activeCategory === "uncategorized"){
                Array.from(globalVariables).filter(el => el && (!el.category || self.helpers.getGlobalVariableCategoryObjById(el.category) === false)).forEach(obj => {
                    cssContent += `--${obj.name}:${obj.value}${obj.value.trim().endsWith(';') ? '' : ';'}`;
                })
            } else {
                globalVariables = Array.from(globalVariables).filter(el => el && el.hasOwnProperty('category') && el.category === self.cssVariablesStates.activeCategory).forEach(obj => {
                    cssContent += `--${obj.name}:${obj.value}${obj.value.trim().endsWith(';') ? '' : ';'}`;
                })
            }
            
            const finalCSS = css_beautify( `:root{${cssContent}}`, { indent_size: 2 });
            content += `<div class="brxc-codemirror__wrapper"><textarea class="brxc-style-overview-css">${finalCSS}</textarea>`;
            content += `<div class="brxc-overlay__action-btn" style="margin-left: auto" onclick="ADMINBRXC.copytoClipboard(this, this.previousElementSibling.CodeMirror.getValue(), 'Copied!', 'Copy to Clipboard')"><span>Copy to Clipboard</span></div></div>`;
            content += '</div>'
            canvas.innerHTML = content;

            //Generated CSS
            const textarea = canvas.querySelector('textarea.brxc-style-overview-css');
            if(textarea) {
                const dataOptions = { indent_size: 2 }
                const dataObj = textarea.textContent.replaceAll('.brxe-block', '');
                const options = self.codeMirrorOptions(textarea);
                options.autofocus = false;
                const MyCM = CodeMirror.fromTextArea(textarea, self.codeMirrorOptions(options));
                MyCM.getWrapperElement().setAttribute('data-type', 'generated-css');
                MyCM.getWrapperElement().classList.add("disable");
                MyCM.setValue(css_beautify(dataObj, dataOptions));
                MyCM.setOption('readOnly',  true);
                MyCM.setOption('gutters', []);
                
            };
            return;
        }

        function mountScale(id, type = "global"){
            const base = globalVars.find(el => el.scaleId === id && el.base === true);
            if(!base) return;

            const scaleRatios = [
                { value: 1.067, name: "Minor Second" },
                { value: 1.125, name: "Major Second" },
                { value: 1.2, name: "Minor Third" },
                { value: 1.25, name: "Major Third" },
                { value: 1.333, name: "Perfect Fourth" },
                { value: 1.414, name: "Augmented Fourth" },
                { value: 1.5, name: "Perfect Fifth" },
                { value: 1.618, name: "Golden Ratio" },
                { value: 1.667, name: "Major Sixth" },
                { value: 1.778, name: "Minor Seventh" },
                { value: 1.875, name: "Major Seventh" },
                { value: 2, name: "Octave" }
            ];
            const previous = [
                {value: 'size', name: 'Size'},
                {value: 'typography', name: 'Typography'},
                {value: 'borderRadius', name: 'Border-radius'}
            ];
            content = `
                <li data-scale-id="${id}">
                    <div class="variable-wrapper">
                        <div class="handle">
                            <i class="fas fa-grip-vertical"></i>
                        </div>
                        <div class="brxc-scale-wrapper">
                            <div class="brxc-scale-control-wrapper">
                                <div class="brxc-scale-control">
                                    <div class="brxc-scale-control--label">Custom Label</div>
                                    <div class="brxc-scale-control--value">
                                        <input type="text" class="variable-value no-autocomplete" oninput="ADMINBRXC.recalculateBaseVariableScale(event, 'customLabel', '${id}')" value="${base.customLabel || ''}"/>
                                    </div>
                                </div>
                                <div class="brxc-scale-control">
                                    <div class="brxc-scale-control--label">Prefix</div>
                                    <div class="brxc-scale-control--value">
                                        <input type="text" class="variable-value no-autocomplete" oninput="ADMINBRXC.recalculateBaseVariableScale(event, 'label', '${id}')" value="${base.label}"/>
                                    </div>
                                </div>
                                <div class="brxc-scale-control">
                                    <div class="brxc-scale-control--label">Preview</div>
                                    <div class="brxc-scale-control--value">
                                        <div class="brxc-select-new rounded hidden changePreviewVariable" data-id="${id}">
                                            <div class="brxc-select-new__wrapper">
                                                ${previous.map(el => {
                                                    const isActive = base.preview ? el.value === base.preview : el.value === 'size';
                                                    return `<div data-value="${el.value}"${isActive ? ' class="active"' : ''}><span>${el.name}</span></div>`;
                                                }).join('')}
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div class="brxc-scale-control">
                                    <div class="brxc-scale-control--label">Base Min</div>
                                    <div class="brxc-scale-control--value">
                                        <input type="number" min="0.1" step="0.1" class="variable-value no-autocomplete" oninput="ADMINBRXC.recalculateBaseVariableScale(event, 'min', '${id}')" value="${base.min}"/>
                                    </div>
                                </div>
                                <div class="brxc-scale-control">
                                    <div class="brxc-scale-control--label">Type Scale Min</div>
                                    <div class="brxc-scale-control--value">
                                        <div class="brxc-select-new rounded hidden changeTypeScaleVariable" data-id="${id}" data-key="Min">
                                            <div class="brxc-select-new__wrapper">
                                                ${scaleRatios.map(el => {
                                                    const value =  base.scaleTypeMin || base.scaleType;
                                                    return `<div data-value="${el.value}"${el.value === value ?' class="active"' : ''}><span>${el.name}</span></div>`
                                                }).join('')}
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div class="brxc-scale-control">
                                    <div class="brxc-scale-control--label">Base Max</div>
                                    <div class="brxc-scale-control--value">
                                        <input type="number" min="0.1" step="0.1" class="variable-value no-autocomplete" oninput="ADMINBRXC.recalculateBaseVariableScale(event, 'max', '${id}')" value="${base.max}"/>
                                    </div>
                                </div>
                                <div class="brxc-scale-control">
                                    <div class="brxc-scale-control--label">Type Scale Max</div>
                                    <div class="brxc-scale-control--value">
                                        <div class="brxc-select-new rounded hidden changeTypeScaleVariable" data-id="${id}" data-key="">
                                            <div class="brxc-select-new__wrapper">
                                                ${scaleRatios.map(el => 
                                                    `<div data-value="${el.value}"${el.value === base.scaleType ?' class="active"' : ''}><span>${el.name}</span></div>`
                                                ).join('')}
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <ul class="brxc-generated-scale" data-scale-id="${id}" style="--${base.name}: ${base.value};"></ul>
                        </div>
                        <div class="right-actions">
                            <div class="brxc-delete-scale" data-balloon="Delete Scale" data-balloon-pos="left" onclick="ADMINBRXC.deteleScaleVariable(event)"><span class="bricks-svg-wrapper"><i class="ti-trash"></i></span></div>
                        </div>
                    </div>
                </li>
            `;
            return content;
        }

        function mountGroup(id, type = "global"){
            const vars = globalVars.filter(el => el.group === id);
            const base = self.vueState.globalVariables.find(el => el.group === id && el.groupBase === true);
            if(!base) return;

            const controls = vars.map(el => {
                return self.mountVariableControls(el);
            }).join('');

            content = `
                <li data-group-id="${id}">
                    <div class="variable-wrapper">
                        <div class="handle">
                            <i class="fas fa-grip-vertical"></i>
                        </div>
                        <div class="brxc-group-wrapper">
                            <div class="brxc-group-control-wrapper">
                                <div class="brxc-group-control">
                                    <div class="brxc-group-control--label">Group Name</div>
                                    <div class="brxc-group-control--value">
                                        <input type="text" class="variable-value no-autocomplete" oninput="ADMINBRXC.renameBaseVariableGroup(event, 'groupName', '${id}')" value="${base.groupName || ''}"/>
                                    </div>
                                </div>
                            </div>
                            <ul class="brxc-generated-group" data-group-id="${id}">
                                ${controls}
                                <input type="text" class="brxc-add-new-variable" placeholder="Add a new global variable to this group" onkeyup="ADMINBRXC.addVariable('global', event, '${id}');" />
                            </ul>
                        </div>
                        <div class="right-actions">
                            <div class="brxc-delete-group" data-balloon="Remove Group" data-balloon-pos="left" onclick="ADMINBRXC.deteleGroupVariable(event)"><span class="bricks-svg-wrapper"><i class="fas fa-unlink"></i></span></div>
                        </div>
                    </div>
                </li>
            `;
            return content;
        }

        const vars = self.helpers.isCSSVariablesTabActive('theme-variables') && self.helpers.themeHasVariables() ? self.vueState.globalVariables.concat(self.vueState.themeStyleSettings.general._cssVariables) : self.vueState.globalVariables;
        let allVars;
    
        if (self.cssVariablesStates.activeCategory === 'all') {
            allVars = vars;
        } else if (self.cssVariablesStates.activeCategory === 'uncategorized') {
            allVars = vars.filter(el => el && self.helpers.isVariableUncategorized(el));
        } else {
            allVars = vars.filter(el => el && el.hasOwnProperty('category') && el.category === self.cssVariablesStates.activeCategory);
        }
    
        let globalVars = Object.values(self.vueState.globalVariables);
    
        if (self.cssVariablesStates.activeCategory !== 'all') {
            globalVars = globalVars.filter(el => {
                if (self.cssVariablesStates.activeCategory === 'uncategorized') {
                    return self.helpers.isVariableUncategorized(el);
                } else {
                    return el && el.hasOwnProperty('category') && el.category === self.cssVariablesStates.activeCategory;
                }
            });
        }
    
        if (self.cssVariablesStates.search !== '') {
            const search = self.cssVariablesStates.search.toLowerCase();
        
            // Find all scaleIds that match via name
            const matchedScaleIds = new Set(
                globalVars
                    .filter(el => {
                        const label = el?.customLabel?.toLowerCase() ?? "";
                        const name = el?.name?.toLowerCase() ?? "";
                        return label.includes(search) || name.includes(search);
                    })
                    .map(el => el.scaleId)
                    .filter(Boolean)
            );
        
            // Filter globalVars
            globalVars = globalVars.filter(el =>
                el &&
                (
                    el.label?.toLowerCase().includes(search) ||
                    el.customLabel?.toLowerCase().includes(search) ||
                    el.name?.toLowerCase().includes(search) ||
                    (el.scaleId && matchedScaleIds.has(el.scaleId))
                )
            );
        }
    
        let content = '';
        const isGlobalVisible = self.cssVariablesStates.showGlobal === true;
        const hasMultipleVars = allVars.length > 1;
        const hasGlobalVars = globalVars.length > 0;

        const excludeKeys = ['_typography','_css', '_classes', '_generated-code', '_attributes'];
        const cssCategories = [{key: 'content', title: 'Content'}, {key: '_grid', title: 'Grids'}, {key: '_gap', title: 'Gap'}, {key: '_spacing', title: 'Spacing'}, {key: '_typography', title: 'Typography'},
            ...new Map(
                Object.values(bricksData.elements)
                    .map(el => el.controlGroups)
                    .flatMap(el => el) 
                    .flatMap(obj => Object.entries(obj))
                    .filter(([key, value]) => 
                        value.tab === "style" && 
                        !excludeKeys.some(exclude => key.includes(exclude))
                    )
                    .map(([key, value]) => [key, { key, title: value.title }])
            ).values()
        ];

        const activeCategory = self.vueState.globalVariablesCategories.find(el => el.id === self.cssVariablesStates.activeCategory);

        // Header
        content += `
        <div class="variable-heading${hasMultipleVars ? ' sticky' : ''} global">
            <label class="has-tooltip">
            <span class="title${isGlobalVisible ? '' : ' inactive'}">
                Global Variables (${globalVars.length})
            </span>
            <div 
                data-balloon="The global variables apply on all your website. They have lower specificity compared to theme-specific variables."
                data-balloon-pos="bottom"
                data-balloon-length="large">
                <i class="fas fa-circle-question"></i>
            </div>
            <span class="brxc-add-new-scale" onClick="ADMINBRXC.addNewVariableScale('global');">+ New Scale</span>
            </label>
            <div class="action">
            ${!['all','uncategorized'].includes(self.cssVariablesStates.activeCategory) ? `
            <div class="brxc-select-new rounded hidden" id="brxcContextualCategorySelect">
                <div class="brxc-select-new__wrapper">
                    <div data-value="none" ${!activeCategory.hasOwnProperty('cssCategory') ? ' class="active"' : ''}><span>--- Choose a Category ---</span></div>
                     ${cssCategories.map(el => `<div data-value="${el.key}"${activeCategory && activeCategory.hasOwnProperty('cssCategory') && activeCategory.cssCategory === el.key ? ' class="active"' : ''}><span>${el.title}</span></div>`).join('')}
                </div>
            </div>` 
            : ''}
            <div 
                class="brxc-icon" 
                data-balloon="${isGlobalVisible ? 'Hide' : 'Show'} Global Variables" 
                data-balloon-pos="left" 
                onclick="ADMINBRXC.toggleGlobalVars('global')">
                <span class="bricks-svg-wrapper">
                <i class="fas fa-eye${isGlobalVisible ? '' : '-slash'}"></i>
                </span>
            </div>
            </div>
        </div>
        `;

        // Variable List
        if (hasGlobalVars && isGlobalVisible) {
            content += '<ul class="brxc-global-variable-list">';

            if (!['all','uncategorized'].includes(self.cssVariablesStates.activeCategory) && activeCategory.hasOwnProperty('description')){
                content += `<div data-control="info">${activeCategory.description}</div>`;
            }
            
            const scales = [];
            const groups = [];
            globalVars.forEach(el => {
                // Scales
                const scaleId = el?.scaleId || '';
                if(scales.includes(scaleId)) return;
                if(scaleId !== '') {
                    scales.push(scaleId);
                    return content += mountScale(scaleId);
                };

                // Groups
                const group = el?.group ?? false;
                if(groups.includes(group)) return;
                if(group && !groups.includes(group)){
                    groups.push(group)
                    return content += mountGroup(group);
                }

                // Single Controls
                content += self.mountVariableControls(el);
            });
            
            content += '</ul>';
        } else if (isGlobalVisible) {
            content += `<p class="brxc-variable__category-empty" data-control="info">No global variable found in this category.</p>`;
        }
        
    
        // Add new variable
        if(isGlobalVisible){
            content += `<div class="brxc-add-color-wrapper">`;
            content += `<div class="brxc-import-css-colors${self.cssVariablesStates.importGlobalVariables === true ? ' active' : ''}" data-balloon="Import CSS variables" data-balloon-pos="bottom-left" onclick="ADMINBRXC.toggleImportVariables('global','${self.cssVariablesStates.importGlobalVariables === true ? 'true' : 'false'}');"><i class="fas fa-code"></i></div> `;
            content += self.cssVariablesStates.importGlobalVariables === true ? `<textarea id="addNewGlobalVariableCSS" rows="20" placeholder="Paste your CSS variables here"></textarea>` : `<input type="text" id="addNewVariable" class="brxc-add-new-variable" placeholder="Add a new global variable" onkeyup="ADMINBRXC.addVariable('global', event);" />`;
            content += `</div>`;
            if (self.cssVariablesStates.importGlobalVariables === true) {
                content += `<div id="brxcImportVariableWrapper">
                                <div class="gridUI__input-wrapper">
                                    <label class="has-tooltip">
                                        <span>Skip values?</span>
                                        <div data-balloon="Toggle this option if you're importing variables that are defined elsewhere, but want them selectable inside the Variable Picker." data-balloon-pos="top" data-balloon-length="medium">
                                            <i class="fas fa-circle-question"></i>
                                        </div>
                                    </label>
                                    <i class="fas fa-toggle-${self.cssVariablesStates.skipValues === true ? 'on' : 'off'}" onClick="ADMINBRXC.cssVariablesStates.skipValues = !ADMINBRXC.cssVariablesStates.skipValues;ADMINBRXC.setCSSVariableManagerBody();"></i>
                                </div>
                                <a class="brxc-overlay__action-btn primary" onclick="ADMINBRXC.importVariables('global');"><span>Import Variables</span></a>
                            </div>`;
            }
        }
        
    
        if (!self.helpers.isCSSVariablesTabActive('theme-variables')) {
            return canvas.innerHTML = content;
        }
    
        // Theme Variables
        if(self.helpers.isThemeVariableActive()){
            if (self.helpers.themeHasVariables() && self.cssVariablesStates.activeCategory) {
                let tempVarsTheme;
                if (self.cssVariablesStates.activeCategory === 'all') {
                    tempVarsTheme = self.vueState.themeStyleSettings.general._cssVariables;
                } else if (self.cssVariablesStates.activeCategory === 'uncategorized') {
                    tempVarsTheme = Array.from(self.vueState.themeStyleSettings.general._cssVariables).filter(el => el && self.helpers.isVariableUncategorized(el));
                } else {
                    tempVarsTheme = Array.from(self.vueState.themeStyleSettings.general._cssVariables).filter(el => el && el.hasOwnProperty('category') && el.category === self.cssVariablesStates.activeCategory);
                }
        
                let themeVars = Object.values(tempVarsTheme);
        
                if (self.cssVariablesStates.search !== '') {
                    themeVars = themeVars.filter(el => el && el.hasOwnProperty('name') && el.name.includes(self.cssVariablesStates.search));
                }
        
                content += `<div class="variable-heading${allVars.length > 1 ? ' sticky' : ''} theme"><label class="has-tooltip"><span class="title${self.cssVariablesStates.showTheme !== true ? ' inactive' : ''}">Theme Variables (${themeVars.length})</span><div data-balloon="The theme variables only apply on posts/pages where the specific theme style is active. They have higher specificity than global variables." data-balloon-pos="bottom" data-balloon-length="large"><i class="fas fa-circle-question"></i></div></label>`;
                content += `<div class="action">`;
                content += `<div class="brxc-icon" data-balloon="${self.cssVariablesStates.showTheme === true ? 'Hide' : 'Show'} Theme Variables" data-balloon-pos="left" onclick="ADMINBRXC.toggleGlobalVars('theme')"><span class="bricks-svg-wrapper"><i class="fas fa-eye${self.cssVariablesStates.showTheme !== true ? '-slash' : ''}"></i></span></div>`;
                content += '</div></div>';
                if (themeVars.length > 0 && self.cssVariablesStates.showTheme === true) {
                    content += '<ul class="brxc-theme-variable-list" data-type="theme">';
                    themeVars.forEach(el => {
                        content += `<li data-id="${el.hasOwnProperty('id') ? el.id : ''}" class=""><div class="variable-wrapper">`;
                        content += themeVars.length > 1 && self.cssVariablesStates.activeCategory === 'all' ? `<div class="handle"><i class="fas fa-grip-vertical"></i></div>` : '';
                        content += `<div class="variable-inner-wrapper">`;
                        content += `<button class="variable-type-switch ${el.hasOwnProperty('type') && el.type === "clamp" ? 'clamp' : 'static'}" data-type="theme" data-id="${el?.id ?? ''}">${el.hasOwnProperty('type') ? el.type.slice(0, 2) : 'ST'}${self.helpers.isVarActiveOnPage(`var(--${self.helpers.formatForClasses(el.name)})`) ? `<div class="btn-color-check" data-balloon="active on the page" data-balloon-pos="right"><i class="fas fa-check"></i></i></div>` : ''}</button>`;
                        content += `<span class="variable-prefix">--</span>`;
                        content += `<input type="text" class="variable-name" data-original="${el && el.hasOwnProperty('name') ? el.name : ''}" value="${el && el.hasOwnProperty('name') ? el.name : ''}" onkeyup="ADMINBRXC.renameVariable('theme', event)" onblur="this.value = this.dataset.original"/>`;
                        content += el.hasOwnProperty('type') && el.type === "clamp" ? `<div class="input-container"><div class="input-wrapper"><input type="number" class="variable-min" value="${el && el.hasOwnProperty('min') ? el.min : ''}" oninput="ADMINBRXC.setVariableClamp('theme', event,'min');" /><span class="variable-unit">px</span> </div><div class="input-wrapper"><input type="number" class="variable-max" value="${el && el.hasOwnProperty('max') ? el.max : ''}" oninput="ADMINBRXC.setVariableClamp('theme', event,'max');" /><span class="variable-unit">px</span> </div></div>` : `<input type="text" class="variable-value" value="${el && el.hasOwnProperty('value') ? el.value : ''}" oninput="ADMINBRXC.setVariableValue('theme', event,'value');" />`;
                        content += `</div>`;
                        content += `<div class="right-actions">`;
                        content += `<div class="duplicate-variable" data-balloon="Duplicate Variable" data-balloon-pos="left" onClick="ADMINBRXC.duplicateVariable('theme', '${el.hasOwnProperty("id") ? el.id : false}');"><span class="bricks-svg-wrapper"><i class="fas fa-clone"></i></span></div>`;
                        content += `<div class="delete-variable" data-balloon="Delete Variable" data-balloon-pos="left" onClick="ADMINBRXC.setDeleteVariableSingle('theme', this, '${el.hasOwnProperty("id") ? el.id : false}');"><span class="bricks-svg-wrapper"><i class="ti-trash"></i></span></div>`;
                        content += `</div></div>`;
                        content += `</li>`;
                    });
                    content += '</ul>';
                } else if (self.cssVariablesStates.showTheme === true) {
                    content += `<p class="brxc-variable__category-empty" data-control="info">No theme variable found in this category.</p>`
                }
            } else {
                content += `<div class="variable-heading theme"><label class="has-tooltip"><span class="title${self.cssVariablesStates.showTheme !== true ? ' inactive' : ''}">Theme Variables (0)</span><div data-balloon="The theme variables only apply on posts/pages where the specific theme style is active. They have higher specificity than global variables." data-balloon-pos="bottom" data-balloon-length="large"><i class="fas fa-circle-question"></i></div></label>`;
                content += `<div class="action">`;
                content += `<div class="brxc-icon" data-balloon="${self.cssVariablesStates.showTheme === true ? 'Hide' : 'Show'} Theme Variables" data-balloon-pos="left" onclick="ADMINBRXC.toggleGlobalVars('theme')"><span class="bricks-svg-wrapper"><i class="fas fa-eye${self.cssVariablesStates.showTheme !== true ? '-slash' : ''}"></i></span></div>`;
                content += '</div></div>';
                content += `<p class="brxc-variable__category-empty" data-control="info">No theme variable found in this category.</p>`;
            }
        
            // Add new variable
            if(self.cssVariablesStates.showTheme === true){
                content += `<div class="brxc-add-color-wrapper">`;
                content += `<div class="brxc-import-css-colors${self.cssVariablesStates.importThemeVariables === true ? ' active' : ''}" data-balloon="Import CSS variables" data-balloon-pos="bottom-left" onclick="ADMINBRXC.toggleImportVariables('theme', '${self.cssVariablesStates.importThemeVariables === true ? 'true' : 'false'}');"><i class="fas fa-code"></i></div> `;
                content += self.cssVariablesStates.importThemeVariables === true ? `<textarea id="addNewThemeVariableCSS" rows="20" placeholder="Paste your CSS variables here"></textarea>` : `<input type="text" id="addNewThemeVariable" class="brxc-add-new-variable" placeholder="Add a new theme variable" onkeyup="ADMINBRXC.addVariable('theme', event);" />`;
                content += `</div>`;
                if (self.cssVariablesStates.importThemeVariables === true) {
                    content += `<div id="brxcImportVariableWrapper">
                                    <div class="gridUI__input-wrapper">
                                        <label class="has-tooltip">
                                            <span>Skip values?</span>
                                            <div data-balloon="Toggle this option if you're importing variables that are defined elsewhere, but want them selectable inside the Variable Picker." data-balloon-pos="top" data-balloon-length="medium">
                                                <i class="fas fa-circle-question"></i>
                                            </div>
                                        </label>
                                        <i class="fas fa-toggle-${self.cssVariablesStates.skipValues === true ? 'on' : 'off'}" onClick="ADMINBRXC.cssVariablesStates.skipValues = !ADMINBRXC.cssVariablesStates.skipValues;ADMINBRXC.setCSSVariableManagerBody();"></i>
                                    </div>
                                    <a class="brxc-overlay__action-btn primary" onclick="ADMINBRXC.importVariables('theme');"><span>Import Variables</span></a>
                                </div>`;
                }
            }
        }
        
    
        canvas.innerHTML = content;

        // Select Contextual Category
        const contextualSelect = canvas.querySelector('#brxcContextualCategorySelect');
        self.helpers.selectControl(contextualSelect, (target) => {
            self.changeCSSCategoryVariableManager(target.dataset.value)
        })

        // Select Type Scale
        const typeScales = canvas.querySelectorAll('.changeTypeScaleVariable');
        typeScales.forEach(select => {
            self.helpers.selectControl(select, (target) => {
                const scaleId = select.dataset.id;
                const key = select.dataset.key;
                self.changeTypeScaleVariable(parseFloat(target.dataset.value), scaleId, key);
            });
        });

        const changePreviews = canvas.querySelectorAll('.changePreviewVariable');
        changePreviews.forEach(select => {
            self.helpers.selectControl(select, (target) => {
                const scaleId = select.dataset.id;
                self.changePreviewVariable(target.dataset.value, scaleId);
            });
        });

        const scalePreviews = canvas.querySelectorAll('.brxc-generated-scale');
        if(scalePreviews.length > 0){
            scalePreviews.forEach(el => {
                self.mountVariableScalePreview(el.dataset.scaleId, 'global');
           })
        }

        //Mount computed color
        const colorBtns = canvas.querySelectorAll('.brxc-variable-color__preview');
        colorBtns.forEach(el => {
            el.dataset.initialColor = window.getComputedStyle(el).backgroundColor;
        })
    
        //Listeners

        const toggleButtons = canvas.querySelectorAll('.variable-type-switch');

        toggleButtons.forEach(toggle => {
            toggle.addEventListener('click', (e) => {
                const wrapper = e.target.closest('.variable-inner-button-wrapper');
                const type = toggle.dataset.type;
                const id = toggle.dataset.id;

                // Prevent creating duplicate modals
                const existing = canvas.querySelector('.brxc-variable-switch__modal');
                if (existing) return existing.remove();

                const modal = document.createElement('DIV');
                modal.setAttribute("class", "brxc-variable-switch__modal");
                modal.innerHTML = `
                <div class="brxc-variable-switch__wrapper">
                    <div class="brxc-variable-switch__item" data-value="static">Static</div>
                    <div class="brxc-variable-switch__item" data-value="clamp">Clamp</div>
                    <div class="brxc-variable-switch__item" data-value="color">Color</div>
                </div>`;
                wrapper.appendChild(modal);

                const outsideClickListener = () => {
                    if(modal) modal.remove();
                    window.removeEventListener('click', outsideClickListener);
                    
                };

                setTimeout(() => {
                    // Listeners
                    const buttons = wrapper.querySelectorAll('.brxc-variable-switch__item');
                    buttons.forEach(btn => {
                        btn.addEventListener('click', () => {
                            const value = btn.dataset.value;
                            self.toggleTypeSwitch(type, id, value);
                        })
                    })
                    window.addEventListener('click', outsideClickListener);
                }, 0);
            });
        });

        const colorPreviewButtons = canvas.querySelectorAll('.brxc-variable-color__preview');

        colorPreviewButtons.forEach(btn => {

            let picker = new ColorPicker(btn, btn.dataset.initialColor);
    
            btn.addEventListener('colorChange', (event) => {
                const input = event.target.nextElementSibling;
                const color = event.detail.color[colorPickerComp.colorTypeStatus.toLowerCase()]
                input.value = color;
                input.dispatchEvent(new Event('input'));
            })
            
        });
    
        const variableWrappers = canvas.querySelectorAll('ul.brxc-theme-variable-list, ul.brxc-global-variable-list');
        if (variableWrappers.length < 1) return;
    
        variableWrappers.forEach(variableWrapper => {
            const inputs = variableWrapper.querySelectorAll('input.variable-value:not(.no-autocomplete)');
            if (inputs && inputs.length > 0) {
                inputs.forEach(input => {
                    // auto-complete
                    if (Object.values(self.globalSettings.classFeatures).includes("autocomplete-variable")) {
                        input.addEventListener('focus', () => {
                            self.autocomplete(input, self.cssVariables, "style");
                        });
                    }
    
                    //autoformat
                    if (Object.values(self.globalSettings.classFeatures).includes("autoformat-field-values")) {
                        input.addEventListener('blur', () => {
                            self.autoformat(input, "custom");
                            input.dispatchEvent(new Event('input'));
                        });
                    }
                });
            }

            // Add Group
            const addGroups = canvas.querySelectorAll('.variable-add-group');
            addGroups.forEach(addGroup => {
                addGroup.addEventListener('click', () => {
                    const variableId = addGroup.closest('li[data-id]')?.dataset.id;
                    const variable = self.helpers.getGlobalVariableObjById(variableId);

                    variable.group = self.vueGlobalProp.$_generateId();
                    variable.groupName = "My Group";
                    variable.groupBase = true;

                    self.setCSSVariableManager();
                })
            })

            //Drag and drop
            const rows = variableWrapper.querySelectorAll('li .handle');
            if (!rows || rows.length < 1) return;
            
            const setDragginItems = (evt) => {
                const extractItem = (el) => {
                    const { id, scaleId, groupId } = el.dataset;
                    let type = "var";
            
                    switch (true) {
                        case !!scaleId:
                            type = "scale";
                            break;
                        case !!groupId:
                            type = "group";
                            break;
                    }
            
                    return {
                        id: scaleId ?? groupId ?? id,
                        type
                    };
                };
            
                const items = evt.items.length > 0 ? evt.items : [evt.item];
                self.cssVariablesStates.onDrag = items.map(extractItem);
            };
            const reorderItems = (variableWrapper) => {
                const isTheme = variableWrapper.dataset.type === "theme";
                const vars = isTheme
                    ? self.vueState.themeStyleSettings.general._cssVariables
                    : self.vueState.globalVariables;

                const items = variableWrapper.querySelectorAll('li[data-id]');

                items.forEach((item, index) => {
                    const { id, scaleId } = item.dataset;

                    const target = vars.find(el =>
                        el?.id === id || (el?.base === true && el?.scaleId === scaleId)
                    );

                    if (target) {
                        self.helpers.moveArr(vars, vars.indexOf(target), index);
                    }
                });

                self.setCSSVariableManager();
            }
            new Sortable(variableWrapper, {
                group: 'variables',
                multiDrag: true,
                fallbackOnBody: true,
                swapThreshold: 0.65,
                multiDrag: true,
                selectedClass: "sortable-selected",
                animation: 150,
                handle: "li .handle",
                helper: 'clone',
                onStart: function (evt) {
                    setDragginItems(evt)
                },
                onEnd: (evt) => {
                    if(evt.to.classList.contains('brxc-generated-group')){
                        const groupId = evt.to.closest('li[data-group-id]')?.dataset.groupId;
                        self.cssVariablesStates.onDrag.forEach(el => {
                            const obj = self.helpers.getGlobalVariableObjById(el.id);
                            if(!obj) return;

                            delete obj.groupName;
                            delete obj.groupeBase;
                            obj.group = groupId
                        })
                    } 

                    reorderItems(variableWrapper);
                },
            });

            // Then initialize Sortable for nested containers
            variableWrapper.querySelectorAll('.brxc-generated-group').forEach(group => {
                new Sortable(group, {
                    group: 'variables',
                    multiDrag: true,
                    animation: 150,
                    selectedClass: "sortable-selected",
                    handle: "li .handle",
                    fallbackOnBody: true,
                    onStart: function (evt) {
                        setDragginItems(evt)
                    },
                    onEnd: (evt) => {
                        const draggedItems = self.cssVariablesStates.onDrag;
                        draggedItems.forEach(el => {
                            const obj = self.helpers.getGlobalVariableObjById(el.id);
                            if(!obj) return;

                            // Move the groupBase
                            if(obj.groupBase){
                                const allGroupVars = vars.filter(el => el.group === obj.group && el.id !== obj.id);
                                if(allGroupVars.length > 0){
                                    const newBase = allGroupVars[0];
                                    newBase.groupBase = true;
                                    newBase.groupName = obj.groupName;
                                }
                            }

                            // Moving element outside of the group
                            if(!evt.to.classList.contains('brxc-generated-group')){
                                if(obj.groupBase){
                                    const allGroupVars = self.vueState.globalVariables.filter(el2 => el2.group === obj.group && el2.id !== obj.id);
                                    if(allGroupVars.length > 0){
                                        const newBase = allGroupVars[0];
                                        newBase.groupBase = true;
                                        newBase.groupName = obj.groupName;
                                    }
                                }

                                delete obj.group;

                            // Moving inside another group
                            } else {
                                const groupId = evt.to.closest('li[data-group-id]')?.dataset.groupId;
                                obj.group = groupId
                            }

                            delete obj.groupBase;
                            delete obj.groupName;
                        })

                        reorderItems(variableWrapper);
                    }
                });
            });
 
        });
    },
    mountVariableControls: function(el){
        const self = this;

        function mountClampVariable(min, max, type){
            return `<div class="input-container">
                        <div class="input-wrapper">
                            <div class="variable-value__svg" data-balloon="Min Value" data-balloon-pos="right">${self.helpers.bpIcons("phone-portrait")}</div>
                            <input type="number" class="variable-min" value="${min}" oninput="ADMINBRXC.setVariableClamp('${type}', event, 'min');" onkeyup="ADMINBRXC.setVariableClamp('${type}', event, 'min');" />
                            <span class="variable-unit">px</span>
                        </div>
                        <div class="input-wrapper">
                            <div class="variable-value__svg" data-balloon="Max Value" data-balloon-pos="right">${self.helpers.bpIcons()}</div>
                            <input type="number" class="variable-max" value="${max}" oninput="ADMINBRXC.setVariableClamp('${type}', event, 'max');" onkeyup="ADMINBRXC.setVariableClamp('${type}', event, 'max');" />
                            <span class="variable-unit">px</span>
                        </div>
                    </div>`
        }
        
        function escapeHtml(str) {
            return String(str)
                .replace(/&/g, "&amp;")
                .replace(/"/g, "&quot;")
                .replace(/</g, "&lt;")
                .replace(/>/g, "&gt;");
        }
        
        function mountStaticVariable(value, type) {
            return `<input type="text" class="variable-value" value="${escapeHtml(value)}" placeholder="Type an associated value here." oninput="ADMINBRXC.setVariableValue('${type}', event, 'value');" />`;
        }
        function mountColorVariable(value, type){
            return `<div class="brxc-variable-color-wrapper">
                        <div class="brxc-variable-color__preview" data-initial-color="${value}" style="background-color:${value};"></div>
                        <input type="text" class="variable-value" value="${value}" placeholder="Type an valid color code here." oninput="ADMINBRXC.setVariableValue('${type}', event, 'value', true);" />
                    </div>`
        }

        const id = el?.id ?? '';
        const type = el?.type ?? 'static';
        const name = el?.name ?? '';
        const label = el?.label ?? '';
        const min = el?.min ?? '';
        const max = el?.max ?? '';
        const value = el?.value ?? '';
        const isGroup = el?.group ?? false; 
        const isClamp = type === "clamp";
        const isColor = type === "color";
        const isStatic = type !== "clamp" && type !== "color";
        const isActive = self.helpers.isVarActiveOnPage(`var(--${self.helpers.formatForClasses(name)})`);

        return `
        <li data-id="${id}" class="">
            <div class="variable-wrapper">
            <div class="handle">
                <i class="fas fa-grip-vertical"></i>
            </div>
            <div class="variable-inner-wrapper">
                <div class="variable-inner-button-wrapper">
                    <button 
                    class="variable-type-switch ${type}"
                    data-type="global"
                    data-id="${id}">
                    ${type.slice(0, 2)}
                    ${isActive ? '<div class="btn-color-check" data-balloon="active on the page" data-balloon-pos="right"><i class="fas fa-check"></i></div>' : ''}
                    </button>
                </div>
                <span class="variable-prefix">--</span>
                <input 
                    type="text" 
                    class="variable-name" 
                    data-original="${name}" 
                    value="${name}" 
                    onkeyup="ADMINBRXC.renameVariable('global', event)" 
                    onblur="this.value = this.dataset.original"
                />
                <input 
                    type="text" 
                    class="variable-label" 
                    value="${label}"
                    placeholder="Type a custom label here."
                    onkeyup="ADMINBRXC.relabelVariable('global', event)" 
                />
                ${isColor ? mountColorVariable(value, type) : ''}
                ${isClamp ? mountClampVariable(min,max,'global') : ''}
                ${isStatic ? mountStaticVariable(value, type) : ''}
                ${!isGroup 
                    ? `<div class="variable-add-group" data-balloon="Create a New Group" data-balloon-pos="left">
                            <i class="fas fa-plus"></i>
                        </div>` : ''}
            </div>
            <div class="right-actions">
                <div class="duplicate-variable" data-balloon="Duplicate Variable" data-balloon-pos="left" onClick="ADMINBRXC.duplicateVariable('global', '${id || false}');">
                <span class="bricks-svg-wrapper"><i class="fas fa-clone"></i></span>
                </div>
                <div class="delete-variable" data-balloon="Delete Variable" data-balloon-pos="left" onClick="ADMINBRXC.setDeleteVariableSingle('global', this, '${id || false}');">
                <span class="bricks-svg-wrapper"><i class="ti-trash"></i></span>
                </div>
            </div>
            </div>
        </li>`;
    },
    changeCSSCategoryVariableManager: function(value){
        const self = this;
        const categoryId = self.cssVariablesStates.activeCategory;
        const category = self.vueState.globalVariablesCategories.find(el => el.id === categoryId);
        if(!category) return;
        value === "none" ? delete category.cssCategory : category.cssCategory = value;
    },
    toggleGlobalVars: function(type){
        const self = this;
        if(type === 'theme'){
            self.cssVariablesStates.showTheme === true ? self.cssVariablesStates.showTheme = false : self.cssVariablesStates.showTheme = true;
        } else {
            self.cssVariablesStates.showGlobal === true ? self.cssVariablesStates.showGlobal = false : self.cssVariablesStates.showGlobal = true;
        }
        self.setCSSVariableManager();
    },
    variableScaleSuffixs: [
        {suffix: '8xl', step: 10, multiplier: 16},
        {suffix: '7xl', step: 9, multiplier: 14},
        {suffix: '6xl', step: 8, multiplier: 12},
        {suffix: '5xl', step: 7, multiplier: 10},
        {suffix: '4xl', step: 6, multiplier: 8},
        {suffix: '3xl', step: 5, multiplier: 6},
        {suffix: '2xl', step: 4, multiplier: 4},
        {suffix: 'xl', step: 3, multiplier: 3},
        {suffix: 'l', step: 2, multiplier: 2},
        {suffix: 'm', step: 1, multiplier: 1.5},
        {suffix: 's', step: 0, multiplier: 1},
        {suffix: 'xs', step: -1, multiplier: 0.75},
        {suffix: '2xs', step: -2, multiplier: 0.5},
        {suffix: '3xs', step: -3, multiplier: 0.25},
        {suffix: '4xs', step: -4, multiplier: 0.20},
        {suffix: '5xs', step: -5, multiplier: 0.15},
    ],
    addNewVariableScale: function(type){
        const self = this;
        // Regenerate CSS

        let vars;

        if(type === "theme") {
            self.helpers.createThemeVariable();
            vars = self.vueState.themeStyleSettings.general._cssVariables;
        } else {
            vars = self.vueState.globalVariables;
        };

        const scaleId = self.vueGlobalProp.$_generateId();
        const start = self.variableScaleSuffixs.findIndex(el => el.suffix === '3xl');
        const end = self.variableScaleSuffixs.findIndex(el => el.suffix === '3xs');
        const suffixs = self.variableScaleSuffixs.slice(start, end + 1);
        suffixs.forEach((obj, index) => {
            let newObj;
            if(obj.suffix === 's'){
                newObj = {
                    id: self.vueGlobalProp.$_generateId(),
                    scaleId: scaleId,
                    label: "scale",
                    suffix: obj.suffix,
                    name: `scale-${obj.suffix}`,
                    customLabel: "My New Scale",
                    step: 0,
                    smallSteps: 3,
                    largeSteps: 6,
                    multiplier: obj.multiplier,
                    multiplierMin: obj.multiplier,
                    type: 'scale',
                    scaleType: 1.25,
                    scaleTypeMin: 1.25,
                    value: self.helpers.clampBuilder(18, 20),
                    base: true,
                    min: 18,
                    max: 20,
                    preview: 'size',
                }
            } else {
                const multiplier = parseFloat(Math.pow(1.25, obj.step).toFixed(3))
                newObj = {
                    id: self.vueGlobalProp.$_generateId(),
                    scaleId: scaleId,
                    suffix: obj.suffix,
                    name: `scale-${obj.suffix}`,
                    step: obj.step,
                    multiplier: multiplier,
                    multiplierMin: multiplier,
                    value: `calc(var(--scale-s) * ${multiplier})`,
                    type: 'scale',
                }
            }
            if(!['all', 'uncategorized'].includes(self.cssVariablesStates.activeCategory)) newObj.category = self.cssVariablesStates.activeCategory;
            vars.unshift(newObj)
        })
        if(type === "theme"){
            self.generateVariableCSS('theme');
            self.generateBuilderCSS();  
        }
        self.setCSSVariableManager();
    },
    deteleScaleVariable: function(event){
        const self = this;
        const scaleEl = event.target.closest('[data-scale-id]');
        if(!scaleEl) return;

        const scaleId = scaleEl.dataset.scaleId;
        const scaleElements = self.vueState.globalVariables.filter(el => el.scaleId === scaleId);
        scaleElements.forEach(el => {
            const index = self.vueState.globalVariables.indexOf(el);
            if (index !== -1) self.vueState.globalVariables.splice(index, 1);
        })

        self.setCSSVariableManager();
    },
    deteleGroupVariable: function(event){
        const self = this;
        const groupEl = event.target.closest('[data-group-id]');
        if(!groupEl) return;

        const groupId = groupEl.dataset.groupId;
        const groupElements = self.vueState.globalVariables.filter(el => el.group === groupId);
        groupElements.forEach(el => {
            delete el.group;
            delete el.groupName;
            delete el.groupBase
        })

        self.setCSSVariableManager();
    },
    mountVariableScalePreview: function(id, type = "global"){
        const self = this;
        const canvas = document.querySelector(`.brxc-generated-scale[data-scale-id="${id}"]`);
        if (!canvas) return;

        const vars = self.helpers.isCSSVariablesTabActive('theme-variables') && self.helpers.themeHasVariables()
            ? self.vueState.globalVariables.concat(self.vueState.themeStyleSettings.general._cssVariables)
            : self.vueState.globalVariables;
        
        const scaleElements = vars.filter(el => el.scaleId === id);

        scaleElements.sort((a, b) => a.step - b.step);

        const base = scaleElements.find(el => el.base === true);
        let content = "";
        content += `<div class="brxc-generated-scale__controls" data-key="smallSteps">
                        <i class="fas fa-minus" data-action="remove"></i>
                        <i class="fas fa-plus" data-action="add"></i>
                    </div>`
        scaleElements.forEach(el => {
            content += `
                <li data-id="${el.id}"${el.base === true ? ` class="brxc-scale--base"`: ''}>
                    <div class="variable-wrapper-scale">
                        <div class="variable-inner-wrapper">
                            <div class="brxc-base-input-wrapper"><div class="brxc-base-input${el.base === true ? ' active' : ''}"${el.base !== true ? ` onclick="ADMINBRXC.setNewBaseVariable('${el.id}', '${id}', ${el.step})"` : ''}></div></div>
                            <span class="variable-prefix">--</span>
                            <input type="text" class="variable-name" value="${el.name}" data-original="${el.name}" onkeyup="ADMINBRXC.renameVariable('global', event)" onblur="this.value = this.dataset.original" />
                            <div class="variable-modifier__container">
                                <input type="number" min="0" step="0.1" class="variable-modifier" value="${el.multiplierMin ? el.multiplierMin : el.multiplier}"${el.base === true ? ' readOnly' : ''} oninput="ADMINBRXC.setVariableMultiplier('${type}', event, '${id}', 'Min');"/>
                                <input type="number" min="0" step="0.1" class="variable-modifier" value="${el.multiplier}"${el.base === true ? ' readOnly' : ''} oninput="ADMINBRXC.setVariableMultiplier('${type}', event, '${id}', '');"/>
                            </div>
                            <div class="variable-value">
                                ${self.mountScalePreview(base, el)}
                            </div>
                        </div>
                    </div>
                </li>`

        })
        content += `<div class="brxc-generated-scale__controls" data-key="largeSteps">
                        <i class="fas fa-minus" data-action="remove"></i>
                        <i class="fas fa-plus" data-action="add"></i>
                    </div>`
        canvas.innerHTML = content;
        
        // listeners
        const controls = canvas.querySelectorAll('.brxc-generated-scale__controls');
        controls.forEach(control => {
            const key = control.dataset.key;
            const icons = control.querySelectorAll('i');
            icons.forEach(icon => {
                icon.addEventListener('click', () => {
                    const action = icon.dataset.action;
                    self.recalculateStepsVariableScale(key, id, action)
                })
            })
        })
    },
    mountScalePreview: function(base, el){
        const self = this;
        const hasTwoScaleTypes = base.scaleTypeMin && base.scaleType !== base.scaleTypeMin;
        const fontSizeMin = `${parseFloat((base.min * (hasTwoScaleTypes ? el.multiplierMin ?? 1 : el.multiplier ?? 1)).toFixed(3)).toString()}px`;
        const fontSize = `${parseFloat((base.max * el.multiplier).toFixed(3)).toString()}px`;
        let mount;
        switch(base.preview){
            case "typography":
                mount = `<div class="variable-value__container">
                            <div class="variable-value__svg" data-balloon="${fontSizeMin}" data-balloon-pos="right">${self.helpers.bpIcons("phone-portrait")}</div>
                            <span class="preview-typgragraphy-scale" style="font-size:${fontSizeMin};">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</span>
                        </div>
                        <div class="variable-value__container">
                            <div class="variable-value__svg" data-balloon="${fontSize}" data-balloon-pos="right">${self.helpers.bpIcons()}</div>
                            <span class="preview-typgragraphy-scale" style="font-size:${fontSize};">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</span>
                        </div>`;
                break;
            case "borderRadius":
                mount = `<div class="variable-value__container">
                            <div class="variable-value__svg" data-balloon="${fontSizeMin}" data-balloon-pos="right">${self.helpers.bpIcons("phone-portrait")}</div>
                            <div class="variable-value__border" style="border-radius:${fontSizeMin};"></div>
                            <span class="variable-value__sizer-label">${fontSizeMin}</span>
                        </div>
                        <div class="variable-value__container">
                            <div class="variable-value__svg" data-balloon="${fontSize}" data-balloon-pos="right">${self.helpers.bpIcons()}</div>
                            <div class="variable-value__border" style="border-radius:${fontSize};"></div>
                            <span class="variable-value__sizer-label">${fontSize}</span>
                        </div>`;
                break; 
            default: 
                mount = `<div class="variable-value__container">
                            <div class="variable-value__svg" data-balloon="${fontSizeMin}" data-balloon-pos="right">${self.helpers.bpIcons("phone-portrait")}</div>
                            <div class="variable-value__sizer" style="width:${fontSizeMin};"></div>
                            <span class="variable-value__sizer-label">${fontSizeMin}</span>
                        </div>
                        <div class="variable-value__container">
                            <div class="variable-value__svg" data-balloon="${fontSize}" data-balloon-pos="right">${self.helpers.bpIcons()}</div>
                            <div class="variable-value__sizer" style="width:${fontSize};"></div>
                            <span class="variable-value__sizer-label">${fontSize}</span>
                        </div>`;
                break; 
        }
        return mount;
    },
    setNewBaseVariable: function(elID, scaleID, diff){
        const self = this;
        const vars = self.helpers.isCSSVariablesTabActive('theme-variables') && self.helpers.themeHasVariables()
            ? self.vueState.globalVariables.concat(self.vueState.themeStyleSettings.general._cssVariables)
            : self.vueState.globalVariables;

            const scaleElements = vars.filter(el => el.scaleId === scaleID);
            const oldBase = scaleElements.find(el => el.base === true);
            const newBase = scaleElements.find(el => el.id === elID);
            scaleElements.forEach(el => {
                el.step = el.step - diff;
            })
            if (oldBase && newBase) {
                const keysToMove = [
                    'base',
                    'customLabel',
                    'label',
                    'min',
                    'max',
                    'largeSteps',
                    'preview',
                    'smallSteps',
                    'scaleType',
                    'scaleTypeMin',
                    'value'
                ];

                keysToMove.forEach(key => {
                    if(Object.keys(oldBase).includes(key)) newBase[key] = oldBase[key];
                    delete oldBase[key];
                });
                newBase['multiplier'] = 1;
                newBase['multiplierMin'] = 1;
                newBase['smallSteps'] = parseInt(newBase['smallSteps']) + parseInt(diff);
                newBase['largeSteps'] = parseInt(newBase['largeSteps']) - parseInt(diff);
            }
        self.changeTypeScaleVariable(null, scaleID, "");
        self.changeTypeScaleVariable(null, scaleID, "Min");
        self.setCSSVariableManager();
    },
    renameBaseVariableGroup: function(event, value, id){
        const self = this;
        const vars = self.helpers.isCSSVariablesTabActive('theme-variables') && self.helpers.themeHasVariables() ? self.vueState.globalVariables.concat(self.vueState.themeStyleSettings.general._cssVariables) : self.vueState.globalVariables;

        const base = vars.find(el => el.group === id && el.groupBase === true);
        if(!base) return;

        let newValue = event.target.value;
        base[value] = newValue;
    },
    recalculateBaseVariableScale: function(event, value, id){
        const self = this;
        const vars = self.helpers.isCSSVariablesTabActive('theme-variables') && self.helpers.themeHasVariables() ? self.vueState.globalVariables.concat(self.vueState.themeStyleSettings.general._cssVariables) : self.vueState.globalVariables;

        const base = vars.find(el => el.scaleId === id && el.base === true);
        let newValue = event.target.value;
        base[value] = newValue;

        if(value === "label"){
            const scaleElements = vars.filter(el => el.scaleId === id);
            const base = scaleElements.find(el => el.base === true);
            scaleElements.forEach(el => {
                el.name = `${newValue}-${el.suffix}`;
                if(el.base !== true){
                    if(base.scaleType !== base.scaleTypeMin){
                        el.value = `calc(var(--${newValue}-${base.suffix}) * ${el.multiplier})`;
                    } else {
                        const scaleTypeMin = base.scaleTypeMin || base.scaleType;
                        const minValue = parseFloat(Math.pow(scaleTypeMin, el.step))
                        const maxValue = parseFloat(Math.pow(base.scaleType, el.step))
                        const min = (parseFloat(base.min) * minValue).toFixed(3)
                        const max = (parseFloat(base.max) * maxValue).toFixed(3)
                        el.value = self.helpers.clampBuilder(min, max)
                    }
                }
            })
        } else {
            base.value = self.helpers.clampBuilder(base.min, base.max);
        }
        
        self.mountVariableScalePreview(id);
    },
    setVariableMultiplier: function(type, event, id, key){
        const self = this;
        const vars = type === "theme" ? self.vueState.themeStyleSettings.general._cssVariables : self.vueState.globalVariables;
        const base = vars.find(el => el.scaleId === id && el.base === true);
        const row = event.target.closest('li');
        const variable = Array.from(vars).find(el => el && el.hasOwnProperty('id') && row.dataset.id && row.dataset.id === el.id);
        if(!variable) return;

        variable[`multiplier${key}`] = parseFloat(event.target.value);
        if(base.scaleType === base.scaleTypeMin){
            variable.value = `calc(var(--${base.name}) * ${variable.multiplier})`;
        } else {
            const minValue = parseFloat(variable[`multiplierMin`]) || 1.25
            const maxValue = parseFloat(variable[`multiplier`]) || 1.25
            const min = (parseFloat(base.min) * minValue).toFixed(3)
            const max = (parseFloat(base.max) * maxValue).toFixed(3)
            variable.value = self.helpers.clampBuilder(min, max)
        }
        const preview = event.target.closest('.variable-inner-wrapper')?.querySelector('.variable-value');
        preview.innerHTML = self.mountScalePreview(base, variable)
    },
    changeTypeScaleVariable: function(value, id, key, type = "global"){
        const self = this;
        const vars = type === "theme" ? self.vueState.themeStyleSettings.general._cssVariables : self.vueState.globalVariables;
        const base = vars.find(el => el.scaleId === id && el.base === true);
        const scaleValue = value ? value : base[`scaleType${key}`];
        base[`scaleType${key}`] = scaleValue;
        const items = vars.filter(el => el.scaleId === id && el.step !== 0);
        // const defaultValues = {
        //     baseFont: self.vueState.globalVariables.find(el => el.id === "at_base-font")?.value,
        //     clampUnit: self.vueState.globalVariables.find(el => el.id === "at_clamp-unit")?.value,
        //     minViewport: self.vueState.globalVariables.find(el => el.id === "at_min-viewport")?.value,
        //     maxViewport: self.vueState.globalVariables.find(el => el.id === "at_max-viewport")?.value,
        // }
        items.forEach(el => {
            el[`multiplier${key}`] = parseFloat(Math.pow(scaleValue, el.step).toFixed(3));
            if(base.scaleType === base.scaleTypeMin){
                el.value =  `calc(var(--${base.name}) * ${parseFloat(Math.pow(scaleValue, el.step).toFixed(3))})`;
            } else {
                const scaleTypeMin = base.scaleTypeMin || base.scaleType;
                const minValue = parseFloat(Math.pow(scaleTypeMin, el.step))
                const maxValue = parseFloat(Math.pow(base.scaleType, el.step))
                const min = (parseFloat(base.min) * minValue).toFixed(3)
                const max = (parseFloat(base.max) * maxValue).toFixed(3)
                el.value = self.helpers.clampBuilder(min, max)
            }
        })
        self.mountVariableScalePreview(id);
    },
    changePreviewVariable: function(value, id, type = "global"){
        const self = this;
        const vars = type === "theme" ? self.vueState.themeStyleSettings.general._cssVariables : self.vueState.globalVariables;
        const base = vars.find(el => el.scaleId === id && el.base === true);
        base.preview = value;
        self.mountVariableScalePreview(id);
    },
    recalculateStepsVariableScale: function(key, id, action){
        const self = this;
        const vars = self.vueState.globalVariables;

        const base = vars.find(el => el.scaleId === id && el.base === true);
        let newValue = String(action === "add" ? parseInt(base[key]) + 1 : parseInt(base[key]) - 1);
        base[key] = newValue;

        function getAdjustedSteps(baseSuffix) {
            const baseIndex = self.variableScaleSuffixs.findIndex(el => el.suffix === baseSuffix);
            if (baseIndex === -1) return [];
        
            return self.variableScaleSuffixs.map((item, index) => ({
                ...item,
                step: item.step - self.variableScaleSuffixs[baseIndex].step
            }));
        }

        const adjustedSteps = getAdjustedSteps(base.suffix);

        // Small Steps
        if (key === "smallSteps") {
            newValue = parseInt(newValue);
            
            const smallValues = vars
                .filter(el => el.scaleId === id && el.step < 0)
                .sort((a, b) => a.step - b.step);

            if (action === "remove") {
                const toRemove = smallValues[0];
                const index = vars.indexOf(toRemove);
                if (index !== -1) {
                    vars.splice(index, 1);
                }
            } else if (action === "add") {
                const i = smallValues.length;
                const toAdd = adjustedSteps.find(el => el.step === -smallValues.length - 1);
                if (toAdd) {
                    const multiplier = parseFloat(Math.pow(base.scaleType, toAdd.step).toFixed(3));
                    const multiplierMin = base.scaleTypeMin ? parseFloat(Math.pow(base.scaleTypeMin, toAdd.step).toFixed(3)) : multiplier;
                    let value;
                    if(base.scaleType !== base.scaleTypeMin){
                        const scaleTypeMin = base.scaleTypeMin || base.scaleType;
                        const minValue = parseFloat(Math.pow(scaleTypeMin, toAdd.step))
                        const maxValue = parseFloat(Math.pow(base.scaleType, toAdd.step))
                        const min = (parseFloat(base.min) * minValue).toFixed(3)
                        const max = (parseFloat(base.max) * maxValue).toFixed(3)
                        value = self.helpers.clampBuilder(min, max)
                    } else {
                        value = `calc(var(--${base.label}-${base.suffix}) * ${multiplier})`;
                    }
                    const newObj = {
                        id: self.vueGlobalProp.$_generateId(),
                        scaleId: id,
                        suffix: toAdd.suffix,
                        step: toAdd.step,
                        multiplier: multiplier,
                        multiplierMin: multiplierMin,
                        type: 'scale',
                        name: `${base.label}-${toAdd.suffix}`,
                        value: value
                    };
                    if (base.hasOwnProperty('category')) {
                        newObj.category = base.category;
                    }
                    vars.unshift(newObj);
                }
            }
        }

        // Large Steps
        if (key === "largeSteps") {
            newValue = parseInt(newValue);

            const largeValues = vars
                .filter(el => el.scaleId === id && el.step >= 0)
                .sort((a, b) => a.step - b.step);

            if (action === "remove") {
                const toRemove = largeValues.pop(); // Last element
                const index = vars.indexOf(toRemove);
                if (index !== -1) {
                    vars.splice(index, 1);
                }
            } else if (action === "add") {
                const i = largeValues.length;
                const toAdd = adjustedSteps.find(el => el.step === i);
                if (toAdd) {
                    const multiplier = parseFloat(Math.pow(base.scaleType, toAdd.step).toFixed(3));
                    const multiplierMin = base.scaleTypeMin ? parseFloat(Math.pow(base.scaleTypeMin, toAdd.step).toFixed(3)) : multiplier;
                    let value;
                    if(base.scaleType !== base.scaleTypeMin){
                        const scaleTypeMin = base.scaleTypeMin || base.scaleType;
                        const minValue = parseFloat(Math.pow(scaleTypeMin, toAdd.step))
                        const maxValue = parseFloat(Math.pow(base.scaleType, toAdd.step))
                        const min = (parseFloat(base.min) * minValue).toFixed(3)
                        const max = (parseFloat(base.max) * maxValue).toFixed(3)
                        value = self.helpers.clampBuilder(min, max)
                    } else {
                        value = `calc(var(--${base.label}-${base.suffix}) * ${multiplier})`;
                    }
                    const newObj = {
                        id: self.vueGlobalProp.$_generateId(),
                        scaleId: id,
                        suffix: toAdd.suffix,
                        step: toAdd.step,
                        multiplier: multiplier,
                        multiplierMin: multiplierMin,
                        type: 'scale',
                        name: `${base.label}-${toAdd.suffix}`,
                        value: value
                    };
                    if (base.hasOwnProperty('category')) {
                        newObj.category = base.category;
                    }
                    vars.push(newObj);
                }
            }                
        }

        self.mountVariableScalePreview(id);
    },
    deleteVariable: function(type, id){
        const self = this;
        const vars = type === "theme" ? self.vueState.themeStyleSettings.general._cssVariables : self.vueState.globalVariables;
        const variable = Array.from(vars).find(el => el && el.hasOwnProperty('id') && el.id === id);
        if (!variable) return;

        if(variable.groupBase){
            const allGroupVars = vars.filter(el => el.group === variable.group && el.id !== variable.id);
            if(allGroupVars.length > 0){
                const newBase = allGroupVars[0];
                newBase.groupBase = true;
                newBase.groupName = variable.groupName;
            }
        }

        const index = vars.indexOf(variable);
        if (index === -1) return;

        vars.splice(index, 1);

        // Regenerate CSS
        if(type === "theme"){
            self.generateVariableCSS('theme');
            self.generateBuilderCSS();  
        }

        self.setCSSVariableManager();
    },
    addVariable: function(type, event, group = false){
        if(event.key !== "Enter") return;
        const self = this;
        let vars;

        const isGroup = event.target.closest('li[data-group-id]');
        const groupId = isGroup?.dataset.groupId

        if(type === "theme") {
            self.helpers.createThemeVariable();
            vars = self.vueState.themeStyleSettings.general._cssVariables;
        } else {
            vars = self.vueState.globalVariables;
        }
        const newVariable = {
            id: self.vueGlobalProp.$_generateId(),
            name: self.helpers.formatForClasses(event.target.value),
            type: 'static',
        }

        // Add Category
        if(self.cssVariablesStates.activeCategory && !['all','uncategorized'].includes(self.cssVariablesStates.activeCategory)) newVariable.category = self.cssVariablesStates.activeCategory;
        
        // Add Group
        if(group) newVariable.group = group;

        // Push Variable
        vars.push(newVariable);

        // Regenerate theme CSS
        if(type === 'theme'){
            self.generateVariableCSS('theme');
            self.generateBuilderCSS();
        }

        self.vueGlobalProp.$_showMessage('Variable successfully added');
        self.setCSSVariableManager();

        // refocus the cursor
        setTimeout(() => {
            let input;
            if(isGroup){
                input = document.querySelector(`li[data-group-id="${groupId}"] .brxc-add-new-variable`);
            } else {
                input = type === "theme" ? document.querySelector('#addNewThemeVariable') : document.querySelector('#addNewVariable');
            }
            if(!input) return;

            const end = input.value.length;
            input.setSelectionRange(end, end);
            input.focus();
        },10)

    },
    duplicateVariable: function(type, id){
        const self = this;
        const vars = type === 'theme' ? self.vueState.themeStyleSettings.general._cssVariables : self.vueState.globalVariables;
        const variable = Array.from(vars).find(el => el && el.hasOwnProperty('id') && el.id === id);
        if (!variable) return;

        const newVariable = {...variable};
        newVariable.id = self.vueGlobalProp.$_generateId();
        newVariable.name = `${variable.name}-copy`;
        delete newVariable.at_framework;
        delete newVariable.at_version;

        vars.push(newVariable);

        // Regenerate CSS
        if(type === "theme"){
            self.generateVariableCSS('theme');
            self.generateBuilderCSS();
        }

        self.setCSSVariableManager();
    },
    setaddVariableFromPicker: function(event, target){
        const self = this;
        event.preventDefault();
        event.stopPropagation();
        const group = event.target.dataset.group;
        const parent = event.target.closest('.brxc-overlay__action-btn-wrapper');
        event.target.remove();
        let input = document.createElement('input');
        input.type = "text";
        input.setAttribute('class', 'add-new-variable-input');
        parent.appendChild(input);

        input = parent.querySelector('.add-new-variable-input');
        const end = input.value.length;
        input.setSelectionRange(end, end);
        input.focus();
        input.addEventListener('keyup', (e) => {
            self.addVariableFromPicker(e, group, target);
        })
    },
    addVariableFromPicker: function(event, groupId, target){
        if(event.key !== "Enter") return;
        const self = this;
        self.cssVariablesStates.activeCategory = groupId;
        target.value = `var(--${self.helpers.formatForClasses(event.target.value)})`;
        const event2 = new Event('input', {
            bubbles: true,
            cancelable: true,
        });
        target.dispatchEvent(event2);
        self.openVariableCategory(groupId);
        self.addVariable('global', event);
        setTimeout(() => {
            const inputs = document.querySelectorAll('.brxc-global-variable-list input[type="text"].variable-value');
            if(!inputs || inputs.length < 1) return;
            const input = inputs[inputs.length - 1];
            const end = input.value.length;
            input.setSelectionRange(end, end);
            input.focus();

        }, 5)
    },
    importVariables: function(type){
        const self = this;
        const selector = type === "theme" ? '#addNewThemeVariableCSS' : '#addNewGlobalVariableCSS'
        const value = document.querySelector(selector).value;
        const cssVariablePattern = /(--[\w-]+):\s*([^;]+);/g;
        const parsedValue = value ? value.replaceAll('\n', '') : false;
        let vars;
        let importedVariables = 0;
        let newVariable;

        // No value found
        if (!parsedValue || parsedValue.length < 1) return;

        const matches = parsedValue.match(cssVariablePattern);
        if(!matches || !Array.isArray(matches) || matches.length < 1) return self.vueGlobalProp.$_showMessage(`No Matching Variables found`);

        // Assigning the correct array
        if(type === "theme") {
            self.helpers.createThemeVariable();
            vars = self.vueState.themeStyleSettings.general._cssVariables;
        } else {
            vars = self.vueState.globalVariables;
        }
        
        // Loop throug all the declarations
        matches.forEach(match => {
            const matchResult = match.match(cssVariablePattern);
            if (!matchResult) return;
            const split = matchResult[0].split(':');
            const name = split[0].substr(2);
            const value = split[1].trimStart().replaceAll(';', '');
            const formattedName = self.helpers.formatForClasses(name);
            let newVariable = '';
            // Parse clamp values

            if(self.cssVariablesStates.skipValues === true){
                newVariable = {
                    id: self.vueGlobalProp.$_generateId(),
                    name: formattedName,
                    type: 'static',
                }
            } else if (value.includes('clamp(')) {

                function remToPx(remValue, rootFontSize) {
                    const pxValue = remValue * rootFontSize;
                    return parseFloat(pxValue.toFixed(2)).toString();
                }

                // Root
                let rootFontSize = self.helpers.getRootFontSize();
                let min = false;
                let max = false;

                // Extracting min and max values from the clamp function
                const clampValues = value.match(/clamp\((.+)\)/)[1].split(',').map(v => v.trim());

                let tempMin = clampValues[0];
                let tempMax = clampValues[clampValues.length - 1];

                // min
                if(tempMin.includes('rem')) {
                    min = remToPx(parseFloat(tempMin), rootFontSize);
                } else if (tempMin.includes('px')){
                    min = tempMin.replaceAll('px','');
                }

                // max
                if(tempMax.includes('rem')) {
                    max = remToPx(parseFloat(tempMax), rootFontSize);
                } else if (tempMax.includes('px')){
                    max = tempMax.replaceAll('px','');
                }

                // Clamp with either px or rem
                if(min && max){
                    newVariable = {
                        id: self.vueGlobalProp.$_generateId(),
                        name: formattedName,
                        type: 'clamp',
                        value: self.helpers.clampBuilder(min, max),
                        min: min,
                        max: max,
                    };

                // Clamp with unknown unit
                } else {
                    newVariable = {
                        id: self.vueGlobalProp.$_generateId(),
                        name: formattedName,
                        type: 'static',
                        value: value,
                    }
                }
                
            
            // Static Values
            } else {
                newVariable = {
                    id: self.vueGlobalProp.$_generateId(),
                    name: formattedName,
                    type: 'static',
                    value: value,
                }
            }

            // Add Category
            if(self.cssVariablesStates.activeCategory && !['all','uncategorized'].includes(self.cssVariablesStates.activeCategory)) newVariable.category = self.cssVariablesStates.activeCategory;
            
            // Push new variable
            vars.push(newVariable);

            importedVariables++;

        })

        // Message
        importedVariables === 0 ? self.vueGlobalProp.$_showMessage(`No Variables found`) : self.vueGlobalProp.$_showMessage(`${importedVariables} Variables have been successfully imported`);
        
        // Regenerate Theme CSS
        if(type === "theme"){
            self.generateVariableCSS('theme');
            self.generateBuilderCSS();
            self.cssVariablesStates.importThemeVariables = false;
        } else {
            self.cssVariablesStates.importGlobalVariables = false;
        }
        self.setCSSVariableManager();

    },
    renameVariable: function(type, event){
        if(event.key !== "Enter") return;
        const self = this;
        const vars = type === "theme" ? self.vueState.themeStyleSettings.general._cssVariables : self.vueState.globalVariables;
        const row = event.target.closest('li');
        const variable = Array.from(vars).find(el => el && el.hasOwnProperty('id') && row.dataset.id && row.dataset.id === el.id);
        if(!variable) return;

        const newName = self.helpers.formatForClasses(event.target.value)
        variable.name = newName;

        if(variable.base){
            const scaleElements = vars.filter(el => el.scaleId === variable.scaleId);
            const base = scaleElements.find(el => el.base === true);
            scaleElements.filter(el => !el.base).forEach(el => {
                if(base.scaleType !== base.scaleTypeMin){
                    el.value = `calc(var(--${newName}) * ${el.multiplier})`;
                } else {
                    const scaleTypeMin = base.scaleTypeMin || base.scaleType;
                    const minValue = parseFloat(Math.pow(scaleTypeMin, el.step))
                    const maxValue = parseFloat(Math.pow(base.scaleType, el.step))
                    const min = (parseFloat(base.min) * minValue).toFixed(3)
                    const max = (parseFloat(base.max) * maxValue).toFixed(3)
                    el.value = self.helpers.clampBuilder(min, max)
                }
            })
        }

        // Regenerate Theme CSS
        if(type === "theme"){
            self.generateVariableCSS('theme');
            self.generateBuilderCSS();
        }

        self.vueGlobalProp.$_showMessage('Variable successfully renamed');
        self.setCSSVariableManager();
    },
    relabelVariable:function(type, event){
        const self = this;
        const vars = type === "theme" ? self.vueState.themeStyleSettings.general._cssVariables : self.vueState.globalVariables;
        const row = event.target.closest('li');
        const variable = Array.from(vars).find(el => el && el.hasOwnProperty('id') && row.dataset.id && row.dataset.id === el.id);
        if(!variable) return;

        event.target.value === "" ? delete variable.label : variable.label = event.target.value;
    },
    setVariableValue: function(type, event, property, color = false){
        const self = this;
        const vars = type === "theme" ? self.vueState.themeStyleSettings.general._cssVariables : self.vueState.globalVariables;
        const row = event.target.closest('li');
        const variable = Array.from(vars).find(el => el && el.hasOwnProperty('id') && row.dataset.id && row.dataset.id === el.id);
        if(!variable) return;

        const value = event.target.value
        value === '' ? delete variable[property] : variable[property] = value;

        if(type === "color"){
            const preview = event.target.previousElementSibling;
            if( preview && self.helpers.isValidCSSVar(value) ){
                preview.setAttribute("style", `background-color:${value}`)
                const computedColor = window.getComputedStyle(preview).backgroundColor;
                preview.dataset.initialColor = computedColor;
                preview.setAttribute("data-color", computedColor)
            }
            if( preview && color && chroma.valid(value) ){
                preview.setAttribute("style", `background-color:${value}`)
                preview.setAttribute("data-color", value)
                const existing = self.vueState.colorPalette
                    .flatMap(el => el.colors)
                    .find(color => color.id === variable.id);

                if(existing){
                    existing.rawValue.light = value;
                }
            }
        }
        
        if (self.debounceTimer) {
            clearTimeout(self.debounceTimer);
        }

        // Regenerate Theme CSS
        self.debounceTimer = setTimeout(() => {
            if (type !== "theme") return;
            self.generateVariableCSS('theme');
            self.generateBuilderCSS();
        }, 300)
        
    },
    setVariableClamp: function(type, event, property){
        const self = this;
        const vars = type === "theme" ? self.vueState.themeStyleSettings.general._cssVariables : self.vueState.globalVariables;
        const row = event.target.closest('li');
        const variable = Array.from(vars).find(el => el && el.hasOwnProperty('id') && row.dataset.id && row.dataset.id === el.id);
        if(!variable) return;

        variable[property] = event.target.value;
        if(variable.hasOwnProperty('min') && variable.hasOwnProperty('max')){
            variable['value'] = self.helpers.clampBuilder(parseFloat(variable['min']), parseFloat(variable['max']));
        }

        if (type === "theme") {
            self.generateVariableCSS('theme');
            self.generateBuilderCSS();
        };

        
    },
    toggleTypeSwitch: function(type, id, value){
        const self = this;
        const vars = type === 'theme' ? self.vueState.themeStyleSettings.general._cssVariables : self.vueState.globalVariables;
        const variable = Array.from(vars).find(el => el && el.hasOwnProperty('id') && el.id === id);
        if (!variable) return;
        
        variable.type = value;
        
        if(type === "theme"){
            self.generateVariableCSS('theme');
            self.generateBuilderCSS();
        }

        self.setCSSVariableManager();
    },
    toggleImportVariables: function(type, importCSS){
        const self = this;
        const value = !(importCSS === 'true');
        type === 'theme' ?  self.cssVariablesStates.importThemeVariables = value : self.cssVariablesStates.importGlobalVariables = value;
        self.setCSSVariableManagerBody();
    },
    // Color Manager
    colorStates:{
        viewCSS: false,
        activePalette: "",
        activeColor: false,
        colorManagerMode: "light",
        colorManagerSearch: "",
        colorManagerRenamePalette: false,
        colorManagerAddPalette: false,
        colorManagerShadePopup: false,
        colorManagerShadePopupId: false,
        colorManagerShadePopupLastId: false,
        colorManagerShadeNumber: 6,
        colorManagerShadeBaseName: false,
        colorManagerShadeCustom: false,
        colorManagerShadeLight: true,
        colorManagerShadeDark: true,
        colorManagerShadeTransparent: true,
        colorManagerShadeLightValid: true,
        colorManagerShadeDarkValid: true,
        colorManagerShadeTransparentValid: true,
        colorManagerShadeColors: ['#ffffff'],
        colorManagerShadeFinalColors: ['#ffffff'],
        colorManagerComplementaryPopup: false,
        colorManagerComplementaryPopupId: false,
        colorManagerComplementaryPopupLastId: false,
        colorManagerComplementaryBaseName: false,
        colorManagerComplementaryScheme: 'complementary',
        colorManagerComplementaryFinalColors: [],
        generatedCSS: false,
        generatedCSSType: "palette",
    },
    setColorManager: function(){
        const self = this;
        if(self.colorStates.viewCSS){
            self.setColorManagerHeader();
            self.setColorManagerViewCSS();
        } else {
            self.setColorManagerHeader();
            self.setColorManagerSearch();
            self.setColorManagerBody();
        }
    },
    colorManagerToggleCSSView: function(){
        const self = this;
        self.colorStates.viewCSS = !self.colorStates.viewCSS;
        self.setColorManager();
    },
    setColorManagerViewCSS: function(){
        const self = this;

        const canvas = {
            search: document.querySelector('#colorSearchCanvas'),
            body: document.querySelector('#colorBodyCanvas'),
        };

        if(!canvas.search || !canvas.body) return;

        // reset header and search
        canvas.search.innerHTML = '';
        canvas.body.innerHTML = '';

        // mount editor
        function generateCSS() {
            const modes = [
                {
                    name: 'light',
                    selectors: ':root, .brxc-light-colors, html[data-theme="dark"] .brxc-reversed-colors, html[data-theme="light"] .brxc-initial-colors'
                }
            ];

            // darkmode
            if(self.globalSettings.generalCats.globalColorsDarkMode) {
                modes.push({
                    name: 'dark',
                    selectors: 'html[data-theme="dark"], .brxc-dark-colors, html[data-theme="light"] .brxc-reversed-colors, html[data-theme="dark"] .brxc-initial-colors'
                })
            }
            
            // 1. Generate @property declarations
            const generatePropertyDeclarations = () => {
                return self.vueState.colorPalette
                .flatMap(palette => (Array.isArray(palette.colors) ? palette.colors : []).map(color => ({...color, _prefix: palette.prefix || ''})))
                .filter(color => color?.colorProperty)
                .map(color => `@property --${self.helpers.getColorName(color, color._prefix)} { syntax: '<color>'; initial-value: ${color.rawValue.light}; inherits: true; }`)
                .join('\n');
            };
            
            // 2. Generate mode-specific CSS blocks for a given palette
            const generateModeBlocks = (paletteId = false) => {
                const blocks = modes.map(mode => {
                const cssValue = self.generateColorCSSValue(mode.name, paletteId);
                if (cssValue === '') return '';
                return `${mode.selectors} { ${cssValue} }`;
                });
            
                const nonEmptyBlocks = blocks.filter(Boolean);
            
                return nonEmptyBlocks.length > 0
                ? nonEmptyBlocks.join('\n')
                : '/* No styles generated by AT */';
            };
            
            // 3. Build full CSS output based on current generation mode
            const generateCSSOutput = () => {
                if (self.colorStates.generatedCSSType === "palette") {
                return self.vueState.colorPalette
                    .filter(palette => palette.id === self.colorStates.activePalette)
                    .map(palette => generateModeBlocks(palette.id))
                    .join('\n');
                } else {
                return generateModeBlocks();
                }
            };
            
            // 4. Compose full CSS string
            const properties = generatePropertyDeclarations();
            const modeCSS = generateCSSOutput();
            const css = css_beautify(`${properties}\n${modeCSS}`, { indent_size: 2 });
            
            return css;
        }


        let content = `
                        <div class="brxc-overlay__panel-inline-btns-wrapper">
                            <input type="radio" id="brxc-this-palette" name="brxc-view-palette-css" class="brxc-input__checkbox" data-type="palette" value="palette"${self.colorStates.generatedCSSType === "palette" ? ' checked' : ''}>
                            <label for="brxc-this-palette" class="brxc-overlay__panel-inline-btns">This Palette</label>
                            <input type="radio" id="brxc-all-palettes" name="brxc-view-palette-css" class="brxc-input__checkbox" data-type="all" value="all" ${self.colorStates.generatedCSSType === "all" ? ' checked' : ''}>
                            <label for="brxc-all-palettes" class="brxc-overlay__panel-inline-btns">All Palettes</label>
                        </div>
                        <div id="brxcColorManagerViewCSSContainer">
                            <p data-control="info">The following CSS is dynamically generated by Advanced Themer on the frontend. If you plan to deactivate the plugin, be sure to copy and paste this code into your global.css file or export the variables to the CSS Variables Manager to preserve your styles.</p>
                            <div class="brxc-codemirror__wrapper">
                                <textarea id="brxcColorManagerViewCSS">${generateCSS()}</textarea>
                                <div class="brxc-overlay__action-btn" style="margin-left: auto" onclick="ADMINBRXC.copytoClipboard(this, this.previousElementSibling.CodeMirror.getValue(), 'Copied!', 'Copy to Clipboard')"><span>Copy to Clipboard</span></div>
                            </div>
                            <div id="brxcExportColorsToManager" class="brxc-overlay__action-btn primary" onClick="ADMINBRXC.exportColorsToManager()">Export Colors to the Variable Manager</div>
                        </div>`
        canvas.body.innerHTML = content;

        const options = self.codeMirrorOptions(false);
        options.readOnly = true;
        options.styleActiveLine = true;
        options.autofocus = false
        options.search = { bottom: false };

        // Listeners
        const inputs = canvas.body.querySelectorAll('[name=brxc-view-palette-css]');
        inputs.forEach(input => {
            input.addEventListener('click', () => {
                const type = input.dataset.type;
                self.colorStates.generatedCSSType = type;
                self.setColorManager();
            })
        })

        // Refresh Editor
        const MyCM = CodeMirror.fromTextArea(document.querySelector('#brxcColorManagerViewCSS'), options);
        setTimeout(() => {
            MyCM.refresh()
        }, 1)
    },
    exportColorsToManager: function () {
        const self = this;
        let count = 0;
      
        const exportPalette = (paletteId) => {
          const palette = self.vueState.colorPalette.find(p => p.id === paletteId);
          if (!palette || palette.status === "disabled") return;
      
          const colors = Array.isArray(palette.colors) ? palette.colors : [];

          const variables = colors
            .filter(color => color.rawValue)
            .map(color => ({
              id: color.id,
              name: self.helpers.setColorPrefix(self.helpers.getColorName(color, palette.prefix), false, palette.prefix),
              value: color.rawValue.light,
              category: palette.id,
              type: 'color',
            }));
      
          if (!variables.length) return;
      
          // Add category if missing
          if (!self.vueState.globalVariablesCategories.some(cat => cat.id === palette.id)) {
            self.vueState.globalVariablesCategories.push({
              id: palette.id,
              name: palette.name,
            });
          }
          
          // Replace or add each variable
          variables.forEach(variable => {
            const index = self.vueState.globalVariables.findIndex(v => v.id === variable.id);
            if (index !== -1) self.vueState.globalVariables.splice(index, 1);
            self.vueState.globalVariables.push(variable);
            count++;
          });
        };
      
        // Export either single or all palettes
        const palettesToExport = self.colorStates.generatedCSSType === "palette"
          ? [self.colorStates.activePalette]
          : self.vueState.colorPalette.map(p => p.id);
      
        palettesToExport.forEach(exportPalette);
      
        self.vueGlobalProp.$_showMessage(`${count} Variable(s) correctly exported to the manager!`);
      },
    setFavoritePalette: function(paletteId){
        const self = this;
        const palettes = self.vueState.colorPalette;
        const activePalette = Array.from(palettes).find(el => el && el.hasOwnProperty('id') && el.id === paletteId);
        if(!activePalette) return;

        const defaultPalette = Array.from(palettes).find(el => el && el.hasOwnProperty('default') && el.default === "true");
        if(defaultPalette && activePalette === defaultPalette){
            delete defaultPalette.default;
        } else {
            if(defaultPalette) delete defaultPalette.default;
            activePalette.default = "true";
        }
    },
    togglePaletteStatus: function(paletteId){
        const self = this;
        const palettes = self.vueState.colorPalette;
        const palette = Array.from(palettes).find(el => el && el.hasOwnProperty('id') && el.id == paletteId)
        if(!palette) return;

        !palette.hasOwnProperty('status') || palette.status !== "disabled" ? palette.status = "disabled" : palette.status = "enabled";
        self.generateColorCSS();
        self.generateBuilderCSS();
    },
    setColorManagerHeader: function(){
        const self = this;
        const canvas = document.querySelector('#colorHeaderCanvas');
        if(!canvas) return;

        let content = '';
        const palettes = self.vueState.colorPalette;
        if(palettes.length < 1) return;
        const palette = Array.from(palettes).find(el => el && el.hasOwnProperty('id') && el.id == self.colorStates.activePalette)
        const actionStatusEnabled = !palette.hasOwnProperty('status') || palette.status !== "disabled"
        content += `<div class="brxc-select-palette">
                        <div class="brxc-label">Palette</div>
                        <div class="brxc-input-wrapper">`;
        content += (self.colorStates.colorManagerMode === 'dark') ? `<div class="brxc-darkmode active" data-balloon="Switch to Lightmode" data-balloon-pos="top-left" onclick="ADMINBRXC.toggleTopbarTweaks([&quot;darkmode&quot;], false)"><i class="ion-ios-moon"></i></div>` : `<div class="brxc-darkmode" data-balloon="Switch to Darkmode" data-balloon-pos="top-left" onclick="ADMINBRXC.toggleTopbarTweaks([&quot;darkmode&quot;], false)"><i class="ion-ios-sunny"></i></div>`;
        if(self.colorStates.colorManagerRenamePalette === false && self.colorStates.colorManagerAddPalette === false){
            content += `
                    <div class="brxc-select-wrapper">
                        <div class="active-palette">
                            <span>${palette.name}</span>
                            <div class="brxc-action">
                                <div class="brxc-icon${palette.hasOwnProperty('default') && palette.default === "true" ? ' active' : ''}" data-action="favorite" data-id="${palette.id}" data-balloon="Set as Default" data-balloon-pos="bottom-right"><span class="bricks-svg-wrapper"><i class="fas fa-star"></i></span></div>
                                <div data-action="${actionStatusEnabled ? "disable" : "enable"}" data-id="${palette.id}" data-balloon="${actionStatusEnabled ? "Palette Enabled" : "Palette Disabled"}" data-balloon-pos="bottom-right"><i class="fas fa-toggle-${actionStatusEnabled ? 'on' : 'off'}"></i></div>
                            </div>
                        </div>
                        <div class="list-palette hidden">
                        ${palettes.filter(el => el.id !== palette.id)
                            .map(el => {
                                const actionStatusEnabled = !el.hasOwnProperty('status') || el.status !== "disabled"
                                return `<div class="inactive-palette" data-palette-id="${el.id}">
                                            <span>${el.name}</span>
                                            <div class="brxc-action">
                                                <div class="brxc-icon${el.hasOwnProperty('default') && el.default === "true" ? ' active' : ''}" data-action="favorite" data-id="${el.id}" data-balloon="Set as Default" data-balloon-pos="bottom-right"><span class="bricks-svg-wrapper"><i class="fas fa-star"></i></span></div>
                                                <div data-action="${actionStatusEnabled ? "disable" : "enable"}" data-id="${el.id}" data-balloon="${actionStatusEnabled ? "Palette Enabled" : "Palette Disabled"}" data-balloon-pos="bottom-right"><i class="fas fa-toggle-${actionStatusEnabled ? 'on' : 'off'}"></i></div>
                                            </div>
                                        </div>`
                            }).join('')}
                        </div>
                    </div>
                </div>
            </div>
            <div class="brxc-prefix-container">
                <div class="brxc-label">Prefix</div>
                <input type="text" id="brxcPalettePrefix" value="${palette.hasOwnProperty('prefix') ? palette.prefix : ''}" />
            </div>
            <div class="brxc-icon-container">
                <div class="brxc-icon palette-menu" data-balloon="Palette Menu" data-balloon-pos="bottom-right" onclick="event.stopPropagation();ADMINBRXC.openPaletteMenu(this)">
                    <span class="bricks-svg-wrapper">
                        <svg version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" class="bricks-svg" style="rotate: 90deg;">
                            <path d="M3,9.5c-0.828427,0-1.5-0.671573-1.5-1.5s0.671573-1.5 1.5-1.5c0.828427,0 1.5,0.671573 1.5,1.5s-0.671573,1.5-1.5,1.5Zm5,0c-0.828427,0-1.5-0.671573-1.5-1.5s0.671573-1.5 1.5-1.5c0.828427,0 1.5,0.671573 1.5,1.5s-0.671573,1.5-1.5,1.5Zm5,0c-0.828427,0-1.5-0.671573-1.5-1.5s0.671573-1.5 1.5-1.5c0.828427,0 1.5,0.671573 1.5,1.5s-0.671573,1.5-1.5,1.5Z" fill="currentColor" fill-rule="evenodd"></path>
                        </svg>
                    </span>
                </div>
            </div>`;
        } else if(self.colorStates.colorManagerRenamePalette === true){
            content += `<input type="text" id="brxcRenamePalette" value="${palette.name}" />`;
        } else if(self.colorStates.colorManagerAddPalette === true){
            content += `<input type="text" id="brxcAddPalette" placeholder="Type the color palette's name here and hit ENTER." value="" />`;
        }
        content += `</div>`;

        canvas.innerHTML = content;

        // Menu Dropdown
        const paletteWrapper = canvas.querySelector('.brxc-select-wrapper');
        if(paletteWrapper){
            paletteWrapper.addEventListener('click', (e) => {
                const action = e.target.closest('[data-action]');
                const paletteId = e.target.closest('[data-palette-id]')
                let icon;
                if(action) {
                    switch(action.dataset.action){
                        case 'favorite':
                            paletteWrapper.querySelectorAll(`[data-action="favorite"]:not([data-id=${action.dataset.id}])`).forEach(el => el.classList.remove('active'))
                            action.classList.toggle('active')
                            self.setFavoritePalette(action.dataset.id, action)
                            break;
                        case 'enable':
                            action.dataset.action = "disable"
                            action.dataset.balloon = "Palette Enabled"
                            icon = action.querySelector('i');
                            icon.classList.remove('fa-toggle-off');
                            icon.classList.add('fa-toggle-on');
                            self.togglePaletteStatus(action.dataset.id, action);
                            if(self.colorStates.viewCSS){
                                self.setColorManagerViewCSS();
                            }
                            break;
                        case 'disable':
                            action.dataset.action = "enable"
                            action.dataset.balloon = "Palette Disabled"
                            icon = action.querySelector('i');
                            icon.classList.remove('fa-toggle-on');
                            icon.classList.add('fa-toggle-off');
                            self.togglePaletteStatus(action.dataset.id, action)
                            if(self.colorStates.viewCSS){
                                self.setColorManagerViewCSS();
                            }
                            break;
                    }
                } else if(paletteId) {
                    self.colorStates.activePalette = paletteId.dataset.paletteId;
                    self.setColorManager();
                } else {
                    paletteWrapper.querySelector('.list-palette')?.classList.toggle('hidden')
                }
            })
        }

        // Prefix
        const prefixInput = canvas.querySelector('#brxcPalettePrefix');
        if(prefixInput){
            prefixInput.addEventListener('input', () => {
                const newPrefix = prefixInput.value.replaceAll(' ','');
                palette.prefix = newPrefix;
                (Array.isArray(palette.colors) ? palette.colors : []).forEach(color => {
                    color.raw = `var(--${newPrefix}${self.helpers.formatForClasses(self.helpers.getColorName(color, palette.prefix))})`
                })
            })
            self.generateColorCSS();
        }

        // Rename
        if (self.colorStates.colorManagerRenamePalette === true) {
            self.colorStates.colorManagerRenamePalette = false;
            const input = canvas.querySelector('#brxcRenamePalette');
            if (!input) return;
            const end = input.value.length;
            input.setSelectionRange(end, end);
            input.focus();

            function saveName(input) {
                const palette = Array.from(palettes).find(el => el && el.hasOwnProperty('id') && el.id == self.colorStates.activePalette);
                if (palette.name !== input.value) {
                    palette.name = input.value;
                    self.vueGlobalProp.$_showMessage('Color Palette correctly renamed!');
                }
                setTimeout(() => {
                    self.setColorManager();
                }, 10);
            }

            const onBlur = () => {
                saveName(input);
                input.removeEventListener("blur", onBlur);
                input.removeEventListener("keydown", onKeyDown);
                setTimeout(() => {
                    self.setColorManagerHeader();
                }, 10);
            };

            const onKeyDown = (event) => {
                if (event.key === "Enter") {
                    saveName(input);
                    input.removeEventListener("blur", onBlur);
                    input.removeEventListener("keydown", onKeyDown);
                }
            };

            input.addEventListener("blur", onBlur);
            input.addEventListener("keydown", onKeyDown);
        }


        // Add
        if (self.colorStates.colorManagerAddPalette === true) {
            self.colorStates.colorManagerAddPalette = false;
            const input = canvas.querySelector('#brxcAddPalette');
            if (!input) return;
            const end = input.value.length;
            input.setSelectionRange(end, end);
            input.focus();
            const newId = self.vueGlobalProp.$_generateId();

            function addName(input) {
                const newPalette = {
                    id: newId,
                    name: input.value,
                    colors: []
                };
                palettes.push(newPalette);
                self.colorStates.activePalette = newId;
                self.vueGlobalProp.$_showMessage('Color Palette successfully created!');
                self.setColorManager();
            }

            const onBlur = () => {
                input.removeEventListener("blur", onBlur);
                input.removeEventListener("keydown", onKeyDown);
                setTimeout(() => {
                    self.setColorManagerHeader();
                }, 10);
            };

            const onKeyDown = (event) => {
                if (event.key === "Enter") {
                    addName(input);
                    input.removeEventListener("blur", onBlur);
                    input.removeEventListener("keydown", onKeyDown);
                }
            };

            input.addEventListener("blur", onBlur);
            input.addEventListener("keydown", onKeyDown);
        }
    },
    duplicatePalette: function () {
        const self = this;
        const palettes = self.vueState.colorPalette;
        const activePalette = palettes.find(el => el && el.hasOwnProperty('id') && el.id === self.colorStates.activePalette);

        function reassignNewIds(arr) {
            const idMap = new Map();
        
            // First, assign new IDs and strip meta fields
            for (const item of arr) {
                const oldId = item.id;
                const newId = self.vueGlobalProp.$_generateId();
                idMap.set(oldId, newId);
        
                item.id = newId;
                delete item.at_framework;
                delete item.at_version;
        
                // Prepare empty shadeChildren if not present
                if (!Array.isArray(item.shadeChildren)) {
                    item.shadeChildren = [];
                }
            }
        
            // Then, update shadeParent and shadeChildren references using the map
            for (const item of arr) {
                if (item.shadeParent && idMap.has(item.shadeParent)) {
                    item.shadeParent = idMap.get(item.shadeParent);
                }
        
                if (Array.isArray(item.shadeChildren)) {
                    item.shadeChildren = item.shadeChildren
                        .map(oldChildId => idMap.get(oldChildId))
                        .filter(Boolean);
                }
            }
        
            return arr;
        }
    
        if (activePalette) {
            const duplicate = {
                ...activePalette,
                id: self.vueGlobalProp.$_generateId(),
                name: activePalette.name + ' (Copy)',
            };
            duplicate.colors = reassignNewIds(JSON.parse(JSON.stringify(duplicate.colors)));
            delete duplicate.default;
            delete duplicate.at_framework;
            delete duplicate.at_version;
    
            palettes.push(duplicate);
            self.colorStates.activePalette = duplicate.id;
            self.vueGlobalProp.$_showMessage('Color Palette successfully duplicated!');
            self.setColorManager();
        }
        
    },
    deletePalette: function(){
        const self = this;
        const palettes = self.vueState.colorPalette;
        const activePalette = Array.from(palettes).find(el => el && el.hasOwnProperty('id') && el.id === self.colorStates.activePalette);
        
        palettes.splice(palettes.indexOf(activePalette), 1);
        self.colorStates.activePalette = (self.vueState.colorPalette[0]) ? self.vueState.colorPalette[0].id : '';

        self.vueGlobalProp.$_showMessage('Color Palette successfully deleted!');
        self.generateColorCSS();
        self.generateBuilderCSS();
        self.setColorManager();

    },
    convertPalettesToNative: function(){
        const self = this;
        const palettes = self.vueState.colorPalette;
        
        palettes.forEach(palette => {
            palette.colors = (Array.isArray(palette.colors) ? palette.colors : []).map(color => {
                if (color.hasOwnProperty('rawValue')) {
                    return {
                        id: color.id,
                        name: self.helpers.getColorName(color, palette.prefix),
                        hsl: color.rawValue.light,
                        skipPrefix: true,
                    };
                }
                return color;
            });
        });
    },
    setColorManagerSearch: function(){
        const self = this;
        const canvas = document.querySelector('#colorSearchCanvas');
        if(!canvas) return;

        const palettes = self.vueState.colorPalette;
        const activePalette = Array.from(palettes).find(el => el && el.hasOwnProperty('id') && el.id === self.colorStates.activePalette);
        if(!activePalette || !activePalette.hasOwnProperty('colors') || !Array.isArray(activePalette.colors) || activePalette.colors.length < 2) return canvas.innerHTML = '';
        let content = `<div class="brxc-overlay__search-box">
                        <input type="text" class="class-filter" name="class-search" placeholder="Filter by color name" data-type="title" value="${self.colorStates.colorManagerSearch}" oninput="ADMINBRXC.colorStates.colorManagerSearch = this.value;ADMINBRXC.setColorManagerBody();">
                        <div class="iso-search-icon">
                            <i class="bricks-svg ti-search"></i>
                        </div>
                        <div class="iso-reset" data-balloon="Reset Filter" data-balloon-pos="bottom-right" onclick="ADMINBRXC.colorStates.colorManagerSearch = '';ADMINBRXC.setColorManagerSearch();ADMINBRXC.setColorManagerBody();">
                            <i class="bricks-svg ti-close"></i>
                        </div>
                      </div>`;
        canvas.innerHTML = content;
    },
    setColorManagerBody: function() {
        const self = this;
        self.resetStates();
        
        const canvas = document.querySelector('#colorBodyCanvas');
        if (!canvas) return;
        
        const { activePalette, filteredColors } = this._getActivePaletteAndColors();
        if (!activePalette) return;
        
        const content = this._generateColorListHTML(filteredColors, activePalette);
        canvas.innerHTML = content;
        
        this._setupEventHandlers(canvas, activePalette);
        this._resetPopupStates();
    },
    
    _getActivePaletteAndColors: function() {
        const palettes = this.vueState.colorPalette;
        const activePalette = Array.from(palettes).find(el => 
            el && el.hasOwnProperty('id') && el.id === this.colorStates.activePalette
        );
        
        if (!activePalette) return { activePalette: null, filteredColors: [] };
        
        if (!activePalette.hasOwnProperty('colors')) {
            activePalette.colors = {};
        }
        
        let colors = activePalette.colors;
        const searchTerm = this.colorStates.colorManagerSearch;
        const filteredColors = (searchTerm === '') 
            ? colors 
            : Array.from(colors).filter(el => el && self.helpers.getColorName(el, activePalette.prefix).includes(searchTerm));
        
        return { activePalette, filteredColors };
    },
    
    _generateColorListHTML: function(colors, activePalette) {
        const self = this;
        const isSearching = self.colorStates.colorManagerSearch !== ""; 
        let content = `<ul class="brxc-color-list${isSearching ? ` is-searching` : ''}" style="--bg-checkboard: url(${this.globalSettings.transparencyCheckboard})">`;
        
        // Get root colors (colors without shadeParent)
        let rootColors = Object.values(colors)
        if(!isSearching) rootColors = rootColors.filter(el => !el.shadeParent);
        
        for (const rootColor of rootColors) {
            content += this._generateColorHierarchy(rootColor, colors, 0, rootColor);
        }
        
        content += '</ul>';
        content += this._generateAddColorSection(activePalette);
        
        return content;
    },
    
    _generateColorHierarchy: function(color, allColors, level, rootColor) {
        let content = '';
        
        // Generate the current color item
        content += this._generateColorItemHTML(color, level);
        
        // Check if this color is expanded and has children
        const isExpanded = rootColor.hasOwnProperty('isExpanded') && rootColor.isExpanded === true;
    
        if (isExpanded) {
            // Find all direct children of this color
            const childColors = Object.values(allColors).filter(el => 
                el.shadeParent === color.id
            );
            
            // Recursively generate each child and its descendants
            for (const childColor of childColors) {
                content += this._generateColorHierarchy(childColor, allColors, level + 1, rootColor);
            }
        }
        
        
        return content;
    },
    
    _shouldHideColor: function(color, colors) {
        const hasShadeParent = color.hasOwnProperty('shadeParent');
        if (!hasShadeParent) return false;
        
        const parent = Array.from(colors).find(el => 
            el && el.hasOwnProperty('id') && el.id === color.shadeParent
        );
        
        return parent && parent.hasOwnProperty('isExpanded') && parent.isExpanded !== true;
    },
    
    _generateColorItemHTML: function(color, level) {
        const mode = this.colorStates.colorManagerMode;
        const colorProperties = this._getColorProperties(color);
        const colorValue = this._getColorValue(color, colorProperties.hasRaw);
        const cssClasses = this._getColorItemClasses(color, colorProperties, mode);
        
        let content = `<li data-id="${color.id}"${!colorProperties.isShade ? ' data-parent="true"' : ` data-level="${level}" style="--level:${level}"`} class="${cssClasses}">`;
        content += '<div class="color-wrapper">';
        content += this._generateColorHandle(color);
        content += this._generateColorButton(color, colorValue, colorProperties);
        content += this._generateColorTypeToggle(colorProperties.isVariableOnly);
        content += this._generateColorNameInput(color, colorProperties, mode);
        content += this._generateActionButtons(color, colorProperties, mode);
        content += this._generateExpandToggleButtons(color);
        content += '</div>';
        content += this._generatePopupForms(color);
        content += '</li>';
        
        return content;
    },
    
    _getColorProperties: function(color) {
        return {
            hasRaw: color.hasOwnProperty('raw'),
            hasRawValue: color.hasOwnProperty('rawValue'),
            isShade: color.hasOwnProperty('isShade') && color.hasOwnProperty('shadeParent') && color.shadeParent,
            isVariableOnly: color.hasOwnProperty('isVariableOnly') && color.isVariableOnly === true,
            isFramework: this.helpers.isFramework(color.id)
        };
    },
    
    _getColorValue: function(color, hasRaw) {
        return this._checkRow(color, hasRaw);
    },
    
    _checkRow: function(obj, hasRaw) {
        const mode = this.colorStates.colorManagerMode;
        
        if (!hasRaw) {
            if (obj.hasOwnProperty('hsl')) return obj.hsl;
            if (obj.hasOwnProperty('rgb')) return obj.rgb;
            if (obj.hasOwnProperty('hex')) return obj.hex;
        } else {
            if (obj.hasOwnProperty('raw') && obj.hasOwnProperty('rawValue') && obj.rawValue.hasOwnProperty(mode)) {
                return obj.rawValue[mode];
            }
            if (mode === "dark" && obj.hasOwnProperty('raw') && obj.hasOwnProperty('rawValue') && obj.rawValue.hasOwnProperty("light")) {
                return obj.rawValue.light;
            }
            if (obj.hasOwnProperty('raw')) return obj.raw;
            return '#ff0000';
        }
    },
    
    _getColorItemClasses: function(color, properties, mode) {
        const classes = [];
        
        const isPopupActive = this._isPopupActive(color.id);
        if (isPopupActive) classes.push('active');
        
        if (mode === "light" && properties.isFramework) classes.push('framework');
        if (!properties.hasRaw) classes.push('disable');
        
        return classes.join(' ');
    },
    
    _isPopupActive: function(colorId) {
        const shadePopupActive = this.colorStates.colorManagerShadePopup === true && 
                               this.colorStates.colorManagerShadePopupId === colorId;
        const compPopupActive = this.colorStates.colorManagerComplementaryPopup === true && 
                              this.colorStates.colorManagerComplementaryPopupId === colorId;
        
        return shadePopupActive || compPopupActive;
    },
    
    _generateColorHandle: function(color) {
        const self = this;
        if(color.shadeParent || self.colorStates.colorManagerSearch !== "") return '';
        return '<div class="handle"><i class="fas fa-grip-vertical"></i></div>';
    },
    
    _generateColorButton: function(color, colorValue, properties) {
        const mode = this.colorStates.colorManagerMode;
        const buttonClass = `brxc-color-input${mode === "light" && properties.isFramework ? '-framework' : ''}${!properties.isVariableOnly ? ' main-color': ''}`;
        const displayValue = properties.isVariableOnly ? color.raw : colorValue;
        
        let content = `<div class="btn-color-wrapper">`;
        content += `<button class="${buttonClass}" data-id="${color.id}" data-initial-color="${colorValue}" data-balloon="${displayValue}" data-balloon-pos="top-left" style="background:${displayValue};"></button>`;
        
        if (color.hasOwnProperty('raw') && this.helpers.isVarActiveOnPage(color.raw)) {
            content += '<div class="btn-color-check" data-balloon="active on the page" data-balloon-pos="right"><i class="fas fa-check"></i></div>';
        }
        
        content += '</div>';
        return content;
    },
    
    _generateColorTypeToggle: function(isVariableOnly) {
        const activeClass = isVariableOnly ? ' active' : '';
        const tooltipText = isVariableOnly ? 'variable' : 'color';
        const displayText = isVariableOnly ? 'V' : 'C';
        
        return `<div class="brxc-color-type-toggle${activeClass}" data-balloon="${tooltipText}" data-balloon-pos="top">${displayText}</div>`;
    },
    
    _generateColorNameInput: function(color, properties, mode) {
        const inactiveClass = properties.hasRaw && !properties.hasRawValue &&
                             properties.isFramework && mode === "dark" ? ' inactive' : '';
        const palette = this.vueState.colorPalette.find(p => p.id === this.colorStates.activePalette);
        const colorName = this.helpers.getColorName(color, palette?.prefix);
        return `<input type="text" class="color-name${inactiveClass}" value="${colorName}" />`;
    },
    
    _generateActionButtons: function(color, properties, mode) {
        let content = '<div class="actions">';
        
        if (properties.isVariableOnly) {
            content += this._generateVariableOnlyActions(color);
        } else if (properties.hasRaw && properties.hasRawValue && !properties.isFramework) {
            content += this._generateFullColorActions(color, properties, mode);
        } else if (properties.hasRaw && properties.hasRawValue && properties.isFramework && mode === "dark") {
            content += this._generateFrameworkDarkActions(color);
        } else if (!properties.hasRaw && !properties.isFramework) {
            content += this._generateConvertColorAction(color);
        } else if (properties.hasRaw && properties.isFramework) {
            content += this._generateFrameworkCopyAction(color);
        }
        
        content += '</div>';
        return content;
    },
    
    _generateVariableOnlyActions: function(color) {
        const palette = this.vueState.colorPalette.find(p => p.id === this.colorStates.activePalette);
        const colorName = this.helpers.getColorName(color, palette?.prefix);
        return `
            <div class="brxc-icon" data-balloon="Rename" data-balloon-pos="bottom-right" onClick="ADMINBRXC.renameColor(event,'${color.id}','${colorName}');"><span class="bricks-svg-wrapper"><i class="fas fa-pen"></i></span></div>
            <div class="brxc-icon" data-balloon="Duplicate" data-balloon-pos="bottom-right" onClick="ADMINBRXC.duplicateColor('${color.id}');"><span class="bricks-svg-wrapper"><i class="fas fa-clone"></i></span></div>
            <div class="brxc-icon" data-balloon="Copy to Clipboard" data-balloon-pos="bottom-right" onClick="ADMINBRXC.copytoClipboardSimple('${color.raw}','${color.raw} successfully copied to clipboard');"><span class="bricks-svg-wrapper"><i class="fas fa-clipboard"></i></span></div>
            <div class="brxc-icon" data-balloon="Delete" data-balloon-pos="bottom-right" onClick="ADMINBRXC.setDeleteColor('${color.id}', this)"><span class="bricks-svg-wrapper"><i class="ti-trash"></i></span></div>
        `;
    },
    
    _generateFullColorActions: function(color, properties, mode) {
        const isShade = properties.isShade;
        const palette = this.vueState.colorPalette.find(p => p.id === this.colorStates.activePalette);
        const colorName = this.helpers.getColorName(color, palette?.prefix);
        let content = `<div class="brxc-icon" data-balloon="Rename" data-balloon-pos="bottom-right" onClick="ADMINBRXC.renameColor(event,'${color.id}','${colorName}');"><span class="bricks-svg-wrapper"><i class="fas fa-pen"></i></span></div>`;
        
        if (mode === "light") {
            const compActive = this.colorStates.colorManagerComplementaryPopup === true && 
                              this.colorStates.colorManagerComplementaryPopupId === color.id ? ' active' : '';
            const shadeActive = this.colorStates.colorManagerShadePopup === true && 
                               this.colorStates.colorManagerShadePopupId === color.id ? ' active' : '';
            
            content += `<div class="brxc-icon${compActive}" data-balloon="Generate Complementary Colors" data-balloon-pos="bottom-right" onClick='ADMINBRXC.colorStates.activeColor = ${JSON.stringify(color)};ADMINBRXC.setComplementaryWrapper("${this.colorStates.colorManagerComplementaryPopup}","${color.id}");'><span class="bricks-svg-wrapper"><i class="fas fa-palette"></i></span></div>`;
            content += `<div class="brxc-icon${shadeActive}" data-balloon="Generate Shades" data-balloon-pos="bottom-right" onClick='ADMINBRXC.colorStates.activeColor = ${JSON.stringify(color)};ADMINBRXC.setShadesWrapper("${this.colorStates.colorManagerShadePopup}","${color.id}");'><span class="bricks-svg-wrapper"><i class="fas fa-wand-magic-sparkles"></i></span></div>`;
        }
        
        const propertyActive = color.colorProperty ? ' active' : '';
        content += `<div class="brxc-icon${propertyActive}" data-balloon="Add @property declarations" data-balloon-pos="bottom-right" onClick="ADMINBRXC.toggleColorProperty('${color.id}');"><span class="bricks-svg-wrapper"><i class="fas fa-at"></i></span></div>`;
        
        if (mode === "dark") {
            content += `<div class="brxc-icon" data-balloon="Convert to Dark Color" data-balloon-pos="bottom-right" onClick="ADMINBRXC.convertDarkColor('${color.id}');"><span class="bricks-svg-wrapper"><i class="fas fa-right-left"></i></span></div>`;
        }
        
        content += `
            <div class="brxc-icon" data-balloon="Duplicate" data-balloon-pos="bottom-right" onClick="ADMINBRXC.duplicateColor('${color.id}');"><span class="bricks-svg-wrapper"><i class="fas fa-clone"></i></span></div>
            <div class="brxc-icon" data-balloon="Copy to Clipboard" data-balloon-pos="bottom-right" onClick="ADMINBRXC.copytoClipboardSimple('${color.raw}','${color.raw} successfully copied to clipboard');"><span class="bricks-svg-wrapper"><i class="fas fa-clipboard"></i></span></div>
            <div class="brxc-icon" data-balloon="Delete" data-balloon-pos="bottom-right" onClick="ADMINBRXC.setDeleteColor('${color.id}', this)"><span class="bricks-svg-wrapper"><i class="ti-trash"></i></span></div>
        `;
        
        return content;
    },
    
    _generateFrameworkDarkActions: function(color) {
        return `<div class="brxc-icon" data-balloon="Remove Dark Color" data-balloon-pos="bottom-right" onClick="ADMINBRXC.removeRawValue('${color.id}', this)"><span class="bricks-svg-wrapper"><i class="ti-trash"></i></span></div>`;
    },
    
    _generateConvertColorAction: function(color) {
        return `<div class="brxc-icon" data-balloon="Convert to a CSS variable" data-balloon-pos="left" onClick="ADMINBRXC.convertColor('${color.id}');"><span class="bricks-svg-wrapper"><i class="fas fa-right-left"></i></span></div>`;
    },
    
    _generateFrameworkCopyAction: function(color) {
        return `<div class="brxc-icon" data-balloon="Copy to Clipboard" data-balloon-pos="bottom-right" onClick="ADMINBRXC.copytoClipboardSimple('${color.raw}','${color.raw} successfully copied to clipboard');"><span class="bricks-svg-wrapper"><i class="fas fa-clipboard"></i></span></div>`;
    },
    
    _generateExpandToggleButtons: function(color) {
        let content = '';
        
        if (color.hasOwnProperty('shadeChildren') && Array.isArray(color.shadeChildren) && color.shadeChildren.length > 0) {
            const isExpanded = color.hasOwnProperty('isExpanded') && color.isExpanded === true;
            const tooltipText = isExpanded ? 'Hide' : 'Show';
            const iconClass = isExpanded ? 'minus' : 'plus';
            
            content += '<div class="actions always-visible">';
            content += `<div class="brxc-icon" data-balloon="${tooltipText} Shades" data-balloon-pos="bottom-right" onClick="ADMINBRXC.toggleExpandShades('${color.id}');"><span class="bricks-svg-wrapper"><i class="fas fa-${iconClass}"></i></span></div>`;
            content += '</div>';
        } else if (color.hasOwnProperty('shadeParent') && color.shadeParent) {
            const isLinked = color.hasOwnProperty('isShade') && color.isShade === true;
            const linkClass = !isLinked ? ' unlinked' : '';
            const tooltipText = isLinked ? 'Unlink' : 'Link';
            const iconClass = isLinked ? 'link' : 'link-slash';
            
            content += '<div class="actions always-visible">';
            content += `<div class="brxc-icon links${linkClass}" data-balloon="${tooltipText} to parent color" data-balloon-pos="bottom-right" onClick="ADMINBRXC.toggleLinkShades('${color.id}');"><span class="bricks-svg-wrapper"><i class="fas fa-${iconClass}"></i></span></div>`;
            content += '</div>';
        }
        
        return content;
    },
    
    _generatePopupForms: function(color) {
        let content = '';
        
        if (this.colorStates.colorManagerShadePopup === true && this.colorStates.colorManagerShadePopupId === color.id) {
            content += this.setShadesForm(color.id);
        }
        
        if (this.colorStates.colorManagerComplementaryPopup === true && this.colorStates.colorManagerComplementaryPopupId === color.id) {
            content += this.setComplementaryForm(color.id);
        }
        
        return content;
    },
    
    _generateAddColorSection: function(activePalette) {
        if (this.helpers.isFramework(activePalette.id)) return '';
        
        let content = '<div class="brxc-add-color-wrapper">';
        
        const importActive = this.colorStates.colorManagerImportCSSVariables === true ? ' active' : '';
        content += `<div class="brxc-import-css-colors${importActive}" data-balloon="Import CSS variables" data-balloon-pos="bottom-left" onclick="ADMINBRXC.toggleImportColorVariables('${this.colorStates.colorManagerImportCSSVariables === true ? 'true' : 'false'}');"><i class="fas fa-code"></i></div> `;
        
        if (this.colorStates.colorManagerImportCSSVariables === true) {
            content += '<textarea id="addNewColorCSS" rows="20" placeholder="Paste your CSS variables here"></textarea>';
        } else {
            content += '<input type="text" id="addNewColor" placeholder="Add a new color" onkeyup="ADMINBRXC.addNewColor(event);" />';
        }
        
        content += '</div>';
        
        if (this.colorStates.colorManagerImportCSSVariables === true) {
            content += this._generateImportVariableWrapper();
        }
        
        return content;
    },
    
    _generateImportVariableWrapper: function() {
        const toggleState = this.colorStates.colorManagerImportCSSVariablesskipValues === true ? 'on' : 'off';
        
        return `
            <div id="brxcImportVariableWrapper">
                <div class="gridUI__input-wrapper">
                    <label class="has-tooltip">
                        <span>Import as Variables?</span>
                        <div data-balloon="Toggle this option if you're importing variables that are defined elsewhere, but want them selectable inside the Variable Picker." data-balloon-pos="top" data-balloon-length="medium">
                            <i class="fas fa-circle-question"></i>
                        </div>
                    </label>
                    <i class="fas fa-toggle-${toggleState}" onClick="ADMINBRXC.colorStates.colorManagerImportCSSVariablesskipValues = !ADMINBRXC.colorStates.colorManagerImportCSSVariablesskipValues;ADMINBRXC.setColorManager();"></i>
                </div>
                <a class="brxc-overlay__action-btn primary" onclick="ADMINBRXC.importColorVariables();"><span>Import Colors</span></a>
            </div>
        `;
    },
    
    _setupEventHandlers: function(canvas, activePalette) {
        this._setupComplementarySelect(canvas);
        this._setupHeaderDropdownHandler(canvas);
        this._setupColorTypeToggle(canvas);
        this._setupColorPickers(canvas);
        this._setupScalePicker();
        this._setupDragAndDrop(canvas, activePalette);
    },
    
    _setupComplementarySelect: function(canvas) {
        const complementarySelect = canvas.querySelector('#brxcScheme');
        this.helpers.selectControl(complementarySelect, (target) => {
            this.colorStates.colorManagerComplementaryScheme = target.dataset.value;
            this.changeColorScheme(complementarySelect.dataset.id);
        });
    },
    
    _setupHeaderDropdownHandler: function(canvas) {
        canvas.addEventListener('click', () => {
            const headerDropdown = document.querySelector('#colorHeaderCanvas .list-palette');
            if (headerDropdown && !headerDropdown.classList.contains('hidden')) {
                headerDropdown.classList.add('hidden');
            }
        });
    },
    
    _setupColorTypeToggle: function(canvas) {
        const toggleTypes = canvas.querySelectorAll('.brxc-color-type-toggle');
        if (toggleTypes.length === 0) return;
        
        toggleTypes.forEach(el => {
            el.addEventListener('click', () => {
                const colorId = el.parentElement.parentElement.dataset.id;
                const palettes = this.vueState.colorPalette;
                const activePalette = Array.from(palettes).find(el => 
                    el && el.hasOwnProperty('id') && el.id === this.colorStates.activePalette
                );
                
                if (!activePalette) return;
                
                const colorObj = activePalette.colors.find(el => el && el.id === colorId);
                if (!colorObj) return;
                
                if (colorObj.hasOwnProperty('isVariableOnly') && colorObj.isVariableOnly) {
                    delete colorObj.isVariableOnly;
                } else {
                    colorObj.isVariableOnly = true;
                }
                
                this.generateColorCSS();
                this.generateBuilderCSS();
                this.setColorManager();
            });
        });
    },
    
    _setupColorPickers: function(canvas) {
        const self = this;
        const btnMain = canvas.querySelectorAll('li .brxc-color-input.main-color');
        const mode = this.colorStates.colorManagerMode;
        
        btnMain.forEach(el => {
            let picker = new ColorPicker(el, el.dataset.initialColor);
            
            el.addEventListener('colorChange', self.debounce((event) => {
                const colorPickr = document.querySelector('#color_picker');
                const display = window.getComputedStyle(colorPickr).getPropertyValue("display");
                
                if (display && display === "none") {
                    this.setColorManagerBody();
                }

                const palettes = self.vueState.colorPalette;
                const palette = palettes.find(el => el?.id === self.colorStates.activePalette);
                if (!palette) return;
                
                const dataId = event.target.closest('[data-id]')?.dataset.id
                const colors = Array.isArray(palette.colors) ? palette.colors : [];
                const activeColor = colors.find(el => el?.id === dataId);
                if (!activeColor) return;

                const hasChildren = colors.some(el => el.shadeParent === activeColor.id)

                const color = event.detail.color.hsla;
                this.updateColor({
                    color: color, 
                    colorId: event.target.dataset.id, 
                    mode: mode,
                    currentPalette: palette,
                    currentColor: activeColor,
                    hasChildren: hasChildren
                });
            }, 10));
        });
    },
    
    _setupScalePicker: function() {
        if (this.colorStates.colorManagerShadePopup === true) {
            this.setScalePicker();
        }
    },
    
    _setupDragAndDrop: function(canvas, activePalette) {
        if (this.colorStates.colorManagerShadePopup === true) return;
        
        const colorWrapper = canvas.querySelector('ul');
        
        new Sortable(colorWrapper, {
            multiDrag: true,
            selectedClass: "sortable-selected",
            animation: 150,
            handle: "li .handle",
            helper: 'clone',
            onMove: function (evt) {
                // Prevent drag if the item does not have data-parent="true"
                return evt.related.hasAttribute('data-parent') && evt.related.getAttribute('data-parent') === "true";
            },
            onEnd: () => {
                const items = Array.from(colorWrapper.children).filter(el => el.dataset.parent === "true");
                let index = 0;
                
                items.forEach((item) => {
                    const target = Array.from(activePalette.colors).find(el => 
                        el && el.hasOwnProperty('id') && el.id === item.dataset.id
                    );
                    
                    if (!target) return;
                    
                    this.helpers.moveArr(activePalette.colors, activePalette.colors.indexOf(target), index);
                    index++;
                    
                    const children = Array.from(activePalette.colors).filter(el => 
                        el.hasOwnProperty('isShade') && el.isShade === true && el.shadeParent === target.id
                    );
                    
                    if (!children || children.length === 0) return;
                    
                    children.forEach(child => {
                        this.helpers.moveArr(activePalette.colors, activePalette.colors.indexOf(child), index);
                        index++;
                    });
                });
                
                this.setColorManager();
                this.helpers.saveChanges('colorPalette');
            },
        });
    },
    _resetPopupStates: function() {
        this.colorStates.colorManagerShadePopup = false;
        this.colorStates.colorManagerShadePopupId = false;
        this.colorStates.colorManagerComplementaryPopup = false;
        this.colorStates.colorManagerComplementaryPopupId = false;
    },
    toggleColorProperty: function(colorId){
        const self = this;
        const palettes = self.vueState.colorPalette;
        const palette = Array.from(palettes).find(el => el && el.hasOwnProperty('id') && el.id == self.colorStates.activePalette);
        if(!palette) return;
        if(!Array.isArray(palette.colors)) palette.colors = [];
        const color = palette.colors.find(el => el && el.hasOwnProperty('id') && el.id === colorId);
        if(!color) return;

        color.colorProperty = color.colorProperty === true ? false : true;
        self.setColorManagerBody();
    },
    toggleLinkShades: function(colorId){
        const self = this;
        const palettes = self.vueState.colorPalette;
        const palette = Array.from(palettes).find(el => el && el.hasOwnProperty('id') && el.id == self.colorStates.activePalette);
        if(!palette) return;
        if(!Array.isArray(palette.colors)) palette.colors = [];
        const color = palette.colors.find(el => el && el.hasOwnProperty('id') && el.id === colorId);
        if(!color || !color.hasOwnProperty('isShade')) return;
        color.isShade === true ? color.isShade = false : color.isShade = true;
        self.setColorManagerBody();
    },
    toggleExpandShades: function(colorId){
        const self = this;
        const palettes = self.vueState.colorPalette;
        const palette = Array.from(palettes).find(el => el && el.hasOwnProperty('id') && el.id == self.colorStates.activePalette);
        if(!palette) return;
        if(!Array.isArray(palette.colors)) palette.colors = [];
        const color = palette.colors.find(el => el && el.hasOwnProperty('id') && el.id === colorId);
        if(!color || !color.hasOwnProperty('isExpanded')) return;
        color.isExpanded === true ? color.isExpanded = false : color.isExpanded = true;
        self.setColorManagerBody();
    },
    toggleImportColorVariables: function(importCSS){
        const self = this;
        importCSS === 'true' ? self.colorStates.colorManagerImportCSSVariables = false : self.colorStates.colorManagerImportCSSVariables = true;
        self.setColorManagerBody();

    },
    importColorVariables: function(){
        const self = this;
        const value = document.querySelector('#addNewColorCSS').value;
        const cssVariablePattern = /(--[\w-]+):\s*([^;]+);/g;
        const parsedValue = value ? value.replaceAll('\n', '') : false;
        if (!parsedValue || parsedValue.length < 1) return;

        const palettes = self.vueState.colorPalette;
        const palette = Array.from(palettes).find(el => el && el.hasOwnProperty('id') && el.id == self.colorStates.activePalette);
        if(!palette) return;
        if(!Array.isArray(palette.colors)) palette.colors = [];

        let incorrectColor = 0;
        let importedColors = 0;

        const matches = parsedValue.match(cssVariablePattern);
        if(!matches || !Array.isArray(matches) || matches.length < 1) return self.vueGlobalProp.$_showMessage(`No Matching Colors found`);

        matches.forEach(match => {
            const matchResult = match.match(cssVariablePattern);
            const split = matchResult[0].split(':');
            const name = split[0].substr(2);
            const value = split[1] ? split[1].trimStart().replaceAll(';', '') : false;
            let newColor = '';
            if (!self.colorStates.colorManagerImportCSSVariablesskipValues && !chroma.valid(value)) return incorrectColor++;

            const formattedName = self.helpers.formatForClasses(name);
            const raw = `var(--${self.helpers.setColorPrefix(formattedName, self.helpers.isFramework(false), palette.prefix)})`;
            const id = self.vueGlobalProp.$_generateId();
            if(self.colorStates.colorManagerImportCSSVariablesskipValues){
                newColor = {
                    id: id,
                    name: formattedName,
                    raw: raw,
                    rawValue: {
                        light: '#fff',
                    },
                    isVariableOnly: true,
                    isExpanded: true,
                    shadeChildren: [],
                    complementaryChildren: [],
                };

            } else {
                const lightness = chroma(value).get('hsl', 'l');
                const colorDark = lightness ? chroma(value).set('hsl.l', 1 - lightness[2]).css('hsla') : false;

                newColor = {
                    id: id,
                    name: formattedName,
                    raw: raw,
                    rawValue: {
                        light: value,
                    },
                    isExpanded: true,
                    shadeChildren: [],
                    complementaryChildren: [],
                };

                colorDark ? (newColor.rawValue.dark = colorDark) : '';
            }
            palette.colors.push(newColor);
            importedColors++;
        });

        
        // Message
        if(importedColors === 0 && incorrectColor > 0){
            self.vueGlobalProp.$_showMessage(`No Matching Colors found<br>${incorrectColor} variables have been skipped due to incorrect color format`);
        } else if(importedColors === 0){
            self.vueGlobalProp.$_showMessage(`No Matching Colors found`);
        } else if(importedColors > 0 && incorrectColor > 0){
            self.vueGlobalProp.$_showMessage(`${importedColors} Colors have been successfully imported<br>${incorrectColor} variables have been skipped due to incorrect color format`);
        } else {
            self.vueGlobalProp.$_showMessage(`${importedColors} Colors have been successfully imported`);
        }

        setTimeout(() => {
            self.setColorManagerSearch();
            self.setColorManagerBody();
            self.generateColorCSS();
            self.generateBuilderCSS();
        }, 10);
    },

    convertColor: function(colorId){
        const self = this;
        const palettes = self.vueState.colorPalette;
        const palette = Array.from(palettes).find(el => el && el.hasOwnProperty('id') && el.id == self.colorStates.activePalette);
        if(!palette) return;
        if(!Array.isArray(palette.colors)) palette.colors = [];
        const obj = palette.colors.find(el => el && el.hasOwnProperty('id') && el.id === colorId);
        
        let col = '';
        ['hex','rgb','hsl'].forEach(format => {
            if(obj.hasOwnProperty(format)){
                col = obj[format];
                delete obj[format];
            }
        })
        obj.name = self.helpers.formatForClasses(obj.name)
        obj.raw = `var(--${self.helpers.setColorPrefix(obj.name, self.helpers.isFramework(obj.id), palette.prefix)})`;
        obj.rawValue = {
            light: col
        }
        obj.isExpanded = true,
        obj.shadeChildren = [],
        obj.complementaryChildren = [],

        self.generateColorCSS();
        self.generateBuilderCSS();
        self.setColorManagerBody();


    },
    convertDarkColor: function(colorId){
        const self = this;
        const palettes = self.vueState.colorPalette;
        const palette = Array.from(palettes).find(el => el && el.hasOwnProperty('id') && el.id == self.colorStates.activePalette);
        if(!palette) return;
        if(!Array.isArray(palette.colors)) palette.colors = [];
        const obj = palette.colors.find(el => el && el.hasOwnProperty('id') && el.id === colorId);

        const lightColor = (obj.hasOwnProperty('rawValue') && obj.rawValue.hasOwnProperty('light')) ? chroma(obj.rawValue.light).get('hsl.l') : false;
        if (lightColor) obj.rawValue.dark = chroma(obj.rawValue.light).set('hsl.l', 1 - lightColor).css('hsla');;

        self.generateColorCSS();
        self.generateBuilderCSS();
        self.setColorManagerBody();
    },
    resetStates: function(){
        const self = this;
        //self.colorStates.colorManagerShadeNumber = 6,
        self.colorStates.colorManagerShadeBaseName = false;
        const mode = self.colorStates.colorManagerMode;
        if (self.colorStates.activeColor.hasOwnProperty('raw') && self.colorStates.activeColor.hasOwnProperty('rawValue') && self.colorStates.activeColor.rawValue.hasOwnProperty(mode)) self.colorStates.colorManagerShadeColors = [self.colorStates.activeColor.rawValue[mode]];
        self.colorStates.colorManagerShadeFinalColors = ['#ffffff'];
    },
    shadesSlider: function(event){
        const self = this;
        self.colorStates.colorManagerShadeNumber = parseInt(event.target.value);;
        self.setDynamicScaleCanvas();
    },
    addPreviousScaleColor: function(){
        const self = this;
        const canvasScale = document.querySelector('#scaleCanvas');
        const canvasPreview = document.querySelector('#previewCanvas');
        if(!canvasScale || !canvasPreview) return;

        self.colorStates.colorManagerShadeColors.unshift(self.colorStates.colorManagerShadeColors[0]);
        canvasScale.innerHTML = self.setColorScale();
        canvasPreview.innerHTML = self.setColorPreview();
        self.setScalePicker();
    },
    addNextScaleColor: function(){
        const self = this;
        const canvasScale = document.querySelector('#scaleCanvas');
        const canvasPreview = document.querySelector('#previewCanvas');
        if(!canvasScale || !canvasPreview) return;

        self.colorStates.colorManagerShadeColors.push(self.colorStates.colorManagerShadeColors[self.colorStates.colorManagerShadeColors.length - 1]);
        canvasScale.innerHTML = self.setColorScale();
        canvasPreview.innerHTML = self.setColorPreview();
        self.setScalePicker();
    },
    setScalePicker: function(){
        const self = this;
        const canvas = document.querySelector('#scaleCanvas');
        if(!canvas) return;
        const btnScales = canvas.querySelectorAll('.scale-color');
        if(!btnScales) return;

        // Picker
        btnScales.forEach(el => {
            let picker = new ColorPicker(el, el.dataset.initialColor);
            el.addEventListener('colorChange', self.debounce((event) => {
                const color = event.detail.color.hsla;
                self.colorStates.colorManagerShadeColors[el.dataset.index] = color;
                const canvasPreview = document.querySelector('#previewCanvas');
                canvasPreview.innerHTML = self.setColorPreview();
            }, 100))
        })

        //Drag and drop
        const scaleWrapper = canvas.querySelector('.scale-wrapper');

        new Sortable(scaleWrapper, {
            animation: 150,
            handle: ".scale-color",
            helper : 'clone',
            onEnd: function (evt) {
                if(evt.oldIndex !== evt.newIndex){
                    self.helpers.moveArr(self.colorStates.colorManagerShadeColors, evt.oldIndex -1, evt.newIndex -1);
                    const canvasPreview = document.querySelector('#previewCanvas');
                    canvasPreview.innerHTML = self.setColorPreview();
                }
            },
        })
    },
    deleteScaleColor: function(btn){
        const self = this;
        const canvasScale = document.querySelector('#scaleCanvas');
        const canvasPreview = document.querySelector('#previewCanvas');
        if(!canvasScale || !canvasPreview) return;

        const index = Array.from(document.querySelectorAll('.brxc-color-input.scale-color')).indexOf(btn)
        self.colorStates.colorManagerShadeColors.splice(index, 1);
        canvasScale.innerHTML = self.setColorScale();
        canvasPreview.innerHTML = self.setColorPreview();
        self.setScalePicker();
    },
    setColorScale: function(){
        const self = this;
        let content = '';
        content += `<div class="control-inner control-inline">`;
        content += `<label class="has-tooltip"><span>Color Scale</span><div data-balloon="Choose the colors that compose the color scale." data-balloon-pos="bottom-left" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>`;
        content += `<div class="scale-wrapper">`;
        content += `<div class="dotted-border" data-balloon="Add previous color" data-balloon-pos="top-left" onclick="ADMINBRXC.addPreviousScaleColor();"><i class="fas fa-plus"></i></div>`;
        index = 0;
        self.colorStates.colorManagerShadeColors.forEach(color => {
            content += `<button class="brxc-color-input scale-color" data-index="${index}" data-initial-color="${color}" style="background:${color};">`;
            if(self.colorStates.colorManagerShadeColors.length > 1) content += `<div class="delete-scale-color" data-balloon="Delete" data-balloon-pos="top" onclick="event.preventDefault();event.stopPropagation();ADMINBRXC.deleteScaleColor(this.parentElement);"><i class="fas fa-xmark"></i></div>`;
            content += `</button>`
            index++;
        })
        content += `<div class="dotted-border" data-balloon="Add next color" data-balloon-pos="top-right" onclick="ADMINBRXC.addNextScaleColor();"><i class="fas fa-plus"></i></div>`;
        content += `</div></div>`;
        return content;

    },
    changeColorScheme: function(){
        const self = this;
        const canvas = document.querySelector('#previewComplementaryCanvas');
        if(!canvas) return;

        canvas.innerHTML = self.setComplementaryColorPreview();
    },
    setColorPreview: function(){
        const self = this;
        const mode = self.colorStates.colorManagerMode;
        
        let content = '';
        content += `<div class="control-inner control-inline">`;
        content += `<label class="has-tooltip"><span>Preview</span><div data-balloon="Here is the preview of the shades that will be created." data-balloon-pos="bottom-left" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>`;
        content += `<div class="color-btn-wrapper">`;
        if (self.colorStates.activeColor.hasOwnProperty('raw') && self.colorStates.activeColor.hasOwnProperty('rawValue') && self.colorStates.activeColor.rawValue.hasOwnProperty(mode)) self.colorStates.colorManagerShadeColors.unshift(self.colorStates.activeColor.rawValue[mode]);
        const colors = chroma.scale(self.colorStates.colorManagerShadeColors)
                            .colors(parseInt(self.colorStates.colorManagerShadeNumber) + 1);
        let ind = 0;
        colors.forEach(color => {
            colors[ind] = chroma(color).css('hsl');
            ind++;
        })
        colors.shift();
        self.colorStates.colorManagerShadeFinalColors = colors;
        self.colorStates.colorManagerShadeColors.shift();
        let index = 0;
        colors.forEach(color => {
            content += `<button class="scale-color" data-index="${index}" data-initial-color="${color}" data-balloon="${color}" data-balloon-pos="top" style="background:${color};"></button>`;
            index++;
        })
        content += `</div></div>`;
        return content;
    },
    setDynamicScaleCanvas: function(){
        const self = this;
        const canvas = document.querySelector('#dynamicScaleCanvas');
        if(!canvas) return;

        canvas.innerHTML = self.dynamicScaleCanvas(self.colorStates.activeColor.id);
        self.setScalePicker();
    },
    dynamicScaleCanvas: function(colorId){
        const self = this;
        const palettes = self.vueState.colorPalette;
        const palette = Array.from(palettes).find(el => el && el.hasOwnProperty('id') && el.id == self.colorStates.activePalette);
        if(!palette) return '';
        if(!Array.isArray(palette.colors)) palette.colors = [];
        const color = palette.colors.find(el => el && el.hasOwnProperty('id') && el.id === colorId);
        let content = `<div class="brxc-overlay__panel-inline-btns-wrapper" style="margin-top:16px;">
                            <input type="radio" id="brxc-custom-shade-toggle-auto" name="brxc-custom-shade-toggle" class="brxc-input__checkbox" value="0" onclick="ADMINBRXC.colorStates.colorManagerShadeCustom = false;ADMINBRXC.colorStates.colorManagerShadePopup = true;ADMINBRXC.colorStates.colorManagerShadePopupId = '${colorId}';ADMINBRXC.setDynamicScaleCanvas();"${self.colorStates.colorManagerShadeCustom !== true ? ' checked=""' : ''}>
                            <label for="brxc-custom-shade-toggle-auto" class="brxc-overlay__panel-inline-btns">Auto-Shades</label>
                            <input type="radio" id="brxc-custom-shade-toggle-custom" name="brxc-custom-shade-toggle" class="brxc-input__checkbox" value="1" onclick="ADMINBRXC.colorStates.colorManagerShadeCustom = true;ADMINBRXC.colorStates.colorManagerShadePopup = true;ADMINBRXC.colorStates.colorManagerShadePopupId = '${colorId}';ADMINBRXC.setDynamicScaleCanvas();"${self.colorStates.colorManagerShadeCustom === true ? ' checked=""' : ''}>
                            <label for="brxc-custom-shade-toggle-custom" class="brxc-overlay__panel-inline-btns">Custom Scales</label>
                        </div>`;
        if(self.colorStates.colorManagerShadeCustom !== true){
            let showButton = false;
            const children = Array.from(palette.colors || []).filter(el => el && el.hasOwnProperty('shadeParent') && el.shadeParent === colorId);
            const lightChildren = children && children.length > 0 ? Array.from(children).filter(el => el && el.hasOwnProperty('shadeType') && el.shadeType === "Light") : false;
            const darkChildren = children && children.length > 0 ? Array.from(children).filter(el => el && el.hasOwnProperty('shadeType') && el.shadeType === "Dark") : false;
            const transparentChildren = children && children.length > 0 ? Array.from(children).filter(el => el && el.hasOwnProperty('shadeType') && el.shadeType === "Transparent") : false;
            
            // Light
            if(!lightChildren || lightChildren.length === 0){
                self.colorStates.colorManagerShadeLightValid = true;
                const lightEnabled = self.colorStates.colorManagerShadeLight;
                showButton = true;
                    content += `<div class="control-inner control-inline">
                                    <label class="has-tooltip"><span>Generate Light Shades<div data-balloon="Generate lighter versions of the current color. The script will generate the shades up to 95% of the color's lightness." data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></span></label>
                                    <div class="" onclick="ADMINBRXC.toggleAutoShade('Light')"><i class="fas fa-toggle-${lightEnabled ? 'on' : 'off'}"></i></div>
                                </div>`;
                if(lightEnabled){
                    content += self.setAutoShadePreview('Light');
                }
            } else {
                self.colorStates.colorManagerShadeLightValid = false;
                self.colorStates.colorManagerShadeLight = true;
                    content += `<div class="control-inner control-inline">
                                    <label class="has-tooltip"><span>Generate Light Shades</span><div data-balloon="Generate lighter versions of the current color. The script will generate the shades up to 95% of the color's lightness." data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>
                                    <div><i class="fas fa-toggle-off"></i></div>
                                </div>
                                <div><span class="existing-shades-message">Light shades have already been generated for this color. Remove the existing shades to generate new ones.</span></div>`;                
            }

            // Dark

            if(!darkChildren|| darkChildren.length === 0){
                self.colorStates.colorManagerShadeDarkValid = true;
                const darkEnabled = self.colorStates.colorManagerShadeDark;
                showButton = true;
                    content += `<div class="control-inner control-inline">
                                    <label class="has-tooltip"><span>Generate Dark Shades</span><div data-balloon="Generate darker versions of the current color. The script will generate the shades up to 5% of the color's lightness." data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>
                                    <div class="" onclick="ADMINBRXC.toggleAutoShade('Dark')"><i class="fas fa-toggle-${darkEnabled ? 'on' : 'off'}"></i></div>
                                </div>`;
                if(darkEnabled){
                    content += self.setAutoShadePreview('Dark');
                }
            } else {
                self.colorStates.colorManagerShadeDarkValid = false;
                self.colorStates.colorManagerShadeDark = true;
                    content += `<div class="control-inner control-inline">
                                    <label class="has-tooltip"><span>Generate Dark Shades</span><div data-balloon="Generate darker versions of the current color. The script will generate the shades up to 5% of the color's lightness." data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>
                                    <div><i class="fas fa-toggle-off"></i></div>
                                </div>
                                <div><span class="existing-shades-message">Dark shades have already been generated for this color. Remove the existing shades to generate new ones.</span></div>`;    
            }

            if(!transparentChildren || transparentChildren.length === 0){
                self.colorStates.colorManagerShadeTransparentValid = true;
                const transparentEnabled = self.colorStates.colorManagerShadeTransparent;
                showButton = true;
                    content += `<div class="control-inner control-inline">
                                    <label class="has-tooltip"><span>Generate Transparent Shades</span><div data-balloon="Generate transparent versions of the current color. The script will generate the shades up to 5% of the color's transparency." data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>
                                    <div class="" onclick="ADMINBRXC.toggleAutoShade('Transparent')"><i class="fas fa-toggle-${transparentEnabled ? 'on' : 'off'}"></i></div>
                                </div>`;
                if(transparentEnabled){
                    content += self.setAutoShadePreview('Transparent');
                }
            } else {
                self.colorStates.colorManagerShadeTransparentValid = false;
                self.colorStates.colorManagerShadeTransparent = true;
                    content += `<div class="control-inner control-inline">
                                    <label class="has-tooltip"><span>Generate Transparent Shades</span><div data-balloon="Generate transparent versions of the current color. The script will generate the shades up to 5% of the color's transparency." data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>
                                    <div><i class="fas fa-toggle-off"></i></div>
                                </div>
                                <div><span class="existing-shades-message">Transparent shades have already been generated for this color. Remove the existing shades to generate new ones.</span></div>`;
            }
            content += showButton ? `<a class="brxc-overlay__action-btn primary" style="margin-top:16px;" onclick="ADMINBRXC.generateShades('${color.id}');"><span>Generate Shades</span></a>` : '';
            
        } else {
            const children = Array.from(palette.colors || []).filter(el => el && el.hasOwnProperty('shadeParent') && el.shadeParent === colorId);
            const customChildren = children && children.length > 0 ? Array.from(children).filter(el => el && el.hasOwnProperty('shadeMode') && el.shadeMode === "custom") : false;

            if(!customChildren || customChildren.length === 0){
                    content += `<div class="control-inner control-inline">
                                <label class="has-tooltip"><span>Base Name</span><div data-balloon="For example, the base name of 'primary-l-1' is 'primary-l-'" data-balloon-pos="bottom-left" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>
                                <input id="nameInput" type="text" value="${self.helpers.getColorName(color, palette.prefix)}-" oninput="ADMINBRXC.colorStates.colorManagerShadeBaseName = event.target.value;">
                            </div>`;
                    content += `<div id="scaleCanvas">${self.setColorScale()}</div>`;
                    content += `<div id="previewCanvas">${self.setColorPreview(color.id)}</div>`;
                    content += `<a class="brxc-overlay__action-btn primary" style="margin-top:16px;" onclick="ADMINBRXC.generateShades('${color.id}');"><span>Generate Scale</span></a>`;
            } else {
                    content += `<div><span class="existing-shades-message">A custom scale has already been generated for this color. Remove the existing scale to generate new ones.</span></div>`;
            }
        }
        return content;
    },
    setShadesForm: function(colorId){
        const self = this;
        const palettes = self.vueState.colorPalette;
        const palette = Array.from(palettes).find(el => el && el.hasOwnProperty('id') && el.id == self.colorStates.activePalette);
        if(!palette) return;
        if(!Array.isArray(palette.colors)) palette.colors = [];
        const color = palette.colors.find(el => el && el.hasOwnProperty('id') && el.id === colorId);

        let content = `<div class="shade-form">`;
        content += `<div class="brxc-shade-wrapper bricks-control-popup bottom">
                        <div class="control-inner control-inline">
                            <label for="numberShades" class="has-tooltip"><span>Num Shades</span><div data-balloon="The number of shades you want to create." data-balloon-pos="bottom-left" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>
                            <div class="brxc__range">
                                <input type="range" min="2" max="20" step="1" value="${self.colorStates.colorManagerShadeNumber}" name="numberShades" id="numberShades" class="brxc-input__range" oninput="ADMINBRXC.shadesSlider(event);document.querySelector('#numberShadesValue').value = parseInt(event.target.value);">
                                <input type="number" min="2" max="20" id="numberShadesValue" value="${self.colorStates.colorManagerShadeNumber}" oninput="ADMINBRXC.shadesSlider(event);document.querySelector('#numberShades').value = parseInt(event.target.value);">
                            </div>
                        </div>
                        <div id="dynamicScaleCanvas">${self.dynamicScaleCanvas(colorId)}</div>`;
        content += `</div></div>`;

        return content;

    },
    toggleAutoShade: function(mode){
        const self = this;
        if(mode === "Light"){
            self.colorStates.colorManagerShadeLight === true ? self.colorStates.colorManagerShadeLight = false : self.colorStates.colorManagerShadeLight = true;
        } else if(mode === "Dark"){
            self.colorStates.colorManagerShadeDark === true ? self.colorStates.colorManagerShadeDark = false : self.colorStates.colorManagerShadeDark = true;
        } else if(mode === "Transparent"){
            self.colorStates.colorManagerShadeTransparent === true ? self.colorStates.colorManagerShadeTransparent = false : self.colorStates.colorManagerShadeTransparent = true;
        }
        self.setDynamicScaleCanvas();
    },
    setAutoShadePreview: function(mode){
        const self = this;
        const activeColor = self.colorStates.activeColor.rawValue.light;
        let targetColor;
        if(mode === 'Light') targetColor = chroma(activeColor).set('hsl.l', 0.98).css('hsla');
        if(mode === 'Dark') targetColor = chroma(activeColor).set('hsl.l', 0.05).css('hsla');
        if(mode === 'Transparent') targetColor = chroma(activeColor).alpha(0.05).css('hsla');
        const colors = chroma.scale([activeColor, targetColor])
                        .correctLightness()
                        .colors(parseInt(self.colorStates.colorManagerShadeNumber) + 1);
        let ind = 0;
        colors.forEach(color => {
            colors[ind] = chroma(color).css('hsla');
            ind++;
        })
        colors.shift();
        let content = `<div class="control-inner control-inline">
                            <label class="has-tooltip"><span>Preview ${mode} Shades</span><div data-balloon="Here is the preview of the shades that will be created." data-balloon-pos="bottom-left" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>
                            <div class="color-btn-wrapper">`;
                            colors.forEach(el => {
                                content += `<button class="scale-color" data-index="0" data-initial-color="${el}" data-balloon="${el}" data-balloon-pos="top" style="background:${el};"></button>`;
                            })
        content += `</div></div>`;
        return content;
    },
    setComplementaryColorPreview: function(){
        const self = this;
        const mode = self.colorStates.colorManagerMode;
        const activeColor = (self.colorStates.activeColor.hasOwnProperty('raw') && self.colorStates.activeColor.hasOwnProperty('rawValue') && self.colorStates.activeColor.rawValue.hasOwnProperty(mode)) ? self.colorStates.activeColor.rawValue[mode] : false;
        if(!activeColor) return;
        const hue = parseInt(chroma(activeColor).get('hsl', 'h'))

        let content = '';
        content += `<div class="control-inner control-inline">`;
        content += `<label class="has-tooltip"><span>Preview</span><div data-balloon="Here is the preview of the complementary colors that will be created." data-balloon-pos="bottom-left" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>`;
        content += `<div class="color-btn-wrapper">`;
    
        self.colorStates.colorManagerComplementaryFinalColors = [];

        // Contrast
        if(self.colorStates.colorManagerComplementaryScheme === 'complementary'){
            self.colorStates.colorManagerComplementaryFinalColors.push(chroma(activeColor).set('hsl.h', hue + 180).css('hsla'));
        }

        // Split-Complementary
        if(self.colorStates.colorManagerComplementaryScheme === 'split-complementary'){
            self.colorStates.colorManagerComplementaryFinalColors.push(chroma(activeColor).set('hsl.h', hue + 150).css('hsla'));
            self.colorStates.colorManagerComplementaryFinalColors.push(chroma(activeColor).set('hsl.h', hue + 210).css('hsla'));
        }

        // Triade
        if(self.colorStates.colorManagerComplementaryScheme === 'triade'){
            self.colorStates.colorManagerComplementaryFinalColors.push(chroma(activeColor).set('hsl.h', hue + 120).css('hsla'));
            self.colorStates.colorManagerComplementaryFinalColors.push(chroma(activeColor).set('hsl.h', hue + 240).css('hsla'));
        }

        // Tetrade
        if(self.colorStates.colorManagerComplementaryScheme === 'tetrade'){
            self.colorStates.colorManagerComplementaryFinalColors.push(chroma(activeColor).set('hsl.h', hue + 90).css('hsla'));
            self.colorStates.colorManagerComplementaryFinalColors.push(chroma(activeColor).set('hsl.h', hue + 180).css('hsla'));
            self.colorStates.colorManagerComplementaryFinalColors.push(chroma(activeColor).set('hsl.h', hue + 270).css('hsla'));
        }

        // Split-Tetradic
        if(self.colorStates.colorManagerComplementaryScheme === 'split-tetradic'){
            self.colorStates.colorManagerComplementaryFinalColors.push(chroma(activeColor).set('hsl.h', hue + 60).css('hsla'));
            self.colorStates.colorManagerComplementaryFinalColors.push(chroma(activeColor).set('hsl.h', hue + 180).css('hsla'));
            self.colorStates.colorManagerComplementaryFinalColors.push(chroma(activeColor).set('hsl.h', hue + 240).css('hsla'));
        }

        // Quadratic
        if(self.colorStates.colorManagerComplementaryScheme === 'quadratic'){
            self.colorStates.colorManagerComplementaryFinalColors.push(chroma(activeColor).set('hsl.h', hue + 120).css('hsla'));
            self.colorStates.colorManagerComplementaryFinalColors.push(chroma(activeColor).set('hsl.h', hue + 240).css('hsla'));
            self.colorStates.colorManagerComplementaryFinalColors.push(chroma(activeColor).set('hsl.h', hue + 300).css('hsla'));
        }

        // Compound
        if(self.colorStates.colorManagerComplementaryScheme === 'compound'){
            self.colorStates.colorManagerComplementaryFinalColors.push(chroma(activeColor).set('hsl.h', hue + 60).css('hsla'));
            self.colorStates.colorManagerComplementaryFinalColors.push(chroma(activeColor).set('hsl.h', hue + 180).css('hsla'));
            self.colorStates.colorManagerComplementaryFinalColors.push(chroma(activeColor).set('hsl.h', hue + 300).css('hsla'));
        }

        // Analogous
        if(self.colorStates.colorManagerComplementaryScheme === 'analogous'){
            self.colorStates.colorManagerComplementaryFinalColors.push(chroma(activeColor).set('hsl.h', hue + 30).css('hsla'));
            self.colorStates.colorManagerComplementaryFinalColors.push(chroma(activeColor).set('hsl.h', hue + 60).css('hsla'));
            self.colorStates.colorManagerComplementaryFinalColors.push(chroma(activeColor).set('hsl.h', hue + 90).css('hsla'));
        }

        // Split-Analogous
        if(self.colorStates.colorManagerComplementaryScheme === 'split-analogous'){
            self.colorStates.colorManagerComplementaryFinalColors.push(chroma(activeColor).set('hsl.h', hue + 30).css('hsla'));
            self.colorStates.colorManagerComplementaryFinalColors.push(chroma(activeColor).set('hsl.h', hue + 60).css('hsla'));
            self.colorStates.colorManagerComplementaryFinalColors.push(chroma(activeColor).set('hsl.h', hue + 150).css('hsla'));
        }

        self.colorStates.colorManagerComplementaryFinalColors.forEach(color => {
            content += `<button class="scale-color" data-initial-color="${color}" data-balloon="${color}" data-balloon-pos="top" style="background:${color};"></button>`;
        })
        content += `</div></div>`;
        return content;
    },
    setComplementaryForm: function(colorId){
        const self = this;
        const palettes = self.vueState.colorPalette;
        const palette = Array.from(palettes).find(el => el && el.hasOwnProperty('id') && el.id == self.colorStates.activePalette);
        if(!palette) return;
        if(!Array.isArray(palette.colors)) palette.colors = [];
        const color = palette.colors.find(el => el && el.hasOwnProperty('id') && el.id === colorId);

        const options = [
            { value: 'complementary', label: 'Complementary' },
            { value: 'split-complementary', label: 'Split-Complementary' },
            { value: 'triade', label: 'Perfect Triad' },
            { value: 'tetrade', label: 'Tetrade' },
            { value: 'split-tetradic', label: 'Split-Tetradic' },
            { value: 'quadratic', label: 'Quadratic' },
            { value: 'compound', label: 'Compound' },
            { value: 'analogous', label: 'Analogous' },
            { value: 'split-analogous', label: 'Split-Analogous' },
        ];

        let content = `<div class="complementary-form">`;
        content += `<div class="brxc-shade-wrapper bricks-control-popup bottom">
                        <div class="control-inner control-inline">
                            <label class="has-tooltip"><span>Base Name</span><div data-balloon="For example, the base name of 'primary-l-1' is 'primary-l-'" data-balloon-pos="bottom-left" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>
                            <input id="nameInput" type="text" value="${self.helpers.getColorName(color, palette.prefix)}-" oninput="ADMINBRXC.colorStates.colorManagerComplementaryBaseName = event.target.value;">
                        </div>
                        <div class="control-inner control-inline">
                            <label for="Scheme" class="has-tooltip"><span>Scheme</span><div data-balloon="The color scheme you want to create." data-balloon-pos="bottom-left" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>
                            <div class="brxc-select">
                                <div class="brxc-select-new rounded hidden" name="Scheme" id="brxcScheme" data-id="${colorId}">
                                    <div class="brxc-select-new__wrapper">
                                        ${options.map(opt => {
                                            return `<div data-value="${opt.value}"${self.colorStates.colorManagerComplementaryScheme === opt.value ? ' class="active"' : ''}><span>${opt.label}</span></div>`;
                                        }).join('')}
                                    </div>
                                </div>
                            </div>
                        </div>`;
        content += `<div id="previewComplementaryCanvas">${self.setComplementaryColorPreview(color.id)}</div>`;
        content += `<a class="brxc-overlay__action-btn primary" style="margin-top:16px;" onclick="ADMINBRXC.generateComplementary('${color.id}');"><span>Generate Colors</span></a>`;
        content += `</div></div>`;

        return content;

    },
    generateShades: function(colorId){
        const self = this;
        if(self.colorStates.colorManagerShadeCustom === true){
            self.generateCustomShades(colorId);
        } else {
            self.generateAutoShades(colorId);
        }
    },
    generateCustomShades: function(colorId){
        const self = this;
        const palettes = self.vueState.colorPalette;
        const palette = Array.from(palettes).find(el => el && el.hasOwnProperty('id') && el.id == self.colorStates.activePalette);
        if(!palette) return;
        if(!Array.isArray(palette.colors)) palette.colors = [];
        const color = Array.from(palette.colors).find(el => el && el.hasOwnProperty('id') && el.id === colorId);

        if(!color) return;

        let colorOrder = parseInt(palette.colors.indexOf(color));

        color.shadeArray = self.colorStates.colorManagerShadeColors;
        const colorName = self.helpers.getColorName(color, palette.prefix);
        self.colorStates.colorManagerShadeFinalColors.forEach((el,index) => {
            function setSufix(name, number){
                const exist = Array.from(palette.colors || []).find(el => el && self.helpers.getColorName(el, palette.prefix) === `${name}${number}`);
                if(!exist) return `${name}${number}`;
                number++;
                return setSufix(name, number);
            }
            const lightness = chroma(el).get('hsl', 'l');
            const elDark = chroma(el).set('hsl.l', 1 - lightness[2]).css('hsla');
            let name = (self.colorStates.colorManagerShadeBaseName) ? self.colorStates.colorManagerShadeBaseName : `${colorName}-`;
            name = setSufix(self.helpers.formatForClasses(name), 1);
            const id = self.vueGlobalProp.$_generateId();
            const raw = `var(--${self.helpers.setColorPrefix(name, self.helpers.isFramework(color.id), palette.prefix)})`;
            const newColor = {
                id: id,
                name: name,
                raw: raw,
                rawValue: {
                    light: el,
                    dark: elDark
                },
                isShade: true,
                shadeMode: 'custom',
                shadeParent: colorId,
                shadeOrder: index,
            }
            if(color.hasOwnProperty('colorProperty') && color.colorProperty === true) newColor.colorProperty = true;
            if(color.hasOwnProperty('shadeChildren') && Array.isArray(color.shadeChildren)) color.shadeChildren.push(id);

            palette.colors.push(newColor);
            self.helpers.moveArr(palette.colors, palette.colors.length - 1, colorOrder + 1, 1);
            setTimeout(()=> {
                self.setColorManagerSearch();
                self.setColorManagerBody();
            },10)

            colorOrder++;

        })
        self.generateColorCSS();
        self.generateBuilderCSS();
    },
    generateAutoShades: function(colorId){
        const self = this;
        const palettes = self.vueState.colorPalette;
        const palette = Array.from(palettes).find(el => el && el.hasOwnProperty('id') && el.id == self.colorStates.activePalette);
        if(!palette) return;
        if(!Array.isArray(palette.colors)) palette.colors = [];
        const color = palette.colors.find(el => el && el.hasOwnProperty('id') && el.id === colorId);
        let colorOrder = parseInt(palette.colors.indexOf(color));
        const activeColor = self.colorStates.activeColor.rawValue.light;
        let targetColor;

        function createScale(mode){
            if(mode === 'Light') targetColor = chroma(activeColor).set('hsl.l', 0.98).css('hsla');
            if(mode === 'Dark') targetColor = chroma(activeColor).set('hsl.l', 0.05).css('hsla');
            if(mode === 'Transparent') targetColor = chroma(activeColor).alpha(0.05).css('hsla');
            const colors = chroma.scale([activeColor, targetColor])
                                .correctLightness()
                                .colors(parseInt(self.colorStates.colorManagerShadeNumber) + 1);
            let ind = 0;
            colors.forEach(color => {
                colors[ind] = chroma(color).css('hsla');
                ind++;
            })
            colors.shift();
            return colors;
        }
        
        const modes = [];
        if(self.colorStates.colorManagerShadeLight === true && self.colorStates.colorManagerShadeLightValid === true) modes.push('Light');
        if(self.colorStates.colorManagerShadeDark === true && self.colorStates.colorManagerShadeDarkValid === true) modes.push('Dark');
        if(self.colorStates.colorManagerShadeTransparent === true && self.colorStates.colorManagerShadeTransparentValid === true) modes.push('Transparent')

        const autoColorName = self.helpers.getColorName(color, palette.prefix);
        modes.forEach(mode => {
            const colors = createScale(mode);
            const suffix = `-${mode[0].toLowerCase()}-`
            colors.forEach((el, index) => {

                function setSufix(name, number){
                    const exist = Array.from(palette.colors || []).find(el => el && self.helpers.getColorName(el, palette.prefix) === `${name}${number}`);
                    if(!exist) return `${name}${number}`;
                    number++;
                    return setSufix(name, number);
                }
                const lightness = chroma(el).get('hsl', 'l');
                const elDark = chroma(el).set('hsl.l', 1 - lightness[2]).css('hsla');
                const name = setSufix(self.helpers.formatForClasses(`${autoColorName}${suffix}`), 1);
                const raw = `var(--${self.helpers.setColorPrefix(name, self.helpers.isFramework(color.id), palette.prefix)})`;
                const id = self.vueGlobalProp.$_generateId();
                const newColor = {
                    id: id,
                    name: name,
                    raw: raw,
                    rawValue: {
                        light: el,
                        dark: elDark
                    },
                    isShade: true,
                    shadeMode: 'auto',
                    shadeType: mode,
                    shadeParent: colorId,
                    shadeOrder: index,
                }

                if(color.hasOwnProperty('colorProperty') && color.colorProperty === true) newColor.colorProperty = true;
                if(color.hasOwnProperty('shadeChildren') && Array.isArray(color.shadeChildren)) color.shadeChildren.push(id);

                palette.colors.push(newColor);
                self.helpers.moveArr(palette.colors, palette.colors.length - 1, colorOrder + 1, 1);
                colorOrder++;
    
            })
        })

        setTimeout(()=> {
            self.setColorManagerSearch();
            self.setColorManagerBody();
            self.generateColorCSS();
            self.generateBuilderCSS();
        },10)
    },
    generateComplementary: function(colorId){
        const self = this;
        const palettes = self.vueState.colorPalette;
        const palette = Array.from(palettes).find(el => el && el.hasOwnProperty('id') && el.id == self.colorStates.activePalette);
        if(!palette) return;
        if(!Array.isArray(palette.colors)) palette.colors = [];
        const color = palette.colors.find(el => el && el.hasOwnProperty('id') && el.id === colorId);
        let colorOrder = parseInt(palette.colors.indexOf(color));

        const compColorName = self.helpers.getColorName(color, palette.prefix);
        self.colorStates.colorManagerComplementaryFinalColors.forEach((el,index) => {
            function setSufix(name, number){
                const exist = Array.from(palette.colors || []).find(el => el && self.helpers.getColorName(el, palette.prefix) === `${name}${number}`);
                if(!exist) return `${name}${number}`;
                number++;
                return setSufix(name, number);
            }
            const lightness = chroma(el).get('hsl', 'l');
            const elDark = chroma(el).set('hsl.l', 1 - lightness[2]).css('hsla');
            let name = (self.colorStates.colorManagerComplementaryBaseName) ? self.colorStates.colorManagerComplementaryBaseName : `${compColorName}-`;
            name = setSufix(self.helpers.formatForClasses(name), 1);
            const raw = `var(--${self.helpers.setColorPrefix(name, self.helpers.isFramework(color.id), palette.prefix)})`;
            const id = self.vueGlobalProp.$_generateId();
            const newColor = {
                id: id,
                name: name,
                raw: raw,
                rawValue: {
                    light: el,
                    dark: elDark
                },
                isComplementary: true,
                complementaryParent: colorId,
                complementaryOrder: index,
                shadeChildren: [],
                isExpanded: true,
            }
            if(color.hasOwnProperty('complementaryChildren') && Array.isArray(color.complementaryChildren)) color.complementaryChildren.push(id);

            palette.colors.push(newColor);
            self.helpers.moveArr(palette.colors, palette.colors.length - 1, colorOrder + 1, 1);
            setTimeout(()=> {
                self.setColorManagerSearch();
                self.setColorManagerBody();
            },10)

            colorOrder++;

        })
        self.generateColorCSS();
        self.generateBuilderCSS();
    },
    setShadesWrapper: function(popup, colorId){
        const self = this;
        if(popup === 'true' && self.colorStates.colorManagerShadePopupLastId === colorId) return self.setColorManagerBody();
        self.colorStates.colorManagerShadePopup = true;
        self.colorStates.colorManagerShadePopupId = colorId;
        self.colorStates.colorManagerShadePopupLastId = colorId;
        self.setColorManagerBody();


    },
    setComplementaryWrapper: function(popup, colorId){
        const self = this;
        if(popup === 'true' && self.colorStates.colorManagerComplementaryPopupLastId === colorId) return self.setColorManagerBody();
        self.colorStates.colorManagerComplementaryPopup = true;
        self.colorStates.colorManagerComplementaryPopupId = colorId;
        self.colorStates.colorManagerComplementaryPopupLastId = colorId;
        self.setColorManagerBody();


    },
    renameColor: function(event, colorId, initial){
        const self = this;
        const palettes = self.vueState.colorPalette;
        const input = event.target.parentElement.previousElementSibling;
        input.classList.add('editable');
        const end = input.value.length; 
        input.setSelectionRange(end, end);
        input.focus();

        function renameColor(color, oldName, newName, palette){
            const currentName = self.helpers.getColorName(color, palette.prefix);
            if(currentName.includes(oldName)){
                color.name = currentName.replaceAll(oldName, newName);
                color.raw = `var(--${self.helpers.setColorPrefix(self.helpers.formatForClasses(color.name), false, palette.prefix)})`;
            }
        }

        function saveName(input){
            if (input.value === initial || input.value === '') return self.setColorManagerBody();
            const palette = Array.from(palettes).find(el => el && el.hasOwnProperty('id') && el.id == self.colorStates.activePalette);
            if(!palette) return;
            if(!Array.isArray(palette.colors)) palette.colors = [];
            const color = palette.colors.find(el => el && el.hasOwnProperty('id') && el.id === colorId);
            const oldName = self.helpers.getColorName(color, palette.prefix);

            // Rename Shades
            if(color.hasOwnProperty('shadeChildren') && Array.isArray(color.shadeChildren) && color.shadeChildren.length > 0){
                color.shadeChildren.forEach(shade => {
                    const color = Array.from(palette.colors || []).find(el => el && el.hasOwnProperty('id') && el.id === shade);
                    if(!color) return;
                    renameColor(color, oldName, input.value, palette);

                })
            }

            // Change current color
            color.name = input.value;
            color.raw = `var(--${self.helpers.setColorPrefix(self.helpers.formatForClasses(input.value), false, palette.prefix)})`;
            

            // Remove input
            input.classList.remove('editable');
            input.blur();

            // Regenerate CSS
            self.generateColorCSS();
            self.generateBuilderCSS();
            self.setColorManagerBody();
            self.vueGlobalProp.$_showMessage('Color(s) correctly renamed!');
        }

        input.addEventListener("blur", () =>{
            saveName(input);
        })
        input.addEventListener("keydown", (event) =>{
            if(event.key === "Enter"){
                saveName(input);
            }
        })
    },
    addNewColor: function(event){
        if(event.key !== "Enter") return;
        const self = this;
        const palettes = self.vueState.colorPalette;
        const palette = Array.from(palettes).find(el => el && el.hasOwnProperty('id') && el.id == self.colorStates.activePalette);
        if(!palette) return;
        if(!Array.isArray(palette.colors)) palette.colors = [];
        const name = event.target.value;
        const id = self.vueGlobalProp.$_generateId();
        const raw = `var(--${self.helpers.setColorPrefix(self.helpers.formatForClasses(name), false, palette.prefix)})`;
        function createColor(){
            const newColor = {
                id: id,
                name: name,
                raw: raw,
                rawValue: {
                    light: "#ffffff",
                    dark: "#000000",
                },
                complementaryChildren: [],
                shadeChildren: [],
                isExpanded: true,
            }
            palette.colors.push(newColor);

            self.vueGlobalProp.$_showMessage(`Color ${name} correctly created!`);
            self.setColorManagerSearch();
            self.setColorManagerBody();
        }
        createColor();
        self.generateColorCSS();
        self.generateBuilderCSS();

    },
    setDeleteColor: function(colorId,target){
        const oldContent = target.innerHTML;
        const oldBalloon = target.dataset.balloon;
        const oldFunction = `ADMINBRXC.setDeleteColor('${colorId}',this)`;
        const newContent = '<span class="bricks-svg-wrapper"><i class="fas fa-check"></i></span>';
        const newBalloon = 'Confirm?';
        const newFunction = `ADMINBRXC.deleteColor('${colorId}')`;

        target.setAttribute("onClick", newFunction);
        target.setAttribute("data-balloon", newBalloon);
        target.innerHTML = newContent;
        setTimeout(() => {
            target.setAttribute("onClick", oldFunction);
            target.setAttribute("data-balloon", oldBalloon);
            target.innerHTML = oldContent;
        }, 2000)
    },
    deleteColor: function(colorId){
        const self = this;
        const palettes = self.vueState.colorPalette;
        const palette = Array.from(palettes).find(el => el && el.hasOwnProperty('id') && el.id == self.colorStates.activePalette);
        if(!palette) return;
        if(!Array.isArray(palette.colors)) palette.colors = [];
        const color = palette.colors.find(el => el && el.hasOwnProperty('id') && el.id === colorId);
        if(!color) return;

        // Remove Shade from parent
        if(color.hasOwnProperty('shadeParent')){
            const parent = Array.from(palette.colors || []).find(el => el && el.hasOwnProperty('id') && el.id === color.shadeParent);
            if(parent && parent.hasOwnProperty('shadeChildren') && Array.isArray(parent.shadeChildren) && parent.shadeChildren.length > 0){
                const index = parseInt(parent.shadeChildren.indexOf(colorId));
                if(index !== -1) {
                    parent.shadeChildren.splice(index, 1);
                }
            }
        }

        function deleteColor(color){
            const index = palette.colors.indexOf(color)
            palette.colors.splice(index,1);
        }
        
        function deleteShadesRecursive(color) {
            const children = palette.colors.filter(el => el.shadeParent === color.id);
        
            for (const child of children) {
                deleteShadesRecursive(child);
                deleteColor(child);
            }
        }
        // Delete Shades
        deleteShadesRecursive(color);

        // Delete color
        deleteColor(color);

        // Regenerate CSS
        self.generateColorCSS();
        self.generateBuilderCSS();

        setTimeout(()=> {
            self.setColorManagerSearch();
            self.setColorManagerBody();
        },10)

    },
    removeRawValue: function(colorId){
        const self = this;
        const palettes = self.vueState.colorPalette;
        const palette = Array.from(palettes).find(el => el && el.hasOwnProperty('id') && el.id == self.colorStates.activePalette);
        if(!palette) return;
        if(!Array.isArray(palette.colors)) palette.colors = [];
        const color = palette.colors.find(el => el && el.hasOwnProperty('id') && el.id === colorId);
        if (color.hasOwnProperty('rawValue')) delete color.rawValue;
        self.generateColorCSS();
        self.generateBuilderCSS();
        setTimeout(()=> {
            self.setColorManagerBody();
        },10)
    },
    duplicateColor: function (colorId) {
        const self = this;
        const palette = self.vueState.colorPalette.find(p => p?.id === self.colorStates.activePalette);
        if (!palette) return;
        if(!Array.isArray(palette.colors)) palette.colors = [];

        const originalColor = palette.colors.find(c => c?.id === colorId);
        if (!originalColor) return;
    
        const originalChildren = palette.colors.filter(c => c.shadeParent === colorId);
        const insertIndex = originalChildren.length === 0
            ? palette.colors.indexOf(originalColor) + 1
            : palette.colors.indexOf(originalColor) + originalChildren.length + 1
    
        const idMap = new Map(); // map oldId => newId
    
        function cloneColor(color, index, parentId = null) {
            const newId = self.vueGlobalProp.$_generateId();
            idMap.set(color.id, newId);
    
            const name = `(Copy) ${self.helpers.getColorName(color, palette.prefix)}`;
            const newColor = {
                ...color,
                id: newId,
                name,
                raw: `var(--${self.helpers.setColorPrefix(self.helpers.formatForClasses(name), false, palette.prefix)})`,
                rawValue: JSON.parse(JSON.stringify(color.rawValue))
            };
    
            // Conditionally copy shadeParent only if it exists in original
            if ('shadeParent' in color && parentId) {
                newColor.shadeParent = parentId;
            }
    
            delete newColor.at_framework;
            delete newColor.at_version;
    
            palette.colors.push(newColor);

            
            self.helpers.moveArr(
                palette.colors,
                palette.colors.length - 1,
                index,
                1
            );
            return newColor;
        }
        let index = insertIndex
        const duplicatedParent = cloneColor(originalColor, index);
    
        function duplicateShades(parentColor, originalParentId) {
            const children = palette.colors.filter(c => c.shadeParent === originalParentId);
            for (const child of children) {
                index++;
                const duplicatedChild = cloneColor(child, index, parentColor.id);
                if ('shadeChildren' in parentColor) {
                    parentColor.shadeChildren.push(duplicatedChild.id);
                }
                duplicateShades(duplicatedChild, child.id); // recurse
            }
        }
    
        duplicateShades(duplicatedParent, originalColor.id);
    
        setTimeout(() => {
            self.setColorManagerSearch();
            self.setColorManagerBody();
        }, 10);
    },
    // Helpers
    _colorCreateScale: function(scaleMode, numShades, baseColor, arr = false) {
        let targetColor;
        if (scaleMode === 'Light') targetColor = chroma(baseColor).set('hsl.l', 0.98).css('hsla');
        if (scaleMode === 'Dark') targetColor = chroma(baseColor).set('hsl.l', 0.05).css('hsla');
        if (scaleMode === 'Transparent') targetColor = chroma(baseColor).alpha(0.05).css('hsla');
        if (scaleMode === 'Custom') targetColor = [baseColor, ...arr];

        const scaleColors = scaleMode === 'Custom'
            ? chroma.scale(targetColor).colors(parseInt(numShades) + 1)
            : chroma.scale([baseColor, targetColor]).colors(parseInt(numShades) + 1);

        return scaleColors.slice(1).map(c => chroma(c).css('hsla'));
    },
    _colorUpdateValue: function(colors, targets) {
        if (!Array.isArray(colors)) return;

        colors.forEach((col, index) => {
            const target = targets.find(el =>
                el?.isShade && parseInt(el.shadeOrder) === index
            );
            if (!target) return;

            const lightness = chroma(col).get('hsl.l');
            const darkVersion = chroma(col).set('hsl.l', 1 - lightness).css('hsla');

            target.rawValue = target.rawValue || {};
            target.rawValue.light = col;
            target.rawValue.dark = darkVersion;
        });
    },
    _colorUpdateNestedShades: function (baseColor, baseColorId, mode, palette, isRoot = true) {
        const self = this;
        const children = (Array.isArray(palette.colors) ? palette.colors : []).filter(el => el?.shadeParent === baseColorId);
        if (!children.length) return;
    
        const base = palette.colors.find(c => c.id === baseColorId);
        const shadeArray = base?.shadeArray?.length > 0 ? base.shadeArray : undefined;
    
        const grouped = {
            Light: [],
            Dark: [],
            Transparent: [],
            Custom: []
        };
    
        for (const child of children) {
            if (child.shadeMode === 'custom') {
                grouped.Custom.push(child);
            } else if (grouped[child.shadeType]) {
                grouped[child.shadeType].push(child);
            }
        }
    
        for (const [type, group] of Object.entries(grouped)) {
            if (!group.length) continue;
    
            const newColors = self._colorCreateScale(type, group.length, baseColor, shadeArray);
            self._colorUpdateValue(newColors, group);
    
            for (const child of group) {
                const childColor = child.rawValue?.[mode];
                if (childColor) {
                    self._colorUpdateNestedShades(childColor, child.id, mode, palette, false);
                }
            }
        }
    },
    updateColor: function(obj) {
        const self = this;
        let mode = self.colorStates.colorManagerMode;
        if (obj.mode) mode = obj.mode;
    
    
        if (!obj.currentColor.hasOwnProperty('rawValue')) obj.currentColor.rawValue = {};
        if (obj.currentColor.hasOwnProperty('raw')) {
            obj.currentColor.rawValue[mode] = obj.color;
        }
        if (obj.currentColor.hasOwnProperty('isVariableOnly')) {
            delete obj.currentColor.isVariableOnly;

        }
        if (mode === 'light' && obj.hasChildren) {
            self._colorUpdateNestedShades(obj.color, obj.colorId, obj.mode, obj.currentPalette);
        }
    
        self.helpers.saveChanges('colorPalette');
        self.generateColorCSS();
        self.generateBuilderCSS();
    },
    generateColorCSS: function() {
        const self = this;

        if(!self.helpers.isGlobalColorsTabActive()) return '';

        const mode = self.colorStates.colorManagerMode;
        const css = self.generateColorCSSValue(mode);
        
        self.colorStates.generatedCSS = css;
    },
    generateColorCSSValue: function(mode, paletteId = false) {
        const self = this;
        const palettes = paletteId 
            ? self.vueState.colorPalette.filter(palette => palette.id === paletteId) 
            : self.vueState.colorPalette;
    
        return palettes.reduce((css, palette) => {
            if (palette?.status === "disabled" || !palette?.colors) return css;
    
            const vars = (Array.isArray(palette.colors) ? palette.colors : []).filter(el =>
                el?.raw && el?.rawValue &&
                (String(el.isVariableOnly) !== "true")
            );
    
            vars.forEach(el => {
                const name = self.helpers.setColorPrefix(
                    self.helpers.formatForClasses(self.helpers.getColorName(el, palette.prefix)),
                    self.helpers.isFramework(el.id),
                    palette.prefix
                );
    
                const colorValue = mode === "dark" ? el.rawValue?.dark : el.rawValue?.light;
                if (colorValue) css += `--${name}:${colorValue};`;

                // HSL
                if (el.shadeChildren && colorValue) {
                    const match = colorValue.match(/hsla?\(([^,]+),\s*([^,]+%),\s*([^,]+%)/);
                    if (match) {
                        css += `--${name}-h:${match[1]};`;
                        css += `--${name}-s:${match[2]};`;
                        css += `--${name}-l:${match[3]};`;
                    }
                }

            });
    
            return css;
        }, "");
    },
    
    
    // Class Manager
    
    removeDuplicateClass: function(){
        const self = this;
        const arr = Array.from(self.vueState.globalClasses).filter(el => el && el.new === true);
        if (arr.length < 1) return;
        arr.forEach(el => {
            delete el.new;
        })
    },
    bulkClassesReset: function(){
        const self = this;
        const containEl = document.querySelector('[name="brxcClassManagercontain"]');
        const excludeEl = document.querySelector('[name="brxcClassManagerexclude"]');
        if(containEl) containEl.value = '';
        if(excludeEl) excludeEl.value = '';
        self.states.classManagerBulkActionTargetContain = '';
        self.states.classManagerBulkActionTargetExclude = '';
        self.states.classManagerBulkActionTargetGroup = 'All';
        self.states.classManagerBulkActionLock = 'All';
        self.states.classManagerBulkActionHasStyles = 'All';
        self.states.classManagerBulkActionIsActive = 'All';
        self.states.classManagerBulkActionOld = '';
        self.states.classManagerBulkActionNew = '';
        self.states.classManagerBulkActionPrefix = '';
        self.states.classManagerBulkActionSuffix = '';
        self.states.classManagerBulkActionNewGroup = '';
        self.states.classManagerBulkAssignElements = true;
        self.states.classManagerBulkRemoveOldClass = false;
        self.states.classManagerBulkDeleteOldClass = false;
        self.states.classManagerBulkConvertLogical = true;
        self.setClassManagerBulk();
    },
    bulkDeleteClasses: function(){
        const self = this;
        let showMessage = 'Global Classes successfully removed!';

        const cls = document.querySelectorAll('#brxcClassBulkActionList ul li.bulk-action-Delete[data-id]:not([data-enable="false"]');
        if(cls.length < 1) return self.vueGlobalProp.$_showMessage('Abort: No Class found!');

        cls.forEach(cl => {
            const clId = cl.dataset.id;

            // Remove from elements
            if(self.states.classManagerBulkRemoveOldClass === true || self.states.classManagerBulkDeleteOldClass === true){

                let filteredEls;

                // All post
                if(self.states.classManagerType === "global"){
                    const content = self.helpers.getContent() || [];
                    filteredEls = Array.from(content).filter(el => el && el.settings.hasOwnProperty('_cssGlobalClasses') && el.settings._cssGlobalClasses.includes(clId));
                
                // Component
                } else {
                    const compElements = self.helpers.getComponentElements([],self.builderStates.activeElement?.id);
                    filteredEls = Array.from(compElements).filter(el => el && el.settings.hasOwnProperty('_cssGlobalClasses') && el.settings._cssGlobalClasses.includes(clId));
                }
                
                if(filteredEls && filteredEls.length > 0){
                    filteredEls.forEach(element => {
                        const index = element.settings._cssGlobalClasses.indexOf(clId);
                        element.settings._cssGlobalClasses.splice(index, 1);
                    })
                }
            }

            // Delete Classes
            if(self.states.classManagerBulkDeleteOldClass === true){
                setTimeout(() => {
                    const activeClass = self.vueGlobalProp.$_getGlobalClass(clId);
                    if(!activeClass) return;

                    const index = parseInt(self.vueState.globalClasses.indexOf(activeClass))
                    self.vueState.globalClasses.splice(index,1);

                    // Move to Trash
                    if(self.vueState.globalClassesTrash && Array.isArray(self.vueState.globalClassesTrash)){
                        activeClass.deletedAt = Date.now();
                        activeClass.originalIndex = index;
                        activeClass.user_id = bricksData.loadData.currentUserId;

                        self.vueState.globalClassesTrash.push(activeClass);
                        showMessage = 'Global Classes correctly moved to trash!';
                    }
                },5)
            }
        })
        
        setTimeout(() => {
            self.vueGlobalProp.$_showMessage(showMessage);
            self.bulkClassesReset();
            self.setClassManagerBulkActionsList();
        },100)
    },
    bulkPermadeleteClasses: function(){
        const self = this;
        let showMessage = 'Global Classes successfully deleted permanently!';

        const cls = document.querySelectorAll('#brxcClassBulkActionList ul li.bulk-action-Permadelete[data-id]:not([data-enable="false"]');
        if(cls.length < 1) return self.vueGlobalProp.$_showMessage('Abort: No Class found!');

        cls.forEach(cl => {
            const clId = cl.dataset.id;
            self.vueGlobalProp.$_deleteClassesPermanently(clId);
        })
        
        setTimeout(() => {
            self.vueGlobalProp.$_showMessage(showMessage);
            self.bulkClassesReset();
            self.setClassManagerBulkActionsList();
        },100)
    },
    bulkRestoreClasses: function(){
        const self = this;
        let showMessage = 'Global Classes successfully restored!';

        const cls = document.querySelectorAll('#brxcClassBulkActionList ul li.bulk-action-Restore[data-id]:not([data-enable="false"]');
        if(cls.length < 1) return self.vueGlobalProp.$_showMessage('Abort: No Class found!');

        cls.forEach(cl => {
            const clId = cl.dataset.id;
            self.vueGlobalProp.$_restoreGlobalClasses(clId);
        })
        
        setTimeout(() => {
            self.vueGlobalProp.$_showMessage(showMessage);
            self.bulkClassesReset();
            self.setClassManagerBulkActionsList();
        },100)
    },
    bulkDuplicateClasses: function(){
        const self = this;
        const items = document.querySelectorAll('#brxcClassBulkActionList ul li.bulk-action-Duplicate[data-id]:not([data-enable="false"]');

        if(items.length < 1) return self.vueGlobalProp.$_showMessage('Abort: No Class found!');

        function replaceRootCustomCss(target, obj, oldName, newName){
            if(obj.settings.hasOwnProperty(target)) return obj.settings[target] = obj.settings[target].replaceAll(`.${oldName}`, `.${newName}`);

        }
        function loopCustomCss(obj, oldName, newName){
            let target = "_cssCustom";
            if(obj.settings.hasOwnProperty(target)) replaceRootCustomCss(target, obj, oldName, newName);
            const bps = self.vueState.breakpoints
            bps.forEach(bp => {
                target += `:${bp.key}`;
                if(obj.settings.hasOwnProperty(target)) replaceRootCustomCss(target, obj, oldName, newName);
            })
        }
        
        items.forEach(el => {
            setTimeout(() => {
                const oldId = el.dataset.id;
                const oldObj = self.vueGlobalProp.$_getGlobalClass(oldId);
                if(!oldObj) return;

                const obj = JSON.parse(JSON.stringify(oldObj));
                const objOrder = self.vueState.globalClasses.indexOf(oldObj);

                self.vueState.globalClasses.push(obj);
                const newId = self.vueGlobalProp.$_generateId();
                const oldName = obj.name;
                let newName = el.dataset.name !== "false" ? el.dataset.name : el.querySelector('input[type="text"]')?.value  && el.querySelector('input[type="text"]')?.value.length > 0 ? el.querySelector('input[type="text"]').value : oldName;
                const newClass = self.vueState.globalClasses[self.vueState.globalClasses.length - 1];
                if(!newClass) return;
                newClass.id = newId;
                newName = self.helpers.checkClassName(newName.replaceAll(' ',''));
                newClass.name = newName;
                loopCustomCss(newClass, oldName, newName);
                self.helpers.moveArr(self.vueState.globalClasses, self.vueState.globalClasses.length - 1, parseInt(objOrder + 1), 1);
                setTimeout(() => {
                    self.states.classManagerActiveClass = newId;
                }, 10);

                // Content
                let filteredEls;

                // All post
                if(self.states.classManagerType === "global"){
                    const content = self.helpers.getContent() || [];
                    filteredEls = Array.from(content).filter(el => el && el.settings.hasOwnProperty('_cssGlobalClasses') && el.settings._cssGlobalClasses.includes(oldId));
                
                // Component
                } else {
                    const compElements = self.helpers.getComponentElements([],self.builderStates.activeElement.id);
                    filteredEls = Array.from(compElements).filter(el => el && el.settings.hasOwnProperty('_cssGlobalClasses') && el.settings._cssGlobalClasses.includes(oldId));
                }

                if(filteredEls && filteredEls.length > 0){
                    filteredEls.forEach(element => {
                        // Assign to element
                        if(self.states.classManagerBulkAssignElements === true){
                            element.settings._cssGlobalClasses.push(newId);
                        }
                        // Remove old class
                        if(self.states.classManagerBulkRemoveOldClass === true){
                            const index = element.settings._cssGlobalClasses.indexOf(oldId);
                            element.settings._cssGlobalClasses.splice(index, 1);
                        }
                    })
                }

                // Delete Original class
                if(self.states.classManagerBulkDeleteOldClass === true){
                    const index = self.vueState.globalClasses.indexOf(oldObj);
                    self.vueState.globalClasses.splice(index, 1);

                    // Move to Trash
                    if(self.vueState.globalClassesTrash && Array.isArray(self.vueState.globalClassesTrash)){
                        oldObj.deletedAt = Date.now();
                        oldObj.originalIndex = index;
                        oldObj.user_id = bricksData.loadData.currentUserId;

                        self.vueState.globalClassesTrash.push(oldObj);
                    }
                }
                    
            },10)
        })
        setTimeout(() => {
            self.vueGlobalProp.$_showMessage('Classes successfully duplicated!');
            self.helpers.saveChanges('globalClasses');
            self.bulkClassesReset();
            self.setClassManagerBulkActionsList();
        },100)
    },
    bulkRenameClasses: function(){
        const self = this;
        const items = document.querySelectorAll('#brxcClassBulkActionList ul li[data-id]:not([data-enable="false"]');

        if(items.length < 1) return self.vueGlobalProp.$_showMessage('Abort: No Class found!');

        function replaceRootCustomCss(target, obj, oldName, newName){
            if(obj.settings.hasOwnProperty(target)) return obj.settings[target] = obj.settings[target].replaceAll(`.${oldName}`, `.${newName}`);

        }
        function loopCustomCss(obj, oldName, newName){
            let target = "_cssCustom";
            if(obj.settings.hasOwnProperty(target)) replaceRootCustomCss(target, obj, oldName, newName);
            const bps = self.vueState.breakpoints
            bps.forEach(bp => {
                target += `:${bp.key}`;
                if(obj.settings.hasOwnProperty(target)) replaceRootCustomCss(target, obj, oldName, newName);
            })
        }

        items.forEach(el => {
            const id = el.dataset.id;
            const obj = self.vueGlobalProp.$_getGlobalClass(id);
            if(!obj) return;

            const oldName = obj.name;
            const tempName = el.dataset.name !== "false" ? el.dataset.name : el.querySelector('input[type="text"]').value  && el.querySelector('input[type="text"]').value.length > 0 ? el.querySelector('input[type="text"]').value : oldName;
            const newName = self.helpers.checkClassName(tempName.replaceAll(' ',''));
            obj.name = newName;
            loopCustomCss(obj, oldName, newName);
        })
        setTimeout(() => {
            self.vueGlobalProp.$_showMessage('Classes successfully renamed!');
            self.bulkClassesReset();
            self.setClassManagerBulkActionsList();
        },100)
    },
    bulkFindAndReplaceClasses: function(){
        const self = this;
        const items = document.querySelectorAll('#brxcClassBulkActionList ul li[data-id]:not([data-enable="false"]');
        if(items.length < 1) return self.vueGlobalProp.$_showMessage('Abort: No Class found!');

        const findEl = document.querySelector('#brxcClassBulkActionCanvas #brxc-bulkActionsOld');
        const replaceEl = document.querySelector('#brxcClassBulkActionCanvas #brxc-bulkActionsNew');
        if(!findEl || !replaceEl) return;
        const findValue = findEl.value;
        if(!findValue || findValue === "") return self.vueGlobalProp.$_showMessage(`Abort: the find value can't be empty`);

        const replaceValue = replaceEl.value;

        function replaceSettingValue(settings) {
            if (settings === null || typeof settings !== 'object') {
                return;
            }
            
            // Arrays
            if (Array.isArray(settings)) {
                for (let i = 0; i < settings.length; i++) {
                    const value = settings[i];
                    
                    if (typeof value === 'string') {
                        settings[i] = value.replaceAll(findValue, replaceValue);
                    } 
                    else if (value !== null && typeof value === 'object') {
                        replaceSettingValue(value);
                    }
                }
            } else {
                for (const key in settings) {
                    if (Object.prototype.hasOwnProperty.call(settings, key)) {
                        const value = settings[key];
                        
                        // If value is a string, replace
                        if (typeof value === 'string') {
                            settings[key] = value.replaceAll(findValue, replaceValue);
                        } 
                        // If value is an object or array, process recursively
                        else if (value !== null && typeof value === 'object') {
                            replaceSettingValue(value);
                        }
                    }
                }
            }
        }

        items.forEach(el => {
            const id = el.dataset.id;
            const obj = self.vueGlobalProp.$_getGlobalClass(id);
            if(!obj) return;

            replaceSettingValue(obj.settings);
        })
        setTimeout(() => {
            self.vueGlobalProp.$_showMessage('Find & replaced ran successfully!');
            self.bulkClassesReset();
            self.setClassManagerBulkActionsList();
        },100)
    },
    renameBulkedClass: function(event, bulkedName){
        const prev = event.target.parentElement.previousElementSibling;
        const parent = event.target.parentElement.parentElement;
        if(!event) return;
        prev.innerHTML = `.<input type="text" value="${bulkedName}">`;
        parent.setAttribute('data-name', false);
        const input = prev.querySelector('input');
        input.focus();
        input.select()

    },

    enableBulkedClass: function(event){
        const li = event.target.closest('li');
        if(event.target.classList.contains('enable')){
            li.setAttribute('data-enable', 'false')
            event.target.classList.remove('enable');
            event.target.classList.add('disable');
            event.target.setAttribute('data-balloon', 'Skipped');
            event.target.querySelector('i').setAttribute('class', 'fas fa-toggle-off');
        } else {
            li.setAttribute('data-enable', 'true');
            event.target.classList.add('enable');
            event.target.classList.remove('disable');
            event.target.setAttribute('data-balloon', 'Included');
            event.target.querySelector('i').setAttribute('class', 'fas fa-toggle-on');
        }
    },
    bulkGroupClasses: function(){
        const self = this;

        const cls = document.querySelectorAll('#brxcClassBulkActionList ul li.bulk-action-Group[data-id]:not([data-enable="false"])');
        if(cls.length < 1) return self.vueGlobalProp.$_showMessage('Abort: No Class found!');
        
        if(!self.states.classManagerCategories.includes(self.states.classManagerBulkActionNewGroup)) self.helpers.createClassCategory(self.states.classManagerBulkActionNewGroup)
        cls.forEach(el => {
            const clId = el.dataset.id;
            const obj = self.vueGlobalProp.$_getGlobalClass(clId);
            if(!obj) return;

            obj.category = self.helpers.getClassCategoryIdByName(self.states.classManagerBulkActionNewGroup);
        })
        setTimeout(() => {
            self.vueGlobalProp.$_showMessage(`Classes successfully assigned to ${self.states.classManagerBulkActionNewGroup}!`);
            self.bulkClassesReset();
            self.setClassManagerBulkActionsList();
        },100)
    },
    bulkExportClasses: function(){
        const self = this;

        const cls = document.querySelectorAll('#brxcClassBulkActionList ul li.bulk-action-Export[data-id]:not([data-enable="false"]');
        if(cls.length < 1) return self.vueGlobalProp.$_showMessage('Abort: No Class found!');

        const globalClasses = [];

        cls.forEach(cl => {
            const obj = self.vueGlobalProp.$_getGlobalClass(cl.dataset.id);
            if(!obj) return;
            globalClasses.push(obj);
        })
        
        self.vueGlobalProp.$_exportAsJsonFile(globalClasses, 'bricks-css-classes');
        
        setTimeout(() => {
            self.vueGlobalProp.$_showMessage(`Classes successfully exported!`);
            self.bulkClassesReset();
            self.setClassManagerBulkActionsList();
        },100)
    },
    bulkLockClasses: function(){
        const self = this;

        const cls = document.querySelectorAll('#brxcClassBulkActionList ul li.bulk-action-Lock[data-id]:not([data-enable="false"]');
        if(cls.length < 1) return self.vueGlobalProp.$_showMessage('Abort: No Class found!');

        const lockedClasses = Array.from(cls).map(el => el.dataset.id);
        self.vueState.globalClassesLocked = [...new Set(self.vueState.globalClassesLocked.concat(lockedClasses))];
        
        
        setTimeout(() => {
            self.vueGlobalProp.$_showMessage(`Classes successfully locked!`);
            self.bulkClassesReset();
            self.setClassManagerBulkActionsList();
        },100)
    },
    bulkUnlockClasses: function(){
        const self = this;

        const cls = document.querySelectorAll('#brxcClassBulkActionList ul li.bulk-action-Unlock[data-id]:not([data-enable="false"]');
        if(cls.length < 1) return self.vueGlobalProp.$_showMessage('Abort: No Class found!');

        const unlockedClasses = Array.from(cls).map(el => el.dataset.id);
        self.vueState.globalClassesLocked = Array.from(self.vueState.globalClassesLocked).filter(el => !unlockedClasses.includes(el));
        
        
        setTimeout(() => {
            self.vueGlobalProp.$_showMessage(`Classes successfully unlocked!`);
            self.bulkClassesReset();
            self.setClassManagerBulkActionsList();
        },100)
    },
    bulkModifyClasses: function(){
        const self = this;

        const cls = document.querySelectorAll('#brxcClassBulkActionList ul li.bulk-action-Modify[data-id]:not([data-enable="false"]');
        if(cls.length < 1) return self.vueGlobalProp.$_showMessage('Abort: No Class found!');

        const modifiedCls = Array.from(cls).map(el => el.dataset.id);
        modifiedCls.forEach(id => {
            const obj = self.vueGlobalProp.$_getGlobalClass(id);
            obj.settings = self.convertToLogicalProperties(obj.settings)
        })
        
        setTimeout(() => {
            self.vueGlobalProp.$_showMessage(`Classes successfully modified!`);
            self.bulkClassesReset();
            self.setClassManagerBulkActionsList();
        },100)
    },
    loadMoreClasses: function(num){
        const self = this;
        self.states.classManagerMaxClasses = num;
    },
    setClassManagerUnused: function(forceAjax = false) {
        const self = this;
        self.setClassManagerUnusedList();
        self.setClassManagerUnusedCanvas();
        
    },
    mountUnusedClasses: function(callback = false){
        const self = this;
        const dataObj = {
            action: 'get_used_classes_ajax_function',
            nonce: openai_ajax_req.nonce,
        };

        function getUniqueClasses(data) {
            const allClasses = [];
            
            ["posts", "components"].forEach(key => {
                data[key].forEach(post => {
                    Object.entries(post.classes).forEach(([classType, classList]) => {
                        if (classType === "global") {
                            allClasses.push(...classList);
                        } else {
                            const cls = self.vueState.globalClasses.filter(el => classList.includes(el.name)).map(el => el.id);
                            allClasses.push(...cls);
                        }
                    });
                });
            })
        
            return [...new Set(allClasses)];
        }

        function getUsedClassesByAjax(){
            return new Promise((resolve, reject) => {
                jQuery.ajax({
                    url: openai_ajax_req.ajax_url,
                    data: dataObj,
                    method: "POST",
                    success: function (response) {
                        self.states.classManagerUsedClasses = response.data;
                        const usedClasses = [...new Set(getUniqueClasses(response.data))];
                        self.states.classManagerUnusedClasses = self.vueState.globalClasses.filter(el => !usedClasses.includes(el.id));
                        if(callback) callback();
                        resolve(response);
                    },
                    error: function (data) {
                        reject('Something went wrong.');
                    }
                });
            });
        }
        getUsedClassesByAjax()
    },
    setClassManagerUnusedList: function(){
        const canvas = document.querySelector('#brxcClassUnusedList');
        if(!canvas) return;

        const self = this;
        let cls = self.states.classManagerUnusedClasses;

        let content = '';

        if(Array.isArray(cls) && cls.length > 0 ) {
            // filters
            const contain = self.states.classManagerUnusedTargetContain.replaceAll(' ', '').split(',');
            const exclude = self.states.classManagerUnusedTargetExclude.replaceAll(' ', '').split(',');
            const checkContain = (e) => (contain.length === 1 && contain[0] === '') || contain.some(target => target !== '' && e.name.includes(target));
            const checkExclude = (e) => (exclude.length === 1 && exclude[0] === '') || exclude.every(target => target === '' || !e.name.includes(target));
            const checkGroup = (e) => {
                if(self.states.classManagerUnusedTargetGroup === "All"){
                    return true;
                } else if(self.states.classManagerUnusedTargetGroup === "Uncategorized"){
                    return !e.hasOwnProperty('category');
                } else {
                    return e.category === self.states.classManagerUnusedTargetGroup;
                }
            }
            const checkLock = (e) => self.states.classManagerUnusedLock !== "All" ? (self.states.classManagerUnusedLock === "locked" ? self.vueGlobalProp.$_isLocked(e.id) : !self.vueGlobalProp.$_isLocked(e.id)) : true;
            const checkStyle = (e) => self.states.classManagerUnusedHasStyles !== "All" ? (self.states.classManagerUnusedHasStyles === "has-styles" ? self.vueGlobalProp.$_generateCss('globalClass', e.id, ['block']) !== '' : self.vueGlobalProp.$_generateCss('globalClass', e.id, ['block']) === '') : true;
            
            cls = cls.filter(el =>
                el 
                && checkContain(el)
                && checkExclude(el)
                && checkGroup(el)
                && checkLock(el)
                && checkStyle(el)
            );

            content += `<ul>`;
            content += cls.map(el => (
                `<li data-id="${el.id}">
                    <div class="span-wrapper"><span>.${el.name}</span></div>
                    <div class="brxc-unused-action-wrapper">
                        <div class="brxc-icon enable" data-balloon="Included" data-balloon-pos="left" onClick="ADMINBRXC.enableBulkedClass(event);">
                            <span class="bricks-svg-wrapper"><i class="fas fa-toggle-on"></i></span>
                        </div>
                    </div>
                </li>`
            )).join(""); // This removes the default commas
            content += `</ul>`;
        }
         
        canvas.innerHTML = content;
    },
    setClassManagerUnusedCanvas: function(){
        const self = this;
        const canvas = document.querySelector('#brxcClassUnusedCanvas #brxcFilterCanvas');
        if(!canvas) return;

        let content = '';
        content += self.generateClassManagerBulkActionFilters(['group', 'lock', 'styles']);

        canvas.innerHTML = content;
        // Filter Group
        const containInput = canvas.querySelector('#brxcClassManagercontain');
        if(containInput){
            containInput.addEventListener('input', (e) => {
                self.states.classManagerUnusedTargetContain = e.target.value;
                self.setClassManagerUnusedList();
            })
        }
        const excludeInput = canvas.querySelector('#brxcClassManagerexclude')
        if(excludeInput){
            excludeInput.addEventListener('input', (e) => {
                self.states.classManagerBulkUnusedTargetExclude = e.target.value;
                self.setClassManagerUnusedList();
            })
        }
        [
            { selector: '#bulkActionsOptionsGroup', stateKey: 'classManagerUnusedTargetGroup' },
            { selector: '#bulkActionsOptionsLock', stateKey: 'classManagerUnusedLock' },
            { selector: '#bulkActionsOptionsHasStyles', stateKey: 'classManagerUnusedHasStyles' }
        ].forEach(({ selector, stateKey }) => {

            const select = canvas.querySelector(selector);
            self.helpers.selectControl(select, (target) => {
                self.states[stateKey] = target.dataset.value;
                self.setClassManagerUnusedList();
            });
        });
    },
    unusedClassesReset: function(){
        const self = this;
        self.states.classManagerUnusedTargetContain = '';
        self.states.classManagerUnusedTargetExclude = '';
        self.states.classManagerUnusedTargetGroup = 'All';
        self.states.classManagerUnusedLock = 'All';
        self.states.classManagerUnusedHasStyles = 'All';
        self.setClassManagerUnused();
    },
    unusedClassesRescan: function(){
        const self = this;
        self.mountUnusedClasses(() => {
            self.setClassManagerUnusedList();
        });
        self.vueGlobalProp.$_showMessage('The website has been rescanned successfully!')
    },
    unusedClassesTrash: function(){
        const self = this;
        const items = document.querySelectorAll('#brxcClassUnusedList ul li[data-id]:not([data-enable="false"]');

        if(items.length < 1) return self.vueGlobalProp.$_showMessage('Abort: No Class found!');
        const clsIds = Array.from(items).map(item => item.dataset.id)
        self.vueGlobalProp.$_moveGlobalClassesToTrash(clsIds);
        self.vueGlobalProp.$_showMessage(`${items.length} Class(es) moved to trash successfully!`);
        self.unusedClassesReset();
        self.setClassManagerUnused(true);

    },
    setClassManagerBulk: function(){
        const self = this;
        self.states.classManagerMaxClasses = 50;
        self.setClassManagerBulkActionsList();
        self.setClassManagerBulkActions();
    },
    setClassManagerBulkActionsList: function(){
        const canvas = document.querySelector('#brxcClassBulkActionList');
        if(!canvas) return;

        const self = this;
        const isTrashList = ['Restore','Permadelete'].includes(self.states.classManagerBulkActionType);
        let cls;
        
        // Type
        if(isTrashList){
            cls = self.vueState.globalClassesTrash;
        } else if(self.states.classManagerType === "global") {
            cls = self.vueState.globalClasses;
         } else {
            let globalClasses = [];
            const tempClasses = self.helpers.getComponentClasses([],self.builderStates.activeElement?.id);
            
            if(tempClasses.length > 0){
                tempClasses.forEach(el => {
                    const classObj = self.vueGlobalProp.$_getGlobalClass(el);
                    if(classObj) globalClasses.push(classObj)
                })
                cls = globalClasses.concat(Array.from(self.vueState.globalClasses).filter(el => el && el.new === true))
            }
         }

         let content = '';

         if(Array.isArray(cls) && cls.length > 0 ) {
            // filters
            const contain = self.states.classManagerBulkActionTargetContain.replaceAll(' ', '').split(',');
            const exclude = self.states.classManagerBulkActionTargetExclude.replaceAll(' ', '').split(',');
            const checkContain = (e) => (contain.length === 1 && contain[0] === '') || contain.some(target => target !== '' && e.name.includes(target));
            const checkExclude = (e) => (exclude.length === 1 && exclude[0] === '') || exclude.every(target => target === '' || !e.name.includes(target));
            const checkGroup = (e) => {
                if(self.states.classManagerBulkActionTargetGroup === "All"){
                    return true;
                } else if(self.states.classManagerBulkActionTargetGroup === "Uncategorized"){
                    return !e.hasOwnProperty('category');
                } else {
                    return e.category === self.states.classManagerBulkActionTargetGroup;
                }
            }
            const checkLock = (e) => self.states.classManagerBulkActionLock !== "All" ? (self.states.classManagerBulkActionLock === "locked" ? self.vueGlobalProp.$_isLocked(e.id) : !self.vueGlobalProp.$_isLocked(e.id)) : true;
            const checkStyle = (e) => self.states.classManagerBulkActionHasStyles !== "All" ? (self.states.classManagerBulkActionHasStyles === "has-styles" ? self.vueGlobalProp.$_generateCss('globalClass', e.id, ['block']) !== '' : self.vueGlobalProp.$_generateCss('globalClass', e.id, ['block']) === '') : true;
            const checkisActive = (e) => {
                if (self.states.classManagerBulkActionIsActive === 'is-active') {
                    const template = self.helpers.getTemplateType();
                    return self.vueState[template].some(el =>
                        el?.settings?._cssGlobalClasses?.includes(e.id)
                    );
                }
                
                if (self.states.classManagerBulkActionIsActive === 'is-not-active') {
                    const template = self.helpers.getTemplateType();
                    return !self.vueState[template].some(el =>
                        el?.settings?._cssGlobalClasses?.includes(e.id)
                    );
                }
                
                return true; // No filter applied
            };
        
            cls = cls.filter(el =>
                el 
                && checkContain(el)
                && checkExclude(el)
                && checkGroup(el)
                && checkLock(el)
                && checkStyle(el)
                && checkisActive(el)
            );
    
            content += `<ul>`;
            if(cls.length > 0) {
                let index = 1;
                cls.slice(0, self.states.classManagerMaxClasses).forEach(el => {
                    const tempName = `<span class="brxc_changes">${self.states.classManagerBulkActionPrefix.replaceAll(' ','')}</span>` + (self.states.classManagerBulkActionOld === '' || self.states.classManagerBulkActionNew === "" ? el.name : el.name.replaceAll(self.states.classManagerBulkActionOld, `<span class="brxc_changes">${self.states.classManagerBulkActionNew.replaceAll(' ','')}</span>`)) + `<span class="brxc_changes">${self.states.classManagerBulkActionSuffix.replaceAll(' ','')}</span>`;
                    const newName = self.helpers.checkClassName(tempName, true);
                    const newNameWithoutTags = newName.replaceAll('<span class="brxc_changes">', '').replaceAll('</span>', '');
                    if(self.states.classManagerBulkActionType === "Duplicate") content += `<li class="active"><div class="span-wrapper"><span>.${el.name}</span></div></li>`;
                    const classicNames = ['Delete', 'Group', 'Modify', 'Export', 'Lock', 'Unlock', "FindAndReplace"];
                    content += `<li class="bulk-action-${self.states.classManagerBulkActionType}" data-id="${el.id}" data-name="${newNameWithoutTags}" data-enable="true"><div class="span-wrapper"><span>.${classicNames.includes(self.states.classManagerBulkActionType) ? el.name : newName}</span></div>`;
                    content += `<div class="brxc-bulk-action-wrapper">`
                    if(self.states.classManagerBulkActionType === "Rename" || self.states.classManagerBulkActionType === "Duplicate"){
                        content += `<div class="brxc-icon" data-action="rename" data-new-name="${newNameWithoutTags}" data-balloon="Rename" data-balloon-pos="left"><span class="bricks-svg-wrapper"><i class="fas fa-pen"></i></span></div>`;
                        
                    } 
                    content += `<div class="brxc-icon enable" data-action="enable" data-balloon="Included" data-balloon-pos="left"><span class="bricks-svg-wrapper"><i class="fas fa-toggle-on"></i></span></div>`;
                    content += `</div>`
                    content +=`</li>`;
                    if(index === self.states.classManagerMaxClasses && self.states.classManagerMaxClasses < cls.length) content += `<li onclick="ADMINBRXC.loadMoreClasses(${cls.length});ADMINBRXC.setClassManagerBulkActionsList();"><div class="span-wrapper"><span class="max-results">Load ${cls.length - 50} more classes....</span></div></li>`;
                    index++;
                })
            }
            content += '</ul>';
         }
         
        canvas.innerHTML = content;

        // Listeners
        const wrapper = canvas.querySelector('ul');
        if(wrapper){
            wrapper.addEventListener('click', (e) => {
                const action = e.target.dataset.action;
                if(action){
                    switch(action){
                        case 'rename':
                            self.renameBulkedClass(e, e.target.dataset.newName);
                            break;
                        case 'enable':
                            self.enableBulkedClass(e);
                            break;
                    }
                }
            })
        }

    },
    generateClassManagerBulkActionFilters: function(settings){
        const self = this;
        const sortedCats = Array.from(self.vueState.globalClassesCategories)
            .filter(el => el && el.name)
            .map(el => el.name)
            .sort((a, b) => a.localeCompare(b, undefined, { sensitivity: 'base' }));

        const groupOptions = [
            { value: 'All', label: 'All' },
            { value: 'Uncategorized', label: 'Uncategorized' },
            ...sortedCats.map(name => ({
                value: self.helpers.getClassCategoryIdByName(name),
                label: name
            }))
        ];
        const lockOptions = [
            { value: 'All', label: 'All' },
            { value: 'locked', label: 'Locked' },
            { value: 'unlocked', label: 'Unlocked' },
        ];
        const hasStylesOptions = [
            { value: 'All', label: 'All' },
            { value: 'has-styles', label: 'Have Styles' },
            { value: 'has-no-styles', label: 'Have No Styles' },
        ]
        const isActiveOptions = [
            { value: 'All', label: 'All' },
            { value: 'is-active', label: 'Active on page' },
            { value: 'is-not-active', label: 'Inactive on Page' },
        ]

        let content = '';
        content += `<fieldset>
                        <legend>Filters</legend>
                        <div>
                            <label class="has-tooltip">
                            <span>Include String:</span>
                            <div data-balloon="Type a keyword to filter the classes that you want to target. For multiple keywords, separate each word by a comma." data-balloon-pos="bottom" data-balloon-length="medium">
                                <i class="fas fa-circle-question"></i>
                            </div>
                            </label>
                            <div class="brxc__text">
                            <input type="text" name="brxcClassManagercontain" id="brxcClassManagercontain" placeholder="Type here the keywords you want to include">
                            </div>
                        </div>
                        <div>
                            <label class="has-tooltip">
                            <span>Exclude String:</span>
                            <div data-balloon="Type keywords that will exclude the classes from the selection. For multiple keywords, separate each word by a comma." data-balloon-pos="bottom" data-balloon-length="medium">
                                <i class="fas fa-circle-question"></i>
                            </div>
                            </label>
                            <div class="brxc__text">
                            <input type="text" name="brxcClassManagerexclude" id="brxcClassManagerexclude" placeholder="Type here the keywords you want to exclude">
                            </div>
                        </div>`;
        if(settings.includes('group')){
            content += `<div style="z-index:3"><label class="has-tooltip"><span>Group:</span><div data-balloon="Filter the selection by any Class Group." data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>`;
            content += `<div class="brxc-select">
                            <div class="brxc-select-new bg2 rounded hidden" name="brxc-bulkActionsOptions" id="bulkActionsOptionsGroup">
                                <div class="brxc-select-new__wrapper">
                                    ${groupOptions.map(opt => {
                                        return `<div data-value="${opt.value}"${self.states.classManagerBulkActionTargetGroup === opt.value ? ' class="active"' : ''}><span>${opt.label}</span></div>`;
                                    }).join('')}
                                </div>
                            </div>
                        </div>`;
            content += `</div>`;
        }
        if(settings.includes('lock')){
            content += `<div style="z-index:2"><label class="has-tooltip"><span>Locked/Unlocked:</span><div data-balloon="Filter the selection by their Lock status." data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>`;
            content += `<div class="brxc-select">
                            <div class="brxc-select-new bg2 rounded hidden" name="brxc-bulkActionsOptions" id="bulkActionsOptionsLock">
                                <div class="brxc-select-new__wrapper">
                                    ${lockOptions.map(opt => {
                                        return `<div data-value="${opt.value}"${self.states.classManagerBulkActionLock === opt.value ? ' class="active"' : ''}><span>${opt.label}</span></div>`;
                                    }).join('')}
                                </div>
                            </div>
                        </div>`;
            content += `</div>`;
        }
        if(settings.includes('styles')){
            content += `<div style="z-index:1"><label class="has-tooltip"><span>Have Styles:</span><div data-balloon="Filter the selection of the classes that contain custom styles." data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>`;
            content += `<div class="brxc-select">
                            <div class="brxc-select-new bg2 rounded hidden" name="brxc-bulkActionsOptions" id="bulkActionsOptionsHasStyles">
                                <div class="brxc-select-new__wrapper">
                                    ${hasStylesOptions.map(opt => {
                                        return `<div data-value="${opt.value}"${self.states.classManagerBulkActionHasStyles === opt.value ? ' class="active"' : ''}><span>${opt.label}</span></div>`;
                                    }).join('')}
                                </div>
                            </div>
                        </div>`
            content += `</div>`;
        }
        if(settings.includes('active')){
            content += `<div style="z-index:0"><label class="has-tooltip"><span>Active on Page:</span><div data-balloon="Filter the selection of the classes that are used on this page." data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>`;
            content += `<div class="brxc-select">
                            <div class="brxc-select-new bg2 rounded hidden" name="brxc-bulkActionsOptions" id="bulkActionsOptionsIsActive">
                                <div class="brxc-select-new__wrapper">
                                    ${isActiveOptions.map(opt => {
                                        return `<div data-value="${opt.value}"${self.states.classManagerBulkActionIsActive === opt.value ? ' class="active"' : ''}><span>${opt.label}</span></div>`;
                                    }).join('')}
                                </div>
                            </div>
                        </div>`;
            content += `</div>`;
        }
        content += `</fieldset>`;
        return content
    },
    setClassManagerBulkActions: function(){
        const self = this;
        const canvas = document.querySelector('#brxcClassBulkActionCanvas');
        if(!canvas) return;

        let content = '';
        content += self.generateClassManagerBulkActionFilters(['group', 'lock','styles','active']);
        if(["Rename", "Duplicate", "FindAndReplace"].includes(self.states.classManagerBulkActionType)){
            content += `<fieldset><legend>Action</legend>`;
            content += `<div><label class="has-tooltip"><span>Find:</span><div data-balloon="Type here the string that you want to replace." data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>`;
            content += `<div class="brxc__text"><input type="text" name="brxcClassManagerOld" id="brxc-bulkActionsOld" placeholder="Type here the string you want to replace" value="${self.states.classManagerBulkActionOld}" onInput="ADMINBRXC.states.classManagerBulkActionOld = this.value;ADMINBRXC.setClassManagerBulkActionsList();"></div></div>`;
            content += `<div><label class="has-tooltip"><span>Replace with:</span><div data-balloon="Type here the new string that will replace the old one." data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>`;
            content += `<div class="brxc__text"><input type="text" name="brxcClassManagerNew" id="brxc-bulkActionsNew" placeholder="Type here the new string" value="${self.states.classManagerBulkActionNew}" onInput="ADMINBRXC.states.classManagerBulkActionNew = this.value;ADMINBRXC.setClassManagerBulkActionsList();"></div></div>`;
            if(self.states.classManagerBulkActionType === "FindAndReplace") content += `</fieldset>`;
            if(self.states.classManagerBulkActionType !== "FindAndReplace"){
                content += `<div><label class="has-tooltip"><span>Add a prefix:</span><div data-balloon="Add a prefix to the renamed classes" data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>`;
                content += `<div class="brxc__text"><input type="text" name="brxcClassManagerNew" id="brxc-bulkActionsPrefix" placeholder="Type here the prefix" value="${self.states.classManagerBulkActionPrefix}" onInput="ADMINBRXC.states.classManagerBulkActionPrefix = this.value;ADMINBRXC.setClassManagerBulkActionsList();"></div></div>`;
                content += `<div><label class="has-tooltip"><span>Add a suffix:</span><div data-balloon="Add a suffix to the renamed classes" data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>`;
                content += `<div class="brxc__text"><input type="text" name="brxcClassManagerNew" id="brxc-bulkActionsSuffix" placeholder="Type here the suffix" value="${self.states.classManagerBulkActionSuffix}" onInput="ADMINBRXC.states.classManagerBulkActionSuffix = this.value;ADMINBRXC.setClassManagerBulkActionsList();"></div></div>`;
                if(self.states.classManagerBulkActionType === "Rename") content += `</fieldset>`;
            }
        } 
        if(self.states.classManagerBulkActionType === "Duplicate"){
            content += `<div><label class="has-tooltip"><span>Assign duplicated classes to same elements:</span><div data-balloon="If yes, the duplicated classes will be added to the same elements where the original classes are assigned. This will apply on the current post only - not sitewide." data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>`;
            content += `<div class="brxc-overlay__panel-inline-btns-wrapper m-bottom-24">
                            <input type="radio" id="brxc-class-converter-assign-yes" name="brxc-class-converter-assign-elements" class="brxc-input__checkbox" value="0"${self.states.classManagerBulkAssignElements === false ? ' checked=""' : ''} onclick="ADMINBRXC.states.classManagerBulkAssignElements = false">
                            <label for="brxc-class-converter-assign-yes" class="brxc-overlay__panel-inline-btns">No</label>
                            <input type="radio" id="brxc-class-converter-assign-no" name="brxc-class-converter-assign-elements" class="brxc-input__checkbox" value="1"${self.states.classManagerBulkAssignElements === true ? ' checked=""' : ''} onclick="ADMINBRXC.states.classManagerBulkAssignElements = true">
                            <label for="brxc-class-converter-assign-no" class="brxc-overlay__panel-inline-btns">Yes</label>
                        </div></div>`;
            content += `<div><label class="has-tooltip"><span>Remove old classes from all the elements:</span><div data-balloon="If yes, the original classes will be removed from all the elements on this ${self.states.classManagerType === "global" ? 'post' : 'component'}. This will apply on the current post only - not sitewide." data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>`;
            content += `<div class="brxc-overlay__panel-inline-btns-wrapper m-bottom-24">
                            <input type="radio" id="brxc-class-converter-remove-yes" name="brxc-class-converter-remove-elements" class="brxc-input__checkbox" value="0"${self.states.classManagerBulkRemoveOldClass === false ? ' checked=""' : ''} onclick="ADMINBRXC.states.classManagerBulkRemoveOldClass = false">
                            <label for="brxc-class-converter-remove-yes" class="brxc-overlay__panel-inline-btns">No</label>
                            <input type="radio" id="brxc-class-converter-remove-no" name="brxc-class-converter-remove-elements" class="brxc-input__checkbox" value="1"${self.states.classManagerBulkRemoveOldClass === true ? ' checked=""' : ''} onclick="ADMINBRXC.states.classManagerBulkRemoveOldClass = true">
                            <label for="brxc-class-converter-remove-no" class="brxc-overlay__panel-inline-btns">Yes</label>
                        </div></div>`;
            content += `<div><label class="has-tooltip"><span>Delete old classes from the Global Classes list:</span><div data-balloon="If yes, the original classes will be deleted from the Global Classes list. This will apply sitewide and impact all your posts/pages." data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>`;
            content += `<div class="brxc-overlay__panel-inline-btns-wrapper m-bottom-24">
                            <input type="radio" id="brxc-class-converter-delete-yes" name="brxc-class-converter-delete-elements" class="brxc-input__checkbox" value="0"${self.states.classManagerBulkDeleteOldClass === false ? ' checked=""' : ''} onclick="ADMINBRXC.states.classManagerBulkDeleteOldClass = false">
                            <label for="brxc-class-converter-delete-yes" class="brxc-overlay__panel-inline-btns">No</label>
                            <input type="radio" id="brxc-class-converter-delete-no" name="brxc-class-converter-delete-elements" class="brxc-input__checkbox" value="1"${self.states.classManagerBulkDeleteOldClass === true ? ' checked=""' : ''} onclick="ADMINBRXC.states.classManagerBulkDeleteOldClass = true">
                            <label for="brxc-class-converter-delete-no" class="brxc-overlay__panel-inline-btns">Yes</label>
                        </div></div>`;
            content += `</fieldset>`;
        } else if(self.states.classManagerBulkActionType === "Group"){
            content += `<fieldset><legend>Action</legend>`;
            content += `<div><label class="has-tooltip"><span>Assign classes to the following group:</span><div data-balloon="Write here the group you want to assign the classes." data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>`;
            content += `<div class="brxc__text"><input type="text" name="brxcClassManagerNewGroup" id="brxc-bulkActionsNewGroup" placeholder="Type here the group you want to assign the classes" value="${self.states.classManagerBulkActionNewGroup}" onInput="ADMINBRXC.states.classManagerBulkActionNewGroup = this.value;ADMINBRXC.setClassManagerBulkActionsList();"></div></div>`;
            content += `</fieldset>`;
        } else if(self.states.classManagerBulkActionType === "Modify"){
            content += `<fieldset><legend>Action</legend>`;
            content += `<div><label class="has-tooltip"><span>Convert the styles of the selected classes to Logical Properties:</span><div data-balloon="If yes, all the Directional Properties of the selected classes will be converted as Logical Properties" data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>`;
            content += `<div class="brxc-overlay__panel-inline-btns-wrapper m-bottom-24">
                            <input type="radio" id="brxc-class-converter-convert-logical-no" name="brxc-class-converter-convert-logical" class="brxc-input__checkbox" value="0"${self.states.classManagerBulkConvertLogical === false ? ' checked=""' : ''} onclick="ADMINBRXC.states.lassManagerBulkConvertLogical = false">
                            <label for="brxc-class-converter-convert-logical-no" class="brxc-overlay__panel-inline-btns">No</label>
                            <input type="radio" id="brxc-class-converter-convert-logical-yes" name="brxc-class-converter-convert-logical" class="brxc-input__checkbox" value="1"${self.states.classManagerBulkConvertLogical === true ? ' checked=""' : ''} onclick="ADMINBRXC.states.lassManagerBulkConvertLogical = true">
                            <label for="brxc-class-converter-convert-logical-yes" class="brxc-overlay__panel-inline-btns">Yes</label>
                        </div></div>`;
            content += `</fieldset>`;
        } else if(self.states.classManagerBulkActionType === "Delete"){
            content += `<fieldset><legend>Action</legend>`;
            content += `<div><label class="has-tooltip"><span>Remove classes from all the elements:</span><div data-balloon="If yes, the targeted classes will be removed from all the elements on this ${self.states.classManagerType === "global" ? 'post' : 'component'}. This will apply on the current post only - not sitewide." data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>`;
            content += `<div class="brxc-overlay__panel-inline-btns-wrapper m-bottom-24">
                            <input type="radio" id="brxc-class-converter-remove-yes" name="brxc-class-converter-remove-elements" class="brxc-input__checkbox" value="0"${self.states.classManagerBulkRemoveOldClass === false ? ' checked=""' : ''} onclick="ADMINBRXC.states.classManagerBulkRemoveOldClass = false">
                            <label for="brxc-class-converter-remove-yes" class="brxc-overlay__panel-inline-btns">No</label>
                            <input type="radio" id="brxc-class-converter-remove-no" name="brxc-class-converter-remove-elements" class="brxc-input__checkbox" value="1"${self.states.classManagerBulkRemoveOldClass === true ? ' checked=""' : ''} onclick="ADMINBRXC.states.classManagerBulkRemoveOldClass = true">
                            <label for="brxc-class-converter-remove-no" class="brxc-overlay__panel-inline-btns">Yes</label>
                        </div></div>`;
            content += `<div><label class="has-tooltip"><span>Delete classes from the Global Classes list:</span><div data-balloon="If yes, the original classes will be deleted from the Global Classes list. This will apply sitewide and impact all your posts/pages." data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>`;
            content += `<div class="brxc-overlay__panel-inline-btns-wrapper m-bottom-24">
                            <input type="radio" id="brxc-class-converter-delete-yes" name="brxc-class-converter-delete-elements" class="brxc-input__checkbox" value="0"${self.states.classManagerBulkDeleteOldClass === false ? ' checked=""' : ''} onclick="ADMINBRXC.states.classManagerBulkDeleteOldClass = false">
                            <label for="brxc-class-converter-delete-yes" class="brxc-overlay__panel-inline-btns">No</label>
                            <input type="radio" id="brxc-class-converter-delete-no" name="brxc-class-converter-delete-elements" class="brxc-input__checkbox" value="1"${self.states.classManagerBulkDeleteOldClass === true ? ' checked=""' : ''} onclick="ADMINBRXC.states.classManagerBulkDeleteOldClass = true">
                            <label for="brxc-class-converter-delete-no" class="brxc-overlay__panel-inline-btns">Yes</label>
                        </div></div>`;
            content += `</fieldset>`;
        }
        content += `<div id="bulk${self.states.classManagerBulkActionType}ClassesCTA" class="brxc-overlay__action-btn-wrapper right sticky-bottom generate-content active"><div class="brxc-overlay__action-btn" onclick="ADMINBRXC.bulkClassesReset()"><span>Reset</span></div><div class="brxc-overlay__action-btn primary" onclick="ADMINBRXC.bulk${self.states.classManagerBulkActionType}Classes()"><span>Apply</span></div></div>`;

        canvas.innerHTML = content;

        // Filter Group
        const containInput = canvas.querySelector('#brxcClassManagercontain');
        if(containInput){
            containInput.addEventListener('input', (e) => {
                self.states.classManagerBulkActionTargetContain = e.target.value;
                self.setClassManagerBulkActionsList();
            })
        }
        const excludeInput = canvas.querySelector('#brxcClassManagerexclude')
        if(excludeInput){
            excludeInput.addEventListener('input', (e) => {
                self.states.classManagerBulkActionTargetExclude = e.target.value;
                self.setClassManagerBulkActionsList();
            })
        }
        [
            { selector: '#bulkActionsOptionsGroup', stateKey: 'classManagerBulkActionTargetGroup' },
            { selector: '#bulkActionsOptionsLock', stateKey: 'classManagerBulkActionLock' },
            { selector: '#bulkActionsOptionsHasStyles', stateKey: 'classManagerBulkActionHasStyles' },
            { selector: '#bulkActionsOptionsIsActive', stateKey: 'classManagerBulkActionIsActive' }
        ].forEach(({ selector, stateKey }) => {
            const select = canvas.querySelector(selector);
            self.helpers.selectControl(select, (target) => {
                self.states[stateKey] = target.dataset.value;
                self.setClassManagerBulkActionsList();
            });
        });

        const newGroup = document.querySelector('#brxc-bulkActionsNewGroup');
        if (newGroup){
            newGroup.addEventListener('keydown', () => {
                self.autocomplete(newGroup,self.vueState.globalClassesCategories.map(el => el && el.name),false);
            })
        } 
    },
    openClassManager: function(type) {
        const self = this;
        if(typeof self.vueState.globalClassesCategories === "undefined"){
            return alert('The class manager requires Bricks 1.9.5+ to be installed. Please upgrade your theme.')
        }


        self.removeDuplicateClass();
        self.states.classManagerType = type;
        self.openModal({target: false, id: "#brxcClassManagerOverlay", focus: "#brxcClassManagerOverlay input.class-filter", callback: () => {
            Promise.resolve()
                .then(() => {
                    if(self.states.classManagerUnusedClasses === false){
                        self.mountUnusedClasses();
                    }
                })
                .then(() => {
                    self.setClassManager();
                    self.setClassManagerBulk();
                })
        }})
    },
    setClassManager: function(){
        const self = this;
        self.states.classManagerMaxClasses = 50;
        self.setCatList();
        self.setClassList();
        self.setClassContent();
    },
    setCatList: function(){
        const self = this;
        const listWrapper = document.querySelector('#brxcClassManagerOverlay #brxcCatListCanvas');
        if(!listWrapper || !Array.isArray(self.states.classManagerCategories)) return;
        let cats = '<ul>';
        let categoryFound;
        let count;
        let isCatActive;

        function isActive (cat) {
            if(self.helpers.getClassCategoryIdByName(cat) === self.states.classManagerActiveCategory) return true;
            return false;
        }

        function exportBtn(isCatActive){
            if(!isCatActive) return '';
            return `${isCatActive ? `<div class="export${self.states.classManagerExportCSS ? ' active' : ''}" data-balloon="View Category CSS" data-balloon-pos="top-right"><i class="fab fa-css3-alt"></i></div>` : ''}`
        }

        // All
        if(!Array.isArray(self.vueState.globalClasses)) return;
        count = self.vueState.globalClasses.length;
        isCatActive = self.states.classManagerActiveCategory === "All";
        cats += `<li class="category ignore-drag${isCatActive ? ' active' : ''}"${isCatActive ? ' data-active="true"' : ''} data-id="All"><input type="text" value="All" readonly/><div class="action">${exportBtn(isCatActive)}<span class="count">${count}</span></div></li>`
        
        // Uncategorized
        isCatActive = self.states.classManagerActiveCategory === "Uncategorized";
        count = Array.from(self.vueState.globalClasses).filter(el => el && (!el.category || self.helpers.getClassCategoryObjById(el.category) === false)).length;
        cats += `<li class="category ignore-drag${self.states.classManagerActiveCategory === "Uncategorized" ? ' active' : ''}"${self.states.classManagerActiveCategory === "Uncategorized" ? ' data-active="true"' : ''} data-id="Uncategorized"><input type="text" value="Uncategorized" readonly/><div class="action">${exportBtn(isCatActive)}<span class="count">${count}</span></div></li>`

        // Categories
        const sortedCats = Array.from(self.vueState.globalClassesCategories).filter(el => el && el.name).map(el => el && el.name);
        cats += `<div id="sortableWrapper">`;
        sortedCats.forEach(cat => {
            categoryFound = self.helpers.getClassCategoryObjByName(cat)
            if(!categoryFound) return;
            isCatActive = categoryFound.id === self.states.classManagerActiveCategory;
            count = Array.from(self.vueState.globalClasses).filter(el => el && el.hasOwnProperty('category') && categoryFound && categoryFound.id === el.category).length;
            cats += `<li class="category custom${isActive(cat) ? ' active' : ''}"${isActive(cat) ? ' data-active="true"' : ''} data-id="${categoryFound.id}"><div class="handle"><i class="fas fa-grip-vertical"></i></div><input type="text" data-initial="${cat}" value="${cat}"${!isCatActive ? ' readonly' : ''}/><div class="action">${isCatActive ? `${exportBtn(isCatActive)}<div class="deleteCat" onClick="event.stopPropagation();ADMINBRXC.deleteCategory('${self.states.classManagerActiveCategory}')" data-balloon="Delete category" data-balloon-pos="top-right"><span class="bricks-svg-wrapper"><i class="ti-trash"></i></span></div>` : ``}<span class="count">${count}</span></div></li>`
            
        })
        cats += `</div>`;

        // Trash
        if(self.vueState.hasOwnProperty('globalClassesTrash') && Array.isArray(self.vueState.globalClassesTrash)){
            count = self.vueState.globalClassesTrash.length;
            cats += `<li class="category ignore-drag${self.states.classManagerActiveCategory === "Trash" ? 'active' : ''} trash"${self.states.classManagerActiveCategory === "Trash" ? ' data-active="true"' : ''} data-id="Trash"><i class="ti-trash"></i><input type="text" value="Trash" readonly/><span class="count">${count}</span></li>`
        }

        cats += '</ul><input type="text" id="addNewCat" placeholder="+ New category" onkeyup="ADMINBRXC.addNewCategory(event);" />';
        if (self.helpers.isAIActive() && self.globalSettings.isAIApiKeyEmpty !== "" && self.states.classManagerCategories.length > 1) cats += `<a class="brxc-overlay__action-btn" style="margin-top: 12px;" onclick="ADMINBRXC.classCategoriesAI(this);"><span>Assign with AI</span></a>`;
        listWrapper.innerHTML = cats;


        // Listeners
        const lists = listWrapper.querySelectorAll('li.category')
        lists.forEach(el => {
            el.addEventListener('click', (event) => {
                if(event.target.classList.contains('export')){
                    self.states.classManagerExportCSS = !self.states.classManagerExportCSS;
                    self.setCatList();
                    self.setClassContent();
                    return;
                }
                self.classManagerFilterCat(event);
            })
            if(el.classList.contains('custom')){
                el.addEventListener('dragover', (event) => {
                    event.preventDefault()
                })
                el.addEventListener('dragenter', (event) => {
                    el.classList.add('dragged');
                })
                el.addEventListener('dragleave', (event) => {
                    el.classList.remove('dragged');
                })
                el.addEventListener('drop', (event) => {
                    event.preventDefault();
                    self.onDropCatList(el);
                }) 
            }
        })

        // rename cat
        const input = listWrapper.querySelector('li.active input');
        if(input){
            input.addEventListener('keyup', (event) => {
                if(event.key !== "Enter") return;
                if(event.target.value === event.target.dataset.initial) return self.setCatList();
                if(self.states.classManagerCategories.includes(event.target.value)) return self.vueGlobalProp.$_showMessage(`ABORT: category "${event.target.value}" already exists`);
                const activeObj = self.helpers.getClassCategoryObjById(self.states.classManagerActiveCategory)
                if(!activeObj) return;
                activeObj.name = event.target.value;
                self.populateClassCategories();
                self.vueGlobalProp.$_showMessage(`Category correctly renamed to ${event.target.value}`)
                self.setCatList();
                self.setClassContent();
            })
        }

        //Drag and drop
        const rows = listWrapper.querySelectorAll('ul li .handle');
        if (!rows || rows.length < 1) return;

        const headerWrapper = listWrapper.querySelector('#sortableWrapper');
        new Sortable(headerWrapper, {
            selectedClass: "sortable-selected",
            animation: 150,
            filter: ".ignore-drag",
            handle: "li .handle",
            helper: 'clone',
            onStart: function (evt) {
                self.states.classManagerOnDrag = [{
                    id: evt.item.dataset.id,
                    type: "cat"
                }];
            },
            onEnd: (e) => {
                const originalObj = self.vueState.globalClassesCategories.find(el => el.id === self.states.classManagerOnDrag[0].id);
                const originalIndex = self.vueState.globalClassesCategories.indexOf(originalObj)
                self.helpers.moveArr(self.vueState.globalClassesCategories, originalIndex, e.newIndex);

                self.setCatList();
            },
        });
        
    },
    generateClassCategoriesAI: function (response){
        const self = this;
        const classes = JSON.parse(response).classes;
        const matchingClasses = classes.filter(el => el && el.hasOwnProperty('category') && el.category !== "noMatch" && self.helpers.getClassCategoryIdByName(el.category));
        if(matchingClasses.length > 0){
            matchingClasses.forEach(cls => {
                const obj = Array.from(self.vueState.globalClasses).find(el => el && el.hasOwnProperty('id') && cls.id === el.id);
                if (obj && (!obj.hasOwnProperty('category') || self.helpers.getClassCategoryObjById(obj.category) === false) ) {
                    obj.category = self.helpers.getClassCategoryIdByName(cls.category)
                } else {
                    console.log('Error')
                }
            })
        }
        self.populateClassCategories();
        self.setCatList();
        self.setClassList();
    },
    classCategoriesAI: function(target){
        const self = this;
        const obj = [];
        const defaultModel = self.globalSettings.defaultAIModel;
        self.vueState.globalClasses.forEach(cls => {
            if(!cls.hasOwnProperty('category') || self.helpers.getClassCategoryObjById(cls.category) === false){
                obj.push({
                    id: cls.id,
                    name: cls.name.replaceAll('__', ' ').replaceAll('_', ' ').replaceAll('--', ' ').replaceAll('-', ' '),
                })
            }
        })
        target.classList.add('disable');
        const categories = Array.from(self.vueState.globalClassesCategories).map(el => el && el.name)
        categories.shift();
        categories.push('Others');
        const json = {
            "model": defaultModel,
            "messages": [
              {
                "role":"user",
                "content": `Given the following object: ${JSON.stringify(obj)}. Assign each object to an existing category. Check the name provided in each object to determine if it can be related to a provided category. If no match is found, assign it to "noMatch".`,
              }
            ],
            "functions":[{
                "name":"generateClassCategoriesAI",
                "description":"Assign categories to objects.",
                "parameters":{
                   "type":"object",
                   "properties":{
                      "classes":{
                         "type":"array",
                         "items":{
                            "type":"object",
                            "properties":{
                               "id":{
                                  "type":"string",
                                  "description":"The object's ID"
                               },
                               "category":{
                                  "type":"string",
                                  "description":"The object's category",
                                  "enum": categories
                               }
                            }
                         }
                      }
                   },
                   "required":[
                      "classes"
                   ]
                }
             }],
            "function_call": "auto",
            "temperature": 0
          }

        jQuery.ajax({
            type: 'POST',
            url: openai_ajax_req.ajax_url,
            data: {
                action: 'openai_ajax_function',
                nonce: openai_ajax_req.nonce,
            },
            success: function(response) {
                const post = async () => {
                    const rawResponse = await fetch('https://api.openai.com/v1/chat/completions', {
                      method: 'POST',
                      headers: {
                          'Content-Type': 'application/json',
                          'Authorization' : 'Bearer '+ response,
                        },
                      body: JSON.stringify(json)
                    });
                    const content = await rawResponse.json();
                    if(content.error){
                        self.insertErrorMessage('classManager', false, '#brxcClassManagerOverlay', content.error.message);
                        target.classList.remove('disable');
                    } else {
                        target.classList.remove('disable');
                        self.generateClassCategoriesAI(content.choices[0].message.function_call.arguments);
                    }
                };
                post();
            },
            error: function(response){
                console.log('Something went wrong with the OpenAI AJAX request: ' + response);
                target.classList.remove('disable');
            }
        });
    },
    onDropCatList: function(target){
        const self = this;
        if(self.states.classManagerStartDrag && Array.isArray(self.states.classManagerStartDrag)){
            self.states.classManagerStartDrag.forEach(id => {
                const obj = self.vueGlobalProp.$_getGlobalClass(id);
                if(obj) obj.category = target.dataset.id;
            })
        }
        self.setCatList();
        self.setClassList();
        self.setClassContent();
    },
    onDropVariableCatList: function(target){
        const self = this;
        if (!self.cssVariablesStates.onDrag || !Array.isArray(self.cssVariablesStates.onDrag) || self.cssVariablesStates.onDrag.length === 0) {
            console.error('Error: onDrag object is null or empty - Please contact support.', self.cssVariablesStates.onDrag);
            return;
        }
        
        const updateCategory = (obj) => {
            if (obj) obj.category = target.dataset.id;
        };
        
        self.cssVariablesStates.onDrag.forEach(item => {
            if (!item || !item.type || !item.id) {
                console.error('Error: Invalid onDrag item detected - Please contact support.', item);
                return;
            }
        
            switch (item.type) {
                case "var":
                    updateCategory(self.helpers.getGlobalVariableObjById(item.id));
                    break;
                case "scale":
                    const objs = self.vueState.globalVariables.filter(el => el && el.scaleId === item.id);
                    objs.length > 0 ? objs.forEach(updateCategory) 
                                    : console.error(`Error: No matching global variable found for scaleId - Please contact support. "${item.id}"`);
                    break;
                case "group":
                    const groupVars = self.vueState.globalVariables.filter(el => el && el.group === item.id);
                    groupVars.length > 0 ? groupVars.forEach(updateCategory) 
                                    : console.error(`Error: No matching global variable found for Group - Please contact support. "${item.id}"`);
                    break;
            }
        });
        self.setCSSVariableManager();
    },
    deleteCategory: function(catId){
        const self = this;
        const obj = self.helpers.getClassCategoryObjById(catId);
        self.vueState.globalClassesCategories.splice(self.vueState.globalClassesCategories.indexOf(obj), 1);
        self.states.classManagerActiveCategory = "All";

        const cls = Array.from(self.vueState.globalClasses).filter(el => el && el.hasOwnProperty('category') && el.category === catId);
        let hasChanges = false
        cls.forEach(el => {
            hasChanges = true
            delete el.category;
        })
        if(hasChanges) self.helpers.saveChanges('globalClasses');

        self.populateClassCategories();
        self.setCatList();
        self.setClassList();
        self.setClassContent();
    },
    addNewCategory: function(event){
        const self = this;

        if(event.key !== "Enter") return;

        const values = event.target.value.split(',').map(item => item.trim());
        if(values.length < 1) return;

        let hasChanges = false;

        values.forEach(name => {
            if(Array.from(self.vueState.globalClassesCategories).map(obj => obj && obj.name).includes(name)) {
                return self.vueGlobalProp.$_showMessage('ABORT: category already exists');
            } else {
                hasChanges = true;
                self.helpers.createClassCategory(name);
                self.helpers.saveChanges('globalClasses');

            }
        })
        if(hasChanges === true) {
            //self.states.classManagerCategories.sort();
            self.states.classManagerActiveCategory = self.helpers.getClassCategoryIdByName(values[values.length - 1]);
            self.setCatList();
            self.setClassList();
        };  
    },
    classManagerFilterCat: function(event){
        const self = this;
        target = (event.target.dataset.id) ? event.target : event.target.parentElement;
        if(target.dataset.active === 'true') return;
        self.states.classManagerActiveCategory = target.dataset.id;
        self.setCatList();
        self.setClassList();
        if(self.states.classManagerExportCSS) self.setClassContent();
    },
    setClassList: function(){
        const self = this;
        const listWrapper = document.querySelector('#brxcClassManagerOverlay #brxcClassListCanvas');
        if(!listWrapper) return;
        const template = self.helpers.getTemplateType();
        const isClassTrash = self.vueState.hasOwnProperty('globalClassesTrash') && Array.isArray(self.vueState.globalClassesTrash);
        let count = 0;
        let classes = '<ul>';
        let globalClasses;
        const fullList = self.states.classManagerSearch === '' && self.states.classManagerType ===  "global" && self.states.classManagerFilterLocked === false && self.states.classManagerFilterActive === false && self.states.classManagerFilterStyle === false;

        // Type
        if(self.states.classManagerActiveCategory === "Trash"){
            globalClasses = self.vueState.globalClassesTrash;
        } else if(self.states.classManagerType === "global") {
            globalClasses = self.vueState.globalClasses;
         } else {
            globalClasses = [];
            const tempClasses = self.helpers.getComponentClasses([],self.builderStates.activeElement?.id);

            if(tempClasses.length > 0){
                tempClasses.forEach(el => {
                    const classObj = self.vueGlobalProp.$_getGlobalClass(el);
                    if(classObj) globalClasses.push(classObj)
                })
                globalClasses = globalClasses.concat(Array.from(self.vueState.globalClasses).filter(el => el && el.new === true))
            }
         }
         // Uncategorized
         if(self.states.classManagerActiveCategory === "Uncategorized"){
            globalClasses = Array.from(globalClasses).filter(el => el && (!el.category || self.helpers.getClassCategoryObjById(el.category) === false));
        
        // Cat
         } else if(self.states.classManagerActiveCategory !== "All" && self.states.classManagerActiveCategory !== "Trash"){
            globalClasses = Array.from(globalClasses).filter(el => el && el.hasOwnProperty('category') && el.category === self.states.classManagerActiveCategory);
         }

         // Search
        globalClasses = (self.states.classManagerSearch === '') ? globalClasses : Array.from(globalClasses).filter(el => el && el.name && el.name.includes(self.states.classManagerSearch));

        // Filter By Style
        if (self.states.classManagerFilterStyle === "has-styles") {
            globalClasses = Array.from(globalClasses).filter(el1 => el1 && self.vueGlobalProp.$_generateCss('globalClass',el1.id,['block']) !== '');
        } else if (self.states.classManagerFilterStyle === "has-no-styles"){
            globalClasses = Array.from(globalClasses).filter(el1 => el1 && self.vueGlobalProp.$_generateCss('globalClass',el1.id,['block']) === '');
        }

        // Filter By Active
        if (self.states.classManagerFilterActive === 'is-active') {
            globalClasses = Array.from(globalClasses).filter(el1 => el1 && Array.from(self.vueState[template]).find(el => el && el.settings._cssGlobalClasses && el.settings._cssGlobalClasses.includes(el1.id)));
        } else if (self.states.classManagerFilterActive === 'is-not-active') {
            globalClasses = Array.from(globalClasses).filter(el1 => {
                const matchingElements = Array.from(self.vueState[template]).filter(el => el &&
                  el.settings._cssGlobalClasses &&
                
                  el.settings._cssGlobalClasses.includes(el1.id)
                );
                return matchingElements.length === 0;
            });
        }
        
        // Filter By Status
        if(self.states.classManagerFilterLocked === "locked"){
            globalClasses = Array.from(globalClasses).filter(el => el && el.hasOwnProperty('id') && self.vueGlobalProp.$_isLocked(el.id));
        } else if(self.states.classManagerFilterLocked === "unlocked"){
            globalClasses = Array.from(globalClasses).filter(el => el && el.hasOwnProperty('id') && !self.vueGlobalProp.$_isLocked(el.id));
        }

        index = 1;
        globalClasses.slice(0, self.states.classManagerMaxClasses).forEach(cls => {

            const active = Array.from(self.vueState[template]).find(el => el && el.settings._cssGlobalClasses && el.settings._cssGlobalClasses.includes(cls.id)) ? 'active' : '';
            classes += `<li data-order="${index - 1}" class="${active}${self.states.classManagerActiveClass === cls.id ? ' selected' : ''}" data-id="${cls.id}">
                            <div class="span-wrapper" ${!fullList ? ` data-id="${cls.id}" draggable=true` : ''}>
                                <div class="handle"><i class="fas fa-grip-vertical"></i></div>
                                <span>.${cls.name}</span>
                            </div>
                            <div class="actions">`;
            classes += `${self.vueGlobalProp.$_generateCss('globalClass',cls,['block']) !== '' ? `<div class="css3-icon" data-balloon="Has styles assigned" data-balloon-pos="bottom-right""><span class="bricks-svg-wrapper"><i class="fab fa-css3-alt"></i></span></div>` : ''}
                        ${self.vueGlobalProp.$_isLocked(cls.id) ? `<div class="lock-icon" data-action="unlock" data-balloon="Unlock class" data-balloon-pos="bottom-right"><span class="bricks-svg-wrapper"><i class="fas fa-lock"></i></span></div>` : `<div class="unlock-icon" data-action="lock" data-balloon="Lock class" data-balloon-pos="bottom-right"><span class="bricks-svg-wrapper"><i class="fas fa-unlock"></i></span></div>`}`
            if(self.states.classManagerActiveCategory !== "Trash"){
                classes += `<div class="clone-icon" data-action="duplicate" data-balloon="Duplicate class" data-balloon-pos="bottom-right"><span class="bricks-svg-wrapper"><i class="fas fa-clone"></i></span></div>
                            <div class="clone-icon" data-action="copyClipboard" data-class-name="${cls.name}" data-balloon="Copy to Clipboard" data-balloon-pos="bottom-right"><span class="bricks-svg-wrapper"><i class="fas fa-clipboard"></i></span></div>`;
            } else {
                classes += `<div class="clone-icon" data-action="restore" data-balloon="Restore class" data-balloon-pos="bottom-right"><span class="bricks-svg-wrapper"><i class="fas fa-trash-restore"></i></span></div>`
            }
            classes += `<div class="trash-icon" data-action="delete" data-balloon="${isClassTrash && self.states.classManagerActiveCategory !== "Trash" ? 'Move to Trash' : 'Delete class permanently'}" data-balloon-pos="bottom-right"><span class="bricks-svg-wrapper"><i class="ti-trash"></i></span></div>
                            </div>
                        </li>`;
            if(index === self.states.classManagerMaxClasses && self.states.classManagerMaxClasses < globalClasses.length) classes += `<li class="ignore-drag" onclick="ADMINBRXC.loadMoreClasses(${globalClasses.length});ADMINBRXC.setClassList();"><div class="span-wrapper"><span class="max-results">Load ${globalClasses.length - 50} more classes....</span></div></li>`;
            index++;
        })
        classes += '</ul>';
        if(self.states.classManagerActiveCategory !== "Trash") classes += `<div class="brxc-class-manager__footer"><input type="text" id="addNewClass" placeholder="Add a new class" onkeyup="ADMINBRXC.addNewClass(event);" /></div>`;
        listWrapper.innerHTML = classes;

        // Listeners
        const classWrapper = listWrapper.querySelector('ul');
        classWrapper.addEventListener('click', (e) => {
            const action = e.target.closest('[data-action]');
            const clsId = e.target.closest('[data-id]')?.dataset.id;
            if(action && clsId){
                switch(action.dataset.action){
                    case 'unlock':
                        self.changeLockStatus(clsId, 'unlock');
                        break;
                    case 'lock':
                        self.changeLockStatus(clsId, 'lock');
                        break;
                    case 'duplicate':
                        self.duplicateClass(clsId);
                        break;
                    case 'copyClipboard':
                        const name = action.dataset.className;
                        self.copytoClipboardSimple(name,`${name} successfully copied to clipboard`);
                        break;
                    case 'restore':
                        self.restoreClass(clsId);
                        break;
                    case 'delete':
                        self.states.classManagerActiveCategory === "Trash" ? self.deleteClassPermanently(clsId) : self.deleteClass(clsId);
                        break;
                }

            } else if(clsId){
                e.stopPropagation();
                self.selectClass(clsId);
            }
        })

        //Drag and drop
        if(fullList){
            new Sortable(classWrapper, {
                multiDrag: true,
                selectedClass: "sortable-selected", // Class name for selected item
                animation: 150,
                handle: "li .handle",
                filter: ".ignore-drag",
                helper : 'clone',
                onStart: function (evt) {
                    self.states.classManagerStartDrag = evt.items.length > 0 ? evt.items.map(el => el.dataset.id) : [evt.item.dataset.id];
                },
                onEnd: function (evt) {
                    const items = Array.from(classWrapper.children).filter(child => child && !child.classList.contains('ignore-drag'));
                    const reorderedClasses = [];
                    const newOrder = items.map(item => parseInt(item.getAttribute('data-order')));
                    newOrder.forEach(el => {
                        const cls = self.vueState.globalClasses[el];
                        if(cls) reorderedClasses.push(cls);
                    })
                    reorderedClasses.forEach((el, ind) => {
                        if(el) self.vueState.globalClasses[ind] = JSON.parse(JSON.stringify(el));
                    })
                    self.setClassList();
                    self.setClassContent();
                    self.helpers.saveChanges('globalClasses');
                    setTimeout(() => evt.item.querySelector('.span-wrapper').click(), 0);
                },
            })
        } else {
            const items = listWrapper.querySelectorAll('ul li .span-wrapper');
            items.forEach(el => {
                el.addEventListener('mousedown', (e) => {
                    self.states.classManagerStartDrag = [el.dataset.id];
                })
            })
        }

    },
    setClassContent: function(del = false){
        const self = this;
        const contenttWrapper = document.querySelector('#brxcClassManagerOverlay #brxcClassContentCanvas');
        if(!contenttWrapper) return;
        const classId = self.states.classManagerActiveClass;
        const arr = self.states.classManagerActiveCategory === "Trash" ? self.vueState.globalClassesTrash : self.vueState.globalClasses;
        if(!Array.isArray(arr)) return;
        const obj = arr.find(el => el && el.id === classId);
        let viewButtons = '';
        let header = '';
        let status = '';
        let description = '';
        let usedPages = '';
        let used = '';
        let css = '';
        if(!obj && !self.states.classManagerExportCSS) return contenttWrapper.innerHTML = `<div class="notification">
                        <span class="bricks-svg-wrapper" data-name="no-results">
                            <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="bricks-svg">
                                <path d="M0.75 12a11.25 11.25 0 1 0 22.5 0 11.25 11.25 0 1 0 -22.5 0Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"></path>
                                <path d="M15.665 18.75a0.76 0.76 0 0 0 0.744 -0.9 4.5 4.5 0 0 0 -8.818 0 0.759 0.759 0 0 0 0.744 0.9Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"></path>
                                <path d="m6.75 6.75 3 3 -3.75 0" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"></path>
                                <path d="m17.25 6.75 -3 3 3.75 0" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"></path>
                            </svg>
                        </span>
                        <div class="message"><p>Select a class inside the left menu.</p></div>
                    </div>`;


        const target = self.helpers.createTarget('_cssCustom');
        const targetSass = self.helpers.createTarget('_cssCustomSass');
        
        // View Buttons
        viewButtons = `
            <div class="brxc-class-manager__view-wrapper">
                <div class="brxc-class-manager__view-btn${self.states.classManagerView === "class" ? ' active' : ''}" data-view="class">
                    <i class="ion-md-options"></i>
                    <span>Class Overview</span>
                </div>
                <div class="brxc-class-manager__view-btn${self.states.classManagerView === "css" ? ' active' : ''}" data-view="css">
                    <i class="fab fa-css3-alt"></i>
                    <span>Custom CSS</span>
                </div>
            </div>`
        if(self.states.classManagerExportCSS){
            viewButtons = `<div class="brxc-class-manager__content-css export">`;

            //Generated CSS
            let globalClasses = Array.isArray(self.vueState.globalClasses) ? self.vueState.globalClasses : [];
            let cssContent = '';
            if(self.states.classManagerActiveCategory === "All"){
                cssContent += globalClasses.map(obj => {
                    return self.helpers.removeCommentedCSS(self.vueGlobalProp.$_generateCss("globalClass", obj, ['block']));
                }).join('')
            } else if(self.states.classManagerActiveCategory === "Uncategorized"){
                cssContent += Array.from(globalClasses).filter(el => el && (!el.category || self.helpers.getClassCategoryObjById(el.category) === false)).map(obj => {
                    return self.helpers.removeCommentedCSS(self.vueGlobalProp.$_generateCss("globalClass", obj, ['block']));
                }).join('')
            } else {
                cssContent += globalClasses = Array.from(globalClasses).filter(el => el && el.hasOwnProperty('category') && el.category === self.states.classManagerActiveCategory).map(obj => {
                    return self.helpers.removeCommentedCSS(self.vueGlobalProp.$_generateCss("globalClass", obj, ['block']));
                }).join('')
            }
            
            const finalCSS = css_beautify(cssContent, { indent_size: 2 });
            viewButtons += `<div class="brxc-codemirror__wrapper"><textarea class="brxc-style-overview-css">${finalCSS}</textarea>`;
            viewButtons += `<div class="brxc-overlay__action-btn" style="margin-left: auto" onclick="ADMINBRXC.copytoClipboard(this, this.previousElementSibling.CodeMirror.getValue(), 'Copied!', 'Copy to Clipboard')"><span>Copy to Clipboard</span></div></div>`;
            viewButtons += '</div>'
        } else if(self.states.classManagerView === "class" && obj){
            // Header
            const showOrderInput = self.states.classManagerActiveCategory !== "Trash";
            const categoryName = obj.hasOwnProperty('category') && self.helpers.getClassCategoryNameById(obj.category) !== false
            ? self.helpers.getClassCategoryNameById(obj.category)
            : '';

            header = `
            <div class="brxc-class-manager__content-header">
                <div style="width: 100%;">
                <label class="brxc-input__label has-tooltip">
                    <span>Name</span>
                    <span class="brxc__light">(ID: ${obj.id})</span>
                    <div data-balloon="To rename the current class, just type the new name inside the input and press ENTER" data-balloon-pos="bottom-left" data-balloon-length="medium">
                    <i class="fas fa-circle-question"></i>
                    </div>
                </label>
                <input id="nameInput" type="text" value="${obj.name}"/>
                </div>

                <div style="width: 75%; position: relative;">
                <label class="brxc-input__label has-tooltip">
                    <span>Category</span>
                    <div data-balloon="To assign the class to specific category, just type the new name inside the input and press ENTER" data-balloon-pos="bottom" data-balloon-length="medium">
                    <i class="fas fa-circle-question"></i>
                    </div>
                </label>
                <input id="catInput" type="text" value="${categoryName}"/>
                </div>

                ${showOrderInput ? `
                <div style="position:relative;">
                    <label class="brxc-input__label has-tooltip">
                    <span>Order</span>
                    <div data-balloon="Changing this value will impact the order of the current class inside the Class Dropdown." data-balloon-pos="bottom-right" data-balloon-length="medium">
                        <i class="fas fa-circle-question"></i>
                    </div>
                    </label>
                    <div class="span-unit-wrapper">
                    <input type="text" id="orderInput" value="${arr.indexOf(obj) + 1}"/>
                    <span class="units">/ ${self.vueState.globalClasses.length}</span>
                    </div>
                </div>
                ` : ''}
            </div>`;

            // deleted at
            if (self.states.classManagerActiveCategory === "Trash") {
                const timestamp = obj.deletedAt;
                const date = new Date(timestamp);
                const humanDate = date.toLocaleDateString('en-US', {
                    year: 'numeric',
                    month: 'short',
                    day: 'numeric',
                    hour: '2-digit',
                    minute: '2-digit',
                });

                header += `
                    <div style="width: 100%;">
                        <label class="brxc-input__label">
                            <span>Deleted at</span>
                        </label>
                        <input id="deletedAtInput" type="text" value="${humanDate}" readonly />
                    </div>`;
            }

            // Description
            description = `
            <div class="brxc-class-manager__content-status-wrapper">
                <div class="brxc-class-manager__content-description">
                    <label class="brxc-input__label has-tooltip">
                    <span>Description</span>
                    <div data-balloon="Type a description of the class. This field is only for management purposes and has no effect on frontend" data-balloon-pos="bottom-left" data-balloon-length="medium">
                        <i class="fas fa-circle-question"></i>
                    </div>
                    </label>
                    <textarea placeholder="Give your class a description here" oninput="ADMINBRXC.updateClassDescription('${classId}', event.currentTarget.value);">${obj.hasOwnProperty('description') ? obj.description.trim() : ''}</textarea>
                </div>`;

            // Status
            const isLocked = self.vueGlobalProp.$_isLocked(classId);
            status = `
                <div class="brxc-class-manager__content-status">
                    <label class="brxc-input__label has-tooltip">
                        <span>Status</span>
                        <div data-balloon="Click on the following buttons to lock/unlock the current class" data-balloon-pos="bottom" data-balloon-length="medium">
                        <i class="fas fa-circle-question"></i>
                        </div>
                    </label>
                    <div class="brxc-overlay__action-btn-wrapper">
                        <div class="brxc-overlay__action-btn${isLocked ? ' primary' : ''}" onClick="ADMINBRXC.changeLockStatus('${classId}','lock');">Locked</div>
                        <div class="brxc-overlay__action-btn${!isLocked ? ' primary' : ''}" onClick="ADMINBRXC.changeLockStatus('${classId}','unlock');">Unlocked</div>
                    </div>
                </div>
            </div>`;

            
            // Class used on the following elements
            const fullArr = self.helpers.getPageContentAndPageComponents();
            const activeElements = fullArr.filter(el => el.obj && el.obj.hasOwnProperty('settings') && el.obj.settings.hasOwnProperty('_cssGlobalClasses') && el.obj.settings._cssGlobalClasses.includes(classId));
            if(activeElements.length > 0){
                used += `<div class="brxc-class-manager__content-used">
                            <label class="brxc-input__label">
                                <span>Class used on the following </span>
                                <span style="color:var(--builder-color-accent)">elements of this page</span>
                            </label>`;
                    used += `<ul class="brxc-overlay__action-btn-wrapper">`; 
                    activeElements.forEach(el => {
                        used += `<li ${el.hasOwnProperty('component') ? 'class="component"' : ''} onClick="ADMINBRXC.openElement('${el.obj.id}');ADMINBRXC.closeModal(event, event.target, '#brxcClassManagerOverlay');">
                                    <div class="icon"><i class="${bricksData.elements[el.obj.name]?.icon}"></i></div>
                                    <span>${el.obj.label ? self.helpers.escapeHtmlSpecialChars(el.obj.label) : bricksData.elements[el.obj.name]?.label}</span>
                                </li>`
                })
                    used += `</ul>
                        </div>`; 
            } else {
                used += `<div>
                            <label class="brxc-input__label">
                                <span>Class used on the following </span>
                                <span style="color:var(--builder-color-accent)">elements of this page</span>
                            </label>
                            <p class="no-result" data-control="info">This class isn't set on any element inside this page</p>
                        </div>`;
            }

            // Class used on the following Pages/Components

            if (self.states.classManagerUnusedClasses && Array.isArray(self.states.classManagerUnusedClasses) && self.states.classManagerUnusedClasses?.some(el => el.id === obj.id)) {
                usedPages += `
                    <div>
                        <label class="brxc-input__label"><span>Used on the whole website</span></label>
                        <p class="no-result" data-control="info">This class isn't attached to any element across all your posts, pages, templates & components.</p>
                    </div>
                `;
            } else {
                const items = self.helpers.getUsedPostsFromClassObj(obj);
                const components = self.helpers.getUsedComponentsFromClassObj(obj);

                usedPages += `
                    <div class="brxc-class-manager__content-used-sitewide">
                        <label class="brxc-input__label">
                            <span>Class used on the following </span>
                            <span style="color:var(--builder-color-accent)">posts/components across the website</span>
                        </label>
                        <ul class="brxc-overlay__action-btn-wrapper">
                `;

                if (items.length > 0) {
                    const addParamToUrl = (url, param) => {
                        return url.includes('?') ? `${url}&${param}` : `${url}?${param}`;
                    };
                    items.forEach(item => {
                        const postUrl = addParamToUrl(item.post_url, 'bricks=run');
                    
                        usedPages += `
                        <li>
                            <div class="icon">
                            ${item.post_type === "page" 
                                ? '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="bricks-svg"><path d="M17.625 23.25h-13.5a1.5 1.5 0 0 1 -1.5 -1.5V5.625" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path><path d="M21.375 18.159A1.8 1.8 0 0 1 19.625 20H7.375a1.8 1.8 0 0 1 -1.75 -1.841V2.591A1.8 1.8 0 0 1 7.375 0.75h8.9a1.711 1.711 0 0 1 1.238 0.539l3.349 3.524a1.888 1.888 0 0 1 0.513 1.3Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path></svg>'
                                : '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="bricks-svg"><path d="M20.25 9.75v-3a1.5 1.5 0 0 0 -1.5 -1.5H8.25v-1.5a1.5 1.5 0 0 0 -1.5 -1.5h-4.5a1.5 1.5 0 0 0 -1.5 1.5v16.3a1.7 1.7 0 0 0 3.336 0.438l2.351 -9.657A1.5 1.5 0 0 1 7.879 9.75H21.75a1.5 1.5 0 0 1 1.45 1.886l-2.2 9a1.5 1.5 0 0 1 -1.45 1.114H2.447" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path></svg>' }
                            </div>
                            <a href="${postUrl}" target="_blank">${item.post_title}</a>
                        </li>
                        `;
                    });
                }

                if (components.length > 0) {
                    components.forEach(component => {
                        const componentObj = self.vueGlobalProp.$_getComponentById(component.component_id);
                        if (!componentObj || !componentObj.elements.length) return;

                        const firstEl = componentObj.elements[0];
                        const label = firstEl.label || (bricksData.elements[firstEl.name]?.label || "Unnamed Component");

                        usedPages += `
                            <li class="component" onclick="ADMINBRXC.vueGlobalProp.$_setActiveComponent('${component.component_id}');ADMINBRXC.closeModal(event, event.target, '#brxcClassManagerOverlay');">
                                <div class="icon"><i class="${bricksData.elements[firstEl.name]?.icon || 'default-icon'}"></i></div>
                                <span>${label}</span>
                            </li>
                        `;
                    });
                }
                

                // If no posts or components were found, show "no result"
                if (items.length === 0 && components.length === 0) {
                    usedPages += `
                        <p class="no-result" data-control="info">
                            This class isn't attached to any element across posts, pages, templates, or components.
                        </p>
                    `;
                }

                usedPages += `</ul></div>`;
            }
            usedPages += '</div>';

            used += usedPages;
        } else if(self.states.classManagerView === "css" && obj){
            css = `<div class="brxc-class-manager__content-css">`;

            // Custom CSS
            if(self.states.classManagerActiveCategory !== "Trash"){
                css += `<div class="label-wrapper"><label class="brxc-input__label has-tooltip"><span>Custom CSS</span>${self.globalSettings.superPowerCSSEnableSass === "1" ? '<span class="highlight">SASS</span>' : ''}<div data-balloon="The following CSS will be applied to the current class and can be modified inside the Style tab -> Custom CSS control. Click the breakpoint icons to wrap your CSS code inside your desired media-query" data-balloon-pos="bottom-left" data-balloon-length="large"><i class="fas fa-circle-question"></i></div></label>`;
                css += `<ul class="action-wrapper">`;
                if(!self.vueGlobalProp.$_isLocked(obj.id)){
                    css += `<li class="brxc-group-icon${self.states.classManagerisAIopen ? ` active` : ""}" data-balloon="Generate CSS with AI" data-balloon-pos="bottom" onclick="ADMINBRXC.activateCSSAI();"><span class="bricks-svg-wrapper"><i class="bricks-svg fas fa-robot" style="width:100%;"></i></span></li>`;
                    css += `<li class="brxc-group-icon" data-balloon="Insert %root% {}" data-balloon-pos="bottom" onclick="ADMINBRXC.addRootTag(event, '.brxc-class-manager__content-css');"><span class="bricks-svg-wrapper"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" class="brxc__svg-path"><path d="M28.5 40v-3h6q1.05 0 1.775-.725Q37 35.55 37 34.5v-5q0-1.85 1.125-3.3 1.125-1.45 2.875-2v-.4q-1.75-.5-2.875-1.975T37 18.5v-5q0-1.05-.725-1.775Q35.55 11 34.5 11h-6V8h6q2.3 0 3.9 1.6t1.6 3.9v5q0 1.05.725 1.775Q41.45 21 42.5 21H44v6h-1.5q-1.05 0-1.775.725Q40 28.45 40 29.5v5q0 2.3-1.6 3.9T34.5 40Zm-15 0q-2.3 0-3.9-1.6T8 34.5v-5q0-1.05-.725-1.775Q6.55 27 5.5 27H4v-6h1.5q1.05 0 1.775-.725Q8 19.55 8 18.5v-5q0-2.3 1.6-3.9T13.5 8h6v3h-6q-1.05 0-1.775.725Q11 12.45 11 13.5v5q0 1.85-1.125 3.325T7 23.8v.4q1.75.55 2.875 2T11 29.5v5q0 1.05.725 1.775Q12.45 37 13.5 37h6v3Z"></path></svg></span></li>`;
                }
                
                css += `</ul><ul class="breakpoint-wrapper">`;
                self.vueState.breakpoints.forEach(bp =>{
                    let svg = '<span class="bricks-svg-wrapper"><svg version="1.1" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><path d="M27.744,2.5h-25.488c-0.968,0 -1.756,0.788 -1.756,1.755v17.489c0,0.968 0.788,1.755 1.756,1.755h12.244v3h-5.5c-0.276,0 -0.5,0.224 -0.5,0.5c0,0.276 0.224,0.5 0.5,0.5h12c0.276,0 0.5,-0.224 0.5,-0.5c0,-0.276 -0.224,-0.5 -0.5,-0.5h-5.5v-3h12.244c0.968,0 1.756,-0.788 1.756,-1.755v-17.489c0,-0.967 -0.788,-1.755 -1.756,-1.755Zm-1.244,18h-23v-15h23v15Z" fill="currentColor"></path></svg></span>';
                    if( bp.icon === "laptop") {
                        svg = '<span class="bricks-svg-wrapper"><svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><path d="M80.14,400c-17.7503,0 -32.14,-14.3897 -32.14,-32.14v-239.72c0,-17.7503 14.3897,-32.14 32.14,-32.14h351.72c17.7503,0 32.14,14.3897 32.14,32.14v239.72c0,17.7503 -14.3897,32.14 -32.14,32.14Z" stroke-width="32" stroke="currentColor" fill="none" stroke-linejoin="round"></path><path fill="currentColor" stroke="currentColor" stroke-linecap="round" stroke-width="32" d="M16,416h480"></path></svg></span>';
                    }
                    if( bp.icon === "tablet-landscape") {
                        svg = '<span class="bricks-svg-wrapper"><svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><g transform="matrix(1,0,0,1,0,512)"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M128,496c-26.5094,0 -48,-21.4906 -48,-48v-384c0,-26.5094 21.4906,-48 48,-48h256c26.5094,0 48,21.4906 48,48v384c0,26.5094 -21.4906,48 -48,48Z" transform="matrix(6.12323e-17,-1,1,6.12323e-17,0,0)"></path></g></svg></span>';
                    }
                    if( bp.icon === "tablet-portrait") {
                        svg = '<span class="bricks-svg-wrapper"><svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><path d="M128,496c-26.5094,0 -48,-21.4906 -48,-48v-384c0,-26.5094 21.4906,-48 48,-48h256c26.5094,0 48,21.4906 48,48v384c0,26.5094 -21.4906,48 -48,48Z" stroke-linecap="round" stroke-width="32" stroke="currentColor" fill="none" stroke-linejoin="round"></path></svg></span>';
                    }
                    if( bp.icon === "phone-landscape") {
                        svg = '<span class="bricks-svg-wrapper"><svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><g transform="matrix(1,0,0,1,0,512)"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M176,496c-26.5094,0 -48,-21.4906 -48,-48v-384c0,-26.5094 21.4906,-48 48,-48h160c26.5094,0 48,21.4906 48,48v384c0,26.5094 -21.4906,48 -48,48Z" transform="matrix(6.12323e-17,-1,1,6.12323e-17,0,0)"></path></g><path d="M16,336v-24l9.23706e-14,1.20797e-06c-6.67141e-07,-4.41828 3.58172,-8 8,-8v0h-6.99382e-07c8.83656,3.86258e-07 16,-7.16344 16,-16v-64v0c0,-8.83656 -7.16344,-16 -16,-16v0h-3.49691e-07c-4.41828,-1.93129e-07 -8,-3.58172 -8,-8c0,0 0,-2.84217e-14 0,-2.84217e-14v-24" stroke-linecap="round" stroke-width="32" stroke="currentColor" fill="none" stroke-linejoin="round"></path></svg></span>';
                    }
                    if( bp.icon === "phone-portrait") {
                        svg = '<span class="bricks-svg-wrapper"><svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><g stroke-linecap="round" stroke-width="32" stroke="currentColor" fill="none" stroke-linejoin="round"><path d="M176,496c-26.5094,0 -48,-21.4906 -48,-48v-384c0,-26.5094 21.4906,-48 48,-48h160c26.5094,0 48,21.4906 48,48v384c0,26.5094 -21.4906,48 -48,48Z"></path><path d="M176,16h24l-3.49691e-07,7.10543e-15c4.41828,-1.93129e-07 8,3.58172 8,8v0l1.7053e-13,2.41593e-06c1.33428e-06,8.83656 7.16345,16 16,16h64l-6.99382e-07,-1.42109e-14c8.83656,3.86258e-07 16,-7.16344 16,-16v0l1.13687e-13,1.20797e-06c-6.67141e-07,-4.41828 3.58172,-8 8,-8h24"></path></g></svg></span>';
                    }
                    let selector = `_cssCustom`;
                    if(bp.key !== 'desktop'){
                        selector += `:${bp.key}`;
                    }
                    css += `<li class="brxc-group-icon${self.vueState.breakpointActive === bp.key ? ' active' : ''}${obj.settings.hasOwnProperty(selector) && obj.settings[selector] !== '' ? ' has-styles' : ''}" data-balloon="${bp.label}" data-balloon-pos="bottom-right" onclick="ADMINBRXC.vueState.breakpointActive = '${bp.key}';ADMINBRXC.setClassContent();">${svg}</li>`;
                })
                css += '</ul></div>';
                if(self.states.classManagerisAIopen && !self.vueGlobalProp.$_isLocked(obj.id)) css += `<div id="submitCSSPromptWrapper"><input type="text" id="submitCSSPrompt" placeholder="Submit your prompt here and hit ENTER" onkeydown="ADMINBRXC.callAPIforClassManagerCSS(event)" /></div>`;
                let cssTarget = self.globalSettings.superPowerCSSEnableSass === "1" && obj.settings.hasOwnProperty('_cssCustomSass') ? targetSass : target;
                const textareaContent = obj.settings.hasOwnProperty(cssTarget) ? obj.settings[cssTarget] : '';
                css += `<div class="brxc-codemirror__wrapper"><textarea data-type="class-manager-custom-css">${self.vueGlobalProp.$_replaceCustomCssRoot('.' + obj.name,'%root%', textareaContent)}</textarea>`;
                css += `<div class="brxc-overlay__action-btn" style="margin-left: auto" onclick="ADMINBRXC.copytoClipboard(this, this.previousElementSibling.CodeMirror.getValue(), 'Copied!', 'Copy to Clipboard')"><span>Copy to Clipboard</span></div></div>`;
            }
            
            //Generated CSS
            css += `<label class="brxc-input__label has-tooltip"><span>Generated CSS</span><div data-balloon="The following CSS is the generated code by Bricks on the frontend, thus it's read-only" data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>`; 
            css += self.setStyleCSS("globalClass", obj, ['block']);
            css += '</div>'
        }
        
        contenttWrapper.innerHTML = viewButtons + header + description + status + used + css;
        
        // View Buttons
        const viewBtns = document.querySelectorAll('#brxcClassContentCanvas .brxc-class-manager__view-btn:not(.active)');
        viewBtns.forEach(viewBtn => {
            viewBtn.addEventListener('click', (e) => {
                self.states.classManagerView = e.target.dataset.view;
                self.setClassContent();
            })
        })

        // Custom CSS
        function mountCM(classId, isLocked){
            const customCSS = document.querySelector('textarea[data-type="class-manager-custom-css"]');
            if (customCSS) {
                const options = self.codeMirrorOptions(customCSS);
                options.styleActiveLine = true;
                options.autoCloseBrackets = true;
                options.matchBrackets = true;
                options.selfContain = true;
                options.autofocus = false;
                options.search = { bottom: false };
                options.profile = "xhtml";
                
                const MyCM = CodeMirror.fromTextArea(customCSS, self.codeMirrorOptions(options));
                emmetCodeMirror(MyCM);
                if (isLocked) {
                    MyCM.getWrapperElement().classList.add("disable");
                    MyCM.setOption('readOnly', true);
                }
        
                MyCM.getWrapperElement().setAttribute("data-type", "at");
                MyCM.setOption('gutters', []);
                MyCM.on("keydown", function (cm, event) {
                    if (!cm.state.completionActive &&
                        ((event.key >= '0' && event.key <= '9') ||    // Digits 0-9
                            (event.key >= 'a' && event.key <= 'z') ||    // Letters a-z
                            event.key === '(' || event.key === '!' ||    // Opening parenthesis (
                            event.key === '-') &&                        // Dash
                        !event.metaKey && !event.altKey && event.key !== '{' && event.key !== '}' &&
                        !event.ctrlKey) {
                        CodeMirror.commands.autocomplete(cm, null, { completeSingle: false });
                    }
    
                    if(event.metaKey && event.shiftKey && event.key === "7" ){
                        cm.toggleComment();
                    }
    
                    if (event.key === 'Tab') {
                        self.helpers.replaceRWithRoot(cm, event)
                    }
                })
                let sass = false;
                if(self.globalSettings.superPowerCSSEnableSass === "1"){
                    self.destroySassInstances();
                    sass = self.createSassInstance();
                }
    
                MyCM.on("keyup", function (cm) {
                    const obj = self.vueState.globalClasses.find(e => e.id === classId)
                    if (!obj) return;
    
                    const selector = `.${obj.name}`;
                    const newValue = self.vueGlobalProp.$_replaceCustomCssRoot('%root%', selector, cm.getValue());
    
                    if(Object.getPrototypeOf(obj.settings).length === 0) obj.settings = {};
    
                    if (newValue === "") {
                        delete obj.settings[target];
                        if(self.globalSettings.superPowerCSSEnableSass === "1") delete obj.settings[targetSass];
                    } else {
                        if(self.globalSettings.superPowerCSSEnableSass === "1"){
                            const dataOptions = { indent_size: 2 }
                            obj.settings[targetSass] = newValue;
    
                            // Compiled CSS
                            if(sass){
                                sass.compile( newValue, function(result) {
                                    if (result.status === 0) {
                                        const strippedComment = self.helpers.removeCommentedCSS(result.text) !== '' ? self.helpers.removeCommentedCSS(result.text) : false;
                                        if(strippedComment){
                                            const vanillaCSS = css_beautify( strippedComment, dataOptions);
                                            obj.settings[target] = vanillaCSS;
                                        }
                                    }
                                });
                            }
                        } else {
                            obj.settings[target] = newValue;
                        }
                    }
    
                    // Generated CSS
                    
                    const generatedCSS = contenttWrapper.querySelector('[data-type="generated-css"]');
                    const dataOptions = { indent_size: 2 }
                    setTimeout(() => {
                        generatedCSS.CodeMirror.setValue(css_beautify(self.vueGlobalProp.$_generateCss('globalClass', classId, ['block']).replaceAll('.brxe-block', ''), dataOptions))
                    }, 1);
                    
                    // Save Global Classes
                    self.helpers.saveChanges('globalClasses');
                });

                setTimeout(() => {
                    MyCM.refresh();
                }, 0)
            }
        }

         if(self.states.classManagerActiveCategory !== "Trash") mountCM(classId, self.vueGlobalProp.$_isLocked(classId))

        //Generated CSS
        const textarea = contenttWrapper.querySelector('textarea.brxc-style-overview-css');
        if(textarea) {
            const dataOptions = { indent_size: 2 }
            const dataObj = textarea.textContent.replaceAll('.brxe-block', '');
            const options = self.codeMirrorOptions(textarea);
            options.autofocus = false;
            const MyCM = CodeMirror.fromTextArea(textarea, self.codeMirrorOptions(options));
            MyCM.getWrapperElement().setAttribute('data-type', 'generated-css');
            MyCM.getWrapperElement().classList.add("disable");
            MyCM.setValue(css_beautify(dataObj, dataOptions));
            MyCM.setOption('readOnly',  true);
            MyCM.setOption('gutters', []);
            setTimeout(() => {
                MyCM.refresh();
            }, 0)
            
        };

        // Name event
        const nameInput = contenttWrapper.querySelector('#nameInput');
        if(nameInput){
            nameInput.addEventListener('keyup', function(e){
                if (e.key === 'Enter'){

                    function replaceRootCustomCss(target, obj, oldName, newName){
                        if(obj.settings.hasOwnProperty(target)) return obj.settings[target] = obj.settings[target].replaceAll(`.${oldName}`, `.${newName}`);
            
                    }
                    function loopCustomCss(obj, oldName, newName){
                        let target = "_cssCustom";
                        if(obj.settings.hasOwnProperty(target)) replaceRootCustomCss(target, obj, oldName, newName);
                        const bps = self.vueState.breakpoints
                        bps.forEach(bp => {
                            target += `:${bp.key}`;
                            if(obj.settings.hasOwnProperty(target)) replaceRootCustomCss(target, obj, oldName, newName);
                        })
                    }

                    const arr = self.states.classManagerActiveCategory === "Trash" ? self.vueState.globalClassesTrash : self.vueState.globalClasses;
                    const obj = self.helpers.isClassActive() && self.vueState.activeClass.id === self.states.classManagerActiveClass ? self.vueState.activeClass : arr.find(el => el && el.hasOwnProperty('id') && el.id === self.states.classManagerActiveClass);
                    if(!obj || !obj.hasOwnProperty('name')) return;

                    const oldName = obj.name;
                    if(nameInput.value.length < 1) return self.vueGlobalProp.$_showMessage('Insert at least 1 character');
                    if(!self.helpers.isValidCSSClassName(nameInput.value)) return self.vueGlobalProp.$_showMessage('Invalid Character in the class name');
                    if(oldName === nameInput.value) return;
                    if(Array.from(self.vueState.globalClasses).find(el => el && el.hasOwnProperty('name') && el.name === nameInput.value)) return self.vueGlobalProp.$_showMessage('Class Name already exists!');
                    
                    obj.name = nameInput.value;
                    loopCustomCss(obj, oldName, nameInput.value);
                    self.setClassList();
                    self.setClassContent();
                    self.vueGlobalProp.$_showMessage('Class successfully renamed!');
                    self.helpers.saveChanges('globalClasses');
                }
            })
        }

        // Cat event
        const catInput = contenttWrapper.querySelector('#catInput');
        if(catInput){
            catInput.addEventListener('keyup', function(e){
                if (e.key === 'Enter'){
                    const arr = self.states.classManagerActiveCategory === "Trash" ? self.vueState.globalClassesTrash : self.vueState.globalClasses;
                    const obj = arr.find(el => el && el.hasOwnProperty('id') && el.id === self.states.classManagerActiveClass);
                    if(!obj) return;

                    const oldCat = obj.category;
                    const oldCatObj = self.helpers.getClassCategoryNameById(oldCat);
                    if(catInput.value.length < 1) {
                        delete obj.category;
                        return self.vueGlobalProp.$_showMessage('Category successfully removed!')
                    }
                    if(oldCat && oldCatObj.name === catInput.value) return;
                    let newCatId;
                    if(!Array.from(self.vueState.globalClassesCategories).map(el => el && el.name).includes(catInput.value)) {
                        newCatId = self.vueGlobalProp.$_generateId()
                        self.vueState.globalClassesCategories.push({
                            id: newCatId,
                            name: catInput.value,
                        })
                        obj.category = newCatId;
                        self.states.classManagerActiveCategory = newCatId;
                    } else {
                        newCatId = self.helpers.getClassCategoryIdByName(catInput.value);
                        obj.category = newCatId;
                    }
                    self.states.classManagerActiveCategory = newCatId;
                    self.populateClassCategories();
                    self.setCatList();
                    self.setClassList();
                    self.setClassContent();
                    self.vueGlobalProp.$_showMessage(`Class successfully assigned to the category ${catInput.value}!`);
                    self.helpers.saveChanges('globalClasses');
                }
            })
            catInput.addEventListener('keydown', () =>{
                self.autocomplete(catInput,Array.from(self.vueState.globalClassesCategories).map(el => el && el.name),false)
            })
        }

        // Order event
        const orderInput = contenttWrapper.querySelector('#orderInput');
        if(orderInput){
            orderInput.addEventListener('keyup', function(e){
                if (e.key === 'Enter'){
                    self.changeClassOrder(self.states.classManagerActiveClass,parseInt(orderInput.value - 1) );
                    self.helpers.saveChanges('globalClasses');
                }
            })
        }
    },
    updateClassDescription(classId, value){
        const self = this;
        const arr = self.states.classManagerActiveCategory === "Trash" ? self.vueState.globalClassesTrash : self.vueState.globalClasses;
        const classObj = arr.find(el => el && el.hasOwnProperty('id') && el.id === classId);
        classObj.description = value.trim();
    },
    applyCSSAIgenerated: function(generatedCSS){
        const self = this;
        const target = self.helpers.createTarget('_cssCustom');
        const css = JSON.parse(generatedCSS).css;
        const arr = self.states.classManagerActiveCategory === "Trash" ? self.vueState.globalClassesTrash : self.vueState.globalClasses;
        const classObj = arr.find(el => el && el.hasOwnProperty('id') && el.id === self.states.classManagerActiveClass);
        if(classObj) classObj.settings[target] = css_beautify(css, { indent_size: 2 });
        setTimeout(self.setClassContent(), 5);
    },
    callAPIforClassManagerCSS: function(event,target){
        const self = this;
        if(event.key !== "Enter") return;
        const input = (event.target.value.length > 0) ? `${event.target.value}` : '';
        if (input === '') return;
        const defaultModel = self.globalSettings.defaultAIModel;
        const wrapper = document.querySelector('#submitCSSPromptWrapper');
        var z = document.createElement('span'); // is a node
        z.setAttribute('class', 'brxc-overlay__action-btn primary disable');
        wrapper.appendChild(z);
        const arr = self.states.classManagerActiveCategory === "Trash" ? self.vueState.globalClassesTrash : self.vueState.globalClasses;
        const activeClassObj = arr.find(el => el && el.hasOwnProperty('id') && el.id === self.states.classManagerActiveClass);
        if(!activeClassObj) return;
        const activeClassName = activeClassObj.name
        const cm = document.querySelector('textarea[data-type="class-manager-custom-css"] + .CodeMirror').CodeMirror;
        const existingCSS = self.vueGlobalProp.$_replaceCustomCssRoot('%root%', `.${activeClassName }`,cm.getValue());

        let message = `Add CSS code targeting the class .${activeClassName}. The CSS code should do this:${input}.`
        if(existingCSS !== '') message += `The existing CSS code is the following: ${existingCSS}. Please merge your code with the existing one in a unique declaration (if possible).`;
    
        //target.classList.add('disable');
        const json = {
            "model": defaultModel,
            "messages": [
              {
                "role": "user",
                "content": `${message}`
              }
            ],
            "functions":[{
                "name":"applyCSSAIgenerated",
                "description":"Generate CSS code based on the instructions provided.",
                "parameters":{
                   "type":"object",
                   "properties":{
                        "css":{
                            "type":"string",
                            "description":"The CSS code"
                        }
                   }
                }
             }],
            "function_call": "auto" 
          }

        jQuery.ajax({
            type: 'POST',
            url: openai_ajax_req.ajax_url,
            data: {
                action: 'openai_ajax_function',
                nonce: openai_ajax_req.nonce,
            },
            success: function(response) {
                const post = async () => {
                    const rawResponse = await fetch('https://api.openai.com/v1/chat/completions', {
                      method: 'POST',
                      headers: {
                          'Content-Type': 'application/json',
                          'Authorization' : 'Bearer '+ response,
                        },
                      body: JSON.stringify(json)
                    });
                    const content = await rawResponse.json();
                    const disable = document.querySelector('#submitCSSPromptWrapper .brxc-overlay__action-btn.primary.disable');
                    disable.remove();
                    if(content.error){
                        self.insertErrorMessage('classManager', false, '#brxcClassManagerOverlay', content.error.message);
                    } else {
                        self.applyCSSAIgenerated(content.choices[0].message.function_call.arguments);
                    }
                };
                post();
            },
            error: function(response){
                console.log('Something went wrong with the OpenAI AJAX request: ' + response);
                target.classList.remove('disable');
            }
        });


    },
    activateCSSAI: function(){
        const self = this;
        self.states.classManagerisAIopen ? self.states.classManagerisAIopen = false : self.states.classManagerisAIopen = true;
        self.setClassContent();
    },
    savePost: function(btn){
        const self = this;
        self.vueGlobalProp.$_savePost();
        btn.classList.add('disable');
        setTimeout(() => {
            btn.classList.remove('disable');
        }, 2000)
    },
    duplicateClass: function(classId){
        const self = this;
        const originalObj = self.vueGlobalProp.$_getGlobalClass(classId);
        if(!originalObj) return;

        const obj = JSON.parse(JSON.stringify(originalObj));
        const objOrder = self.vueState.globalClasses.indexOf(originalObj);

        function generateUniqueName(baseName) {
            let name = `${baseName}-copy`;
            while (self.vueState.globalClasses.some(cls => cls?.name === name)) {
                name += "-copy";
            }
            return name;
        }

        const newId = self.vueGlobalProp.$_generateId();
        const newName = generateUniqueName(obj.name);
        const newClass = {
            ...obj,
            id: newId,
            name: newName,
            new: true,
            settings: JSON.parse(JSON.stringify(obj.settings).replaceAll(`.${obj.name}`, `.${newName}`)),
        };
        delete newClass.at_framework;
        delete newClass.at_version;

        self.vueState.globalClasses.push(newClass);

        self.helpers.moveArr(
            self.vueState.globalClasses,
            self.vueState.globalClasses.length - 1,
            Math.min(objOrder + 1, self.vueState.globalClasses.length - 1),
            1
        );

        setTimeout(() => {
            self.helpers.saveChanges('globalClasses');
            self.states.classManagerActiveClass = newId;
            self.setClassList();
            self.setClassContent();
            self.setCatList();
        }, 10);
        

    },
    addNewClass: function(event){
        const self = this;

        if(event.key !== "Enter") return;
        const values = event.target.value.split(' ');
        if(values.length < 1) return;

        values.forEach(el => {
            if(!self.helpers.isValidCSSClassName(el)) return self.vueGlobalProp.$_showMessage('Invalid Character in the class name');
            const exist = Array.from(self.vueState.globalClasses).find(el2 => el2 && el2.hasOwnProperty('name') && el2.name === el);
            if(typeof exist === "object") {
                self.states.classManagerActiveClass = exist.id;
                if(self.states.classManagerActiveCategory && self.states.classManagerActiveCategory !== "All" && self.states.classManagerActiveCategory !== "Uncategorized") exist.category = self.states.classManagerActiveCategory;
                
                self.vueGlobalProp.$_showMessage('Class already exists');
            } else {
                const id = self.vueGlobalProp.$_generateId();
                const obj = {
                    id: id,
                    name: el,
                    settings: {},
                    new: true,
                };
                if(self.states.classManagerActiveCategory && self.states.classManagerActiveCategory !== "All" && self.states.classManagerActiveCategory !== "Uncategorized") obj.category = self.states.classManagerActiveCategory;
                
                self.vueState.globalClasses.push(obj);
                self.states.classManagerActiveClass = id;
                self.vueGlobalProp.$_showMessage('Class successfully created');
            }
        })
        setTimeout(() => {
            self.setClassContent();
            self.setClassList();
            self.setCatList();
        },10)  
    },
    deleteClass: function(classId){
        const self = this;

        // Move to Trash
        if(self.vueState.hasOwnProperty('globalClassesTrash') && Array.isArray(self.vueState.globalClassesTrash) && self.states.classManagerActiveCategory !== "Trash"){
            self.vueGlobalProp.$_moveGlobalClassesToTrash(classId);
        
        // Remove class from Global Classes
        } else {
            const arr =  self.states.classManagerActiveCategory === "Trash" ? self.vueState.globalClassesTrash : self.vueState.globalClasses;
            const classObj = arr.find(el => el && el.id === classId);
            if(!classObj) return;

            const classIndex = parseInt(arr.indexOf(classObj));

            // Remove class from Global Classes
            arr.splice(classIndex,1);
        }

        if(self.states.classManagerActiveClass === classId) self.states.classManagerActiveClass = '';

        setTimeout(()=> {
            self.setClassList();
            self.setClassContent(true);
            self.setCatList();
        },10)

    },
    deleteClassPermanently: function(classId) {
        const self = this;
    
        if (self.states.classManagerActiveClass === classId) self.states.classManagerActiveClass = '';
    
        self.vueGlobalProp.$_deleteClassesPermanently(classId)
            .then(() => {
                setTimeout(() => {
                    self.setClassList();
                    self.setClassContent(true);
                    self.setCatList();
                }, 0);
            })
            .catch(error => {
                console.error("Error deleting class:", error);
            });
    },
    restoreClass: function(classId){
        const self = this;

        self.vueGlobalProp.$_restoreGlobalClasses(classId);

        setTimeout(()=> {
            self.setClassList();
            self.setClassContent(true);
            self.setCatList();
        },10)

    },
    selectClass: function(classId){
        const self = this;
        self.states.classManagerActiveClass = classId;
        const lists = document.querySelectorAll('#brxcClassListCanvas li');
        lists.forEach(list => {
            list.classList.remove('selected');
        })
        const selected = document.querySelector(`#brxcClassListCanvas li[data-id="${classId}"]`);
        if(selected) selected.classList.add('selected');
        self.setClassContent()
    },
    changeClassOrder: function(classId, newOrder){
        const self = this;
        const classObj = self.vueGlobalProp.$_getGlobalClass(classId);
        if(!classObj) return;

        const oldOrder = self.vueState.globalClasses.indexOf(classObj);
        if(oldOrder === newOrder){
            return;
        } else{
            self.helpers.moveArr(self.vueState.globalClasses, oldOrder, newOrder, 1);
            self.vueGlobalProp.$_showMessage('Class order successfullt changed');
        }
        self.helpers.saveChanges('globalClasses');
        self.setClassList();

    },
    changeLockStatus: function(classId, status){
        const self = this;
        if (status === "lock" && !self.vueState.globalClassesLocked.includes(classId)){
            self.vueState.globalClassesLocked.push(classId);
            self.vueGlobalProp.$_showMessage('Class successfully locked');
        } else if(status === "unlock" && self.vueState.globalClassesLocked.includes(classId)){
            const index = self.vueState.globalClassesLocked.indexOf(classId);
            self.vueState.globalClassesLocked.splice(index,1);
            self.vueGlobalProp.$_showMessage('Class successfully unlocked');
        }
        self.helpers.saveChanges('globalClassesLocked');
        self.setClassContent();
        self.setClassList();

    },
    openElement: function(id){
        const self = this;
        const obj = self.helpers.getElementObject(id)
        self.vueState.activePanel = "element";
        self.vueState.activeId = id;
        self.vueState.activeElement = obj;

        if(self.vueState.hasOwnProperty('components') && self.vueState.components.some(el => el.id === id)){
            self.vueState.activeComponent = self.vueState.components.find(el => el.id === id);
        }

        if(self.helpers.isElementInComponent(id)){
            self.vueState.activeComponent = self.helpers.getComponentByElementId(id)
        }

        // const el = FRAMEBRXC.vueGlobalProp.$_getElementNode(obj);
        // if(el){
        //     setTimeout(()=>{
        //         el.scrollIntoView({ behavior: "smooth"});
        //     },10)
        // }
        
    },
    filterClassesByStyle: function(btn){
        const self = this;
        if (self.states.classManagerFilterStyle === false){
            self.states.classManagerFilterStyle = "has-no-styles";
            btn.classList.add("locked");
        } else if (self.states.classManagerFilterStyle === "has-no-styles"){
            self.states.classManagerFilterStyle = "has-styles";
            btn.classList.remove("locked")
            btn.classList.add("unlocked");
        } else {
            self.states.classManagerFilterStyle = false;
            btn.classList.remove("unlocked")
        }
        self.setClassList();
    },
    filterClassesByActive: function(btn){
        const self = this;
        if (self.states.classManagerFilterActive === false){
            self.states.classManagerFilterActive = "is-not-active";
            btn.classList.add("locked");
        } else if (self.states.classManagerFilterActive === "is-not-active"){
            self.states.classManagerFilterActive = "is-active";
            btn.classList.remove("locked")
            btn.classList.add("unlocked");
        } else {
            self.states.classManagerFilterActive = false;
            btn.classList.remove("unlocked")
        }
        self.setClassList();
    },
    filterClassesByStatus: function(btn){
        const self = this;
        if (self.states.classManagerFilterLocked === false){
            self.states.classManagerFilterLocked = "locked";
            btn.classList.add("locked");
        } else if (self.states.classManagerFilterLocked === "locked"){
            self.states.classManagerFilterLocked = "unlocked";
            btn.classList.remove("locked")
            btn.classList.add("unlocked");
        } else {
            self.states.classManagerFilterLocked = false;
            btn.classList.remove("unlocked")
        }
        self.setClassList();
    },
    resetFilter: function(btn){
        const self = this;
        btn.parentElement.previousElementSibling.previousElementSibling = '';
        self.states.classManagerSearch = '';
        self.states.classManagerFilterLocked = false;
        self.states.classManagerFilterActive = false;
        self.states.classManagerFilterStyle = false;
        self.setClassList();
    },
    elementsColStates: {
        col: 1,
    },
    setColumnNumber: function(saveToDB = true){
        const self = this;
        let wrapper = document.querySelector('#bricks-panel-elements #bricks-panel-elements-categories');
        if(!wrapper) return;
        wrapper.setAttribute('data-col', self.elementsColStates.col);
        if(saveToDB) self.helpers.setLocalStorage('elementsColumns', self.elementsColStates.col );
        self.setElementsColumns()
    },
    collapseElementsState : 'collapse',
    collapseElements: function(){
        const self = this;
        const panel = document.querySelector('#bricks-panel-elements');
        if(!panel) return;

        const cats = panel.querySelectorAll('#bricks-panel-elements-categories li.category');
        if(!cats || cats.lentgh < 1) return;
        
        if(self.collapseElementsState === "collapse"){
            cats.forEach(cat => {
                const title = cat.querySelector('.category-title ');
                if(!title) return;
                if(title.classList.contains('expand')){
                    const svg = cat.querySelector('.wrap + span.bricks-svg-wrapper')
                    if(!svg) return;
                    svg.click();
                }
            })
            self.collapseElementsState = "expand";
        } else {
            cats.forEach(cat => {
                const title = cat.querySelector('.category-title ');
                if(!title) return;
                if(!title.classList.contains('expand')){
                    const svg = cat.querySelector('.wrap + span.bricks-svg-wrapper')
                    if(!svg) return;
                    svg.click();
                }
            })
            self.collapseElementsState = "collapse";
        }
    },
    setElementsColumns: function(){
        const self = this;
        if (self.vueState.activePanel !== 'elements') return;

        const header = document.querySelector('#bricks-panel-inner #bricks-panel-elements #bricks-panel-header')
        if(!header) return;

        const oldMenu = document.querySelector('#bricks-panel-view');
        if(oldMenu) oldMenu.remove();
    
        const wrapper = document.createElement("UL");
        wrapper.setAttribute("id", "bricks-panel-view");
        header.after(wrapper);

        const setClass = (num) => {
            let cls = 'brxc-header-icon brxc-header-icon__hover';
            if(num == self.elementsColStates.col){
                cls += " active"
            }
            return cls;
        }
        self.addIconToFields('li',setClass(1), false, '1-col', 'bottom-right', 'ADMINBRXC.elementsColStates.col = 1;ADMINBRXC.setColumnNumber()', true, '<span class="bricks-svg-wrapper"><i class="ti-layout-column3-alt"></i></span>', wrapper, 'child');
        self.addIconToFields('li',setClass(2), false, '2-col', 'bottom-right', 'ADMINBRXC.elementsColStates.col = 2;ADMINBRXC.setColumnNumber()', true, '<span class="bricks-svg-wrapper"><i class="ti-layout-column2-alt"></i></span>', wrapper, 'child');
        self.addIconToFields('li',setClass(3), false, '3-col', 'bottom-right', 'ADMINBRXC.elementsColStates.col = 3;ADMINBRXC.setColumnNumber()', true, '<span class="bricks-svg-wrapper"><i class="ti-layout-column3-alt"></i></span>', wrapper, 'child');
        self.addIconToFields('li',setClass(4), false, '4-col', 'bottom-right', 'ADMINBRXC.elementsColStates.col = 4;ADMINBRXC.setColumnNumber()', true, '<span class="bricks-svg-wrapper"><i class="ti-layout-column4-alt"></i></span>', wrapper, 'child');
        
        const expandSVG = '<span class="bricks-svg-wrapper"><svg version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><g fill="currentColor" fill-rule="evenodd"><path d="M2,8l5.32907e-15,7.54979e-08c-4.16963e-08,-0.276142 0.223858,-0.5 0.5,-0.5h11l-2.18557e-08,8.88178e-16c0.276142,-1.20706e-08 0.5,0.223858 0.5,0.5c1.20706e-08,0.276142 -0.223858,0.5 -0.5,0.5h-11l-2.78181e-08,-3.55271e-15c-0.276142,-4.49893e-08 -0.5,-0.223858 -0.5,-0.5Zm6,-1.5l-2.18557e-08,-8.88178e-16c0.276142,1.20706e-08 0.5,-0.223858 0.5,-0.5v-4.5v0c0,-0.276142 -0.223858,-0.5 -0.5,-0.5c-0.276142,0 -0.5,0.223858 -0.5,0.5v4.5l5.32907e-15,7.54979e-08c4.16963e-08,0.276142 0.223858,0.5 0.5,0.5Z"></path><path d="M10.354,3.854l2.23014e-08,-2.2245e-08c0.195509,-0.195015 0.195909,-0.511597 0.000893739,-0.707106c-0.000297551,-0.000298304 -0.000595479,-0.000596232 -0.000893784,-0.000893784l-2,-2l4.41373e-09,4.4249e-09c-0.195015,-0.195509 -0.511597,-0.195909 -0.707106,-0.000893793c-0.000298304,0.000297551 -0.000596232,0.000595479 -0.000893784,0.000893784l-2,2l-2.1107e-09,2.1107e-09c-0.195509,0.195509 -0.195509,0.512491 4.22141e-09,0.708c0.195509,0.195509 0.512491,0.195509 0.708,-4.22141e-09l1.646,-1.647l1.646,1.647l-3.52833e-08,-3.53726e-08c0.195015,0.195509 0.511597,0.195909 0.707106,0.000893854c0.000298304,-0.000297551 0.000596233,-0.000595479 0.000893784,-0.000893784Zm-2.354,5.646h-2.18557e-08c0.276142,-1.20706e-08 0.5,0.223858 0.5,0.5v4.5v0c0,0.276142 -0.223858,0.5 -0.5,0.5c-0.276142,0 -0.5,-0.223858 -0.5,-0.5v-4.5l5.32907e-15,7.54979e-08c-4.16963e-08,-0.276142 0.223858,-0.5 0.5,-0.5Z"></path><path d="M10.354,12.146l2.23014e-08,2.2245e-08c0.195509,0.195015 0.195909,0.511597 0.000893739,0.707106c-0.000297551,0.000298304 -0.000595479,0.000596232 -0.000893784,0.000893784l-2,2l4.41373e-09,-4.4249e-09c-0.195015,0.195509 -0.511597,0.195909 -0.707106,0.000893793c-0.000298304,-0.000297551 -0.000596232,-0.000595479 -0.000893784,-0.000893784l-2,-2l-2.1107e-09,-2.1107e-09c-0.195509,-0.195509 -0.195509,-0.512491 4.22141e-09,-0.708c0.195509,-0.195509 0.512491,-0.195509 0.708,4.22141e-09l1.646,1.647l1.646,-1.647l-3.52833e-08,3.53726e-08c0.195015,-0.195509 0.511597,-0.195909 0.707106,-0.000893854c0.000298304,0.000297551 0.000596233,0.000595479 0.000893784,0.000893784Z"></path></g></svg></span>';
        const collapseSVG = '<span class="bricks-svg-wrapper"><svg version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><g fill="currentColor" fill-rule="evenodd"><path d="M2,8l5.32907e-15,7.54979e-08c-4.16963e-08,-0.276142 0.223858,-0.5 0.5,-0.5h11l-2.18557e-08,8.88178e-16c0.276142,-1.20706e-08 0.5,0.223858 0.5,0.5c1.20706e-08,0.276142 -0.223858,0.5 -0.5,0.5h-11l-2.78181e-08,-3.55271e-15c-0.276142,-4.49893e-08 -0.5,-0.223858 -0.5,-0.5Zm6,-7h-2.18557e-08c0.276142,-1.20706e-08 0.5,0.223858 0.5,0.5v4.5v0c0,0.276142 -0.223858,0.5 -0.5,0.5c-0.276142,0 -0.5,-0.223858 -0.5,-0.5v-4.5l5.32907e-15,7.54979e-08c-4.16963e-08,-0.276142 0.223858,-0.5 0.5,-0.5Z"></path><path d="M10.354,3.646l2.23014e-08,2.2245e-08c0.195509,0.195015 0.195909,0.511597 0.000893739,0.707106c-0.000297551,0.000298304 -0.000595479,0.000596232 -0.000893784,0.000893784l-2,2l4.41373e-09,-4.4249e-09c-0.195015,0.195509 -0.511597,0.195909 -0.707106,0.000893793c-0.000298304,-0.000297551 -0.000596232,-0.000595479 -0.000893784,-0.000893784l-2,-2l-2.1107e-09,-2.1107e-09c-0.195509,-0.195509 -0.195509,-0.512491 4.22141e-09,-0.708c0.195509,-0.195509 0.512491,-0.195509 0.708,4.22141e-09l1.646,1.647l1.646,-1.647l-3.52833e-08,3.53726e-08c0.195015,-0.195509 0.511597,-0.195909 0.707106,-0.000893854c0.000298304,0.000297551 0.000596233,0.000595479 0.000893784,0.000893784Zm-2.354,11.354h-2.18557e-08c0.276142,1.20706e-08 0.5,-0.223858 0.5,-0.5v-4.5v0c0,-0.276142 -0.223858,-0.5 -0.5,-0.5c-0.276142,0 -0.5,0.223858 -0.5,0.5v4.5l5.32907e-15,7.54979e-08c4.16963e-08,0.276142 0.223858,0.5 0.5,0.5Z"></path><path d="M10.354,12.354l2.23014e-08,-2.2245e-08c0.195509,-0.195015 0.195909,-0.511597 0.000893739,-0.707106c-0.000297551,-0.000298304 -0.000595479,-0.000596232 -0.000893784,-0.000893784l-2,-2l4.41373e-09,4.4249e-09c-0.195015,-0.195509 -0.511597,-0.195909 -0.707106,-0.000893793c-0.000298304,0.000297551 -0.000596232,0.000595479 -0.000893784,0.000893784l-2,2l-2.1107e-09,2.1107e-09c-0.195509,0.195509 -0.195509,0.512491 4.22141e-09,0.708c0.195509,0.195509 0.512491,0.195509 0.708,-4.22141e-09l1.646,-1.647l1.646,1.647l-3.52833e-08,-3.53726e-08c0.195015,0.195509 0.511597,0.195909 0.707106,0.000893854c0.000298304,-0.000297551 0.000596233,-0.000595479 0.000893784,-0.000893784Z"></path></g></svg></span>';
        const finalSVG = self.collapseElementsState === "collapse" ? collapseSVG : expandSVG;
        const balloon = self.collapseElementsState === "collapse" ? "Collapse All" : "Expand All";
        self.addIconToFields('li','brxc-header-icon brxc-header-icon__hover', false, balloon, 'bottom-right', 'ADMINBRXC.collapseElements()', true, finalSVG, wrapper, 'child');
    },
    panelSwitch: function(el){
        const self = this;
        if(el.dataset.panelGroup) {
            self.vueState.activePanelGroup = el.dataset.panelGroup
            const items = document.querySelectorAll('#bricks-panel-element .brxce-panel-shortcut__wrapper li');
            if(items && items.length > 0){
                items.forEach(item => {
                    item.dataset.panelGroup === el.dataset.panelGroup ? item.classList.add('active') : item.classList.remove('active');
                })
            }
        } else{
            self.vueState.activePanelGroup = ''
        }
        if (el.dataset.panel) self.vueState.activePanelTab = el.dataset.panel;
        
    },
    // panelShortcuts: function(){
    //     const self = this;
    //     if(self.vueState.hasOwnProperty('showElementControlShortcuts')) return;

    //     const panelElement = document.querySelector('#bricks-panel-element');
    //     if( !panelElement) return

    //     let wrapper = panelElement.querySelector('.brxce-panel-shortcut__wrapper');
    //     if (wrapper) wrapper.remove();
        
    //     if(!self.builderStates.isElementActive) return;
        
    //     panelElement.setAttribute("data-active", "true");

    //     const panelHeader = panelElement.querySelector('#bricks-panel-header')
    //     if (!panelHeader) return;

    //     //component
    //     if(self.helpers.isComponentPanelOpen()) return;

    //     let activeTabs = [];

    //     const elementObj = self.builderStates.activeElement;
    //     const elementObjWithClasses = self.builderStates.activeObject;

    //     function calculateActiveTabs(){
    //         const name = elementObj.name;
    //         const settings = elementObjWithClasses?.settings;
    //         const activeBp = self.vueState.breakpointActive;
    //         const activePseudo = self.vueState.pseudoClassActive;

    //         let suffix = "";
    //         if(activeBp !== "desktop") suffix += `:${activeBp}`;
    //         if(activePseudo !== "") suffix += activePseudo;

    //         for(const key of Object.keys(settings)){
    //             const setting = key.split(':')[0];
    //             if(key === "_cssClasses" || key === "_cssId" || key === "_attributes" || key === `${setting}${suffix}`){
    //                 if(bricksData.elements[name]?.controls[setting] && bricksData.elements[name]?.controls[setting].hasOwnProperty('group')) activeTabs.push(bricksData.elements[name].controls[setting].group);
    //             } 
    //         }
    //         return activeTabs = [...new Set(activeTabs)];
    //     }

    //     calculateActiveTabs();

    //     var keyboard = 0;
    //     wrapper = `<div class="brxce-panel-shortcut__wrapper"><div class="brxce-panel-shortcut__container">`;
    //     if (Object.values(self.globalSettings.shortcutsTabs).includes('content')) {
    //         wrapper += `<li ${self.vueState.activePanelTab === "content" ? 'class="active"' : ''}data-panel="content" data-balloon="Content" data-order="${keyboard}" data-balloon-pos="right"><span class="bricks-svg-wrapper">${self.helpers.leftIcons.content}</span><span class="keyboard-shortcut">${keyboard}</span></li>`;
    //     }
    //     if(Object.values(self.globalSettings.classFeatures).includes("disable-id-styles") && self.forceClassStlyesStates.showLock === true) {
    //         wrapper += `</div></div>`;
    //         panelHeader.insertAdjacentHTML('afterend', wrapper);
    //         const activePanel = panelElement.querySelector('[data-panel="content"]')
    //         activePanel?.classList.add('active')
    //         return;
    //     }

    //     if(!bricksData.elements[elementObj.name]) return; 
    //     const controlGroups = bricksData.elements[elementObj.name].controlGroups;
        
    //     function createIcon(activeTab, balloon, icon ){
    //         keyboard++;
    //         return `<li class="${activeTabs.includes(activeTab) ? 'has-settings' : ''}${self.vueState.activePanelTab === "style" && activeTab === self.vueState.activePanelGroup ? ' active' : ''}" data-panel="style" data-panel-group="${activeTab}"${keyboard < 10 ? ` data-order="${keyboard}"` : ''} data-balloon="${balloon}" data-balloon-pos="right"><span class="bricks-svg-wrapper">${icon}</span>${keyboard < 10 ? `<span class="keyboard-shortcut">${keyboard}</span>` : '' }</li>`;
    //     }

    //     function createIconConfig(tabKey, balloon, icon) {
    //         return {
    //             tabKey,
    //             balloon,
    //             icon
    //         };
    //     }

    //     const shortcutConfigs = [
    //         createIconConfig('_layout', 'Layout', self.helpers.leftIcons._layout),
    //         createIconConfig('_typography', 'Typography', self.helpers.leftIcons._typography),
    //         createIconConfig('_background', 'Background', self.helpers.leftIcons._background),
    //         createIconConfig('_border', 'Border', self.helpers.leftIcons._border),
    //         createIconConfig('_gradient', 'Gradient / Overlay', self.helpers.leftIcons._gradient),
    //         createIconConfig('_shapes', 'Shape Dividers', self.helpers.leftIcons._shapes),
    //         createIconConfig('_transform', 'Transform', self.helpers.leftIcons._transform),
    //         createIconConfig('_filter', 'Filters / Transitions', self.helpers.leftIcons._filter),
    //         createIconConfig('_animation', 'Animations', self.helpers.leftIcons._animation),
    //         createIconConfig('_css', 'CSS', self.helpers.leftIcons._css),
    //         createIconConfig('_classes', 'Classes / ID', self.helpers.leftIcons._classes),
    //         createIconConfig('_attributes', 'Attributes', self.helpers.leftIcons._attributes),
    //         createIconConfig('_generated-code', 'Generated Code', self.helpers.leftIcons['_generated-code']),
    //         createIconConfig('_pageTransition', 'Page Transition', self.helpers.leftIcons._pageTransition),
    //     ];

    //     shortcutConfigs.forEach(config => {
    //         const { tabKey, balloon, icon } = config;

    //         if (Object.values(self.globalSettings.shortcutsTabs).includes(tabKey.replaceAll('_','')) && typeof controlGroups !== "undefined" && controlGroups.hasOwnProperty(tabKey)) {
    //             wrapper += createIcon(tabKey, balloon, icon);
    //         }
    //     });

    //     wrapper += `</div></div>`;

    //     panelHeader.insertAdjacentHTML('afterend', wrapper);

    //     const newWrapper = document.querySelector('#bricks-panel-element .brxce-panel-shortcut__wrapper');
    //     newWrapper.addEventListener('mousedown', (e) => {
    //         if(e.target.tagName === "LI"){
    //             self.vueState.brxc.clickedOnLeftPanelShortcuts = true;
    //             if(self.vueState.activePanelTab === "style" && self.vueState.activePanelGroup === e.target.dataset.panelGroup) {
    //                 self.vueState.activePanelGroup = '';
    //             } else {
    //                 self.panelSwitch(e.target)
    //             }
    //         }
    //     })

    // },
    setColorsforStructureIndicators: function (){
        const self = this;
        if(self.structurePanelStates.tweaks.includes('styles-and-classes-indicators')){
            document.body.classList.add(`at-indicators-color-colored`);
        } else {
            document.body.classList.remove(`at-indicators-color-colored`);
        }
    },
    setColorsforStructureParents: function (){
        const self = this;
        if(self.structurePanelStates.tweaks.includes('highlight-parent-elements')){
            document.body.classList.add('at-highlight-parents');
        } else {
            document.body.classList.remove('at-highlight-parents');
        }
    },
  
    // groupClassIndicator() {
    //     const self = this;
    //     if (!self.builderStates.isElementActive) return;

    //     const panel = document.querySelector("#bricks-panel-element");
    //     const elements = panel.querySelectorAll("[data-control-group]");
    //     if (!elements || elements.length < 1) return;
        
    //     // Remove Existing classes from the title
    //     elements.forEach(el => {
    //         const controlGroupTitle = el.querySelector('.control-group-title');
    //         controlGroupTitle.classList.remove('has-class-styles');
    //         controlGroupTitle.classList.remove('has-id-styles');
    //       });

    //     let settingKeys;
    //     const elementObj = self.builderStates.activeElement;
        
    //     // ID
    //     if(!self.builderStates.isClassActive){
    //         const classIds = elementObj.settings?.['_cssGlobalClasses'] || false;
    //         if (!classIds) return;
        
    //         settingKeys = classIds.flatMap(cls => {
    //             const obj = self.vueGlobalProp.$_getGlobalClass(cls);
    //             if(!obj) return;

    //             const clsSettings = obj.settings;
    //             const keys = Object.keys(clsSettings);
    //             return keys.filter(
    //                 key => self.helpers.keyMatchBreakpoint(key, self.vueState.breakpointActive) 
    //                 && self.helpers.keyMatchPseudo(key, self.vueState.pseudoClassActive));
    //         });

    //     // Class
    //     } else {
    //         settingKeys = Object.keys(elementObj.settings).filter(
    //                 key => self.helpers.keyMatchBreakpoint(key, self.vueState.breakpointActive) 
    //                 && self.helpers.keyMatchPseudo(key, self.vueState.pseudoClassActive));
    //     }
    
    //     settingKeys = [...new Set(settingKeys.map(key => key && key.split(':')[0]))];
    //     let categories = settingKeys.flatMap(key => bricksData.elements[elementObj.name]?.controls[key]?.group || []);
    
    //     categories = [...new Set(categories)];
    //     if (!categories || categories.length < 1) return;
        
    //     // Add class to title
    //     const customClass = !self.builderStates.isClassActive ? 'has-class-styles' : 'has-id-styles';
    //     categories.forEach(cat => {
    //         const panelTitle = panel.querySelector(`[data-control-group="${cat}"] .control-group-title`);
    //         panelTitle.classList.add(customClass);
    //     })
    // },
    // classIndicator() {
    //     const self = this;
    //     if(!self.builderStates.isElementActive) return;
    
    //     const panel = document.querySelector("#bricks-panel-element");
    //     const els = panel?.querySelectorAll("[data-controlkey^='_']");
    
    //     if (!els || !els.length) return;
    
    //     // Remove existing attributes
    //     els.forEach((el) => {
    //         el.removeAttribute("data-has-class-style");
    //         el.removeAttribute("data-has-id-style");
    //     });

    //     const activeElementSettings = self.builderStates.activeObject?.settings;
    //     if(!activeElementSettings.hasOwnProperty('_cssGlobalClasses') || activeElementSettings._cssGlobalClasses.length < 1) return;

    //     function buildKey(el) {
    //         let key = el.dataset.controlkey;
    //         if (self.vueState.breakpointActive !== "desktop") {
    //             key += `:${self.vueState.breakpointActive}`;
    //         }
    //         if (self.vueState.pseudoClassActive !== "") {
    //             key += self.vueState.pseudoClassActive;
    //         }
    //         return key;
    //     }
    
    //     const isClassActive = self.builderStates.isClassActive;
    //     let finalKeys = isClassActive
    //         ? Object.keys(activeElementSettings).filter(el => el && el.startsWith("_") && activeElementSettings[el] !== "")
    //         : self.helpers.getClassKeysFromGlobalSettings(activeElementSettings._cssGlobalClasses);
    
    //     const attr = isClassActive ? 'hasIdStyle' : 'hasClassStyle';
    //     els.forEach((el) => {
    //         if (finalKeys.includes(buildKey(el))) {
    //             el.dataset[attr] = "true";
    //         }
    //     });
        
    //     if(isClassActive){
    //         const globalClasses = activeElementSettings._cssGlobalClasses.slice();
    //         globalClasses.splice(globalClasses.indexOf(self.vueState.activeClass.id),1);
    //         if(globalClasses.length < 1) return;

    //         finalKeys = self.helpers.getClassKeysFromGlobalSettings(globalClasses);
    
    //         els.forEach((el) => {
    //             const key = buildKey(el);
    //             if (finalKeys.includes(key)) {
    //                 el.dataset['hasClassStyle'] = "true";
    //             }
    //         });
    //     }
    // },

    breakpointIndicator: function(){
        const self = this;
        if(!self.builderStates.isElementActive) return;

        // Const
        const panel = document.querySelector("#bricks-panel-element");
        const groups = panel.querySelectorAll('.control-group');
        if (groups.length < 1) return;
        const activePseudo = self.vueState.pseudoClassActive;
        const elementObj = self.builderStates.activeElement;
        const elementObjWithClasses = self.builderStates.activeObject;
        const activeBp = self.vueState.breakpointActive;

        
        function mountIcons(){
            const name =  elementObj?.name;
            const settings =  elementObjWithClasses?.settings;
            
            if(!settings) return;
            
            const activePseudo = self.vueState.pseudoClassActive;
    
            // Render
            groups.forEach((group,index) => {
                const groupName = group.dataset.controlGroup;
                self.vueState.breakpoints.forEach(bp => {
                    const icon = group.querySelector(`.brxc-group-icon[data-device="${bp.key}"]`);
                    if(icon) icon.remove();

                    let hasStyles = false;
                    let suffix = "";
                    if(bp.key !== "desktop") suffix += `:${bp.key}`;
                    if(activePseudo !== "") suffix += activePseudo;

                    for(const key of Object.keys(settings)){
                        const setting = key.split(':')[0];
                        if(key === `${setting}${suffix}`){
                            if(bricksData.elements[name]?.controls[setting] && bricksData.elements[name].controls[setting].hasOwnProperty('group') && bricksData.elements[name].controls[setting].group === groupName) {
                                hasStyles = true;
                            }
                        } 
                    }
    
                    if(hasStyles){
                        let svg = '<span class="bricks-svg-wrapper"><svg version="1.1" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><path d="M27.744,2.5h-25.488c-0.968,0 -1.756,0.788 -1.756,1.755v17.489c0,0.968 0.788,1.755 1.756,1.755h12.244v3h-5.5c-0.276,0 -0.5,0.224 -0.5,0.5c0,0.276 0.224,0.5 0.5,0.5h12c0.276,0 0.5,-0.224 0.5,-0.5c0,-0.276 -0.224,-0.5 -0.5,-0.5h-5.5v-3h12.244c0.968,0 1.756,-0.788 1.756,-1.755v-17.489c0,-0.967 -0.788,-1.755 -1.756,-1.755Zm-1.244,18h-23v-15h23v15Z" fill="currentColor"></path></svg></span>';
                        if( bp.icon === "laptop") {
                            svg = '<span class="bricks-svg-wrapper"><svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><path d="M80.14,400c-17.7503,0 -32.14,-14.3897 -32.14,-32.14v-239.72c0,-17.7503 14.3897,-32.14 32.14,-32.14h351.72c17.7503,0 32.14,14.3897 32.14,32.14v239.72c0,17.7503 -14.3897,32.14 -32.14,32.14Z" stroke-width="32" stroke="currentColor" fill="none" stroke-linejoin="round"></path><path fill="currentColor" stroke="currentColor" stroke-linecap="round" stroke-width="32" d="M16,416h480"></path></svg></span>';
                        }
                        if( bp.icon === "tablet-landscape") {
                            svg = '<span class="bricks-svg-wrapper"><svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><g transform="matrix(1,0,0,1,0,512)"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M128,496c-26.5094,0 -48,-21.4906 -48,-48v-384c0,-26.5094 21.4906,-48 48,-48h256c26.5094,0 48,21.4906 48,48v384c0,26.5094 -21.4906,48 -48,48Z" transform="matrix(6.12323e-17,-1,1,6.12323e-17,0,0)"></path></g></svg></span>';
                        }
                        if( bp.icon === "tablet-portrait") {
                            svg = '<span class="bricks-svg-wrapper"><svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><path d="M128,496c-26.5094,0 -48,-21.4906 -48,-48v-384c0,-26.5094 21.4906,-48 48,-48h256c26.5094,0 48,21.4906 48,48v384c0,26.5094 -21.4906,48 -48,48Z" stroke-linecap="round" stroke-width="32" stroke="currentColor" fill="none" stroke-linejoin="round"></path></svg></span>';
                        }
                        if( bp.icon === "phone-landscape") {
                            svg = '<span class="bricks-svg-wrapper"><svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><g transform="matrix(1,0,0,1,0,512)"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M176,496c-26.5094,0 -48,-21.4906 -48,-48v-384c0,-26.5094 21.4906,-48 48,-48h160c26.5094,0 48,21.4906 48,48v384c0,26.5094 -21.4906,48 -48,48Z" transform="matrix(6.12323e-17,-1,1,6.12323e-17,0,0)"></path></g><path d="M16,336v-24l9.23706e-14,1.20797e-06c-6.67141e-07,-4.41828 3.58172,-8 8,-8v0h-6.99382e-07c8.83656,3.86258e-07 16,-7.16344 16,-16v-64v0c0,-8.83656 -7.16344,-16 -16,-16v0h-3.49691e-07c-4.41828,-1.93129e-07 -8,-3.58172 -8,-8c0,0 0,-2.84217e-14 0,-2.84217e-14v-24" stroke-linecap="round" stroke-width="32" stroke="currentColor" fill="none" stroke-linejoin="round"></path></svg></span>';
                        }
                        if( bp.icon === "phone-portrait") {
                            svg = '<span class="bricks-svg-wrapper"><svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><g stroke-linecap="round" stroke-width="32" stroke="currentColor" fill="none" stroke-linejoin="round"><path d="M176,496c-26.5094,0 -48,-21.4906 -48,-48v-384c0,-26.5094 21.4906,-48 48,-48h160c26.5094,0 48,21.4906 48,48v384c0,26.5094 -21.4906,48 -48,48Z"></path><path d="M176,16h24l-3.49691e-07,7.10543e-15c4.41828,-1.93129e-07 8,3.58172 8,8v0l1.7053e-13,2.41593e-06c1.33428e-06,8.83656 7.16345,16 16,16h64l-6.99382e-07,-1.42109e-14c8.83656,3.86258e-07 16,-7.16344 16,-16v0l1.13687e-13,1.20797e-06c-6.67141e-07,-4.41828 3.58172,-8 8,-8h24"></path></g></svg></span>';
                        }
                        let newClass = 'brxc-group-icon';
                        if(self.vueState.breakpointActive === bp.key) newClass = 'brxc-group-icon active';
                        self.addIconToFields('li', newClass, [['data-device', bp.key]] , bp.label, 'top', false, true, svg, group.querySelector('.control-group-title'), 'child');
                    }
                })
     
            })
            
    
            const groupIcons = panel.querySelectorAll('.brxc-group-icon');
            if(groupIcons.length < 1 ) return;
            groupIcons.forEach(el => {
                el.addEventListener('click', (e) => {
                    e.preventDefault();
                    const parentGroup = e.target.closest('li.control-group');
                    if(parentGroup.classList.contains('open')) e.stopPropagation();
                    self.vueState.breakpointActive = el.dataset.device;
                })
            })
        }
        
        mountIcons();

        // Recalculate indicators on changes
        setTimeout(() => {
            if(activePseudo !== self.vueState.pseudoClassActive ||
               elementObjWithClasses !== self.builderStates.activeObject ||
               activeBp !== self.vueState.breakpointActive) {
                   mountIcons();
            }
        }, 150)

    },
    lockedClassIndicator: function(){
        const self = this;
        if(!self.builderStates.isElementActive) return;

        const classes = document.querySelectorAll('#bricks-panel-element #bricks-panel-element-classes .active-classes li');
        if (classes.length < 1) return;

        classes.forEach(el => {
            el.removeAttribute("data-locked");
            const name = el.querySelector('.name')
            const id = name.dataset.classId;
            if (self.vueGlobalProp.$_isLocked(id)) el.setAttribute("data-locked", "true");
        })
    },
    focusOnFirstClassStates: {
        lastElementFocus: false,
        isComponentActive: false, 
    },
    focusOnFirstClass: function(){
        const self = this;
        if(!self.helpers.isElementActive()) {
            self.focusOnFirstClassStates.lastElementFocus = false;
            return;
        }

        const elementObj = self.vueState.activeElement;
        const hasClass = elementObj && elementObj.hasOwnProperty('id') && elementObj.hasOwnProperty('settings') && elementObj.settings.hasOwnProperty('_cssGlobalClasses');
        if(!hasClass){
            self.focusOnFirstClassStates.lastElementFocus = false;
            return;
        }
        
        const isSameElement = self.focusOnFirstClassStates.lastElementFocus === elementObj.id && self.focusOnFirstClassStates.isComponentActive === self.helpers.isComponentActive();
        if(isSameElement) {
            return;
        } 

        self.focusOnFirstClassStates.isComponentActive = self.helpers.isComponentActive();
        self.focusOnFirstClassStates.lastElementFocus = elementObj.id;

        if (elementObj.settings.hasOwnProperty('_cssGlobalClasses') && elementObj.settings._cssGlobalClasses.length > 0) {
            const unlockedClass = elementObj.settings._cssGlobalClasses.find(classId => {
                const globalClass = self.vueGlobalProp.$_getGlobalClass(classId);
                return classId && globalClass && !self.vueGlobalProp.$_isLocked(classId);
            });
            if (unlockedClass) {
                self.vueState.messageOrigin = "main";
                const classObj = self.vueState.globalClasses.find(el => el.id === unlockedClass);
                self.vueState.activeClass = classObj;

                self.forceClassStlyesStates.showLock = false;
            }
        }
        
    },
    setTagInStructurePanel: function(id,tag){
        const self = this;
        const obj = self.helpers.getElementObject(id);
        if(!obj) return;

        if(obj.settings.length === 0) obj.settings = {};
        obj.settings.tag = tag;
        self.tagBtnStates.active = null;


        self.showTagInStructurePanel();
        self.vueState.rerenderControls = Date.now();
        
    },
    setCustomTagInStructurePanel: function(input, event, optionType){
        const self = this;
        if(event.key === "Enter"){
            const elementObj = self.helpers.getElementObject(input.closest('.element').dataset.id);
            if(optionType === "text"){
                elementObj.settings.tag = input.value
            } else if(optionType === "select"){
                elementObj.settings.tag = "custom";
                elementObj.settings.customTag = input.value;
            }
            self.tagBtnStates.active = null;
            self.showTagInStructurePanel();
            self.vueState.rerenderControls = Date.now();
        }
    },
    elementsTagStates: {
        mode: 'developer',
    },
    showTagInStructurePanel: function(){
        const self = this;
        const structurePanel = document.querySelector('#bricks-structure');
        if(!structurePanel) return;

        const els = structurePanel.querySelectorAll('#bricks-structure main .element');
        if (els.length < 1) return;

        document.body.classList.remove('at-tag-btn-color')
        if(self.elementsTagStates.mode === '') {
            els.forEach(el => {
                const wrapper = el.querySelector('.brxc-tag-btn-wrapper');
                if (wrapper) wrapper.remove();
            })
            return;
        }

        els.forEach(el => {
            const oldBtn = el.querySelector('.brxc-tag-btn-wrapper');
            if(oldBtn) oldBtn.remove();

            const obj = self.helpers.getElementObject(el.dataset.id);
            const tag = self.helpers.getElementTag(obj);
            if(!tag) return;
            
            const title = el.querySelector('.title .icon')
            self.helpers.createTagBtn(title, tag);
        })

        if(self.elementsTagStates.mode === 'developer'){
            document.body.classList.add('at-tag-btn-color')
            self.vueState.brxc.tagdropDownVisible = true;
        }
    },
    showTagInStructurePanelCustomTags: function(){
        const self = this;
        if(!self.builderStates.isElementActive) return;
        const input = document.querySelector('input#customTag');
        if(!input || input.dataset.listening === "true") return;
        input.setAttribute('data-listening', "true");
        input.addEventListener('keyup', () => {
            self.showTagInStructurePanel();
        })

    },
    expandAllChildren: function(event){
        const self = this;
        const parent = event.target.closest('[data-id]');
        if(!parent) return;
        const toggles = parent.querySelectorAll('.bricks-svg-wrapper.toggle')
        if(toggles.length < 1) return;
        toggles.forEach(toggle => {
            const parent = toggle.closest('[data-id]');
            if (!parent) return;
            const target = parent.querySelector('.bricks-structure-list')
            if (!target) return;
            const status = window.getComputedStyle(target).getPropertyValue("display");
            if(status && status === 'none') toggle.click();
        })
        const toggle = parent.querySelector('.structure-item')
        if(toggle) toggle.click();

        self.vueState.rerenderControls = Date.now();

    },
    collapseAllChildren: function(event){
        const self = this;
        const parent = event.target.closest('[data-id]');
        if(!parent) return;
        const toggles = parent.querySelectorAll('.bricks-svg-wrapper.toggle')
        if(toggles.length < 1) return;
        toggles.forEach(toggle => {
            const parent = toggle.closest('[data-id]');
            if (!parent) return;
            const target = parent.querySelector('.bricks-structure-list')
            if (!target) return;
            const status = window.getComputedStyle(target).getPropertyValue("display");
            if(status && status !== 'none') toggle.click();
        })
        const toggle = parent.querySelector('.structure-item')
        if(toggle) toggle.click();
        
        self.vueState.rerenderControls = Date.now();

    },
    replaceColorsPalette: function(){
        const self = this;
        if(!self.builderStates.isElementActive) return;
        const grid = document.querySelector('#bricks-panel-element ul.color-palette.grid');
        if(!grid) return;
        const btns = grid.querySelectorAll('li.color .color-button');
        btns.forEach(btn => {
            const balloon = btn.dataset.balloon;
            if(!balloon.startsWith('var(')) return;
            btn.style.backgroundColor = balloon;
        })

    },
    previousTheme: false,
    checkForThemeChange: function(){
        const self = this;
        if(self.previousTheme === false) self.previousTheme = self.vueState.themeStyleActive;
        if(self.previousTheme !== self.vueState.themeStyleActive) {
            self.previousTheme = self.vueState.themeStyleActive;
            self.generateVariableCSS('theme');
            self.generateBuilderCSS();
        }
    },
    dynamicDataStates: {
        initialized: false,
        input: false,
        search: '',
        activeGroups: ['all'],
        groups: false,
        recentSearch: [],
    },
    // addDynamicDataTrigger: async function(){
    //     const self = this;
    //     setTimeout(() => {
    //         self.fields['dynamicDataModal']['includedFields'].forEach(field => {
    //             let elements;
    //             if (typeof field === 'string') {
    //                 elements = Array.from(document.querySelectorAll(field));
    //             } else {
    //                 // Get elements with the selector
    //                 const filteredElements = Array.from(document.querySelectorAll(field.selector));
        
    //                 // Check if they have any of the specified child elements
    //                 elements = filteredElements.filter(el =>
    //                     el && field.hasChild.some(child => child && el.querySelector(child))
    //                 );
    //             }
        
    //             const wrappers = elements.filter(
    //                 item => item && !item.parentNode.closest(self.fields['dynamicDataModal']['excludedFields'])
    //             );
    //             if (wrappers.length < 1) return;
    //             wrappers.forEach(wrapper => {
    //                 if(wrapper.dataset.listening === "true") return;
    //                 wrapper.setAttribute('data-listening', 'true');
    //                 wrapper.addEventListener('click', (event) => {
    //                     event.stopPropagation();
    //                     event.preventDefault();
    //                     self.dynamicDataStates.input = wrapper.parentElement.querySelector('.has-dynamic-data, textarea, input[type="text"]');
    //                     self.dynamicDataStates.search = '';
    //                     self.openModal({target: false, id: "#brxcDynamicDataModalOverlay", focus: '#brxcDynamicDataModalOverlay input[type="text"]', callback: () => {
    //                         self.dynamicDataInit();
    //                     }})
    //                 })
    //             })
    //         })
    //     }, 300)
    // },
    dynamicDataInit: function(){
        const self = this;
        const overlay = document.querySelector('#brxcDynamicDataModalOverlay');
        const canvas = overlay.querySelector('#brxcDynamicDataCanvas');
        const filters = overlay.querySelector('#brxcDynamicDataFilters');
        if(!canvas || !filters) return;

        // Set Categories
        self.dynamicDataStates.categories = [...new Set(bricksData.dynamicTags.map(item => item.group))];

        // Mount data
        self.dynamicDataCategories();
        self.dynamicDataMount();
    },
    dynamicDataCategories: function(){
        const self = this;
        const canvas = document.querySelector('#brxcDynamicDataFilters');
        if(!canvas) return;

        let content = "";

        // Recent Searchs
        if(self.dynamicDataStates.recentSearch.length > 0){
            content += `<div id="brxcRecentSearch"><span>Recent Search: </span>${self.dynamicDataStates.recentSearch.slice(0, 10).map(el => `<a>${el}</a>`).join('<span>, </span>')}</div>`
        }
        // Filters
        content += `<div class="brxc-overlay__action-btn-wrapper"><div data-group="all" class="brxc-overlay__action-btn${self.dynamicDataStates.activeGroups.includes('all') ? ' active' : ''}">All</div>`;
        self.dynamicDataStates.categories.forEach(group => {
            content += `<div data-group="${group}" class="brxc-overlay__action-btn${self.dynamicDataStates.activeGroups.includes(group) ? ' active' : ''}">${group}</div>`;
        })
        content += '</div>';

        canvas.innerHTML = content;

        const recentSearchLinks = canvas.querySelectorAll('#brxcRecentSearch a');
        if(recentSearchLinks){
            recentSearchLinks.forEach(el => {
                el.addEventListener('click', () => {
                    self.dynamicDataStates.search = el.textContent;
                    document.querySelector('#brxcDynamicDataModalOverlay input[type="text"]').value = el.textContent;
                    self.dynamicDataMount();
                })
            })
        }

        // Listeners
        const btnWrapper = canvas.querySelector('.brxc-overlay__action-btn-wrapper');
        btnWrapper.addEventListener('mousedown', (event) => {
            const btn = event.target
            event.stopPropagation();
            event.preventDefault();
            if(btn.dataset.group === "all"){
                self.dynamicDataStates.activeGroups = ['all'];
            } else {
                if(self.dynamicDataStates.activeGroups.includes('all')) self.dynamicDataStates.activeGroups.splice(0, 1);
                if(self.dynamicDataStates.activeGroups.includes(btn.dataset.group)){
                    self.dynamicDataStates.activeGroups.splice(self.dynamicDataStates.activeGroups.indexOf(btn.dataset.group), 1);
                    if(self.dynamicDataStates.activeGroups.length === 0) self.dynamicDataStates.activeGroups = ['all'];
                } else {
                    self.dynamicDataStates.activeGroups.push(btn.dataset.group)
                }
            } 
            self.dynamicDataInit();
        })
      
    },
    dynamicDataMount: function(){
        const self = this;
        const overlay = document.querySelector('#brxcDynamicDataModalOverlay');
        if(!overlay) return;

        const canvas = overlay.querySelector('#brxcDynamicDataCanvas');
        if(!canvas) return;

        const activeGroups = self.dynamicDataStates.activeGroups; // Cache activeGroups
        const categories = self.dynamicDataStates.categories; // Cache categories
        const tags = bricksData.dynamicTags; // Cache dynamicTags
        const search = self.dynamicDataStates.search.toLowerCase(); // Cache search string

        let contentArr = []; // Use an array for better string concatenation performance
        contentArr.push('<ul id="brxcDynamicDataWrapper">');

        categories.forEach(category => {
            if (!activeGroups.includes("all") && !activeGroups.includes(category)) return;
        
            // Temporary array to store <li> tags
            const tagItems = [];
        
            tags.forEach(tag => {
                if (!tag || tag.group !== category) return;
        
                const tagName = tag.name.toLowerCase();
                const tagLabel = tag.label.toLowerCase();
                const tagGroup = tag.group.toLowerCase();
        
                if (search !== "" && !tagName.includes(search) && !tagLabel.includes(search) && !tagGroup.includes(search)) return;
        
                const label = bricksData.builderDynamicDropdownNoLabel === "1" ? tag.name : tag.label;
                const balloon = bricksData.builderDynamicDropdownKey === "1" ? '' : `data-balloon="${tag.name}" data-balloon-pos="top"`;
        
                tagItems.push(`<li data-value="${tag.name}" ${balloon}><span>${label}</span><div class="copy-tag-icon" data-balloon="Copy Tag to Clipboard" data-balloon-pos="left" data-value="${tag.name}"><i class="fas fa-clipboard"></i></div></li>`);
            });
        
            // Only if there are tag items, push the div
            if (tagItems.length) {
                contentArr.push(`<div><span>${category}</span><ul>`);
                contentArr.push(...tagItems);
                contentArr.push('</ul></div>');
            }
        });

        contentArr.push('</ul>');

        // Join the array into a single string and update the DOM once
        canvas.innerHTML = contentArr.join('');


        // On click
        const ul = canvas.querySelector('#brxcDynamicDataWrapper');
        ul.addEventListener('click', (event) => {
            // Copy tag
            const copyTag = event.target.closest('.copy-tag-icon');
            const li = event.target.closest('li');

            if(copyTag && ul.contains(copyTag)){
                event.stopPropagation();
                const tagName = li.dataset.value;
                return self.copytoClipboardSimple(tagName,`${tagName} successfully copied to clipboard`);
            }

            // li
            if (li && ul.contains(li)) {
                const input = self.dynamicDataStates.input;
                const tag = li.dataset.value;
                const pos = self.dynamicDataStates.cursorPos ?? input.value.length;
                input.value = input.value.slice(0, pos) + tag + input.value.slice(pos);
                self.dynamicDataStates.cursorPos = pos + tag.length;
                const evt = new Event('input');
                input.dispatchEvent(evt);

                if (event.shiftKey) {
                    self.vueGlobalProp.$_showMessage(`${li.dataset.value} inserted correctly!`);
                } else {
                    const searchInput = document.querySelector('#brxcDynamicDataModalOverlay input[type="text"]');
                    if (searchInput && searchInput.value !== "") {
                        self.dynamicDataStates.recentSearch = self.dynamicDataStates.recentSearch.filter(el => el !== searchInput.value);
                        self.dynamicDataStates.recentSearch.unshift(searchInput.value);
                    }
                    self.closeModal(event, event.target, '#brxcDynamicDataModalOverlay');
                }
            }
        });
    },
    focusPointStates: {
        type: null,
        mode: 'grid',
        imgFound: false,
    },
    addBgPositionIcon: function(){
        const self = this;
        if(!self.builderStates.isElementActive || self.vueState.activePanelTab !== "style" || self.vueState.activePanelGroup !== "_background" || self.vueState.showInteractions === true || self.vueState.showConditions === true) return;

        Promise.resolve().then(() => {

            const wrapper = document.querySelector('[data-controlkey="_background"] label[for="position"] + div[data-control="select"]')
            if (!wrapper) return;
             
            const icon = wrapper.parentElement.querySelector('.brxc-position-icon');
            if (icon) return;
        
            wrapper.classList.add('position-icon-active');
            self.addIconToFields(
                'div',
                'brxc-position-icon',
                false,
                'Focus Point',
                'top-right',
                'ADMINBRXC.openModal({target: false, id: "#brxcBackgroundFocus", callback: () => {ADMINBRXC.bgFocusInit("_background");}})',
                false,
                "<i class='fas fa-crosshairs'></i>",
                wrapper,
                'after'
            );
            

        });
    },
    addBgMaskIcon: function(){
        const self = this;
        if(!self.builderStates.isElementActive || self.vueState.activePanelTab !== "content" || self.vueState.showInteractions === true || self.vueState.showConditions === true) return;

        const elementObj = self.builderStates.activeElement;
        if(elementObj.name !== "image") return;
        
        Promise.resolve().then(() => {

            const wrapper = document.querySelector('[data-controlkey="mask"] label[for="mask"] + div[data-control="select"]')
            if (!wrapper) return;
             
            const icon = wrapper.parentElement.querySelector('.brxc-mask-icon');
            if (icon) return;
        
            wrapper.classList.add('mask-icon-active');
            self.addIconToFields(
                'div',
                'brxc-mask-icon',
                false,
                'Mask Helper',
                'top-right',
                'ADMINBRXC.openModal({target: false, id: "#brxcMaskHelperOverlay", callback: () => {ADMINBRXC.maskHelperInit();}})',
                false,
                "<i class='fas fa-mask'></i>",
                wrapper,
                'after'
            );
        });
    },
    maskHelperInit: function(){
        const self = this;
        const canvas = document.querySelector('#brxcMaskHelperCanvas');
        if(!canvas) return;

        const content = self.maskHelperMount();
        canvas.innerHTML = content
    },
    maskHelperMount: function(){
        const self = this;
        const elementObj = self.builderStates.activeElement;
        const settings = elementObj?.settings;
        const image = settings.hasOwnProperty('image') && settings.image.hasOwnProperty('url') && self.helpers.isValidUrl(settings.image.url) ? settings.image.url : self.globalSettings.placeholderImg;
        let position
        let size
        let repeat
        settings.hasOwnProperty('maskPosition') ? position = settings.maskPosition : position = "center center";
        settings.hasOwnProperty('maskSize') ? size = settings.maskSize : size = "contain";
        settings.hasOwnProperty('maskRepeat') ? repeat = settings.maskRepeat : repeat = "no-repeat";
        let content = '<ul>';

        const masks = self.vueGlobalProp.$_getElementConfig(elementObj.name).controls.mask.options;
        for (const key of Object.keys(masks)) {
            if(key !== "custom") content += `<li class="brxc-box-item">
                <img src="${image}" style="mask-image: url(${bricksData.assetsUrl}svg/masks/${key}.svg);mask-size:${size};mask-position:${position};mask-repeat:${repeat};">
                <div class="brxc-box-btn-wrapper">
                    <a class="" onclick="ADMINBRXC.maskHelperApply('${key}');ADMINBRXC.closeModal(event, this, '#brxcMaskHelperOverlay');">Apply</a>
                </div>
            </li>`;
        }
        content += '</ul>';
        return content;

    },
    maskHelperApply: function(key){
        const self = this;
        const settings = self.builderStates.activeElement;
        settings.settings['mask'] = key;
        self.vueGlobalProp.$_forceRender(100);
        self.vueState.rerenderControls = Date.now();
    },
    addObjPositionIcon: function(){
        const self = this;
        if(!self.builderStates.isElementActive || self.vueState.activePanelTab !== "content" || self.vueState.showInteractions === true || self.vueState.showConditions === true) return;
        
        const elementObj = self.builderStates.activeElement;
        if(elementObj.name !== "image") return;

        Promise.resolve().then(() => {
            const wrapper = document.querySelector('[data-controlkey="_objectPosition"] label[for="_objectPosition"] + div[data-control="text"]')
            if (!wrapper) return;
             
            const icon = wrapper.parentElement.querySelector('.brxc-position-icon');
            if (icon) return;
        
            wrapper.classList.add('position-icon-active');
            self.addIconToFields(
                'div',
                'brxc-position-icon',
                false,
                'Focus Point',
                'top-right',
                'ADMINBRXC.openModal({target: false, id: "#brxcBackgroundFocus", callback: () => {ADMINBRXC.bgFocusInit("image");}})',
                false,
                "<i class='fas fa-crosshairs'></i>",
                wrapper,
                'after'
            );
        });
    },
    bgFocusInit: function(type = false){
        const canvas = document.querySelector('#brxcBgFocusCanvas');
        if(!canvas) return;

        const self = this;
        if (type) self.focusPointStates.type = type;
        const targetBackground = self.helpers.createTargetWithPseudo(self.focusPointStates.type);
        let settings = self.builderStates.activeObject?.settings;
        settings = self.focusPointStates.type === "_background" ? settings : self.builderStates.activeElement?.settings
        
        let image;
        if(self.focusPointStates.type === "_background"){
            if(!settings.hasOwnProperty(targetBackground) || !settings[targetBackground].hasOwnProperty('image') || !settings[targetBackground].image.hasOwnProperty('url') || !self.helpers.isValidUrl(settings[targetBackground].image.url)){
                self.focusPointStates.imgFound = false;
                image = self.globalSettings.placeholderImg; 
            } else {
                self.focusPointStates.imgFound = true;
                image = settings[targetBackground].image.url;
            }
        } else if(self.focusPointStates.type === "image"){
            if(!settings.hasOwnProperty('image') || !settings.image.hasOwnProperty('url') || !self.helpers.isValidUrl(settings.image.url)) {
                self.focusPointStates.imgFound = false;
                image = self.globalSettings.placeholderImg;
            } else {
                self.focusPointStates.imgFound = true;
                image = settings.image.url;
            }
        }

        if(self.focusPointStates.mode === "grid"){
            self.bgFocusMountGrid(image);
        } else {
            self.bgFocusMountCustom(image);
        }
    },
    bgFocusMountGrid: function(image){
        const self = this;
        const canvas = document.querySelector('#brxcBgFocusCanvas');
        if(!canvas) return;

        // Structure
        let content = '';
        content += `<div id="brxcFocusContainer">
                        <div class="brxc-focus-col">`;
         if(self.focusPointStates.imgFound !== true) content += `<div data-control="info" style="margin-bottom: 10px;"><u>Image not found!</u> A placeholder will be used instead.</div>`;
                    content += `<div id="brxcFocusWrapper">
                                <img src="${image}" />
                                <div id="brxcFocusGrid">
                                    <div class="brxc-focus-item" data-pos-x="left" data-pos-y="top"></div>
                                    <div class="brxc-focus-item" data-pos-x="center" data-pos-y="top"></div>
                                    <div class="brxc-focus-item" data-pos-x="right" data-pos-y="top"></div>
                                    <div class="brxc-focus-item" data-pos-x="left" data-pos-y="center"></div>
                                    <div class="brxc-focus-item active" data-pos-x="center" data-pos-y="center"></div>
                                    <div class="brxc-focus-item" data-pos-x="right" data-pos-y="center"></div>
                                    <div class="brxc-focus-item" data-pos-x="left" data-pos-y="bottom"></div>
                                    <div class="brxc-focus-item" data-pos-x="center" data-pos-y="bottom"></div>
                                    <div class="brxc-focus-item" data-pos-x="right" data-pos-y="bottom"></div>
                                </div>
                            </div>
                        </div>
                        <div class="brxc-focus-col">
                            <div id="brxcFocusPreview">
                                <div class="brxc-focuc-preview-item"><span>AR: <b>4</b></span><img src="${image}" class="ar-4" /></div>
                                <div class="brxc-focuc-preview-item"><span>AR: <b>3</b></span><img src="${image}" class="ar-3" /></div>
                                <div class="brxc-focuc-preview-item"><span>AR: <b>2</b></span><img src="${image}" class="ar-2" /></div>
                                <div class="brxc-focuc-preview-item"><span>AR: <b>16/9</b></span><img src="${image}" class="ar-16-9" /></div>
                                <div class="brxc-focuc-preview-item"><span>AR: <b>3/2</b></span><img src="${image}" class="ar-3-2" /></div>
                                <div class="brxc-focuc-preview-item"><span>AR: <b>4/3</b></span><img src="${image}" class="ar-4-3" /></div>
                                <div class="brxc-focuc-preview-item"><span>AR: <b>1</b></span><img src="${image}" class="ar-1" /></div>
                                <div class="brxc-focuc-preview-item"><span>AR: <b>3/4</b></span><img src="${image}" class="ar-3-4" /></div>
                                <div class="brxc-focuc-preview-item"><span>AR: <b>2/3</b></span><img src="${image}" class="ar-2-3" /></div>
                                <div class="brxc-focuc-preview-item"><span>AR: <b>9/16</b></span><img src="${image}" class="ar-9-16" /></div>
                                <div class="brxc-focuc-preview-item"><span>AR: <b>1/2</b></span><img src="${image}" class="ar-1-2" /></div>
                            </div>
                        </div>
                    </div>`
        canvas.innerHTML = content;

        const container = canvas.querySelector('#brxcFocusContainer');
        const items = canvas.querySelectorAll('.brxc-focus-item');
        items.forEach(item => {
            item.addEventListener('click', () => {
                items.forEach(el => el.classList.remove('active'))
                item.classList.add('active');
                container.style.setProperty('--left', item.dataset.posX);
                container.style.setProperty('--top', item.dataset.posY);
            })
        })
    },
    bgFocusMountCustom: function(image){
        const self = this;
        const canvas = document.querySelector('#brxcBgFocusCanvas');
        if(!canvas) return;

        // Structure
        let content = '';
        content += `<div id="brxcFocusContainer">
                        <div class="brxc-focus-col">`;
        if(self.focusPointStates.imgFound !== true) content += `<div data-control="info" style="margin-bottom: 10px;"><u>Image not found!</u> A placeholder will be used instead.</div>`;
                    content += `<div id="brxcFocusWrapper">
                                <img src="${image}" />
                                <div id="brxcFocusPoint"></div>
                            </div>
                        </div>
                        <div class="brxc-focus-col">
                            <div id="brxcFocusPreview">
                                <div class="brxc-focuc-preview-item"><span>AR: <b>4</b></span><img src="${image}" class="ar-4" /></div>
                                <div class="brxc-focuc-preview-item"><span>AR: <b>3</b></span><img src="${image}" class="ar-3" /></div>
                                <div class="brxc-focuc-preview-item"><span>AR: <b>2</b></span><img src="${image}" class="ar-2" /></div>
                                <div class="brxc-focuc-preview-item"><span>AR: <b>16/9</b></span><img src="${image}" class="ar-16-9" /></div>
                                <div class="brxc-focuc-preview-item"><span>AR: <b>3/2</b></span><img src="${image}" class="ar-3-2" /></div>
                                <div class="brxc-focuc-preview-item"><span>AR: <b>4/3</b></span><img src="${image}" class="ar-4-3" /></div>
                                <div class="brxc-focuc-preview-item"><span>AR: <b>1</b></span><img src="${image}" class="ar-1" /></div>
                                <div class="brxc-focuc-preview-item"><span>AR: <b>3/4</b></span><img src="${image}" class="ar-3-4" /></div>
                                <div class="brxc-focuc-preview-item"><span>AR: <b>2/3</b></span><img src="${image}" class="ar-2-3" /></div>
                                <div class="brxc-focuc-preview-item"><span>AR: <b>9/16</b></span><img src="${image}" class="ar-9-16" /></div>
                                <div class="brxc-focuc-preview-item"><span>AR: <b>1/2</b></span><img src="${image}" class="ar-1-2" /></div>
                            </div>
                        </div>
                    </div>`
        canvas.innerHTML = content;

        // Cache the CSS properties and elements
        const focusContainer = canvas.querySelector('#brxcFocusContainer');
        const focusWrapper = canvas.querySelector('#brxcFocusWrapper');
        const focusPoint = canvas.querySelector('#brxcFocusPoint');
        let pos1 = 0, pos2 = 0;

        function dragElement(elmnt) {
            // Otherwise, move the DIV from anywhere inside the DIV:
            elmnt.onmousedown = dragMouseDown;

            function dragMouseDown(e) {
                e = e || window.event;
                e.preventDefault();
                // Get the mouse cursor position at startup:
                pos1 = e.clientX;
                pos2 = e.clientY;
                document.onmouseup = closeDragElement;
                // Call a function whenever the cursor moves:
                document.onmousemove = elementDrag;
            }

            function elementDrag(e) {
                e = e || window.event;
                e.preventDefault();
                // Calculate the cursor movement since the last event:
                const deltaX = e.clientX - pos1;
                const deltaY = e.clientY - pos2;
                pos1 = e.clientX;
                pos2 = e.clientY;

                // Get the wrapper's dimensions
                const wrapperWidth = focusWrapper.offsetWidth;
                const wrapperHeight = focusWrapper.offsetHeight;

                // Calculate the new cursor position as percentages relative to wrapper
                const offsetX = deltaX / wrapperWidth * 100;
                const offsetY = deltaY / wrapperHeight * 100;

                // Get the current position as percentages
                const currentLeft = parseFloat(getComputedStyle(focusContainer).getPropertyValue('--left'));
                const currentTop = parseFloat(getComputedStyle(focusContainer).getPropertyValue('--top'));

                // Calculate the new position by adding the offset
                let newLeft = currentLeft + offsetX;
                let newTop = currentTop + offsetY;

                // Ensure the position stays within 0% to 100%
                newLeft = Math.min(Math.max(newLeft, 0), 100);
                newTop = Math.min(Math.max(newTop, 0), 100);

                // Update the CSS variables
                focusContainer.style.setProperty('--left', newLeft + '%');
                focusContainer.style.setProperty('--top', newTop + '%');
            }

            function closeDragElement() {
                // Stop moving when mouse button is released:
                document.onmouseup = null;
                document.onmousemove = null;
            }
        }

        // Call the dragElement function passing the focusPoint element
        dragElement(focusPoint);
    },
    applyBgFocus: function(){
        const self = this;
        const focusPoint = document.querySelector('#brxcFocusContainer');
        const currentLeft = parseFloat(getComputedStyle(focusPoint).getPropertyValue('--left'));
        const currentTop = parseFloat(getComputedStyle(focusPoint).getPropertyValue('--top'));
        let settings = self.builderStates.activeObject?.settings;

        // mode custom
        if(self.focusPointStates.mode === "custom"){
            if(self.focusPointStates.type === "_background"){
                const targetBackground = self.helpers.createTargetWithPseudo('_background');
                if(!settings.hasOwnProperty(targetBackground)) settings[targetBackground] = {};
                settings[targetBackground].position = 'custom';
                settings[targetBackground].positionX = `${currentLeft.toFixed(2)}%`;
                settings[targetBackground].positionY = `${currentTop.toFixed(2)}%`;
            } else if(self.focusPointStates.type === "image"){
                const targetObjPosition = self.helpers.createTargetWithPseudo('_objectPosition');
                settings[targetObjPosition] = `${currentLeft.toFixed(2)}% ${currentTop.toFixed(2)}%`
            }
        
        // mode grid
        } else if(self.focusPointStates.mode === "grid"){
            const activeEl = document.querySelector('.brxc-focus-item.active');
            if(!activeEl) return self.vueGlobalProp.$_showMessage('Abort - Select a grid item first');

            const posX = activeEl.dataset.posX;
            const posY = activeEl.dataset.posY;

            if(self.focusPointStates.type === "_background"){
                const targetBackground = self.helpers.createTargetWithPseudo('_background');
                if(!settings.hasOwnProperty(targetBackground)) settings[targetBackground] = {};
                settings[targetBackground].position = 'custom';
                settings[targetBackground].positionX = posX;
                settings[targetBackground].positionY = posY;
            } else if(self.focusPointStates.type === "image"){
                const targetObjPosition = self.helpers.createTargetWithPseudo('_objectPosition');
                settings[targetObjPosition] = `${posX} ${posY}`
            }
        }

        self.vueState.rerenderControls = Date.now();
    },
    // addGridUIIcon: function(){
    //     const self = this;
    //     if(!self.builderStates.isElementActive || self.vueState.showInteractions === true || self.vueState.showConditions === true) return;

    //     Promise.resolve().then(() => {
    //         const wrapper = document.querySelector('[data-controlkey="_display"]')
    //         if (!wrapper) return;

    //         const elementObj = self.builderStates.activeObject;

    //         if(!self.helpers.elementHasGrid()){
    //             wrapper.classList.remove('grid-icon-active');
    //             const icon = wrapper.querySelector('.brxc-gridui-icon');
    //             if(icon) icon.remove(); 
    //             return;
    //         }
             
    //         const icon = wrapper.querySelector('.brxc-gridui-icon');
    //         const target = self.helpers.createTargetWithPseudo('gridBuilderSettings');
    //         const settings = elementObj.settings;
    //         if (icon) {
    //             settings.hasOwnProperty(target) ? icon.classList.add('active') : icon.classList.remove('active');
    //             return;
    //         }

    //         const className = settings.hasOwnProperty(target) ? 'brxc-gridui-icon active' : 'brxc-gridui-icon';
        
    //         wrapper.classList.add('grid-icon-active');
    //         self.addIconToFields(
    //             'div',
    //             className,
    //             false,
    //             'Grid Builder',
    //             'top-right',
    //             'ADMINBRXC.openModal({target: false, id: "#brxcGridUIOverlay", callback: () => {ADMINBRXC.gridBuilderInit();}})',
    //             false,
    //             "<i class='ion-ios-grid'></i>",
    //             wrapper.querySelector("[data-control='select']"),
    //             'after'
    //         );
    //     });
    // },
    gridUIStates: {
        activeChild: null,
        grid: null,
        elements: null,
        gridReset: null,
        elementsReset: null,
        els: [],
        draggingEl: null,
        draggingElSize: null,
        globalCols: 3,
        globalRows: 3,
        globalGap: '20px',
    },
        // States
    
    gridBuilderBentoGrid: function(){
        const self = this;
        const elements = self.gridUIStates.elements;
        self.gridUIStates.grid.autoFlow = true;
        elements.forEach(el => {
            el.xSpan = 1;
            el.xSpanValue = 1;
            el.ySpan = 1;
            el.ySpanValue = 1;
        });

        const cols = self.gridUIStates.grid.col.length;
        const rows = self.gridUIStates.grid.row.length;
        
        function getFreeSlots(cols, rows){
            let usedSlots = 0;
            elements.forEach(el => {
                usedSlots += el.xSpanValue * el.ySpanValue;
            })
            return (cols * rows) - usedSlots;
        }
        function removeSlot(){
            let span;
            span = Math.floor(Math.random() * 2) === 1 ?  "xSpanValue" : "ySpanValue";
            const filteredEls = elements.filter(el => el && el[span] > 1);
            if(!filteredEls) return;
            let ind = Math.floor(Math.random() * filteredEls.length);
            const obj = filteredEls[ind];
            obj[span]--;
        }
        function addNewSlot(){
            let span;
            span = Math.floor(Math.random() * 2) === 1 ?  "x" : "y";
            const index = Math.floor(Math.random() * (elements.length - 1));
            elements[index][`${span}SpanValue`]++;
        }
        function populateSlots(){
            if(getFreeSlots(cols, rows) === 0) return;
            if(getFreeSlots(cols, rows) < 0) {
                removeSlot();
                populateSlots();
                return;
            }
            addNewSlot();
            populateSlots();
        }
        populateSlots()

         // Reload Grid
         self.gridBuilderSaveSettings();
         self.gridBuilderInit();
    },

    gridBuilderSetHeight: function(){
        const height = parseInt(document.defaultView.getComputedStyle(document.querySelector('.gridUI__grid-maxi-container')).height, 10)
        document.querySelector('.gridUI__main-container').style.setProperty("--max-height", `${height}px`);
    },
    gridBuilderSetNotification: function(){
        const self = this;
        const isCSS = self.gridUIStates.isClass || self.gridUIStates.hasQuery || self.gridUIStates.hasComponent;
        const wrapper = document.querySelector('#gridUI-notification');
        const mainContainer = document.querySelector('.gridUI__main-container');
        let text = '';
        if(self.gridUIStates.children === "[]"){
            mainContainer.classList.add('empty');
            text = `<div class="danger" data-control="info"><u>No Children detected!</u> Make sure to add children elements to your parent container.</div>`;
            wrapper.innerHTML = text;
            return;
        }
        mainContainer.classList.remove('empty');
        if(!isCSS) return wrapper.innerHTML = '';
        if(self.gridUIStates.hasQuery) text = `<div data-control="info"><u>Query Loop detected!</u> The Grid settings will be saved as Custom CSS.</div>`;
        if(self.gridUIStates.isClass) text = `<div data-control="info"><u>Class detected!</u> The Grid settings will be saved as Custom CSS.</div>`;
        if(self.gridUIStates.hasComponent) text = `<div data-control="info"><u>Component detected as child!</u> The Grid settings will be saved as Custom CSS.</div>`;
        wrapper.innerHTML = text;
    },
    gridBuilderSetBreakpoints: function(){
        const self = this;
        const wrapper = document.querySelector('#gridUI-bp-wrapper');
        let css = '';
        self.vueState.breakpoints.forEach(bp =>{
            let svg = '<span class="bricks-svg-wrapper"><svg version="1.1" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><path d="M27.744,2.5h-25.488c-0.968,0 -1.756,0.788 -1.756,1.755v17.489c0,0.968 0.788,1.755 1.756,1.755h12.244v3h-5.5c-0.276,0 -0.5,0.224 -0.5,0.5c0,0.276 0.224,0.5 0.5,0.5h12c0.276,0 0.5,-0.224 0.5,-0.5c0,-0.276 -0.224,-0.5 -0.5,-0.5h-5.5v-3h12.244c0.968,0 1.756,-0.788 1.756,-1.755v-17.489c0,-0.967 -0.788,-1.755 -1.756,-1.755Zm-1.244,18h-23v-15h23v15Z" fill="currentColor"></path></svg></span>';
            if( bp.icon === "laptop") {
                svg = '<span class="bricks-svg-wrapper"><svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><path d="M80.14,400c-17.7503,0 -32.14,-14.3897 -32.14,-32.14v-239.72c0,-17.7503 14.3897,-32.14 32.14,-32.14h351.72c17.7503,0 32.14,14.3897 32.14,32.14v239.72c0,17.7503 -14.3897,32.14 -32.14,32.14Z" stroke-width="32" stroke="currentColor" fill="none" stroke-linejoin="round"></path><path fill="currentColor" stroke="currentColor" stroke-linecap="round" stroke-width="32" d="M16,416h480"></path></svg></span>';
            }
            if( bp.icon === "tablet-landscape") {
                svg = '<span class="bricks-svg-wrapper"><svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><g transform="matrix(1,0,0,1,0,512)"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M128,496c-26.5094,0 -48,-21.4906 -48,-48v-384c0,-26.5094 21.4906,-48 48,-48h256c26.5094,0 48,21.4906 48,48v384c0,26.5094 -21.4906,48 -48,48Z" transform="matrix(6.12323e-17,-1,1,6.12323e-17,0,0)"></path></g></svg></span>';
            }
            if( bp.icon === "tablet-portrait") {
                svg = '<span class="bricks-svg-wrapper"><svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><path d="M128,496c-26.5094,0 -48,-21.4906 -48,-48v-384c0,-26.5094 21.4906,-48 48,-48h256c26.5094,0 48,21.4906 48,48v384c0,26.5094 -21.4906,48 -48,48Z" stroke-linecap="round" stroke-width="32" stroke="currentColor" fill="none" stroke-linejoin="round"></path></svg></span>';
            }
            if( bp.icon === "phone-landscape") {
                svg = '<span class="bricks-svg-wrapper"><svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><g transform="matrix(1,0,0,1,0,512)"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M176,496c-26.5094,0 -48,-21.4906 -48,-48v-384c0,-26.5094 21.4906,-48 48,-48h160c26.5094,0 48,21.4906 48,48v384c0,26.5094 -21.4906,48 -48,48Z" transform="matrix(6.12323e-17,-1,1,6.12323e-17,0,0)"></path></g><path d="M16,336v-24l9.23706e-14,1.20797e-06c-6.67141e-07,-4.41828 3.58172,-8 8,-8v0h-6.99382e-07c8.83656,3.86258e-07 16,-7.16344 16,-16v-64v0c0,-8.83656 -7.16344,-16 -16,-16v0h-3.49691e-07c-4.41828,-1.93129e-07 -8,-3.58172 -8,-8c0,0 0,-2.84217e-14 0,-2.84217e-14v-24" stroke-linecap="round" stroke-width="32" stroke="currentColor" fill="none" stroke-linejoin="round"></path></svg></span>';
            }
            if( bp.icon === "phone-portrait") {
                svg = '<span class="bricks-svg-wrapper"><svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><g stroke-linecap="round" stroke-width="32" stroke="currentColor" fill="none" stroke-linejoin="round"><path d="M176,496c-26.5094,0 -48,-21.4906 -48,-48v-384c0,-26.5094 21.4906,-48 48,-48h160c26.5094,0 48,21.4906 48,48v384c0,26.5094 -21.4906,48 -48,48Z"></path><path d="M176,16h24l-3.49691e-07,7.10543e-15c4.41828,-1.93129e-07 8,3.58172 8,8v0l1.7053e-13,2.41593e-06c1.33428e-06,8.83656 7.16345,16 16,16h64l-6.99382e-07,-1.42109e-14c8.83656,3.86258e-07 16,-7.16344 16,-16v0l1.13687e-13,1.20797e-06c-6.67141e-07,-4.41828 3.58172,-8 8,-8h24"></path></g></svg></span>';
            }
            let selector = `gridBuilderSettings`;
            if(bp.key !== 'desktop'){
                selector += `:${bp.key}`;
            }

            const settings = self.gridUIStates.isClass ? self.vueState.globalClasses.find(el => el && el.id === self.vueState.activeClass.id)?.settings : self.builderStates.activeElement.settings;
            let hasStyle = settings.hasOwnProperty(selector) ? true : false;

            //css += `<li class="brxc-group-icon${self.vueState.breakpointActive === bp.key ? ' active' : ''}${self.vueGlobalProp.$_getGlobalClass(classId).settings.hasOwnProperty(selector) && self.vueGlobalProp.$_getGlobalClass(classId).settings[selector] !== '' ? ' has-styles' : ''}" data-balloon="${bp.label}" data-balloon-pos="bottom-right" onclick="ADMINBRXC.vueState.breakpointActive = '${bp.key}';ADMINBRXC.gridBuilderInit();">${svg}</li>`;
            css += `<li class="brxc-group-icon${self.vueState.breakpointActive === bp.key ? ' active' : ''}${hasStyle ? ' has-styles' : ''}" data-balloon="${bp.label}" data-balloon-pos="bottom-right" onclick="ADMINBRXC.vueState.breakpointActive = '${bp.key}';Promise.resolve().then(() => ADMINBRXC.gridBuilderInit());">${svg}</li>`;
        })
        wrapper.innerHTML = css;
    },
    gridBuilderRemoveSetting: function(){
        const self = this;
        const parent = self.builderStates.activeObject;
        const target = self.helpers.createTargetWithPseudo('gridBuilderSettings');
        delete parent.settings[target];
        self.vueState.rerenderControls = Date.now()
        self.gridBuilderInit();
    },

    gridBuilderResizableWidth: function(){
        const wrapper = document.querySelector('.gridUI__main-container');
        const draggable = document.querySelector('.gridUI__grid-width.handle-right')
    

        let startX, startWidth;

        // Width
        const initDragWidth = (e) => {
            startX = e.clientX;
            startWidth = parseInt(document.defaultView.getComputedStyle(wrapper).width, 10);
            document.documentElement.addEventListener('mousemove', doDragWidth, false);
            document.documentElement.addEventListener('mouseup', stopDragWidth, false);
        }

        const doDragWidth = (e) => {
            wrapper.style.maxWidth = (startWidth + e.clientX - startX) + 'px';
        }

        const stopDragWidth = (e) => {
            document.documentElement.removeEventListener('mousemove', doDragWidth, false);    
            document.documentElement.removeEventListener('mouseup', stopDragWidth, false);
        }

        draggable.addEventListener('mousedown', initDragWidth, false);
    },

    gridBuilderResizableHeight: function(){
        const wrapper = document.querySelector('.gridUI__main-container');
        const draggable = document.querySelector('.gridUI__grid-width.handle-bottom')
    

        let startY, startHeight;

        // Width
        const initDragHeight = (e) => {
            startY = e.clientY;
            startHeight = parseInt(document.defaultView.getComputedStyle(wrapper).height, 10);
            document.documentElement.addEventListener('mousemove', doDragHeight, false);
            document.documentElement.addEventListener('mouseup', stopDragHeight, false);
        }

        const doDragHeight = (e) => {
            wrapper.style.setProperty('--max-height',`${startHeight + e.clientY - startY}px`);
        }

        const stopDragHeight = (e) => {
            document.documentElement.removeEventListener('mousemove', doDragHeight, false);    
            document.documentElement.removeEventListener('mouseup', stopDragHeight, false);
        }

        draggable.addEventListener('mousedown', initDragHeight, false);
    },

    gridBuilderSetGridElements: function(){
        const self = this;
        const container = document.querySelector('.gridUI__grid-container');
        container.innerHTML = '';
        let i = 0;
        for (const key of Object.keys(self.gridUIStates.elements)) {
            const element = document.createElement('div');
            element.classList.add('gridUI__grid-element');
            element.setAttribute('data-id', self.gridUIStates.elements[key].id);
            element.style.setProperty('--hue', self.gridUIStates.elements[key].color);
            element.setAttribute('draggable', 'true');
            element.setAttribute('onclick', `ADMINBRXC.gridBuilderSetChild('${self.gridUIStates.elements[key].id}');`)
            element.setAttribute('ondragstart', 'this.preventDefault;event.stopPropagation();ADMINBRXC.gridBuilderDragStartElement(this)');
            element.setAttribute('ondrag', 'this.preventDefault;event.stopPropagation();ADMINBRXC.gridBuilderDragElement(this)');
            element.setAttribute('ondragend', 'ADMINBRXC.gridBuilderDragEnd(this)');
            if(self.gridUIStates.activeChild !== null && self.gridUIStates.activeChild !== self.gridUIStates.elements[key].id) element.classList.add('inactive');
            if(self.gridUIStates.activeChild !== null && self.gridUIStates.activeChild === self.gridUIStates.elements[key].id) element.classList.add('active');
            let content = '';
            content += `${self.gridUIStates.elements[key].label}<div class="gridUI__grid-handle-container${(self.gridUIStates.elements[key].hasOwnProperty('yEnd') && self.gridUIStates.elements[key].yEnd > (self.gridUIStates.grid.col.length + 1)) || (self.gridUIStates.elements[key].hasOwnProperty('xEnd') && self.gridUIStates.elements[key].xEnd > (self.gridUIStates.grid.row.length + 1)) ? ' error' : ''}">`
            content += `<div class="action-top">`;
            if(self.gridUIStates.activeChild !== null && self.gridUIStates.activeChild === self.gridUIStates.elements[key].id) content +=`<div class="gridUI__grid-handle clear" data-balloon="Clear View" data-balloon-pos="bottom" onClick="event.stopPropagation();ADMINBRXC.gridBuilderRemoveActiveChild();"><span class="bricks-svg-wrapper"><i class="fas fa-xmark"></i></span></div>`;
            if(self.gridUIStates.elements[key].hasOwnProperty('xStart') 
                || self.gridUIStates.elements[key].hasOwnProperty('xEnd') 
                || self.gridUIStates.elements[key].hasOwnProperty('xStart') 
                || self.gridUIStates.elements[key].hasOwnProperty('xEnd') 
                || self.gridUIStates.elements[key].hasOwnProperty('yStart') 
                || self.gridUIStates.elements[key].hasOwnProperty('yEnd') 
                || (self.gridUIStates.elements[key].hasOwnProperty('xSpan') && self.gridUIStates.elements[key].xSpan === 1 && self.gridUIStates.elements[key].hasOwnProperty('xSpanValue'))
                || (self.gridUIStates.elements[key].hasOwnProperty('ySpan') && self.gridUIStates.elements[key].ySpan === 1 && self.gridUIStates.elements[key].hasOwnProperty('ySpanValue'))
              ) {
                content += `<div class="gridUI__grid-handle delete" data-balloon="Remove Styles" data-balloon-pos="bottom" onClick="event.stopPropagation();ADMINBRXC.gridBuilderDeleteElementSettings(this.parentElement.parentElement.parentElement.dataset.id)"><span class="bricks-svg-wrapper"><i class="fas fa-undo"></i></span></div>`;
            }
            content +=`<div class="gridUI__grid-handle dom">${i + 1}</div>`;
            content +=`</div>`
            content +=`<div class="gridUI__grid-handle resize handle-down-right" data-x-dir="ltr" data-y-dir="ttb"><span class="bricks-svg-wrapper"><i class="fas fa-chevron-up"></i></span></div>`;
            content +=`<div class="gridUI__grid-handle resize handle-down-left" data-x-dir="rtl" data-y-dir="ttb"><span class="bricks-svg-wrapper"><i class="fas fa-chevron-up"></i></span></div>`;
            content +=`<div class="gridUI__grid-handle resize handle-up-right" data-x-dir="ltr" data-y-dir="btt"><span class="bricks-svg-wrapper"><i class="fas fa-chevron-up"></i></span></div>`;
            content +=`<div class="gridUI__grid-handle resize handle-up-left" data-x-dir="rtl" data-y-dir="btt"><span class="bricks-svg-wrapper"><i class="fas fa-chevron-up"></i></span></div>`;
            content +=`</div>`;
            element.innerHTML = content
            container.appendChild(element);
            i++;
        }
    },
    gridBuilderSetChild: function(id){
        const self = this;
        self.gridUIStates.activeChild = id;
        self.gridBuilderSetChildInfo(id);
        self.gridBuilderInitPreview();
    },
    gridBuilderAddCell: function(){
        const self = this;
        self.gridUIStates.elements.push({
            id: `${self.gridUIStates.elements.length + 1}`,
            label: `nth-child(${self.gridUIStates.elements.length + 1})`,
            color: Math.floor(Math.random() * 360),
        });
        self.gridBuilderSaveSettings();
        self.gridBuilderSetGridElements();
    },
    gridBuilderRemoveCell: function(){
        const self = this;
        self.gridUIStates.elements.pop();
        self.gridUIStates.activeChild = null;
        self.gridBuilderSaveSettings();
        self.gridBuilderSetGridElements();
        self.gridBuilderSetChildInfo(false);
    },
    gridBuilderSetParentInfo: function(){
        const self = this;
        const isCSS = self.gridUIStates.isClass || self.gridUIStates.hasQuery || self.gridUIStates.hasComponent;
        const wrapper = document.querySelector('#gridUI__parent-settings');
        let content = `<span class="gridUI__title">Parent Settings</span>
                    <div class="gridUI__input-inline-container">
                        <div class="gridUI__input-wrapper">
                            <label for="cols">Columns:</label>
                            <input id="cols" class="gridUI__grid-inputs event" type="number" value="${self.gridUIStates.grid.col.length}" min="0" max="12" autocomplete="off">
                        </div>
                        <div class="gridUI__input-wrapper">
                            <label for="rows">Rows:</label>
                            <input id="rows" class="gridUI__grid-inputs event" type="number" value="${self.gridUIStates.grid.row.length}" min="0" max="12" autocomplete="off">
                        </div>
                    </div>
                    <div class="gridUI__input-wrapper">
                        <label for="cols">Gap:</label>
                        <input id="gap" class="gridUI__grid-inputs" type="text" value="${self.gridUIStates.grid.gap}" autocomplete="off">
                    </div>
                    <div class="gridUI__input-wrapper auto-flow">
                        <label for="auto-flow" class="has-tooltip"><span>Fill empty cells</span><div data-balloon="If this option is checked, the grid-auto-flow will be set to DENSE and fill the empty cells inside the grid." data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>
                        ${self.gridUIStates.grid.autoFlow === true ? '<i class="fas fa-toggle-on"></i>' : '<i class="fas fa-toggle-off"></i>'}
                    </div>
                    <div class="gridUI__input-wrapper minmax">
                        <label for="minmax" class="has-tooltip"><span>Use minmax()</span><div data-balloon="If this option is checked, all the cols/rows values will be wrapped inside a minmax() function." data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>
                        ${self.gridUIStates.grid.minmax === true ? '<i class="fas fa-toggle-on"></i>' : '<i class="fas fa-toggle-off"></i>'}
                    </div>`;
        if(isCSS){
            content += `<div class="gridUI__input-wrapper repeat">
                            <label for="repeat" class="has-tooltip"><span>Repeat Grid</span><div data-balloon="If this option is checked, the childen CSS declarations will include a repetitive pattern (an+b)." data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>
                            ${self.gridUIStates.grid.repeat === true ? '<i class="fas fa-toggle-on"></i>' : '<i class="fas fa-toggle-off"></i>'}
                        </div>
                        <div class="gridUI__input-wrapper replace-css">
                            <label for="minmax" class="has-tooltip"><span>Replace CSS automatically</span><div data-balloon="If this option is checked, the script will remove any CSS declarations generated previously by the Grid Builder before adding the new ones." data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>
                            ${self.gridUIStates.grid.replaceCSS === true ? '<i class="fas fa-toggle-on"></i>' : '<i class="fas fa-toggle-off"></i>'}
                        </div>
                        <div class="gridUI__input-inline-container add-cells">
                            <a class="brxc-overlay__action-btn secondary" onclick="ADMINBRXC.gridBuilderRemoveCell();"><span>Remove Cell</span></a>
                            <a class="brxc-overlay__action-btn secondary" onclick="ADMINBRXC.gridBuilderAddCell();"><span>Add Cell</span></a>
                        </div>`;
        }
        wrapper.innerHTML = content;

        // Cols / rows
        const inputs = document.querySelectorAll('.gridUI__grid-inputs.event');
        inputs.forEach(input => {
            input.addEventListener('change', (e) => {
                if(e.target.value !== "" && typeof parseInt(e.target.value) !== "number") {
                    input.parentElement.classList.add('error');
                    return;
                }
                input.parentElement.classList.remove('error');
                self.gridBuilderSaveSettings();
                self.gridBuilderListenInputs();
                self.gridBuilderInitPreview();
                self.gridBuilderInitChild();
            })
            input.addEventListener('input', (e) => {
                if(e.target.value !== "" && typeof parseInt(e.target.value) !== "number") {
                    input.parentElement.classList.add('error');
                    return;
                }
                input.parentElement.classList.remove('error');
                self.gridBuilderSaveSettings();
                self.gridBuilderListenInputs();
                self.gridBuilderInitPreview();
                self.gridBuilderInitChild();
            })
        })

        // Gap
        const gapControl = document.querySelector('.gridUI__grid-inputs#gap');
        gapControl.addEventListener('input', (e) => {
            if(e.target.value !== "" && !CSS.supports("gap", e.target.value)) {
                gapControl.parentElement.classList.add('error');
                return;
            }
            gapControl.parentElement.classList.remove('error');
            self.gridBuilderSaveSettings();
            self.gridBuilderListenInputs();
            self.gridBuilderInitPreview();
            self.gridBuilderInitChild();
        })
        gapControl.addEventListener('focus', () =>{
            self.autocomplete(gapControl, self.cssVariables, "style", true);
        })

        // auto-flow
        const autoflowInput = document.querySelector('.gridUI__input-wrapper.auto-flow i[class*="fa-toggle"]');
        autoflowInput.addEventListener('click', () => {
            if(autoflowInput.classList.contains('fa-toggle-off')){
                self.gridUIStates.grid.autoFlow = true;
            } else {
                self.gridUIStates.grid.autoFlow = false;
            }
            self.gridBuilderSetGridCSS();
            self.gridBuilderSaveSettings();
            self.gridBuilderSetParentInfo();
        })

        // Use minmax()
        const minmaxInput = document.querySelector('.gridUI__input-wrapper.minmax i[class*="fa-toggle"]');
        minmaxInput.addEventListener('click', () => {
            if(minmaxInput.classList.contains('fa-toggle-off')){
                self.gridUIStates.grid.minmax = true;
            } else {
                self.gridUIStates.grid.minmax = false;
            }
            self.gridBuilderSaveSettings();
            self.gridBuilderSetParentInfo();
        })
        // Use repeat
        const repeatInput = document.querySelector('.gridUI__input-wrapper.repeat i[class*="fa-toggle"]');
        if(repeatInput){
            repeatInput.addEventListener('click', () => {
                if(repeatInput.classList.contains('fa-toggle-off')){
                    self.gridUIStates.grid.repeat = true;
                } else {
                    self.gridUIStates.grid.repeat = false;
                }
                self.gridBuilderSaveSettings();
                self.gridBuilderSetParentInfo();
            })
        }

        // replace CSS
        const replaceCSSInput = document.querySelector('.gridUI__input-wrapper.replace-css i[class*="fa-toggle"]');
        if(replaceCSSInput){
            replaceCSSInput.addEventListener('click', () => {
                if(replaceCSSInput.classList.contains('fa-toggle-off')){
                    self.gridUIStates.grid.replaceCSS = true;
                } else {
                    self.gridUIStates.grid.replaceCSS = false;
                }
                self.gridBuilderSaveSettings();
                self.gridBuilderSetParentInfo();
            })
        }
    },
    gridBuilderSetChildInfo: function(id){
        const self = this;
        const wrapper = document.querySelector('#gridUI__child-settings');
        const isCSS = self.gridUIStates.isClass || self.gridUIStates.hasQuery || self.gridUIStates.hasComponent;
        if(id === false){
            wrapper.innerHTML = '';
            return;
        }
        const gridObj = Object.values(self.gridUIStates.elements).find(el => el && el.id === id);
        if(!gridObj) return;

        const events = ['change', 'input']
        let posXstart, posXend, posYstart, posYend, xSpan, xSpanValue, ySpan, ySpanValue, zIndex, color;
        gridObj.hasOwnProperty('xStart') ? posXstart = gridObj.xStart : posXstart = '';
        gridObj.hasOwnProperty('xEnd') ? posXend = gridObj.xEnd : posXend = '';
        gridObj.hasOwnProperty('yStart') ? posYstart = gridObj.yStart : posYstart = '';
        gridObj.hasOwnProperty('yEnd') ? posYend = gridObj.yEnd : posYend = '';
        gridObj.hasOwnProperty('xSpan') ? xSpan = gridObj.xSpan : false;
        gridObj.hasOwnProperty('xSpanValue') ? xSpanValue = gridObj.xSpanValue : xSpanValue = '';
        gridObj.hasOwnProperty('ySpan') ? ySpan = gridObj.ySpan : false;
        gridObj.hasOwnProperty('ySpanValue') ? ySpanValue = gridObj.ySpanValue : ySpanValue = '';
        gridObj.hasOwnProperty('zIndex') ? zIndex = gridObj.zIndex : zIndex = '';
        gridObj.hasOwnProperty('color') ? color = gridObj.color : color = '';
        let content = `<span class="gridUI__title">Child Settings <div class="gridUI__id-selector">${isCSS ? `nth-child(${id})` : `#${id}`}<div class="icon-wrapper"data-balloon="Clear" data-balloon-pos="top" onclick="ADMINBRXC.gridBuilderRemoveActiveChild();"><i class="fas fa-close"></i></div></div></span>`;
        content += `<div class="gridUI__input-inline-container">
                        <div class="gridUI__input-wrapper">
                            <label for="label">Label:</label>
                            <input id="label" class="gridUI__grid-inputs label" type="text" value="${gridObj.label}" data-type="label"${isCSS ? ' readonly' : ''} autocomplete="off">
                        </div>
                    </div>`;
        content += `<div class="gridUI__input-inline-container">`
        if(ySpan !== 1){
            content += `<div class="gridUI__input-wrapper">
                            <label for="grid-col-start">Column-Start:</label>
                            <input id="grid-col-start" class="gridUI__grid-inputs pos" type="number" min="1" max="12" value="${posYstart}" data-type="yStart" autocomplete="off">
                        </div>
                        <div class="gridUI__input-wrapper${posYend > (self.gridUIStates.grid.col.length + 1) ? ' error' : ''}">
                            <label for="grid-col-end">Column-End:</label>
                            <input id="grid-col-end" class="gridUI__grid-inputs pos" type="number" min="1" max="13" value="${posYend}" data-type="yEnd" autocomplete="off">
                        </div>`;
        } else {
            content += `<div class="gridUI__input-wrapper">
                            <label for="grid-col-span">Column-Span:</label>
                            <input id="grid-col-span" class="gridUI__grid-inputs pos" type="number" min="1" max="12" value="${ySpanValue}" data-type="ySpanValue" autocomplete="off">
                        </div>`
        }
            content += `<div class="gridUI__span-toggle"><div${ySpan === 1 ? ' class="active"' : ''} data-type="ySpan" data-balloon="${ySpan ? 'Disable' : 'Enable'} span" data-balloon-pos="top-right"><i class="fas fa-table-cells-large"></i></div></div>
                    </div>`;
        content += `<div class="gridUI__input-inline-container">`;
        if(xSpan !== 1){
            content += `<div class="gridUI__input-wrapper">
                            <label for="grid-row-start">Row-Start:</label>
                            <input id="grid-row-start" class="gridUI__grid-inputs pos" type="number" min="1" max="12" value="${posXstart}" data-type="xStart" autocomplete="off">
                        </div>
                        <div class="gridUI__input-wrapper${posXend > (self.gridUIStates.grid.row.length + 1) ? ' error' : ''}">
                            <label for="grid-row-end">Row-End:</label>
                            <input id="grid-row-end" class="gridUI__grid-inputs pos" type="number" min="1" max="13" value="${posXend}" data-type="xEnd" autocomplete="off">
                        </div>`
        } else {
            content += `<div class="gridUI__input-wrapper">
                            <label for="grid-row-span">Row-Span:</label>
                            <input id="grid-row-span" class="gridUI__grid-inputs pos" type="number" min="1" max="12" value="${xSpanValue}" data-type="xSpanValue" autocomplete="off">
                        </div>`
        }
                        
            content += `<div class="gridUI__span-toggle"><div${xSpan === 1 ? ' class="active"' : ''} data-type="xSpan" data-balloon="${xSpan ? 'Disable' : 'Enable'} span" data-balloon-pos="top-right"><i class="fas fa-table-cells-large"></i></div></div>
                    </div>`;
        content += `<div class="gridUI__input-inline-container">
                        <div class="gridUI__input-wrapper">
                            <label for="zIndex">z-index:</label>
                            <input id="zIndex" class="gridUI__grid-inputs z-index" type="number" min="-1" max="99999" value="${zIndex}" data-type="zIndex" autocomplete="off">
                        </div>
                        <div class="gridUI__input-wrapper">
                            <label for="color">Hue Color:</label>
                            <input id="color" class="gridUI__grid-inputs color" type="number" min="0" max="360" value="${color}" data-type="color" autocomplete="off">
                        </div>
                    </div>`;
        content += `<div class="gridUI__input-inline-container bottom m-top-16"><a class="brxc-overlay__action-btn secondary" onclick="ADMINBRXC.gridBuilderDeleteElementSettings(ADMINBRXC.gridUIStates.activeChild)"><span>Reset Styles</span></a>`;
        if(!isCSS) content += `<a class="brxc-overlay__action-btn secondary" onclick="ADMINBRXC.openElement('${id}');ADMINBRXC.closeModal(event, event.target, '#brxcGridUIOverlay')"><span>View Element</span></a>`;
        content += `</div>`;
        wrapper.innerHTML = content;
        const inputs = wrapper.querySelectorAll('.gridUI__grid-inputs.pos');
        if(!inputs || inputs.length < 1) return;
        inputs.forEach(input => {
            events.forEach(event => {
                input.addEventListener(event, (e) => {
                    const type = input.dataset.type.startsWith('x') ? 'row' : 'col';
                    if(typeof parseInt(e.target.value) !== "number" || e.target.value > (self.gridUIStates.grid[type].length + 1)) {
                        input.parentElement.classList.add('error');
                        return;
                    }
                    input.parentElement.classList.remove('error');
                    self.gridBuilderChangeGrid(id, input.dataset.type, parseInt(e.target.value))
                })
            })
        })

        // span toggle
        const spanToggles = document.querySelectorAll('.gridUI__span-toggle div');
        spanToggles.forEach(toggle => {
            toggle.addEventListener('click', () => {
                let value;
                toggle.classList.contains('active') ? value = 0 : value = 1;
                self.gridBuilderChangeGrid(id, toggle.dataset.type, value, true)
            })
        })

        // label
        const labelInput = document.querySelector('.gridUI__grid-inputs.label');
        if(!labelInput) return;
        labelInput.addEventListener('input', (e) => {
            if(e.target.value === "") {
                labelInput.parentElement.classList.add('error');
                return;
            }
            labelInput.parentElement.classList.remove('error');
            const gridObj = Object.values(self.gridUIStates.elements).find(el => el && el.id === id);
            if(!gridObj) return;
            gridObj.label = e.target.value;
            self.gridBuilderInitPreview();
            self.gridBuilderSaveSettings();
        })
    

        // zIndex
        const zIndexInput = document.querySelector('.gridUI__grid-inputs.z-index');
        if(!zIndexInput) return;
        events.forEach(event => {
            zIndexInput.addEventListener(event, (e) => {
                if(typeof parseInt(e.target.value) !== "number") {
                    zIndexInput.parentElement.classList.add('error');
                    return;
                }
                zIndexInput.parentElement.classList.remove('error');
                const gridObj = Object.values(self.gridUIStates.elements).find(el => el && el.id === id);
                if(!gridObj) return;
                gridObj.zIndex = parseInt(e.target.value);
                self.gridBuilderSaveSettings();
            })
        })

        // Color
        const colorInput = document.querySelector('.gridUI__grid-inputs.color');
        if(!colorInput) return;
        events.forEach(event => {
            colorInput.addEventListener(event, (e) => {
                if(typeof parseInt(e.target.value) !== "number") {
                    colorInput.parentElement.classList.add('error');
                    return;
                }
                colorInput.parentElement.classList.remove('error');
                const gridObj = Object.values(self.gridUIStates.elements).find(el => el && el.id === id);
                if(!gridObj) return;
                gridObj.color = parseInt(e.target.value);
                self.gridBuilderInitPreview();
                self.gridBuilderSaveSettings();
            })
        })
    },
    gridBuilderChangeGrid: function(id, type, value, reloadChild = false){
        const self = this;
        if(typeof value !== "number") return;
        const gridObj = Object.values(self.gridUIStates.elements).find(el => el && el.id === id);
        if(!gridObj) return;
        gridObj[type] = value;

         // Add Cols
         if(type === 'yEnd' && value > (self.gridUIStates.grid.col.length + 1)){
            const newCols = value - self.gridUIStates.grid.col.length + 1;
            for(let i = 0; i < newCols; i++){
                self.gridUIStates.grid.col.push('1fr');
            }
        }

        // Add Rows
        if(type === 'xEnd' && value > (self.gridUIStates.grid.row.length + 1)){
            const newRows = value - self.gridUIStates.grid.row.length + 1;
            for(let i = 0; i < newRows; i++){
                self.gridUIStates.grid.row.push('1fr');
            }
        }

        self.gridBuilderSaveSettings();
        self.gridBuilderInitPreview();
        self.gridBuilderInitParent();
        if (reloadChild) self.gridBuilderInitChild();

    },
    gridBuilderRemoveActiveChild: function(){
        const self = this;
        self.gridUIStates.activeChild = null;
        self.gridBuilderSetChildInfo(false);
        self.gridBuilderInitPreview();
    },
    gridBuilderDeleteElementSettings: function(id){
        const self = this;
        const obj = Object.values(self.gridUIStates.elements).find(el => el && el.id === id);
        delete obj.xStart;
        delete obj.xEnd;
        delete obj.yStart;
        delete obj.yEnd;
        delete obj.xSpan;
        delete obj.xSpanValue;
        delete obj.ySpan;
        delete obj.ySpanValue;
        self.gridBuilderSaveSettings();
        self.gridBuilderInitPreview();
        self.gridBuilderInitParent();
        self.gridBuilderInitChild();
    },
    gridBuilderDragStartElement: function(el){
        const self = this;
        self.gridUIStates.draggingEl = el;
        //el.classList.add('moving');
        //intersect
        self.gridUIStates.els = [];
        const resizedRect = el.getBoundingClientRect();
        const guides = document.querySelectorAll('.gridUI__grid-guide');
        guides.forEach((guide) => {
            const guideRect = guide.getBoundingClientRect();

            // Check for intersection
            if (
                resizedRect.right > guideRect.left &&
                resizedRect.left < guideRect.right &&
                resizedRect.bottom > guideRect.top &&
                resizedRect.top < guideRect.bottom
            ) {
                // Intersection detected, you can handle it here
                if(!self.gridUIStates.els.includes(guide)) self.gridUIStates.els.push(guide);
            } else {
                self.gridUIStates.els = self.gridUIStates.els.filter(item => item !== guide);
            }
        });

        const sizeX = self.gridBuilderFindExtremeValue(self.gridUIStates.els, 'xEnd', 'max') - self.gridBuilderFindExtremeValue(self.gridUIStates.els, 'xStart', 'min');
        const sizeY = self.gridBuilderFindExtremeValue(self.gridUIStates.els, 'yEnd', 'max') - self.gridBuilderFindExtremeValue(self.gridUIStates.els, 'yStart', 'min');
        self.gridUIStates.draggingElSize = [sizeX, sizeY];
    },

    gridBuilderDragElement: function(el){
        //el.stopPropagation();
        const container = document.querySelector('.gridUI__grid-container-guide');
        container.style.zIndex = 2;
        const activeEl = document.querySelector('.gridUI__grid-element.active');
        if(!activeEl) return;
        activeEl.classList.add('inactive');
        activeEl.classList.remove('active');
        
    },

    gridBuilderDragEnd: function(){
        const self = this;
        const container = document.querySelector('.gridUI__grid-container-guide');
        container.style.zIndex = 0;
        self.gridBuilderSaveSettings();
    },

    gridBuilderDropElement: function(e){
        const self = this;
        const xEnd = parseInt(e.dataset.xEnd);
        const yEnd = parseInt(e.dataset.yEnd);
        const xStartTemp = xEnd - parseInt(self.gridUIStates.draggingElSize[0]);
        const yStartTemp = yEnd - parseInt(self.gridUIStates.draggingElSize[1]);
        const xStart = (xStartTemp > 0) ? xStartTemp : 1;
        const yStart = (yStartTemp > 0) ? yStartTemp : 1;
        const obj = Object.values(self.gridUIStates.elements).find(el => el && el.id === self.gridUIStates.draggingEl.dataset.id);
        if(obj.hasOwnProperty('xSpan')) delete obj.xSpan;
        if(obj.hasOwnProperty('xSpanValue')) delete obj.xSpanValue;
        if(obj.hasOwnProperty('ySpan')) delete obj.ySpan;
        if(obj.hasOwnProperty('ySpanValue')) delete obj.ySpanValue;
        obj.xStart = xStart;
        obj.xEnd = xEnd;
        obj.yStart = yStart;
        obj.yEnd = yEnd;

        // Add Cols
        if(yEnd > (self.gridUIStates.grid.col.length + 1)){
            const newCols = yEnd - self.gridUIStates.grid.col.length + 1;
            for(let i = 0; i < newCols; i++){
                self.gridUIStates.grid.col.push('1fr');
            }
        }

        // Add Rows
        if(xEnd > (self.gridUIStates.grid.row.length + 1)){
            const newRows = xEnd - self.gridUIStates.grid.row.length + 1;
            for(let i = 0; i < newRows; i++){
                self.gridUIStates.grid.row.push('1fr');
            }
        }
        self.gridBuilderSaveSettings();
        self.gridBuilderInitPreview();
        self.gridBuilderInitParent();
        self.gridBuilderInitChild();
    },

    gridBuilderBuildCSS: function(){
        const self = this;
        const styleSheet = document.querySelector('#gridUI__grid-elements');
        content = '';
        for(const key of Object.keys(self.gridUIStates.elements)){
            let hasStyle = false;
            let xStyles = false;
            let yStyles = false;

            // x
            if(self.gridUIStates.elements[key].hasOwnProperty('xSpan') && self.gridUIStates.elements[key].xSpan === 1 && self.gridUIStates.elements[key].hasOwnProperty('xSpanValue')){
                hasStyle = true;
                xStyles = `grid-row: span ${self.gridUIStates.elements[key].xSpanValue};`
            } else if(self.gridUIStates.elements[key].hasOwnProperty('xStart') && self.gridUIStates.elements[key].hasOwnProperty('xEnd')){
                hasStyle = true;
                xStyles = `grid-row: ${self.gridUIStates.elements[key].xStart} / ${self.gridUIStates.elements[key].xEnd};`
            }

            // y
            if(self.gridUIStates.elements[key].hasOwnProperty('ySpan') && self.gridUIStates.elements[key].ySpan === 1 && self.gridUIStates.elements[key].hasOwnProperty('ySpanValue')){
                hasStyle = true;
                yStyles = `grid-column: span ${self.gridUIStates.elements[key].ySpanValue};`
            } else if(self.gridUIStates.elements[key].hasOwnProperty('yStart') && self.gridUIStates.elements[key].hasOwnProperty('yEnd')){
                hasStyle = true;
                yStyles = `grid-column: ${self.gridUIStates.elements[key].yStart} / ${self.gridUIStates.elements[key].yEnd};`
            }

            // Styles
            if(hasStyle){
                content += `.gridUI__grid-element[data-id="${self.gridUIStates.elements[key].id}"]{`;
                if(xStyles) content += xStyles;
                if(yStyles) content += yStyles;
                content += '}';
            }

        }
        styleSheet.innerHTML = content;
    },

    gridBuilderSetGridGuides: function(){
        const self = this;
        const container = document.querySelector('.gridUI__grid-container-guide');
        const max = Array.from(self.gridUIStates.grid.col).length * Array.from(self.gridUIStates.grid.row).length;

        // Clear existing content
        container.innerHTML = '';

        // Create and append elements with valid dimensions
        for (let i = 0; i < max; i++) {
            const guide = document.createElement('div');
            guide.classList.add('gridUI__grid-guide');
            guide.setAttribute('data-id', i);
            guide.setAttribute('draggable', 'true');
            guide.setAttribute('ondragenter' , "this.classList.add('active')" );
            guide.setAttribute('ondragleave', "this.classList.remove('active')" );
            guide.setAttribute('ondragover', "event.preventDefault()" )
            guide.setAttribute('ondrop', 'ADMINBRXC.gridBuilderDropElement(this)');
            container.appendChild(guide);
        }

    },

    gridBuilderCalculateGridPosition: function() {
        const gridContainer = document.querySelector('.gridUI__grid-container');
        const gridGuides = document.querySelectorAll('.gridUI__grid-guide');
        const colCount = parseInt(window.getComputedStyle(gridContainer).gridTemplateColumns.split(' ').length);

        let row = 0;
        let col = 0;

        gridGuides.forEach(function(guide) {
            guide.setAttribute('data-x-start', row + 1);
            guide.setAttribute('data-x-end', row + 2);
            guide.setAttribute('data-y-start', col + 1);
            guide.setAttribute('data-y-end', col + 2);

            col++;

            if (col >= colCount) {
            col = 0;
            row++;
            }
        });
    },

    gridBuilderSetHandles: function(){
        const self = this;
        const handles = document.querySelectorAll('.gridUI__grid-handle-container');
        handles.forEach(handle => {
            self.gridBuilderMakeResizableDiv(handle);
        })
    },

    gridBuilderFindExtremeValue: function(elements, attribute, type) {
        if (elements.length === 0) {
            return undefined; // Return undefined if there are no elements
        }

        // Use the reduce function to find the extreme value
        const initialValue = parseInt(elements[0].dataset[attribute], 10);
        const extremeValue = Array.from(elements).reduce((extreme, element) => {
            const attributeValue = parseInt(element.dataset[attribute], 10); // Assuming the attribute is stored in the 'data-' attribute

            if (!isNaN(attributeValue)) {
            return type === 'min' ? Math.min(extreme, attributeValue) : Math.max(extreme, attributeValue);
            } else {
            return extreme;
            }
        }, initialValue);

        return extremeValue;
    },

    gridBuilderCalculateNewPosition: function(id, els){
        const self = this;
        const xStart = self.gridBuilderFindExtremeValue(self.gridUIStates.els, 'xStart', 'min')
        const xEnd = self.gridBuilderFindExtremeValue(self.gridUIStates.els, 'xEnd', 'max')
        const yStart = self.gridBuilderFindExtremeValue(self.gridUIStates.els, 'yStart', 'min')
        const yEnd = self.gridBuilderFindExtremeValue(self.gridUIStates.els, 'yEnd', 'max');
        const obj = Object.values(self.gridUIStates.elements).find(el => el && el.id === id);
        
        delete obj.xSpan;
        delete obj.xSpanValue;
        delete obj.ySpan;
        delete obj.ySpanValue;
        
        obj.xStart = xStart;
        obj.xEnd = xEnd;
        obj.yStart = yStart;
        obj.yEnd = yEnd;

    },

    gridBuilderMakeResizableDiv: function(div) {
        const self = this;
        const handles = div.querySelectorAll('.gridUI__grid-handle.resize');
        let isResizing = false;
        let startX, startY;

        handles.forEach(handle => {
            const xDirection = handle.dataset.xDir;
            const yDirection = handle.dataset.yDir;

            handle.addEventListener("mousedown", (e) => {
                e.preventDefault();
                e.stopPropagation();
                handle.parentElement.style.zIndex = 2;
                handle.parentElement.parentElement.classList.add('moving');
                isResizing = true;
                startX = e.clientX;
                startY = e.clientY;
                document.addEventListener("mousemove", handleMouseMove);
                document.addEventListener("mouseup", handleMouseUp);
                const activeEl = document.querySelector('.gridUI__grid-element.active');
                if(!activeEl) return;
                activeEl.classList.add('inactive');
                activeEl.classList.remove('active');
            });
        
            function handleMouseUp(){
                isResizing = false;
                document.removeEventListener("mousemove", handleMouseMove);
                document.removeEventListener("mouseup", handleMouseUp);
                self.gridBuilderCalculateNewPosition(handle.parentElement.parentElement.dataset.id, self.gridUIStates.els);
                self.gridBuilderSaveSettings();
                self.gridBuilderInitPreview();
                self.gridBuilderInitParent();
                self.gridBuilderInitChild();
            }
            function handleMouseMove(e) {
                if (isResizing) {
                    e.stopPropagation();
                    self.gridUIStates.els = [];
                    const deltaX = xDirection === "ltr" ? e.clientX - startX : -e.clientX + startX;
                    const deltaY = yDirection === "ttb" ? e.clientY - startY : -e.clientY + startY ;

                    // Calculate the new width and height based on the initial position
                    const newWidth = div.getBoundingClientRect().width + deltaX;
                    const newHeight = div.getBoundingClientRect().height + deltaY;

                    // Ensure resizing within the boundaries of the container
                    div.style.width = `${newWidth}px`;
                    div.style.height = `${newHeight}px`;
                    div.style.left = xDirection === "ltr" ? '0' : `auto`;
                    div.style.top = yDirection === "ttb" ? '0' : `auto`;

                    // Update the start position for the next movement
                    startX = e.clientX;
                    startY = e.clientY;

                    //intersect
                    const resizedRect = div.getBoundingClientRect();
                    const guides = document.querySelectorAll('.gridUI__grid-guide');
                    guides.forEach((guide) => {
                        const guideRect = guide.getBoundingClientRect();

                        // Check for intersection
                        if (
                            resizedRect.right >= guideRect.left &&
                            resizedRect.left <= guideRect.right &&
                            resizedRect.bottom >= guideRect.top &&
                            resizedRect.top <= guideRect.bottom
                        ) {
                            // Intersection detected, you can handle it here
                            guide.classList.add('active');
                            if(!self.gridUIStates.els.includes(guide)) self.gridUIStates.els.push(guide);
                        } else {
                            guide.classList.remove('active');
                            self.gridUIStates.els = self.gridUIStates.els.filter(item => item !== guide);
                        }
                    });
                }
            }
        })
    },

    gridBuilderSetHeaders: function(){
        const self = this;
        const headerTop = document.querySelector('.gridUI__grid-header.top');
        const headerLeft = document.querySelector('.gridUI__grid-header.left');
        let content = '';

        let i = 0;
        for(const value of Array.from(self.gridUIStates.grid.col)){
            content += `<div class="input-wrapper" data-balloon="Invalid CSS value" data-balloon-pos="top"><input type="text" value="${value}" data-type="col" data-index="${i}"></div>`;
            i++;
        }
        headerTop.innerHTML = content;

        content = '';
        i = 0;
        for(const value of Array.from(self.gridUIStates.grid.row)){
            content += `<div class="input-wrapper" data-balloon="Invalid CSS value" data-balloon-pos="top"><input type="text" value="${value}" data-type="row" data-index="${i}"></div>`
            i++;
        }
        headerLeft.innerHTML = content;
        const headerInputs = document.querySelectorAll('.gridUI__grid-header input');
        headerInputs.forEach(input => {
            input.addEventListener('input', (e) => {
                if(!CSS.supports("grid-template-columns", input.value)) {
                    input.parentElement.classList.add('error');
                    return;
                }
                input.parentElement.classList.remove('error');
                const type = input.dataset.type;
                const index = input.dataset.index;
                self.gridUIStates.grid[type][index] = input.value; 
                self.gridBuilderSetGridCSS();
                self.gridBuilderSaveSettings();
            })
        })
    },

    gridBuilderInitPreview: function(){
        const self = this;
        self.gridBuilderSetGridCSS();
        self.gridBuilderSetGridElements();
        self.gridBuilderSetGridGuides();
        self.gridBuilderSetHeaders();
        self.gridBuilderCalculateGridPosition();
        self.gridBuilderBuildCSS();
        self.gridBuilderSetHandles();
    },
    gridBuilderInitParent: function(){
        const self = this;
        self.gridBuilderSetParentInfo();
    },
    gridBuilderInitChild: function(){
        const self = this;
        if(self.gridUIStates.activeChild === null) return self.gridBuilderSetChildInfo(false);
        self.gridBuilderSetChildInfo(self.gridUIStates.activeChild);
    },

    gridBuilderCalculateGridCols: function(checkRows = true, rows, cols){
        const self = this;
        const container = document.querySelector('.gridUI__grid-container');
        const tempRows = window.getComputedStyle(container).getPropertyValue("grid-template-rows").split(' ').length;
        if(checkRows && parseInt(globalRows) < parseInt(tempRows)) {
            self.gridUIStates.globalRows = parseInt(tempRows);
            document.querySelector('#rows').value = self.gridUIStates.globalRows;
        }
        const main = document.querySelector('.gridUI__main-container');

        // main.style.setProperty('--col', globalCols);
        // main.style.setProperty('--row', globalRows);
        // main.style.setProperty('--gap', globalGap);

    },
    gridBuilderLoadDefaultGrid: function(){
        const self = this;
        self.gridUIStates.grid = {}
            self.gridUIStates.grid.col = []
            self.gridUIStates.grid.row = []
            // Cols
            const defaultCols = {
                '991': 3,
                '767': 2,
                '478': 1,
            };
            const orderedKeys = ['991', '767', '478'];

            const currentVw = parseInt(self.vueState.previewWidth);
            let finalCol = false;
            for(const key of orderedKeys){
                if(currentVw <= parseInt(key)) finalCol = defaultCols[key];
            }
            if(finalCol === false) finalCol = 4;
            for(let i = 0; i < finalCol; i++){
                self.gridUIStates.grid.col[i] = '1fr';
            }

            // Rows
            let finalRows;
            const numberItems = Object.keys(JSON.parse(self.gridUIStates.children)).length;
            numberItems === 0 ? finalRows = 1 : finalRows = Math.ceil(numberItems / finalCol);
            for(let i = 0; i < finalRows; i++){
                self.gridUIStates.grid.row[i] = '1fr';
            }

            // Gap
            self.gridUIStates.grid.gap = '20px';
    },
    gridBuilderLoadGrid: function(){
        const self = this;

        const parent = self.builderStates.activeObject;
        const target = self.helpers.createTargetWithPseudo('gridBuilderSettings');
        const higherBp = self.gridUIStates.isClass ? self.helpers.checkHigherBreakpoint('gridBuilderSettings', 'class') : self.helpers.checkHigherBreakpoint('gridBuilderSettings', 'element');
        if(parent.settings.hasOwnProperty(target)){
            self.gridUIStates.grid = JSON.parse(JSON.stringify(parent.settings[target].grid));
        } else if(higherBp){
            self.gridUIStates.grid = JSON.parse(JSON.stringify(parent.settings[higherBp].grid));
        } else {
            self.gridBuilderLoadDefaultGrid();
        }
        
    },

    // gridBuilderSetGridCSS: function(){
    //     const self = this;
    //     const main = document.querySelector('.gridUI__main-container');
    //     main.style.setProperty('--globalCol', Array.from(self.gridUIStates.grid.col).map(value => value).join(' '));
    //     main.style.setProperty('--globalGap', self.gridUIStates.grid.gap);
    //     let autoFlow;
    //     self.gridUIStates.grid.autoFlow === true ? autoFlow = 'dense' : autoFlow = 'initial';
    //     main.style.setProperty('--globalAutoFlow', autoFlow);
       
    //     const container = main.querySelector('.gridUI__grid-container');
    //     setTimeout(() => {

    //         const realRows = window.getComputedStyle(container).gridTemplateRows;
    //         const numRealRows = realRows.split(' ').length;
    //         const calculatedRows = Array.from(self.gridUIStates.grid.row).map(value => value).join(' ')
    //         const numCalculatedRows = calculatedRows.split(' ').length;

    //         if(numRealRows > numCalculatedRows){
    //             main.style.setProperty('--globalRow', 'auto');
    //             setTimeout(() => {
    //                 for(let i = 0; i < numRealRows - numCalculatedRows; i++){
    //                     self.gridUIStates.grid.row.push('1fr')
    //                 }
    //                 self.gridUIStates.globalRows = numRealRows;
    //                 self.gridBuilderInitParent();
    //                 self.gridBuilderInitPreview();
    //             },5)

    //         } else {
    //             main.style.setProperty('--globalRow', calculatedRows);
    //         }
    //     }, 5)
    // },
    gridBuilderSetGridCSS: function(){
        const self = this;
        const main = document.querySelector('.gridUI__main-container');
        main.style.setProperty('--globalCol', Array.from(self.gridUIStates.grid.col).map(value => value).join(' '));
        main.style.setProperty('--globalRow', Array.from(self.gridUIStates.grid.row).map(value => value).join(' '));
        main.style.setProperty('--globalGap', self.gridUIStates.grid.gap);
        const autoFlow = self.gridUIStates.grid.autoFlow === true ? 'dense' : 'initial';
        main.style.setProperty('--globalAutoFlow', autoFlow);
    },
    gridBuilderLoadElements: function(initialize = false){
        const self = this;
        const isCSS = self.gridUIStates.isClass || self.gridUIStates.hasQuery || self.gridUIStates.hasComponent;

        let tempEls = [];
        const activeEl = self.builderStates.activeObject;
        const children = JSON.parse(self.gridUIStates.children);
        const target = self.helpers.createTargetWithPseudo('gridBuilderSettings');
        const higherBp = self.gridUIStates.isClass === true ? self.helpers.checkHigherBreakpoint('gridBuilderSettings', 'class') : self.helpers.checkHigherBreakpoint('gridBuilderSettings', 'element');
        let gridSettings = false;
        if(activeEl.settings.hasOwnProperty(target)) {
            gridSettings = activeEl.settings[target];
        } else if(higherBp){
            gridSettings = activeEl.settings[higherBp];
        } 

        // Element
        if(!isCSS){
            for(let i = 0; i<children.length; i++){
                const obj = self.helpers.getElementObject(children[i]);
                tempEls[i] = {};
                tempEls[i].id = children[i];
                const label = obj.hasOwnProperty('label') ? obj.label : bricksData.elements[obj.name]?.label;
                tempEls[i].label = label;
                if(gridSettings && !initialize){
                    const gridObj = Object.values(gridSettings.elements).find(el => el && el.id === children[i])
                    if(gridObj){
                        // Position
                        if(gridObj.hasOwnProperty('xStart')) tempEls[i].xStart = gridObj.xStart;
                        if(gridObj.hasOwnProperty('xEnd')) tempEls[i].xEnd = gridObj.xEnd;
                        if(gridObj.hasOwnProperty('xSpan')) tempEls[i].xSpan = gridObj.xSpan;
                        if(gridObj.hasOwnProperty('xSpanValue')) tempEls[i].xSpanValue = gridObj.xSpanValue;
                        if(gridObj.hasOwnProperty('yStart')) tempEls[i].yStart = gridObj.yStart; 
                        if(gridObj.hasOwnProperty('yEnd')) tempEls[i].yEnd = gridObj.yEnd;
                        if(gridObj.hasOwnProperty('ySpan')) tempEls[i].ySpan = gridObj.ySpan;
                        if(gridObj.hasOwnProperty('ySpanValue')) tempEls[i].ySpanValue = gridObj.ySpanValue;


                        // zIndex
                        if(gridObj.hasOwnProperty('zIndex')) tempEls[i].zIndex = gridObj.zIndex;

                        // Color
                        if(gridObj.hasOwnProperty('color')) tempEls[i].color = gridObj.color; 
                    }
                }
            } 

        // Class
        } else {
            let childrenLength = Object.keys(children).length;
            // Existing settings
            if(gridSettings){
                tempEls = JSON.parse(JSON.stringify(gridSettings.elements));
                // if(gridSettings.elements.length > childrenLength){
                //     const minus = gridSettings.elements.length - childrenLength;
                //     for(let i = 0; i<minus; i++){
                //         tempEls.pop();
                //     }
                // }
                if (tempEls.length > childrenLength) childrenLength = tempEls.length;
                for(let i = 0; i<childrenLength; i++){
                    if(!tempEls[i]) tempEls[i] = {};
                    tempEls[i].id = `${i + 1}`;
                    tempEls[i].label = `nth-child(${i + 1})`;
                }
            
            // Generate new settings
            } else {
                for(let i = 0; i<childrenLength; i++){
                    tempEls[i] = {};
                    tempEls[i].id = `${i + 1}`;
                    tempEls[i].label = `nth-child(${i + 1})`;
                }
            }
        }

        self.gridUIStates.elements = tempEls;
        
        for(const key of Object.keys(self.gridUIStates.elements)){
            const color = Math.floor(Math.random() * 360)
            if(!self.gridUIStates.elements[key].hasOwnProperty('color')) self.gridUIStates.elements[key].color = color;
        }
    },

    gridBuilderAddColumn: function(){
        const self = this;
        self.gridUIStates.grid.col[Array.from(self.gridUIStates.grid.col).length] = '1fr';
        self.gridUIStates.grid.colWidth = Array.from(self.gridUIStates.grid.col).length;
        self.gridBuilderSaveSettings();
    },

    gridBuilderRemoveColumn: function(){
        const self = this;
        self.gridUIStates.grid.col.pop();
        self.gridUIStates.grid.colWidth = Array.from(self.gridUIStates.grid.col).length;
        self.gridBuilderSaveSettings();
    },

    gridBuilderAddRow: function(){
        const self = this;
        self.gridUIStates.grid.row[Array.from(self.gridUIStates.grid.row).length] = '1fr';
        self.gridUIStates.grid.rowWidth = Array.from(self.gridUIStates.grid.row).length;
        self.gridBuilderSaveSettings();
    },

    gridBuilderRemoveRow: function(){
        const self = this;
        self.gridUIStates.grid.row.pop();
        self.gridUIStates.grid.rowWidth = Array.from(self.gridUIStates.grid.row).length;
        self.gridBuilderSaveSettings();
    },

    gridBuilderListenInputs: function(){
        const self = this;
        let inputs = document.querySelectorAll('.gridUI__grid-inputs');

        self.gridUIStates.globalCols = inputs[0].value === "" ? 0 : parseInt(inputs[0].value);
        self.gridUIStates.globalRows = inputs[1].value === "" ? 0 : parseInt(inputs[1].value);
        self.gridUIStates.grid.gap = inputs[2].value;

        self.gridUIStates.grid.row = [];
        self.gridUIStates.grid.col = [];

        const headerTop = document.querySelectorAll('.gridUI__grid-header.top input');
        const headerLeft = document.querySelectorAll('.gridUI__grid-header.left input');

        for(let i = 0; i < headerTop.length; i++){
            self.gridUIStates.grid.col[i] = headerTop[i].value;
        }
        for(let i = 0; i < headerLeft.length; i++){
            self.gridUIStates.grid.row[i] = headerLeft[i].value;
        }

        // Col
        if(self.gridUIStates.grid.col.length < self.gridUIStates.globalCols) {
            const max = self.gridUIStates.globalCols - self.gridUIStates.grid.col.length;
            for(let i = 0; i<max; i++){
                self.gridBuilderAddColumn()
            }
        } else if(self.gridUIStates.grid.col.length > self.gridUIStates.globalCols){
            const max = self.gridUIStates.grid.col.length - self.gridUIStates.globalCols;
            for(let i = 0; i<max; i++){
                self.gridBuilderRemoveColumn();
            }
        }

        // Row
        if(self.gridUIStates.grid.row.length < self.gridUIStates.globalRows) {
            const max = self.gridUIStates.globalRows - self.gridUIStates.grid.row.length;
            for(let i = 0; i<max; i++){
                self.gridBuilderAddRow()
            }
        } else if(self.gridUIStates.grid.row.length > self.gridUIStates.globalRows){
            const max = self.gridUIStates.grid.row.length - self.gridUIStates.globalRows;
            for(let i = 0; i<max; i++){
                self.gridBuilderRemoveRow()
            }
        }

        self.gridBuilderSaveSettings();
    },
    gridBuilderIsQueryLoop: function(){
        const self = this;
        const children = self.builderStates.activeElement?.children;
        let hasQuery = false;
        if(children && children.length > 0) {
            hasQuery = children.some(el => self.helpers.getElementObject(el, true)?.settings?.hasOwnProperty('hasLoop') && self.helpers.getElementObject(el, true).settings.hasLoop === true); 
        }
        self.gridUIStates.hasQuery = hasQuery ? true : false;
    },
    gridBuilderhasComponent: function(){
        const self = this;
        const children = self.builderStates.activeElement?.children;
        let hasComponent = false;
        if(children && children.length > 0) {
            hasComponent = children.some(el => self.helpers.getElementObject(el, true)?.hasOwnProperty('cid')); 
        }
        self.gridUIStates.hasComponent = hasComponent ? true : false;
    },
    gridBuilderSetChildren: function(){
        const self = this;
        const isCSS = self.gridUIStates.isClass || self.gridUIStates.hasQuery || self.gridUIStates.hasComponent;
        const elementObj = self.builderStates.activeElement; 
        self.gridUIStates.children = isCSS ? JSON.stringify(FRAMEBRXC.vueGlobalProp.$_getElementNode(elementObj).children) : JSON.stringify(elementObj.children);
    },
  
    gridBuilderIsClass: function(){
        const self = this;
        self.gridUIStates.isClass = self.builderStates.isClassActive ? true : false;
    },

    gridBuilderInit: function(){
        const self = this;
        self.gridUIStates.activeChild = null;
        self.hideNativeGridBuilder();
        self.gridBuilderSetHeight();
        self.gridBuilderIsQueryLoop();
        self.gridBuilderhasComponent();
        self.gridBuilderIsClass();
        self.gridBuilderSetBreakpoints();
        self.gridBuilderSetChildren();
        self.gridBuilderSetNotification();
        self.gridBuilderLoadGrid();
        self.gridBuilderSetGridCSS();
        self.gridBuilderLoadElements();
        self.gridBuilderResizableWidth()
        self.gridBuilderResizableHeight()
        self.gridBuilderInitPreview();
        self.gridBuilderInitParent();
        self.gridBuilderInitChild();
    },
    hideNativeGridBuilder: function(){
        document.documentElement.classList.add('at-hide-native-grid-builder');
    },
    gridBuilderSaveSettings: function(){
        const self = this;
        const parent = self.builderStates.activeObject;
        const target = self.helpers.createTargetWithPseudo('gridBuilderSettings');

        parent.settings[target] = {};
        parent.settings[target].grid = self.gridUIStates.grid;
        parent.settings[target].elements = self.gridUIStates.elements;
        if(self.gridUIStates.isClass === true) ADMINBRXC.helpers.saveChanges('globalClasses');
        self.vueState.rerenderControls = Date.now();
    },
    gridBuilderRemovePreviousCSS: function(css){
        const pattern = /\/\*\* GRID BUILDER[\s\S]*?End of Grid Builder CSS \*\*\//g;
        return css.replaceAll(pattern, '');
    },
    gridBuilderApply: function(){
        const self = this;
        const isCSS = self.gridUIStates.isClass || self.gridUIStates.hasQuery || self.gridUIStates.hasComponent;
        const parent = self.builderStates.activeObject;
        

        // parent
        const targetGap = self.helpers.createTargetWithPseudo('_gridGap');
        parent.settings[targetGap] = self.gridUIStates.grid.gap;


        // ID
        if(!isCSS){

            // parent
            const targetCol = self.helpers.createTargetWithPseudo('_gridTemplateColumns');
            const targetRow = self.helpers.createTargetWithPseudo('_gridTemplateRows');
            const targetAutoFlow = self.helpers.createTargetWithPseudo('_gridAutoFlow');
            parent.settings[targetCol] = Array.from(self.gridUIStates.grid.col).map(value => self.gridUIStates.grid.hasOwnProperty('minmax') &&  self.gridUIStates.grid.minmax === true ? `minmax(0,${value})` : value).join(' ');
            parent.settings[targetRow] = Array.from(self.gridUIStates.grid.row).map(value => self.gridUIStates.grid.hasOwnProperty('minmax') &&  self.gridUIStates.grid.minmax === true ? `minmax(0,${value})` : value).join(' ');
            parent.settings[targetAutoFlow] = self.gridUIStates.grid.autoFlow === true ? 'dense' : '';

            //children
            const children = JSON.parse(self.gridUIStates.children);
            if(!Array.isArray(children) || children.length < 1) return;
            children.forEach(child => {
                const gridElement = Object.values(self.gridUIStates.elements).find(el => el && el.id === child);
                if(!gridElement) return;
                const obj = self.helpers.getElementObject(child);
                if(!obj.hasOwnProperty('settings')) obj.settings = {};

                // x
                const targetRowSpan = self.helpers.createTargetWithPseudo('_gridItemRowSpan');
                if(gridElement.hasOwnProperty('xSpan') && gridElement.xSpan === 1 && gridElement.hasOwnProperty('xSpanValue')) {
                    obj.settings[targetRowSpan] = `span ${gridElement.xSpanValue}`;
                } else {
                    gridElement.hasOwnProperty('xStart') && gridElement.hasOwnProperty('xEnd') ? obj.settings[targetRowSpan] = `${gridElement.xStart} / ${gridElement.xEnd}` : obj.settings[targetRowSpan] = 'unset';
                }

                // 
                const targetColSpan = self.helpers.createTargetWithPseudo('_gridItemColumnSpan');
                if(gridElement.hasOwnProperty('ySpan') && gridElement.ySpan === 1 && gridElement.hasOwnProperty('ySpanValue')) {
                    obj.settings[targetColSpan] = `span ${gridElement.ySpanValue}`;
                } else {
                    gridElement.hasOwnProperty('yStart') && gridElement.hasOwnProperty('yEnd') ? obj.settings[targetColSpan] = `${gridElement.yStart} / ${gridElement.yEnd}` : obj.settings[targetColSpan] = 'unset';
                }
                const targetZIndex =  self.helpers.createTargetWithPseudo('_zIndex');
                if (gridElement.hasOwnProperty('zIndex')) obj.settings[targetZIndex] = gridElement.zIndex;
                if (gridElement.label !== obj.label) obj.label = gridElement.label
            })

        // Class
        }  else {
            const elements = self.gridUIStates.elements;
            const selector = self.gridUIStates.isClass ? `.${parent.name}` : `#${self.vueGlobalProp.$_getElementId()}`;
            let cssChild = '';
            let cssParent = '';
            let hasParentStyle = false;

            // Parent CSS
            if(self.gridUIStates.grid.col && self.gridUIStates.grid.col.length > 0){
                hasParentStyle = true;
                cssParent += `grid-template-columns: ${Array.from(self.gridUIStates.grid.col).map(value => self.gridUIStates.grid.hasOwnProperty('minmax') &&  self.gridUIStates.grid.minmax === true ? `minmax(0,${value})` : value).join(' ')};`;
            }
            if(self.gridUIStates.grid.row && self.gridUIStates.grid.row.length > 0){
                hasParentStyle = true;
                cssParent += `grid-template-rows: ${Array.from(self.gridUIStates.grid.row).map(value => self.gridUIStates.grid.hasOwnProperty('minmax') &&  self.gridUIStates.grid.minmax === true ? `minmax(0,${value})` : value).join(' ')};`;
            }

            if(self.gridUIStates.grid.autoFlow === true){
                hasParentStyle = true;
                cssParent += `grid-auto-flow: dense;`;
            } else {
                hasParentStyle = true;
                cssParent += `grid-auto-flow: unset;`;
            }

            // Children CSS
            for(const key of Object.keys(elements)){
                const element = elements[key];
                let hasStyle = false;
                let xCSS = '';
                let yCSS = '';
                let zIndex = '';

                // x
                if(element.hasOwnProperty('xSpan') && element.xSpan === 1 && element.hasOwnProperty('xSpanValue')) {
                    hasStyle = true;
                    xCSS = `grid-row: span ${element.xSpanValue};`;
                } else if(element.hasOwnProperty('xStart') && element.hasOwnProperty('xEnd')){
                    hasStyle = true;
                    xCSS = `grid-row: ${element.xStart} / ${element.xEnd};`
                }

                // y
                if(element.hasOwnProperty('ySpan') && element.ySpan === 1 && element.hasOwnProperty('ySpanValue')) {
                    hasStyle = true;
                    yCSS = `grid-column: span ${element.ySpanValue};`;
                } else if(element.hasOwnProperty('yStart') && element.hasOwnProperty('yEnd')){
                    hasStyle = true;
                    yCSS = `grid-column: ${element.yStart} / ${element.yEnd};`
                }

                // z-index
                if(element.hasOwnProperty('zIndex')){
                    hasStyle = true;
                    zIndex = `z-index: ${element.zIndex};`
                }
                if(hasStyle){
                    const label = self.gridUIStates.grid.repeat === true ? `nth-child(${self.gridUIStates.elements.length}n+${element.id})` : `nth-child(${element.id})`
                    cssChild += `${selector} > *:where(:${label}){${xCSS}${yCSS}${zIndex}}\n\n`;
                }
            }
            if(!hasParentStyle && cssChild === '') return self.vueGlobalProp.$_showMessage(`Abort: no styles to apply on ${activebp.label}`);;

            let css = `/** GRID BUILDER (autogenerated on ${new Date(Date.now()).toLocaleDateString()}) **/\n\n`;
            
            if(hasParentStyle){
                css += `${selector}{${cssParent}}\n\n${selector}>*{grid-row:unset;grid-column:unset;}\n\n`;
            }
            if(cssChild !== ''){
                css += cssChild;
            }

            css += `/** End of Grid Builder CSS **/`;


            const target = self.helpers.createTarget('_cssCustom');
            parent.settings.hasOwnProperty(target) && self.gridUIStates.grid.replaceCSS === true ? parent.settings[target] = self.gridBuilderRemovePreviousCSS(parent.settings[target]) : '';
            css = css_beautify(css, { indent_size: 2 });
            if(!parent.settings.hasOwnProperty(target) || parent.settings[target] === ''){
                parent.settings[target] = css;
            } else {
                parent.settings[target] = `${self.helpers.removeTrailingNewlines(parent.settings[target])}\n\n${css}`;
            }
        }

        const activebp = self.vueState.breakpoints.find(el => el && el.key === self.vueState.breakpointActive);
        self.vueGlobalProp.$_showMessage(`Grid correctly applied on ${activebp.label}`);
    },
    // Box Shadow Generator
    setBoxShadowGenerator: function(){
        const self = this;
        Promise.resolve().then(()=> {
            const controls = document.querySelectorAll('[type="box-shadow"]');
            if(!controls || controls.length < 1) return;

            const settings = self.builderStates.activeObject;
            if(!settings) return;
            
            controls.forEach(control => {
                // Copy
                const icon = control.querySelector('.brxc-box-shadow-generator');
                if (icon) icon.remove();
                const controlkey = control.getAttribute('controlkey') || control.closest('[data-controlkey]')?.getAttribute('data-controlkey');
                if(!controlkey) return;
                const target = self.helpers.createTargetWithPseudo(`${controlkey.replaceAll('_', '')}Generator`);
                const cls = Object.keys(settings.settings).includes(target) ?  'brxc-box-shadow-generator bricks-control-preview active': 'brxc-box-shadow-generator bricks-control-preview';

                self.addIconToFields(
                    'div',
                    cls,
                    false,
                    'Box-Shadow Generator',
                    'top-right',
                    `ADMINBRXC.openModal({target: false, id: "#brxcBoxShadowUIOverlay", callback: () => {ADMINBRXC.bsInit("${controlkey}");}});`,
                    false,
                    '<span class="bricks-svg-wrapper"><i class="fas fa-layer-group"></i></span>',
                    control,
                    'child'
                );
                
            })
        });
    },
    bsSettings: undefined,
    bsTemp: {
        width: 400,
        height: 400,
        borderRadius: 10,
        layerAmount: 5,
        verticalDistance: 32,
        horizontalDistance: 0,
        blur: 24,
        spread: 0,
        shadowRgb: [3, 7, 18],
        //shadowStyle: "soft",
        boxColor: '#ffffff',
        boxBgColor: '#fafafa',
        opacity: 0.08,
        inset: '0',
    },
    bsStates: {
        selector: false,
        activeLayer: null,
        activeWindow: 'generator',
    },
    // Default
    bsRenderBoxShadows: function(obj) {
        const self = this;
        const boxShadows = [];

        const getX = (i) => {
            const startX = 0;
            const endX = obj.horizontalDistance;
            return startX + self.helpers.easeInQuad((i + 1) / obj.layerAmount) * (endX - startX);
        };

        const getY = (i) => {
            const startY = 0;
            const endY = obj.verticalDistance;
            return startY + self.helpers.easeInQuad((i + 1) / obj.layerAmount) * (endY - startY);
        };

        const getBlur = (i) => {
            const startBlur = 0;
            const endBlur = obj.blur;
            return (
            startBlur +
            self.helpers.easeInQuad((i + 1) / obj.layerAmount) * (endBlur - startBlur)
            );
        };

        // let getAlpha = (i) => obj.opacity;
        // if (obj.shadowStyle === "sharp") {
        //     getAlpha = (i) => {
        //     const increment = obj.opacity / obj.layerAmount;
        //     return obj.opacity - i * increment;
        //     };
        // } else if (obj.shadowStyle === "soft") {
        //     getAlpha = (i) => {
        //     const increment = obj.opacity / obj.layerAmount;
        //     return (i + 1) * increment;
        //     };
        // }

        const getAlpha = (i) => {
            const increment = obj.opacity / obj.layerAmount;
            return (i + 1) * increment;
        };


        for (let i = 0; i < obj.layerAmount; i++) {
            const x = getX(i).toFixed(0);
            const y = getY(i).toFixed(0);
            const blur = getBlur(i).toFixed(0);
            const spread = obj.spread;
            const rgb = obj.shadowRgb;
            const alpha = getAlpha(i).toFixed(2);
            const inset = obj.inset;

            boxShadows.push({ x, y, blur, spread, rgb, alpha, inset });
        }

        return boxShadows;
    },

    bsRenderCssShadows: function() {
        const self = this;
        const box = document.querySelector('#boxShadowUI__box');
        const boxShadows = typeof self.bsSettings === "undefined" ? self.bsRenderBoxShadows(self.bsTemp) : self.bsSettings.layers;
        const cssShadows = boxShadows.map(
            ({ x, y, blur, spread, rgb, alpha, inset }) =>
            `${inset === '1' ? 'inset ' : ''}${x}px ${y}px ${blur}px ${spread}px rgba(${Array.isArray(rgb) ? rgb.join(',') : rgb}, ${alpha})`
        );
        box.style.boxShadow = cssShadows.join(",\n  ");

    },
    bsRenderCssBox: function() {
        const self = this;
        const main = document.querySelector('#boxShadowUI__main');
        const box = main.querySelector('#boxShadowUI__box');
        const obj = typeof self.bsSettings === "undefined" ? self.bsTemp : self.bsSettings;

        box.style.width = `${obj.width}px`;
        box.style.height = `${obj.height}px`;
        box.style.borderRadius = `${obj.borderRadius}px`;
        box.style.backgroundColor = obj.boxColor;
        main.style.backgroundColor = obj.boxBgColor;
    },
    bsSetBoxInputs: function(){
        const self = this;
        const obj = typeof self.bsSettings === "undefined" ? self.bsTemp : self.bsSettings;
        const box = document.querySelector('#boxShadowUI__global #boxSettings');
        const arr = [
            {
                id: 'brxcBsWidth',
                title: 'Width',
                min: '0',
                max: '500',
                step: '1',
                property: 'width',
                value: obj.width,

            },
            {
                id: 'brxcBsHeight',
                title: 'Height',
                min: '0',
                max: '500',
                step: '1',
                property: 'height',
                value: obj.height,

            },
            {
                id: 'brxcBsWidthBorderRadius',
                title: 'Border-Radius',
                min: '0',
                max: '500',
                step: '1',
                property: 'borderRadius',
                value: obj.borderRadius,

            },
        ];
        let content = '';
        content += `<div class="brxc__title">Box</div>`;
        arr.forEach(el => {
            content += `
            <div class="brxc__field">
                <label for="${el.id}" class="brxc__label">${el.title}</label>
                <div class="brxc__range">
                    <input id="${el.id}" type="range" min="${el.min}" max="${el.max}" step="${el.step}" value="${el.value}" class="brxc-input__range" 
                        oninput="
                            ADMINBRXC.bsChangeBoxInput('${el.property}', parseInt(this.value));
                            document.querySelector('#${el.id}Value').value = this.value;
                            ADMINBRXC.bsRenderCssBox();
                        "
                    />
                    <input id="${el.id}Value" type="number" min="${el.min}" max="${el.max}" step="${el.step}" value="${el.value}"
                        oninput="
                            ADMINBRXC.bsChangeBoxInput('${el.property}', parseInt(this.value));
                            document.querySelector('#${el.id}').value = this.value;
                            ADMINBRXC.bsRenderCssBox();
                        "
                    />
                </div>
            </div>`;
        })
        content += `
        <div class="brxc__field">
            <label for="boxColor" class="brxc__label">Box Color</label>
            <div class="brxc__simple-color">
                <div id="boxColor" class="brxc-input__simple-color" data-initial="${obj.boxColor}" data-property="boxColor" style="background-color:${obj.boxColor}"></div>
                <input id="$boxColorValue" type="text" value="${obj.boxColor}"
                    oninput="
                        ADMINBRXC.bsChangeBoxInput('boxColor', this.value);
                        document.querySelector('#boxColor').style.backgroundColor = this.value;
                        ADMINBRXC.bsRenderCssBox();
                    "
                />
            </div>
        </div>
        <div class="brxc__field">
            <label for="boxBgColor" class="brxc__label">Background Color</label>
            <div class="brxc__simple-color">
                <div id="boxBgColor" class="brxc-input__simple-color" data-initial="${obj.boxBgColor}" data-property="boxBgColor" style="background-color:${obj.boxBgColor}"></div>
                <input id="$boxBgColorValue" type="text" value="${obj.boxBgColor}"
                    oninput="
                        ADMINBRXC.bsChangeBoxInput('boxBgColor', this.value);
                        document.querySelector('#boxBgColor').style.backgroundColor = this.value;
                        ADMINBRXC.bsRenderCssBox();
                    "
                />
            </div>
        </div>`;
        box.innerHTML = content;
        const simpleColors = document.querySelectorAll('.brxc-input__simple-color');
        simpleColors.forEach(el => {
            // Color Picker
            let picker = new ColorPicker(el, el.dataset.initialColor);
    
            el.addEventListener('colorChange', (event) => {
                const property = el.dataset.property;
                const obj = typeof self.bsSettings === "undefined" ? self.bsTemp : self.bsSettings;
                const color = event.detail.color.rgb;
                el.nextElementSibling.value = color.replace('rgba', 'rgb');
                obj[property] = color;
                self.bsRenderCssBox();
            })
        })
    },
    bsChangeBoxInput: function(prop, value){
        const self = this;
        const obj = typeof self.bsSettings === "undefined" ? self.bsTemp : self.bsSettings;
        obj[prop] = value;
        self.bsRenderCssBox();
    },
    bsSetTempInputs: function(){
        const self = this;
        const box = document.querySelector('#boxShadowUI__global #boxShadowSettings');
        const child = document.querySelector('#boxShadowUI__global #boxShadowUI__child');
        child.innerHTML = '';
        let content = '';
        const arr = [
            {
                id: 'brxcBsLayers',
                title: 'Number of Layers',
                min: '1',
                max: '10',
                step: '1',
                value: '5',
                property: 'layerAmount',

            },
            {
                id: 'brxcBsVerticalDistance',
                title: 'Vertical Distance',
                min: '-500',
                max: '500',
                step: '1',
                value: '32',
                property: 'verticalDistance',

            },
            {
                id: 'brxcBsHorizontalDistance',
                title: 'Horizontal Distance',
                min: '-500',
                max: '500',
                step: '1',
                value: '0',
                property: 'horizontalDistance',

            },
            {
                id: 'brxcBsOpacity',
                title: 'Opacity',
                min: '0.01',
                max: '1',
                step: '0.01',
                value: '0.08',
                property: 'opacity',

            },
            {
                id: 'brxcBsBlur',
                title: 'Blur',
                min: '0',
                max: '100',
                step: '1',
                value: '24',
                property: 'blur',

            },
            {
                id: 'brxcBsSpread',
                title: 'Spread',
                min: '-100',
                max: '100',
                step: '1',
                value: '0',
                property: 'spread',

            },
        ];
        content += `<div class="brxc__title">Box-shadow</div>`;
        arr.forEach(el => {
            content += `
            <div class="brxc__field">
                <label for="${el.id}" class="brxc__label">${el.title}</label>
                <div class="brxc__range">
                    <input id="${el.id}" type="range" min="${el.min}" max="${el.max}" step="${el.step}" value="${el.value}" class="brxc-input__range"
                        oninput="
                            ADMINBRXC.bsTemp['${el.property}'] = this.value;
                            document.querySelector('#${el.id}Value').value = this.value;
                            ADMINBRXC.bsRenderCssShadows();ADMINBRXC.bsSaveSettings();;
                        "
                    />
                    <input id="${el.id}Value" type="number" min="${el.min}" max="${el.max}" step="${el.step}" value="${el.value}"
                        oninput="
                            ADMINBRXC.bsTemp['${el.property}'] = this.value;
                            document.querySelector('#${el.id}').value = this.value;
                            ADMINBRXC.bsRenderCssShadows();ADMINBRXC.bsSaveSettings();;
                        "
                    />
                </div>
            </div>`;
        })
        content += `<div class="brxc__field">
            <label for="shadowRgb" class="brxc__label">Shadow Color</label>
            <div class="brxc__simple-color">
                <div id="shadowRgb" class="brxc-input__simple-color" data-initial="rgb(3,7,18)" data-property="shadowRgb" style="background-color:rgb(3,7,18)"></div>
                <input id="$shadowRgbValue" type="text" value="rgb(3,7,18)"
                    oninput="
                        ADMINBRXC.bsTemp['shadowRgb'] = ADMINBRXC.helpers.rgbStringToArray(this.value);
                        document.querySelector('#shadowRgb').style.backgroundColor = this.value;
                        ADMINBRXC.bsRenderCssBox();
                    "
                />
            </div>
        </div>
        <div class="brxc__field">
            <label for="shadowInset" class="brxc__label">Inset</label>
            <div id="shadowInset" class="brxc__toggle-icon" onClick="ADMINBRXC.bsTemp.inset = '${self.bsTemp.inset === '1' ? '0' : '1'}';ADMINBRXC.bsSetTempInputs();ADMINBRXC.bsRenderCssShadows();ADMINBRXC.bsSaveSettings();;"><i class="fas fa-toggle-${self.bsTemp.inset === '1' ? 'on' : 'off'}"></i></div>
        </div>`;
        content += `<a class="brxc-overlay__action-btn primary m-top-24" style="width:100%;justify-content:center;" onClick="ADMINBRXC.bsGenerateLayers();">Generate Layers</button>`;
        box.innerHTML = content;
        const simpleColors = document.querySelectorAll('.brxc-input__simple-color');
        simpleColors.forEach(el => {
            // Color Picker
            let picker = new ColorPicker(el, el.dataset.initialColor);
    
            el.addEventListener('colorChange', (event) => {
                const property = el.dataset.property;
                const color = event.detail.color.rgb;
                el.nextElementSibling.value = color.replace('rgba', 'rgb');
                self.bsTemp[property] = self.helpers.rgbStringToArray(color);
                self.bsRenderCssShadows();
                self.bsSaveSettings();

            })
        })
    },
    bsSetInputs: function(){
        const self = this;
        const box = document.querySelector('#boxShadowUI__global #boxShadowSettings');
        let content = '<div class="brxc__title">Layers</div><div class="brxc-layer-btn-wrapper">';
        self.bsSettings.layers.forEach((layer,index) => {
            content += `<div class="brxc-layer-btn${index === self.bsStates.activeLayer ? ' active': ''}" data-order="${index}" onClick="ADMINBRXC.bsSetActiveLayer(this.dataset.order)"><div class="icon"><i class="fas fa-layer-group"></i></div></<span>Layer ${index + 1}</span></div>`
        })
        content += `<div class="brxc-layer-btn" onClick="ADMINBRXC.bsAddNewLayer();"><div class="icon"><i class="fas fa-plus"></i></div></<span>Add</span></div>`;
        content += '</div>'
        box.innerHTML = content;
    },
    bsSetActiveLayer: function(order){
        const self = this;
        self.bsStates.activeLayer = parseInt(order);
        self.bsSetBoxInputs();
        self.bsSetInputs();
        self.bsLoadLayer();
    },
    bsLoadLayer: function(){
        const self = this;
        const box = document.querySelector('#boxShadowUI__child');
        const layer = self.bsSettings.layers[self.bsStates.activeLayer];
        const layerColor = `rgb(${Array.isArray(layer.rgb) ? layer.rgb.join(',') : layer.rgb})`;
        const arr = [
            {
                id: 'brxcBsVerticalDistanceChild',
                title: 'Vertical Distance',
                min: '-500',
                max: '500',
                step: '1',
                property: 'y',

            },
            {
                id: 'brxcBsHorizontalDistanceChild',
                title: 'Horizontal Distance',
                min: '-500',
                max: '500',
                step: '1',
                property: 'x',

            },
            {
                id: 'brxcBsOpacityChild',
                title: 'Opacity',
                min: '0.01',
                max: '1',
                step: '0.01',
                property: 'alpha',

            },
            {
                id: 'brxcBsBlurChild',
                title: 'Blur',
                min: '0',
                max: '100',
                step: '1',
                property: 'blur',

            },
            {
                id: 'brxcBsSpreadChild',
                title: 'Spread',
                min: '-100',
                max: '100',
                step: '1',
                property: 'spread',

            },
        ];
        let content = `
        <div class="brxc__title-wrapper">
            <div class="brxc__title">Layer ${self.bsStates.activeLayer + 1}</div>
            <div class="trash-icon" data-balloon="Delete Layer" data-balloon-pos="right" onclick="ADMINBRXC.setDeleteVariable(this,'ADMINBRXC.bsDeleteLayer()');">
                <span class="bricks-svg-wrapper">
                    <i class="ti-trash"></i>
                </span>
            </div>
        </div>`;
        arr.forEach(el => {
            content += `
            <div class="brxc__field">
                <label for="${el.id}" class="brxc__label">${el.title}</label>
                <div class="brxc__range">
                    <input id="${el.id}" type="range" min="${el.min}" max="${el.max}" step="${el.step}" value="${layer[el.property]}" class="brxc-input__range" 
                        oninput="
                            ADMINBRXC.bsSettings.layers[${self.bsStates.activeLayer}]['${el.property}'] = this.value;
                            document.querySelector('#${el.id}Value').value = this.value;
                            ADMINBRXC.bsRenderCssShadows();ADMINBRXC.bsSaveSettings();;
                        "
                    />
                    <input id="${el.id}Value" type="number" min="${el.min}" max="${el.max}" step="${el.step}" value="${layer[el.property]}"
                        oninput="
                            ADMINBRXC.bsSettings.layers[${self.bsStates.activeLayer}]['${el.property}'] = this.value;
                            document.querySelector('#${el.id}').value = this.value;
                            ADMINBRXC.bsRenderCssShadows();ADMINBRXC.bsSaveSettings();;
                        "
                    />
                </div>
            </div>`;
        })
        content += `<div class="brxc__field">
            <label for="shadowRgbChild" class="brxc__label">Shadow Color</label>
            <div class="brxc__simple-color">
                <div id="shadowRgbChild" class="brxc-input__simple-color" data-initial="${layerColor}" data-property="rgb" style="background-color:${layerColor}"></div>
                <input id="$shadowRgbChildValue" type="text" value="${layerColor}"
                    oninput="
                        ADMINBRXC.bsSettings.layers[ADMINBRXC.bsStates.activeLayer][this.previousElementSibling.dataset.property] = ADMINBRXC.helpers.rgbStringToArray(this.value);
                        document.querySelector('#shadowRgbChild').style.backgroundColor = this.value;
                        ADMINBRXC.bsRenderCssShadows();
                    "
                />
            </div>
        </div>
        <div class="brxc__field">
            <label for="shadowInsetChild" class="brxc__label">Inset</label>
            <div id="shadowInsetChild" class="brxc__toggle-icon" onClick="ADMINBRXC.bsSettings.layers[${self.bsStates.activeLayer}].inset = '${layer.inset === '1' ? '0' : '1'}';ADMINBRXC.bsLoadLayer();ADMINBRXC.bsRenderCssShadows();ADMINBRXC.bsSaveSettings();;"><i class="fas fa-toggle-${layer.inset === '1' ? 'on' : 'off'}"></i></div>
        </div>`;
        box.innerHTML = content;
        const simpleColors = document.querySelectorAll('.brxc-input__simple-color');
        simpleColors.forEach(el => {
            // Color Picker
            let picker = new ColorPicker(el, el.dataset.initialColor);
    
            el.addEventListener('colorChange', (event) => {
                const property = el.dataset.property;
                const color = event.detail.color.rgb;
                el.nextElementSibling.value = color.replace('rgba', 'rgb');
                self.bsSettings.layers[self.bsStates.activeLayer][property] = self.helpers.rgbStringToArray(color);
                self.bsRenderCssShadows();
                self.bsSaveSettings();

            })
        })

    },
    bsLoadDefault: function(){
        const self = this;
        self.bsRenderCssBox();
        self.bsRenderCssShadows();
        self.bsSetBoxInputs();
        self.bsSetTempInputs();
    },
    bsGenerateLayers: function(presetsArr = false){
        const self = this;
        const layers = self.bsRenderBoxShadows(self.bsTemp);
        self.bsSettings = {
            boxColor: self.bsTemp.boxColor,
            boxBgColor: self.bsTemp.boxBgColor,
            width: self.bsTemp.width,
            height: self.bsTemp.height,
            borderRadius: self.bsTemp.borderRadius,
            layers: layers,
        };
        if(Array.isArray(presetsArr)) self.bsSettings.layers = presetsArr;
        self.bsSaveSettings();
        self.bsStates.activeLayer = 0;
        self.bsSetActiveLayer(0);

        self.bsInit();
    },
    //
    bsLoad: function(){
        const self = this;
        self.bsRenderCssBox();
        self.bsRenderCssShadows();
        self.bsSetBoxInputs();
        self.bsSetInputs();
    },
    bsSaveSettings: function(){
        const self = this;
        const target = self.helpers.createTargetWithPseudo(`${self.bsStates.selector.replaceAll('_','')}Generator`);
        const settings = self.helpers.areElementsSelected() ? self.vueState.selectedElementSettings : self.builderStates.activeObject?.settings;
        settings[target] = self.bsSettings;
    },
    bsRemoveSettings: function(){
        const self = this;
        const target = self.helpers.createTargetWithPseudo(`${self.bsStates.selector.replaceAll('_','')}Generator`);
        const settings = self.helpers.areElementsSelected() ? self.vueState.selectedElementSettings : self.builderStates.activeObject?.settings;
        delete settings[target];
        self.vueState.rerenderControls = Date.now();
        self.vueGlobalProp.$_showMessage('Box-shadow settings correctly removed!');

    },
    bsApplyPresets(targetNode){
        const self = this;
        const boxShadow = targetNode.dataset.value;
        const target = self.helpers.createTargetWithPseudo(self.bsStates.selector);
        const settings = self.helpers.areElementsSelected() ? self.vueState.selectedElementSettings : self.builderStates.activeObject?.settings;
        settings[target] = {color:{raw: boxShadow}};
        
        self.vueState.rerenderControls = Date.now();
        self.vueGlobalProp.$_showMessage('Box-shadow correctly applied!');

    },
    bsApply: function(){
        const self = this;
        if(typeof self.bsSettings === "undefined") return self.vueGlobalProp.$_showMessage('Abort: create the layers first.');
        const target = self.helpers.createTargetWithPseudo(self.bsStates.selector);
        const settings = self.helpers.areElementsSelected() ? self.vueState.selectedElementSettings : self.builderStates.activeObject?.settings;

        const cssShadows = self.bsSettings.layers.map(
            ({ x, y, blur, spread, rgb, alpha, inset }) =>
            `${inset === '1' ? 'inset ' : ''}${x}px ${y}px ${blur}px ${spread}px rgba(${Array.isArray(rgb) ? rgb.join(',') : rgb}, ${alpha})`
        );
        const styles = cssShadows.join(",\n  ");
        settings[target] = {color:{raw: styles}};

        self.vueState.rerenderControls = Date.now();
        self.vueGlobalProp.$_showMessage('Box-shadow correctly applied!');
    },
    bsLoadBoxValues: function(){
         const self = this;
         const elementObj = self.builderStates.activeElement;
         const node = FRAMEBRXC.vueGlobalProp.$_getElementNode(elementObj);
         function getStyle(el, prop){
            return window.getComputedStyle(el).getPropertyValue(prop);
         }

         function getInheritedBackgroundColor(el) {
            var defaultStyle = getDefaultBackground()
            var backgroundColor = window.getComputedStyle(el).backgroundColor
            if (backgroundColor != defaultStyle) return backgroundColor
            if (!el.parentElement) return defaultStyle
            return getInheritedBackgroundColor(el.parentElement)
        }
        function getDefaultBackground() {
            var div = document.createElement("div")
            document.head.appendChild(div)
            var bg = window.getComputedStyle(div).backgroundColor
            document.head.removeChild(div)
            return bg
        }
        const width = node.getBoundingClientRect().width > 0 ? node.getBoundingClientRect().width : 400;
        const height = node.getBoundingClientRect().height > 0 ? node.getBoundingClientRect().height : 400;
        const ratio = width > height ? height / width : width / height;
        if(width > height){
            self.bsTemp.width = 400;
            self.bsTemp.height = Math.floor(self.bsTemp.width * ratio)
        } else {
            self.bsTemp.height = 400;
            self.bsTemp.width = Math.floor(self.bsTemp.height * ratio);
        }
        self.bsTemp.borderRadius = parseInt(getStyle(node, 'border-radius').replace('px',''));
        self.bsTemp.boxColor = getStyle(node, 'background-color');
        self.bsTemp.boxBgColor = getInheritedBackgroundColor(node.parentElement);
    },
    bsAddNewLayer: function(){
        const self = this;
        const length = self.bsSettings.layers.length;
        self.bsSettings.layers.push(JSON.parse(JSON.stringify(self.bsSettings.layers[length - 1])));
        self.bsStates.activeLayer = length;
        self.bsRenderCssShadows();
        self.bsSaveSettings();
        self.bsLoadLayer();
        self.bsSetInputs();
    },
    bsSetDeleteLayer: function(){
        const self = this;
        self.bsSettings.layers.splice(self.bsStates.activeLayer, 1);
        self.bsStates.activeLayer = self.bsSettings.layers.length - 1;
        self.bsRenderCssShadows();
        self.bsSaveSettings();
        self.bsLoadLayer();
        self.bsSetInputs();
    },
    bsDeleteLayer: function(){
        const self = this;
        self.bsSettings.layers.splice(self.bsStates.activeLayer, 1);
        self.bsStates.activeLayer = self.bsSettings.layers.length - 1;
        self.bsRenderCssShadows();
        self.bsSaveSettings();
        self.bsLoadLayer();
        self.bsSetInputs();
    },
    bsImportLayersFromPresets: function(target){
        const self = this;
        self.bsGenerateLayers(JSON.parse(target.dataset.obj));
        document.querySelector('#box-shadow-ui-generator').click();
    },
    bsInit: function(selector = false){
        const self = this;
        if(!self.builderStates.isElementActive) return;

        if(selector) self.bsStates.selector = selector
        // Get the target Key
        const target = self.helpers.createTargetWithPseudo(`${self.bsStates.selector.replaceAll('_', '')}Generator`);
        const settings = self.builderStates.activeObject?.settings;

        // Conditional Load
        if(typeof settings[target] === "undefined"){
            self.bsSettings = undefined;
            self.bsLoadBoxValues();
            self.bsLoadDefault();
        } else {
            self.bsStates.activeLayer = 0;
            self.bsSettings = settings[target];
            self.bsLoad();
        }
    },
    stateInteractions: null,
    stateConditions: null,
    copyInteractions: function(key){
        const self = this;
        let settings;
        const finalObj = self.builderStates.activeObject?.settings;
        const elementObj = self.builderStates.activeElement?.settings;
        if(self.builderStates.isClassActive && key === "_interactions") {
            settings = finalObj[key]
        } else {
            settings = elementObj[key];
        } 
        if(key === "_interactions"){
            self.stateInteractions = JSON.stringify(settings);
        } else {
            self.stateConditions = JSON.stringify(settings);
        }
        const message = key === "_interactions" ? "Interactions" : "Conditions";
        self.vueGlobalProp.$_showMessage(`${message} successfully copied!`);
        self.vueState.rerenderControls = Date.now();
    },
    pasteInteractions: function(key){
        const self = this;
        const arr = key === "_interactions" ? JSON.parse(self.stateInteractions) : JSON.parse(self.stateConditions);
        const elementObj = key === "_interactions" ? self.builderStates.activeObject : self.builderStates.activeElement;

        if(!elementObj.settings.hasOwnProperty(key)) elementObj.settings[key] = [];
        arr.forEach(obj => {
            if(key === "_conditions"){
                obj.forEach(newObj => {
                    newObj.id = self.vueGlobalProp.$_generateId();
                })
            } else if(key === "_interactions"){
                obj.id = self.vueGlobalProp.$_generateId();
            }
            elementObj.settings[key].push(obj);
        })
        

        const message = key === "_interactions" ? "Interactions" : "Conditions";
        self.vueState.rerenderControls = Date.now();
        self.vueGlobalProp.$_showMessage(`${message} successfully pasted!`);
    },
    setCopyConditions: function(){
        const self = this;
        if(!self.builderStates.isElementActive || self.vueState.showConditions !== true ) return;
        
        let copyIcon = document.querySelector('.brxc-copy-conditions');
        if (copyIcon) copyIcon.remove();
        let pasteIcon = document.querySelector('.brxc-paste-conditions');
        if (pasteIcon) pasteIcon.remove();

        const actions = document.querySelector('#bricks-panel div[data-control="conditions"] .title-wrapper .actions');
        if(!actions) return;

        const settings = self.builderStates.activeElement?.settings;
    

        // Copy
        const copyCls = settings && settings.hasOwnProperty('_conditions') ? 'brxc-copy-conditions' : 'brxc-copy-conditions disabled'
        copyIcon = actions.querySelector('.brxc-copy-conditions');
        if (!copyIcon) {
            self.addIconToFields(
                'button',
                copyCls,
                false,
                'Copy Conditions',
                'top-right',
                'ADMINBRXC.copyInteractions("_conditions");',
                false,
                '<span class="bricks-svg-wrapper"><i class="fas fa-clipboard"></i></span>',
                actions,
                'child'
            );
        }

        // Paste
        const pasteCls = self.stateConditions !== null ? 'brxc-paste-conditions' : 'brxc-paste-conditions disabled'
        pasteIcon = actions.querySelector('.brxc-paste-conditions');
        if (!pasteIcon) {
            self.addIconToFields(
                'button',
                pasteCls,
                false,
                'Import Conditions',
                'top-right',
                'ADMINBRXC.pasteInteractions("_conditions");',
                false,
                '<span class="bricks-svg-wrapper"><i class="fas fa-file-import"></i></span>',
                actions,
                'child'
            );
        }
    },
    setCopyInteractions: function(){
        const self = this;
        
        if(!self.builderStates.isElementActive || self.vueState.showInteractions !== true ) return;
        
        let copyIcon = document.querySelector('.brxc-copy-interactions');
        if (copyIcon) copyIcon.remove();
        let pasteIcon = document.querySelector('.brxc-paste-interactions');
        if (pasteIcon) pasteIcon.remove();

        
        const actions = document.querySelector('#bricks-panel div[data-control="interactions"] .title-wrapper .actions');
        if(!actions) return;

        const settings = self.builderStates.activeObject?.settings;

        // Copy

        const copyCls = settings && settings.hasOwnProperty('_interactions') ? 'brxc-copy-interactions' : 'brxc-copy-interactions disabled';
        copyIcon = actions.querySelector('.brxc-copy-interactions');
        if (!copyIcon) {
            self.addIconToFields(
                'button',
                copyCls,
                false,
                'Copy Interactions',
                'top-right',
                'ADMINBRXC.copyInteractions("_interactions");',
                false,
                '<span class="bricks-svg-wrapper"><i class="fas fa-clipboard"></i></span>',
                actions,
                'child'
            );
        }

        // Paste
        const pasteCls = self.stateInteractions !== null ? 'brxc-paste-interactions' : 'brxc-paste-interactions disabled'
        pasteIcon = actions.querySelector('.brxc-paste-interactions');
        if (!pasteIcon) {
            self.addIconToFields(
                'button',
                pasteCls,
                false,
                'Import Interactions',
                'top-right',
                'ADMINBRXC.pasteInteractions("_interactions");',
                false,
                '<span class="bricks-svg-wrapper"><i class="fas fa-file-import"></i></span>',
                actions,
                'child'
            );
        }
    },
    basicTextStates:{
        tag: 'span',
        options: ['span','strong','a','em','mark','abbr','p','custom'],
        class: "false",
        classTxt: "",
        style: "false",
        styleTxt: "",
        url: "false",
        urlTxt: "",
    },
    setbasicTextOptions: function(){
        const self = this;
        if(!self.builderStates.isElementActive || self.vueState.activePanelTab !== "content" || self.vueState.showInteractions === true || self.vueState.showConditions === true) return;

        const elementObj = self.builderStates.activeElement;
        if(!['text-basic','heading'].includes(elementObj.name)) return
        
        Promise.resolve().then(() => {
            const textarea = document.querySelector('#bricks-panel .controls [data-control=textarea]');
            if(!textarea) return;

            if(textarea.parentElement.querySelector('#brxc-text-basic-options')) return;
            const wrapper  = document.createElement("DIV");
            wrapper.id = "brxc-text-basic-options";
            textarea.parentElement.insertBefore(wrapper, textarea);
            self.basicTextOptions(wrapper);

        })
    },
    basicTextOptions: function(wrapper){
        const self = this;
        let content = "";
        if(!self.basicTextStates.options.includes(self.basicTextStates.tag)) self.basicTextStates.options.push(self.basicTextStates.tag);
        content += `
        <div class="brxc-select-new max-width rounded bg2 hidden" value name="html-tag-wrapper" id="brxc-html-tag-wrapper">
            <div class="brxc-select-new__wrapper">
                ${self.basicTextStates.options.map(option => {
                    return `<div data-value="${option}"${self.basicTextStates.tag === option ? ' class="active"' : ''}><span>${option}</span></div>`;
                }).join('')}
            </div>
        </div>`
        content += `</div></div>`;
        if(self.basicTextStates.tag === "custom"){
            content += `<input type="text" onblur="ADMINBRXC.basicTextStates.tag = this.value">`
        }
        // Url
        if(self.basicTextStates.tag === "a"){
            content += `<div class="${self.basicTextStates.url === "true" ? 'active' : ''}" data-balloon="${self.basicTextStates.url === "true" ? 'Remove' : 'Add'} URL tag" data-balloon-pos="top" onclick='ADMINBRXC.basicTextStates.url = "${self.basicTextStates.url === "true" ? "false" : "true"}";ADMINBRXC.basicTextOptions(this.parentElement)'>
                <span class="bricks-svg-wrapper">
                    <i class="fas fa-link"></i>
                </span>
            </div>`
        }

        content += `<div class="${self.basicTextStates.class === "true" ? 'active' : ''}" data-balloon="${self.basicTextStates.class === "true" ? 'Remove' : 'Add'} Class tag" data-balloon-pos="top" onclick='ADMINBRXC.basicTextStates.class = "${self.basicTextStates.class === "true" ? "false" : "true"}";ADMINBRXC.basicTextOptions(this.parentElement)'>
            <span class="bricks-svg-wrapper">
                <i class="fab fa-css3-alt"></i>
            </span>
        </div>
        <div class="${self.basicTextStates.style === "true" ? 'active' : ''}" data-balloon="${self.basicTextStates.style === "true" ? 'Remove' : 'Add'} Style tag" data-balloon-pos="top" onclick='ADMINBRXC.basicTextStates.style = "${self.basicTextStates.style === "true" ? "false" : "true"}";ADMINBRXC.basicTextOptions(this.parentElement)'>
            <span class="bricks-svg-wrapper">
                <i class="fas fa-broom"></i>
            </span>
        </div>
        <a class="" onclick="ADMINBRXC.unwrapSelectedContent(this.parentElement.parentElement.querySelector('textarea'))">Unwrap</a>
        <a class="" onclick="ADMINBRXC.wrapSelectedContent(this.parentElement.parentElement.querySelector('textarea'))">Wrap</a>
        `;
        if(Object.values(self.basicTextStates).some(value => value === "true")){
            content += `<div id="brxc-text-basic-options-extra">`
            if(self.basicTextStates.tag === "a" && self.basicTextStates.url === "true"){
                content += `<div class="brxc-field-wrapper">
                    <div class="icon-wrapper">
                        <span class="bricks-svg-wrapper">
                            <i class="fas fa-link"></i>
                        </span>
                    </div>
                    <input type="text" oninput="ADMINBRXC.basicTextStates.urlTxt = this.value" value="${self.basicTextStates.urlTxt}">
                </div>`
            }
            if(self.basicTextStates.class === "true"){
                content += `<div class="brxc-field-wrapper">
                    <div class="icon-wrapper">
                        <span class="bricks-svg-wrapper">
                            <i class="fab fa-css3-alt"></i>
                        </span>
                    </div>
                    <input type="text" id="brxcBasicTextClass" oninput="ADMINBRXC.basicTextStates.classTxt = this.value" value="${self.basicTextStates.classTxt}">
                </div>`
            }
            if(self.basicTextStates.style === "true"){
                content += `<div class="brxc-field-wrapper">
                    <div class="icon-wrapper">
                        <span class="bricks-svg-wrapper">
                            <i class="fas fa-broom"></i>
                        </span>
                    </div>
                    <input type="text" oninput="ADMINBRXC.basicTextStates.styleTxt = this.value" value="${self.basicTextStates.styleTxt}">
                </div>`
            }


            content += `</div>`;
        }
        wrapper.innerHTML = content;

        const select = wrapper.querySelector('.brxc-select-new');
        self.helpers.selectControl(select, (target) => {
            self.basicTextStates.tag = target.dataset.value;
            self.basicTextOptions(wrapper);
        })


        const classInput = wrapper.querySelector('#brxcBasicTextClass');
        if(classInput) {
            classInput.addEventListener('input', () => {
                self.autocomplete(classInput, self.vueState.globalClasses.map(el => el.name), false);
            })
        }

    },
    wrapSelectedContent: function(textarea){
        const self = this;
        const start = textarea.selectionStart;
        const end = textarea.selectionEnd;
        const selectedText = textarea.value.substring(start, end).trim();
        if(selectedText === '') return self.vueGlobalProp.$_showMessage('Abort: select the content to wrap first.')

        const beforeText = textarea.value.substring(0, start);
        const afterText = textarea.value.substring(end);
        const newText = `${beforeText}<${self.basicTextStates.tag}${self.basicTextStates.tag === "abbr" ? ` title=""` : ''}${self.basicTextStates.tag === "a" && self.basicTextStates.url === "true" ? ` href="${self.basicTextStates.urlTxt}" target="_blank"` : ''}${self.basicTextStates.class === "true" ? ` class="${self.basicTextStates.classTxt}"` : ''}${self.basicTextStates.style === "true" ? ` style="${self.basicTextStates.styleTxt}"` : ''}>${selectedText}</${self.basicTextStates.tag}>${afterText}`
        textarea.value = newText;
        const evt = new Event('input');
        textarea.dispatchEvent(evt);
    },
    unwrapSelectedContent: function(textarea){
        const self = this;
        const start = textarea.selectionStart;
        const end = textarea.selectionEnd;
        const selectedText = textarea.value.substring(start, end).trim();
        if(selectedText === '') return self.vueGlobalProp.$_showMessage('Abort: select the content to wrap first.')

        const beforeText = textarea.value.substring(0, start);
        const afterText = textarea.value.substring(end);
        const newText = `${beforeText}${selectedText.replaceAll(/<[^>]*>/g, '')}${afterText}`
        textarea.value = newText;
        const evt = new Event('input');
        textarea.dispatchEvent(evt);
    },
    queryManagerStates: {
        active: null,
        activeCategory: 'All',
        search: '',
    },
    queryListState: {
        show: false,
        search: '',
    },
    setQueryList: function(){
        const self = this;
        if(!self.builderStates.isElementActive) return;

        const x = document.querySelector('#bricks-builder-iframe').contentWindow;
        function openPopup() {
            window.addEventListener('click', windowClickListener);
            x.document.addEventListener('click', windowClickListener);
        }
        
        function closePopup() {
            self.queryListState.show = false;
            window.removeEventListener('click', windowClickListener);
            x.document.removeEventListener('click', windowClickListener);
            self.setQueryList();

        }
        
        function windowClickListener(event) {
            const popup = document.querySelector('.brxc-global-query-loops');
            if (popup && !popup.contains(event.target)) {
                closePopup();
            }
        }

        setTimeout(()=> {
            const control = document.querySelector('[data-controlkey="query"] [data-control="query"]');
            if(!control) return;

            const icon = control.querySelector('.brxc-global-query-loops');
            if (icon) icon.remove();

            const elementObj = self.builderStates.activeElement;

            function isActive(){
                if(elementObj.settings.hasOwnProperty('query') 
                    && elementObj.settings.query.hasOwnProperty('objectType')
                    && typeof Array.from(self.globalSettings.generalCats.queryManager).find(el => el && el.id === elementObj.settings.query.objectType) !== "undefined") return true;
                return false;
            }

            let content = self.queryListContent();
            const classes = isActive() ? 'brxc-global-query-loops active' : 'brxc-global-query-loops';

            self.addIconToFields(
                'div',
                classes,
                false,
                'Global Query Loops',
                'top-right',
                '',
                false,
                content,
                control,
                'child'
            );

            openPopup();
                

        }, 5);
    },
    queryListContent: function(){
        const self = this;
        let content = '<div class="icon" onclick="ADMINBRXC.queryListState.show = true;ADMINBRXC.setQueryList();"><span class="bricks-svg-wrapper"><i class="fas fa-globe"></i></span></div>';
            if(self.queryListState.show === true){
                content += `<div class="bricks-control-popup bottom">
                                <div class="input-wrapper">
                                    <input type="text" autocomplete="off" spellcheck="false" placeholder="Search for a query loop ..." oninput="ADMINBRXC.queryListState.search = this.value;ADMINBRXC.updateQueryListLi();">
                                 </div>
                                 <div class="css-classes">
                                    <h6 class="title"><span>Global Query Loops</span></h6>
                                    <ul id="brxcQueryListLiCanvas">`;
                content += self.queryListLi();
                content +=         `</ul>
                                </div>
                            </div>`;
            }
        return content;
    },
    queryListLi: function(){
        const self = this;
        const elementObj = self.builderStates.activeElement;
        let content = '';
        function isActive(id){
            if(elementObj.settings.hasOwnProperty('query') 
                && elementObj.settings.query.hasOwnProperty('objectType')
                && elementObj.settings.query.objectType === id) return true;
            return false;
        }
        self.globalSettings.generalCats.queryManager.forEach(el => {
            content += `<li data-id="${el.id}" ${isActive(el.id) ? 'class="active" ': ''}onmousedown="ADMINBRXC.selectQueryList(this.dataset.id)"><span class="name">${el.title}</span></li>`
        })

        return content;
    },
    updateQueryListLi: function(){
        const self = this;
        const items = document.querySelectorAll('#brxcQueryListLiCanvas li');
        items.forEach(el => {
            self.queryListState.search === "" || el.textContent.includes(self.queryListState.search) ? el.removeAttribute('style') : el.style.display = "none";
        })
    },
    selectQueryList: function(id){
        const self = this;
        const elementObj = self.builderStates.activeElement;
        self.queryListState.show = false;
        elementObj.settings['query'] = {objectType: id};
        self.vueState.rerenderControls = Date.now();
    },
    setGenerateGlobalQuery: function(){
        const self = this;
        const popup = document.querySelector('[data-controlkey="query"] [data-control="query"] .bricks-control-popup');
        if(!popup || !self.builderStates.isElementActive) return;

        const elementObj = self.builderStates.activeElement
        if(!elementObj.settings.hasOwnProperty('query')) return removeBtn();

        function removeBtn(){
            const btn = popup.querySelector('.brxc-generate-global-query');
            if (btn) btn.remove();
        }

        Promise.resolve().then(()=> {
            removeBtn()

            if(elementObj.settings.query.hasOwnProperty('objectType')
                && !( elementObj.settings.query.objectType === "post"
                    || elementObj.settings.query.objectType === "term"
                    || elementObj.settings.query.objectType === "user")
            ) return;

            content = `<div class="control control-separator">
                            <div class="control-inner">
                                <label for="infinite_scroll_separator" data-balloon-break="">
                                    <span>Global Query Loop</span>
                                </label>
                                <div data-control="separator" type="separator"></div>
                            </div>
                        </div>
                        <a class="brxc-overlay__action-btn primary" style="width:100%;text-align:center;justify-content:center;margin-top:16px;" onclick="ADMINBRXC.generateGlobalQuery();">Generate Global Query Loop</a>`

            self.addIconToFields(
                'div',
                'brxc-generate-global-query',
                false,
                '',
                '',
                '',
                false,
                content,
                popup,
                'child'
            );
                

        });
    },
    generateGlobalQuery: function(){
        const self = this;
        const elementObj = self.builderStates.activeElement;
        const id = self.vueGlobalProp.$_generateId();
        self.getQueryVar(elementObj.settings, elementObj.id)
        .then(args => {
            // Check if args is populated before pushing the object
            if (args && args.trim() !== '') {
                const title = 'New Query Loop'
                self.globalSettings.generalCats.queryManager.push({
                    id: id,
                    title: title,
                    description: '',
                    category: '',
                    args: self.helpers.convertToPhpArrowFunction(args),
                });
                self.queryManagerStates.active = id;
                bricksData.controlOptions.queryTypes[id] = title;
                elementObj.settings['query'] = {objectType: id};
                self.vueState.rerenderControls = Date.now();
                self.openModal({target: false, id: "#brxcQueryManagerOverlay", callback: () => {
                    self.queryManagerInit();
                }});
            } else {
                // Handle the case where args is not populated
                console.log('Args is not populated. Object not pushed.');
            }

        })
        .catch(error => {
            console.error('Error fetching args:', error);

            // Handle the error if needed
        });
    },
    queryManagerInit: function(){
        const self = this;
        if(self.queryManagerStates.active === null){
            if(self.globalSettings.generalCats.queryManager[0]) self.queryManagerStates.active = self.globalSettings.generalCats.queryManager[0].id;
        }
        self.queryManagerCat();
        self.queryManagerList();
        self.queryManagerPanel();
    },
    queryManagerCat: function(){
        const self = this;
        const listWrapper = document.querySelector('#brxcQueryCatListCanvas');
        if(!listWrapper || !Array.isArray(self.globalSettings.generalCats.queryManagerCats)) return;
        let cats = '<ul>';
        let categoryFound;
        let count;

        function isActive (cat) {
            if(self.helpers.getQueryCategoryIdByName(cat) === self.queryManagerStates.activeCategory) return true;
            return false;
        }

        // All
        count = self.globalSettings.generalCats.queryManager.length;
        cats += `<li class="${self.queryManagerStates.activeCategory === "All" ? 'active' : ''}"${self.queryManagerStates.activeCategory === "All" ? ' data-active="true"' : ''} data-id="All" data-balloon="All" data-balloon-pos="right" onClick="ADMINBRXC.queryManagerFilterCat(event)"><input type="text" value="All" readonly/><span class="count">${count}</span></li>`
        
        // Uncategorized
        count = Array.from(self.globalSettings.generalCats.queryManager).filter(el => el && (!el.category || el.category === "")).length;
        cats += `<li class="${self.queryManagerStates.activeCategory === "Uncategorized" ? 'active' : ''}"${self.queryManagerStates.activeCategory === "Uncategorized" ? ' data-active="true"' : ''} data-id="Uncategorized" data-balloon="Uncategorized" data-balloon-pos="right" onClick="ADMINBRXC.queryManagerFilterCat(event)"><input type="text" value="Uncategorized" readonly/><span class="count">${count}</span></li>`

        // Categories
        const sortedCats = Array.from(self.globalSettings.generalCats.queryManagerCats).filter(el => el && el.name).map(el => el && el.name).sort((a, b) => a.localeCompare(b, undefined, {sensitivity: 'base'}));
        sortedCats.forEach(cat => {
            categoryFound = self.helpers.getQueryCategoryObjByName(cat)
            count = Array.from(self.globalSettings.generalCats.queryManager).filter(el => el && el.hasOwnProperty('category') && categoryFound && categoryFound.id === el.category).length;
            cats += `<li class="${isActive(cat) ? 'active' : ''}"${isActive(cat) ? ' data-active="true"' : ''} data-id="${categoryFound.id}" data-balloon="${cat}" data-balloon-pos="right" ondragenter="this.classList.add('dragged')" ondragleave="this.classList.remove('dragged')" ondrop="event.preventDefault();ADMINBRXC.onDropCatList(this);" ondragover="event.preventDefault();" onClick="ADMINBRXC.queryManagerFilterCat(event)"><input type="text" data-initial="${cat}" value="${cat}"${categoryFound.id !== self.queryManagerStates.activeCategory ? ' readonly' : ''}/>${categoryFound.id === self.queryManagerStates.activeCategory ? `<div class="deleteCat" onClick="event.stopPropagation();ADMINBRXC.deleteQueryCategory('${self.queryManagerStates.activeCategory}')" data-balloon="Delete category" data-balloon-pos="top-right"><span class="bricks-svg-wrapper"><i class="ti-trash"></i></span></div>` : `<span class="count">${count}</span>`}</li>`
            
        })

        cats += '</ul><input type="text" id="addNewQueryCat" placeholder="+ New category" onkeyup="ADMINBRXC.addNewQueryCategory(event);" />';
        
        listWrapper.innerHTML = cats;

        // rename cat
        const input = listWrapper.querySelector('li.active input');
        if(input){
            input.addEventListener('keyup', (event) => {
                if(event.key !== "Enter") return;
                if(event.target.value === event.target.dataset.initial) return self.queryManagerCat();
                if(self.globalSettings.generalCats.queryManagerCats.includes(event.target.value)) return self.vueGlobalProp.$_showMessage(`ABORT: category "${event.target.value}" already exists`);
                const activeObj = self.helpers.getQueryCategoryObjById(self.queryManagerStates.activeCategory)
                activeObj.name = event.target.value;
                self.vueGlobalProp.$_showMessage(`Category correctly renamed to ${event.target.value}`)
                self.queryManagerCat();
                self.queryManagerPanel();
            })
        }
        
    },
    queryManagerFilterCat: function(event){
        const self = this;
        target = (event.target.dataset.id) ? event.target : event.target.parentElement;
        if(target.dataset.active === 'true') return;
        self.queryManagerStates.activeCategory = target.dataset.id;
        self.queryManagerCat();
        self.queryManagerList();
    },
    addNewQueryCategory: function(event){
        const self = this;

        if(event.key !== "Enter") return;

        const values = event.target.value.split(' ');
        if(values.length < 1) return;

        let hasChanges = false;
        let newId;

        values.forEach(name => {
            if(Array.from(self.globalSettings.generalCats.queryManagerCats).map(obj => obj && obj.name).includes(name)) {
                return self.vueGlobalProp.$_showMessage('ABORT: category already exists');
            } else {
                hasChanges = true;
                newId = self.vueGlobalProp.$_generateId();
                self.globalSettings.generalCats.queryManagerCats.push({
                    id: newId,
                    name: name,
                })

            }
        })
        if(hasChanges === true) {
            self.queryManagerStates.activeCategory = newId;
            self.queryManagerCat();
        };  
    },
    deleteQueryCategory: function(id){
        const self = this;
        const obj = self.helpers.getQueryCategoryObjById(id);
        if(!obj) return self.vueGlobalProp.$_showMessage('Abort: error finding the category');
        const catName = obj.name;
        const order = self.globalSettings.generalCats.queryManagerCats.indexOf(obj);
        self.globalSettings.generalCats.queryManagerCats.splice(order, 1);
        const loops = Array.from(self.globalSettings.generalCats.queryManager).filter(el => el && el.category === id);
        if(loops.length > 0){
            loops.forEach(el => {
                el.category = '';
            })
        }
        self.queryManagerStates.activeCategory = "All";
        self.vueGlobalProp.$_showMessage(`Category "${catName}" has been successfully deleted!`);
        self.queryManagerCat();
        self.queryManagerList();
        self.queryManagerPanel();

    },
    queryManagerList: function(){
        const self = this;
        const list = document.querySelector('#queryManagerUI__list');
        let arr = self.globalSettings.generalCats.queryManager;

        // Search
        if(self.queryManagerStates.search !== ''){
            arr = Array.from(arr).filter(el => el && el.title.includes(self.queryManagerStates.search))
        }

        // Uncategorized
        if(self.queryManagerStates.activeCategory === 'Uncategorized') {
            arr = Array.from(arr).filter(el => el && !el.category || el.category === '');
        // Category
        } else if(self.queryManagerStates.activeCategory !== 'All') {
            arr = Array.from(arr).filter(el => el && el.category === self.queryManagerStates.activeCategory);
        }

        // Content
        let content = '';
        arr.forEach(obj => {
            content += `<li class="${self.queryManagerStates.active === obj.id ? ' active' : ''}" data-id="${obj.id}" >
                            <span>${obj.title}</span>
                            <div class="actions">
                                <div class="duplicate" data-id="${obj.id}" data-balloon="Duplicate" data-balloon-pos="bottom-right" onclick="event.stopPropagation();ADMINBRXC.duplicateQueryLoop(this.dataset.id)"><i class="fas fas fa-clone"></i></div>
                                <div class="delete" data-id="${obj.id}" data-balloon="Delete" data-balloon-pos="bottom-right" onclick="event.stopPropagation();ADMINBRXC.setDeleteVariable(this, 'ADMINBRXC.deleteQueryLoop(this.dataset.id);')"><i class="ti-trash"></i></div>
                            </div> 
                        </li>`
        });
        //content += `<div class="brxc-class-manager__footer"><input type="text" id="addNewQueryLoop" placeholder="Add a new Query Loop" onkeyup="ADMINBRXC.addNewQueryLoop(event);"></div>`
        list.innerHTML = content;
        const li = list.querySelectorAll('li');
        if(li.length > 0){
            li.forEach(el => {
                el.addEventListener('click', () => {
                    self.queryManagerStates.active = el.dataset.id;
                    self.queryManagerInit();
                })
            })
        }
    },
    queryManagerPanel: function(){
        const self = this;
        const panel = document.querySelector('#queryManagerUI__panel');

        const activeObj = self.globalSettings.generalCats.queryManager.find(el => el.id ===self.queryManagerStates.active);
        if (!activeObj) return;
        let content = '';
        content += `<div class="brxc-query-manager__title-wrapper">
                        <div>
                            <label for="brxcQueryTitle" class="brxc-input__label has-tooltip"><span>Name</span><div data-balloon="To rename the current Query, just type the new name inside this input" data-balloon-pos="bottom-left" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>
                            <input type="text" id="brxcQueryTitle" placeholder="" value="${activeObj.title}" />
                        </div>
                        <div>
                            <label for="brxcQueryCategory" class="brxc-input__label has-tooltip"><span>Category</span><div data-balloon="To assign the query to a category, just type the new category name inside the input and press ENTER" data-balloon-pos="bottom-left" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>
                            <input type="text" id="brxcQueryCategory" placeholder="" value="${self.helpers.getQueryCategoryNameById(activeObj.category) ? self.helpers.getQueryCategoryNameById(activeObj.category) : ''}" />
                        </div>
                    </div>`;
        content += `<div>
                        <label class="brxc-input__label has-tooltip">
                            <span>Description</span>
                            <div data-balloon="Add here any text that will help you to quickly describe what this Query does" data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div>
                        </label>
                        <textarea class="description">${activeObj.description}</textarea>
                    </div>`;
        content += `<div class="codemirror-wrapper">
                        <label class="brxc-input__label has-tooltip">
                            <span>Query vars</span>
                            <div data-balloon="Add here the query vars of the Query (in a correct Array). " data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div>
                        </label>
                        <textarea class="codemirror">${activeObj.args}</textarea>
                    </div>`;
        panel.innerHTML = content;

        const title = panel.querySelector('#brxcQueryTitle');
        if (title){
            title.addEventListener('input', () => {
                activeObj.title = title.value;
                bricksData.controlOptions.queryTypes[activeObj.id] = title.value;
                self.queryManagerList();
            })
        }
        const category = panel.querySelector('#brxcQueryCategory');

        if (category){
            category.addEventListener('keydown', (e) => {
                self.autocomplete(category, self.globalSettings.generalCats.queryManagerCats.map(el => el && el.name), false);
                if(e.key !== "Enter") return;
                const maybeCat = Array.from(self.globalSettings.generalCats.queryManagerCats).find(el => el && el.name === category.value);
                if(maybeCat){
                    activeObj.category = maybeCat.id;
                    self.queryManagerStates.activeCategory = maybeCat.id;
                } else {
                    const newId = self.vueGlobalProp.$_generateId();
                    self.globalSettings.generalCats.queryManagerCats.push({
                        id: newId,
                        name: category.value,
                    })
                    activeObj.category = newId;
                    self.queryManagerStates.activeCategory = newId;
                    self.vueGlobalProp.$_showMessage(`New Category "${category.value}" has been created!`)
                }

                self.queryManagerCat();
                self.queryManagerList();
            })
        }
        const textarea = panel.querySelector('textarea.codemirror');
        if (textarea){
            const options = self.codeMirrorOptions(textarea);
            options.mode = "javascript";
            options.styleActiveLine = true;
            options.autoCloseBrackets = true;
            options.matchBrackets = true;
            options.selfContain = true;
            options.autofocus = true;
            options.search = { bottom: false };
            const MyCM = CodeMirror.fromTextArea(textarea, options);
            MyCM.on("change", function (cm) {
                activeObj.args = cm.getValue();
            });
        }
        const description = panel.querySelector('textarea.description');
        if (description){
            description.addEventListener('change', () => {
                activeObj.description = description.value;
            })
        }
    },
    resetQueryFilter: function(btn){
        const self = this;
        btn.previousElementSibling.previousElementSibling.value = '';
        self.queryManagerStates.search = '';
        self.queryManagerList();
    },
    addNewQueryLoop: function(event){
        const title = event.target.value;
        if(title === "" || event.key !== "Enter") return;
        const self = this;
        const id = self.vueGlobalProp.$_generateId()
        self.globalSettings.generalCats.queryManager.push({
            id: id,
            title: title,
            description: '',
            args: '',
            category: '',
        })
        bricksData.controlOptions.queryTypes[id] = title;
        self.queryManagerStates.active = id;
        event.target.value = '';
        self.queryManagerInit();
        self.vueGlobalProp.$_showMessage(`Query Loop "${title}" has been correctly created!`);
    },
    duplicateQueryLoop: function(id){
        const self = this;
        const activeObj = self.globalSettings.generalCats.queryManager.find(el => el.id === id);
        const newId = self.vueGlobalProp.$_generateId()
        self.globalSettings.generalCats.queryManager.push({
            ...activeObj, 
            id: newId, 
            title: `${activeObj.title} (Copy)`,
        })
        bricksData.controlOptions.queryTypes[newId] = `${activeObj.title} (Copy)`;
        self.queryManagerStates.active = id;
        self.queryManagerInit();
        self.vueGlobalProp.$_showMessage(`Query Loop "${`${activeObj.title} (Copy)`}" has been correctly duplicated!`);
    },
    deleteQueryLoop: function(id){
        const self = this;
        const activeObj = self.globalSettings.generalCats.queryManager.find(el => el.id === id);
        if(self.queryManagerStates.active === activeObj.id) self.queryManagerStates.active = null;
        self.globalSettings.generalCats.queryManager.splice(self.globalSettings.generalCats.queryManager.indexOf(activeObj), 1);
        delete bricksData.controlOptions.queryTypes[activeObj.id];
        self.queryManagerInit();
        self.vueGlobalProp.$_showMessage(`Query Loop "${`${activeObj.title}`}" has been correctly deleted!`);
    },
    getQueryVar: function (settings, element_id) {
        const self = this;
    
        // Return a Promise that resolves with the response data or rejects with an error
        return new Promise((resolve, reject) => {
            jQuery.ajax({
                url: openai_ajax_req.ajax_url,
                data: {
                    action: 'get_var_query_ajax_function',
                    nonce: openai_ajax_req.nonce,
                    settings: settings,
                    element_id: element_id,
                },
                method: "POST",
                success: function (response) {
                    // Resolve the Promise with the response data
                    resolve(JSON.stringify(response.data));
                },
                error: function (data) {
                    // Reject the Promise with an error
                    reject('Something went wrong.');
                }
            });
        });
    },
    saveQueryManager: function(){
        const self = this;
        const obj = self.globalSettings.generalCats.queryManager || [];
        const obj2 = self.globalSettings.generalCats.queryManagerCats || [];
        jQuery.ajax({
            url: openai_ajax_req.ajax_url,
            data: {
                action: 'save_query_manager_ajax_function',
                nonce: openai_ajax_req.nonce,
                query_manager: obj,
                query_manager_cats: obj2,
            },
            method: "POST",
            success: function(data) {
                self.vueGlobalProp.$_showMessage('Query Loops settings saved successfully!')
            },
            error: function(data) {
                self.vueGlobalProp.$_showMessage('Something went wrong - Query options not saved.')
            }
        });
    },
    // Prompt
    promptManagerStates: {
        active: null,
        activeCategory: 'css',
        search: '',
        categories: ['css', 'content']
    },
    promptManagerInit: function(){
        const self = this;
        if(self.promptManagerStates.active === null){
            if(brxcPromptManager && brxcPromptManager.length >0) self.promptManagerStates.active = brxcPromptManager[0].id;
        }
        self.promptManagerCat();
        self.promptManagerList();
        self.promptManagerPanel();
    },
    promptManagerCat: function(){
        const self = this;
        const listWrapper = document.querySelector('#brxcPromptCatListCanvas');
        if(!listWrapper || !Array.isArray(self.promptManagerStates.categories)) return;
        let cats = '<ul>';
        let categoryFound;
        let count;

        function isActive (cat) {
            if(cat === self.promptManagerStates.activeCategory) return true;
            return false;
        }

        // Categories
        self.promptManagerStates.categories.forEach(cat => {
            count = Array.from(brxcPromptManager).filter(el => el && el.hasOwnProperty('category') && cat === el.category).length;
            cats += `<li class="${isActive(cat) ? 'active' : ''}"${isActive(cat) ? ' data-active="true"' : ''} data-id="${cat}" data-balloon="${cat}" data-balloon-pos="right" onClick="ADMINBRXC.promptManagerFilterCat(event)"><input type="text" data-initial="${cat}" value="${cat}" readonly/><span class="count">${count}</span></li>`
            
        })

        cats += '</ul>';
        
        listWrapper.innerHTML = cats;   
    },
    promptManagerFilterCat: function(event){
        const self = this;
        target = (event.target.dataset.id) ? event.target : event.target.parentElement;
        if(target.dataset.active === 'true') return;
        self.promptManagerStates.activeCategory = target.dataset.id;
        self.promptManagerCat();
        self.promptManagerList();
    },
    promptManagerList: function(){
        const self = this;
        const list = document.querySelector('#promptManagerUI__list');
        let arr = Array.from(brxcPromptManager).filter(el => el && el.category === self.promptManagerStates.activeCategory);

        // Search
        if(self.promptManagerStates.search !== ''){
            arr = Array.from(arr).filter(el => el && (el.label.toLowerCase().includes(self.promptManagerStates.search.toLowerCase()) || el.prompt.toLowerCase().includes(self.promptManagerStates.search.toLowerCase())))
        }
        
        // Content
        let content = '';
        arr.forEach(obj => {
            content += `<li class="${self.promptManagerStates.active === obj.id ? ' active' : ''}" data-id="${obj.id}" >
                            <span>${obj.label}</span>
                            <div class="actions">
                                <div class="duplicate" data-id="${obj.id}" data-balloon="Duplicate" data-balloon-pos="bottom-right" onclick="event.stopPropagation();ADMINBRXC.duplicatePrompt(this.dataset.id)"><i class="fas fas fa-clone"></i></div>
                                <div class="delete" data-id="${obj.id}" data-balloon="Delete" data-balloon-pos="bottom-right" onclick="event.stopPropagation();ADMINBRXC.setDeleteVariable(this, 'ADMINBRXC.deletePrompt(this.dataset.id);')"><i class="ti-trash"></i></div>
                            </div> 
                        </li>`
        });
        list.innerHTML = content;
        const li = list.querySelectorAll('li');
        if(li.length > 0){
            li.forEach(el => {
                el.addEventListener('click', () => {
                    self.promptManagerStates.active = el.dataset.id;
                    self.promptManagerInit();
                })
            })
        }
    },
    promptManagerPanel: function(){
        const self = this;
        const panel = document.querySelector('#promptManagerUI__panel');

        const activeObj = brxcPromptManager.find(el => el.id === self.promptManagerStates.active);
        if (!activeObj) return;

        let content = '';
        content += `<div class="brxc-prompt-manager__title-wrapper">
                        <div>
                            <label for="brxcPromptTitle" class="brxc-input__label has-tooltip"><span>Name</span><div data-balloon="To rename the current Prompt label, just type inside this input." data-balloon-pos="bottom-left" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div></label>
                            <input type="text" id="brxcPromptTitle" placeholder="" value="${activeObj.label}" />
                        </div>
                    </div>`;
        content += `<div class="brxc-prompt-manager__prompt-wrapper">
                        <label class="brxc-input__label has-tooltip">
                            <span>AI Prompt</span>
                            <div data-balloon="Add here your AI prompt." data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div>
                        </label>
                        <textarea class="description">${activeObj.prompt}</textarea>
                    </div>`;
        panel.innerHTML = content;

        const title = panel.querySelector('#brxcPromptTitle');
        
        // Listeners
        if (title){
            title.addEventListener('input', () => {
                activeObj.label = title.value;
                self.promptManagerList();
            })
        }
        const description = panel.querySelector('textarea.description');
        if (description){
            description.addEventListener('change', () => {
                activeObj.prompt = description.value;
            })
        }
    },
    resetPromptFilter: function(btn){
        const self = this;
        btn.previousElementSibling.previousElementSibling.value = '';
        self.promptManagerStates.search = '';
        self.promptManagerList();
    },
    addNewPrompt: function(event){
        const label = event.target.value;
        if(label === "" || event.key !== "Enter") return;
        const self = this;
        const id = self.vueGlobalProp.$_generateId()
        brxcPromptManager.push({
            id: id,
            label: label,
            prompt: '',
            category: self.promptManagerStates.activeCategory,
        })
        self.promptManagerStates.active = id;
        event.target.value = '';
        self.promptManagerInit();
        self.vueGlobalProp.$_showMessage(`Prompt "${label}" has been correctly created!`);
    },
    duplicatePrompt: function(id){
        const self = this;
        const activeObj = brxcPromptManager.find(el => el.id === id);
        const newId = self.vueGlobalProp.$_generateId()
        brxcPromptManager.push({
            ...activeObj, 
            id: newId, 
            label: `${activeObj.label} (Copy)`,
        })
        self.promptManagerStates.active = id;
        self.promptManagerInit();
        self.vueGlobalProp.$_showMessage(`Prompt "${`${activeObj.label} (Copy)`}" has been correctly duplicated!`);
    },
    deletePrompt: function(id){
        const self = this;
        const activeObj = brxcPromptManager.find(el => el.id === id);
        if(self.promptManagerStates.active === id) {
            if(brxcPromptManager.length > 0){
                self.promptManagerStates.active = brxcPromptManager[0].id;
            } else {
                self.promptManagerStates.active = null;
            }
        }
        brxcPromptManager.splice(brxcPromptManager.indexOf(activeObj), 1);
        self.promptManagerInit();
        self.vueGlobalProp.$_showMessage(`Prompt "${`${activeObj.label}`}" has been correctly deleted!`);
    },
    savePromptManager: function(){
        const self = this;
        const obj = brxcPromptManager || [];
        jQuery.ajax({
            url: openai_ajax_req.ajax_url,
            data: {
                action: 'save_prompt_manager_ajax_function',
                nonce: openai_ajax_req.nonce,
                prompt_manager: obj,
            },
            method: "POST",
            success: function(data) {
                self.vueGlobalProp.$_showMessage('Prompt settings saved successfully!')
            },
            error: function(data) {
                self.vueGlobalProp.$_showMessage('Something went wrong - Prompts not saved.')
            }
        });
    },
    advancedCSSStates: {
        view: 'stylesheet',
        active: 'at-page-css',
        search: '',
        showOptions: false,
        sidebar: false,
        addCategory: false,
        renameCategory: false,
        partials: '',
        partialVariables: [],
        editAI: false,
        communityRecipesLoaded: false,
    },
    advancedCSSInit: function(){
        const self = this;
        const wrapper = document.querySelector('#brxcCSSOverlay')
        wrapper.classList.contains('sidebar') ? self.advancedCSSStates.sidebar = true :self.advancedCSSStates.sidebar = false;
        self.disableSelectorPicker();
        self.compilePartials(self.advancedCSSStates);
        self.compilePartialsVariables(self.advancedCSSStates);
        self.advancedCSSCat();
        self.advancedCSSPanel();
    },
    compilePartials: function(state){
        state.partials = brxcAdvancedCSSDefault.filter(el => el && el.type === "scssp" && el.status == "1" && el.contentSass).map(el => el.contentSass).join('');
    },
    compilePartialsVariables: function(state){
        state.partialVariables = state.partials.match(/\$[a-zA-Z0-9_-]+/g) ?? [];
    },
    advancedCSSCat: function(){
        const self = this;
        self.advancedCSSStates.sidebar ? self.advancedCSSCatSidebar() : self.advancedCSSCatFullsize(); 
    },

    getCommunityRecipes: async function(advancedCSS = false) {
        const self = this;
        const loader = document.querySelector('#advancedCSSUI__loader');
        if(advancedCSS) loader.classList.add('active');

        function removeLoader(){
            self.advancedCSSCatFullsizeRender();
            loader.classList.remove('active');
        }

        try {
            let allResults = [];
            let page = 1;
            let totalPages = 1;

            while (page <= totalPages) {
                const rawResponse = await fetch(`https://advancedthemer.com/wp-json/wp/v2/recipes?_fields=id,status,title,acf&per_page=100&page${page}`);
                const content = await rawResponse.json();
                if (content.error) {
                    console.log('content error');
                    self.advancedCSSStates.communityRecipesLoaded = true
                    if(advancedCSS) removeLoader();
                    break;
                } else {
                    const results = content
                        .filter(el => el.status === "publish")
                        .sort((a, b) => b.id - a.id)
                        .map(el => {
                            return {
                                category: "community recipes",
                                contentCss: el.acf.recipe_code,
                                default: true,
                                file: false,
                                id: `community_recipe_${el.title.rendered}`,
                                label: el.title.rendered,
                                message: `This recipe is provided by ${el.acf.recipe_author}. The Community Recipes can't be modified and are set as read-only`,
                                readOnly: true,
                                saveMethod: false,
                                status: 1,
                                toggleActive: false,
                                type: "recipe",
                                typeLabel: "recipe",
                            };
                        });
                    allResults = allResults.concat(results);

                    const totalPagesHeader = rawResponse.headers.get('X-WP-TotalPages');
                    totalPages = totalPagesHeader ? parseInt(totalPagesHeader) : totalPages;
                    page++;
                }
            }

            allResults.forEach(result => {
                const existing = brxcAdvancedCSSDefault.find(el => el.id === result.id);
                if(!existing) brxcAdvancedCSSDefault.unshift(result);
            })
            self.advancedCSSStates.communityRecipesLoaded = true
            if(advancedCSS) removeLoader();
                
            
        } catch (error) {
            console.log('Fetch error:', error);
            self.advancedCSSStates.communityRecipesLoaded = true
            if(advancedCSS) removeLoader();
        }
    },
    advancedCSSCatFullsize: function(){
        const self = this;
    
        self.globalSettings.classFeatures.advancedCSSCommunityRecipes && self.advancedCSSStates.communityRecipesLoaded === false & self.advancedCSSStates.view === "recipes" ? self.getCommunityRecipes(true) : self.advancedCSSCatFullsizeRender();    
    },

    advancedCSSCatFullsizeRender: function(){
        const self = this;
        const listWrapper = document.querySelector('#brxcAdvancedCSSCatListCanvas');
        if(!listWrapper) return;
        const categories = [...new Set(brxcAdvancedCSSDefault.map(el => el.category))];
        let cats = '';

        function isActive (objId) {
            if(objId === self.advancedCSSStates.active) return true;
            return false;
        }
        function isCatIncluded(el){
            const field = self.globalSettings.classFeatures.advancedCSSEnableSass && el.hasOwnProperty('contentSass') ? 'contentSass' : 'contentCss';
            if(el[field]?.toLowerCase().includes(self.advancedCSSStates.search.toLowerCase())) return true;
            return false;
        }


        function view(obj){
            if(self.advancedCSSStates.view === "recipes"){
                return obj.typeLabel === "recipe";
            } else {
                return obj.typeLabel !== "recipe";
            }
        }

        function renderCategory(category, defaultFlag = true) {
            let defaultCats = brxcAdvancedCSSDefault.filter(obj => !obj.removed && obj.category === category && view(obj));
        
            // Apply search filter if any
            if (self.advancedCSSStates.search !== '') {
                defaultCats = defaultCats.filter(el => isCatIncluded(el) || (el.label?.toLowerCase().includes(self.advancedCSSStates.search.toLowerCase())));
            }
        
            let output = `<div class="cat-separation${category === 'custom' ? ' custom' : ''}"><span class="title">${category === 'custom' ? `custom ${self.advancedCSSStates.view}` : category}</span><ul>`;
            
            defaultCats.forEach(obj => {
                const isActiveClass = isActive(obj.id) ? 'active' : '';
                const isActiveData = isActive(obj.id) ? ' data-active="true"' : '';
                const readOnlyAttr = !isActive(obj.id) ? ' readonly' : '';
        
                output += `<li class="${isActiveClass}"${isActiveData} data-id="${obj.id}" onClick="ADMINBRXC.advancedCSSFilterCat(event)">`;
                if(obj.hasChanged === true) output += `<div class="brxc-advanced-css--change-indicator"></div>`
                output += `<div class="brxc-advanced-css-type--label">${obj.typeLabel}</div>`;
                
                // Handle default or custom input rendering
                output += `<input type="text" data-initial="${obj.label}" value="${obj.label}"${obj.default !== defaultFlag ? readOnlyAttr : ' readonly'}/>`;
                
                // Render actions if necessary
                output += renderActions(obj);
        
                output += `</li>`;
            });
        
            output += `</ul></div>`;
            return output;
        }
        
        function renderActions(obj) {
            let actions = `<div class="brxc-actions">`;
        
            if (isActive(obj.id) && ["custom", "at framework"].includes(obj.category)) {
                actions += `<div class="deleteCat" onClick="event.stopPropagation();ADMINBRXC.deleteAdvancedCSSCategory(event, '${self.advancedCSSStates.active}')" 
                              data-balloon="Delete File" data-balloon-pos="top-right">
                              <span class="bricks-svg-wrapper"><i class="ti-trash"></i></span></div>`;
            }
        
            if (obj.readOnly) {
                actions += `<div class="brxc-readonly--icon" data-balloon="Readonly" data-balloon-pos="top-right"><i class="fas fa-eye"></i></div>`;
            }
        
            if (obj.toggleActive) {
                actions += `<div class="brxc-toggle-palette">
                              <div class="" data-balloon="${obj.status === "1" ? 'Disable' : 'Enable'} Stylesheet" data-balloon-pos="top-right"
                              onclick="ADMINBRXC.toggleAdvancedCSSStatus(event, '${obj.id}')">
                              <i class="fas fa-toggle-${obj.status === "1" ? 'on' : 'off'}"></i></div></div>`;
            }
        
            actions += `</div>`;
            return actions;
        }
        
        // Main Render Function
        function renderCategories(categories) {
            let cats = '';
            categories.filter(el => el && el !== "custom").forEach(category => {
                cats += renderCategory(category);
            });
        
            // Custom Category Section
            cats += renderCategory("custom", false);
        
            return cats;
        }

        cats += renderCategories(categories);

        // Add new CSS file
        const placeholder = self.advancedCSSStates.view === "stylesheet" ? "stylesheet" : "recipe";
        const keyupFn = self.advancedCSSStates.view === "stylesheet" ? "ADMINBRXC.addNewAdvancedCSSCategory(event);" : "ADMINBRXC.addNewAdvancedCSSRecipe(event);"

        cats += `<input type="text" id="addNewAdvancedCSSCat" placeholder="+ New ${placeholder}" onkeyup="${keyupFn}" />`;
        
        listWrapper.innerHTML = cats;

        // rename cat
        const input = listWrapper.querySelector('li.active input');
        if(input){
            input.addEventListener('keyup', (event) => {
                if(event.key !== "Enter") return;
                const value = event.target.value.replaceAll(' ', '-').toLowerCase();
                if(value === event.target.dataset.initial) return self.advancedCSSCat();
                if(brxcAdvancedCSSDefault.map(el => el && el.label).includes(value)) return self.vueGlobalProp.$_showMessage(`ABORT: ${self.advancedCSSStates.view} "${value}" already exists`);
                const activeObj = brxcAdvancedCSSDefault.find(el => el && el.id === self.advancedCSSStates.active);
                if(!activeObj) return self.vueGlobalProp.$_showMessage(`ABORT: Error renaming the ${self.advancedCSSStates.view}.`);
                activeObj.label = value;
                self.vueGlobalProp.$_showMessage(`${self.advancedCSSStates.view} correctly renamed to ${value}`)
                self.advancedCSSCat();
            })
        }
        
    },
    advancedCSSCatSidebar: function(){
        const self = this;
        const listWrapper = document.querySelector('#brxcAdvancedCSSCatListCanvas');
        if(!listWrapper)  return;
        const activeObj = brxcAdvancedCSSDefault.find(el => el && el.id === self.advancedCSSStates.active);
        let content = '';
        content += `<div class="brxc-select">`;
        
        if(self.advancedCSSStates.renameCategory === false && self.advancedCSSStates.addCategory === false && self.advancedCSSStates.active){
            const uneditableCategories = brxcAdvancedCSSDefault.filter(el => el && el.category === "default").map(el => el && el.id);

            content += `
            <div class="brxc-select-new rounded hidden" name="brxc-cssVariablesOptions" id="cssVariablesOptions">
                <div class="brxc-select-new__wrapper">
                    ${brxcAdvancedCSSDefault.map(cat => {
                        return `<div data-value="${cat.id}"${cat.id === self.advancedCSSStates.active ? ' class="active"' : ''}><span>${cat.label}</span></div>`;
                    }).join('')}
                </div>
            </div>`
            content += '<div class="brxc-icon-container">'
            content += !uneditableCategories.includes(self.advancedCSSStates.active) ? `<div class="brxc-icon" data-balloon="Rename CSS File" data-balloon-pos="bottom-right" onClick="ADMINBRXC.advancedCSSStates.renameCategory = true;ADMINBRXC.advancedCSSCat()"><span class="bricks-svg-wrapper"><i class="fas fa-pen"></i></span></div>` : '';
            content += `<div class="brxc-icon" data-balloon="Add New CSS File" data-balloon-pos="bottom-right" onClick="ADMINBRXC.advancedCSSStates.addCategory = true;ADMINBRXC.advancedCSSCat()"><span class="bricks-svg-wrapper"><i class="fas fa-plus"></i></span></div>`;
            content += !uneditableCategories.includes(self.advancedCSSStates.active) ? `<div class="brxc-icon" data-balloon="Delete CSS File" data-balloon-pos="bottom-right" onClick="ADMINBRXC.setDeleteVariable(this, 'ADMINBRXC.deleteVariableCategory()');"><span class="bricks-svg-wrapper"><i class="ti-trash"></i></span></div>` : '';
            content += '</div>';
            content += activeObj.toggleActive && !uneditableCategories.includes(self.advancedCSSStates.active) ? `<div class="brxc-toggle-palette"><div class="" data-balloon="${activeObj.hasOwnProperty('status') && activeObj.status === "1" ? "Disable CSS File" : "Enable CSS File"}" data-balloon-pos="bottom-right" onclick="ADMINBRXC.toggleAdvancedCSSStatus(event, '${activeObj.id}')"><i class="fas fa-toggle-${activeObj.hasOwnProperty('status') && activeObj.status === "1" ? 'on' : 'off'}"></i></div></div>` : '';
            
        } else if(self.advancedCSSStates.renameCategory === true){
            content += `<input type="text" id="brxcRenameCategory" data-initial="${activeObj.label}" value="${activeObj.label}" />`;
        } else if(self.advancedCSSStates.addCategory === true){
            content += `<input type="text" id="brxcAddCategory" placeholder="Type the filename here and hit ENTER." value="" />`;
        }
        content += `</div>`;
        if(activeObj.hasOwnProperty('message') && activeObj.message !== "") content += `<div class="brxc-panel-message" data-control="info">${activeObj.message}</div>`;

        if(listWrapper && content) listWrapper.innerHTML = content;

        // Select
        const select = document.querySelector('#cssVariablesOptions');
        self.helpers.selectControl(select, (target) => {
            self.advancedCSSStates.search = '';
            self.advancedCSSStates.active = target.dataset.value;
            self.advancedCSSInit();
        })

        // Add
        if (self.advancedCSSStates.addCategory === true || !self.advancedCSSStates.active) {
            self.advancedCSSStates.addCategory = false;
            const input = listWrapper.querySelector('#brxcAddCategory');
            if (!input) return;
            const end = input.value.length;
            input.setSelectionRange(end, end);
            input.focus();

            const onBlur = () => {
                input.removeEventListener("blur", onBlur);
                input.removeEventListener("keydown", onKeyDown);
                setTimeout(() => {
                    self.advancedCSSCat();
                }, 10);
            };

            const onKeyDown = (event) => {
                if (event.key === "Enter") {
                    self.addNewAdvancedCSSCategory(event);
                    input.removeEventListener("blur", onBlur);
                    input.removeEventListener("keydown", onKeyDown);
                };
            };

            input.addEventListener("blur", onBlur);
            input.addEventListener("keydown", onKeyDown);
        }

        // Rename
        if (self.advancedCSSStates.renameCategory === true) {
            self.advancedCSSStates.renameCategory = false;
            const input = listWrapper.querySelector('#brxcRenameCategory');
            if (!input) return;
            const end = input.value.length;
            input.setSelectionRange(end, end);
            input.focus();

            function renameName(event, activeObj) {

                const value = event.target.value.replaceAll(' ', '-').toLowerCase();
                if(value === event.target.dataset.initial) return self.advancedCSSCat();
                if(brxcAdvancedCSSDefault.map(el => el && el.label).includes(value)) return self.vueGlobalProp.$_showMessage(`ABORT: CSS File "${value}" already exists`);
                activeObj.label = value;
                self.vueGlobalProp.$_showMessage(`CSS file correctly renamed to ${value}`)
                self.advancedCSSCat();
            }

            const onBlur = () => {
                input.removeEventListener("blur", onBlur);
                input.removeEventListener("keydown", onKeyDown);
                setTimeout(() => {
                    self.advancedCSSCat();
                }, 10);
            };

            const onKeyDown = (event) => {
                if (event.key === "Enter") {
                    renameName(event, activeObj);
                    input.removeEventListener("blur", onBlur);
                    input.removeEventListener("keydown", onKeyDown);
                }
            };

            input.addEventListener("blur", onBlur);
            input.addEventListener("keydown", onKeyDown);
        }
    },

    toggleAdvancedCSSStatus: function(event, objId){
        const self = this;
        event.stopPropagation();
        const obj = brxcAdvancedCSSDefault.find(el => el && el.id === objId);
        if(!obj) return;

        obj.status == "1" ? obj.status = "0" : obj.status = "1";
        obj.hasChanged = true;
  
        self.advancedCSSRenderValue(obj, false)
        self.advancedCSSInit();
    },
    advancedCSSFilterCat: function(event){
        const self = this;
        target = (event.target.dataset.id) ? event.target : event.target.parentElement;
        if(target.dataset.active === 'true') return;
        self.advancedCSSStates.active = target.dataset.id;
        self.advancedCSSInit();
    },
    addNewAdvancedCSSCategory: function(event){
        const self = this;

        if(event.key !== "Enter") return;

        const values = event.target.value.split(',');
        if(values.length < 1) return;

        let hasChanges = false;
        let newId;

        values.forEach(name => {
            if(brxcAdvancedCSSDefault.map(obj => obj && obj.typeLabel !== "recipe" && obj.label).includes(name)) {
                return self.vueGlobalProp.$_showMessage('ABORT: File already exists');
            } else {
                hasChanges = true;
                newId = self.vueGlobalProp.$_generateId();
                const type = self.globalSettings.classFeatures.advancedCSSEnableSass ? 'scss' : 'css'; 
                brxcAdvancedCSSDefault.push({
                    "id": `css-${newId}`,
                    "file": false,
                    "label": name,
                    "type": type,
                    "typeLabel": type,
                    "category": "custom",
                    "scope": "global",
                    "message": '',
                    "note": "",
                    "read-only": false,
                    "contentCss": '',
                    "contentSass": '',
                    "saveMethod": "ajax",
                    "status": "1",
                    "priority": "10",
                    "toggleActive": true,
                    "enqueueFrontend": 1,
                    "enqueueBuilder": 0,
                    "enqueueGutenberg": 0,

                })
            }
        })
        if(hasChanges === true) {
            self.advancedCSSStates.active = `css-${newId}`;
            self.advancedCSSInit();
        };  
    },
    addNewAdvancedCSSRecipe: function(event){
        const self = this;

        if(event.key !== "Enter") return;

        const values = event.target.value.split(',');
        if(values.length < 1) return;

        let hasChanges = false;
        let newId;

        values.forEach(name => {
            if(brxcAdvancedCSSDefault.map(obj => obj && obj.typeLabel === "recipe" && obj.label).includes(name)) {
                return self.vueGlobalProp.$_showMessage('ABORT: Recipe already exists');
            } else {
                hasChanges = true;
                newId = self.vueGlobalProp.$_generateId();
                const type = self.globalSettings.classFeatures.advancedCSSEnableSass ? 'scss' : 'css'; 
                brxcAdvancedCSSDefault.push({
                    "id": `recipe-${newId}`,
                    "file": false,
                    "label": self.helpers.formatForClasses(name),
                    "type": "css",
                    "typeLabel": "recipe",
                    "category": "custom",
                    "message": "",
                    "readOnly": false,
                    "contentCss": "",
                    "status": "1",
                    "saveMethod": "ajax",
                    "toggleActive": true,

                })
            }
        })
        if(hasChanges === true) {
            self.advancedCSSStates.active = `recipe-${newId}`;
            self.advancedCSSInit();
        };  
    },
    deleteAdvancedCSSCategory: function(event,id){
        const self = this;
        event.stopPropagation();
        const target = event.target;
        const oldContent = target.innerHTML;
        const oldBalloon = target.dataset.balloon;
        const oldFunction = target.getAttribute('onclick');
        const newContent = '<span class="bricks-svg-wrapper"><i class="fas fa-check"></i></span>';
        const newBalloon = 'Confirm?';

        target.setAttribute("onClick", `event.stopPropagation(),ADMINBRXC.deleteAdvancedCSSCategoryFinal('${id}')`);
        target.setAttribute("data-balloon", newBalloon);
        target.innerHTML = newContent;
        setTimeout(() => {
            target.setAttribute("onClick", oldFunction);
            target.setAttribute("data-balloon", oldBalloon);
            target.innerHTML = oldContent;
        }, 2000)
    },
    deleteAdvancedCSSCategoryFinal: function(id){
        const self = this;
        const obj = brxcAdvancedCSSDefault.find(el => el && el.id === id);
        if(!obj) return self.vueGlobalProp.$_showMessage('Abort: error finding the CSS file');
        obj['removed'] = true;
        const catName = obj.label;

        // Remove <style>
        const x = document.querySelector('#bricks-builder-iframe').contentWindow;
        let override = x.document.querySelector(`#at-${id}-css`);
        if(override) override.remove();
        
        // reinit
        self.advancedCSSStates.active = "at-page-css";
        self.vueGlobalProp.$_showMessage(`CSS file "${catName}" has been successfully deleted!`);
        self.advancedCSSInit();
    },
    toggleCompiledCSS: function (id){
        const self = this;
        const activeObj = brxcAdvancedCSSDefault.find(el => el.id === id);
        if(activeObj.hasOwnProperty('compiledCSS') && activeObj.compiledCSS){
            activeObj.compiledCSS = false;
            if(self.globalSettings.classFeatures.advancedCSSEnableSass) activeObj.readOnly = false;
        } else {
            activeObj.compiledCSS = true;
            activeObj.readOnly = true;
        }
        self.advancedCSSCat();
        self.advancedCSSPanel();
    },
    advancedCSSPanel: function(){
        const self = this;
        const header = document.querySelector('#advancedCSSUI__header');
        const panel = document.querySelector('#advancedCSSUI__panel');
        let content = '';

        const activeObj = brxcAdvancedCSSDefault.find(obj => obj.id === self.advancedCSSStates.active);
        if (!activeObj) return;

        // Header
        content += `
                    <div id="brxcAdvancedCSSToggleType">
                        <a class="brxc-overlay__action-btn ${self.advancedCSSStates.view === "stylesheet" ? "primary" : "secondary"}" onclick="ADMINBRXC.advancedCSSStates.view = 'stylesheet';ADMINBRXC.advancedCSSInit();"><span>Stylesheets</span></a>
                        <a class="brxc-overlay__action-btn ${self.advancedCSSStates.view === "recipes" ? "primary" : "secondary"}" onclick="ADMINBRXC.advancedCSSStates.view = 'recipes';ADMINBRXC.advancedCSSInit();"><span>Recipes</span></a>
                    </div>
                    <div class="brxc-panel-header">
                        <div class="brxc-panel-category">${activeObj.category}</div>
                        <div class="brxc-panel-separator">/</div>
                        <div class="brxc-panel-title">${activeObj.label}</div>`;
        if(activeObj.type === "scss") content += `<div class="brxc-advanced-css-type--compiled-css${activeObj.compiledCSS ? ' active' :''}" onclick="ADMINBRXC.toggleCompiledCSS('${activeObj.id}')">View compiled CSS</div>`;

        if(activeObj.category === "custom") content += `<div class="brxc-panel-options${self.advancedCSSStates.showOptions ? ' active' : ''}" data-balloon="${self.advancedCSSStates.showOptions ?  'Hide' : 'Show'} Advanced Settings" data-balloon-pos="right" onclick="ADMINBRXC.advancedCSSStates.showOptions = !ADMINBRXC.advancedCSSStates.showOptions;ADMINBRXC.advancedCSSPanel();"><i class="fas fa-gear"></i></div>`;
        content += `</div>`;
        if(activeObj.hasOwnProperty('message') && activeObj.message !== "" && !self.advancedCSSStates.showOptions){
            content += `<div class="brxc-panel-message" data-control="info">${activeObj.message}</div>`;
        }
        header.innerHTML = content;

        // Panel
        const textareaContent = activeObj.type !== "css" && activeObj.hasOwnProperty('contentSass') && activeObj.compiledCSS !== true ? activeObj.contentSass : activeObj.contentCss;
        content = '';
        let sass = false;
        if (self.globalSettings.classFeatures.advancedCSSEnableSass){
            self.destroySassInstances('advancedCss');
            sass = self.createSassInstance('advancedCss');
        }
        if(self.advancedCSSStates.showOptions && activeObj.category === "custom"){
            const objs = [
                {
                    label: "Enqueue on Frontend?",
                    balloon: "If this option is checked, the CSS file will be enqueued on the frontend (and inside the preview window of the builder)",
                    data: "click",
                    prop: "enqueueFrontend",
                    rerender: 1,
                },
                {
                    label: "Enqueue in the Builder?",
                    balloon: "If this option is checked, the CSS file will be enqueued in the builder itself but not inside the preview window.",
                    data: "click",
                    prop: "enqueueBuilder",
                    rerender: 1,
                },
                {
                    label: "Enqueue in Gutenberg?",
                    balloon: "If this option is checked, the CSS file will be enqueued inside the Block Editor of Gutenberg.",
                    data: "click",
                    prop: "enqueueGutenberg",
                    rerender: 0,
                },
            ];
            content += `<div class="brxc-advanced-options__wrapper">
                            <div>
                                <label for="brxcAdvancedCSsID" class="has-tooltip">
                                    <span>Internal ID</span>
                                    <div data-balloon="This ID is used to create the CSS file and enqueue it on your website." data-balloon-pos="right" data-balloon-length="large"><i class="fas fa-circle-question"></i></div>
                                </label>
                                <input type="text" id="brxcAdvancedCSsID" class="brxc-input-text" value="${activeObj.id}" readonly></input>
                            </div>
                            <div${self.globalSettings.classFeatures.advancedCSSEnableSass ? ` class="brxc-select"` : ''}>
                                <label for="brxcAdvancedCSSType" class="has-tooltip">
                                    <span>Type</span>
                                    <div data-balloon="Choose the type of file you want to work with." data-balloon-pos="right" data-balloon-length="large"><i class="fas fa-circle-question"></i></div>
                                </label>`;
            if(self.globalSettings.classFeatures.advancedCSSEnableSass){
                const types = [
                    { value: 'css', label: 'css' },
                    { value: 'scss', label: 'scss' },
                    { value: 'scssp', label: 'partial' }
                ];
                content += `<div class="brxc-select-new bg2 rounded hidden" id="brxcAdvancedCSSType">
                                <div class="brxc-select-new__wrapper">
                                    ${types.map(type => {
                                        return `<div data-value="${type.value}"${activeObj.type === type.value ? ' class="active"' : ''} data-label="${type.label}"><span>${type.label}</span></div>`;
                                    }).join('')}
                                </div>
                            </div>`
            } else {
                content += `<input type="text" id="brxcAdvancedCSSType" class="brxc-input-text" value="${activeObj.typeLabel}" readonly></input>`
            }
                content +=  `</div>
                             <div>
                                <label for="brxcAdvancedCSsPriority" class="has-tooltip">
                                    <span>Priority</span>
                                    <div data-balloon="Set the priority the CSS file should be enqueued. The lower the number is, the fastest it will be printed." data-balloon-pos="right" data-balloon-length="large"><i class="fas fa-circle-question"></i></div>
                                </label>
                                <input type="number" id="brxcAdvancedCSsPriority" data-prop="priority" data-default="10" class="brxc-input-text" min="1" max="9999" value="${activeObj.type !== 'scssp' ? `${activeObj.priority}"` : '" readonly'}></input>
                            </div>
                            <div style="flex-basis:100%;">
                                <label for="brxcAdvancedCSSMessage" class="has-tooltip">
                                    <span>Message</span>
                                    <div data-balloon="Add a custom message that will be visible on top when selecting this stylesheet." data-balloon-pos="right" data-balloon-length="large"><i class="fas fa-circle-question"></i></div>
                                </label>
                                <textarea id="brxcAdvancedCSSMessage" data-prop="message" data-default="">${activeObj.message}</textarea>
                            </div>`
            objs.forEach(obj => {
                if(obj.data === "click"){
                    content += `<div class="gridUI__input-wrapper">
                            <label class="has-tooltip">
                                <span>${obj.label}</span>
                                <div data-balloon="${obj.balloon}" data-balloon-pos="bottom" data-balloon-length="medium">
                                    <i class="fas fa-circle-question"></i>
                                </div>
                            </label>
                            <i class="fas fa-toggle-${activeObj[obj.prop] == 1 ? 'on' : 'off'}" data-click="${obj.prop}" data-rerender="${obj.rerender}"></i>
                        </div>`
                }
            })
        content += `</div>`;
        }
        content += `<div class="actions"></div><div class="codemirror-wrapper">
            <textarea class="codemirror">${textareaContent}</textarea>
            <div class="brxc-error-handling"></div>`

        // AI
        if(self.helpers.isAIActive() && self.globalSettings.isAIApiKeyEmpty !== "") {
            const isAIreadOnly = activeObj.readOnly || activeObj.id === "at-child-css";
            content += `<div id="brxcAdvancedCSSAIpromptContainer">
                            <div id="brxcAdvancedCSSAIpromptWrapper"${isAIreadOnly ? ' class="readonly"': ''}>
                                <div id="brxcAdvancedCSSAIEdit"${self.advancedCSSStates.editAI ? ' class="active"' : ''}" data-balloon="Edit existing code" data-balloon-pos="top-left"><i class="fas fa-edit"></i></div>
                                <textarea id="brxcAdvancedCSSAIprompt" placeholder="Message AI" onInput="ADMINBRXC.helpers.textAreaAutoGrow(this, '40px')"></textarea>
                                <div id="brxcAdvancedCSSAISendRequest"><i class="fas fa-arrow-up"></i></div>
                            </div>
                        </div>
                    </div>`;
        }
        panel.innerHTML = content;

        // Listeners
        const inputs = panel.querySelectorAll('input[data-prop],textarea[data-prop]');
        if(inputs.length > 0){
            ['input', 'change'].forEach(ev => {
                inputs.forEach(input => {
                    input.addEventListener(ev, () => {
                        const prop = input.dataset.prop;
                        input.value !== "" ? activeObj[prop] = input.value : activeObj[prop] = input.dataset.default;
                    })
                }) 
            })
        }

        const clicks = panel.querySelectorAll('[data-click]');
        if(clicks.length > 0){
            clicks.forEach(el => {
                el.addEventListener('click', () => {
                    const prop = el.dataset.click;
                    activeObj[prop] == 1 ?  activeObj[prop] = 0 : activeObj[prop] = 1;
                    const newCSS = activeObj.type !== "css" && activeObj.hasOwnProperty('contentSass') && activeObj.compiledCSS !== true ? activeObj.contentSass : activeObj.contentCss;
                    if(el.dataset.rerender === "1") self.advancedCSSRenderValue(activeObj, newCSS);
                    self.advancedCSSPanel();
                })
            }) 
        }

        const select = panel.querySelector('#brxcAdvancedCSSType');
        self.helpers.selectControl(select, (target) => {
                activeObj.type = target.dataset.value;
                activeObj.typeLabel = target.dataset.label
                self.advancedCSSInit();
        })

        // Edit AI
        const editAI = panel.querySelector('#brxcAdvancedCSSAIEdit');
        if(editAI){
            editAI.addEventListener('click', () => {
                self.advancedCSSStates.editAI = !self.advancedCSSStates.editAI;
                self.advancedCSSPanel();
            })
        }

        // Codemirror
        const textarea = panel.querySelector('textarea.codemirror');
        if (textarea){
            const metaKey = (e) => self.vueState.isMac ? e.metaKey : e.ctrlKey;
            const options = self.codeMirrorOptions(textarea);
            options.mode = activeObj.type !== "css" ? "text/x-scss" : "css";
            options.styleActiveLine = true;
            options.autoCloseBrackets = true;
            options.matchBrackets = true;
            options.selfContain = true;
            options.search = { bottom: false };
            options.autofocus = false;
            if(activeObj.readOnly) {
                options.readOnly = true;
            } else {
                options.profile = "xhtml"
            }
            const MyCM = CodeMirror.fromTextArea(textarea, options);
            if(!activeObj.readOnly) emmetCodeMirror(MyCM);
            MyCM.getWrapperElement().setAttribute("data-type", "at");
            if(activeObj.id === "at-child-css") self.helpers.childThemeCommentReadOnly(MyCM);

            const debouncedRenderValue = self.debounce(function(activeObj, value) {
                self.advancedCSSRenderValue(activeObj, value);
            }, 500);
            // Input events
            if(!activeObj.readOnly){
                MyCM.on("keydown", function (cm, event) {
                    // Beautify
                    if(metaKey(event) && event.key === "b" ){
                        event.preventDefault();
                        event.stopPropagation();
                        return self.beautifyCSS(`#advancedCSSUI__panel`)
                    }

                    if(metaKey(event) && event.shiftKey && event.key === "7" ){
                        cm.toggleComment();
                    }

                    // Search
                    if(metaKey(event) && event.key === "f" ){
                        event.preventDefault();
                        event.stopPropagation();
                        return cm.execCommand('find');
                    }
    
                    if (event.key === 'Tab') {
                        self.helpers.replaceRWithRoot(MyCM, event)
                        
                    }

                    if (!cm.state.completionActive &&
                        ((event.key >= '0' && event.key <= '9') ||    // Digits 0-9
                            (event.key >= 'a' && event.key <= 'z') ||    // Letters a-z
                            event.key === '(' || event.key === '!' ||    // Opening parenthesis (
                            event.key === '-') &&                        // Dash
                        !event.metaKey && !event.altKey && event.key !== '{' && event.key !== '}' &&
                        !event.ctrlKey) {
                            CodeMirror.commands.autocomplete(cm, null, { completeSingle: false });
                    }
                });

                MyCM.on("change", function (cm, event) {
                    const value = cm.getValue();
                    let hasChanged = false;
                    if(!activeObj.hasOwnProperty('hasChanged')) hasChanged = true;
                    activeObj.hasChanged = true;
                    if(hasChanged) self.advancedCSSCat();
                    debouncedRenderValue(activeObj, value);
                });
            }

            // AI
            const aiRequest = panel.querySelector('#brxcAdvancedCSSAISendRequest');
            if(aiRequest){
                aiRequest.addEventListener('click', () => {
                    const prompt = panel.querySelector('#brxcAdvancedCSSAIprompt');
                    self.advancedCSSAI(MyCM, prompt.value);
                    prompt.value = "";
                })
            }
        }

        // set icons
        const action = panel.querySelector('.actions');
        if(!action) return;
        let options = '';
        if(activeObj.readOnly){
            options = {
                "wrapper": action,
                "selector": '#advancedCSSUI__panel',
                "comment": false,
                "fullscreen": true,
                "selector-picker": false,
                "contextualSuperpowercss": {
                    "extract-global-classes": true,
                    "extract-global-variables": true,
                }
            }
        } else if(activeObj.type === "scssp") {
            options = {
                "wrapper": action,
                "selector": '#advancedCSSUI__panel',
                "comment": true,
                "fullscreen": true,
                "selector-picker": true,
                "contextualSuperpowercss": {
                    "beautify-css": true,
                }
            }
        } else {
            options = {
                "wrapper": action,
                "selector": '#advancedCSSUI__panel',
                "comment": true,
                "fullscreen": true,
                "selector-picker": true,
                "contextualSuperpowercss": {
                    "component-selectors": true,
                    "beautify-css": true,
                    "variabilize-css": true,
                },
                "rootSelector": ':root',
            }
        }
        if(activeObj.type === "css"){
            options["contextualSuperpowercss"] = {
                "component-selectors": true,
                "beautify-css": true,
                "variabilize-css": true,
                "extract-global-classes": true,
                "extract-global-variables": true,
            };
        }

        self.superPowerCSSIcons(options);

    },
    advancedCSSAI: function(cm, promptRequest){
        const self = this;
        const activeStyle = brxcAdvancedCSSDefault.find(el => el.id === self.advancedCSSStates.active);
        const type = activeStyle.type === "css" ? "CSS" : "SCSS";
        let systemtContent = '';
        if(self.advancedCSSStates.editAI){
            systemtContent = `You are an expert ${type} developer. You will receive a ${type} string and a user prompt. Your task is to edit or improve the existing ${type} rules based on the prompt. Return only the raw ${type} code without any additional comments, explanations, or text. The output must be valid, executable ${type} code, with no formatting, comments, or non-${type} elements. Do not include any text that is not part of a valid ${type} declaration.`
        } else {
            systemtContent = `You are an expert ${type} developer. You will receive existing  and a user prompt. Your task is to generate new ${type} code based on the prompt and append it to the existing ${type} code. Do not repeat or modify the existing ${type} code. Output only the new rules without any additional comments, explanations, or text. Don't start with "scss". The response should contain only valid, executable ${type} declarations and nothing else.`
        }
        let cssString = cm.getValue();
        const requestBody = {
            model: self.globalSettings.defaultAIModel,
            stream: true,
            messages: [
                {
                    role: "system",
                    content: systemtContent,
                },
                {
                    role: "user",
                    content: `Existing ${type}:\n${cssString}\n\nUser Request: ${promptRequest}`
                }
            ]
        };

        jQuery.ajax({
            type: 'POST',
            url: openai_ajax_req.ajax_url,
            data: {
                action: 'openai_ajax_function',
                nonce: openai_ajax_req.nonce
            },
            success: function(response) {
                const fetchDescription = async () => {
                    const rawResponse = await fetch('https://api.openai.com/v1/chat/completions', {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                            'Authorization' : 'Bearer ' + response,
                        },
                        body: JSON.stringify(requestBody)
                    });
 
                    if(!rawResponse.ok){
                        const statusText = rawResponse.status === 401 ? "Unauthorized. Double-check you correctly inserted the OpenAI API key inside the Theme Settings." : rawResponse.statusText;
                        self.insertErrorMessage('brxcCSSOverlay', false, '#brxcCSSOverlay', `${rawResponse.status}: ${statusText}`);
                        //target.classList.remove('disable');
                    } else {
                        // Create a reader to read the streamed response
                        const reader = rawResponse.body.getReader();
                        const decoder = new TextDecoder();
                        let newCssCode = '';
                
                        // Function to handle each chunk of data
                        const processChunk = async () => {
                            const { done, value } = await reader.read();
                            if (done) {
                                // All chunks have been read
                                return;
                            }
                
                            // Decode and parse the JSON chunk
                            const chunkText = decoder.decode(value);


                            // Split the chunk text into lines and process each one
                            const lines = chunkText.split('\n').filter(line => line.trim() !== '');
                            for (let line of lines) {
                                // Check if the line starts with "data: "
                                if (line.startsWith("data: ")) {
                                    const jsonLine = line.replace("data: ", "").trim();
                                    if (jsonLine !== "[DONE]") {
                                        try {
                                            // Parse the JSON and get the new CSS content
                                            const parsedData = JSON.parse(jsonLine);
                                            if (parsedData.choices && parsedData.choices[0].delta && parsedData.choices[0].delta.content) {
                                                let cssChunk = parsedData.choices[0].delta.content;
                                
                                                // Remove any code block symbols and formatting hints
                                                cssChunk = cssChunk.replace(/```/g, '');

                                                // Append the clean CSS content
                                                newCssCode += cssChunk;

                                                // Apply the new CSS live to the document
                                                const cmValue = self.advancedCSSStates.editAI ? newCssCode : cssString + newCssCode;
                                                cm.setValue(css_beautify(cmValue, { indent_size: 2 }));
                                            }
                                        } catch (e) {
                                            console.error('Failed to parse JSON chunk:', e, jsonLine);
                                        }
                                    }
                                }
                            }
                
                            // Continue reading the next chunk
                            processChunk();
                        };
                
                        // Start processing chunks
                        await processChunk();
                    }
                };
                fetchDescription();
            },
            error: function(response){
                self.vueGlobalProp.$_showMessage('Something went wrong with the OpenAI AJAX request: ' + response);
                //target.classList.remove('disable');
            }
        }); 
    },
    advancedCSSRenderValue: function(activeObj,value){
        const self = this;

        activeObj.lastModified = new Date(
            new Date().toLocaleString("en-US", { timeZone: self.globalSettings.timezone })
          ).getTime();
        activeObj.lastModifiedBy = bricksData.author;

        if(activeObj.id === 'at-page-css' ){
            return self.advancedCSSRenderPageCSS(activeObj, value);
            
        }

        if(activeObj.id === 'at-global-css' ){
            return self.advancedCSSRenderGlobalCSS(activeObj, value)
            
        }

        if(activeObj.id === 'at-child-css' ){
            return self.advancedCSSRenderChildCSS(activeObj, value)
            
        }

        if(activeObj.type === 'scssp' ){
            return self.advancedCSSRenderPartials(activeObj, value)
            
        }

        if(activeObj.category === 'wpcodebox' ){
            const x = document.querySelector('#bricks-builder-iframe').contentWindow;
            const files = x.document.querySelectorAll('.wpcb2-external-style');
            // External Link
            const externalLinks = Array.from(files).find(el => el.href.includes(`${activeObj.id}.css`));
            const override = {};
            if (!externalLinks){
                // Inline script
                override.Frontend = x.document.querySelector(`[wpcb-ids="${activeObj.id}"]`);
            }
            if (!override.Frontend){
                // AT override
                override.Frontend = x.document.querySelector(`#at-${activeObj.id}-css`);
            }
            return self.advancedCSSRenderCustomCSS(activeObj, value, override);
            
        }


        // Custom
        const x = document.querySelector('#bricks-builder-iframe').contentWindow;
        const override = {
            'Frontend': x.document.querySelector(`#at-${activeObj.id}-css`),
            'Builder': document.querySelector(`#at-${activeObj.id}-css`),
        };

        self.advancedCSSRenderCustomCSS(activeObj, value, override);
    },
    advancedCSSRenderPageCSS: function(activeObj, value){
        const self = this;
        const pageSettings = self.vueState.pageSettings;
        const baseKey = self.vueGlobalProp.$_getBaseBreakpointKey();

        const targetCss = baseKey === "desktop" ? "customCss" : `customCss:${baseKey}`;
        if (value === "") {
            self.advancedCSSRemoveError(document.querySelector('#advancedCSSUI__panel'));
            setTimeout(() => {
                delete pageSettings[targetCss];
                activeObj.contentCss = "";
            }, 10);
            if(activeObj.type !== "css") {
                setTimeout(() => {
                    delete pageSettings['customSass'];
                    activeObj.contentSass = "";
                }, 10);
            }
        } else if(value) {
            if(activeObj.type !== "css"){
                const dataOptions = { indent_size: 2 }
                pageSettings['customSass'] = value;
                activeObj.contentSass = value;

                // Compiled CSS
                const sass = self.sassInstances[0];
                sass.compile( self.advancedCSSStates.partials+value, function(result) {
                    if (result.status === 0) {
                        self.advancedCSSRemoveError(document.querySelector('#advancedCSSUI__panel'));
                        const strippedComment = self.helpers.removeCommentedCSS(result.text) !== '' ? self.helpers.removeCommentedCSS(result.text) : false;
                            if(strippedComment){
                                const compiledFromSass = css_beautify( strippedComment, dataOptions);
                                pageSettings[targetCss] = compiledFromSass;
                                activeObj.contentCss = compiledFromSass;
                            }
                    } else {
                        self.advancedCSSHandleError(result, document.querySelector('#advancedCSSUI__panel'))
                    }
                });
            } else {
                pageSettings[targetCss] = value;
                activeObj.contentCss = value;
            }
        }
    },

    advancedCSSRenderGlobalCSS: function(activeObj, value){
        const self = this;
        const globalSettings = self.vueState.globalSettings;
    
        if (value === "") {
            self.advancedCSSRemoveError(document.querySelector('#advancedCSSUI__panel'));
            setTimeout(() => {
                delete globalSettings['customCss'];
                activeObj.contentCss = "";
            }, 10);
            if (activeObj.type !== "css") {
                setTimeout(() => {
                    activeObj.contentSass = "";
                }, 10);
            }
        } else if(value){
            if (activeObj.type !== "css") {
                const dataOptions = { indent_size: 2 };
                activeObj.contentSass = value;
    
                // Compile the Sass code
                const sass = self.sassInstances[0];
                sass.compile(self.advancedCSSStates.partials + value, function(result) {
                    if (result.status === 0) {
                        self.advancedCSSRemoveError(document.querySelector('#advancedCSSUI__panel'));
                        const strippedComment = self.helpers.removeCommentedCSS(result.text) !== '' ? self.helpers.removeCommentedCSS(result.text) : false;
                        if (strippedComment) {
                            const compiledFromSass = css_beautify(strippedComment, dataOptions);
                            globalSettings['customCss'] = compiledFromSass;
                            activeObj.contentCss = compiledFromSass;
                        }
                    } else {
                        self.advancedCSSHandleError(result, document.querySelector('#advancedCSSUI__panel'));
                    }
                });
            } else {
                globalSettings['customCss'] = value;
                activeObj.contentCss = value;
            }
        }
    },
    
    advancedCSSRenderChildCSS: function(activeObj, value){
        const self = this;
        const x = document.querySelector('#bricks-builder-iframe').contentWindow;
        let override = x.document.querySelector('#at-child-override');

        // update object
        if(value === ""){
            activeObj.contentCss = "";
        } else if(value){
            activeObj.contentCss = value;
        }

        // Update style
        setTimeout(() => {
            // Update style
            if (value === "") {
                if(override) override.remove();
            } else if(value){
                if(!override) {
                    const newStyle = document.createElement('style');
                    newStyle.id = "at-child-override";
                    x.document.head.appendChild(newStyle);
                    override = x.document.querySelector('#at-child-override');
                }
                override.innerHTML = activeObj.contentCss;
            }
        },5)
    },
    advancedCSSRenderPartials: function(activeObj, value){
        const self = this;
  
        activeObj.contentSass = value;

        const partials = brxcAdvancedCSSDefault.filter(el => el && el.type === "scssp" && el.status == "1" && el.contentSass).map(el => el.contentSass).join('');

        const sass = self.sassInstances[0];
        sass.compile(partials, function(result) {
            if (partials === '' || result.status === 0) {
                self.advancedCSSRemoveError(document.querySelector('#advancedCSSUI__panel'));

                // Regenerate partials
                self.compilePartials(self.advancedCSSStates);
                self.compilePartialsVariables(self.advancedCSSStates);

                // Rerender custom sass files
                brxcAdvancedCSSDefault.filter(item => ['default', 'custom'].includes(item.category) && item.type === "scss" && item.contentSass !== '').forEach(item => {
                        self.advancedCSSRenderValue(item,item.contentSass);
                })
            } else {
                self.advancedCSSHandleError(result, document.querySelector('#advancedCSSUI__panel'))
            }
        });
        
    },
    advancedCSSRenderCustomCSS: function(activeObj, value, override){
        const self = this;
        const x = document.querySelector('#bricks-builder-iframe').contentWindow;
        // update object
        if(value === ""){
            // Empty value
            activeObj.contentCss = "";
            if(activeObj.type !== "css") activeObj.contentSass = "";
            self.advancedCSSRemoveError(document.querySelector('#advancedCSSUI__panel'));
        } else if(value){
            if(activeObj.type !== "css"){
                activeObj.contentSass = value;
                const dataOptions = { indent_size: 2 }

                const sass = self.sassInstances[0];
                sass.compile( self.advancedCSSStates.partials+value, function(result) {
                    
                    // Compiled CSS
                    if (result.status === 0) {
                        self.advancedCSSRemoveError(document.querySelector('#advancedCSSUI__panel'));
                        const strippedComment = self.helpers.removeCommentedCSS(result.text) !== '' ? self.helpers.removeCommentedCSS(result.text) : false;
                        if(strippedComment){
                            const compiledFromSass = css_beautify( strippedComment, dataOptions);
                            activeObj.contentCss = compiledFromSass;
                        }
                    } else {
                        self.advancedCSSHandleError(result, document.querySelector('#advancedCSSUI__panel'))
                    }
                });
                    
            } else {
                activeObj.contentCss = value;
            }
        }

        // Update style
        setTimeout(() => {
            for (let key in override){
                let currentOverride = override[key];
                if (value === "" || activeObj.status == "0" || activeObj[`enqueue${key}`] == "0") {
                    if(currentOverride) currentOverride.remove();
                } else {
                    if (!currentOverride || currentOverride.tagName.toLowerCase() === 'link') {
                        if (currentOverride) currentOverride.remove();
    
                        // if style is enabled
                        if(activeObj.status == "1"){
                            const newStyle = document.createElement('style');
                            newStyle.id = `at-${activeObj.id}-css`;
                            const doc = key === "Frontend" ? x.document : document;
                            doc.head.appendChild(newStyle);
                            currentOverride = doc.querySelector(`#at-${activeObj.id}-css`);
                        }
                    }
                    if(activeObj.status == "1" && currentOverride) {
                        
                        currentOverride.innerHTML = activeObj.contentCss 
                    } else if(activeObj.status == "0" && currentOverride) {
                        currentOverride.remove();
                    }
                    
                }
            }
        }, 5)
    },
    advancedCSSHandleError: function(result, wrapper){
        if(!wrapper) return;

        const messageWrapper = wrapper.querySelector('.brxc-error-handling');
        if(!messageWrapper) return;

        messageWrapper.innerHTML = `Error: ${result.message}`;
        messageWrapper.classList.remove('success');
        messageWrapper.classList.add('visible')
        messageWrapper.classList.add('error')

    },
    advancedCSSRemoveError: function(wrapper){
        if(!wrapper) return;

        const errorWrapper = wrapper.querySelector('.brxc-error-handling.error');
        const messageWrapper = wrapper.querySelector('.brxc-error-handling');
        if(!errorWrapper || !messageWrapper) return;

        messageWrapper.classList.remove('error');
        messageWrapper.innerHTML = 'CSS correctly compiled and saved!';
        messageWrapper.classList.add('success');
    },
    regenerateAdvancedCSS: async function(target) {
        const self = this;
        if(target) target.classList.add('disable');
    
        // Compile partials
        self.compilePartials(self.advancedCSSStates);
        self.compilePartialsVariables(self.advancedCSSStates);
    
        const renderPromises = [];
    
        brxcAdvancedCSSDefault.filter(item => item && ['custom','at framework'].includes(item.category) && item.type !== "recipe").forEach(item => {
            item.hasChanged = true;
    
            // SASS files
            if (item.type === "scss" && item.contentSass) {
                renderPromises.push(self.advancedCSSRenderValue(item, item.contentSass));
    
            // CSS files
            } else if (item.contentCss && item.contentCss) {
                renderPromises.push(self.advancedCSSRenderValue(item, item.contentCss));
            }
        });
    
        await Promise.all(renderPromises);
    
        self.saveAdvancedCSS(target);
    },
    saveAdvancedCSS: function(target){
        const self = this;
        if(target) target.classList.add('disable');
        const settings = brxcAdvancedCSSDefault.filter(el => el 
            && !el.id.startsWith('acss_')
            && !el.id.startsWith('php_recipe_')
            && !el.id.startsWith('community_recipe')
            && !el.id.startsWith('imported_css_')
        )
        jQuery.ajax({
            url: openai_ajax_req.ajax_url,
            data: {
                action: 'save_advanced_css_ajax_function',
                nonce: openai_ajax_req.nonce,
                advanced_css: settings, 
            },
            method: "POST",
            success: function(data) {
                if(self.sassInstances.length < 1 && self.globalSettings.classFeatures.advancedCSSEnableSass) self.createSassInstance("advancedCss");

                self.recompileSASStoCSS(self.vueState.globalClasses, 'globalClasses')
                    .then(() => self.recompileSASStoCSS(Array.from(self.vueState[self.helpers.getTemplateType()]), 'content'))
                    .then(() => setTimeout(() => {
                        if(target) target.classList.remove('disable');
                        self.vueGlobalProp.$_savePost();
                        brxcAdvancedCSSDefault.filter(el => el && el.hasChanged === true).forEach(el => {
                            delete el.hasChanged;
                        });
                        self.advancedCSSCat();
                    }, 500))
                    .catch(error => {
                        if(target) target.classList.remove('disable');
                        self.vueGlobalProp.$_showMessage('An error occurred during the CSS recompilation process');
                        console.log("An error occurred during the CSS recompilation process", error);
                    });
            },
            error: function(data) {
                if(target) target.classList.remove('disable');
                console.log("Error fetching data from wp_options table", data);
                self.vueGlobalProp.$_showMessage('Abort: An error occured - the CSS has NOT been saved Correctly!')
            }
        });
    },
    recompileSASStoCSS: function(arr, type){
        const self = this;
        return new Promise((resolve, reject) => {
            try {
                const partials = brxcAdvancedCSSDefault.filter(el => el && el.type === "scssp");
                if(!partials || partials.length === 0) return resolve();

                const changed = brxcAdvancedCSSDefault.filter(el => el && el.hasChanged === true);
                if(!changed || changed.length === 0) return resolve();

                const hasCustomSass = (settings) => Object.keys(settings).some(key => key.startsWith('_cssCustomSass'));

                const clsWithCustomCSS = arr.filter(el => el && el.hasOwnProperty('settings') && hasCustomSass(el.settings))
                if(!clsWithCustomCSS || clsWithCustomCSS.length === 0) return resolve();

                const newPartial = partials.map(el => el.contentSass).join(' ');
                clsWithCustomCSS.forEach(cls => {
                    const settings = cls.settings;
                    
                    Object.keys(settings).filter(key => key.startsWith('_cssCustomSass')).forEach(key => {
                        const value = settings[key];
                        
                        const sass = self.sassInstances[0];
                        sass.compile(newPartial + value, function(result) {
                            if (result.status === 0) {
                                const strippedComment = self.helpers.removeCommentedCSS(result.text);
                                if (strippedComment !== '') {
                                    const compiledFromSass = css_beautify(strippedComment, { indent_size: 2 });
                                    settings[key.replace('_cssCustomSass', '_cssCustom')] = compiledFromSass;

                                    //Modified
                                    if (type === "globalClasses") self.helpers.saveChanges(type, cls.id);
                                }
                            }
                        });
                    });
                }); 
                resolve();
            } catch (error) {
                reject(error);
            }
        });
    },
    setClassShortcuts: function(){
        const self = this;

        if(!self.builderStates.isElementActive) return;

        Promise.resolve().then(() => {
            // Const
            const activeClasses = document.querySelector('#bricks-panel-element-classes .active-class, #bricks-panel-element-classes .active-selector .actions-wrapper');
            const x = document.querySelector('#bricks-builder-iframe').contentWindow;
            if(!activeClasses) return;

            const copyToClipboardIcon = activeClasses.querySelector('.copy-class-icon'); // Copy to clipboard icon
            const cloneClassIcon = activeClasses.querySelector('.clone-class-icon'); // Clone Class Icon
            const importSylesicon = activeClasses.querySelector('.copy-class-to-id-icon'); // Import Styles from ID
            const exportStylesIcon = activeClasses.querySelector('.copy-id-to-class-icon'); // Export Styles to the ID
            const classContextualMenuIcon = activeClasses.querySelector('.class-contextual-menu-icon'); // Class Contextual Menu 
            const countClassesIcon = activeClasses.querySelector('.num-class-icon'); // Count Classes
            const plainClassesIcon = activeClasses.querySelector('.plain-classes-icon'); // Plain Classes

            // Remove Icon
            if(countClassesIcon) countClassesIcon.remove();
            if(copyToClipboardIcon) copyToClipboardIcon.remove();
            if(cloneClassIcon) cloneClassIcon.remove();
            if(exportStylesIcon) exportStylesIcon.remove();
            if(importSylesicon) importSylesicon.remove();
            if(classContextualMenuIcon) classContextualMenuIcon.remove();
            if(plainClassesIcon) plainClassesIcon.remove();



            // Icons that are always added - START
            // Plain Classes
            if(Object.values(self.globalSettings.elementShortcutIcons).includes("plain-classes")){
                const balloon = self.globalSettings.openPlainClassByDefault ? false : 'Plain Classes';
                const balloonPos = self.globalSettings.openPlainClassByDefault ? false : 'top-right';
                self.addIconToFields('div','at-icon plain-classes-icon', false, balloon, balloonPos, 'event.preventDefault();event.stopPropagation();ADMINBRXC.openPlainClassesModal(event, "#brxcPlainClassesOverlay")', false,  "<span class='symbol counter'>P</span>", activeClasses, 'child');
            }

            // Icons only available on Element ID
            if(!self.builderStates.isClassActive){

                // Export Styles to ID
                if(Object.values(self.globalSettings.elementShortcutIcons).includes("export-styles-to-class")){
                    self.addIconToFields('div','at-icon copy-id-to-class-icon', false, 'Export the styles to a class', 'top-right', 'ADMINBRXC.exportIDStylestoClass()', false,  "<span class='symbol counter'><i class='fas fa-file-export' title='fas fa-file-export'></i></span>", activeClasses, 'child');
                    const newExportStylesIcon = activeClasses.querySelector('.copy-id-to-class-icon');
                    newExportStylesIcon.addEventListener('click', (e) => e.stopPropagation());
                }
            }

            // Icons only available on classes
            if(self.builderStates.isClassActive){

                // Count Classes
                const cls = x.document.querySelectorAll('.' + self.vueState.activeClass.name);
                if(Object.values(self.globalSettings.classFeatures).includes("count-classes") && cls.length > 0){
                    
                    self.addIconToFields('div','at-icon num-class-icon', false, 'Used class on page', 'top-right', '', false,  `<span class="symbol counter">${cls.length}</span>`, activeClasses, 'child');
                    const newCountClassesIcon = activeClasses.querySelector('.num-class-icon');

                    let i = 0;
                    newCountClassesIcon.addEventListener('click', (e) => {
                        e.stopPropagation();
                        cls[i].scrollIntoView({ behavior: "smooth"});
                        (i === cls.length - 1) ? i = 0 : i++;
                    })
                }

                // Copy Class to clipboard
                if(Object.values(self.globalSettings.elementShortcutIcons).includes("copy-class-to-clipboard")) {
                    self.addIconToFields('div','at-icon copy-class-icon', false, 'Copy Class to Clipboard', 'top-right', `ADMINBRXC.copytoClipboardSimple('${self.vueState.activeClass.name}','"${self.vueState.activeClass.name}" successfully copied to clipboard')`, false,  '<span class="symbol counter"><i class="fas fa-clipboard"></i></span', activeClasses, 'child');
                    const newCopyToClipboardIcon = activeClasses.querySelector('.copy-class-icon');
                    newCopyToClipboardIcon.addEventListener('click', (e) => e.stopPropagation());
                }

                // Import Styles from ID
                if(Object.values(self.globalSettings.elementShortcutIcons).includes("export-styles-to-class") && !self.vueGlobalProp.$_isLocked(self.vueState.activeClass.id)){
                    self.addIconToFields('div','at-icon copy-class-to-id-icon', false, 'Import styles from the ID element', 'top-right', '', false,  "<span class='symbol counter'><i class='fas fa-file-import' title='fas fa-file-import'></i></span>", activeClasses, 'child');
                    const newimportSylesicon = activeClasses.querySelector('.copy-class-to-id-icon');
                    newimportSylesicon.addEventListener('click', (e) => {
                        e.stopPropagation();
                        self.vueState.brxcShowImportInput = true;
                        newimportSylesicon.remove();
                    })

                    if (self.vueState.brxcShowImportInput === true){
                        const newimportSylesiconHTML = `<span class='symbol counter'><i class='fas fa-file-import' title='fas fa-file-import'></i></span>`;
                        newimportSylesicon.innerHTML = `<span class='symbol counter'><i class='fas fa-check' title='fas fa-check'></i></span>`;
                        newimportSylesicon.setAttribute("onClick", "ADMINBRXC.importIDStylestoClass();ADMINBRXC.vueState.brxcShowImportInput = false");
                        newimportSylesicon.setAttribute("data-balloon", "Confirm?");
                        setTimeout(() => {
                            newimportSylesicon.innerHTML = newimportSylesiconHTML;
                            self.vueState.brxcShowImportInput = false
                        }, 2000)
                    }
                }

                // Clone Class
                if(Object.values(self.globalSettings.elementShortcutIcons).includes("clone-class")){
                    self.addIconToFields('div','at-icon clone-class-icon', false, 'Clone class', 'top-right', 'ADMINBRXC.cloneClass()', false,  '<span class="symbol counter"><i class="fa-solid fa-clone"></i></span', activeClasses, 'child');
                    const newCloneClassIcon = activeClasses.querySelector('.clone-class-icon');
                    newCloneClassIcon.addEventListener('click', (e) => e.stopPropagation());
                }
            }
            
            // Icons that are always added - END
            // Class Contextual Menu
            if(Object.values(self.globalSettings.elementShortcutIcons).includes("class-contextual-menu")){
                self.addIconToFields('div','class-contextual-menu-icon', false, 'Class Contextual Menu', 'top-right', 'event.stopPropagation();ADMINBRXC.openContextualMenu(event, () => {return ADMINBRXC.classContextualMenu()})', false,  '<span class="bricks-svg-wrapper"><svg version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg" style="rotate: 90deg;"><path d="M3,9.5l-6.55671e-08,-1.77636e-15c-0.828427,-3.62117e-08 -1.5,-0.671573 -1.5,-1.5c3.62117e-08,-0.828427 0.671573,-1.5 1.5,-1.5l-6.55671e-08,1.77636e-15c0.828427,-3.62117e-08 1.5,0.671573 1.5,1.5c3.62117e-08,0.828427 -0.671573,1.5 -1.5,1.5Zm5,0l-6.55671e-08,-1.77636e-15c-0.828427,-3.62117e-08 -1.5,-0.671573 -1.5,-1.5c3.62117e-08,-0.828427 0.671573,-1.5 1.5,-1.5l-6.55671e-08,1.77636e-15c0.828427,-3.62117e-08 1.5,0.671573 1.5,1.5c3.62117e-08,0.828427 -0.671573,1.5 -1.5,1.5Zm5,0l-6.55671e-08,-1.77636e-15c-0.828427,-3.62117e-08 -1.5,-0.671573 -1.5,-1.5c3.62117e-08,-0.828427 0.671573,-1.5 1.5,-1.5l-6.55671e-08,1.77636e-15c0.828427,-3.62117e-08 1.5,0.671573 1.5,1.5c3.62117e-08,0.828427 -0.671573,1.5 -1.5,1.5Z" fill="currentColor" fill-rule="evenodd"></path></svg></span>', activeClasses, 'child');
            }
            
        
        });
    },
    // hideElementInBuilderStates: {
    //     els: [],
    //     builder: [],
    //     frontend: [],
    // },
    // hideElementInBuilderCSS: function(){
    //     const self = this;
    //     const x = document.querySelector('#bricks-builder-iframe').contentWindow;
    //     let xStylesheet = x.document.querySelector('#brxc-hide-elements-in-builder');
    //     if(!xStylesheet){
    //         const el = document.createElement('style');
    //         el.id = 'brxc-hide-elements-in-builder';
    //         const xHead = x.document.head;
    //         xHead.appendChild(el);
    //     }
    //     xStylesheet = x.document.querySelector('#brxc-hide-elements-in-builder');

    //     const css = self.hideElementInBuilderStates.builder.length > 0 ? `${self.hideElementInBuilderStates.builder.map(el => `[data-id="${el}"]`).join(',')}{display:none !important}` : '';
    //     xStylesheet.innerHTML = css;
    // },
    // hideElementInBuilder: function(){
    //     const self = this;
    //     const structureEls = document.querySelectorAll('#bricks-structure li.element');
    //     if(structureEls.length < 1) return;

    //     let hasChanges = false;

    //     structureEls.forEach(el => {
    //         const elId = el.dataset.id;
    //         const elObj = self.helpers.getElementObject(elId);
    //         if(!elObj) return;

    //         // builder
    //         if(elObj?.settings?.hasOwnProperty('_hideElementBuilder')){
    //             if(!self.hideElementInBuilderStates.builder.includes(elId)) {
    //                 self.hideElementInBuilderStates.builder.push(elId);
    //                 hasChanges = true;
    //             }
    //             el.setAttribute('data-builder-hidden', 'true');
    //         } else {
    //             const index = self.hideElementInBuilderStates.builder.indexOf(elId);
    //             if(index > -1) {
    //                 self.hideElementInBuilderStates.builder.splice(index, 1);
    //                 hasChanges = true;
    //             }
    //             el.removeAttribute('data-builder-hidden');
    //         }
            
    //         // frontend
    //         if(elObj.settings.hasOwnProperty('_hideElementFrontend')){
    //             if(!self.hideElementInBuilderStates.frontend.includes(elId)) {
    //                 self.hideElementInBuilderStates.frontend.push(elId);
    //                 hasChanges = true;
    //             }
    //             el.setAttribute('data-frontend-hidden', 'true');
    //         } else {
    //             const index = self.hideElementInBuilderStates.frontend.indexOf(elId);
    //             if(index > -1) {
    //                 self.hideElementInBuilderStates.frontend.splice(index, 1);
    //                 hasChanges = true;
    //             }
    //             el.removeAttribute('data-frontend-hidden');
    //         }
    //     })
    //     if(hasChanges) self.hideElementInBuilderCSS();
    // },
    activateTagManagerDropdown: function(id){
        const self = this;
        // if(id === self.structureStates.activeDropdown){
        //     self.structureStates.activeDropdown = false;
        // } else {
        //     self.structureStates.activeDropdown = id;
        // }
        self.structureStates.activeDropdown = id
        self.vueState.rerenderControls = Date.now();
    },
    structureStates: {
        activeDropdown: false,
    },
    runStructureHighlights: function() {
        const self = this;
        const settings = self.structurePanelStates.tweaks;
        const structure = document.querySelector('#bricks-structure');
        if (!structure) return;

        const x = document.querySelector('#bricks-builder-iframe').contentWindow;
        const iframeElements = x.document.querySelectorAll('.brxc-active-class');
        const draggableCls = ['bricks-draggable-item','bricks-draggable-handle'];
    
        const els = structure.querySelectorAll('.element');
        if (els.length < 1) return;

        const condition = {
            styleAndClassesIndicators: settings.includes("styles-and-classes-indicators"),
            highlightClasses: settings.includes("highlight-classes"),
            highlightNestable: settings.includes("highlight-nestable-elements"),
            expandChildren: settings.includes("expand-all-children"),
            notes: self.noteStates.active !== "none",
            links: settings.includes("link"),
            tags: true,
            lockOrder: true,
            hideRemove: settings.includes('hide-remove-highlights'),
        }
    
        function returnAction(el){
            let action = el.querySelector('ul.actions');
            if (action) return action;

            el.querySelector(".title").insertAdjacentHTML("afterend", `<ul class="actions"></ul>`);
            return el.querySelector('ul.actions');
        }

        // Remove Class in the iframe
        iframeElements.forEach(el => el.classList.remove('brxc-active-class'))

        // Body Classes
        condition.tags && self.elementsTagStates.mode === 'developer' ? document.body.classList.add('at-tag-btn-color') : document.body.classList.remove('at-tag-btn-color') 

        // Iframe
        const xElsHaveClass = x.document.querySelectorAll('.brxc-active-class');
        xElsHaveClass.forEach(el => el.classList.remove('brxc-active-class'));
        if(condition.highlightClasses && self.builderStates.isClassActive){
            const xactiveEls = x.document.querySelectorAll('.' + self.vueState.activeClass.name);
            xactiveEls.forEach(el => el.classList.add('brxc-active-class'));
        }
        
        // Loop into the Structure elements
        els.forEach(el => {
            const elID = el.dataset.id;
            const elementObject = self.helpers.getElementObject(elID);
            const action = returnAction(el);

            if(typeof elementObject !== "object" || elementObject === null) {
                return console.log('Error: no object found.');
            }

            const elementSettings = elementObject.settings
            
            // Style & Class Indicators
            el.removeAttribute('data-sci');
            if (condition.styleAndClassesIndicators) {
            
                const hasStyle = self.helpers.elementHasStyle(elementSettings);
                const hasClass = self.helpers.elementHasClass(elementSettings);
            
                if (hasStyle && hasClass) {
                    el.setAttribute('data-sci', 'both');
                } else if (hasStyle) {
                    el.setAttribute('data-sci', 'style');
                } else if (hasClass) {
                    el.setAttribute('data-sci', 'class');
                }
            } 

            // Highlight Classes
            el.removeAttribute('data-active-class')
            if(condition.highlightClasses && self.builderStates.isClassActive && self.vueGlobalProp.$_getElementGlobalClassNames(elementObject.settings).includes(self.vueState.activeClass.name)){
                el.setAttribute('data-active-class', 'true');   
            }

            // Highlight Nestable elements
            el.removeAttribute('data-nestable');
            if (condition.highlightNestable && self.nestableElements.includes(elementObject.name)){
                el.setAttribute('data-nestable', 'true');
            }

            // Expand Children
            
            const toggle = el.querySelector('.toggle');
            if (toggle) {

                const existingExpand = action?.querySelector('.action.expand, .action.collapse');
                if (existingExpand) existingExpand.remove();
                
                if (condition.expandChildren) {
                    const isOpened = toggle.dataset.name === "arrow-down";
                    const parent = action.closest('[data-id]');
                    const toggles = parent.querySelectorAll('.bricks-svg-wrapper.toggle');
                    if (toggles.length > 0) {
                        const liClass = isOpened ? 'collapse' : 'expand';
                        const liLabel = isOpened ? 'Collapse' : 'Expand';
                        const liFunction = isOpened ? 'ADMINBRXC.collapseAllChildren(event)' : 'ADMINBRXC.expandAllChildren(event)';
                        const liSpan = isOpened ? 
                            `<span class="bricks-svg-wrapper"><svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="bricks-svg"><path d="m23.25 0.748 -9 9" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path><path d="m9.75 20.998 0 -6.75 -6.75 0" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path><path d="m14.25 2.998 0 6.75 6.75 0" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path><path d="m9.75 14.248 -9 9" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path></svg></span>` : 
                            `<span class="bricks-svg-wrapper"><svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="bricks-svg"><path d="m9.75 14.248 -9 9" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path><path d="m23.25 7.498 0 -6.75 -6.75 0" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path><path d="m0.75 16.498 0 6.75 6.75 0" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path><path d="m23.25 0.748 -9 9" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path></svg></span>`;
                        const li = document.createElement('li');
                        li.className = `action ${liClass}`;
                        li.title = liLabel;
                        li.setAttribute('onclick', liFunction);
                        li.innerHTML = liSpan;
                        action.prepend(li);
                    };
                }
            }
            

            // Notes
            const existingNote = action?.querySelector('.action.notes');
            if(condition.notes && elementSettings.hasOwnProperty(self.noteStates.active) ) {
                if(!existingNote){
                    const liSpan = `<span class="bricks-svg-wrapper"><i class="ti-comment-alt"></i></span>`;
                    const li = document.createElement('li');
                    li.className = `action notes`;
                    li.setAttribute('onmouseenter', `ADMINBRXC.showNotes(event, ${JSON.stringify(elementSettings[self.noteStates.active])})`);
                    li.setAttribute('onmouseleave', `ADMINBRXC.hideNotes()`)
                    li.innerHTML = liSpan;
                    action.append(li);
                }
            } else {
                if (existingNote) existingNote.remove();
            }

            // Link
            const existingLink = action?.querySelector('.action.link');
            if(condition.links && elementSettings.hasOwnProperty('link')) {
                if(!existingLink){
                    const liSpan = `<span class="bricks-svg-wrapper"><i class="ti-link"></i></span>`;
                    const li = document.createElement('li');
                    li.className = `action link`;
                    li.title = 'Has a link';
                    li.innerHTML = liSpan;
                    action.append(li);
                }
            } else {
                if (existingLink) existingLink.remove();
            }

            // Show Tags
            if (condition.tags) {
                const wrapper = el.querySelector('.brxc-tag-btn-wrapper')
                if(self.elementsTagStates.mode === '') {
                    wrapper?.remove();
                } else {
                    if(!wrapper || elID === elementObject.id) {
                        wrapper?.remove();
                        const tag = self.helpers.getElementTag(elementObject);
                        if(tag) {
                            const title = el.querySelector('.title .icon')
                            self.helpers.createTagBtn(title, tag);
                        }
                    }
                }
            }

            // Lock Elements Order
            if(condition.lockOrder){
                self.lockDraggableElementsStates.active == 1 ? el.classList.remove(...draggableCls) : el.classList.add(...draggableCls) ;

            }

            el.removeAttribute('data-builder-hidden')
            el.removeAttribute('data-frontend-hidden');
            // Hide/Remove Highlights
            if(condition.hideRemove){

                // Hide builder
                if(elementSettings.hasOwnProperty('_hideElementBuilder') && elementSettings._hideElementBuilder === true){
                    el.setAttribute('data-builder-hidden', 'true');
                }

                // Hide frontend
                if(elementSettings.hasOwnProperty('_hideElementFrontend') && elementSettings._hideElementFrontend === true){
                    el.setAttribute('data-frontend-hidden', 'true');
                }
            }
        })

        self.structureStates.activeDropdown = false;
        self.vueState.brxc.tagDropdownActive = false;
        self.showTagInStructurePanelCustomTags();

        
    },
    noteStates: {
        active : 'adminNotes',
    },
    showNotes: function(event,txt){
        const element = event.target;
        const rect = element.getBoundingClientRect();
        const div = document.createElement('div');
        div.className = `brxc-notes`;
        div.innerHTML = `<span>${txt}</span>`;
        div.style.top = `${parseInt(rect.bottom)}px`; 
        div.style.left = `calc(${parseInt(rect.right)}px - 216px)`; 
        document.body.append(div);

    },  
    hideNotes: function(){
        const existingNotes = document.querySelectorAll('.brxc-notes');
        if(existingNotes) existingNotes.forEach(el => el.remove());
    },
    // setCodeElementIcons: function(){
    //     const self = this;
    //     if(!self.builderStates.isElementActive || self.vueState.activePanelTab !== "content" || self.vueState.showInteractions === true || self.vueState.showConditions === true) return;

    //     const elementObj = self.builderStates.activeElement;
    //     if(elementObj.name !== "code") return;

    //     Promise.resolve().then(() => {
    //         const panel = document.querySelector('#bricks-panel')
    //         const controls = panel.querySelectorAll(`.control.control-code .header .actions`);
    //         controls.forEach(control => {
    //             const existingIcon = control.querySelector('#brxc-expand-code-element');
    //             if(existingIcon) return;

    //             const el = document.createElement('SPAN');
    //             el.id = 'brxc-expand-code-element';
    //             el.setAttribute('data-balloon', 'Full Screen');
    //             el.setAttribute('data-balloon-pos', 'top-right');
    //             el.setAttribute('onclick', `ADMINBRXC.codeElementFullScreen(this)`);
    //             el.classList.add('bricks-svg-wrapper');
    //             el.innerHTML = `<i class="fas fa-display"></i>`;
    //             control.appendChild(el);
    //         })
    //     })
    // },
    codeElementFullScreen: function(icon){
        const control = icon.closest('[data-controlkey]');
        if(!control) return;

        const cm = control.querySelector('.CodeMirror').CodeMirror;
        if(!cm) return;

        control.classList.contains('at-full-screen') ? control.classList.remove('at-full-screen') : control.classList.add('at-full-screen');

        Promise.resolve().then(() => {
            cm.refresh();
        })
    },
    syncLabelwithGlobalClassStates: {
        active: false,
        globalClasses: false,
    },
    syncLabelwithGlobalClass: function(){
        const self = this;
        if(!self.builderStates.isElementActive) return self.syncLabelwithGlobalClassStates.active = false;

        const elementObj = self.builderStates.activeElement;
        if(!elementObj) return;

        if(elementObj.hasOwnProperty('label')) return self.syncLabelwithGlobalClassStates.active = false;

        // has no global class
        if(!elementObj.settings.hasOwnProperty('_cssGlobalClasses') || elementObj.settings._cssGlobalClasses.length === 0){
            self.syncLabelwithGlobalClassStates.globalClasses = false;
        }

        // has global class
        if(elementObj.settings.hasOwnProperty('_cssGlobalClasses') && elementObj.settings._cssGlobalClasses.length > 0){
            if(self.syncLabelwithGlobalClassStates.active && elementObj.id === self.syncLabelwithGlobalClassStates.active && self.syncLabelwithGlobalClassStates.globalClasses === false){
                const cls = self.vueState.globalClasses.find(el => el.id === elementObj.settings._cssGlobalClasses[0]);
                if(!self.vueGlobalProp.$_isLocked(cls.id)){
                    elementObj.label = self.helpers.classNametoLabel(cls.name);
                }
            }
            self.syncLabelwithGlobalClassStates.globalClasses = elementObj.settings._cssGlobalClasses
        }

        // update active ID
        if(elementObj.id !== self.syncLabelwithGlobalClassStates.active){
            self.syncLabelwithGlobalClassStates.active = elementObj.id;
        }

    },
    
    quickSearchStates: {
        active: 'all',
        maxResults: 3,
    },
    openQuickSearch: function(){
        const self = this;
        const existing = document.querySelector('#brxcQuickSearch');
        if(existing) existing.remove();
        const main = document.querySelector('.brx-body.main');
        if(!main) return;

        let keySequence = [];

        self.quickSearchResetStates();
        self.quickSearchsetActiveElement();

        const a = document.createElement('div');
        a.id = "brxcQuickSearch";
        a.innerHTML = `<div class="brxc-overlay__search-box">
                            <div class="brxc-overlay__close-btn" onclick="this.parentElement.parentElement.remove()">
                                <i class="bricks-svg ti-close"></i>
                            </div>
                            <input type="text" class="iso-search" name="typography-search" placeholder="Search anything" data-type="textContent" oninput="ADMINBRXC.quickSearchStates.search = this.value;ADMINBRXC.renderQuickSearchResults();">
                            <div class="iso-search-icon">
                                <i class="bricks-svg ti-search"></i>
                            </div>
                            <div class="iso-reset" data-balloon="Reset" data-balloon-pos="left" onclick="ADMINBRXC.quickSearchStates.search = '';ADMINBRXC.renderQuickSearchResults();this.previousElementSibling.previousElementSibling.value = '';">
                                <i class="bricks-svg fas fa-undo"></i>
                            </div>
                        </div>
                        <div id="brxcQuickSearchResults"></div>`

        main.appendChild(a);
        const input = main.querySelector('#brxcQuickSearch .brxc-overlay__search-box input');
        const end = input.value.length;
        input.setSelectionRange(end, end);
        input.focus();

        // Listeners
        a.addEventListener('mousedown', (e) => {
            self.quickSearchHandleListeners(e, e.target);
            setTimeout(() => self.quickSearchRefocus(), 0);
        })
        a.addEventListener('keydown', (e) => {
            const allMenus = Array.from(a.querySelectorAll('#brxcQuickSearchHeader li.active'));
            const highlight = a.querySelector('#brxcQuickSearchHeader li.highlight');
            const allTypes = Array.from(a.querySelectorAll('#brxcQuickSearchResults [data-type]'));
            const selected = a.querySelector('#brxcQuickSearchResults [data-type].selected');
        
            const moveHighlight = (items, current, direction) => {
                let currentIndex = items.indexOf(current);
                let nextElement = '';
                current.classList.remove('highlight');
                if (direction === 'left') {
                    nextElement = currentIndex === 0 ? items[items.length - 1] : items[currentIndex - 1];
                } else {
                    nextElement = currentIndex === items.length - 1 ? items[0] : items[currentIndex + 1];
                }
                self.quickSearchStates.active = nextElement.dataset.active;
                self.quickSearchStates[`menu${nextElement.dataset.active}`] = true;
                self.renderQuickSearchResults();
                setTimeout(() => self.quickSearchRefocus(), 0);

            };
        
            const moveSelection = (items, current, direction) => {
                let index = items.indexOf(current);
                let nextElement = ''
                current.classList.remove('selected');
                if (direction === 'up') {
                    nextElement = index === 0 ? items[items.length - 1] : items[index - 1];
                } else {
                    nextElement = index === items.length - 1 ? items[0] : items[index + 1];
                }
                nextElement.classList.add('selected');
            };
        
            // Menus
            if (e.key === "ArrowLeft" && highlight) {
                e.preventDefault();
                moveHighlight(allMenus, highlight, 'left');
        
            } else if ((e.key === "ArrowRight" || (e.shiftKey && e.key === 'Tab')) && highlight) {
                e.preventDefault();
                moveHighlight(allMenus, highlight, 'right');
        
            // Data-type
            } else if (e.key === "Enter" && selected) {
                self.quickSearchHandleListeners(e, selected);
                setTimeout(() => self.quickSearchRefocus(), 0);
        
            } else if (e.key === "ArrowUp" && selected) {
                e.preventDefault();
                moveSelection(allTypes, selected, 'up');
        
            } else if ((e.key === "ArrowDown" || e.key === 'Tab') && selected) {
                e.preventDefault();
                moveSelection(allTypes, selected, 'down');
            } else if(e.ctrlKey){
                if (!isNaN(e.key)) {
                    keySequence.push(e.key);
        
                    // Keep only the last two digits
                    if (keySequence.length > 2) {
                        keySequence.shift();
                    }
        
                    // Convert array to a string (e.g., ["0", "1"] → "01")
                    let pressedKeys = keySequence.join('');

                    const action = document.querySelector(`#brxcQuickSearchResults [data-kb="${pressedKeys}"]`);
                    if(action) {
                        keySequence = []; 
                        e.preventDefault();
                        e.stopPropagation();
                        self.quickSearchHandleListeners(e, action.parentElement);
                        setTimeout(() => self.quickSearchRefocus(), 0);
                    }
                }
            }
        });

        function handleEscapeKey(e) {
            if (e.key === "Escape") {
                const quickSearch = document.querySelector('#brxcQuickSearch');
                if(quickSearch) quickSearch.remove();
                window.removeEventListener('keydown', handleEscapeKey);
                x.window.removeEventListener('keydown', handleEscapeKey);
            }
        }
        const x = document.querySelector('#bricks-builder-iframe').contentWindow;
        window.addEventListener('keydown', handleEscapeKey);
        x.window.addEventListener('keydown', handleEscapeKey);      
    },
    
    quickSearchResetStates: function(){
        const self = this;
        self.quickSearchStates.search = '';
        self.quickSearchStates.activeControl = false;
        self.quickSearchStates.menuGlobalClasses = false;
        self.quickSearchStates.menuGlobalVariables = false;
        self.quickSearchStates.menuThemeVariables = false;
        self.quickSearchStates.menuElements = false;
        self.quickSearchStates.menuComponents = false;
        self.quickSearchStates.menuStructure = false;
    },
    quickSearchsetActiveElement: function(){
        const self = this;
        const activeElement = document.activeElement;
        const tag = document.activeElement.tagName === "INPUT";
        const type = document.activeElement.type === "text";
        const structure = document.activeElement.closest('#bricks-structure');
        self.quickSearchStates.activeControl = activeElement && tag && type && !structure ? document.activeElement : false;
    },
    quickSearchRefocus: function(){
        const input = document.querySelector('#brxcQuickSearch .brxc-overlay__search-box input');
        if(!input) return;
        input.focus();
        input.setSelectionRange(0, input.value.length);
    },
    quickSearchHandleListeners: function(event, target){
        const self = this;
        switch(target.dataset.type){
            case 'more':
                self.quickSearchStates.active = target.dataset.cat;
                self.renderQuickSearchResults();
                break;
            case 'add-element':
                self.addElementtoStructure(event, target.dataset.name);
                break;
            case 'add-component':
                self.addComponenttoStructure(event, target.dataset.id, target.dataset.name);
                break;
            case 'jump-element':
                self.openElement(target.dataset.id);
                break;
            case 'add-class':
                const addClass = () => {
                    const element = self.builderStates.activeElement
                    const classId = target.dataset.id;
                    if (typeof element !== "undefined" && !element.hasOwnProperty('settings') || Object.getPrototypeOf(element.settings).length === 0) element.settings = {};
                    if (typeof element.settings !== "undefined" && !element.settings.hasOwnProperty('_cssGlobalClasses')) element.settings._cssGlobalClasses = []
                    if (typeof element.settings._cssGlobalClasses !== "undefined" && !element.settings._cssGlobalClasses.includes(classId)) element.settings._cssGlobalClasses.push(classId);
                }
                addClass();
                break;
            case 'add-new-class':
                const addNewClass = () => {
                    const newId = self.vueGlobalProp.$_generateId();
                    const clsName = self.helpers.formatForClasses(self.quickSearchStates.search);
                    self.vueState.globalClasses.push({
                        id: newId,
                        name: clsName,
                        settings: {},
                    })
                    self.helpers.saveChanges('globalClasses');
                    self.vueGlobalProp.$_showMessage(`Global Class "${clsName}" successfully created!`);

                    // Add Class to element
                    if(self.builderStates.isElementActive){
                        const element = self.builderStates.activeElement
                        if (typeof element !== "undefined" && !element.hasOwnProperty('settings') || Object.getPrototypeOf(element.settings).length === 0) element.settings = {};
                        if (typeof element.settings !== "undefined" && !element.settings.hasOwnProperty('_cssGlobalClasses')) element.settings._cssGlobalClasses = []
                        if (typeof element.settings._cssGlobalClasses !== "undefined" && !element.settings._cssGlobalClasses.includes(newId)) element.settings._cssGlobalClasses.push(newId);
                    }
                }
                addNewClass();
                break;
            case 'add-variable':
                if(self.quickSearchStates.activeControl){
                    self.quickSearchStates.activeControl.value = target.dataset.value;
                    self.quickSearchStates.activeControl.dispatchEvent(new Event('input'));

                }
            break;
            case 'add-new-global-variable':
                const addNewGlobalVariable = () => {
                    const newId = self.vueGlobalProp.$_generateId();
                    const varName = self.helpers.formatForClasses(self.quickSearchStates.search);
                    self.vueState.globalVariables.push({
                        id: newId,
                        name: varName,
                    })
                    self.helpers.saveChanges('globalVariables');
                    self.vueGlobalProp.$_showMessage(`Global Variable "--${varName}" successfully created!`);

                    // Add Variable to element
                    if(self.quickSearchStates.activeControl){
                        self.quickSearchStates.activeControl.value = `var(--${varName})`;
                        self.quickSearchStates.activeControl.dispatchEvent(new Event('input'));
                    }

                    // Open the Variable Manager
                    self.openModal({target: false, id: '#brxcCSSVariableManagerOverlay', callback: () => {
                        self.cssVariablesStates.search = "";
                        self.cssVariablesStates.view = "full"
                        self.setCSSVariableManager();
                    }});
                    setTimeout(() => {
                        const inputs = document.querySelectorAll('.brxc-global-variable-list input[type="text"].variable-value');
                        if(!inputs || inputs.length < 1) return;
                        const input = inputs[inputs.length - 1];
                        const end = input.value.length;
                        input.setSelectionRange(end, end);
                        input.focus();
                    }, 5)
                }
                addNewGlobalVariable();
            break;
            case 'add-new-theme-variable':
                const addNewThemeVariable = () => {
                    const newId = self.vueGlobalProp.$_generateId();
                    const varName = self.helpers.formatForClasses(self.quickSearchStates.search);
                    self.vueState.themeStyleSettings.general._cssVariables.push({
                        id: newId,
                        name: varName,
                    })
                    self.vueGlobalProp.$_showMessage(`Theme Variable "--${varName}" successfully created!`);

                    // Add Variable to element
                    if(self.quickSearchStates.activeControl){
                        self.quickSearchStates.activeControl.value = `var(--${varName})`;
                        self.quickSearchStates.activeControl.dispatchEvent(new Event('input'));
                    }

                    // Open the Variable Manager
                    self.openModal({target: false, id: '#brxcCSSVariableManagerOverlay', callback: () => {
                        self.cssVariablesStates.search = "";
                        self.cssVariablesStates.view = "full"
                        self.setCSSVariableManager();
                    }});
                    setTimeout(() => {
                        const inputs = document.querySelectorAll('.brxc-theme-variable-list input[type="text"].variable-value');
                        if(!inputs || inputs.length < 1) return;
                        const input = inputs[inputs.length - 1];
                        const end = input.value.length;
                        input.setSelectionRange(end, end);
                        input.focus();
                    }, 5)
                }
                addNewThemeVariable();
            break;
        }

    },
    renderQuickSearchResults: function(){
        const self = this;
        const canvas = document.querySelector('#brxcQuickSearchResults');
        if(!canvas) return;

        let content = '';
        let header = '';
        let count = {value: -1};
        if(self.quickSearchStates.active === "all" || self.quickSearchStates.active === "GlobalClasses") content += self.quickSearchGlobalClasses(count);
        if(self.quickSearchStates.active === "all" || self.quickSearchStates.active === "GlobalVariables") content += self.quickSearchGlobalVariables(count);
        if((self.quickSearchStates.active === "all" || self.quickSearchStates.active === "ThemeVariables") && self.helpers.isThemeVariableActive() && self.helpers.themeHasVariables()) content += self.quickSearchThemeVariables(count);
        if(self.quickSearchStates.active === "all" || self.quickSearchStates.active === "Elements") content += self.quickSearchElements(count);
        if(self.quickSearchStates.active === "all" || self.quickSearchStates.active === "Components") content += self.quickSearchComponents(count);
        if(self.quickSearchStates.active === "all" || self.quickSearchStates.active === "Structure") content += self.quickSearchStructure(count);

        if(content !== ''){
            header += '<ul id="brxcQuickSearchHeader">';
            header += `<li class="active${self.quickSearchStates.active === 'all' ? ' highlight' : ''}" data-active="all">All</li>`
            const cats = ["Global Classes","Global Variables","Theme Variables","Elements", "Components", "Structure"]
            cats.forEach(el => {
                const name = el.replaceAll(' ','');
                header += `<li class="${self.quickSearchStates[`menu${name}`] ? 'active' : ''}${self.quickSearchStates.active === name ? ' highlight' : ''}" data-active="${name}">${el}</li>`
            })
            header += '</ul>';
        }

        canvas.innerHTML = header + content;

        // Header
        header = canvas.querySelector('#brxcQuickSearchHeader');
        if(header){
            header.addEventListener('mousedown', (e) => {
                if(!e.target.classList.contains('active')) return;
                self.quickSearchStates.active = e.target.dataset.active;
                self.renderQuickSearchResults();

            })
        }

        // First active
        const firstActive = canvas.querySelector('#brxcQuickSearchResults [data-type]:not(.brxc-more)');
        if(firstActive){
            firstActive.classList.add('selected');
        }


    },
    quickSearchRerender: function(){
        const self = this;
        const existing = document.querySelector('#brxcQuickSearch');
        if(!existing) return;
        self.quickSearchsetActiveElement();
        self.renderQuickSearchResults();
    },
    quickSearchGlobalClasses: function(count){
        const self = this;
        const clsName = self.helpers.formatForClasses(self.quickSearchStates.search);

        function classExists(name){
            return self.vueState.globalClasses.find(el => el && el.name === name);
        }
        const filteredArr = self.vueState.globalClasses
            .filter(el => el && self.quickSearchStates.search !== "" && el.name.toLowerCase().includes(self.quickSearchStates.search.toLowerCase()));
        content = '';
        if(filteredArr.length > 0) {
            self.quickSearchStates.menuGlobalClasses = true;
            content += `<div class="brxc-title">Global Classes</div>`;
            const finalArr = self.quickSearchStates.active === 'all' ? filteredArr.slice(0, self.quickSearchStates.maxResults) : filteredArr;
            content += finalArr
                        .map(el => {
                            let formattedCount, formattedOutput;
                            if(self.builderStates.isElementActive) {
                                if(count.value < 99) count.value++;
                                formattedCount = String(count.value).padStart(2, '0');
                                formattedOutput = formattedCount.split("").map(digit => `<div class="digit">${digit}</div>`).join('<div class="plus">+</div>');
                            }
                            return `<div${self.builderStates.isElementActive ? ` data-type="add-class" data-id="${el.id}"` : ''}><i class="fab fa-html5"></i><span>.${el.name}</span>${self.builderStates.isElementActive && count.value < 99? `<div class="keyboard-sc" data-kb="${formattedCount}"><div>CTRL</div> <div class="plus">+</div> ${formattedOutput}</div>` : ''}</div>`;
                        })
                        .join('');
            if(self.quickSearchStates.active === 'all' && filteredArr.length > self.quickSearchStates.maxResults) content += `<div class="brxc-more" data-type="more" data-cat="GlobalClasses"><span>${filteredArr.length - self.quickSearchStates.maxResults} more match(es).</span></div>`;
            
            // Add new class
            if(!classExists(clsName)){
                if(count.value < 99) count.value++;
                const formattedCount = String(count.value).padStart(2, '0');
                const formattedOutput = formattedCount.split("").map(digit => `<div class="digit">${digit}</div>`).join('<div class="plus">+</div>');
                content += `<div data-type="add-new-class"><span>Create new class ".${clsName}"</span><div class="keyboard-sc" data-kb="${formattedCount}"><div>CTRL</div> <div class="plus">+</div> ${formattedOutput}</div></div>`
            }
        } else if(self.quickSearchStates.search !== "" && !classExists(clsName)){
            self.quickSearchStates.menuGlobalClasses = true;
            if(count.value < 99) count.value++;
            const formattedCount = String(count.value).padStart(2, '0');
            const formattedOutput = formattedCount.split("").map(digit => `<div class="digit">${digit}</div>`).join('<div class="plus">+</div>');
            content += `<div class="brxc-title">Global Classes</div>`;
            content += `<div data-type="add-new-class"><span>Create new class ".${clsName}"</span><div class="keyboard-sc" data-kb="${formattedCount}"><div>CTRL</div> <div class="plus">+</div> ${formattedOutput}</div></div>`
        } else {
            self.quickSearchStates.menuGlobalClasses = false;
        }

        return content;
    },
    quickSearchGlobalVariables: function(count){
        const self = this;
        const varName = self.helpers.formatForClasses(self.quickSearchStates.search);

        function varExists(name){
            return self.vueState.globalVariables.find(el => el && el.name === name);
        }
        const filteredArr = self.vueState.globalVariables
            .filter(el => el && self.quickSearchStates.search !== "" && el.name.toLowerCase().includes(self.quickSearchStates.search.toLowerCase()));
        content = '';
        if(filteredArr.length > 0) {
            self.quickSearchStates.menuGlobalVariables = true;
            content += `<div class="brxc-title">Global Variables</div>`;
            const finalArr = self.quickSearchStates.active === 'all' ? filteredArr.slice(0, self.quickSearchStates.maxResults) : filteredArr;
            content += finalArr
                        .map(el => {
                            let formattedCount, formattedOutput;
                            if(self.quickSearchStates.activeControl) {
                                if(count.value < 99) count.value++;
                                formattedCount = String(count.value).padStart(2, '0');
                                formattedOutput = formattedCount.split("").map(digit => `<div class="digit">${digit}</div>`).join('<div class="plus">+</div>');
                            }
                            return `<div${self.quickSearchStates.activeControl ? ` data-type="add-variable" data-value="var(--${el.name})"` : ''}><i class="fas fa-square-root-variable"></i><span>--${el.name}</span>${self.quickSearchStates.activeControl && count.value < 99? `<div class="keyboard-sc" data-kb="${formattedCount}"><div>CTRL</div> <div class="plus">+</div> ${formattedOutput}</div>` : ''}</div>`;
                        })
                        .join('');
            if(self.quickSearchStates.active === 'all' && filteredArr.length > self.quickSearchStates.maxResults) content += `<div class="brxc-more" data-type="more" data-cat="GlobalVariables"><span>${filteredArr.length - self.quickSearchStates.maxResults} more match(es).</span></div>`;
            
            // Add new Global Variable
            if(!varExists(varName)){
                if(count.value < 99) count.value++;
                const formattedCount = String(count.value).padStart(2, '0');
                const formattedOutput = formattedCount.split("").map(digit => `<div class="digit">${digit}</div>`).join('<div class="plus">+</div>');
                content += `<div data-type="add-new-global-variable"><span>Create a New Global Variable "--${varName}"</span><div class="keyboard-sc" data-kb="${formattedCount}"><div>CTRL</div> <div class="plus">+</div> ${formattedOutput}</div></div>`
            }
        } else if (self.quickSearchStates.search !== "" && !varExists(varName)){
            self.quickSearchStates.menuGlobalVariables = true;
            if(count.value < 99) count.value++;
            const formattedCount = String(count.value).padStart(2, '0');
            const formattedOutput = formattedCount.split("").map(digit => `<div class="digit">${digit}</div>`).join('<div class="plus">+</div>');
            content += `<div class="brxc-title">Global Variables</div>`;
            content += `<div data-type="add-new-global-variable"><span>Create a New Global Variable "--${varName}"</span><div class="keyboard-sc" data-kb="${formattedCount}"><div>CTRL</div> <div class="plus">+</div> ${formattedOutput}</div></div>`
        } else {
            self.quickSearchStates.menuGlobalVariables = false;
        }

        return content;
    },
    quickSearchThemeVariables: function(count){
        const self = this;
        const varName = self.helpers.formatForClasses(self.quickSearchStates.search);

        function varExists(name){
            return self.vueState.themeStyleSettings.general._cssVariables.find(el => el && el.name === name);
        }
        const filteredArr = self.vueState.themeStyleSettings.general._cssVariables
            .filter(el => el && self.quickSearchStates.search !== "" && el.name.toLowerCase().includes(self.quickSearchStates.search.toLowerCase()));
        content = '';
        if(filteredArr.length > 0) {
            self.quickSearchStates.menuThemeVariables = true;
            content += `<div class="brxc-title">Theme Variables</div>`;
            const finalArr = self.quickSearchStates.active === 'all' ? filteredArr.slice(0, self.quickSearchStates.maxResults) : filteredArr;
            content += finalArr
                        .map(el => {
                            let formattedCount, formattedOutput;
                            if(self.quickSearchStates.activeControl) {
                                if(count.value < 99) count.value++;
                                formattedCount = String(count.value).padStart(2, '0');
                                formattedOutput = formattedCount.split("").map(digit => `<div class="digit">${digit}</div>`).join('<div class="plus">+</div>');
                            }
                            return `<div${self.quickSearchStates.activeControl ? ` data-type="add-variable" data-value="var(--${el.name})"` : ''}><i class="fas fa-square-root-variable"></i><span>--${el.name}</span>${self.quickSearchStates.activeControl && count.value < 99? `<div class="keyboard-sc" data-kb="${formattedCount}"><div>CTRL</div> <div class="plus">+</div> ${formattedOutput}</div>` : ''}</div>`;
                        })
                        .join('');
            if(self.quickSearchStates.active === 'all' && filteredArr.length > self.quickSearchStates.maxResults) content += `<div class="brxc-more" data-type="more" data-cat="ThemeVariables"><span>${filteredArr.length - self.quickSearchStates.maxResults} more match(es).</span></div>`;

            // Add new Theme Variable
            if(!varExists(varName)){
                if(count.value < 99) count.value++;
                const formattedCount = String(count.value).padStart(2, '0');
                const formattedOutput = formattedCount.split("").map(digit => `<div class="digit">${digit}</div>`).join('<div class="plus">+</div>');
                content += `<div data-type="add-new-theme-variable"><span>Create a New Theme Variable "--${varName}"</span><div class="keyboard-sc"  data-kb="${formattedCount}"><div>CTRL</div> <div class="plus">+</div> ${formattedOutput}</div></div>`
            }
        } else if (self.quickSearchStates.search !== "" && !varExists(varName)){
            self.quickSearchStates.menuThemeVariables = true;
            if(count.value < 99) count.value++;
            const formattedCount = String(count.value).padStart(2, '0');
            const formattedOutput = formattedCount.split("").map(digit => `<div class="digit">${digit}</div>`).join('<div class="plus">+</div>');
            content += `<div class="brxc-title">Theme Variables</div>`;
            content += `<div data-type="add-new-theme-variable"><span>Create a New Theme Variable "--${varName}"</span><div class="keyboard-sc"  data-kb="${formattedCount}"><div>CTRL</div> <div class="plus">+</div> ${formattedOutput}</div></div>`
        } else {
            self.quickSearchStates.menuThemeVariables = false;
        }

        return content;
    },
    quickSearchElements: function(count){
        const self = this;
        const filteredArr = Object.values(bricksData.elements)
            .filter(el => el && self.quickSearchStates.search !== "" && el.label.toLowerCase().includes(self.quickSearchStates.search.toLowerCase()));
        content = '';
        if(filteredArr.length > 0) {
            self.quickSearchStates.menuElements = true;
            content += `<div class="brxc-title">Add Element to the Structure</div>`;
            const finalArr = self.quickSearchStates.active === 'all' ? filteredArr.slice(0, self.quickSearchStates.maxResults) : filteredArr;
            content += finalArr
                        .map(el => {
                            if(count.value < 99) count.value++;
                            const formattedCount = String(count.value).padStart(2, '0');
                            const formattedOutput = formattedCount.split("").map(digit => `<div class="digit">${digit}</div>`).join('<div class="plus">+</div>');
                            return `<div data-type="add-element" data-name="${el.name}"><i class="${el.icon}"></i><span>${el.label.toLowerCase()}</span><div class="keyboard-sc" data-kb="${formattedCount}"><div>CTRL</div> <div class="plus">+</div> ${formattedOutput}</div></div>`;
                        })
                        .join('');
            if(self.quickSearchStates.active === 'all' && filteredArr.length > self.quickSearchStates.maxResults) content += `<div class="brxc-more" data-type="more" data-cat="Elements"><span>${filteredArr.length - self.quickSearchStates.maxResults} more match(es).</span></div>`;
        } else {
            self.quickSearchStates.menuElements = false;
        }

        return content;
    },
    quickSearchComponents: function(count) {
        const self = this;
        const filteredArr = self.vueState.components.map(obj => obj.elements[0])
            .filter(el => el && self.quickSearchStates.search !== "" && el.label.toLowerCase().includes(self.quickSearchStates.search.toLowerCase()));
        content = '';
        if(filteredArr.length > 0) {
            self.quickSearchStates.menuComponents = true;
            content += `<div class="brxc-title">Add Component to the Structure</div>`;
            const finalArr = self.quickSearchStates.active === 'all' ? filteredArr.slice(0, self.quickSearchStates.maxResults) : filteredArr;
            content += finalArr
                        .map(el => {
                            if(count.value < 99) count.value++;
                            const formattedCount = String(count.value).padStart(2, '0');
                            const formattedOutput = formattedCount.split("").map(digit => `<div class="digit">${digit}</div>`).join('<div class="plus">+</div>');
                            return `<div data-type="add-component" data-id="${el.id}" data-name="${el.label}"><i class="${bricksData.elements[el.name]?.icon}"></i><span>${el.label}</span><div class="keyboard-sc" data-kb="${formattedCount}"><div>CTRL</div> <div class="plus">+</div> ${formattedOutput}</div></div>`;
                        })
                        .join('');
            if(self.quickSearchStates.active === 'all' && filteredArr.length > self.quickSearchStates.maxResults) content += `<div class="brxc-more" data-type="more" data-cat="Components"><span>${filteredArr.length - self.quickSearchStates.maxResults} more match(es).</span></div>`;
        } else {
            self.quickSearchStates.menuComponents = false;
        }

        return content;
    },
    quickSearchStructure: function(count){
        const self = this;
        let arr = self.helpers.getPageContentAndPageComponents();
        const filteredArr = arr
        .filter(el => {
            const searchTerm = self.quickSearchStates.search.toLowerCase();
            if (searchTerm === "") return false;
            const obj = el.obj;
            const elementObj = self.vueGlobalProp.$_getElementConfig(obj.name);
            const nameMatch = elementObj.label.toLowerCase().includes(searchTerm);
            const labelMatch = obj.label ? obj.label.toLowerCase().includes(searchTerm) : false;
            const globalClassMatch = obj.hasOwnProperty('settings') && obj.settings.hasOwnProperty('_cssGlobalClasses') ? obj.settings._cssGlobalClasses.some(el => self.vueGlobalProp.$_getGlobalClass(el)?.name.toLowerCase().includes(searchTerm)) : false;
            const textMatch = obj.hasOwnProperty('settings') && obj.settings.hasOwnProperty('text') ? obj.settings.text.toLowerCase().includes(searchTerm) : false;
            const idMatch = obj.id.toLowerCase().includes(searchTerm);
            const cssIdMatch = obj.hasOwnProperty('settings') && obj.settings.hasOwnProperty('_cssId') ? obj.settings._cssId.toLowerCase().includes(searchTerm) : false;
            return nameMatch || globalClassMatch || labelMatch || textMatch || idMatch || cssIdMatch;
        });

        content = '';
        if(filteredArr.length > 0) {
            self.quickSearchStates.menuStructure = true;
            content += `<div class="brxc-title">Jump to Element inside the Structure</div>`;
            const finalArr = self.quickSearchStates.active === 'all' ? filteredArr.slice(0, self.quickSearchStates.maxResults) : filteredArr;
            content += finalArr
                        .map(el => {
                            if(count.value < 99) count.value++;
                            const formattedCount = String(count.value).padStart(2, '0');
                            const formattedOutput = formattedCount.split("").map(digit => `<div class="digit">${digit}</div>`).join('<div class="plus">+</div>');
                            return `<div data-type="jump-element" data-id="${el.obj.id}"${el.hasOwnProperty('component') ? ' class="component"' : ''}><i class="${self.vueGlobalProp.$_getElementConfig(el.obj.name).icon}"></i><span>${el.obj.hasOwnProperty('label') ? el.obj.label : self.vueGlobalProp.$_getElementConfig(el.obj.name).label} <span>(#${el.obj.hasOwnProperty('settings') && el.obj.settings.hasOwnProperty('_cssId') ? el.obj.settings._cssId : `brxe-${el.obj.id}`})</span></span>${count.value < 100 ? `<div class="keyboard-sc" data-kb="${formattedCount}"><div>CTRL</div> <div class="plus">+</div> ${formattedOutput}</div>`: ''}</div>`;
                        })
                        .join('');
            if(self.quickSearchStates.active === 'all' && filteredArr.length > self.quickSearchStates.maxResults) content += `<div class="brxc-more" data-type="more" data-cat="Structure"><span>${filteredArr.length - self.quickSearchStates.maxResults} more match(es).</span></div>`;
        } else {
            self.quickSearchStates.menuStructure = false;
        }

        return content;
    },
    focusModeStates: {
        active: null,
        parent: null,
        preview: true,
    },
    // setFocusModeListener: function(){
    //     const self = this;

    //     const structure = document.querySelector('#bricks-structure');
    //     if(!structure) return;

    //     // Structure
    //     structure.addEventListener('click', (e) => {
    //         const shortcut = self.vueState.isMac ? e.metaKey && e.shiftKey : e.ctrlKey && e.shiftKey;
    //         const element = e.target.closest('.element');
    //         if(!shortcut || !element) return;

    //         e.preventDefault();
    //         e.stopPropagation()

    //         self.focusModeStates.active = element.dataset.id;
    //         const parent = element.parentElement.closest('.element');
    //         if(parent){
    //             self.focusModeStates.parent = parent.dataset.id;
    //         }
    //         self.setFocusMode();
    //     }, true);

    //     // Iframe
    //     setTimeout(() => {
    //         const iBody = FRAMEBRXC.content;
    //         if(!iBody) return;

    //         iBody.addEventListener('click', (e) => {
    //             const shortcut = self.vueState.isMac ? e.metaKey && e.shiftKey : e.ctrlKey && e.shiftKey;
    //             const element = e.target.closest('[data-id]');
    //             if(!shortcut || !element) return;

    //             e.preventDefault();
    //             e.stopPropagation()

    //             self.focusModeStates.active = element.dataset.id;
    //             const parent = element.parentElement.closest('[data-id]');
    //             if(parent){
    //                 self.focusModeStates.parent = parent.dataset.id;
    //             }
    //             self.setFocusMode();
    //         }, true);
    //     }, 2000)
    // },
    setFocusMode: function(){
        const self = this;
        const structure = document.querySelector('#bricks-structure');
        if(!structure) return;

        const topContainer = structure.querySelector('#brxcStructureTopContainer');
        if(!topContainer) return;

        const existing = structure.querySelector('#brxcFocusModeAlert');
        if(existing) existing.remove();

        function focusModeClearAtts(){
            // Structure
            const focusedElement = structure.querySelector(".structure-item[data-focus='true']");
            if(focusedElement) focusedElement.removeAttribute('data-focus');
            const focusedElementParents = structure.querySelectorAll(".bricks-structure-list[data-parent-focus='true']");
            focusedElementParents.forEach(parent => {
                parent.removeAttribute('data-parent-focus');
            })

            // Iframe
            const iBody = FRAMEBRXC.content.body;
            const focusedIframes = iBody.querySelectorAll('[data-iframe-focus]');
            focusedIframes.forEach(el => el.removeAttribute('data-iframe-focus'))
        }

        const isFocusActive = self.structurePanelStates.tweaks.includes('focus-mode');
        if(isFocusActive){
            const active = document.querySelector(`#bricks-structure .element[data-id="${self.focusModeStates.active}"]`);
            if(!active) return;

            const element = active.querySelector(`.structure-item`);

            // Struture
            document.body.classList.add('at-focus-mode');
            self.focusModeStates.preview ? FRAMEBRXC.content.body.classList.add('at-focus-iframe-mode') : FRAMEBRXC.content.body.classList.remove('at-focus-iframe-mode');
            
            // Mount
            const newElement = self.mountFocusMode();
            topContainer.appendChild(newElement);

            // Close
            const clostBtn = structure.querySelector('#brxcFocusModelClose');
            clostBtn.addEventListener('mousedown', () => {
                focusModeClearAtts();
                document.body.classList.remove('at-focus-mode');
                FRAMEBRXC.content.body.classList.remove('at-focus-iframe-mode');
                self.focusModeStates.active = null;
                self.focusModeStates.parent = null;
                const alert = structure.querySelector('#brxcFocusModeAlert');
                if(alert) alert.remove();
            })

            // Preview
            const previewBtn = structure.querySelector('#brxcFocusModelPreview');
            previewBtn.addEventListener('mousedown', () => {
                self.focusModeStates.preview = !self.focusModeStates.preview;
                self.helpers.setLocalStorage('focusModePreview', self.focusModeStates.preview);
                self.setFocusMode();
            })

            // Parent
            const parentBtn = structure.querySelector('#brxcFocusModelParent');
            if(parentBtn){
                parentBtn.addEventListener('mousedown', () => {
                    if(!self.focusModeStates.parent) return;
                    self.focusModeStates.active = self.focusModeStates.parent;
                    const active = document.querySelector(`#bricks-structure .element[data-id="${self.focusModeStates.active}"]`);
                    let parent = false;
                    if(active) {
                        parent = active.parentElement.closest('.element');
                    }  
                    self.focusModeStates.parent = parent ? parent.dataset.id : null;
                    self.setFocusMode();
                })
            }
            

            focusModeClearAtts();

            // Structure
            element.setAttribute('data-focus', 'true');
            const parents = self.helpers.getAllParentsMatching(element, '.bricks-structure-list');
            parents.forEach(parent => {
                parent.setAttribute('data-parent-focus', 'true');
            })

            // Iframe
            if(self.focusModeStates.preview){
                const activeObj = self.helpers.getElementObject(self.focusModeStates.active);
                const nodeElement = FRAMEBRXC.vueGlobalProp.$_getElementNode(activeObj)
                nodeElement.setAttribute('data-iframe-focus', 'true');
            }
        }
    },
    mountFocusMode: function(){
        const self = this;
        const newElement = document.createElement('div');
        newElement.id = 'brxcFocusModeAlert';
        newElement.innerHTML = `<div id="brxcFocusModeLabel"><i class="fas fa-crosshairs"></i>Focus Mode activated</div>
                                <div class="actions">
                                    ${self.focusModeStates.parent ? `
                                        <div id="brxcFocusModelParent" data-balloon="Jump to Parent" data-balloon-pos="top-right"><i class="bricks-svg fas fa-arrow-turn-up"></i></div>` 
                                    : ''}
                                    <div id="brxcFocusModelPreview" class="${self.focusModeStates.preview ? 'active' : ''}" data-balloon="Apply on Iframe (${self.focusModeStates.preview ? 'enabled' : 'disabled'})" data-balloon-pos="top-right"><i class="bricks-svg ti-eye"></i></div>
                                    <div id="brxcFocusModelClose" data-balloon="Close" data-balloon-pos="top-right"><i class="bricks-svg ti-close"></i></div>
                                </div>`

        return newElement;
    },
    lockDraggableElementsStates: {
        active: false,
    },
    setLockElements: function(){
        const self = this;
        const storage = self.helpers.getLocalStorage();
        self.lockDraggableElementsStates.active = storage.lockDraggableElements;
        if(self.lockDraggableElementsStates.active){
            document.body.classList.add('locked-elements');
        }
    },
    toggleLockElementsState: function(){
        const self = this;

        self.lockDraggableElementsStates.active = !self.lockDraggableElementsStates.active;
        self.helpers.setLocalStorage('lockDraggableElements',  self.lockDraggableElementsStates.active)
        self.lockDraggableElementsStates.active == 1 ? document.body.classList.add('locked-elements') : document.body.classList.remove('locked-elements');
        setTimeout(() => {
            self.runStructureHighlights()
            self.setHeaderStructurePanel()
        }, 5)

    },
    syncLabelHeagings: function(){
        const self = this;
        const names = ['heading'];
        if(!self.builderStates.isElementActive || !names.includes(self.builderStates.activeElement.name)) return;

        Promise.resolve().then(() => {
            const input = document.querySelector('[data-controlkey="text"] textarea, [data-controlkey="text"] input[type="text"]');
            if(!input || input.dataset.listening === "true") return;

            input.setAttribute('data-listening', 'true');
            input.addEventListener('keyup', (e) => {
                self.builderStates.activeElement.label = e.target.value.replaceAll(/<\/?[^>]+(>|$)/g, "");
            })
        })

    },
    runStates: function(){
        const self = this;
        self.builderStates = {
            isElementActive: self.helpers.isElementActive(),
            isClassActive: self.helpers.isClassActive(),
            activeElement: self.helpers.isElementActive() ? self.helpers.getFinalObject(true) : null,
            activeObject: self.helpers.isElementActive() ? self.helpers.getFinalObject() : null,
        }
    },
    runStateFunctionsAlways: function(){
        const self = this;
        self.runStates();
        if (self.helpers.isBuilderTweaksTabActive('classes-and-styles') && 
            Object.values(self.globalSettings.classFeatures).includes("focus-on-first-class")) {
            self.focusOnFirstClass();
        }
        if (self.helpers.isBuilderTweaksTabActive('elements') && 
            Object.values(self.globalSettings.elementShortcutIcons).includes("modified-mode")) {
            self.modifiedMode();
        }

        let arr = Object.values(self.globalSettings.elementFeatures);
        // Builder Tweaks
        if (self.helpers.isBuilderTweaksTabActive()) {
            arr.includes("superpower-custom-css") ? self.setSuperPowerCSS() : '';
        }

    },
    runStateFunctions: function() {
        const self = this;
    
        setTimeout(() => {
            let arr;
            self.runStates();
            // Global Variables
            if (self.helpers.isCSSVariablesTabActive('theme-variables')) {
                self.checkForThemeChange();
            }
    
            // Global Colors
            arr = Object.values(ADMINBRXC.globalSettings.themeSettingsTabs);
            if (arr.includes("global-colors")) {
                self.replaceColorsPalette();
            }
    
            // Builder Tweaks
            if (self.helpers.isBuilderTweaksTabActive()) {
                // Structure Panel
                self.runStructureHighlights();
                self.stickyCssStates.active ? self.setStickyCSSObject() : '';
    
                // Classes
                arr = Object.values(self.globalSettings.classFeatures);
                arr.includes("locked-class-indicator") ? self.lockedClassIndicator() : '';
                arr.includes("color-preview") ? self.setDynamicColorOnHover() : '';
                arr.includes("class-preview") ? self.setDynamicClassOnHover() : '';
                arr.includes("disable-id-styles") ? self.forceClassStlyes() : '';
                arr.includes("breakpoint-indicator") ? self.breakpointIndicator() : '';
                arr.includes("sync-label") ? self.syncLabelwithGlobalClass() : '';
    
                // Elements
                self.setTextShortcutsWrapper();
                arr = Object.values(self.globalSettings.elementFeatures);
                arr.includes("close-accordion-tabs") ? self.setActiveStyleTabs() : '';
                arr.includes("disable-borders-boxshadows") ? self.setBorderAndBoxShadow() : '';
                arr.includes("resize-elements-icons") ? self.setElementsColumns() : '';
                arr.includes("lorem-ipsum") ? self.addDynamicLoremIcon() : '';
                Object.values(self.globalSettings.defaultElementFeatures).includes('generated-code') ? self.setGeneratedCSS() : '';
                Object.values(self.globalSettings.defaultElementFeatures).includes('generated-code') ? self.setGeneratedHTML() : '';
                self.setHideFloatingBar();
                if (arr.includes("focus-point")) {
                    self.addBgPositionIcon();
                    self.addObjPositionIcon();
                }
                arr.includes("mask-helper") ? self.addBgMaskIcon() : '';
                if (arr.includes("copy-interactions-conditions")) {
                    self.setCopyInteractions();
                    self.setCopyConditions();
                }
                arr.includes("box-shadow-generator") ? self.setBoxShadowGenerator() : '';
                arr.includes("text-wrapper") ? self.setbasicTextOptions() : '';
                arr.includes('sync-heading-label') ? self.syncLabelHeagings() : '';
    
                // Icon Shortcuts
                self.setClassShortcuts();
                self.addPanelHeaderIcons();
                arr = Object.values(self.globalSettings.elementShortcutIcons);
                arr.includes("pseudo-shortcut") && self.globalSettings.shortcutsIcons.length > 0 ? self.headerIconsState() : '';
                
                // Quick Search
                self.quickSearchRerender();
            }
    
            // AI
            self.helpers.isAIActive() && self.globalSettings.isAIApiKeyEmpty !== "" ? self.addDynamicAIIcon() : '';
    
            // Strict Editor
            self.setStrictEditorView();
    
            // Global features
            self.setGenerateGlobalQuery();
            self.setQueryList();

            // Preview
            self.topbarStates.tweaks.includes('zoom-out') ? self.zoomOutRemoveDraggable() : '';
        },0)
    },
    runObserver: function() {
        const self = this;
        const panelInner = document.querySelector('#bricks-panel-inner');
        if (!panelInner) return;
    
        const observer = new MutationObserver(function(mutations) {
            let shouldSkip = false;
            // Check if the mutation happens inside a .CodeMirror instance
            mutations.forEach(function(mutation) {
                if (mutation.target.closest('.CodeMirror') || mutation.target.closest('.brxc-skip-remount')) {
                    shouldSkip = true;
                }
            });

            Promise.resolve()
                .then(() => {
                    if (!shouldSkip) self.runStateFunctionsAlways()
                })
                .then(() => {
                    // Skip running the observer if a mutation happens inside .CodeMirror
                    if (shouldSkip || self.vueState.brxcRunningObserver === true) return;
                    self.vueState.brxcRunningObserver = true;
                    self.runStateFunctions();
            
                    setTimeout(() => self.vueState.brxcRunningObserver = false, 300);
                })
        });
    
        observer.observe(panelInner, { 
            subtree: true, 
            childList: true,
        });
    },
    initObservers: function(){
        const self = this;
        // Main Observer
        self.runObserver();
    },
    setKeyboardShortcuts: function () {
        const self = this;
    
        const preventDefault = (e) => {
            if(!e) return;
            e.preventDefault();
            e.stopPropagation();
        };

        const toggleAction = (key) => {
            const menu = document.querySelector('#brxc-main-at-menu');
            if(menu){
                self.toggleTopbarTweaks([key], true)
            } else {
                self.toggleTopbarTweaks([key], false)
            }
        }
    
        const iframeWindow = document.querySelector('#bricks-builder-iframe')?.contentWindow;
    
        const shortcutActions = {
            gridGuides: () => toggleAction('grid-guides'),
            xMode: () => toggleAction('x-mode'),
            contrastChecker: () => toggleAction('contrast-checker'),
            darkmode: () => toggleAction('darkmode'),
            codepenConverter: () => self.openModal({ target: false, id: "#brxcCodePenImporter", callback: () => self.codepenImporterInit() }),
            resources: () => self.openModal({ target: false, id: "#brxcResourcesOverlay", closeActiveModals: false }),
            openai: () => self.openModal({ target: false, id: "#brxcGlobalOpenAIOverlay" }),
            brickslabs: () => self.openModal({ target: false, id: "#brxcBricksLabsOverlay", callback: () => self.bricksLabsAPI(false, false, true) }),
            plainClasses: () => self.builderStates.isElementActive 
                ? self.openPlainClassesModal(event, '#brxcPlainClassesOverlay') 
                : self.vueGlobalProp.$_showMessage('Abort: no element selected!'),
            nestedElemenets: () => self.openModal({ target: false, id: '#brxcCustomComponentsOverlay', focus: '#brxcCustomComponentsSearch input', callback: () => self.setCustomComponents() }),
            findAndReplace: () => self.builderStates.isElementActive 
                ? self.openFindReplaceModal(event, false, '#brxcFindReplaceModal') 
                : self.openFindReplaceModal(event, true, '#brxcFindReplaceModal'),
            colorManager: () => self.openModal({ target: false, id: "#brxcColorManagerOverlay", focus: "#brxcColorManagerOverlay input.class-filter", callback: () => self.setColorManager() }),
            classManager: () => self.builderStates.isElementActive && self.builderStates.isClassActive 
                ? self.openClassInManager(self.vueState.activeClass.id)
                : self.openClassManager('global'),
            variableManager: () => self.openModal({ target: false, id: "#brxcCSSVariableManagerOverlay", focus: '#brxcCSSVariableManagerOverlay input[type=text].class-filter', callback: () => {self.cssVariablesStates.search = "";self.cssVariablesStates.view = "full";self.setCSSVariableManager();} }),
            queryLoopManager: () => self.openModal({ target: false, id: "#brxcQueryManagerOverlay", callback: () => self.queryManagerInit() }),
            promptManager: () => self.openModal({ target: false, id: "#brxcPromptManagerOverlay", callback: () => self.promptManagerInit() }),
            structureHelper: () => self.openModal({ target: false, id: "#brxcStructureHelper", callback: () => self.setStructureHelper() }),
            remoteTemplate: () => self.openRemoteTemplatesModal(),
            ATFramework: () => self.setFrameworkOptions(),
            cssStylesheets: () => self.openModal({ target: false, id: '#brxcCSSOverlay', focus: '#brxcCSSOverlay input.class-filter', callback: () => { self.advancedCSSInit(); } }),
        };
    
        const runShortcuts = (e) => {
            if(!e) return;
            const isShortcutCombo = self.vueState.isMac ? e.metaKey && e.ctrlKey : e.ctrlKey && e.shiftKey;
            if (!isShortcutCombo) return;
    
            const key = e.key.toLowerCase();
            for (const [actionKey, callback] of Object.entries(shortcutActions)) {
                if (self.globalSettings.keyboardShortcuts[actionKey]?.toLowerCase() === key) {
                    preventDefault(e);
                    callback(e);
                    break;
                }
            }
        };
    
        const isQuickSearchCombo = (e) => {
            if(!e) return;
            const key = e.key.toLowerCase();
            const quickKey = self.globalSettings.keyboardShortcuts.quickSearch?.toLowerCase();
            return (
                key === quickKey &&
                (
                    (self.vueState.isMac && e.metaKey && !e.ctrlKey && !e.altKey && !e.shiftKey) ||
                    (!self.vueState.isMac && e.ctrlKey && !e.metaKey && !e.altKey && !e.shiftKey)
                )
            );
        };
    
        const handleKeyDown = (e) => {
            if(!e || document.activeElement.closest('.CodeMirror')) return;
            if (isQuickSearchCombo(e)) {
                preventDefault(e);
                self.openQuickSearch();
            } else {
                runShortcuts(e);
            }
        };
    
        document.body.addEventListener('keydown', handleKeyDown, true);
        iframeWindow?.document?.body?.addEventListener('keydown', handleKeyDown, true);
    },
    setDefaultPseudoClasses: function(){
        const self = this;
        const pseudoList = self.vueState.pseudoClasses;
        const defaultPseudo = [':before',':after',':hover', ':active', ':focus'];
        let hasNewPseudo = false;
        defaultPseudo.forEach(pseudo => {
            if (Object.values(pseudoList).indexOf(pseudo) > -1) return;
            hasNewPseudo = true;
            self.vueState.pseudoClasses.push(pseudo);
        })
        if (hasNewPseudo) self.helpers.saveChanges('pseudoClasses');
    },
    findAndReplace: function(searchValue, replaceValue, property, element, position, inclGlobalClasses){
        const self = this;
        let content = self.helpers.getContent();;
        let numChanges = 0;
        

        function replaceHexWithColor(obj, color) {
            let hexFound = false;
        
            if (Array.isArray(obj)) {
                for (let i = 0; i < obj.length; i++) {
                    const result = replaceHexWithColor(obj[i], color);
                    if (result.found) {
                        obj[i] = result.newValue;
                        hexFound = true;
                    }
                }
            } else if (typeof obj === "object" && obj !== null) {
                for (const key of Object.keys(obj)) {
                    const result = replaceHexWithColor(obj[key], color);
                    if (result.found) {
                        obj[key] = result.newValue;
                        hexFound = true;
                    }
                }
        
                if (obj.hasOwnProperty("hex") && obj.hex === searchValue) {
                    obj = color;
                    hexFound = true;
                    numChanges++;
                }
            }
        
            return { found: hexFound, newValue: obj };
        }

        function replaceColor(replaceColor){
            const palettes = self.vueState.colorPalette;
            let matchingColor = false;
            palettes.forEach(palette => {
                (Array.isArray(palette.colors) ? palette.colors : []).forEach( color => {
                    for (const [key, value] of Object.entries(color)) {
                        if (color[key] === replaceColor)  {
                            matchingColor = color;
                        }
                    }
                })
            })
            return matchingColor;
        }
        function replaceStyle(id, isGlobalClass = false){
            const color = replaceColor(replaceValue)
            const obj = isGlobalClass ? self.vueGlobalProp.$_getGlobalClass(id) : self.helpers.getElementObject(id);
            if(!obj || !obj.hasOwnProperty('settings')) return;

            for (const [key, value] of Object.entries(obj.settings)) {
                if(!self.helpers.isCSSControlKey(key)) continue ;

                if(property === "all" || key === property) {
                    // colors
                    if(color){
                        const checkColor = replaceHexWithColor(obj.settings, color);
                    } else {
                        // other
                        const oldValue = obj.settings[key];
                        obj.settings[key] = JSON.parse(JSON.stringify(value).replaceAll(searchValue, replaceValue));

                        if (JSON.stringify(oldValue) != JSON.stringify(obj.settings[key])) numChanges++;
                    }

                }
            }
   
        }

        function setStyle(obj, id) {
            // Category check
            if(element === "all" || obj.name === element){
                replaceStyle(id);
                if(inclGlobalClasses === "yes" && obj.settings.hasOwnProperty('_cssGlobalClasses')){
                    obj.settings._cssGlobalClasses.forEach(clsId => {
                        replaceStyle(clsId, true);
                    })
                }
            }
            if(Object.keys(obj.children).length > 0){
                Object.keys(obj.children).forEach(function (key){
                    const newObj = self.helpers.getElementObject(obj.children[key]);
                    setStyle(newObj, obj.children[key]);
                });
            }
        }
        if(position === "page"){
            content.forEach(child => {
                if(element === "all" || child.name === category){
                    replaceStyle(child.id);
                    if(inclGlobalClasses === "yes" && child.settings.hasOwnProperty('_cssGlobalClasses')){
                        child.settings._cssGlobalClasses.forEach(clsId => {
                            replaceStyle(clsId, true);
                        })
                    }
                }
            })
        } else {
            // active element
            const el = self.builderStates.activeElement
            const parentID = el.parent;
            if(!parentID || typeof content == "undefined") return;

            function checkParent(elemID){
                let obj;
                if(elemID !== false) obj = self.helpers.getElementObject(elemID);
                
                // sibling
                
                if(position === "siblings"){
                    obj.children.forEach(child => {
                        const obj = self.helpers.getElementObject(child);
                        if(element === "all" || obj.name === element){
                            replaceStyle(child);
                            if(inclGlobalClasses === "yes" && obj.settings.hasOwnProperty('_cssGlobalClasses')){
                                obj.settings._cssGlobalClasses.forEach(clsId => {
                                    replaceStyle(clsId, true);
                                })
                            }
                        }
                    })
                
                // children

                } else if(position === "children"){
                    obj = self.builderStates.activeElement;
                    if (typeof obj === "undefined" || !obj.hasOwnProperty('children') || obj.children.length < 1) return;
                    obj.children.forEach(child => {
                        const obj = self.helpers.getElementObject(child)
                        setStyle(obj, child)
                    })

                // custom postion
                } else {
                    if (obj.name === position){
                        obj.children.forEach(child => {
                            const obj = self.helpers.getElementObject(child)
                            setStyle(obj, child)
                        })
                    } else {
                        if(obj.parent) checkParent(obj.parent);
                    }
                }
            }

            checkParent(parentID);
        }
        
        if(numChanges > 0 ){
            self.vueState.rerenderControls = Date.now();
            self.vueGlobalProp.$_showMessage(`${numChanges} styles correctly replaced!`);
        } else {
            self.vueGlobalProp.$_showMessage(`No corresponding style has been found.`);
        }
    },
    applyFindAndReplace: function(){
        const self = this;
        const searchValue = document.querySelector('#brxcFindReplaceModal input[name=brxc-findreplaceSearch]').value;
        const replaceValue = document.querySelector('#brxcFindReplaceModal input[name=brxc-findreplaceReplace]').value;
        const propertyOptions = document.querySelector('#brxc-findreplacepropertyOptions [data-value].active')?.dataset.value;
        const categoryOptions = document.querySelector('#brxc-findreplacecategoryOptions [data-value].active')?.dataset.value;
        const positionValue = document.querySelector('#brxcFindReplaceModal input[name=brxc-findreplacePosition]:checked').value;
        const globalClassesValue = document.querySelector('#brxcFindReplaceModal input[name=brxc-findreplaceGlobalClasses]:checked').value;

        self.findAndReplace(
        searchValue,
        replaceValue,
        propertyOptions,
        categoryOptions,
        positionValue,
        globalClassesValue
        );

        self.closeModal({target: true}, true, '#brxcFindReplaceModal');
    },
    expandClass: function(type, property, category, position, erase){
        const self = this;
        let content = self.helpers.getContent();

        // active element
        const el = self.builderStates.activeElement
        if (!el) return;
        const classes = el.settings._cssGlobalClasses;
        const cssClasses =  (el.settings._cssClasses) ? el.settings._cssClasses.split(' ') : false;
        if (type === "Classes" && !classes && !cssClasses) return self.vueGlobalProp.$_showMessage('No Class found on the element');
        let styles = [];
        for (const [key, value] of Object.entries(el.settings)) {
            if (self.helpers.isCSSControlKey(key)) styles.push({[key]: value});
        }
        if (type === "Styles" && styles.length < 1) return self.vueGlobalProp.$_showMessage('No Style found on the element');
        let parentID = el.parent;
        if(!parentID || typeof content == "undefined") parentID = false;

        function replaceClass(id){
            for(let i = 0; i < content.length; i++){
                for (const [key, value] of Object.entries(content[i])) {
                    if (key === 'id' && value === id) {
                        if(Object.getPrototypeOf(content[i].settings).length === 0) content[i].settings = {};

                        // classes
                        if (type === "Classes") {
                            if (typeof content[i].settings !== "undefined" && !content[i].settings.hasOwnProperty('_cssGlobalClasses') || erase === "true") content[i].settings._cssGlobalClasses = [];
                            if (typeof content[i].settings !== "undefined" && !content[i].settings.hasOwnProperty('_cssClasses') || erase === "true") content[i].settings._cssClasses = "";
                            if(classes && classes.length > 0){
                                classes.forEach(el => {
                                    if (!content[i].settings._cssGlobalClasses.includes(el)) content[i].settings._cssGlobalClasses.push(el);
                                });
                            }

                            if(cssClasses && cssClasses.length > 0){
                                cssClasses.forEach(el => {
                                    if (!content[i].settings._cssClasses.includes(el)) content[i].settings._cssClasses = `${content[i].settings._cssClasses} ${el}`;
                                });
                            }
                        }

                        // styles
                        if (type === "Styles") {
                            styles.forEach(style => {
                                for (const [key, value] of Object.entries(style)) {
                                    if(property === "all" || key === property) content[i].settings[key] = JSON.parse(JSON.stringify(value));
                                }
                            })
                        }
                    }
                }
            }
        }
        function setClass(obj, id) {
            // Category check
            if(category === "all" || obj.name === category){
                replaceClass(id);
            }
            if(Object.keys(obj.children).length > 0){
                Object.keys(obj.children).forEach(function (key){
                    const newObj = self.helpers.getElementObject(obj.children[key]);
                    setClass(newObj, obj.children[key]);
                });
            }
        }

        function checkParent(elemID){
            let obj;
            if(elemID !== false) obj = self.helpers.getElementObject(elemID);
            
            // sibling
            
            if(position === "siblings"){
                if (obj === false) return;
                obj.children.forEach(child => {
                    const obj2 = self.helpers.getElementObject(child)
                    if(category === "all" || obj2.name === category){
                        replaceClass(child);
                    }
                })

            // children

            } else if(position === "children"){
                obj =self.builderStates.activeElement;
                if (typeof obj === "undefined" || !obj.hasOwnProperty('children') || obj.children.length < 1) return;
                obj.children.forEach(child => {
                    const obj = self.helpers.getElementObject(child)
                    setClass(obj, child)
                })

            // page

            } else if(position === "page"){
                content.forEach(child => {
                    if(category === "all" || child.name === category){
                        replaceClass(child.id);
                    }
                })
            
            // custom container

            } else {
                if (typeof obj === "undefined" || !obj.hasOwnProperty('children') || obj.children.length < 1) return;
                if (obj.name === position){
                    obj.children.forEach(child => {
                        const obj = self.helpers.getElementObject(child)
                        setClass(obj, child)
                    })
                } else {
                    if(obj.parent) checkParent(obj.parent);
                }
            }
        }
        checkParent(parentID);

        setTimeout(() => {
            self.vueGlobalProp.$_showMessage(type + ' correctly extended!');
            self.vueState.rerenderControls = Date.now();
        }, 5)

    },
    classConverterStates:{
        data: [],
        delimiter: '__',
        copyStyles: true,
        deleteStyles: false,
        syncLabels: false,
    },
    popopulateClassConverterStates: function(){
        const self = this;
        const elementObj = self.builderStates.activeElement;
        self.classConverterStates.active = "all";
        self.classConverterStates.category = "";
        self.classConverterStates.data = [];
        const elements = [];

        function populateElements(id, level){
            const obj = JSON.parse(JSON.stringify(self.helpers.getElementObject(id)));
            const component = self.vueGlobalProp.$_getComponentById(id);

            // Components
            if(component && typeof component === "object" && component.hasOwnProperty('id')){
                obj.level = level;
                elements.push(obj);
                level++;

                if(obj.hasOwnProperty('children') && obj.children){
                    obj.children.forEach( newId => {
                        populateElements(newId, level);
                    }) 
                }

                return;
            }

            obj.level = level;
            elements.push(obj);

            // Children
            if (obj.hasOwnProperty('children') && Array.isArray(obj.children) && obj.children.length > 0) {
                level++;
                obj.children.forEach(newId => {
                    populateElements(newId, level);
                })
            }
        }

        function checkchildren(element, arr, compId, isParent, isComponent = false){
            const active = self.classConverterStates.elements.find(el => el && el.id === element.id);
            active.componentId = compId;
            const isComponentRoot = self.helpers.isComponentRoot(active.id);
            if(isParent || isComponentRoot) active.componentParent = true;
            if(isComponentRoot || isComponent) active.isComponent = true;
            if (!element.hasOwnProperty('children') || !Array.isArray(element.children) || element.children.length < 1) return;
            element.children.forEach(id => {
                const obj = self.helpers.getElementObject(id);
                if(self.helpers.isComponentRoot(id) || (obj.settings.hasOwnProperty('classConverterComponent') && obj.settings.classConverterComponent === true)) return;
                const isComponentChild = isComponentRoot || isComponent ? true : false;
                checkchildren(obj, arr, compId, false, isComponentChild);
            })
        }

        // root loop
        populateElements(elementObj.id, 0);
        self.classConverterStates.elements = elements;

        // Root Element
        const compId = self.vueGlobalProp.$_generateId();
        let rootObj = {
            id: compId,
            basename: elementObj.hasOwnProperty('label') ? self.helpers.formatForClasses(elementObj.label) : elementObj.name,
            label: elementObj.hasOwnProperty('label') ? elementObj.label : elementObj.name,
        };

        checkchildren(elementObj, rootObj.content, compId, true);
        self.classConverterStates.data.push(rootObj);

        //component loop
        const components = elements.filter((el, index) => 
            index !== 0 && ( // Exclude comp root to avoid duplicates
                el && self.helpers.isComponentRoot(el.id) || // Bricks components
                (el.settings?.hasOwnProperty('classConverterComponent') && el.settings.classConverterComponent === true) // AT component roots
            )
        );
        components.forEach(comp => {

            const compId = self.vueGlobalProp.$_generateId();
            let newObj = {
                id: compId,
                basename: comp.hasOwnProperty('label') ? self.helpers.formatForClasses(comp.label) : comp.name,
                label: comp.hasOwnProperty('label') ? comp.label : comp.name,
            };
            checkchildren(comp, newObj.content, compId, true);
            if(!self.classConverterStates.data.includes(newObj)) self.classConverterStates.data.push(newObj);
        })
        if(self.classConverterStates.data.length === 1) self.classConverterStates.active = self.classConverterStates.data[0].id;
    },
    renderClassConverter: function(){
        const self = this;
        const canvas = document.querySelector('#brxcClassConvertCanvas');
        if(!canvas) return;

        const activeComponent = self.classConverterStates.data.find(comp => comp && comp.id === self.classConverterStates.active);
        const delimiter = activeComponent && activeComponent.hasOwnProperty('delimiter') ? activeComponent.delimiter : self.classConverterStates.delimiter;
        const basename = activeComponent ? activeComponent.basename : '';
        const category = activeComponent && activeComponent.hasOwnProperty('category') ? activeComponent.category : self.classConverterStates.category;
        const copyStyles = activeComponent && activeComponent.hasOwnProperty('copyStyles') ? activeComponent.copyStyles : self.classConverterStates.copyStyles;
        const deleteStyles = activeComponent && activeComponent.hasOwnProperty('deleteStyles') ? activeComponent.deleteStyles : self.classConverterStates.deleteStyles;
        const syncLabels = activeComponent && activeComponent.hasOwnProperty('syncLabels') ? activeComponent.syncLabels : self.classConverterStates.syncLabels;
        let content = '';
        if(self.classConverterStates.data.length > 1){
            content += `<div class="m-top-16">
                            <label for="ClassDelimiter" class="has-tooltip">
                                <span>Components</span>
                                <div data-balloon="Select a component to apply specific settings to it." data-balloon-pos="bottom" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div>
                            </label>
                            <div class="brxc-overlay__action-btn-wrapper">`;
            content += `<div class="brxc-overlay__action-btn${self.classConverterStates.active === "all" ? ` primary`: ''}" data-id="all" onclick="ADMINBRXC.classConverterStates.active = 'all';ADMINBRXC.renderClassConverter();">Default</div>`
            self.classConverterStates.data.forEach(el => {
                content += `<div class="brxc-overlay__action-btn${el.id === self.classConverterStates.active ? ` primary`: ''}" data-id="${el.id}" onclick="ADMINBRXC.classConverterStates.active = '${el.id}';ADMINBRXC.renderClassConverter();">${el.label}</div>`
            })
            content += `</div></div>`;
        }
        content += `<div class="input-wrapper">`
        // Basename
        content += `<div style="flex-basis: 75%;"${self.classConverterStates.data.length > 1 && self.classConverterStates.active === "all" ? 'class="disable"' : ''}>
                        <label for="ClassPrefix" class="has-tooltip">
                            <span>Basename</span>
                            <div data-balloon="Set the basename of the class. Example for BEM: 'feature' is the basename of 'feature__heading'." data-balloon-pos="bottom-left" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div>
                        </label>
                        <input type="text" id="ClassPrefix" class="brxc-input-text m-bottom-24" value="${basename}" placeholder="Type your class prefix here." oninput="ADMINBRXC.classConverterUpdateComponent('basename', this.value);"></input>
                    </div>`
        content += `<div style="flex-basis: 25%;">
                        <label for="ClassDelimiter" class="has-tooltip">
                            <span>Delimiter</span>
                            <div data-balloon="Set the delimiter of the class. Example for BEM: '__' is the delimiter of 'feature__heading'." data-balloon-pos="bottom-right" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div>
                        </label>
                        <input type="text" id="ClassDelimiter" class="brxc-input-text m-bottom-24" value="${delimiter}" placeholder="Type your delimiter prefix here." value="__" oninput="ADMINBRXC.classConverterUpdateComponent('delimiter', this.value)"></input>
                        </div>
                    </div>
                    <label for="classConverterPreviewCanvas">
                        <span>Preview</span>
                    </label>
                    <ul>
                    <div id="brxcClassConverterPreviewCanvas">`;
        // Preview 
        content += self.setClassConverterPreview();           
        content += `</div></ul>`;
        // Group
        content += `<label for="brxcClassConverterClassCategory" class="has-tooltip">
                        <span>Class Category <span class="brxc__light">(Optional)</span></span>
                        <div data-balloon="Set the Category of the class. The category will be added to the Class Manager." data-balloon-pos="top" data-balloon-length="medium">
                            <i class="fas fa-circle-question"></i>
                        </div>
                    </label>
                    <div id="classConverterGrpWrapper">
                        <input type="text" id="brxcClassConverterClassCategory" class="brxc-input-text m-bottom-24" value="${category}" placeholder="Type the category of the class here." oninput="ADMINBRXC.classConverterUpdateComponent('category', this.value);ADMINBRXC.autocomplete(this,Array.from(ADMINBRXC.vueState.globalClassesCategories).map(el => el && el.name),false)"></input>
                    </div>
                `;
        content += `<label class="has-tooltip">
                        <span>Copy the ID styles to the class(es)?</span>
                        <div data-balloon="Choose if the styles set on the ID level should be transfered to the generated class." data-balloon-pos="top-right" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div>
                    </label>
                    <div class="brxc-overlay__panel-inline-btns-wrapper m-bottom-24">
                        <input type="radio" id="clsConverter-no" name="clsConverter-copy-styles" class="brxc-input__checkbox" onclick="ADMINBRXC.classConverterUpdateComponent('copyStyles', false);"${copyStyles === false ? " checked" : ""}>
                        <label for="clsConverter-no" class="brxc-overlay__panel-inline-btns">No</label>
                        <input type="radio" id="clsConverter-yes" name="clsConverter-copy-styles" class="brxc-input__checkbox" onclick="ADMINBRXC.classConverterUpdateComponent('copyStyles', true);"${copyStyles === true ? " checked" : ""}>
                        <label for="clsConverter-yes" class="brxc-overlay__panel-inline-btns">Yes</label>
                        <input type="radio" id="clsConverter-skip" name="clsConverter-copy-styles" class="brxc-input__checkbox" onclick="ADMINBRXC.classConverterUpdateComponent('copyStyles', 'skip');"${copyStyles === "skip" ? " checked" : ""}>
                        <label for="clsConverter-skip" class="brxc-overlay__panel-inline-btns">Yes, unless the class already exists</label>
                    </div>
                    <label class="has-tooltip">
                        <span>Erase the ID styles?</span>
                        <div data-balloon="Choose if the styles set on the ID level should be erased after being transfered to the class." data-balloon-pos="top" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div>
                    </label>
                    <div class="brxc-overlay__panel-inline-btns-wrapper m-bottom-24">
                        <input type="radio" id="clsConverter-noo" name="clsConverter-erase-styles" class="brxc-input__checkbox" onclick="ADMINBRXC.classConverterUpdateComponent('deleteStyles', false);"${deleteStyles === false ? " checked" : ""}>
                        <label for="clsConverter-noo" class="brxc-overlay__panel-inline-btns">No</label>
                        <input type="radio" id="clsConverter-yess" name="clsConverter-erase-styles" class="brxc-input__checkbox" onclick="ADMINBRXC.classConverterUpdateComponent('deleteStyles', true);"${deleteStyles === true ? " checked" : ""}>
                        <label for="clsConverter-yess" class="brxc-overlay__panel-inline-btns">Yes</label>
                    </div>
                    <label class="has-tooltip">
                        <span>Sync Elements Labels?</span>
                        <div data-balloon="If checked, the elements label will automatically be renamed based on the corresponding class name." data-balloon-pos="top" data-balloon-length="medium"><i class="fas fa-circle-question"></i></div>
                    </label>
                    <div class="brxc-overlay__panel-inline-btns-wrapper m-bottom-24">
                        <input type="radio" id="clsConverter-sync-no" name="clsConverter-sync-labels" class="brxc-input__checkbox" onclick="ADMINBRXC.classConverterUpdateComponent('syncLabels', false);"${syncLabels === false ? " checked" : ""}>
                        <label for="clsConverter-sync-no" class="brxc-overlay__panel-inline-btns">No</label>
                        <input type="radio" id="clsConverter-sync-yes" name="clsConverter-sync-labels" class="brxc-input__checkbox" onclick="ADMINBRXC.classConverterUpdateComponent('syncLabels', true);"${syncLabels === true ? " checked" : ""}>
                        <label for="clsConverter-sync-yes" class="brxc-overlay__panel-inline-btns">Yes</label>
                    </div>`
        canvas.innerHTML = content;
        self.classConverterPreviewCalculateDots();
    },
    setClassConverter:function(){
        const self = this;
        self.popopulateClassConverterStates();
        self.renderClassConverter();
    },
    setClassConverterPreview: function(){
        const self = this;
        let content = '';
        self.classConverterStates.elements.forEach(el =>{
            const activeComponent = self.classConverterStates.data.find(comp => comp && comp.id === el.componentId);
     
            const delimiter = activeComponent && activeComponent.hasOwnProperty('delimiter') ? activeComponent.delimiter : self.classConverterStates.delimiter;
            const basename = activeComponent.basename;
            const isParent = el.hasOwnProperty('componentParent') && el.componentParent === true;
            const isComponent = el.hasOwnProperty('isComponent') && el.isComponent === true;
            const prefix = isParent ? basename : `${basename}${delimiter}`;
            const value = isParent ? '' : el.hasOwnProperty('label') ? self.helpers.formatForClasses(el.label) : el.name;
            content += `<li data-prefix="${prefix}" data-name="${value}" style="--margin:${el.level};${isComponent ? `--builder-bg-3: var(--builder-bg-component);--builder-color-accent: var(--builder-color-component);` : ''}" class="${self.classConverterStates.active === "all" || el.componentId === self.classConverterStates.active ? 'active' : ''}${isParent ? ' parent' : ''}${isComponent ? ' component' : ''}">
                            <div class="icon" data-balloon="${bricksData.elements[el.name]?.label}" data-balloon-pos="top-left">
                                <i class="${bricksData.elements[el.name]?.icon}"></i>
                            </div>
                            <span>.${prefix}</span>`
            content += !el.hasOwnProperty('componentParent') || el.componentParent !== true ? `<input type="text" data-id="${el.id}" value="${value}" oninput="ADMINBRXC.classConverterUpdateElement(this.dataset.id, 'label', this.value);this.parentElement.dataset.name = this.value;ADMINBRXC.classConverterPreviewCalculateDots();">` : '';
            content += `<span class="brxc-class-exists" data-balloon-pos="left"></span>`;
            content += el.hasOwnProperty('skip') && el.skip === true ? `<button data-balloon="click to include${isParent ? ' all children' : ''}" data-id="${el.id}" data-balloon-pos="left" onClick="ADMINBRXC.classConverterUpdateElement(this.dataset.id, 'skip', false${isParent ? ', true' : ''})">
                                                                                <i class="fas fa-toggle-off"></i>
                                                                            </button>
                                                                        </li>` : 
                                                                        `<button data-balloon="click to skip${isParent ? ' all children' : ''}" data-id="${el.id}" data-balloon-pos="left" onClick="ADMINBRXC.classConverterUpdateElement(this.dataset.id, 'skip', true${isParent ? ', true' : ''})">
                                                                                <i class="fas fa-toggle-on"></i>
                                                                            </button>
                                                                        </li>`;
        })
        return content;

    },
    classConverterRenderPreview: function(){
        const self = this;
        const canvas = document.querySelector('#brxcClassConverterPreviewCanvas');
        content = self.setClassConverterPreview();
        canvas.innerHTML = content;

        // Calculate duplicates
        self.classConverterPreviewCalculateDots();
    },
    classConverterPreviewCalculateDots: function(){
        const self = this;
        const canvas = document.querySelector('#brxcClassConverterPreviewCanvas');
        if(!canvas) return;

        const li = canvas.querySelectorAll('li');
        const duplicates = [];
        li.forEach(el => {
            const name = el.dataset.prefix+el.dataset.name;
            const dot = el.querySelector('.brxc-class-exists')
            const classExists = self.vueState.globalClasses.some(el => el.name === name);
            const classDuplicate = duplicates.some(el => el === name);

            if(classExists) {
                dot.setAttribute('data-exists', 'true');
                dot.setAttribute('data-balloon', 'Class already exists')
            } else if(classDuplicate) {
                dot.setAttribute('data-exists', 'duplicate');
                dot.setAttribute('data-balloon', 'Class is duplicated within the Class Converter')
            } else {
                dot.setAttribute('data-exists', 'false');
                dot.setAttribute('data-balloon', `Class doesn't exists yet`)
            }
            duplicates.push(name);
        })
    },
    classConverterUpdateComponent: function(prop, value){
        const self = this;
        const activeComponent = self.classConverterStates.data.find(el => el && el.id === self.classConverterStates.active);
        if(!activeComponent) {
            self.classConverterStates[prop] = value;
        } else {
            activeComponent[prop] = value;
        }
        self.classConverterRenderPreview();
    },
    classConverterUpdateElement: function(id, prop, value, isParent = false){
        const self = this;
        const activeElement = self.classConverterStates.elements.find(el => el && el.id === id);
        if(!activeElement) return console.log('active not found');

        activeElement[prop] = value;

        if(isParent){
            function applyOnChildren(parentId){
                const obj = self.helpers.getElementObject(parentId);
                const parent = self.classConverterStates.elements.find(el => el && el.id === obj.id);
                if(parent){
                    parent[prop] = value;
                    const children = parent.children;
                    if(Array.isArray(children)){
                        children.forEach(childId => {
                            applyOnChildren(childId);
                            
                        })
                    }
                }
            }
            applyOnChildren(activeElement.id);
        }

        if(prop === "skip") self.classConverterRenderPreview();
    },
    classConverter: function(){
        const self = this;

        function checkGlobalClass(classname, element, category, copyStyles, deleteStyles, syncLabels){
            let newClassID;
            let foundMatch = false;
            const obj = Array.from(self.vueState.globalClasses).find(el => el && el.name === classname);
            if(obj){
                foundMatch = true;
                newClassID = obj.id;
            }

            if(foundMatch === true && (copyStyles === "skip" || self.vueGlobalProp.$_isLocked(newClassID))) {
                return;
            }
            if(!foundMatch) {
                if(!category || category.length < 1) category = false;
                newClassID = self.vueGlobalProp.$_generateId();
                self.generateGlobalClass('', classname, category, newClassID);
                classCreated++;
            }

            // Export styles
            if(copyStyles === true || copyStyles === "skip"){
                const styles = [];
                const excludedKeys = [];
                for (const [key, value] of Object.entries(element.settings)) {
                    const prop = key.split(':')[0];
                    if( ['_cssCustom','_cssCustomSass'].includes(prop) ){
                        const dot = self.helpers.isComponentActive() ? '.' : '#';
                        let id = typeof element.settings !== "undefined" && element.settings.hasOwnProperty('_cssId') ? `${dot}${element.settings._cssId}` : `${dot}brxe-${element.id}`;
                        styles.push({[key]: value.replaceAll(id, '.' + classname)});
                        if (deleteStyles === true) {
                            delete element.settings[key];
                        }
                    } else if (!excludedKeys.includes(prop) && self.helpers.isCSSControlKey(key)) {
                        styles.push({[key]: value});
                        if (deleteStyles === true) {
                            delete element.settings[key];
                        }
                    }
                }

                const arr = Array.from(self.vueState.globalClasses).filter(el => el && el.id === newClassID);
                if(arr.length > 0){
                    arr.forEach(el => {
                        if(styles.lengh < 1) return;
                        if(!el.hasOwnProperty('settings')) el.settings = {};
                        styles.forEach((style) => {
                            for (const [key, value] of Object.entries(style)) {
                                el.settings[key] = JSON.parse(JSON.stringify(value));
                            }
                        })
                    })

                }
            }


            if (typeof element !== "undefined" && !element.hasOwnProperty('settings') || Object.getPrototypeOf(element.settings).length === 0) element.settings = {};
            if (typeof element.settings !== "undefined" && !element.settings.hasOwnProperty('_cssGlobalClasses')) element.settings._cssGlobalClasses = []
            if (typeof element.settings._cssGlobalClasses !== "undefined" && !element.settings._cssGlobalClasses.includes(newClassID)) element.settings._cssGlobalClasses.push(newClassID);

            // Sync labels
            if(syncLabels && typeof element !== "undefined"){
                element.label = self.helpers.classNametoLabel(classname);
            }

        }

        let classCreated = 0;

        const els = self.classConverterStates.elements.filter(el => el && (!el.hasOwnProperty('skip') || el.skip !== true));
        if(els.length < 1) return console.log('no elements found');
        els.forEach(el => {
            const activeComponent = self.classConverterStates.data.find(comp => comp && comp.id === el.componentId);
            const delimiter = activeComponent && activeComponent.hasOwnProperty('delimiter') ? activeComponent.delimiter : self.classConverterStates.delimiter;
            const category = activeComponent && activeComponent.hasOwnProperty('category') ? activeComponent.category : self.classConverterStates.category;
            const copyStyles = activeComponent && activeComponent.hasOwnProperty('copyStyles') ? activeComponent.copyStyles : self.classConverterStates.copyStyles;
            const deleteStyles = activeComponent && activeComponent.hasOwnProperty('deleteStyles') ? activeComponent.deleteStyles : self.classConverterStates.deleteStyles;
            const syncLabels = activeComponent && activeComponent.hasOwnProperty('syncLabels') ? activeComponent.syncLabels : self.classConverterStates.syncLabels;
            const clsName = el.hasOwnProperty('componentParent') && el.componentParent === true ? self.helpers.formatForClasses(activeComponent.basename) : self.helpers.formatForClasses(`${activeComponent.basename}${delimiter}${el.hasOwnProperty('label') ? el.label : el.name}`);
            const settings = self.helpers.getElementObject(el.id);
            checkGlobalClass(clsName, settings, category, copyStyles, deleteStyles, syncLabels);

        })

        self.vueState.rerenderControls = Date.now();
        self.vueGlobalProp.$_showMessage(`${classCreated} Classes successfully created`);
        self.closeModal({target: true}, true, '#brxcClassConverterOverlay');
    },
    hideElementStates: {
        active: false,
    },
    toggleHideFloatingBar: function(){
        const self = this;
        self.hideElementStates.active = !self.hideElementStates.active;
        self.helpers.setLocalStorage('visibilityFloatingBar', self.hideElementStates.active )
        self.setHideFloatingBar();
        self.setHeaderStructurePanel();
    },
    setHideFloatingBar: function(){
        const self = this;
        const structure = document.querySelector('#brxcStructureBottomContainer');
        if(!structure) return;

        const existing = structure.querySelector('#brxcHideFloatingBar');
        if(existing) {
            existing.remove();
        }

        if(!self.builderStates.isElementActive || !self.hideElementStates.active || self.vueState.activeElement.hasOwnProperty('cid')) return;
 
        const obj = self.builderStates.activeElement;
        if(!obj || obj.settings.hasOwnProperty('cid')) return;

        const targetDisplay = self.helpers.createTarget('_display'); 
        const displayNone = obj && obj.settings.hasOwnProperty(targetDisplay) && obj.settings[targetDisplay] === "none";
        const hideBuilder = obj.settings.hasOwnProperty('_hideElementBuilder') && obj.settings._hideElementBuilder;
        const removeFrontend = obj.settings.hasOwnProperty('_hideElementFrontend') && obj.settings._hideElementFrontend;


        const bar = document.createElement('DIV');
        bar.id = 'brxcHideFloatingBar';
        bar.innerHTML = `
            <div>
                <span>Display</span>
                <i class="fas fa-toggle-${displayNone ? 'off' : 'on'}" data-toggle="display"></i>
            </div>
            <div>
                <span>Builder</span>
                <i class="fas fa-toggle-${hideBuilder ? 'off' : 'on'}" data-toggle="builder"></i>
            </div>
            <div>
                <span>Frontend</span>
                <i class="fas fa-toggle-${removeFrontend ? 'off' : 'on'}" data-toggle="frontend"></i>
            </div>
        `

        structure.appendChild(bar);
        bar.addEventListener('click', (e) => {
            if(!e.target.dataset.toggle) return;

            const toggle = e.target.dataset.toggle;
            switch(toggle){
                case 'display':
                    self.hideElement();
                    break;
                case 'builder':
                    self.hideElementBuilder();
                    break;
                case 'frontend':
                    self.removeElementFrontend();
                    break;
            }
            self.setHideFloatingBar();
        })
    },
    hideElement: function(){
        const self = this;
        const target = self.helpers.createTarget('_display');
        const settings = self.helpers.areElementsSelected() ? self.vueState.selectedElementSettings : self.builderStates.activeElement?.settings
        settings.hasOwnProperty(target) ? delete settings[target] : settings[target] = 'none';
    },
    hideElementBuilder: function(){
        const self = this;
        const settings = self.helpers.areElementsSelected() ? self.vueState.selectedElementSettings : self.builderStates.activeElement?.settings
        settings.hasOwnProperty('_hideElementBuilder') && settings._hideElementBuilder? delete settings._hideElementBuilder : settings._hideElementBuilder = true;
    },
    removeElementFrontend: function(){
        const self = this;
        const settings = self.helpers.areElementsSelected() ? self.vueState.selectedElementSettings : self.builderStates.activeElement?.settings
        settings.hasOwnProperty('_hideElementFrontend') && settings._hideElementFrontend ? delete settings._hideElementFrontend : settings._hideElementFrontend = true;
    },
    moveElement: function (event, position) {
        const self = this;
        const activeEl = self.builderStates.activeElement;
        if (!activeEl || !activeEl.hasOwnProperty('parent')) return;
    
        let newParentId = false;
        let index = false;
        const parentObject = self.helpers.getElementObject(activeEl.parent);
        const parentChildren = parentObject?.children || [];
        const currentIndex = parentChildren.indexOf(activeEl.id);

        // Element is on root
        if(activeEl.parent === 0){
            const type = self.helpers.getTemplateType();
            const parentArr = self.vueState[type].filter(el => el && el.hasOwnProperty('parent') && el.parent === 0);
            const currentElIndex = parentArr.indexOf(activeEl);
            switch(position){
                case 'top':
                    newParentId = 0;
                    if (currentElIndex === 0) {
                        index = self.vueState[type].length - 1;
                    } else {
                        index = currentElIndex - 1
                    }
                    break;
                case 'down':
                    newParentId = 0;
                    if (currentElIndex === parentArr.length - 1) {
                        index = 0; 
                    } else {
                        index = currentElIndex + 1
                
                    }
                    break;
                case 'right':
                    const parentArrNestable = parentArr.filter(el => el === activeEl || self.vueGlobalProp.$_isNestable({ name: el.name }))
                    if(parentArrNestable.length === 1){
                        // silence
                    } else if(parentArrNestable.indexOf(activeEl) === 0){
                        const obj = parentArrNestable[1];
                        newParentId = obj.id;
                        index = 0;
                    } else {
                        const obj = parentArrNestable[parentArrNestable.indexOf(activeEl) - 1];
                        newParentId = obj.id;
                        index = obj.children.length;
                    }
                    break;
            }
        
        // Element is nested
        } else {
            switch(position){
                case 'top':
                    newParentId = activeEl.parent;
                    index = currentIndex > 0 ? currentIndex - 1 : parentChildren.length - 1;
                    break;
                case 'down':
                    newParentId = activeEl.parent;
                    index = currentIndex < parentChildren.length - 1 ? currentIndex + 1 : 0;
                    break;
                case 'right':
                    for (let i = currentIndex - 1; i >= 0; i--) {
                        const obj = self.helpers.getElementObject(parentChildren[i]);
                        if (self.vueGlobalProp.$_isNestable({ name: obj.name })) {
                            newParentId = obj.id;
                            index = obj.children.length; // End of new parent's children
                            break;
                        }
                    }
                    if (!newParentId) {
                        for (let i = currentIndex + 1; i < parentChildren.length; i++) {
                            const obj = self.helpers.getElementObject(parentChildren[i]);
                            if (self.vueGlobalProp.$_isNestable({ name: obj.name })) {
                                newParentId = obj.id;
                                index = 0; // Start of new parent's children
                                break;
                            }
                        }
                    }
                    break;
                case 'left':
                    if (parentObject.parent === 0) {
                        newParentId = 0;
                        const type = self.helpers.getTemplateType();
                        const parentIndex = self.vueState[type].filter(el => el.hasOwnProperty('parent') && el.parent === 0).indexOf(parentObject)
                        index = parentIndex + 1;
                    } else {
                        const grandParentObject = self.helpers.getElementObject(parentObject?.parent);
                        const grandParentChildren = grandParentObject?.children || [];
                        const parentIndex = grandParentChildren.indexOf(activeEl.parent);
                        if (grandParentObject) {
                            newParentId = grandParentObject.id;
                            index = parentIndex + 1;
                        }
                    }
                break;
            }
        
        }
        if (newParentId !== false && index !== undefined && index !== null && index !== false) {
            try {
                self.vueGlobalProp.$_moveElement({
                    element: activeEl,
                    parentId: newParentId,
                    index: index,
                });
    
                self.runStateFunctions();
                setTimeout(() => {
                    self.disableMoveElement();
                }, 100);
            } catch (error) {
                console.error("Failed to move element:", error);
            }
        }
    },    
    styleOverviewStates: {
        elementObj: false,
        globalClasses: [],
        structure: true,
        componentsExpanded: true,
        panel: "table",
        search: '',
        pseudo: '',
        copy: {
            type: null,
            id: null,
            styles: null,
            bpKey: null,
            pseudo: null,
        },
        scrollTop: 0,
    },
    styleOverviewInit: function(elementObj, elementClasses = true, globalClasses = []){
        const self = this;
        if(!elementObj) return self.styleOverviewStates.panel === "table" ? self.setStyleOverview() : self.setStyleOverviewCSS();
        
        self.styleOverviewStates.elementObj = elementObj;
        if (elementClasses){
            self.styleOverviewStates.globalClasses = elementObj?.settings?.hasOwnProperty('_cssGlobalClasses') ? elementObj.settings._cssGlobalClasses : [];
        } else {
            self.styleOverviewStates.globalClasses = globalClasses ? globalClasses : [];
        }

        const previewWrapper = document.querySelector('#brxcStyleOverviewPreview');
        if(previewWrapper) self.styleOverviewStates.scrollTop = previewWrapper.scrollTop;
        self.styleOverviewStates.panel === "table" ? self.setStyleOverview(true) : self.setStyleOverviewCSS();
        document.querySelector('#brxcStyleOverviewPreview').scrollTop = self.styleOverviewStates.scrollTop;
    },
    styleOverviewCopy: function(bpKey, type, id){
        const self = this;
        let styles = [];
        const bp = Array.from(self.vueState.breakpoints).find(el => el && el.key === bpKey);

        const obj = type === 'id' ? self.helpers.getElementObject(id) : self.vueGlobalProp.$_getGlobalClass(id);
        if(!obj || !obj.hasOwnProperty('settings')) return;

        const settings = obj.settings

        for(const key of Object.keys(settings)){
            if(self.helpers.keyMatchBreakpoint(key, bpKey) && self.helpers.keyMatchPseudo(key,self.styleOverviewStates.pseudo) && self.helpers.isCSSControlKey(key.split(':')[0])) styles[key.split(':')[0]] = settings[key];

        }

        self.styleOverviewStates.copy.type = type;
        self.styleOverviewStates.copy.id = id;
        self.styleOverviewStates.copy.bpKey = bpKey;
        self.styleOverviewStates.copy.styles = styles;

        self.vueGlobalProp.$_showMessage(`Styles on ${bp.label} have been successfully copied!`)
        self.setStyleOverview();
    },
    styleOverviewPaste: function(bpKey, type, id){
        const self = this;
        const bp = Array.from(self.vueState.breakpoints).find(el => el && el.key === bpKey);
        const obj = type === 'id' ? self.helpers.getElementObject(id) : self.vueGlobalProp.$_getGlobalClass(id);
        if(!obj || !obj.hasOwnProperty('settings')) return;
        
        const settings = obj.settings
        Object.keys(self.styleOverviewStates.copy.styles).forEach(key => {
            let finalKey = key;
            if(bpKey !== "desktop") finalKey += `:${bpKey}`
            if(self.styleOverviewStates.pseudo !== '') finalKey += `:${self.styleOverviewStates.pseudo}`;

            settings[finalKey] = self.styleOverviewStates.copy.styles[key];
        })

        self.vueGlobalProp.$_showMessage(`Styles on ${bp.label} have been successfully pasted!`)
        self.setStyleOverview();
    },
    styleOverviewReset: function(bpKey, type, id){
        const self = this;
        const bp = Array.from(self.vueState.breakpoints).find(el => el && el.key === bpKey);

        const obj = type === 'id' ? self.helpers.getElementObject(id) : self.vueGlobalProp.$_getGlobalClass(id);
        if(!obj || !obj.hasOwnProperty('settings')) return;
        
        const settings = obj.settings

        Object.keys(settings).forEach(key => {
            if(self.helpers.keyMatchBreakpoint(key, bpKey) && self.helpers.keyMatchPseudo(key,self.styleOverviewStates.pseudo) && self.helpers.isCSSControlKey(key.split(':')[0])) delete settings[key];
        })

        self.vueGlobalProp.$_showMessage(`Styles on ${bp.label} have been successfully removed!`)
        self.setStyleOverview();
    },
    setStyleOverviewBPMenu: function(target){
        const self = this;
        const canvas = target.nextElementSibling;
        if(!canvas) return;

        const table = target.closest('table');
        const type = table.dataset.table;
        const id = table.id;
        if(target.classList.contains('active')){
            target.classList.remove('active');
            canvas.innerHTML = '';
            return;
        } else {
            target.classList.add('active')
        }
       
        const bpKey = target.dataset.key;
        let content = `<ul>`;
        content += `<li onclick="ADMINBRXC.styleOverviewCopy('${bpKey}','${type}','${id}');">Copy Styles</li>`;
        if(self.styleOverviewStates.copy.styles !== null && Object.keys(self.styleOverviewStates.copy.styles).length > 0 ) content += `<li onclick="ADMINBRXC.styleOverviewPaste('${bpKey}','${type}','${id}');">Paste Styles</li>`;
        content += `<li onclick="ADMINBRXC.styleOverviewReset('${bpKey}','${type}','${id}');">Reset Styles</li>`;
        content += `</ul>`;
        canvas.innerHTML = content;

    },
    generateVariableLabels: function(){
        const self = this;
    
        const suffixMap = [
            { suffix: '--8xl', label: ' 8XL' },
            { suffix: '--7xl', label: ' 7XL' },
            { suffix: '--6xl', label: ' 6XL' },
            { suffix: '--5xl', label: ' 5XL' },
            { suffix: '--4xl', label: ' 4XL' },
            { suffix: '--3xl', label: ' 3XL' },
            { suffix: '--2xl', label: ' 2XL' },
            { suffix: '--xl', label: ' XL' },
            { suffix: '--l', label: ' L' },
            { suffix: '--m', label: ' M' },
            { suffix: '--s', label: ' S' },
            { suffix: '--xs', label: ' XS' },
            { suffix: '--2xs', label: ' 2XS' },
            { suffix: '--3xs', label: ' 3XS' },
            { suffix: '--4xs', label: ' 4XS' },
            { suffix: '--5xs', label: ' 5XS' },
            { suffix: 'x-large', lagel: 'Extra Large'},
            { suffix: '--hover', label: ' (Hover)' },
            { suffix: '--active', label: ' (Active)' }
        ];
    
        const titleCase = str => str.replace(/\b\w/g, char => char.toUpperCase());
    
        const vars = self.vueState.globalVariables.filter(el => el.type !== "scale");
    
        vars.forEach(variable => {
            let baseName = variable.name;
            let labelSuffix = '';
    
            for (const entry of suffixMap) {
                if (baseName.includes(entry.suffix)) {
                    baseName = baseName.replace(entry.suffix, '');
                    labelSuffix += entry.label;
                }
            }
    
            baseName = baseName.replace(/^at-/, '').replaceAll('--', ' ').replace(/-/g, ' ');
            variable.label = titleCase(baseName.trim()) + labelSuffix;
        });
    }, 
    setStylTable: function(type, classId){
        const self = this;
        const breakpoints = self.vueState.breakpoints;
        const elementObject = self.styleOverviewStates.elementObj;
        const pseudo = self.styleOverviewStates.pseudo;
        const activeEl = type === "id" ? elementObject : self.vueGlobalProp.$_getGlobalClass(classId);
        if(!activeEl) return;
        const activeSettings = activeEl.settings;
        const uniqueKeys = self.helpers.stylesByPseudo(activeSettings);
        const existingKeys = [];
        const excludedKeys = ['shadeChildren', 'shadeMode', 'shadeParent', 'shadeType', 'shadeOrder', 'title'];
        let tableContent = '';

        // Create Row
        function createRow(originalObj, obj, key, prefix, path = [], nested = false) {
            let hasStyle = false
            if(excludedKeys.includes(key.split(':')[0])) return '';
    
            // Create the <tr>
            let row = `<tr class="isotope-selector">`;
            
            // If value is string, process the <td>
            if (typeof obj[key] === 'string' && !['id', 'name'].includes(key)) {
                // Prevent duplicated rows inside the table
                existingKeys.push(prefix);

                // Remove the breakpoints from the key
                key = key.split(':')[0];

                // Set the row to have styles
                noStyles = false;

                // Parse the CSS Selector
                let cssSelector;
                if (typeof bricksData.elements[elementObject.name]?.controls[key] !== "undefined" && Array.isArray(bricksData.elements[elementObject.name].controls[key].css) && bricksData.elements[elementObject.name].controls[key].css.length > 0) {
                    cssSelector = bricksData.elements[elementObject.name].controls[key].css[0].property
                } else {
                    switch(prefix){
                        case '_margin':
                        case '_padding':
                            cssSelector = `${self.helpers.camelCaseToHumanReadable(prefix)}-${self.helpers.camelCaseToHumanReadable(key)}`;
                            break;
                        case '_typography':
                            if(key === "raw") {
                                cssSelector = "color";
                                break;
                            }
                            cssSelector = self.helpers.camelCaseToHumanReadable(key);
                            break;
                        default: 
                        const equal = self.helpers.camelCaseToHumanReadable(prefix) === self.helpers.camelCaseToHumanReadable(key);

                        cssSelector = equal ? self.helpers.camelCaseToHumanReadable(prefix) : `${self.helpers.camelCaseToHumanReadable(prefix)} - ${self.helpers.camelCaseToHumanReadable(key)}`;
                    }
                }

                if(self.styleOverviewStates.search !== '' && !cssSelector.includes(self.styleOverviewStates.search)) return '';

                // Add the CSS Selector as first <td>
                const control = bricksData.elements[elementObject.name]?.controls[prefix.split(':')[0]];
                if(!control) return '';
                row +=`<td class="brxc-style-overview__css-selectors" data-click="true" data-tab="${(control.hasOwnProperty('tab')) ? control.tab : ''}" data-group="${(control.hasOwnProperty('group')) ? control.group : ''}" data-pseudo="${pseudo}">${cssSelector}</td>`;
                
                // Loop inside each breakpoints
                breakpoints.forEach(bp => {
                    // If the key is the result of a loop
                    if(nested){
                        let custompath = path.split('.');
                        bp.hasOwnProperty('key') && bp.key === "desktop" ? custompath[0] = prefix.split(':')[0] : custompath[0] = `${prefix.split(':')[0]}:${bp.key}`;
                        pseudo === '' ? '' : custompath[0] = `${custompath[0]}:${pseudo}`;
                        let target = originalObj;
                        for (let i = 0; i < custompath.length - 1; i++) {
                            if (typeof target[custompath[i]] !== "undefined") target = target[custompath[i]];
                        }
                        const finalPath = custompath.join('.');
                        let value;
                        if((target[custompath[custompath.length - 1]])){
                            value = (target[custompath[custompath.length - 1]]);
                            hasStyle = true;
                        } else {
                            value = '';
                        }
                        
                        row +=`<td><input type="text" placeholder="-" value="${(typeof value === "undefined" || !value.hasOwnProperty(key) || typeof value[key] === "undefined") ? '' : value[key]}" data-path='${finalPath}.${key}' oninput="ADMINBRXC.updateStyleOverviewValue(this.value,this.dataset.path,'${type}','${classId}')" /></td>`;
                    
                    // If the key is in the root of the object
                    } else {
                        let valuePath = (bp.hasOwnProperty('key') && bp.key === "desktop") ? key : `${key}:${bp.key}`;
                        pseudo !== '' ? valuePath = `${valuePath}:${pseudo}` : '';
                        let value;
                        if(obj[valuePath]) {
                            value = obj[valuePath];
                            hasStyle = true;
                        } else {
                            value = '';
                        };

                        row +=`<td><input type="text" placeholder="-" value="${value}" data-path='${valuePath}' oninput="ADMINBRXC.updateStyleOverviewValue(this.value,this.dataset.path,'${type}','${classId}')" /></td>`;
                    }
                })

                // Add the final <td> to the row
                row += '<td class="brxc-trash-can-col"><div class="disabled-style-icon-table trash-can" data-balloon="Delete" data-balloon-pos="left" onclick="ADMINBRXC.deleteRowStyleOverview(this);"><span class="bricks-svg-wrapper"><i class="fas fa-trash-can"></i></span></div></td></tr>';
            
            // If value is an object, loop inside the object to find a string
            } else if (typeof obj[key] === 'object') {
                const newPath = (path === key) ? key : `${path}.${key}`;
                for(const childKey of Object.keys(obj[key])){
                    createRow(originalObj, obj[key], childKey, prefix, newPath, true); 
                }
            }

            // Add the row to the table
      
            if(hasStyle) {
                return tableContent += row;
            } else {
                return;
            }
        }
          
        // Create the table
        const theadLabel = (type === "id") 
        ? `<div class="brxc-style-overview__id-tag-wrapper"><span class="brxc-style-overview__id-tag" data-click="true">#${(elementObject.settings.hasOwnProperty('_cssId')) ? elementObject.settings._cssId : 'brxe-' + elementObject.id}</span><div class="disabled-style-icon-table" data-balloon="Click to unlock styling on ID level" data-balloon-pos="bottom" onclick="ADMINBRXC.removeLockFromStyleOverview(this);"><span class="bricks-svg-wrapper"><i class="fas fa-lock"></i></span></div></div>`
        : `<span class="brxc-style-overview__class-tag locked-${self.vueGlobalProp.$_isLocked(activeEl.id)}" data-click="true">.${activeEl.name}</span>`;
        const tableClass = (type === "id") 
        ? `<table id="${elementObject.id}" class="GeneratedTable isotope-container${(self.forceClassStlyesStates.showLock || (Object.values(self.globalSettings.classFeatures).includes("disable-id-styles")) && typeof self.vueState.activeClass === "object" && Object.keys(self.vueState.activeClass).length > 0) ? ' brxc-lock-id-styles' : ''}" data-table="id">` 
        : `<table id="${activeEl.id}" class="GeneratedTable isotope-container locked-${self.vueGlobalProp.$_isLocked(activeEl.id)}" data-table="class">`;
        let table = `${tableClass}
          <thead>
            <tr class="isotope-selector always-on">
              <th>${theadLabel}</th>`;
              breakpoints.forEach(bp=> {
                table +=`<th><div class="brxc-breakpoint-wrapper"><div class="brxc-breakpoint-inner"><div class="brxc-skip-remount brxc-group-icon${(self.vueState.breakpointActive === bp.key) ? ' active' : ''}" data-balloon="${bp.label}" data-balloon-pos="bottom">${self.helpers.bpIcons(bp.icon)}</div><div class="brxc-breakpoint-settings" data-key="${bp.key}" onclick="ADMINBRXC.setStyleOverviewBPMenu(this)"><span class="bricks-svg-wrapper"><svg version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg" style="rotate: 90deg;"><path d="M3,9.5l-6.55671e-08,-1.77636e-15c-0.828427,-3.62117e-08 -1.5,-0.671573 -1.5,-1.5c3.62117e-08,-0.828427 0.671573,-1.5 1.5,-1.5l-6.55671e-08,1.77636e-15c0.828427,-3.62117e-08 1.5,0.671573 1.5,1.5c3.62117e-08,0.828427 -0.671573,1.5 -1.5,1.5Zm5,0l-6.55671e-08,-1.77636e-15c-0.828427,-3.62117e-08 -1.5,-0.671573 -1.5,-1.5c3.62117e-08,-0.828427 0.671573,-1.5 1.5,-1.5l-6.55671e-08,1.77636e-15c0.828427,-3.62117e-08 1.5,0.671573 1.5,1.5c3.62117e-08,0.828427 -0.671573,1.5 -1.5,1.5Zm5,0l-6.55671e-08,-1.77636e-15c-0.828427,-3.62117e-08 -1.5,-0.671573 -1.5,-1.5c3.62117e-08,-0.828427 0.671573,-1.5 1.5,-1.5l-6.55671e-08,1.77636e-15c0.828427,-3.62117e-08 1.5,0.671573 1.5,1.5c3.62117e-08,0.828427 -0.671573,1.5 -1.5,1.5Z" fill="currentColor" fill-rule="evenodd"></path></svg></span></div><div class="brxc-breakpoint-menu-canvas"></div></div></div></th>`;
              })
              table += `<th class="brxc-trash-can-col"></th>`
        table +=`</tr>
          </thead>
          <tbody>`;
          let noStyles = true;
          
          // Loop inside the values
          const arrKey = pseudo === '' ? 'no-pseudo' : pseudo;
        
          uniqueKeys[arrKey].forEach(key =>{

                // Prevent duplicated rows inside the table
                if(existingKeys.includes(key.split(':')[0])) return '';

                let prefix = key.split(':')[0];
                // Process the row creation
                createRow(activeSettings, activeSettings, key, prefix, key, false)
          })
          // return empty if there is no rows
          if( self.styleOverviewStates.search !== "" && tableContent === "") {
            return '';
          }

          table += tableContent;

          // If there is no styles, print a default row
          if(noStyles) table += `<tr class="isotope-selector"><td class="brxc-no-style-found"><div data-control="info">No Styles Found.</div></td></tr>`;
        

        // Add closing tags to the table
        table += `</tbody></table>`;

        // Return the table
        return table;
    },
    deleteRowStyleOverview: function(target){
        const self = this;
        const body = document.querySelector("#brxcStyleOverviewBody");
        const tr = target.closest('tr');
        const inputs = tr.querySelectorAll('input');
        inputs.forEach(el =>{
            el.value = '';
            const evt = new Event('input');
            el.dispatchEvent(evt);
        })

        const scroll = body.scrollTop;
        self.setStyleOverview()
        document.querySelector('#brxcStyleOverviewBody').scrollTop = scroll;
    },
    removeLockFromStyleOverview: function(target){
        const self = this;
        const panel = document.querySelector('#bricks-panel-element');
        if(!panel) return;
        const icon = panel.querySelector('.disabled-style-icon');
        self.forceClassStlyesStates.showLock = false;
        (icon) ? icon.remove() : '';
        target.closest('table').classList.remove('brxc-lock-id-styles');
    },
    updateStyleOverviewValue: function(value,path, type, classId){
        const self = this;
        let activeEl = type === 'id' ? self.styleOverviewStates.elementObj : self.vueGlobalProp.$_getGlobalClass(classId);
        const activeSettings = activeEl.settings;

        if(path){
            path = path.split('.')

            let target = activeSettings;

            if(!value || value === "") {
                for (let i = 0; i < path.length - 1; i++) {
                    if(target.hasOwnProperty(path[i])) target = target[path[i]];
                }

                if (typeof target[path[path.length - 1]] !== "undefined") delete target[path[path.length - 1]];
                for(const key of Object.keys(target)){
                    if (typeof target[key] === "object" && Object.keys(target[key]).length === 0) delete target[key];
                }
            } else {
                for (let i = 0; i < path.length - 1; i++) {
                    if (!target[path[i]]) target[path[i]] = {};
                    target = target[path[i]];
                }
                target[path[path.length - 1]] = value;
            }
        }
    },

    setStyleOverviewPreview: function(){
        const self = this;

        const content = Array.from(self.helpers.getContent(true)).filter(el => el && el.parent === 0);
        const activeId = self.styleOverviewStates.elementObj.id;
        function addElement(originalElement, element, level, isComponent){
            let content = '';
            let classes = [];
            if(element.id === activeId) classes.push('active');
            if(isComponent) classes.push('is-component');
            content += `<li class="${classes.join(' ')}" data-id="${originalElement.id}"${isComponent ? ` data-component="${isComponent.id}"` : ''}${self.helpers.elementHasStyle(element.settings) ? ` data-has-style="true"` : ''}${self.helpers.elementHasClass(element.settings) ? ` data-has-class="true"` : ''} style="--margin:${level};"}>
                            <div class="icon"><i class="${bricksData.elements[element.name]?.icon}"></i></div>
                            <span>${element.label ? element.label : bricksData.elements[element.name]?.label}</span>
                        </li>`;
            return content;
        }

        function checkchildren(element, level, isComponent) {
            if (!element.children || element.children.length < 1 || (isComponent && self.styleOverviewStates.componentsExpanded === false)) {
                return;
            }
            level++;
        
            element.children.forEach(id => {
                const childOriginalElement = self.helpers.getElementObject(id, true);
                const settings = self.helpers.getElementObject(id);
                if(!settings) return;

                const childIsComponent = isComponent || 
                    (self.vueState.hasOwnProperty('components') && 
                     self.vueState.components.find(el => el.id === settings.id));
        
                output += addElement(childOriginalElement, settings, level, childIsComponent);
                checkchildren(settings, level, childIsComponent);
            });
        }

        let output = `<ul id="brxcStyleOverviewPreview" class="brxc-structure-list__wrapper ${self.structureHelperStates.expanded === true ? 'expanded' : 'collapsed'}">`;
        content.forEach(el => {
            const originalElement = self.helpers.getElementObject(el.id, true);
            const element = self.helpers.getElementObject(el.id);
            let isComponent = self.vueState.hasOwnProperty('components') && self.vueState.components.find(el => el.id === element.id);
            output += addElement(originalElement, element, 0, isComponent);
            checkchildren(element, 0, isComponent);
        })
        output += '</ul>';

        return output;

    },
    setStyleOverview: function(focus = false){
        const self = this;
        const canvas = document.querySelector('#brxcStyleOverviewOverlay #brxcStyleOverviewCanvas');
        if(!canvas) return;

        const pseudo = self.styleOverviewStates.pseudo;

        // opening wrapper
        let content = '';
        let tables = '';
        
        content += `<div id="brxcStyleOverviewWrapper" class="${self.styleOverviewStates.structure ? 'brxc-preview' : ''}"><div id="brxcStyleOverviewBody">`;

        // Header
        if(self.styleOverviewStates.panel === "table") content += self.setStyleOverviewHeader();

        // id table
        tables += self.setStylTable("id", false, pseudo);

        //class tables
        if(self.styleOverviewStates.globalClasses){
            self.styleOverviewStates.globalClasses.forEach(el => {
                const cls = self.vueGlobalProp.$_getGlobalClass(el);
                if(!cls) return;
                tables += self.setStylTable("class", el, pseudo);
            })
        }
        if(tables !== ''){
            content += tables;
        } else {
            content += `<div class="notification" style=""><span class="bricks-svg-wrapper" data-name="no-results"><svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="bricks-svg"><path d="M0.75 12a11.25 11.25 0 1 0 22.5 0 11.25 11.25 0 1 0 -22.5 0Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"></path><path d="M15.665 18.75a0.76 0.76 0 0 0 0.744 -0.9 4.5 4.5 0 0 0 -8.818 0 0.759 0.759 0 0 0 0.744 0.9Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"></path><path d="m6.75 6.75 3 3 -3.75 0" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"></path><path d="m17.25 6.75 -3 3 3.75 0" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"></path></svg></span><div class="message"><p>No styles found.</p></div></div>`;
        }
        content += '</div>'

        // preview
        if(self.styleOverviewStates.structure) content += self.setStyleOverviewPreview();

        
        
        // closing wrapper
        content += '</div>';

        canvas.innerHTML = content;

        // Preview
        const previewWrapper = document.querySelector('#brxcStyleOverviewPreview');
        if(previewWrapper){
            previewWrapper.addEventListener('click', (e) => {
                const li = e.target.closest('[data-id]');
                if(!li) return;

                const id = li.dataset?.id
                if(id){
                    const elementObj = self.helpers.getElementObject(id);
                    self.styleOverviewInit(elementObj, true);
                }
            })
        }

        const body = document.querySelector('#brxcStyleOverviewBody');
        if(body){
            //click 
            body.addEventListener('click', (event) => {
                const el = event.target.closest('[data-click="true"]');
                if(!el) return;

                const table = el.closest('table');
                const tab = el.dataset.tab;
                const group = el.dataset.group;
                const pseudo = el.dataset.pseudo;
                self.vueState.activeClass = table.dataset.table === "class" ? self.vueGlobalProp.$_getGlobalClass(table.id) : '';
                self.openElement(self.styleOverviewStates.elementObj.id);

                if (!pseudo || pseudo === '') {
                    self.vueState.pseudoClassActive = '';
                    self.vueState.pseudoClassPopup = false;
                } else {
                    self.vueState.pseudoClassActive = `:${pseudo}`;
                    self.vueState.pseudoClassPopup = true;
                }
                if(group) self.vueState.activePanelGroup = group;
                if(tab) self.vueState.activePanelTab = tab;
                self.closeModal(event, event.target, '#brxcStyleOverviewOverlay');
            })

            //autocomplete
            body.addEventListener('focusin', (event) => {
                const el = event.target;
                if (el.tagName === 'INPUT' && el.closest('td')) {
                    self.autocomplete(el, self.cssVariables, "style", true);
                }
            });
        }

        //focus
        const searchInput = document.querySelector('#brxcStyleOverviewCanvas input[type="text"]');
        if(searchInput&& focus){
            searchInput.focus();
            searchInput.setSelectionRange(searchInput.value.length, searchInput.value.length);
        }

    },
    styleOverviewToggleOption: function(key){
        const self = this;
        self.styleOverviewStates[key] = !self.styleOverviewStates[key]
        self.styleOverviewInit();
    },
    setStyleOverviewHeader: function(){
        const self = this;
        const activeElement = self.styleOverviewStates.elementObj;
        const pseudo = self.styleOverviewStates.pseudo;

        function hasStyle(){
            let hasPseudo = false;
            for(const key of Object.keys(activeElement.settings)){
                const arr = key.split(':');
                if(arr[1] === undefined && self.helpers.isCSSControlKey(arr[0])) hasPseudo = true;
            }

            if(hasPseudo === true) return true;

            if(self.styleOverviewStates.globalClasses){
                self.styleOverviewStates.globalClasses.forEach(el => {
                    const obj = self.vueGlobalProp.$_getGlobalClass(el);
                    if(obj && obj.hasOwnProperty('settings')){
                        for(const key of Object.keys(obj.settings)){
                            const arr = key.split(':');
                            if(arr[1] === undefined && self.helpers.isCSSControlKey(arr[0])) hasPseudo = true;
                        }
                    }
                })
            }

            if(hasPseudo === true) return true;

            return false;
        }
        function hasPseudoStyle(pseudo){
            let hasPseudo = false;
            for(const key of Object.keys(activeElement.settings)){
                if(JSON.stringify(key).includes(pseudo)) hasPseudo = true;
            }
            if(hasPseudo === true) return true;

            if(self.styleOverviewStates.globalClasses){
                self.styleOverviewStates.globalClasses.forEach(el => {
                    const obj = self.vueGlobalProp.$_getGlobalClass(el);
                    if(obj && obj.hasOwnProperty('settings')){
                        for(const key of Object.keys(obj.settings)){
                            if(JSON.stringify(key).includes(pseudo)) hasPseudo = true;
                        }
                    }
                })
            }

            if(hasPseudo === true) return true;

            return false;

        }

        let content = '<div id="brxcStyleOverviewCanvasHeader">';
        //pseudo
        content += `<div class="brxc-overlay__panel-switcher-wrapper style-overview">
                        <input type="radio" id="style-overview-no-pseudo" name="style-overview-switch" class="brxc-input__radio" onclick="ADMINBRXC.styleOverviewStates.pseudo = '';ADMINBRXC.setStyleOverview();"${(pseudo === '') ? ' checked=""' : ''}>
                        <label for="style-overview-no-pseudo" class="brxc-input__label${hasStyle() ? ' has-style' : ''}">No Pseudo</label>`;
        self.vueState.pseudoClasses.forEach(el => {
            content += `<input type="radio" id="style-overview-${el.substr(1, el.length - 1)}" name="style-overview-switch" class="brxc-input__radio" onclick="ADMINBRXC.styleOverviewStates.pseudo = '${el.replace(':','')}';ADMINBRXC.setStyleOverview();"${(pseudo === el.replace(':','')) ? ' checked=""' : ''}>
                        <label for="style-overview-${el.substr(1, el.length - 1)}" class="brxc-input__label${hasPseudoStyle(el) ? ' has-style' : ''}"><span>${el}</span></label>`;
        })
        content += `<div class="brxc-overlay__panel-switcher-wrapper">
                        <input type="radio" id="style-overview-bricks" name="style-overview-switch-css" class="brxc-input__radio" onclick="ADMINBRXC.styleOverviewStates.panel = 'table';ADMINBRXC.styleOverviewInit();" checked>
                        <label for="style-overview-bricks" class="brxc-input__label" style="margin-left: auto"><span>Bricks</span></label>
                        <input type="radio" id="style-overview-css" name="style-overview-switch-css" class="brxc-input__radio" onclick="ADMINBRXC.styleOverviewStates.panel = 'css';ADMINBRXC.styleOverviewInit();">
                        <label for="style-overview-css" class="brxc-input__label has-style"><span>CSS</span></label>
                        <div class="brxc-header-icons ${self.styleOverviewStates.structure === true ? ' active' : ''}" data-balloon="Toggle Structure" data-balloon-pos="left" onclick="ADMINBRXC.styleOverviewToggleOption('structure')"><span class="bricks-svg-wrapper"><i class="bricks-svg fas fa-bars-staggered"></i></span></div>
                        <div class="brxc-header-icons ${self.styleOverviewStates.componentsExpanded === true ? ' active' : ''}" data-balloon="Toggle Components" data-balloon-pos="left" onclick="ADMINBRXC.styleOverviewToggleOption('componentsExpanded')"><span class="bricks-svg-wrapper"><i class="bricks-svg fas ti-package"></i></span></div>
                    </div>`;
        content += `</div>`;

        content += '<div class="isotope-wrapper--late" data-gutter="0" data-filter-layout="fitRows" style="--col:1">';
        
        //Search

        content += `<div class="brxc-overlay__search-box"><div class="iso-search-icon"><i class="bricks-svg ti-search"></i></div><input type="text" class="iso-search" name="typography-search" placeholder="Type here to filter the CSS properties" data-type="textContent" value="${self.styleOverviewStates.search}" oninput="ADMINBRXC.styleOverviewStates.search = this.value;ADMINBRXC.setStyleOverview(true)"><div class="iso-reset" onclick="ADMINBRXC.styleOverviewStates.search = '';ADMINBRXC.setStyleOverview(true)"><i class="bricks-svg ti-close"></i></div></div>`;
        
        // Classes Buttons
        content += '<div class="brxc-style-overview__class-wrapper">';
        if(self.styleOverviewStates.globalClasses){
            self.styleOverviewStates.globalClasses.forEach(el => {
                const cls = self.vueGlobalProp.$_getGlobalClass(el);
                if(!cls) return;
                content += `<a class="brxc-style-overview__class-btn locked-${self.vueGlobalProp.$_isLocked(cls.id)}" onclick="document.getElementById('${cls.id}')?.scrollIntoView();">.${cls.name}</a>`;
            })
        }
        content += '</div></div></div>';
        return content;
    },
    setStyleOverviewCSS: function(){
        const self = this;
        const canvas = document.querySelector('#brxcStyleOverviewOverlay #brxcStyleOverviewCanvas');
        if(!canvas) return;
        
        let content = '';

        content += `<div id="brxcStyleOverviewWrapper" class="${self.styleOverviewStates.structure ? 'brxc-preview' : ''}">
                        <div id="brxcStyleOverviewBody">
                            <div class="brxc-overlay__panel-switcher-wrapper">
                                <input type="radio" id="style-overview-bricks" name="style-overview-switch-css" class="brxc-input__radio" onclick="ADMINBRXC.styleOverviewStates.panel = 'table';ADMINBRXC.styleOverviewInit();">
                                <label for="style-overview-bricks" class="brxc-input__label has-style" style="margin-left: auto"><span>Bricks</span></label>
                                <input type="radio" id="style-overview-css" name="style-overview-switch-css" class="brxc-input__radio" onclick="ADMINBRXC.styleOverviewStates.panel = 'css';ADMINBRXC.styleOverviewInit();" checked>
                                <label for="style-overview-css" class="brxc-input__label"><span>CSS</span></label>
                                <div class="brxc-header-icons ${self.styleOverviewStates.structure === true ? ' active' : ''}" data-balloon="Toggle Structure" data-balloon-pos="left" onclick="ADMINBRXC.styleOverviewToggleOption('structure')"><span class="bricks-svg-wrapper"><i class="bricks-svg fas fa-bars-staggered"></i></span></div>
                        <div class="brxc-header-icons ${self.styleOverviewStates.componentsExpanded === true ? ' active' : ''}" data-balloon="Toggle Components" data-balloon-pos="left" onclick="ADMINBRXC.styleOverviewToggleOption('componentsExpanded')"><span class="bricks-svg-wrapper"><i class="bricks-svg fas ti-package"></i></span></div>
                            </div>`;
        
        const elementObj = self.styleOverviewStates.elementObj;
        const globalClasses = self.styleOverviewStates.globalClasses

        // id table
        content += `<div class="brxc-style-overview__id-tag-wrapper" style="margin-bottom:8px;"><span class="brxc-style-overview__id-tag" data-click="true" data-balloon="Click to jump on the ID styles" data-balloon-pos="right">#${(elementObj.settings.hasOwnProperty('_cssId')) ? elementObj.settings._cssId : 'brxe-' + elementObj.id}</span></div>`;
        content += self.setStyleCSS("element", elementObj, false);

        //class tables
        if(globalClasses && globalClasses.length > 0){
            self.styleOverviewStates.globalClasses.forEach(el => {
                let activeEl = self.vueGlobalProp.$_getGlobalClass(el);
                if(!activeEl) return;
                content += `<div class="brxc-style-overview__id-tag-wrapper" style="margin: 20px 0 8px 0;"><span class="brxc-style-overview__class-tag locked-${self.vueGlobalProp.$_isLocked(activeEl.id)}" data-click="true" data-balloon="Click to jump on this Class styles" data-balloon-pos="right">.${activeEl.name}</span></div>`;
                content += self.setStyleCSS("globalClass", activeEl, [elementObj.name]);
            })
        }
        content += '</div>';

        // preview
        if(self.styleOverviewStates.structure) content += self.setStyleOverviewPreview();

        // closing wrapper
        content += '</div>';

        canvas.innerHTML = content;

        // Preview
        const previewWrapper = document.querySelector('#brxcStyleOverviewPreview');
        if(previewWrapper){
            previewWrapper.addEventListener('click', (e) => {
                const li = e.target.closest('[data-id]');
                if(!li) return;

                const id = li.dataset?.id
                if(id){
                    const elementObj = self.helpers.getElementObject(id);
                    self.styleOverviewInit(elementObj, true);
                }
            })
        }

        const textAreas = document.querySelectorAll('textarea.brxc-style-overview-css');
        textAreas.forEach(textarea => {
            const dataOptions = { indent_size: 2 }

            textarea.value = css_beautify(textarea.value, dataOptions);

            const options = self.codeMirrorOptions(textarea);
            options.autofocus = false;
            options.readOnly = true;

            CodeMirror.fromTextArea(textarea, self.codeMirrorOptions(options));
        })
    },
    setStyleCSS: function(type, activeEl, name){
        const self = this;
        content = `<div class="brxc-codemirror__wrapper"><textarea class="brxc-style-overview-css">${self.vueGlobalProp.$_generateCss(type, activeEl, name)}</textarea>`;
        content += `<div class="brxc-overlay__action-btn" style="margin-left: auto" onclick="ADMINBRXC.copytoClipboard(this, this.previousElementSibling.CodeMirror.getValue(), 'Copied!', 'Copy to Clipboard')"><span>Copy to Clipboard</span></div></div>`;

        return content;
    },
    permadeleteClasses: function(){
        const self = this;

        let removedClasses = [];

        function removeObj(id){
            const obj = self.helpers.getElementObject(id);
            if(!obj) return;

            const contentType = self.helpers.getTemplateType();

            const hasGlobalClasses = obj.settings.hasOwnProperty('_cssGlobalClasses') && obj.settings._cssGlobalClasses.length > 0;
            if(hasGlobalClasses){
                clsArr = obj.settings._cssGlobalClasses;
                removedClasses.push(...obj.settings._cssGlobalClasses)
            }

            const index = self.vueState[contentType].indexOf(obj);
            if(index > -1){
                self.vueState[contentType].splice(index, 1)
            }

            // Children
            if(obj.children && Array.isArray(obj.children) && obj.children.length > 0){
                obj.children.forEach(child => {
                    removeObj(child)
                })
            }
        }
        removeObj(self.vueState.activeElement.id);

        // Unique ID's
        removedClasses = [...new Set(removedClasses)];

        // Move to trash
        if(removedClasses.length > 0){
            self.vueGlobalProp.$_moveGlobalClassesToTrash(removedClasses);
            self.vueGlobalProp.$_showMessage(`${removedClasses.length} classes have been moved to the trash!`);
        }

        self.vueState.activeClass = "";
        self.vueState.activeElement = undefined;
        self.vueState.activePanel = "elements";
        FRAMEBRXC.vueState.activeClass = "";
        FRAMEBRXC.vueState.activeElement = undefined;
        FRAMEBRXC.vueState.activePanel = "elements";
    },
    setContextualMenuItems: function(){
        const self = this;
        const contextualWrapper = document.querySelector("#bricks-builder-context-menu");
        let contextualMenu = contextualWrapper.children[0].children[0];
        let icons = '';
        if(self.helpers.isBuilderTweaksTabActive('structure-panel')){
            const directions = [
                { direction: 'left', label: 'Indent Left', icon: 'fa-arrow-left' },
                { direction: 'right', label: 'Indent Right', icon: 'fa-arrow-right' },
                { direction: 'top', label: 'Move Up', icon: 'fa-arrow-up' },
                { direction: 'down', label: 'Move Down', icon: 'fa-arrow-down' },
            ];
        
            const buttons = directions
                .map(
                    ({ direction, label, icon }) => `
                    <span class="action" 
                            data-balloon="${label}" 
                            data-balloon-pos="top" 
                            onClick="event.stopPropagation();ADMINBRXC.moveElement(event, '${direction}');ADMINBRXC.vueState.showContextMenu = ADMINBRXC.vueState.activeElement?.id;">
                        <i class="fas ${icon}"></i>
                    </span>`
                )
                .join('');
        
            icons += `
                <li id="moveElement">
                    <span class="label">Move</span>
                    <div class="buttons">${buttons}</div>
                </li>`;
            
            icons += `<li id="brxcExpandClasses" onClick='ADMINBRXC.openExtendClassModal(event,"#brxcExtendModal")'>Extend Classes & Styles</li>`;
            icons += `<li id="brxcFindandReplaceStyles" onClick='ADMINBRXC.openFindReplaceModal(event,false, "#brxcFindReplaceModal")'>Find & Replace Styles</li>`;
            icons += `<li id="brxcBEMConverter" onClick='ADMINBRXC.openModal({target: false, id: "#brxcClassConverterOverlay", callback: () => {ADMINBRXC.setClassConverter();}})';'><span class="label">Class Converter</span></li>` ;
            icons += `<li id="brxcStyleOverview" onClick='ADMINBRXC.openModal({target: false, id: "#brxcStyleOverviewOverlay", focus: "#brxcStyleOverviewOverlay input[type=text]", callback: () => {ADMINBRXC.styleOverviewInit(ADMINBRXC.helpers.getFinalObject(true),true);}});this.style.display = "none"; this.style.display = "flex";'>Style Overview</li>` ;
            icons += `<li id="brxcComponentClassManager" onClick='ADMINBRXC.openClassManager("component");'>Component Class Manager</li>` ;
            icons += `<li id="brxcSaveComponent" onClick='ADMINBRXC.openModal({target: false, id: "#brxcAddCustomComponentsOverlay", callback: () => {ADMINBRXC.setAddCustomComponents();}});'>Save as Nested Element</li>`;
            icons += `<li class="sep"></li>`;
        }

        contextualMenu.insertAdjacentHTML("beforeBegin", icons);

        // Paste Logical Properties
        const pasteItem = contextualWrapper.querySelector('[title="CMD + V"]');
        if(pasteItem){
            const newIcon = `<span class="bricks-svg-wrapper action convert-logical" data-name="hash" data-balloon="Convert Logical Properties" data-balloon-pos="top-right" onClick="event.stopPropagation();ADMINBRXC.pasteElementLogicalProperties()"><i class="fas fa-exchange"></i></span>`;
            pasteItem.insertAdjacentHTML("afterEnd",newIcon);
        }

        // Delete corresponding global classes
        const deleteItem = contextualWrapper.querySelector('.delete');
        if (deleteItem) {
            const wrapper = document.createElement('div');
            wrapper.innerHTML = `<span class="bricks-svg-wrapper action delete-classes" data-name="hash" data-balloon="Move Classes to Trash" data-balloon-pos="top-right" onClick="event.stopPropagation();ADMINBRXC.permadeleteClasses()"><i class="fas fa-trash"></i></span>`;
            deleteItem.appendChild(wrapper.firstElementChild);
        }
        
    },
    pasteElementLogicalProperties: function(event){
        const self = this;
        if(!navigator.clipboard){
            return self.vueGlobalProp.$_showMessage('ABORT: Unable to access the clipboard')
        }
        navigator.clipboard.readText()
            .then((text) => {
                if(!text.trim().startsWith(`{"content"`)){
                    return self.vueGlobalProp.$_showMessage('ABORT: No content found')
                }
                const parsedText = JSON.parse(text);
                const content = self.helpers.assignNewIdsToElements(parsedText.content);
                const position = self.builderStates.isElementActive ? self.helpers.getElementRootIndex(self.builderStates.activeElement.id) + 1 : false;
                // Content
                self.convertTemplateData(
                    false, 
                    content,
                    (responseData) => {
                        self.insertTemplateData({
                          response: responseData.response,
                          position: position
                        });
                    },
                    position
                )

                // Global Classes
                if(parsedText.hasOwnProperty('globalClasses')){
                    parsedText.globalClasses.forEach(cls => {
                        if (!self.vueState.globalClasses.some(el => el.id === cls.id)) {
                            if(self.globalSettings.defaultElementFeatures.includes('logical-properties')){
                                if(!cls.hasOwnProperty('settings')) return;
                                cls.settings = self.convertToLogicalProperties(cls.settings);
                            }
                            self.vueState.globalClasses.push(cls);
                        }
                    });
                }
            })
            .catch((err) => {
                console.error('Failed to read clipboard contents: ', err);
        });

    },
    toggleTagsState: function (){
        const self = this;
        if(self.elementsTagStates.mode === 'developer'){
            self.elementsTagStates.mode = '';
        } else if (self.elementsTagStates.mode === ''){
            self.elementsTagStates.mode = 'overview';
        }  else if (self.elementsTagStates.mode === 'overview'){
            self.elementsTagStates.mode = 'developer';
        }
        self.helpers.setLocalStorage('elementsTag', self.elementsTagStates.mode)
        self.setHeaderStructurePanel()
        self.runStructureHighlights()
    },
    toggleNotesState: function(){
        const self = this;
        if(self.noteStates.active === 'adminNotes'){
            self.noteStates.active = 'editorNotes';
        } else if(self.noteStates.active === 'editorNotes'){
            self.noteStates.active = 'none';
        } else if(self.noteStates.active === 'none'){
            self.noteStates.active = 'adminNotes';
        }
        self.helpers.setLocalStorage('structureNotes', self.noteStates.active)

        setTimeout(() => {
            self.setHeaderStructurePanel()
            self.runStructureHighlights()
        },10)
    },
    structureHelperStates:{
        expanded: true,
        showTag: true,
        showId: true,
        highlight: false,
        renameMode: true,
        extendComponent: true,
        activeFilter: false,
        filterArr: [],
    },
    setStructureHelper: function(){
        const self = this;
        self.setStructureHelperList();
        if(self.structureHelperStates.activeFilter){
            const activeLi = document.querySelector(`#brxcStructureHelper .brxc-overlay__pannel-col--left li[data-id="${self.structureHelperStates.activeFilter}"]`);
            if(activeLi) activeLi.click()
            
        }
    },
    setStructureHelperList: function(){
        const self = this;
        const canvas = document.querySelector('#structurPanelList');
        if(!canvas) return;

        let content = `<div class="brxc-structure-panel-list__header">
                        <span>Structure</span>
                        <div class="actions">`;
        self.structureHelperStates.expanded !== true ? content += `<div class="bricks-svg-wrapper active" data-balloon="Expand" data-balloon-pos="bottom-right" onclick="ADMINBRXC.structureHelperStates.expanded = true;ADMINBRXC.setStructureHelperList()"><i class="fas fa-up-right-and-down-left-from-center"></i></div>` : content += `<div class="bricks-svg-wrapper" data-balloon="Collapse" data-balloon-pos="bottom-right" onclick="ADMINBRXC.structureHelperStates.expanded = false;ADMINBRXC.setStructureHelperList()"><i class="fa-solid fa-down-left-and-up-right-to-center"></i></i></i></div>`;
        content += `<div class="bricks-svg-wrapper${ADMINBRXC.structureHelperStates.showTag ? ' active' : ''}" data-balloon="${ADMINBRXC.structureHelperStates.showTag ? 'Hide HTML tags' : 'Show HTML tags'}" data-balloon-pos="bottom-right" onclick="ADMINBRXC.structureHelperStates.showTag = ${ADMINBRXC.structureHelperStates.showTag ? false : true};ADMINBRXC.setStructureHelperList()"><i class="fas fa-code"></i></div>`;
        content += `<div class="bricks-svg-wrapper${ADMINBRXC.structureHelperStates.showId ? ' active' : ''}" data-balloon="${ADMINBRXC.structureHelperStates.showId ? 'Hide Ids' : 'Show Ids'}" data-balloon-pos="bottom-right" onclick="ADMINBRXC.structureHelperStates.showId = ${ADMINBRXC.structureHelperStates.showId ? false : true};ADMINBRXC.setStructureHelperList()"><i class="fas fa-id-card"></i></div>`;
        content += `<div class="bricks-svg-wrapper${ADMINBRXC.structureHelperStates.highlight ? ' active' : ''}" data-balloon="${ADMINBRXC.structureHelperStates.highlight ? 'Disable Highlight' : 'Enable Highlight'}" data-balloon-pos="bottom-right" onclick="ADMINBRXC.structureHelperStates.highlight = ${ADMINBRXC.structureHelperStates.highlight ? false : true};ADMINBRXC.setStructureHelperList()"><i class="fas fa-eye${!ADMINBRXC.structureHelperStates.highlight ? '-slash' : ''}"></i></div>`;
        content += `<div class="bricks-svg-wrapper${ADMINBRXC.structureHelperStates.renameMode ? ' active' : ''}" data-balloon="${ADMINBRXC.structureHelperStates.renameMode ? 'Rename Mode On' : 'Rename Mode Off'}" data-balloon-pos="bottom-right" onclick="ADMINBRXC.structureHelperStates.renameMode = ${ADMINBRXC.structureHelperStates.renameMode ? false : true};ADMINBRXC.setStructureHelperList()"><i class="fas fa-edit"></i></div>`;
        content += `<div class="bricks-svg-wrapper${ADMINBRXC.structureHelperStates.extendComponent ? ' active' : ''}" data-balloon="${ADMINBRXC.structureHelperStates.extendComponent ? 'Components Extended' : 'Components Collapsed'}" data-balloon-pos="bottom-right" onclick="ADMINBRXC.structureHelperStates.extendComponent = ${ADMINBRXC.structureHelperStates.extendComponent ? false : true};ADMINBRXC.setStructureHelperList()"><i class="ti-package"></i></div>`;
        content += `</div></div>`; 
        content += self.structureHelperPreview();

        canvas.innerHTML = content;

        const li = canvas.querySelectorAll('li');
        if(!li || li.length < 1) return;

        if(self.structureHelperStates.renameMode) {
            li.forEach(el => {
                const input = el.querySelector('input');
                ['blur', 'keyup'].forEach(type => {
                    input.addEventListener(type, (e) => {
                    if(type === "keyup" && e.key != "Enter") return;
                    if(e.target.value === "") return self.setStructureHelperList();
                    const obj = self.helpers.getElementObject(el.dataset.id);
                    if(!obj) return;
                    obj.label = e.target.value;
                    })
                })
            })

            return;
        }

        li.forEach(el => {
            el.addEventListener('click', (e) => {
                const obj = self.helpers.getElementObject(el.dataset.id);
                if(!obj) return;
                self.openElement(obj.id);
                self.closeModal(e, e.target, '#brxcStructureHelper');

            })
        })
    },
    structureHelperPreview: function(){
        const self = this;

        const content = Array.from(self.helpers.getContent(true)).filter(el => el && el.parent === 0);


        function addElement(originalElement, element, level, isComponent){
            const check = Array.from(self.structureHelperStates.filterArr).find(el => el && el.hasOwnProperty('id') && el.id === element.id);
            let classNames = [];
            if(check || self.structureHelperStates.highlight) classNames.push('active');
            if(self.structureHelperStates.renameMode) classNames.push('editable');
            if(isComponent) classNames.push('is-component')
            let content = '';
            content += `
            <li class="${classNames.join(' ')}" data-id="${originalElement.id}"${isComponent ? ` data-component="${isComponent.id}"` : ''} style="--margin:${level};"}>
                <div class="icon"><i class="${bricksData.elements[element.name]?.icon}"></i></div>`;
                if(self.structureHelperStates.showTag) {
                    const obj = self.helpers.getElementObject(element.id);
                    const tag = self.helpers.getElementTag(obj);
                    content += `<span class="show-tag">${tag}</span>`;
                }
                content +=  self.structureHelperStates.renameMode ? `<input type="text" value="${element.label ? element.label : bricksData.elements[element.name]?.label}" />`: `<span>${element.label ? element.label : bricksData.elements[element.name]?.label}</span>`;
                if(self.structureHelperStates.showId) {
                    const elId = element.settings.hasOwnProperty('_cssId') ? element.settings._cssId : `brxe-${element.id}`;
                    content += `<span class="show-id">#${elId}
                                <div class="copy-id-icon" data-balloon="Copy ID to Clipboard" data-balloon-pos="top-right" onclick="event.stopPropagation();ADMINBRXC.copytoClipboardSimple('#${elId}','#${elId} successfully copied to clipboard')"><i class="fas fa-clipboard"></i></div>
                                </span>`;
                }
            content +=  `</li>`;
            return content;
        }

        function checkchildren(element, level, isComponent) {
            if (element.children.length < 1 || (isComponent && self.structureHelperStates.extendComponent === false)) {
                return;
            }
            level++;
        
            element.children.forEach(id => {
                const childOriginalElement = self.helpers.getElementObject(id, true);
                const settings = self.helpers.getElementObject(id);

                if(!childOriginalElement || !settings) return;
                
                const childIsComponent = isComponent || 
                    (self.vueState.hasOwnProperty('components') && 
                     self.vueState.components.find(el => el.id === settings.id));
        
                output += addElement(childOriginalElement, settings, level, childIsComponent);
                checkchildren(settings, level, childIsComponent);
            });
        }

        let output = self.structureHelperStates.expanded === true ? '<ul class="brxc-structure-list__wrapper expanded">' : `<ul class="brxc-structure-list__wrapper collapsed">`;
        content.forEach(el => {
            const originalElement = self.helpers.getElementObject(el.id, true);
            const element = self.helpers.getElementObject(el.id);
            let isComponent = self.vueState.hasOwnProperty('components') && self.vueState.components.find(el => el.id === element.id);
            output += addElement(originalElement, element, 0, isComponent);
            checkchildren(element, 0, isComponent);
        })
        output += '</ul>';

        return output;
    },
    shCheckProp: function(event, prop){
        const self = this;
        const setItem = self.helpers.setActiveItem('#brxcStructureHelper .brxc-overlay__pannel-col--left li', event);
        if(!setItem) return;

        const content = self.helpers.getContentWithComponents();

        // Function
        self.structureHelperStates.filterArr = Array.from(content).filter(el => el && Object.keys(el.settings).some(function(k){ return ~k.indexOf(prop) }));
        self.setStructureHelperList();
        self.structureHelperStates.activeFilter = event.target.dataset.id;
    },
    shCheckPropArray: function(event, prop, number){
        const self = this;
        const setItem = self.helpers.setActiveItem('#brxcStructureHelper .brxc-overlay__pannel-col--left li', event);
        if(!setItem) return;


        // Classes
        const contentArray = self.helpers.getContentWithComponents();
        const usedGlobalClasses = contentArray
        .flatMap(el => el && el.settings.hasOwnProperty('_cssGlobalClasses') ? el.settings._cssGlobalClasses : []);

        const corrispondingGlobalClasses = self.vueState.globalClasses
        .filter(el => usedGlobalClasses.includes(el.id) && Array.isArray(el.settings[prop]) && el.settings[prop].length > number)
        .map(el => el.id);

        const corrispondingElements = contentArray
        .filter(el => el && el.settings.hasOwnProperty('_cssGlobalClasses') && corrispondingGlobalClasses.some(value => el.settings._cssGlobalClasses.includes(value)));

        // Function
        self.structureHelperStates.filterArr = contentArray
        .filter(el => (
            Array.isArray(corrispondingElements) && corrispondingElements.length > 0 && corrispondingElements.includes(el)) 
            || (el && el.settings.hasOwnProperty(prop) && Array.isArray(el.settings[prop]) && el.settings[prop].length > number));

        self.setStructureHelperList();
        self.structureHelperStates.activeFilter = event.target.dataset.id;
    },
    shSearchValueInKey: function(event, prop, value){
        const self = this;
        const setItem = self.helpers.setActiveItem('#brxcStructureHelper .brxc-overlay__pannel-col--left li', event);
        if(!setItem) return;

   
        // Classes
        const contentArray = self.helpers.getContentWithComponents();
        const usedGlobalClasses = contentArray
        .flatMap(el => el && el.settings.hasOwnProperty('_cssGlobalClasses') ? el.settings._cssGlobalClasses : []);

        const corrispondingGlobalClasses = self.vueState.globalClasses
        .filter(el => usedGlobalClasses.includes(el.id) && Array.isArray(el.settings[prop]) && el.settings[prop].length > 0 && JSON.stringify(el.settings[prop]).includes(value))
        .map(el => el.id);

        const corrispondingElements = contentArray
        .filter(el => el && el.settings.hasOwnProperty('_cssGlobalClasses') && corrispondingGlobalClasses.some(value => el.settings._cssGlobalClasses.includes(value)));

        // Function
        self.structureHelperStates.filterArr = contentArray
        .filter(el => (
            Array.isArray(corrispondingElements) && corrispondingElements.length > 0 && corrispondingElements.includes(el)) 
            || (el && el.settings.hasOwnProperty(prop) && Array.isArray(el.settings[prop]) && el.settings[prop].length > 0) && JSON.stringify(el.settings[prop]).includes(value));
        
        self.setStructureHelperList();
        self.structureHelperStates.activeFilter = event.target.dataset.id;
    },
    shSearchValueInKeyObj: function(event, prop, value){
        const self = this;
        const setItem = self.helpers.setActiveItem('#brxcStructureHelper .brxc-overlay__pannel-col--left li', event);
        if(!setItem) return;

        const content = self.helpers.getContentWithComponents();

        // Function
        self.structureHelperStates.filterArr = Array.from(content).filter(el => el && el.settings.hasOwnProperty(prop) && JSON.stringify(el.settings[prop]).includes(value));
        self.setStructureHelperList();
        self.structureHelperStates.activeFilter = event.target.dataset.id;
    },
    shSearchValue: function(event, key, value){
        const self = this;
        const setItem = self.helpers.setActiveItem('#brxcStructureHelper .brxc-overlay__pannel-col--left li', event);
        if(!setItem) return;

        const content = self.helpers.getContentWithComponents();

        // Function
        self.structureHelperStates.filterArr = Array.from(content).filter(el => el && el.settings.hasOwnProperty(key) && el.settings[key] === value);
        self.setStructureHelperList();
    },
    shMissingProp: function(event, prop, missing){
        const self = this;
        const setItem = self.helpers.setActiveItem('#brxcStructureHelper .brxc-overlay__pannel-col--left li', event);
        if(!setItem) return;

        const content = self.helpers.getContentWithComponents();

        // Function
        self.structureHelperStates.filterArr = Array.from(content).filter(el => el && el.settings.hasOwnProperty(prop) && !el.settings[prop].hasOwnProperty(missing));
        self.setStructureHelperList();
        self.structureHelperStates.activeFilter = event.target.dataset.id;
    },
    shCheckAriaAttributes: function(event){
        const self = this;
        const setItem = self.helpers.setActiveItem('#brxcStructureHelper .brxc-overlay__pannel-col--left li', event);
        if(!setItem) return;

        const content = self.helpers.getContentWithComponents();

        // Function
        function checkStyles(settings){
            if(settings.hasOwnProperty('_attributes') && Array.isArray(settings['_attributes']) && settings['_attributes'].length > 0) return false;
            let hasStyles = false
            settings['_attributes'].forEach(el => {
                if(el.name.startsWith('aria-')) hasStyles = true;
            })
            return hasStyles;
        }
        self.structureHelperStates.filterArr = Array.from(content).filter(el => el && checkStyles(el.settings));
        self.setStructureHelperList();
        self.structureHelperStates.activeFilter = event.target.dataset.id;
    },
    shHasIDStyles: function(event){
        const self = this;
        const setItem = self.helpers.setActiveItem('#brxcStructureHelper .brxc-overlay__pannel-col--left li', event);
        if(!setItem) return;

        const content = self.helpers.getContentWithComponents();

        // Function
        function checkStyles(settings){
            let hasStyles = false;
            for(const key of Object.keys(settings)){
                if(self.helpers.isCSSControlKey(key)){
                    hasStyles = true;
                }
            }
            return hasStyles;
        }
        self.structureHelperStates.filterArr = Array.from(content).filter(el => el && checkStyles(el.settings));
        self.setStructureHelperList();
        self.structureHelperStates.activeFilter = event.target.dataset.id;
    },
    shHasPseudoStyles: function(event){
        const self = this;
        const setItem = self.helpers.setActiveItem('#brxcStructureHelper .brxc-overlay__pannel-col--left li', event);
        if(!setItem) return;

        const content = self.helpers.getContentWithComponents();

        // Function
        const pseudos = self.vueState.pseudoClasses;
        function checkStyles(settings){
            let hasStyles = false;
            for(const key of Object.keys(settings)){
                const parsedKey = JSON.stringify(key)
                pseudos.forEach(pseudo => {
                    if(parsedKey.includes(pseudo)){
                        hasStyles = true;
                    }
                })
                
            }
            return hasStyles;
        }
        self.structureHelperStates.filterArr = Array.from(content).filter(el => el && checkStyles(el.settings));
        self.setStructureHelperList();
        self.structureHelperStates.activeFilter = event.target.dataset.id;
    },
    shHasBreakpointStyles: function(event){
        const self = this;
        const setItem = self.helpers.setActiveItem('#brxcStructureHelper .brxc-overlay__pannel-col--left li', event);
        if(!setItem) return;

        const content = self.helpers.getContentWithComponents();
        // Function
        const bps = self.vueState.breakpoints;
        function checkStyles(settings){
            let hasStyles = false;
            for(const key of Object.keys(settings)){
                const parsedKey = JSON.stringify(key)
                bps.forEach(bp => {
                    if(parsedKey.includes(`:${bp.key}`)){
                        hasStyles = true;
                    }
                })
                
            }
            return hasStyles;
        }
        self.structureHelperStates.filterArr = Array.from(content).filter(el => el && checkStyles(el.settings));
        self.setStructureHelperList();
        self.structureHelperStates.activeFilter = event.target.dataset.id;
    },
    shCheckCustomCSSinGlobalClasses: function(event){
        const self = this;
        const setItem = self.helpers.setActiveItem('#brxcStructureHelper .brxc-overlay__pannel-col--left li', event);
        if(!setItem) return;

        const content = self.helpers.getContentWithComponents();

        // Function
        function checkStyles(settings){
            let hasStyles = false;
            if(!settings.hasOwnProperty('_cssGlobalClasses') || settings._cssGlobalClasses.length < 1) return hasStyles;
            settings._cssGlobalClasses.forEach(classId => {
                const classObj = self.vueGlobalProp.$_getGlobalClass(classId);
                if(!classObj || !classObj.hasOwnProperty('settings')) return;

                for(const key of Object.keys(classObj.settings)){
                    if(JSON.stringify(key).includes('_cssCustom')) hasStyles = true;
                }
            })
            return hasStyles;
        }
        self.structureHelperStates.filterArr = Array.from(content).filter(el => el && checkStyles(el.settings));
        self.setStructureHelperList();
        self.structureHelperStates.activeFilter = event.target.dataset.id;
    },
    shHasStaticColors: function(event){
        const self = this;
        const setItem = self.helpers.setActiveItem('#brxcStructureHelper .brxc-overlay__pannel-col--left li', event);
        if(!setItem) return;

        const content = self.helpers.getContentWithComponents();
        // Function
        const bps = self.vueState.breakpoints;
        function checkStyles(settings){
            let hasStyles = false;
            const parsedSettings = JSON.stringify(settings);
            ['"hex":"#', '"rgb":"rgb', '"hsl":"hsl'].forEach(el => {
                if(parsedSettings.includes(el)) hasStyles = true;
            })
            
            return hasStyles;
        }
        self.structureHelperStates.filterArr = Array.from(content).filter(el => el && checkStyles(el.settings));
        self.setStructureHelperList();
        self.structureHelperStates.activeFilter = event.target.dataset.id;
    },
    shConditionDateTime: function(event){
        const self = this;
        const setItem = self.helpers.setActiveItem('#brxcStructureHelper .brxc-overlay__pannel-col--left li', event);
        if(!setItem) return;

        const content = self.helpers.getContentWithComponents();

        // Function
        function checkStyles(settings){
            let hasStyles = false;
            const parsedSettings = JSON.stringify(settings);
            ['"key":"weekday"', '"key":"date"', '"key":"time"', '"key":"datetime"'].forEach(el => {
                if(parsedSettings.includes(el)) hasStyles = true;
            })
            
            return hasStyles;
        }
        
        
        self.structureHelperStates.filterArr = Array.from(content).filter(el => el && el.settings.hasOwnProperty('_conditions') && Array.isArray(el.settings['_conditions']) && el.settings['_conditions'].length > 0 && checkStyles(el.settings));
        self.setStructureHelperList();
        self.structureHelperStates.activeFilter = event.target.dataset.id;
    },
    shNonConsecutiveHeaders: function(event){
        const self = this;
        const setItem = self.helpers.setActiveItem('#brxcStructureHelper .brxc-overlay__pannel-col--left li', event);
        if(!setItem) return;

        
        const content = [];

        function checkChildren(id,arr){
            const obj = self.helpers.getElementObject(id);
            if(obj.name === "heading") arr.push(obj);
            if(obj.hasOwnProperty('children') && Array.isArray(obj.children) && obj.children.length > 0){
                obj.children.forEach(childId => {
                    checkChildren(childId, arr);
                })
            } 
        }
        const tempContent = Array.from(self.helpers.getContent()).filter(el => el && el.hasOwnProperty('parent') && el.parent === 0);
        if (!tempContent || tempContent.length < 1) return;

        tempContent.forEach(el => {
            const obj = self.helpers.getElementObject(el.id);
            checkChildren(obj.id, content);
        })
        
        let oldHeading = false;
        // Function
        const bps = self.vueState.breakpoints;
        function checkStyles(settings){
            let hasStyles = false;
            if(oldHeading === false){
                oldHeading = settings.tag ? parseInt(settings.tag.substr(1)) : parseInt(bricksData.elements.heading?.tag.substr(1))
            } else {
                const newHeading = settings.tag ? parseInt(settings.tag.substr(1)) : parseInt(bricksData.elements.heading?.tag.substr(1))
                if(newHeading - oldHeading > 1) hasStyles = true;
                oldHeading = newHeading;
            }

            return hasStyles;
        }
        self.structureHelperStates.filterArr = Array.from(content).filter(el => el && checkStyles(el.settings));
        self.setStructureHelperList();
        self.structureHelperStates.activeFilter = event.target.dataset.id;
    },
    structurePanelStates: {
        icons: ['structure-generator'],
        tweaks: ['right-elements-shortcuts','styles-and-classes-indicators','highlight-classes','highlight-nestable-elements','highlight-parent-elements','expand-all-children','draggable-structure-panel','link','focus-mode','filterable-structure', 'hide-remove-highlights', 'db-click-edit-component']
    },
    setHeaderStructurePanel: function(){
        const self = this;
        const header = document.querySelector("#bricks-structure #bricks-panel-header ul.actions");
        if(!header) return;

        const atICons = header.querySelectorAll("li.brxc-item");
        atICons.forEach(el => el.remove());

        let firstItem = header.querySelector("li");
        if(!firstItem) return;

        let icons = '';

        if(self.structurePanelStates.icons.includes('structure-generator')) {
            icons += `<li class="brxc-item" data-balloon="Structure Generator" onClick='ADMINBRXC.openModal({target: false, id: "#brxcCodePenImporter", callback: () => {ADMINBRXC.codepenImporterInit();}});' data-balloon-pos="bottom-left"><span class="bricks-svg-wrapper"><i class="bricks-svg fas fa-bars-staggered"></i></i></span></li>`;
        }
        if(self.structurePanelStates.icons.includes('structure-helper')){
            icons += `<li class="brxc-item" data-balloon="Structure Helper" onClick='ADMINBRXC.openModal({target: false, id: "#brxcStructureHelper", callback: () => {ADMINBRXC.setStructureHelper();}});' data-balloon-pos="bottom"><span class="bricks-svg-wrapper"><i class="fas fa-circle-question"></i></span></li>`;
        }
        if(self.structurePanelStates.icons.includes('nested-elements-library')){
            icons += `<li class="brxc-item" data-balloon="Nested Elements Library" onClick='ADMINBRXC.openModal({target: false, id: "#brxcCustomComponentsOverlay", callback: () => {ADMINBRXC.setCustomComponents();}});' data-balloon-pos="bottom"><span class="bricks-svg-wrapper"><i class="fas fa-address-card"></i></span></li>`;
        }
        if(self.structurePanelStates.icons.includes('tag-manager')){

            let toggleClasses = '';
            let balloon = "Tag Manager (mode: none)";
            if(self.elementsTagStates.mode === "overview"){
                toggleClasses = ' highlight';
                balloon = "Tag Manager (mode: overview)";

            } else if(self.elementsTagStates.mode === "developer"){
                toggleClasses = ' active';
                balloon = "Tag Manager (mode: developer)";
            }
            icons += `<li class="brxc-item${toggleClasses}" data-balloon="${balloon}" onClick='ADMINBRXC.toggleTagsState();' data-balloon-pos="bottom"><span class="bricks-svg-wrapper"><i class="fas fa-tag"></i></span></li>`;
        }
        if(self.structurePanelStates.icons.includes('notes')){
            let toggleClasses = '';
            let balloon = 'Notes (none)';
            if(self.noteStates.active === 'editorNotes'){
                toggleClasses = ' active';
                balloon = 'Notes (for editors)'
            } else if (self.noteStates.active === 'adminNotes'){
                toggleClasses = ' highlight';
                balloon = 'Notes (for admins)'
            }
            icons += `<li class="brxc-item${toggleClasses}" data-balloon="${balloon}" onClick='ADMINBRXC.toggleNotesState();' data-balloon-pos="bottom"><span class="bricks-svg-wrapper"><i class="ti-comment-alt"></i></span></li>`;
        }
        if(self.structurePanelStates.icons.includes('elements-order')){
            const isLocked = self.lockDraggableElementsStates.active ? ' active' : '';
            icons += `<li class="brxc-item${isLocked}" data-balloon="Elements Order ${isLocked ? "Locked" : "Unlocked"}" onClick='ADMINBRXC.toggleLockElementsState();' data-balloon-pos="bottom"><span class="bricks-svg-wrapper"><i class="ti-${isLocked ? "" : "un"}lock"></i></span></li>`;
        }
        if(self.structurePanelStates.icons.includes('sticky-css')){
            const isSticky = self.stickyCssStates.active ? ' active' : '';
            icons += `<li class="brxc-item${isSticky}" data-balloon="Sticky CSS" onClick='ADMINBRXC.toggleStickyCSS();' data-balloon-pos="bottom"><span class="bricks-svg-wrapper"><i class="fab fa-css3-alt"></i></span></li>`;
        }
        if(self.structurePanelStates.icons.includes('visibility-floating-bar')){
            const isFloating = self.hideElementStates.active ? ' active' : '';
            icons += `<li class="brxc-item${isFloating}" data-balloon="Visibility Floating Bar" onClick='ADMINBRXC.toggleHideFloatingBar();' data-balloon-pos="bottom"><span class="bricks-svg-wrapper"><i class="fas fa-window-maximize" style="rotate:180deg;"></i></span></li>`;
        }
        firstItem.insertAdjacentHTML("beforebegin", icons);


        const contextualIcon = document.createElement('li');
        contextualIcon.id = "brxcStructureMenu";
        contextualIcon.setAttribute('class', 'brxc-item')
        contextualIcon.setAttribute('data-balloon', 'Structure Menu')
        contextualIcon.setAttribute('data-balloon-pos', 'bottom-right');
        contextualIcon.setAttribute('onClick', `ADMINBRXC.openContextualMenu(event, () => {return ADMINBRXC.structureContextualMenu()}, "left", "structure", "2")`,);
        contextualIcon.innerHTML = `<svg version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg" style="rotate: 90deg;"><path d="M3,9.5l-6.55671e-08,-1.77636e-15c-0.828427,-3.62117e-08 -1.5,-0.671573 -1.5,-1.5c3.62117e-08,-0.828427 0.671573,-1.5 1.5,-1.5l-6.55671e-08,1.77636e-15c0.828427,-3.62117e-08 1.5,0.671573 1.5,1.5c3.62117e-08,0.828427 -0.671573,1.5 -1.5,1.5Zm5,0l-6.55671e-08,-1.77636e-15c-0.828427,-3.62117e-08 -1.5,-0.671573 -1.5,-1.5c3.62117e-08,-0.828427 0.671573,-1.5 1.5,-1.5l-6.55671e-08,1.77636e-15c0.828427,-3.62117e-08 1.5,0.671573 1.5,1.5c3.62117e-08,0.828427 -0.671573,1.5 -1.5,1.5Zm5,0l-6.55671e-08,-1.77636e-15c-0.828427,-3.62117e-08 -1.5,-0.671573 -1.5,-1.5c3.62117e-08,-0.828427 0.671573,-1.5 1.5,-1.5l-6.55671e-08,1.77636e-15c0.828427,-3.62117e-08 1.5,0.671573 1.5,1.5c3.62117e-08,0.828427 -0.671573,1.5 -1.5,1.5Z" fill="currentColor" fill-rule="evenodd"></path></svg>`
        header.appendChild(contextualIcon);
    },
    setControlsOptions: function () {
        const self = this;
    
        const elementKeys = Object.values(bricksData.elements)
            .filter(el => typeof el.controls === 'object')
            .flatMap(el => Object.entries(el.controls))
            .filter(([_, val]) => val?.hasOwnProperty('css'))
            .map(([key]) => key);
    
        const themeKeys = Object.values(bricksData.controls.themeStyles.controls)
            .flatMap(group => Object.entries(group))
            .filter(([_, val]) => val?.hasOwnProperty('css'))
            .map(([key]) => key);
    
        self.CSScontrolKeys = [...new Set([...elementKeys, ...themeKeys])];
    },
    reorderClasses: function(){
       const self = this;
       if(self.vueState.globalClasses && typeof self.vueState.globalClasses === "object") self.vueState.globalClasses.sort((a, b) => { if (a.name < b.name) return -1; if (a.name > b.name) return 1; return 0; });
    },
    groupClassesByLockStatus: function(){
        const self = this;
        if(self.vueState.globalClasses && typeof self.vueState.globalClasses === "object"){
            const locked = []; 
            const unlocked = [];
            self.vueState.globalClasses.forEach(el => {
                self.vueGlobalProp.$_isLocked(el.id) ? locked.push(el) : unlocked.push(el);
            })
            self.vueState.globalClasses = JSON.parse(JSON.stringify(locked.concat(unlocked)));
        }
    },
    rightShortcutStates: {
        active: false,
        keyboard: false,
    },
    setRightShortcutCol: function(toggleKeyboard){
        const self = this;
        if(self.structurePanelStates.tweaks.includes('right-elements-shortcuts')){
            document.body.classList.add('at-has-shortcuts-sidebar');
            const structure = document.querySelector('#bricks-structure');
            const structurePanel = structure.querySelector('main.panel-content');
            const existingMenu = structure.querySelector('.brxce-panel-shortcut__wrapper');
            const storage = self.helpers.getLocalStorage();

            if(!self.rightShortcutStates.active){
                self.rightShortcutStates.active = self.globalSettings.generalCats.rightShortcuts;
            }
            if(toggleKeyboard){
                self.rightShortcutStates.keyboard = !self.rightShortcutStates.keyboard;
                self.helpers.setLocalStorage('rightShortcutKeyboard', self.rightShortcutStates.keyboard);
            } else {
                self.rightShortcutStates.keyboard = storage.rightShortcutKeyboard;
            }
            if(existingMenu){
                existingMenu.remove();
            }

            const existingKey = [];
            
            function setKey(e){
                e = e.replace(/\s/g, '');
                for(let i = 0; i<e.length; i++){
                    if(!existingKey.includes(e[i].toLowerCase())){
                        existingKey.push(e[i].toLowerCase());
                        return e[i].toUpperCase();
                    }
                }

                return false;
            }
            let rightCol = `<div class="brxce-panel-shortcut__wrapper">
                                <div class="brxce-panel-shortcut__container">`;
            if (Array.isArray(self.rightShortcutStates.active) && self.rightShortcutStates.active.length > 0) {
                self.rightShortcutStates.active.forEach(key => {
                    // Handle "nested-elements" case
                    if (key === "nested-elements") {
                        rightCol += `
                            <li data-label="Nested Elements"
                                class="brxc-right-sidebar-shortcuts custom-components" 
                                onClick="ADMINBRXC.openModal({target: false, id: '#brxcCustomComponentsOverlay', focus: '#brxcCustomComponentsSearch input', callback: () => {ADMINBRXC.setCustomComponents();}})">
                                <span class="bricks-svg-wrapper"><i class="fas fa-plus"></i></span>
                            </li>`;
                        return;
                    }
            
                    // Check if the key corresponds to an element
                    const isElement = !!bricksData.elements[key];
                    const el = isElement ? bricksData.elements[key] : self.helpers.getElementObject(key);
            
                    // Skip if element is invalid
                    if (!el) return;
            
                    // Determine icon and keyboard shortcut
                    const icon = isElement ? el.icon : bricksData.elements[el.name]?.icon || 'fas fa-question-circle';
                    const keyboard = setKey(el.label);
            
                    // Build common attributes
                    const dataAttributes = `
                        data-panel="${el.name}"
                        data-label="${el.label}"
                        ${isElement ? `data-name="${el.name}"` : `data-component-id="${el.id}" data-component-name="${el.name}"`}
                        ${keyboard ? `data-order="${keyboard}"` : ''}
                    `;
            
                    // Build the list item
                    rightCol += `
                        <li class="brxc-right-sidebar-shortcuts" ${dataAttributes.trim()}>
                            <span class="bricks-svg-wrapper"><i class="${icon}"></i></span>
                            ${keyboard ? `<span class="keyboard-shortcut">${keyboard}</span>` : ''}
                        </li>`;
                });
            }
            

            rightCol += '</div>';

            // Keyboard Shortcuts
            rightCol += `<li id="brxcKeyBoardShortcuts" class="${self.rightShortcutStates.keyboard ? 'active' : ''}" data-balloon="Keyboard Shortcuts ${self.rightShortcutStates.keyboard ? 'ON' : 'OFF'}" data-balloon-pos="left" onclick="ADMINBRXC.setRightShortcutCol(true)"><span class="bricks-svg-wrapper"><i class="fas fa-keyboard"></i></span></li>`;
            
            // Options
            rightCol += `<li id="brxcShortcutsOptions" class="" data-balloon="Shortcuts Settings" data-balloon-pos="left" onclick="ADMINBRXC.setShortcutsOptionsInit()"><span class="bricks-svg-wrapper"><i class="fas fa-gear"></i></span></li></div>`;

            structurePanel.insertAdjacentHTML(
                'afterend',
                rightCol
            );

            // Listeners
            const icons = structure.querySelectorAll('li.brxc-right-sidebar-shortcuts[data-label]');
            icons.forEach(icon => {
                icon.addEventListener('mousedown', (event) => {
                    const isElement = !!icon.dataset.name || false;
                    isElement ? self.addElementtoStructure(event, icon.dataset.name) : self.addComponenttoStructure(event, icon.dataset.componentId, icon.dataset.componentName);
                });

                let balloon = null;

                icon.addEventListener('mouseenter', () => {
                    if (!balloon) {
                        const classes = icon.dataset.componentId ? 'brxc-shortcut-balloon component' : 'brxc-shortcut-balloon'
                        const rect = icon.getBoundingClientRect();
                        balloon = document.createElement('div');
                        balloon.setAttribute('class', classes);
                        balloon.textContent = icon.dataset.label;
                        balloon.style.top = `${rect.y + 8}px`;
                        balloon.style.right = `${window.innerWidth - rect.left + 7}px`;
                        document.body.appendChild(balloon);
                    }
                });

                icon.addEventListener('mouseleave', () => {
                    if (balloon) {
                        balloon.remove();
                        balloon = null;
                    }
                });
            });


            // ACSS
            const acssApp = document.querySelector('.acss-dashboard-app')
            if(acssApp){
                const acssStyle = acssApp.shadowRoot.querySelector('#svelte-y41ihy');
                if(acssStyle) {
                    const defaultStyles = acssStyle.textContent;
                    const newStyles = defaultStyles.replace(/right:\s*10px/, 'right: 50px');
                    acssStyle.innerHTML = newStyles;
                }
            }

        } else {
            document.body.classList.remove('at-has-shortcuts-sidebar');
            const existingMenu = document.querySelector('#bricks-structure .brxce-panel-shortcut__wrapper');
            if(existingMenu) existingMenu.remove();
        }
    },
    setShortcutsOptionsInit: function(){
        const self = this;
        const existing = document.querySelector('#brxcShortcutsSettings');
        if(existing) existing.remove();

        const a = document.createElement('DIV');
        a.id = "brxcShortcutsSettings";
        a.innerHTML = `
        <div id="brxcShortcutsSettingsHeader">
            <span class="title">Shortcut Settings</span>
            <span class="bricks-svg-wrapper save" data-balloon="Save" data-balloon-pos="bottom" onclick="ADMINBRXC.saveRightShortcuts();"><i class="fas fa-floppy-disk"></i></span>
            <span class="bricks-svg-wrapper close" data-balloon="Close" data-balloon-pos="bottom" onclick="document.querySelector('#brxcShortcutsSettings').remove()"><svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><path d="M400,145.49l-33.49,-33.49l-110.51,110.51l-110.51,-110.51l-33.49,33.49l110.51,110.51l-110.51,110.51l33.49,33.49l110.51,-110.51l110.51,110.51l33.49,-33.49l-110.51,-110.51l110.51,-110.51Z" fill="currentColor"></path></svg></span>
        </div>
        <div id="brxcShortcutsSettingsMain"></div>`
        document.body.appendChild(a);

        self.shortcutsOptionsRenderElements();

        // Listeners
        const wrapper = document.querySelector('#brxcShortcutsSettingsMain');
        if(wrapper){
            wrapper.addEventListener('click', (e) => {
                const parent = e.target.parentElement;
                const name = parent.dataset.name || parent.dataset.componentId;
            
                if (name) {
                    if (e.target.classList.contains('fa-toggle-on')) {
                        self.shortcutsOptionsDeactivateElement(name);
                    } else if (e.target.classList.contains('fa-toggle-off')) {
                        self.shortcutsOptionsActivateElement(name);
                    }
                }
            });
        }
    },
    shortcutsOptionsRenderElements: function(){
        const self = this;
        const wrapper = document.querySelector('#brxcShortcutsSettingsMain');
        if(!wrapper) return;
        const nestedELements = {
            name: 'nested-elements',
            label: 'Nested Elements',
            icon: 'fas fa-plus',
        }
        const elements = JSON.parse(JSON.stringify(bricksData.elements));
        elements['nested-elements'] = nestedELements;

        let content = '';
        
        // Active
        if(Array.isArray(self.rightShortcutStates.active)){
            content += `
                <div id="brxcShortcutsSettingsActiveLabel" class="no-handle">
                    <span>Active</span>
                    <span onclick="ADMINBRXC.shortcutsOptionsDeactivateAllElements();">Toggle All</span>
                </div>
                <div id="brxcShortcutsSettingsActive">
            `;

            if (self.rightShortcutStates.active.length > 0) {
                self.rightShortcutStates.active.forEach(el => {
                    const isElement = !!elements[el];
                    const obj = isElement ? elements[el] : self.helpers.getElementObject(el);

                    if (!obj) return;

                    const name = isElement ? obj.name : obj.id;
                    const icon = isElement ? obj.icon : bricksData.elements[obj.name]?.icon || 'fas fa-question-circle';
                    const label = obj.label;

                    content += `
                        <div>
                            <div class="handle"><i class="fas fa-grip-vertical"></i></div>
                            <div ${isElement ? `data-name="${name}"` : `data-component-id="${name}"`}>
                                <i class="icon ${icon}"></i>
                                <span>${label}</span>
                                <i class="toggle fas fa-toggle-on"></i>
                            </div>
                        </div>
                    `;
                });
            } else {
                content += `<p data-control="info">No active elements</p>`;
            }

            content += `</div>`;

    
            // Inactive
            content += '<div id="brxcShortcutsSettingsInactiveLabel"><span>Inactive</span><span onclick="ADMINBRXC.shortcutsOptionsActivateAllElements();">Toggle All</span></div>';
            content += '<div id="brxcShortcutsSettingsInactive">';
            let count = 0;

            // Elements
            for(const [key, value] of Object.entries(elements)){
                if(self.rightShortcutStates.active.includes(key)) continue;
                content += `<div data-name="${elements[key].name}"><i class="icon ${elements[key].icon}"></i><span>${elements[key].label}</span><i class="toggle fas fa-toggle-off"></i></div>`;
                count++;
            }
            if(self.vueState.hasOwnProperty('components')){
                const arr = self.vueState.components.map(el => el.elements[0])
                arr.forEach(el => {
                    if(self.rightShortcutStates.active.includes(el.id)) return;
                    content += `<div data-component-id="${el.id}"><i class="icon ${elements[el.name].icon}"></i><span>${el.label}</span><i class="toggle fas fa-toggle-off"></i></div>`;
                    count++;
                })
            }

            // Components
            if(count === 0){
                content += `<p data-control="info">No active elements</p>`;
            }
            content += '</div>';
        }

        // Return
        wrapper.innerHTML = content;

        // Listeners
        const sortableContainer = wrapper.querySelector('#brxcShortcutsSettingsActive');
        new Sortable(sortableContainer, {
            selectedClass: "sortable-selected",
            handle: ".handle",
            animation: 150,
            helper: 'clone',
            filter: ".no-handle",
            onEnd: (evt) => {
                self.rightShortcutStates.active = Array.from(evt.to.children).map(el => el.children[1].dataset.name || el.children[1].dataset.componentId);
                self.setRightShortcutCol();

            },
        });
    },
    shortcutsOptionsDeactivateElement: function (name){
        const self = this;
        const index = self.rightShortcutStates.active.indexOf(name);
        if(index === -1) return

        self.rightShortcutStates.active.splice(index, 1);
        self.shortcutsOptionsRenderElements();
        self.setRightShortcutCol();
    },
    shortcutsOptionsDeactivateAllElements: function (name){
        const self = this;
        self.rightShortcutStates.active = [];
        self.shortcutsOptionsRenderElements();
        self.setRightShortcutCol();
    },
    shortcutsOptionsActivateElement: function (name){
        const self = this;
        self.rightShortcutStates.active.push(name);
        self.shortcutsOptionsRenderElements();
        self.setRightShortcutCol();
    },
    shortcutsOptionsActivateAllElements: function (name){
        const self = this;
        
        self.rightShortcutStates.active = [
            ...Object.values(bricksData.elements).map(el => el.name),
            ...(self.vueState.components?.map(el => el.id) || []),
            'nested-elements'
        ];

        self.shortcutsOptionsRenderElements();
        self.setRightShortcutCol();
    },
    saveRightShortcuts: function(){
        const self = this;
        const obj = self.rightShortcutStates.active;
        jQuery.ajax({
            url: openai_ajax_req.ajax_url,
            data: {
                action: 'save_right_shortcuts_ajax_function',
                nonce: openai_ajax_req.nonce,
                shortcuts: obj,
            },
            method: "POST",
            success: function(data) {
                self.vueGlobalProp.$_showMessage('Shortcuts settings saved successfully!')
            },
            error: function(data) {
                self.vueGlobalProp.$_showMessage('Something went wrong - Shortcuts setting not saved.')
            }
        });
    },
    addElementtoStructure: function(event, elName){
        const self = this;

        setTimeout(() => {
            const element = self.vueGlobalProp.$_createElement({ name: elName });
            const params = { element: element };

            const newElement = self.vueGlobalProp.$_addNewElement(params, { shiftKey: event.shiftKey }, true);
        
            // Tag Manager
            setTimeout(() => self.showTagInStructurePanel(), 0);
            

            if (elName === "section"){

                setTimeout(() => {
                    // Expand
                    const el = document.querySelector(`#bricks-structure .element[data-id="${newElement.id}"] .toggle`)
                    if(el.dataset.name === "arrow-right") el.click();

                    // Focus element
                    const section = self.helpers.getElementObject(newElement.id);
                    const container = self.helpers.getElementObject(section.children[0])
                    self.vueState.activeId = container.id;
                    self.vueState.activePanel = "element"
                    
                },0)
            }
        }, 0)
    },
    addComponenttoStructure: function(event, componentId, componentName){
        const self = this;

        setTimeout(() => {
            const id = self.vueGlobalProp.$_generateId();
            const parent = self.builderStates.isElementActive && self.vueGlobalProp.$_isNestable(self.vueState.activeElement) ? self.vueState.activeElement.id : 0;
            self.vueGlobalProp.$_addToStore({
                id: id,
                parent: parent,
                cid: componentId,
                name: componentName, 
                children: []
            })
            if(parent !== 0){
                const objChild = self.helpers.getElementObject(id, true);
                const objParent = self.helpers.getElementObject(parent, true);

                if (objChild && objParent) {
                    objChild.parent = parent;
                    objParent.children.push(id);
                }
            }
            
            setTimeout(() => {
                // Tag Manager
                self.showTagInStructurePanel()

                // Focus element on shift click
                if (event?.shiftKey) {
                    self.vueState.activePanel = "element";
                    self.vueState.activeId = id;
                }
            },0)
        },0)
    },
    customComponentStates: {
        search: '',
        activeCategory: 'all',
        defaultCategory: [
            {id: "default", label: "Default", default: true},
        ],
        add: {
            type: 'Add',
            id: false,
            label: '',
            category: '',
            icon: 'ti-arrow-up'
        }
    },
    setAddCustomComponents: function(){
        const self = this;
        self.customComponentStates.add.type = 'Add';
        self.customComponentStates.add.id = false;
        self.customComponentStates.add.label = '';
        self.customComponentStates.add.category = '';
        self.customComponentStates.add.icon = 'ti-arrow-up';
        self.mountAddCustomComponents();
    },
    addCustomComponentsPreview: function(){
        const self = this;
        const elementObj = self.builderStates.activeElement;
        let content = '';
        const elements = [];

        function populateElements(id, level){
            const obj = JSON.parse(JSON.stringify(self.helpers.getElementObject(id)));
            obj.level = level;
            elements.push(obj);

            if (!obj.hasOwnProperty('children') || !Array.isArray(obj.children) || obj.children.length < 1) return;
            level++;
            obj.children.forEach(newId => {
                populateElements(newId, level);
            })
        }
        populateElements(elementObj.id, 0);
        elements.forEach(el =>{
            content += `<li style="--margin:${el.level}">
                            <div class="icon">
                                <i class="${bricksData.elements[el.name]?.icon}"></i>
                            </div>
                            <span>${el.hasOwnProperty('label') ? el.label : bricksData.elements[el.name]?.label}</span>
                        </li>`;
        })
        return content;

    },
    mountAddCustomComponents: function(){
        const self = this;
        const canvas = document.querySelector('#brxcAddCustomComponentsCanvas');
        if(!canvas) return;
        
        let content = '';
        content += `<div class="brxc-overlay__panel-inline-btns-wrapper m-bottom-24" style="padding: 0px">
                        <input type="radio" id="add-custum-component-add" name="add-custom-component-switch" class="brxc-input__radio" onclick="ADMINBRXC.customComponentStates.add.type = 'Add';ADMINBRXC.mountAddCustomComponents();"${ADMINBRXC.customComponentStates.add.type === 'Add' ? ' checked' : ''}>
                        <label for="add-custum-component-add" class="brxc-overlay__panel-inline-btns">Add</label>
                        <input type="radio" id="add-custum-component-edit" name="add-custom-component-switch" class="brxc-input__radio" onclick="ADMINBRXC.customComponentStates.add.type = 'Edit';ADMINBRXC.mountAddCustomComponents();"${ADMINBRXC.customComponentStates.add.type === 'Edit' ? ' checked' : ''}>
                        <label for="add-custum-component-edit" class="brxc-overlay__panel-inline-btns">Edit</label>
                    </div>
                    <label for="brxcCustomComponentPreview" class="has-tooltip">
                        <span>Preview</span>
                        <div data-balloon="This is the DOM structure that will be saved in the database" data-balloon-pos="top-left" data-balloon-length="large">
                            <i class="fas fa-circle-question"></i>
                        </div>
                    </label>
                    <ul class="brxc-custom-components__preview-container">`;
        content += self.addCustomComponentsPreview();
        content += `</ul>`;
        if(self.customComponentStates.add.type === "Edit"){
            content += `<label for="brxcCustomComponentEdit" class="has-tooltip">
                            <span>Edit The following component</span>
                            <div data-balloon="Choose the nested element you want to edit" data-balloon-pos="top" data-balloon-length="large">
                                <i class="fas fa-circle-question"></i>
                            </div>
                        </label>
                        <div class="m-bottom-24">
                            <div class="brxc-select-new bg2 rounded hidden" id="brxcCustomComponentSelect">
                                <div class="brxc-select-new__wrapper">
                                    <div ${self.customComponentStates.add.id === false ? ' class="active"' : ''}><span>---Choose a Component---</span></div>
                                    ${self.globalSettings.customComponentsElements.map(el => `<div data-value="${el.id}"${self.customComponentStates.add.id === el.id ? ' class="active"' : ''}><span>${el.label} (${self.helpers.getCustomComponentCatObjById(el.category)?.label || "Uncategorized"})</span></div>`).join('')}
                                </div>
                            </div>
                        </div>`;
        }                 
        content += `<label for="brxcCustomComponentLabel" class="has-tooltip">
                        <span>Label</span>
                        <div data-balloon="Set a label to your nested element" data-balloon-pos="top-left" data-balloon-length="large">
                            <i class="fas fa-circle-question"></i>
                        </div>
                    </label>
                    <div id="classConverterGrpWrapper">
                        <input type="text" id="brxcCustomComponentLabel" class="brxc-input-text m-bottom-24" value="${self.customComponentStates.add.label ? self.customComponentStates.add.label : ''}" data-prop="label" placeholder="Type the name of your nested element here."></input>
                    </div>
                    <label for="brxcCustomComponentCategory" class="has-tooltip">
                        <span>Category <span class="brxc__light">(Optional)</span></span>
                        <div data-balloon="Assign a category to the nested element" data-balloon-pos="top" data-balloon-length="large">
                            <i class="fas fa-circle-question"></i>
                        </div>
                    </label>
                    <div class="brxc-custom-components__category-wrapper">
                        <input type="text" id="brxcCustomComponentCategory" class="brxc-input-text m-bottom-24" value="${self.customComponentStates.add.category ? self.customComponentStates.add.category : ''}" data-prop="category" placeholder="Type the category of the nested element here."></input>
                    </div>
                    <label for="brxcCustomComponentIcon" class="has-tooltip">
                        <span>Icon</span></span>
                        <div data-balloon="Choose an icon related to the nested element" data-balloon-pos="top-left" data-balloon-length="large">
                            <i class="fas fa-circle-question"></i>
                        </div>
                    </label>
                    <div class="brxc-custom-components__icon-container m-bottom-24">
                        <div class="brxc-custom-components__icon-wrapper m-bottom-24">`;
                        self.helpers.tiIcons.forEach((icon, index) => {
                            content += `<input type="radio" id="brxc-${icon.replaceAll(' ', '-').toLowerCase()}" name="brxc-component-icons" class="brxc-input__radio" data-value="${icon}"${self.customComponentStates.add.icon && self.customComponentStates.add.icon === icon ? ' checked' : ''}>
                                        <label for="brxc-${icon.replaceAll(' ', '-').toLowerCase()}"><i class="${icon}"></i></label>`
                        })
            content += `</div>
                    </div>
                    <div class="brxc-overlay__action-btn-wrapper right m-top-16"> 
                        <div class="brxc-overlay__action-btn primary" onclick="ADMINBRXC.addNewCustomComponent();"><span>${self.customComponentStates.add.type ? self.customComponentStates.add.type : ''} Nested Element</span></div>
                    </div>`
        canvas.innerHTML = content;

        // Listeners;
        const inputs = canvas.querySelectorAll('input[data-prop]');
        inputs.forEach(input => {
            input.addEventListener('input', () => {
                self.customComponentStates.add[input.dataset.prop] = input.value;
            })
        })
        const select = canvas.querySelector('#brxcCustomComponentSelect');
        self.helpers.selectControl(select, (target) => {
            const value = target.dataset.value || false;
            self.customComponentStates.add.id = value;
            const obj = self.helpers.getCustomComponentObjById(value);
            if(!obj) return self.mountAddCustomComponents();

            self.customComponentStates.add.label = obj.label;
            self.customComponentStates.add.icon = obj.icon;
            obj.hasOwnProperty('category') && obj.category !== ''? self.customComponentStates.add.category = self.helpers.getCustomComponentCatObjById(obj.category).label : self.customComponentStates.add.category = '';
            self.mountAddCustomComponents();
        })
        const radios = canvas.querySelectorAll('input[name="brxc-component-icons"]');
        radios.forEach(radio => {
            radio.addEventListener('click', () => {
                self.customComponentStates.add.icon = radio.dataset.value;
            })
        })
        const category = canvas.querySelector('#brxcCustomComponentCategory');
        self.autocomplete(category, Array.from(self.globalSettings.customComponentsCategories).map(el => el && el.label), false);


    },
    addNewCustomComponent: function(){
        const self = this;
        const elementObj = self.builderStates.activeElement;
        let categoryId = false;
        let elements = [];
        let globalClasses = []

        function populateElements(id){
            const obj = JSON.parse(JSON.stringify(self.helpers.getElementObject(id)));
            elements.push(obj);
            
            // Global Classes
            if(obj.settings.hasOwnProperty('_cssGlobalClasses') && obj.settings._cssGlobalClasses.length > 0){
                obj.settings._cssGlobalClasses.forEach(id => {
                    let classObj = self.vueGlobalProp.$_getGlobalClass(id);
                    if(classObj){
                        classObj = JSON.parse(JSON.stringify(classObj));
                        globalClasses.push(classObj);
                        globalClasses = [...new Set(globalClasses)];
                    }
                })
            }

            if (!obj.hasOwnProperty('children') || !Array.isArray(obj.children) || obj.children.length < 1) return;
            obj.children.forEach(newId => {
                populateElements(newId);
            })
        }
        populateElements(elementObj.id);

        // Categories
        if(self.customComponentStates.add.category !== ''){
            const existingCategory = self.helpers.getCustomComponentCatObjByName(self.customComponentStates.add.category);
            if(existingCategory) {
                categoryId = existingCategory.id;
            } else {
                categoryId = self.vueGlobalProp.$_generateId();
                self.globalSettings.customComponentsCategories.push({
                    id: categoryId,
                    label: self.customComponentStates.add.category
                })
            }
            self.customComponentStates.activeCategory = categoryId;
        }

        // Elements
        if(self.customComponentStates.add.type === "Add"){
            const obj = {
                id: self.vueGlobalProp.$_generateId(),
                label: self.customComponentStates.add.label,
                icon: self.customComponentStates.add.icon,
                elements: elements,
                globalClasses: globalClasses
            }
            if(categoryId) obj.category = categoryId;

            self.globalSettings.customComponentsElements.push(obj)
        } else if(self.customComponentStates.add.type === "Edit") {
            const obj = self.helpers.getCustomComponentObjById(self.customComponentStates.add.id);
            obj.label = self.customComponentStates.add.label;
            obj.icon = self.customComponentStates.add.icon;
            obj.elements = elements;
            categoryId ? obj.category = categoryId : delete obj.category;
        }

        if(!self.customComponentStates.add.label || self.customComponentStates.add.label === "" ||
           !self.customComponentStates.add.icon || self.customComponentStates.add.icon === "" ||
           (self.customComponentStates.add.type === "Edit" && !self.customComponentStates.add.id)
        ){
            self.vueGlobalProp.$_showMessage('ABORT: Missing required field values!')
            return;
        }

        self.customComponentStates.add.type === "Add" ? self.vueGlobalProp.$_showMessage('Component correctly created!') : self.vueGlobalProp.$_showMessage('Component correctly edited!');
        self.openModal({target: false, id: '#brxcCustomComponentsOverlay', focus: '#brxcCustomComponentsSearch input', callback: () => {self.setCustomComponents();}});
    },
    setCustomComponents: function(){
        const self = this;
        self.customComponentsMountCategories();
        self.customComponentsMountElements();
    },
    customComponentsMountCategories: function(){
        const self = this;
        const canvas = document.querySelector('#brxcCustomComponentsCats');
        if(!canvas) return;

        let cats = '<ul>';
        let count;
        const arr = brxcNestedElementsDefault.concat(self.globalSettings.customComponentsElements);
        const categories = self.customComponentStates.defaultCategory.concat(self.globalSettings.customComponentsCategories);

        function isActive (id) {
            if(self.helpers.getCustomComponentCatObjById(id).id === self.customComponentStates.activeCategory) return true;
            return false;
        }

        // All
        count = arr.length;
        cats += `<li class="${self.customComponentStates.activeCategory === "all" ? 'active' : ''}"${self.customComponentStates.activeCategory === "all" ? ' data-active="true"' : ''} data-id="all" onClick="ADMINBRXC.customComponentsFilterCat(event)"><input type="text" value="All" readonly/><span class="count">${count}</span></li>`
        
        // Uncategorized
        count = Array.from(arr).filter(el => el && self.helpers.isCustomComponentUncategorized(el)).length;
        cats += `<li class="${self.customComponentStates.activeCategory === "uncategorized" ? 'active' : ''}"${self.customComponentStates.activeCategory === "uncategorized" ? ' data-active="true"' : ''} data-id="uncategorized" onClick="ADMINBRXC.customComponentsFilterCat(event)"><input type="text" value="Uncategorized" readonly/><span class="count">${count}</span></li>`

        // Categories
        categories.forEach(catObj => {
            count = Array.from(arr).filter(el => el && el.hasOwnProperty('category') && catObj.id === el.category).length;
            cats += `<li class="${isActive(catObj.id) ? 'active' : ''}"${isActive(catObj.id) ? ' data-active="true"' : ''} data-id="${catObj.id}" ondragenter="this.classList.add('dragged')" ondragleave="this.classList.remove('dragged')" ondrop="event.preventDefault();ADMINBRXC.onDropVariableCatList(this);" ondragover="event.preventDefault();" onClick="ADMINBRXC.customComponentsFilterCat(event)">
                        <input type="text" data-initial="${catObj.label}" value="${catObj.label}"${catObj.id !== self.customComponentStates.activeCategory ? ' readonly' : ''}/>
                        <div class="action">`;
            if(!catObj.hasOwnProperty('default') && catObj.id === self.customComponentStates.activeCategory){
                    cats += `<div class="deleteCat" onClick="event.stopPropagation();ADMINBRXC.deleteCustomComponementCategory('${self.customComponentStates.activeCategory}')" data-balloon="Delete category" data-balloon-pos="top-right"><span class="bricks-svg-wrapper"><i class="ti-trash"></i></span></div>`;
            }
                    cats += `<span class="count">${count}</span>
                        </div>
                    </li>`;
        })

        cats += '</ul><input type="text" id="addNewCat" placeholder="+ New category" onkeyup="ADMINBRXC.addCustomComponentCategory(this, event);" />';

        if(canvas && cats) canvas.innerHTML = cats;

        // rename cat
        const input = canvas.querySelector('li.active input');
        if(input){
            input.addEventListener('keyup', (event) => {
                if(event.key !== "Enter") return;
                if(event.target.value === event.target.dataset.initial) return self.customComponentsMountCategories();
                if(categories.map(el => el && el.label).includes(event.target.value)) return self.vueGlobalProp.$_showMessage(`ABORT: category "${event.target.value}" already exists`);
                const activeObj = self.helpers.getCustomComponentCatObjById(event.target.parentElement.dataset.id);
                if(!activeObj) return;
                activeObj.label = event.target.value;
                self.vueGlobalProp.$_showMessage(`Category correctly renamed to ${event.target.value}`)
                self.customComponentsMountCategories();
            })
        }
    },
    deleteCustomComponementCategory: function(id){
        const self = this;

        // Remove category from elements
        self.globalSettings.customComponentsElements.filter(el => el && el.hasOwnProperty('category') && el.category === id).map(el => delete el.category);
        
        // Remove Category
        const obj = self.helpers.getCustomComponentObjById(id);
        const order = self.globalSettings.customComponentsCategories.indexOf(obj);
        self.globalSettings.customComponentsCategories.splice(order, 1);

        // Rerender
        self.customComponentStates.activeCategory = "all";
        self.vueGlobalProp.$_showMessage('Category successfully deleted!');
        self.setCustomComponents();
    },
    addCustomComponentCategory: function(input, event){
        if(event && event.key !== "Enter") return;

        const self = this;
        let count = 0;
        let id;
        const categories = self.customComponentStates.defaultCategory.concat(self.globalSettings.customComponentsCategories);
        const names = input.value.split(',').map(item => item.trim());
        names.forEach(el => {
            const name = el.toLowerCase();
            const existingCategory = self.helpers.getCustomComponentCatObjByName(name);
            if(!existingCategory){
                id = self.vueGlobalProp.$_generateId();
                self.globalSettings.customComponentsCategories.push({
                    id: id,
                    label: el
                });
                count++;
            } else {
                id = existingCategory;
            }
        })
        if(count > 0) self.vueGlobalProp.$_showMessage('Category successfully added!');
        
        self.customComponentStates.activeCategory = id;
        self.setCustomComponents();
    },
    customComponentsFilterCat: function(event){
        const self = this;
        target = (event.target.dataset.id) ? event.target : event.target.parentElement;
        if(target.dataset.active === 'true') return;
        self.customComponentStates.activeCategory = target.dataset.id;
        self.setCustomComponents();
    },
    customComponentsMountElements: function(){
        const self = this;
        const canvas = document.querySelector('#brxcCustomComponentsElements');
        if(!canvas) return;
        
        let content = "";
        let elements = brxcNestedElementsDefault.concat(self.globalSettings.customComponentsElements);

        // Categories
        if(self.customComponentStates.activeCategory !== "all"){
            if(self.customComponentStates.activeCategory === "uncategorized"){
                elements = elements.filter(el => el && !el.hasOwnProperty('category'));
            } else {
                elements = elements.filter(el => el && el.hasOwnProperty('category') && el.category === self.customComponentStates.activeCategory);
            }
        }

        // Search
        if(self.customComponentStates.search !== ''){
            elements = elements.filter(el => el.label.toLowerCase().includes(self.customComponentStates.search.toLowerCase()));
        }

        // Loop
        elements.forEach(item => {
            content += `<div class="brxc-custom-components__item" data-id="${item.id}">
                            <i class="${item.icon}"></i>
                            <div class="brxc-custom-components__label">
                                ${item.label}
                            </div>`;
            if(!item.hasOwnProperty('default')){
                content += `<div class="brxc-overlay__close-btn" data-balloon="Delete" data-balloon-pos="left">
                                <i class="bricks-svg ti-trash"></i>
                            </div>`
                if((self.vueState.hasOwnProperty('components'))) content +=  `<div class="brxc-custom-components__convert" data-balloon="Convert as Component" data-balloon-pos="left" data-id="${item.id}">
                                 <i class="fas fa-right-left"></i>
                            </div>`;
            }
            content += `</div>`;
        })
        canvas.innerHTML = content;
        
        // Listeners
        const items = canvas.querySelectorAll('.brxc-custom-components__item[data-id]');
        items.forEach(item => {
            item.addEventListener('click', () => {
                self.addCustomComponent(item.dataset.id);
            })
        })
        const deletes = canvas.querySelectorAll('.brxc-overlay__close-btn');
        deletes.forEach(el => {
            el.addEventListener('click', (e) => {
                e.preventDefault();
                e.stopPropagation();
                self.deleteCustomComponement(el.parentElement.dataset.id);
            })
        })

        const converts = canvas.querySelectorAll('.brxc-custom-components__convert[data-id]');
        converts.forEach(item => {
            item.addEventListener('click', (e) => {
                e.preventDefault();
                e.stopPropagation();
                self.convertNestableintoComponent(item.dataset.id);
            })
        })
    },
    convertNestableintoComponent: function(id){
        const self = this;
        const arr = brxcNestedElementsDefault.concat(self.globalSettings.customComponentsElements);
        const item = arr.find(el => el.id === id);

        const newComponent = {
            id: item.elements[0].id,
            desc: '',
            elements: JSON.parse(JSON.stringify(item.elements).replaceAll('#brxe-', '.brxe-')),
            category: self.globalSettings.customComponentsCategories.find(el => el.id === item.category)?.label,
            properties: [],
            _created: Date.now(),
            _user_id: bricksData.loadData.currentUserId,
            _version: bricksData.version
        }
        self.vueState.components.push(newComponent);
        self.vueGlobalProp.$_showMessage(`${item.label} has been converted as Component!`);
    },
    deleteCustomComponement: function(id){
        const self = this;
        const arr = self.globalSettings.customComponentsElements;
        const element = arr.find(el => el && el.id === id);
        const order = arr.indexOf(element);
        arr.splice(order, 1);
        self.vueGlobalProp.$_showMessage('Nested element successfully deleted!');
        self.setCustomComponents();
    },
    addCustomComponent: function(dataId){
        const self = this;
        const arr = brxcNestedElementsDefault.concat(self.globalSettings.customComponentsElements);
        const item = arr.find(el => el.id === dataId);
        
        function generateNewComponentIds(arr){
            arr.forEach(el => {
                if(!el.hasOwnProperty('settings')) el.settings = {};
            })

            let newArr = JSON.stringify(arr);
            arr.forEach(el => {
                const newId = self.vueGlobalProp.$_generateId();
                newArr = newArr.replaceAll(el.id, newId);
            })
            return JSON.parse(newArr);
        }
        const elements = generateNewComponentIds(item.elements);
        const globalClasses = item.globalClasses;
        const contentType = self.helpers.getTemplateType();
        const content = self.helpers.getContent();

        // Add Global Classes
        if(globalClasses && globalClasses.length > 0){
            globalClasses.forEach(obj => {
                let classExists = Array.from(self.vueState.globalClasses).find(el => el && el.name === obj.name)
                if(!classExists){
                    if(!obj.hasOwnProperty('settings')) obj.settings = {};
                    self.vueState.globalClasses.push(obj);
                }
            }) 
        }

        // Add Elements
        if(self.builderStates.isElementActive){
            const elementObj = self.builderStates.activeElement;
            // Nestable
            if(self.vueGlobalProp.$_getElementConfig(elementObj.name).nestable === true){
                elements[0].parent = elementObj.id;
                elementObj.children.push(elements[0].id);
            // Non Nestable
            } else {
                elements[0].parent = elementObj.parent;
                const parent = self.helpers.getElementObject(elementObj.parent);
                parent.children.push(elements[0].id);
            }

        } else {
            elements[0].parent = 0;
        }
        if(self.helpers.isComponentActive()){
            self.vueState.activeComponent.elements = JSON.parse(JSON.stringify(content.concat(elements)));
        } else {
            self.vueState[contentType] = JSON.parse(JSON.stringify(content.concat(elements)));
        }
        setTimeout((e) => {
            self.vueState.rerenderControls = Date.now();
            document.querySelector('#brxcCustomComponentsOverlay').removeAttribute('data-active');
            self.vueGlobalProp.$_showMessage('Nested Element correctly inserted!');
        },5)
    },
    saveCustomComponentsOptions: function() {
        const self = this;
        const elements = self.globalSettings.customComponentsElements;
        const categories = self.globalSettings.customComponentsCategories;
        jQuery.ajax({
            url: openai_ajax_req.ajax_url,
            data: {
                action: 'save_custom_components_ajax_function',
                nonce: openai_ajax_req.nonce,
                customComponentsElements: JSON.stringify(elements),
                customComponentsCategories: JSON.stringify(categories),
            },
            method: "POST",
            success: function(data) {
                self.vueGlobalProp.$_showMessage('Nested Elements saved successfully!')
            },
            error: function(data) {
                self.vueGlobalProp.$_showMessage('Something went wrong - Nested Elements not saved.')
                console.log(data);
            }
        });
    },
    setGlobalKeyboardsh: function(){
        const self = this;

        function runShortcuts(e, addShortcut = true) {
            const containers = document.querySelectorAll('.brxce-panel-shortcut__container');
        
            if (containers.length < 0) return;
        
            const item = Array.from(document.querySelectorAll('.brxce-panel-shortcut__container li[data-order]')).find(el => el.dataset.order.toLowerCase() === e.key.toLowerCase());
        
            const shortcut = e.shiftKey;
        
            // Check if any excluded keys are pressed
            const excludedKeys = [e.ctrlKey,e.metaKey,e.altKey];
        
            const shouldTriggerItem = !excludedKeys.includes(true);
        
            // View Shortcuts
            if (shortcut) {
                containers.forEach(container => container.classList.add('shortcuts-active'));
            } else {
                containers.forEach(container => container.classList.remove('shortcuts-active'));
            }
        
            if (!addShortcut) return;
        
            // Click shortcut
            if (item && shouldTriggerItem){
                e.preventDefault();
                e.stopPropagation();
                if (shortcut) {
                    const event = new MouseEvent('mousedown', {
                        bubbles: true,
                        cancelable: true,
                        shiftKey: true,
                    });
                    item.dispatchEvent(event);
    
                } else {
                    ADMINBRXC.vueState.brxc.clickedOnLeftPanelShortcuts = true;
                    setTimeout(() => {
                        const event = new MouseEvent('mousedown', {
                            bubbles: true,
                            cancelable: true,
                        });
                        item.dispatchEvent(event);
                        ADMINBRXC.vueState.brxc.clickedOnLeftPanelShortcuts = false;
                    }, 10);
                }
            }
        }
        function excludeFromBuilder(e){
            const activeKeyboard = !self.rightShortcutStates.keyboard;
            const isReadOnly = e.target.tagName.toLowerCase() === 'input' && e.target.readOnly !== true;
            const isTextarea = e.target.tagName.toLowerCase() === 'textarea';
            const isContentEditable = e.target.isContentEditable;
            const isACSSCodeMirror = e.target.classList.contains('acss-dashboard-app');
            const isStructeezy = e.target.closest('#structeezy-menu');
            const isCodeMirror = e.target.closest('.cm-editor');
            return activeKeyboard || isReadOnly || isTextarea || isContentEditable || isACSSCodeMirror || isStructeezy || isCodeMirror;
        }
        function excludeFromPreview(e) {
            const tagName = e.target.tagName.toLowerCase();
            const isContentEditable = e.target.closest('[contenteditable="true"]');
            const activeKeyboard = !self.rightShortcutStates.keyboard;
            const isInput = tagName === 'input';
            const isTextarea = tagName === 'textarea';
            const isSelect = tagName === 'select';
            const isButton = tagName === 'button';
            return activeKeyboard || isInput || isTextarea || isSelect || isButton || isContentEditable;
        }
        const x = document.querySelector('#bricks-builder-iframe').contentWindow;
        document.addEventListener('keyup', function(e) {
            const isExcluded = excludeFromBuilder(e);
            !isExcluded ? runShortcuts(e, false) : '';
        });
        x.document.addEventListener('keyup', function(e) {
            const isExcluded = excludeFromPreview(e);
            !isExcluded ? runShortcuts(e, false) : '';
        });
        document.addEventListener('keydown', function(e) {
            const isExcluded = excludeFromBuilder(e);
            !isExcluded ? runShortcuts(e) : '';
        });
        x.document.addEventListener('keydown', function(e) {
            const isExcluded = excludeFromPreview(e);
            !isExcluded ? runShortcuts(e) : '';
        });
    }, 
    setBricksLabs: function (content){
        if(!content || content.length < 1) return;

        const canvas = document.querySelector('#brxcBricksLabsOverlay #brxc-overlay__canvas');
        if(!canvas) return;

        let output = `<div class="brxc-article__container">`;
        content.forEach(article => {
            const rawDate = new Date(article.date);
            const date = rawDate.toLocaleDateString('en-us', { weekday:"short", year:"numeric", month:"short", day:"numeric"});
            output += `<div class="brxc-article__wrapper">
                <div class="brxc-article__col-left">
                <a href="${article.link}" target="_blank"><img src="${article.featured_image_src_square}" /></a>
                </div>
                <div class="brxc-article__col-right">
                    <a href="${article.link}" target="_blank"><h3>${article.title.rendered}</h3></a>
                    <p class="brxc-article__author-wrapper"><i class="brxc-article__author-icon fas fa-calendar-days"></i>${date}<span class="brxc-article__author">by <strong>${article.author_info.display_name}</strong></span></p>
                    <span class="brxc-article__excerpt">${article.excerpt.rendered}</span>
                    <a href="${article.link}" class="brxc-overlay__action-btn secondary brxc-article__readmore" target="_blank">Read more</a>
                </div>
            </div>`;
        })
        output += `</div>`;
        canvas.innerHTML = output;
    },
    bricksLabsAPI: function(target, query = false, openModal = false){
        const self = this;
        (target) ? target.classList.add('disable') : '';
        const wrapper = document.querySelector('#brxcBricksLabsOverlay');

        if(openModal === true && wrapper.dataset.loaded === "true") {
            return;
        }

        let url;
        (query) ? url = 'https://brickslabs.com/wp-json/wp/v2/posts?search=' + query.replace(/\s+/g, '+') : url = 'https://brickslabs.com/wp-json/wp/v2/posts';
        const post = async () => {
            const rawResponse = await fetch(url);
            const content = await rawResponse.json();
            if(content.error){
                console.log('error');
                (target) ? target.classList.remove('disable') : '';
            } else {
                self.setBricksLabs(content);
                wrapper.setAttribute('data-loaded', 'true');
                (target) ? target.classList.remove('disable') : '';
            }
        };

        post();
            
    },
    // setBreakpointsAttributes: function(){
    //     const self = this;
    //     const icons = document.querySelectorAll('#bricks-toolbar .group-wrapper.breakpoints li.breakpoint');
    //     const breakpoints = self.vueState.breakpoints;
    //     breakpoints.forEach(({ label, key }) => {
    //         icons.forEach(icon => {
    //           const text = icon.dataset.balloon;
    //           if (text.includes(label)) {
    //             icon.dataset.key = key;
    //           }
    //         });
    //     });
    // },
    alertMsg: function(autoremove = true, msg, delay){
        const wrapper = document.querySelector('#brxc-alert-message');
        if(!wrapper) return;

        let message = document.createElement('DIV');
        message.setAttribute("id", "brxcAlertMessageContent");
        message.innerHTML = msg;
        setTimeout(() => {
            wrapper.appendChild(message);
            wrapper.setAttribute('active');
        }, 
        setTimeout(() => {
            if(autoremove){
                message = document.querySelector('#brxcAlertMessageContent');
                message.remove();
                wrapper.classList.remove('active');
            }
        }, delay))
    },
    setAlertMsg: function(){
        const msg = document.querySelector('#bricks-message');
        if(!msg) return;
        const html = `<div id="brxc-alert-message"></div>`;
        msg.insertAdjacentHTML("afterend", html);
    },
    setStructurePanelKeyboardShortcuts: function(){
        const self = this;
        const element = document.getElementById('bricks-structure');
        if(!element) return;
        
        const arrowUpHandler = function(e) {
            if (e.shiftKey && e.key === "ArrowUp" && (e.metaKey && e.altKey) === false) {
                self.moveElement(event,'top');
            }
        };
        
        const arrowRightHandler = function(e) {
            if (e.shiftKey && e.key === "ArrowRight" && (e.metaKey && e.altKey) === false) {
                self.moveElement(event,'right');
            }
        };
        
        const arrowDownHandler = function(e) {
            if (e.shiftKey && e.key === "ArrowDown" && (e.metaKey && e.altKey) === false) {
                self.moveElement(event,'down');
            }
        };
        
        const arrowLeftHandler = function(e) {
            if (e.shiftKey && e.key === "ArrowLeft" && (e.metaKey && e.altKey) === false) {
                self.moveElement(event,'left');
            }
        };
        
        const addKeydownListeners = function() {
            document.addEventListener('keydown', arrowUpHandler);
            document.addEventListener('keydown', arrowRightHandler);
            document.addEventListener('keydown', arrowDownHandler);
            document.addEventListener('keydown', arrowLeftHandler);
        };
        
        const removeKeydownListeners = function() {
            document.removeEventListener('keydown', arrowUpHandler);
            document.removeEventListener('keydown', arrowRightHandler);
            document.removeEventListener('keydown', arrowDownHandler);
            document.removeEventListener('keydown', arrowLeftHandler);
        };
        
        element.addEventListener('mouseenter', addKeydownListeners);
        element.addEventListener('mouseleave', removeKeydownListeners);
    },
    initStates: function(){
        const self = this;
        self.vueState.brxcShowImportInput = false;
        self.vueState.brxcShowLock = true;
        if(Array.isArray(self.vueState.colorPalette) && self.vueState.colorPalette.length > 0){
            const defaultPalette = Array.from(self.vueState.colorPalette).find(el => el && el.hasOwnProperty('default') && el.default === "true");
            if(defaultPalette) {
                self.colorStates.activePalette = defaultPalette.id
            } else {
                self.colorStates.activePalette = self.vueState.colorPalette[0].id;
            }
        }

        // Set light mode as default
        const x = document.querySelector('#bricks-builder-iframe').contentWindow;
        document.documentElement.setAttribute('data-theme', 'light');
        x.document.documentElement.setAttribute('data-theme', 'light');

    },
    
    populateNestableElements: function(){
        const self = this;
        for(const [key, value] of Object.entries(bricksData.elements)){
            if(bricksData.elements[key].hasOwnProperty('nestableChildren') && bricksData.elements[key].nestableChildren !== null && key !== "section" ) self.nestableElements.push(key);
        }        
    },
    disableMoveElement: function(){
        const self = this;
        const elementObj = self.builderStates.activeElement
        if(!elementObj) return;

        const content = self.helpers.getContent();
        const contextualMenu = document.querySelector('#bricks-builder-context-menu');
        const left = contextualMenu.querySelector('span[data-balloon="Indent Left"]');
        const right = contextualMenu.querySelector('span[data-balloon="Indent Right"]');
        const up = contextualMenu.querySelector('span[data-balloon="Move Up"]');
        const down = contextualMenu.querySelector('span[data-balloon="Move Down"]');
        const isParent = elementObj.parent === 0 || self.helpers.isComponentRoot(elementObj.parent)

        // Component Root
        if(self.helpers.isComponentRoot(elementObj.id)){
            [left,right,up,down].forEach(el => {
                el.classList.add('disable');
            })
            return;
        }

        // disable indent left
        left.classList.remove('disable');
        if(isParent) left.classList.add('disable');

        // disable indent right
        right.classList.remove('disable');
        // element is on root
        if (isParent) {
            const hasContainer = content.some(el =>
                (el.parent === 0 || self.helpers.isComponentRoot(el.parent)) &&
                el.id !== elementObj.id &&
                bricksData.elements[el.name]?.nestable === true
            );
        
            if (!hasContainer) {
                right.classList.add('disable');
            }
        // element is nested
        } else {
            const parent = elementObj.parent;
            const parentChildren = self.helpers.getElementObject(parent).children;
        
            const hasNestable = parentChildren.some(el =>
                el !== elementObj.id &&
                bricksData.elements[self.helpers.getElementObject(el).name]?.nestable === true
            );
        
            if (!hasNestable) {
                right.classList.add('disable');
            }
        }
        
        //disable move up & down
        up.classList.remove('disable');
        down.classList.remove('disable');

        // element is on root
        if(isParent){
            const rootContent = self.helpers.isComponentActive() ? self.vueState.activeComponent.elements.filter(el => el.hasOwnProperty('parent') && el.parent === self.vueState.activeComponent.id ) : content.filter(el => el && el.hasOwnProperty('parent') && (el.parent === 0));
            const obj = self.helpers.isComponentActive() ? elementObj.id : elementObj;
            if(rootContent.length === 1 || rootContent.indexOf(obj) === 0) up.classList.add('disable');
            if(rootContent.length === 1 || rootContent.indexOf(obj) === rootContent.length -1) down.classList.add('disable');

        // element is nested
        } else {
            const parent = elementObj.parent;
            const parentChildren = self.helpers.getElementObject(parent).children;
            const currentIndex = parentChildren.indexOf(elementObj.id);
            if(!parentChildren[currentIndex - 1]) up.classList.add('disable');
            if(!parentChildren[currentIndex + 1]) down.classList.add('disable');
        }
        

    },
    // showHideElement: function(){
    //     const self = this;
    //     if(!self.builderStates.isElementActive) return;
    //     const activeEl = self.builderStates.activeElement;

    //     // Label
    //     const hideElement = document.querySelector('#bricks-builder-context-menu #hideElement .label');
    //     if (!hideElement || typeof activeEl === "undefined") return;
    //     const target = self.helpers.createTarget('_display');
    //     if(activeEl.hasOwnProperty('settings') && activeEl.settings.hasOwnProperty(target) && activeEl.settings[target] === "none") {
    //         hideElement.textContent = `Show Element`;
    //     } else {
    //         hideElement.textContent = `Hide Element`;
    //     }

    //     // Frontend
    //     const frontend = document.querySelector('#bricks-builder-context-menu #hideElement .frontend');
    //     if(frontend){
    //         if(activeEl.hasOwnProperty('settings') && activeEl.settings.hasOwnProperty('_hideElementFrontend') && activeEl.settings._hideElementFrontend === true){
    //             frontend.classList.add('active');
    //         } else {
    //             frontend.classList.remove('active');
    //         }
    //     }
    //     // Builder
    //     const builder = document.querySelector('#bricks-builder-context-menu #hideElement .builder');
    //     if(builder){
    //         if(activeEl.hasOwnProperty('settings') && activeEl.settings.hasOwnProperty('_hideElementBuilder') && activeEl.settings._hideElementBuilder === true){
    //             builder.classList.add('active');
    //         } else {
    //             builder.classList.remove('active');
    //         }
    //     }

    //     // Settings
    //     const settings = document.querySelector('#bricks-builder-context-menu #hideElement .settings');
    //     if(settings){
    //         if(self.hideElementStates.active === true){
    //             settings.classList.add('active');
    //         } else {
    //             settings.classList.remove('active');
    //         }
    //     }

    // },
    // setDeleteWrapper: function(){
    //     const self = this;
    //     const elementObj = self.builderStates.activeElement;
    //     if(!elementObj) return;

    //     const contextualMenu = document.querySelector("#bricks-builder-context-menu");
    //     const deleteIcon = contextualMenu.querySelector('li.delete');
    //     if (!deleteIcon) return; 
        
    //     const buttons = deleteIcon.querySelector('div.buttons');
    //     if (buttons) buttons.remove();
        
    //     // component
    //     if(self.helpers.isComponentRoot(elementObj.id)){
    //         if (buttons) buttons.remove();
    //         return;
    //     }

    //     if(typeof elementObj === "undefined" || !elementObj.hasOwnProperty('children') || !Array.isArray(elementObj.children) || elementObj.children.length < 1) return;
    //     let icon = `<div class="buttons"><span class="action" data-balloon="Move Children Up" data-balloon-pos="top-right" onClick="ADMINBRXC.deleteWrapper(event);"><i class="fas fa-trash-can-arrow-up"></i></span></div>`;
    //     deleteIcon.innerHTML += icon;
    // },
    // deleteWrapper: function(event) {
    //     event.preventDefault();
    //     event.stopPropagation();
    
    //     const self = this;
    //     const elementObj = self.builderStates.activeElement;
    
    //     if (!elementObj?.children?.length) return;
    
    //     const parent = elementObj.parent;
    //     const children = [...elementObj.children];
    
    //     const content = self.helpers.getContent();
    //     const siblings = content.filter(el => el.parent === parent);
    //     let objIndex = siblings.indexOf(elementObj);
    
    //     children.forEach(childId => {
    //         const childObj = self.helpers.getElementObject(childId);
    //         if (childObj) {
    //             self.vueGlobalProp.$_moveElement({
    //                 element: childObj,
    //                 parentId: parent,
    //                 index: objIndex,
    //             });
    //             objIndex++;
    //         }
    //     });
    
    //     self.vueGlobalProp.$_deleteElement(elementObj);
    // },
    convertBasicToRichtoHeader: function(newName){
        const self = this;
        const elementObj = self.vueState.activeElement;
        if(!elementObj) return;

        elementObj.name = newName;
        elementObj.settings.tag = newName === "text-basic" ? "p" : bricksData.elements[newName]?.tag;
    },
    setConvertBasictoRichtoHeader: function(){
        const self = this;
        const elementObj = self.builderStates.activeElement;
        if(!elementObj) return;

        const oldMenu = document.querySelector('#brxcConvertBasicToRich');
        if (oldMenu) oldMenu.remove();
        const contextualMenu = document.querySelector("#bricks-builder-context-menu li.wrap");
        if(!contextualMenu) return; 

        const name = elementObj.name;
        if (name === 'text' || name === 'text-basic' || name === 'heading'){
            let icons = '';
            icons += `<li id="brxcConvertBasicToRich" class="convert sep"><span class="label">Convert </span>`;
            (name !== 'text-basic') ? icons += `<div class="buttons"><span data-balloon="Basic Text" data-balloon-pos="top" onclick="ADMINBRXC.convertBasicToRichtoHeader('text-basic')"><i class="ti-align-justify"></i></span>` : '';
            (name !== 'text') ? icons += `<div class="buttons"><span data-balloon="Rich Text" data-balloon-pos="top" onclick="ADMINBRXC.convertBasicToRichtoHeader('text')"><i class="ti-align-left"></i></span>` : '';
            (name !== 'heading') ? icons += `<div class="buttons"><span data-balloon="Heading" data-balloon-pos="top" onclick="ADMINBRXC.convertBasicToRichtoHeader('heading')"><i class="ti-text"></i></span>` : '';
            icons += `</div></li>`;
            contextualMenu.insertAdjacentHTML("afterEnd", icons);
        }
        
    },
    importCSSfromElements: function(btn,cm,type,scope){
        const self = this;
        const existingCSS = cm.getValue();
        const dataOptions = { indent_size: 2 };
        const contentArr = self.helpers.getContent();
        let content;
        if (type === "id"){
            
            content = contentArr
        } else if(scope === "global"){
            content = self.vueState.globalClasses;
        } else if(scope === "page"){
            let activeClasses = [];
            contentArr.forEach(el => {
                if(el.settings.hasOwnProperty('_cssGlobalClasses') && el.settings._cssGlobalClasses.length > 0) activeClasses = activeClasses.concat(el.settings._cssGlobalClasses);
            })
            content = Array.from(self.vueState.globalClasses).filter(el => el && el.hasOwnProperty('id') && activeClasses.includes(el.id));
        }
        let css = "";
        const mq = (self.vueGlobalProp.$_isMobileFirst._value) ? 'min' : 'max';
        self.vueState.breakpoints.forEach(bp => {
            if(bp.hasOwnProperty('base') && bp.base === true) {
                if(content.length > 0){
                    content.forEach(el => {
                        if(el.hasOwnProperty('settings') && el.settings.hasOwnProperty('_cssCustom')) {
                            css += el.settings._cssCustom;
                            delete el.settings._cssCustom;
                        }
                    })
                }
            } else{
                if(content.length > 0){
                    let hasStyle = false;
                    let cssTemp = '';
                    content.forEach(el => {
                        const property = `_cssCustom:${bp.key}`;
                        if(el.hasOwnProperty('settings') && el.settings.hasOwnProperty(property)) {
                            hasStyle = true;
                            cssTemp += el.settings[property];
                            delete el.settings[property];
                        }
                    })
                    if(hasStyle){
                        css += `@media (${mq}-width: ${bp.width}px){`;
                        css += cssTemp; 
                        css += '}'; 
                    }
                }
            }
        })
        
        css = css_beautify(css, dataOptions)
        
        cm.setValue(`${existingCSS}\n${css}`);
        const span = btn.parentElement.querySelector('span');
        setTimeout(() => {
            span.innerHTML = "CSS Imported Successfully!";
        }, setTimeout(() => {
            span.innerHTML = "Import CSS from Global Classes";
        }, 2000))

    },
    generateSelectors: function(btn,cm, incudeMQ){
        const self = this;
        if (!self.builderStates.isElementActive) {
            const wrapper = document.querySelector('#brxcCSSOverlay .brxc-overlay__error-message-wrapper');
            let inner = `<div class="brxc-ai-response-wrapper remove-on-reset">`;
            inner += `<div name="error-css-msg" class="error-message" id="cssErrorMsg"><i class="bricks-svg ti-close" onClick="this.parentElement.parentElement.remove()"></i>Error: Select an element inside the Structure Panel</div></div>`;
            wrapper.innerHTML = inner;
            return;
        }

        const existingCSS = cm.getValue();
        const dataOptions = { indent_size: 2 };
        const mq = (self.vueGlobalProp.$_isMobileFirst._value) ? 'min' : 'max';
        let existingSelector = [];
        let selector = false;
        function createSelector(obj,existingSelector){
            if (obj.settings.hasOwnProperty('_cssGlobalClasses') && obj.settings._cssGlobalClasses.length > 0) {
                const unlocked = [];
                const locked = [];
                obj.settings._cssGlobalClasses.forEach(el => {
                    (self.vueGlobalProp.$_isLocked(el)) ? locked.push(el) : unlocked.push(el);
                });
                const ids = (unlocked.length > 0) ? unlocked : locked;
                if (ids.length > 0) {
                    let classes = [] 
                    ids.forEach(id => {
                        const classObj = self.vueGlobalProp.$_getGlobalClass(id);
                        if(classObj && classObj.hasOwnProperty('name')){
                            classes.push(classObj.name);
                        }
                    })
                    selector = `.${classes.join('.')}`;
                } else {
                    selector = false;
                }
            } else {
                selector = `#${self.vueGlobalProp.$_getElementId(obj)}`;
            } 
            if(selector === false || existingSelector.includes(selector)) return "";
            existingSelector.push(selector);
            return `${selector}{}`;
        }
        let css = "";
        function checkChildren(obj, first){
            if(first === true) existingSelector = [];
            css += createSelector(obj,existingSelector);
            if(!obj.children || obj.children.length < 1) return;
            obj.children.forEach(child =>{
                checkChildren(self.helpers.getElementObject(child), false);
            })
        }
        self.vueState.breakpoints.forEach(bp => {
            if(bp.hasOwnProperty('base') && bp.base === true) {
                checkChildren(self.builderStates.activeElement, true);
            } else if(incudeMQ === true){
                css += `@media (${mq}-width: ${bp.width}px){`;
                checkChildren(self.builderStates.activeElement, true);
                css += '}'; 
            }
        })
        css = css_beautify(css, dataOptions)
        cm.setValue(`${existingCSS}\n${css}`);
        const span = btn.parentElement.querySelector('span');
        setTimeout(() => {
            span.innerHTML = "Selectors Generated Successfully!";
        }, setTimeout(() => {
            span.innerHTML = "Generate Selectors";
        }, 2000))
    },
    setRootClassComponentToggle: function(){
        const self = this;

        // Remove Buttons
        if(!self.builderStates.isElementActive) return
        
        const elementObj = self.builderStates.activeElement;
        if(!bricksData.elements[elementObj.name].hasOwnProperty('nestable') || bricksData.elements[elementObj.name].nestable !== true) {
            const buttons = document.querySelector('#brxcBEMConverter .buttons');
            if (buttons) buttons.remove(); 
            return;
        }
        const li = document.querySelector('#brxcBEMConverter');
        if(!li) return;

        // Add Buttons
        const buttons = li.querySelector('#brxcBEMConverter .buttons');
        if (!buttons){
            const newButtons = document.createElement('DIV');
            newButtons.classList.add('buttons')
            newButtons.innerHTML = `<span class="action" data-balloon="Enable Root Element" data-balloon-pos="top" onclick="event.stopPropagation();ADMINBRXC.rootClassComponentToggle(true)"><i class="fas fas fa-toggle-off"></i></span>`;
            li.appendChild(newButtons);
        }

        const txt = document.querySelector('#brxcBEMConverter span.action');
        if(!txt) return;

        const icon = document.querySelector('#brxcBEMConverter span.action i');
        if(!icon) return;

        if(elementObj.settings.hasOwnProperty('classConverterComponent') && elementObj.settings.classConverterComponent === true){
            txt.dataset.balloon = "Disable Root Component";
            icon.classList.remove('fa-toggle-off')
            icon.classList.add('fa-toggle-on')
        } else {
            txt.dataset.balloon = "Enable Root Component";
            icon.classList.remove('fa-toggle-on')
            icon.classList.add('fa-toggle-off')
        }
    },
    rootClassComponentToggle: function(isStructurePanel = false){
        const self = this;
        if(!self.builderStates.isElementActive) return;

        const elementObj = self.builderStates.activeElement;

        if(elementObj.settings.hasOwnProperty('classConverterComponent') && elementObj.settings.classConverterComponent === true){
            delete elementObj.settings.classConverterComponent;
        } else {
            elementObj.settings.classConverterComponent = true;
        }

        self.vueState.showContextMenu = false;
        if(isStructurePanel){
            self.vueState.showContextMenu = elementObj.id;
            
        } else {
            self.openContextualMenu(false, () => {return self.classContextualMenu()})
        }
    },
    initContextualMenuObservers: function(){
        const self = this;
        const contextualMenu = document.querySelector('#bricks-builder-context-menu');

        const observer = new MutationObserver(function(mutation) {
            const contextualMenu = document.querySelector('#bricks-builder-context-menu');
            if(self.vueState.brxcRunningMenuObserver === true || window.getComputedStyle(contextualMenu).display === 'none') return;
            self.vueState.brxcRunningMenuObserver = true;

            self.runStates();

            if(self.helpers.isBuilderTweaksTabActive('structure-panel')){
                self.disableMoveElement()
                self.setConvertBasictoRichtoHeader()
                self.setRootClassComponentToggle()
            }

            setTimeout(() => self.vueState.brxcRunningMenuObserver = false, 100)
        });

        observer.observe(contextualMenu, { subtree: true, childList: true, attributes: true, attributeFilter: ['style'] });
    },
    getSelectorsFromFile: function (file) {
        // Remove comments from the file
        file = file.replace(/\/\*[\s\S]*?\*\//g, '');
    
        // Remove media query declarations but keep the content
        file = file.replace(/@media[^{]*\{/gi, '');
    
        // Close remaining brackets from media queries
        file = file.replace(/\s*}\s*(?=})/g, '');
    
        // Pattern One: Match text within curly braces {}
        const patternOne = /\{([^}]*)\}/g;
    
        // Pattern Two: Match dot notation (e.g., .example-name) excluding comments
        const patternTwo = /\.([a-zA-Z0-9_-]+)\b/g;
    
        const stripped = file.replace(patternOne, '');
    
        const selectors = [...stripped.matchAll(patternTwo)].map((match) => match[1]);
    
        return Array.from(new Set(selectors));
    },
    getVariablesFromFile: function (file) {
        // Remove comments from the file
        file = file.replace(/\/\*[\s\S]*?\*\//g, '');
        
        // Remove media query declarations but keep the content
        file = file.replace(/@media[^{]*\{/gi, '');
        
        // Close remaining brackets from media queries
        file = file.replace(/\s*}\s*(?=})/g, '');
        
        // Pattern to match CSS variable declarations without capturing the '--' prefix
        const variablePattern = /--([a-zA-Z0-9_-]+)\s*:\s*[^;]+;/g;
        
        // Extract variable names without the '--' prefix
        const variables = [...file.matchAll(variablePattern)].map((match) => match[1]);
        
        // Return unique variable names
        return Array.from(new Set(variables));;
    },

    parseGlobalCSS: function(key){
        const self = this;
        const cm = document.querySelector(key + ' .CodeMirror[data-type="at"]')
        if(!cm) return;

        const file = cm.CodeMirror.getValue();

        const allClasses = self.getSelectorsFromFile(file);
        let itemFound = 0;
        if(allClasses && allClasses.length >0){
            allClasses.forEach(el => {
                const found = Array.from(self.vueState.globalClasses).find(e => e && e.hasOwnProperty('name') &&  e.name === el);
                if(!found){
                    itemFound++;

                    // Generate ID
                    const id = self.vueGlobalProp.$_generateId();

                    // Generate new global class
                    self.generateGlobalClass('globalCSS',el, false, id);

                    // Lock the class
                    if(!self.vueState.globalClassesLocked.includes(`globalCSS${id}`)) self.vueState.globalClassesLocked.push(`globalCSS${id}`);
                }
            })
        }
        const message = () => {
            if(itemFound > 0) {
                return `<span>${itemFound} Classes Exported Successfully!</span>`;
            } else if(itemFound === 0){
                return `<span>Abort: no new class found!</span>`;
            } else {
                return '<span>Error: No Class has been exported</span>'
            }
        }
        self.vueGlobalProp.$_showMessage(message());
    },
    extractGlobalVariables: function(key){
        const self = this;
        const cm = document.querySelector(key + ' .CodeMirror[data-type="at"]')
        if(!cm) return;

        const file = cm.CodeMirror.getValue();
        const allVariables = self.getVariablesFromFile(file);

        let itemFound = 0;
        if(Array.isArray(allVariables) && allVariables.length >0){
            allVariables.forEach(el => {
                const found = Array.from(self.vueState.globalVariables).find(e => e && e.hasOwnProperty('name') &&  e.name === el);
                if(!found){
                    itemFound++;
                    const id = self.vueGlobalProp.$_generateId();

                    self.vueState.globalVariables.push({
                        id: id,
                        name: el,
                    })
                }
            })
        }
        const message = () => {
            if(itemFound > 0) {
                return `<span>${itemFound} Variables Exported Successfully!</span>`;
            } else if(itemFound === 0){
                return `<span>Abort: no new Variable found!</span>`;
            } else {
                return '<span>Error: No Variable has been exported</span>'
            }
        }
        self.vueGlobalProp.$_showMessage(message());
    },
    setDefaultElements: function(){
        const self = this;

        // Heading Textarea
        if (Object.values(self.globalSettings.defaultElementFeatures).includes('heading-textarea')) {
            const textControl = bricksData.elements?.heading?.controls?.text;
            if (textControl) {
              textControl.type = "textarea";
            }
        }
    },
    populateClassCategories: function(){
        const self = this;
        const finalCats = typeof self.vueState.globalClassesCategories !== "undefined" ? ['All', 'Uncategorized'].concat(Array.from(self.vueState.globalClassesCategories).filter(el => el && el.name).map(el => el && el.name).sort((a, b) => a.localeCompare(b, undefined, {sensitivity: 'base'}))) : false; 
        self.states.classManagerCategories = finalCats;
    },
    refreshColorPrefix: function(){
        const self = this;
        if(!self.helpers.isGlobalColorsTabActive()) return;

        const palettes = self.vueState.colorPalette;
        if(!Array.isArray(palettes) || palettes.length < 1) return;
        let hasChanged = false;
        palettes.forEach(palette => {
            if(!palette.hasOwnProperty('colors') || !Array.isArray(palette.colors) || palette.colors.length < 1) return;

            palette.colors.forEach(color => {
                if (!color.hasOwnProperty('raw') || !color.hasOwnProperty('rawValue') || !color.rawValue.hasOwnProperty('light')) return;
                const colorName = self.helpers.getColorName(color, palette.prefix);
                if (!colorName) return;
                const name = self.helpers.setColorPrefix(self.helpers.formatForClasses(colorName), self.helpers.isFramework(color.id), palette.prefix);
                if (color.raw !== `var(--${name})`) {
                    color.raw = `var(--${name})`;
                    hasChanged = true;
                }
            })
        })
        if (hasChanged) self.helpers.saveChanges('colorPalette');
    },
    setColorVariablesOnLoad: function(){
        const self = this;
        self.generateColorCSS();
        self.refreshColorPrefix();
    },
    responsiveSliderStates: {
        active: false,
    },
    toggleResponsiveSlider: function(){
        const self = this;

        self.responsiveSliderStates.active = self.topbarStates.tweaks.includes('responsive-slider')

        // Topbar
        if(!self.responsiveSliderStates.active) {
            self.vueState.previewWrapperHeight = self.vueState.previewWrapperHeight + 66
        } else {
            self.vueState.previewWrapperHeight = self.vueState.previewWrapperHeight - 66;
        }

        self.initToolbar();
        self.setResponsiveSlider();
        
    },
    setResponsiveSlider: function() {
        const self = this;
        const existing = document.querySelector('#brxcResponsiveBar');
        if(existing && !self.responsiveSliderStates.active) return existing.remove();

        const isMobileFirst = self.vueGlobalProp.$_isMobileFirst._value;
        const rulerArr = isMobileFirst 
            ? [0, 200, 400, 600, 800, 1000, 1200, 1400, 1600, 1800, 2000] 
            : [1800, 1600, 1400, 1200, 1000, 800, 600, 400, 200, 0];
        
        const iframePreview = document.querySelector('#bricks-preview');
        if (!iframePreview) return; // Ensure element exists before proceeding
    
        const container = document.createElement('div');
        container.id = "brxcResponsiveBar";
        container.setAttribute('class', 'active');
    
        // Generate breakpoints markers
        const breakpointMarkers = self.vueState.breakpoints
            .slice(1) // Skip the first item (index > 0)
            .map(bp => `<div class="bp-marker" style="${isMobileFirst ? 'left' : 'right'}: calc((${bp.width - 1} - 0) / (2000 - 0) * 100%)"></div>`)
            .join('');
    
        // Generate ruler intervals
        const rulerIntervals = rulerArr
            .map(r => `<div class="interval">${r}px</div>`)
            .join('');
    
        // Construct content
        container.innerHTML = `
            <div class="brxc-range-input-wrapper brxc__range">
                <div class="brxc-range-input-container">
                    <input type="range" min="1" max="2000" value="${self.vueState.previewWidth ?? 1201}" class="brxc-input__range${isMobileFirst ? ' reverse' : ''}" 
                        oninput="ADMINBRXC.responsiveBar(this);">
                    ${breakpointMarkers}
                    <div class="ruler">${rulerIntervals}</div>
                </div>
            </div>
        `;
    
        iframePreview.prepend(container);
    },
    setResponsiveHelper: function(){
        const self = this;

        const isMobileFirst = self.vueGlobalProp.$_isMobileFirst._value;
        document.body.classList.add('at-responsive-helper')

        // listener
        const toolbarItems = document.querySelectorAll('#bricks-toolbar li');
        if (!toolbarItems || toolbarItems.length < 1) return;

        function isDesktop(bp){
            const isMobileFirst = self.vueGlobalProp.$_isMobileFirst._value;
            if(isMobileFirst){
                if(self.vueState.breakpoints.indexOf(bp) === self.vueState.breakpoints.length - 1) return true;
                return false;
                
            } else {
                if(self.vueState.breakpoints.indexOf(bp) === 0) return true;
                return false;
            }
        }

        function isMobile(bp){
            const isMobileFirst = self.vueGlobalProp.$_isMobileFirst._value;
            if(isMobileFirst){
                if(self.vueState.breakpoints.indexOf(bp) === 0) return true;
                return false;
                
            } else {
                if(self.vueState.breakpoints.indexOf(bp) === self.vueState.breakpoints.length - 1) return true;
                return false;
            }
        }
        
        toolbarItems.forEach(el => {
            el.addEventListener('click', () => {
                const isTweakActive = self.topbarStates.tweaks.includes('responsive-helper');
                if(isTweakActive){
                    document.body.classList.add('at-responsive-helper')
                    const slider = document.querySelector('#brxcResponsiveBar input');
                    // Responsive Helper
                    if(self.topbarStates.tweaks.includes('responsive-helper')){
                        if(el.classList.contains('breakpoint')){
                            const bp = self.vueState.breakpoints.find(el => el && el.key === self.vueState.breakpointActive)
                            const bpNext = self.vueState.breakpoints[self.vueState.breakpoints.indexOf(bp) + 1];
                            if(el.dataset.click === 'true') {
                                toolbarItems.forEach(el => el.removeAttribute('data-click'))
                                let minValue;
        
                                // Calculate  minValue
                                if(isMobileFirst){
                                    self.vueState.previewWrapperWidth > bp.width ? minValue = self.vueState.previewWrapperWidth : minValue = 1400
                                } else {
                                    isMobile(bp) && bp.hasOwnProperty('widthBuilder') ? minValue = bp.widthBuilder : minValue = 320
                                }
                                
                                // Calculate previewWidth
                                if(bpNext) {
                                    const nextValue = isMobileFirst ? bpNext.width - 1 : bpNext.width + 1;
                                    self.vueState.previewWidth = nextValue;
                                } else {
                                    self.vueState.previewWidth = minValue
                                }
                            } else {
                                toolbarItems.forEach(el => el.removeAttribute('data-click'))
                                el.setAttribute('data-click', 'true');
                                if((!isMobileFirst && isDesktop(bp) && bp.hasOwnProperty('widthBuilder')) || (isMobileFirst && isMobile(bp) && bp.hasOwnProperty('widthBuilder'))){
                                    self.vueState.previewWidth = bp.widthBuilder;
                                } else if(!isMobileFirst && isDesktop(bp) && self.vueState.previewWrapperWidth > bp.width){
                                    self.vueState.previewWidth = self.vueState.previewWrapperWidth;
                                } else {
                                    self.vueState.previewWidth = bp.width;
                                }
                            }
                        }
                    }

                    // Update slider
                    if(slider) slider.value = self.vueState.previewWidth;
                } else {
                    document.body.classList.remove('at-responsive-helper')
                }
            })


            // Update slide from text inputs
            const slider = document.querySelector('#brxcResponsiveBar input');
            if(slider){
                const input = el.querySelector('input');
                if(!input) return;
                input.addEventListener('keyup', () => {
                    setTimeout(() => {
                        slider.value = self.vueState.previewWidth;
                    },1)
                })
            }
        })

        if(self.topbarStates.tweaks.includes('responsive-helper')){
            const firstBp = document.querySelectorAll('#bricks-toolbar li.breakpoint')[0];
            if(firstBp) firstBp.setAttribute('data-click', 'true'); 
        }
        

    },
    responsiveBar: function(target){
        const self = this;
        self.vueState.previewWidth = target.value;

        if (self.debounceTimer) {
            clearTimeout(self.debounceTimer);
        }

        self.debounceTimer = setTimeout(() => {
            const original = self.vueState.breakpoints;
            const bps = original.slice();
            let device;
            bps.forEach(bp => {
                if(self.vueGlobalProp.$_isMobileFirst._value){
                    if (target.value >= bp.width) device = bp.key;
                } else {
                    if (target.value <= bp.width) device = bp.key;
                }
            })

            device ? self.vueState.breakpointActive = device : self.vueState.breakpointActive = self.vueState.breakpoints[0].key;
            setTimeout(() => self.vueState.previewWidth = target.value, 0);
        }, 0);
    },
    hideEmptyElementCategory: function(){
        const cats = document.querySelectorAll('#bricks-panel-elements-categories .category');
        if(!cats || cats.length < 1) return;
        cats.forEach(cat => {
            const els = cat.querySelectorAll('.sortable-wrapper > li');
            if(!els || els.length < 1) return;
            let isHidden = true;
            els.forEach(el => {
                const display = window.getComputedStyle( el ,null).getPropertyValue('display');
                if(display !== 'none') isHidden = false;
            })
            if(isHidden) cat.style.display = "none";
        })
    },
    draggableStructurePanelStates: {
        isDraggable: false,
        structureOffsetX: null,
        structureOffsetY: null,
        structureWidth: 400,
    },
    draggableStructurePanel: function () {
        const self = this;
        const structure = document.querySelector('#bricks-structure');
        const preview = document.querySelector('#bricks-preview');
        const header = structure.querySelector('#bricks-panel-header .title');
    
        function move(e) {
            structure.style.setProperty('--right', `${e.clientX - self.draggableStructurePanelStates.structureOffsetX}px`);
            structure.style.setProperty('--width', `${self.draggableStructurePanelStates.structureWidth}px`);
            structure.style.setProperty('--top', `${e.clientY - self.draggableStructurePanelStates.structureOffsetY}px`);
        }
    
    
        function toggleDraggableState() {
            self.draggableStructurePanelStates.isDraggable = !self.draggableStructurePanelStates.isDraggable;
            document.body.classList.add('draggable-structure')
        }
    
        function setupDraggable() {
            header.addEventListener("mousedown", handleMouseDown);
            document.addEventListener("mouseup", handleMouseUp);
            document.addEventListener("contextmenu", handleMouseUp)
        }
    
        function resetDraggable() {
            document.body.classList.remove('draggable-structure')
            header.removeEventListener("mousedown", handleMouseDown);
            document.removeEventListener("mouseup", handleMouseUp);
            document.removeEventListener("contextmenu", handleMouseUp)
        }
    
        function handleDoubleClick(e) {
            if(!self.structurePanelStates.tweaks.includes('draggable-structure-panel')){
                return self.draggableStructurePanelStates.isDraggable = false;
            }
            toggleDraggableState();
            if(self.draggableStructurePanelStates.isDraggable){
                move(e)
                setupDraggable()
            } else {
                resetDraggable();
            }
        }
    
        function handleMouseDown(e) {
            preview.style.pointerEvents = "none";
            self.draggableStructurePanelStates.structureOffsetX = e.clientX - structure.offsetLeft;
            self.draggableStructurePanelStates.structureOffsetY = e.clientY - structure.offsetTop;
            self.draggableStructurePanelStates.structureWidth = structure.getBoundingClientRect().width;
            document.addEventListener('mousemove', move);
        }
    
        function handleMouseUp() {
            preview.style.pointerEvents = "auto";
            document.removeEventListener("mousemove", move);
        }
    
        // Initial setup
        header.addEventListener('dblclick', handleDoubleClick);
    },
    codepenStates: {
        mainPrompt: '',
        elementsLabels: true,
        bemClasses: true,
        bricksVariables: false,
        bricksVariablesArr: [],
        bricksColors: false,
        bricksColorsArr: [],
        includesIds: true,
        excludeIds: '',
        includesClasses: true,
        excludeClasses: '',
        createGlobalClasses: false,
        includesTexts: true,
        includesAttributes: true,
        excludeAttributes: '',
        aiPrompt: '',
        viewEditors: true,
        viewPreview: true,
    },
    setCodepenImporter: function(){
        const self = this;
        const modal = document.querySelector('#brxcCodePenImporter');
        if(!modal) return;

        const existing = modal.querySelector('.CodeMirror');
        if(existing) return;

        // Reset States
        self.codepenStates.viewEditors = true;
        self.codepenStates.viewPreview = true;

        // CodeMirror
        const textareas = modal.querySelectorAll('textarea');
        textareas.forEach(textarea => {
            const options = self.codeMirrorOptions(textarea);
            options.mode = textarea.dataset.mode;
            options.styleActiveLine = true;
            options.selfContain = true;
            if(textarea.dataset.mode === "css" || textarea.dataset.mode === "javascript"){
                options.autoCloseBrackets = true;
            }
            if(textarea.dataset.mode === "htmlmixed"){
                options.autoCloseTags = true;
                options.matchTags = true;
                options.profile = "xhtml";
            }
            options.hintOptions = {
                schemaInfo: {
                  html: true  // Enable HTML schema-based hints
                }
            };
            options.search = { bottom: false };
            const MyCM = CodeMirror.fromTextArea(textarea, options);
            emmetCodeMirror(MyCM);
            MyCM.getWrapperElement().setAttribute("data-type", "at");

            // autocomplete
            MyCM.on("keydown", function (cm, event) {
                event.stopPropagation();
                // Check if the completion is not already active
                if (!cm.state.completionActive &&
                    (
                    // Trigger autocomplete only for these keys
                    (event.key >= 'a' && event.key <= 'z') || 
                    event.key === '-' || 
                    event.key === '<' || 
                    event.key === '/') &&
                    // Ensure autocomplete is triggered only when it's appropriate
                    !event.metaKey && !event.altKey && !event.ctrlKey && 
                    event.key !== '{' && event.key !== '}') {

                
                    // Force the autocomplete dropdown to appear without auto-completing
                    CodeMirror.commands.autocomplete(cm, null, { completeSingle: false, hintOptions: { completeSingle: false } });
                    
                }
    
                if(event.metaKey && event.shiftKey && event.key === "7" ){
                    cm.toggleComment();
                }
            })
            MyCM.on("keyup", function (cm, event) {
                event.stopPropagation();
                self.codepenMountPreview(modal);
            })
        })

        // Hide toggle

        const toggles = modal.querySelectorAll('[data-panel]');
        toggles.forEach(toggle => {
            toggle.addEventListener('click', (e) => {
                const icon = e.target.querySelector('i');
                const isVisible = icon.classList.contains('fa-eye') ? true : false;
                const value = isVisible ? 'minmax(32px, 1fr)' : '99fr';
                const panel = e.target.dataset.panel;
                const parent = e.target.closest('#brxcCpImporterEditors')
                parent.style.setProperty(`--${panel}`, value);
                if(isVisible){
                    icon.classList.remove('fa-eye')
                    icon.classList.add('fa-eye-slash')
                } else {
                    icon.classList.add('fa-eye')
                    icon.classList.remove('fa-eye-slash')
                }

            })
        })

        // Mount Devices icons
        const preview = modal.querySelector('#brxcCpImporterPreview')
        const iconContainer = modal.querySelector('#brxcCpImporterPreviewIcons');
        if(iconContainer){
            let iconContent = ''
            self.vueState.breakpoints.forEach((bp, index) =>{
                const icon = self.helpers.bpIcons(bp.icon);
                const isDefault = self.vueGlobalProp.$_isMobileFirst._value ? index === self.vueState.breakpoints.length - 1 : index === 0
                iconContent += `<div${isDefault ? ` class="active"` : ''} data-balloon="${bp.label}" data-balloon-pos="bottom" data-width="${isDefault ? 'full' : bp.width}">${icon}</div>`;
            })
            iconContainer.innerHTML = iconContent;
            iconContainer.addEventListener('click', (e) => {
                const target = e.target;
                const width = target.dataset.width;
                if(width){
                    preview.style.maxWidth = width === "full" ? "100%" : `${width}px`;
                    iconContainer.querySelector('[data-width].active')?.classList.remove('active');
                    target.classList.add('active');
                }
            })
        }

        // AI
        const aiContainer = modal.querySelector("#brxcCpImporterAIContainer");
        if(aiContainer && self.helpers.isAIActive() && self.globalSettings.isAIApiKeyEmpty !== ""){
            const AIprompt = document.createElement('DIV');
            AIprompt.id = "brxcCpConverterAIpromptContainer"
            let content = '';
            content += `<div id="brxcCpConverterAIpromptWrapper">
                            <div id="brxcCpConverterDropzone">
                                <input type="file" id="brxcCpConverterAIImage" accept="image/*" />
                                <div class="dropzone-content">
                                    <div id="previewImage" /><i class="fas fa-upload"></i></div>
                                    <div id="fileInfo">Drop an image here...</div>
                                </div>
                                <div id="removeImage"><i class="bricks-svg ti-close"></i></div>
                            </div>
                            <textarea id="brxcCpConverterAIprompt" placeholder="Message AI">${self.codepenStates.aiPrompt}</textarea>
                            <div id="brxcCpConverterAISendRequest"${self.superPowerStates.isAIRunning ? ' class="disable"' : ' onclick="ADMINBRXC.codepenGenerateAI(this);"'} data-balloon="Send" data-balloon-pos="top-right"><i class="fas fa-arrow-up"></i></div>
                        </div>`;


            AIprompt.innerHTML = content;
            aiContainer.appendChild(AIprompt);

            const inputText = aiContainer.querySelector('#brxcCpConverterAIprompt');
            if(inputText){
                self.helpers.textAreaAutoGrow(inputText, '30px')
                inputText.addEventListener('keyup', (e) => {
                    self.superPowerStates.AIprompt = e.target.value;
                    self.helpers.textAreaAutoGrow(e.target, '30px')
                })
            }
        }

        // Preview

        const bricksStyles = FRAMEBRXC.content.querySelectorAll('style, link');
        const fragment = modal.querySelector('iframe');
        const fragDoc = fragment.contentDocument || fragment.contentWindow.document;

        bricksStyles.forEach(style => {
            const clone = style.cloneNode(true);
            fragDoc.head.appendChild(clone);
        });

        const globalClasses = self.vueState.globalClasses.map(el => self.vueGlobalProp.$_generateCss("globalClass", el, ['block'])).join('');
        const globalClassesDOM = document.createElement('style');
        globalClassesDOM.id = "brxc-global-classes";
        globalClassesDOM.textContent = globalClasses;
        fragDoc.head.appendChild(globalClassesDOM);

        const inlineHtmlStyles = document.documentElement.getAttribute('style') || '';
        fragDoc.documentElement.setAttribute('style', inlineHtmlStyles);

        // Dropzone

        const dropzone = modal.querySelector('#brxcCpConverterDropzone');
        if(dropzone){
            const fileInput = dropzone.querySelector('input');
            const fileInfo = dropzone.querySelector('#fileInfo');
            const previewImage = dropzone.querySelector('#previewImage');
            const removeFileBtn = dropzone.querySelector('#removeImage');
            
            const removeFile = (e, propagation = false) => {
                if(propagation){
                    e.preventDefault();
                    e.stopPropagation()
                }
                fileInput.value = '';
                previewImage.innerHTML = `<i class="fas fa-upload"></i>`
                fileInfo.textContent = 'Drop an image here...';
                removeFileBtn.style.display = "none";
            }

            dropzone.addEventListener('click', (e) => {
                removeFile(e);
                fileInput.click()
            });

            dropzone.addEventListener('dragover', e => {
                e.preventDefault();
                dropzone.classList.add('dragover');
            });

            dropzone.addEventListener('dragleave', () => {
                dropzone.classList.remove('dragover');
            });

            dropzone.addEventListener('drop', e => {
                e.preventDefault();
                dropzone.classList.remove('dragover');
                const file = e.dataTransfer.files[0];
                if (file) {
                    fileInput.files = e.dataTransfer.files;
                    handleFile(file);
                }
            });

            fileInput.addEventListener('change', e => {
                const file = e.target.files[0];
                handleFile(file);
            });

            removeFileBtn.addEventListener('click', (e) => {
                // Reset state
                removeFile(e, true);
            });

            function handleFile(file) {
                if (!file || !file.type.startsWith('image/')) return;

                removeFileBtn.style.display = "flex";

                fileInfo.textContent = file.name;

                const reader = new FileReader();
                reader.onload = (e) => {
                    previewImage.innerHTML = `<img src="${e.target.result}" />`
                };
                
                reader.readAsDataURL(file);
            }
        }
    },
    codepenMountPreview: function(modal){
        const iframe = modal.querySelector('iframe');
        const fragDoc = iframe.contentDocument || iframe.contentWindow.document;
    
        const existingStyle = fragDoc.querySelector('#brxc-preview-styles');
    
        const cms = modal.querySelectorAll('.CodeMirror');
        const editorsValue = {
            html: cms[0].CodeMirror.getValue(),
            css: cms[1].CodeMirror.getValue(),
            javascript: cms[2].CodeMirror.getValue(),
        };
    
        // Set HTML first so we don't wipe out appended nodes
        fragDoc.body.innerHTML = editorsValue.html;
    
        // CSS
        if(existingStyle){
            existingStyle.textContent = editorsValue.css;
        } else {
            const newStyle = document.createElement('style');
            newStyle.id = "brxc-preview-styles";
            newStyle.textContent = editorsValue.css;
            fragDoc.head.appendChild(newStyle);
        }
    
        // JavaScript
        if (editorsValue.javascript) {
            let isValid = true;
            const jsCode = editorsValue.javascript

            try {
                new Function(jsCode); // Syntax check
            } catch (e) {
                isValid = false;
            }

            if (isValid) {
                const newScript = document.createElement('script');
                newScript.id = "brxc-preview-scripts";
                newScript.textContent = `
                  try {
                    ${jsCode}
                  } catch (e) {
                    // Silent catch: do nothing
                  }
                `;
                fragDoc.body.appendChild(newScript);
            }
        }          
    },
    codepenGenerateAI: function(element){
        const self = this;
        const modal = document.querySelector('#brxcCodePenImporter');
        if(!modal) return;

        // Loader
        const loader = modal.querySelector('#brxcCpImporterLoading');

        // Textarea
        const desc = modal.querySelector('#brxcCpConverterAIprompt').value;
        modal.querySelector('#brxcCpConverterAIprompt').value = '';

        // Dropzone
        const dropzone = modal.querySelector('#brxcCpConverterDropzone');
        const fileInput = dropzone.querySelector('input');
        
        const removeInputs = () => {
            dropzone.querySelector('input').value = '';
            dropzone.querySelector('#previewImage').innerHTML = `<i class="fas fa-upload"></i>`
            dropzone.querySelector('#fileInfo').textContent = 'Drop an image here...';
            dropzone.querySelector('#removeImage').style.display = "none";
        }


        const states = self.codepenStates;

        loader.classList.add('active');

        let model = self.globalSettings.defaultAIModel;

        const cms = modal.querySelectorAll('.CodeMirror');
        const editorsValue = {
            html: cms[0].CodeMirror.getValue(),
            css: cms[1].CodeMirror.getValue(),
            javascript: cms[2].CodeMirror.getValue(),
        };

        // Construct the initial description with all the details.
        let description = `Generate HTML structure and CSS and Javascript code based on the following user's request:"${desc}". You are building a component that will be inserted inside the <main> tag of the <body> of the page. Don't add styles to <body> and <main> in your CSS code. Use the best practices in terms of accessibility (aria-label, role, etc...). Make the design responsive on all devices. If no JavaScript is necessary, return an empty string for the "javascript" key.`;
        if (editorsValue.html && editorsValue.html !== "") description += ` Build your response based on the following existing HTML structure: ${editorsValue.html}. Include the existing HTML code in your response where it makes sense.`
        if (editorsValue.css && editorsValue.css !== "") description += ` Build your response based on the following existing CSS code: ${editorsValue.css}.  Include the existing CSS code in your response where it makes sense.`
        if (editorsValue.javascript && editorsValue.javascript !== "") description += ` Build your response based on the following existing Javascript code: ${editorsValue.javascript}.`
        if (states.bemClasses) description += ` For each element, add a class that follows the BEM standards. Include the existing Javascript code in your response where it makes sense.`;
        if (states.elementsLabels) description += ` For each element, add a data-attribute named 'data-bricks-label' and set a short meaningful value into it - possibly related to the associated class and capitalize the text.`;
        
        // Construct detailed descriptions for each property using the state variables
        if (states.bricksVariables) {
            const vars = self.vueState.globalVariables;
            const cats = self.vueState.globalVariablesCategories.filter(el => states.bricksVariablesArr.includes(el.id));
            let string = '';
            cats.forEach(cat => {
                const filteredVars = vars.filter(el => el.category === cat.id).map(el => `--${el.name}`).join(',');
                string += `category **${cat.name}**:${filteredVars}; `;
            });
            description  += ` Use the following CSS variables where it makes the most sense: ${string}.`;
        }
    
        if (states.bricksColors) {
            const palettes = self.vueState.colorPalette.filter(el => states.bricksColorsArr.includes(el.id));
            let string = '';
            palettes.forEach(palette => {
                const hasATColors = (Array.isArray(palette.colors) ? palette.colors : []).filter(el => el.hasOwnProperty('rawValue'));
                const prefix = palette.prefix;
                if (hasATColors.length > 0) {
                    const filteredColors = hasATColors.map(el => {
                        let name = self.helpers.getColorName(el, prefix);
                        if(prefix && prefix !== ""){
                            name = `${prefix}${name}`
                        }
                        return `--${name}`;
                    }).join(',');
                    string += `palette **${palette.name}**:${filteredColors}; `;
                }
            });
            description += ` Use the following CSS variables when using a color: ${string}.`;
        }

        const message = [
            { role: "system", content: "You are a web component generator. Always use the 'generateWebSection' function and nothing else." },
            { role: "user", content: [
                    {type: "text", text: description}
                ]
            }
        ]

        if (fileInput && fileInput.files && fileInput.files.length > 0) {
            const file = fileInput.files[0];
          
            const reader = new FileReader();
            reader.onload = function(event) {
              const base64Image = event.target.result;

              message[1].content.push({
                "type": "image_url",
                "image_url": {
                  "url": base64Image
                }
              });
            };
          
            reader.readAsDataURL(file);
          } 

        const functions = [
            {
                name: "generateWebSection",
                description: "Generate a static webpage component with HTML, CSS, and JS",
                parameters: {
                type: "object",
                properties: {
                    html: { type: "string", description: "The HTML code corresponding to the HTML structure." },
                    css: { type: "string", description: "The CSS code corresponding to the HTML structure." },
                    javascript: { type: "string", description: "The JavaScript code corresponding to the HTML structure." }
                },
                required: ["html", "css", "javascript"]
                }
            }
        ];
        
        function generate(attempt = 1){
            jQuery.ajax({
                type: 'POST',
                url: openai_ajax_req.ajax_url,
                data: {
                    action: 'openai_ajax_function',
                    nonce: openai_ajax_req.nonce
                },
                success: function(response) {
                    const fetchDescription = async () => {
                        const rawResponse = await fetch('https://api.openai.com/v1/chat/completions', {
                            method: 'POST',
                            headers: {
                                'Content-Type': 'application/json',
                                'Authorization' : 'Bearer ' + response,
                            },
                            body: JSON.stringify({
                                model: model,
                                messages: message,
                                functions: functions,
                                function_call: { name: "generateWebSection" },
                            })
                        });

                        const content = await rawResponse.json();
                        removeInputs();
                
                        if(content.error){
                            self.insertErrorMessage('brxcCodePenImporter', false, '#brxcCodePenImporter', content.error.message);
                            console.log(content.error)
                            loader.classList.remove('active');
                        } else {
                            try {
                                const fnCall = content.choices?.[0]?.message?.function_call;
    
                                if (!fnCall || fnCall.name !== 'generateWebSection') {
                                throw new Error('No valid function call returned');
                                }
    
                                let args;
                                try {
                                    args = JSON.parse(fnCall.arguments);
                                } catch (e) {
                                    loader.classList.remove('active');
                                    console.error('Failed to parse function arguments:', fnCall.arguments);
                                    self.insertErrorMessage('brxcCodePenImporter', false, '#brxcCodePenImporter', `Failed to parse function arguments:' ${fnCall.arguments}`);
                                    throw new Error('Invalid function arguments format');
                                }
    
                                // Make sure all expected keys exist (even if values are empty strings)
                                ['html', 'css', 'javascript'].forEach((key) => {
                                if (!(key in args)) {
                                    loader.classList.remove('active');
                                    self.insertErrorMessage('brxcCodePenImporter', false, '#brxcCodePenImporter', `Missing required field: ${key}`);
                                    throw new Error(`Missing required field: ${key}`);
                                }
                                });

                                self.codepenPopulateControls(args);

                                loader.classList.remove('active');
    
    
                            } catch (e) {
                                if (attempt < 2) {
                                console.warn('Retrying...');
                                return generate(attempt + 1);
                                }

                                self.insertErrorMessage('brxcCodePenImporter', false, '#brxcCodePenImporter', `Error: ${e.message}`);
                                loader.classList.remove('active');
                            }
                        }
                    };
                    fetchDescription()
                },
                error: function(response){
                    self.insertErrorMessage('brxcCodePenImporter', false, '#brxcCodePenImporter', `Something went wrong with the OpenAI AJAX request: ${response}`);
                    loader.classList.remove('active');
                }
            });
        }
        
        generate()
    },
    codepenPopulateControls: function(args){
        const self = this;
        const modal = document.querySelector('#brxcCodePenImporter');
        const cms = modal.querySelectorAll('.CodeMirror');
        Object.keys(args).forEach((arg, index) => {
            if(cms[index]) {
                let value = args[arg];
                if (index === 1){
                    value = css_beautify(value, { indent_size: 2 })
                }
                cms[index].CodeMirror.setValue(value);
            }
        })
        
        self.codepenMountPreview(modal);
    },
    codepenImporterInit: function(){
        const self = this;
        self.setCodepenImporter();
        const canvas = document.querySelector('#brxcCpImporterFilterCanvas');
        if(!canvas) return;

        let content = '';

        const modalObjs = [
            {
                label: "View Editors",
                balloon: "Enable this toggle if you wish to display the editors within this modal.",
                balloonPos: "bottom",
                data: "click",
                prop: "viewEditors",
                require: true
            },
            {
                label: "View Preview",
                balloon: "Enable this toggle if you wish to display the preview window within this modal.",
                balloonPos: "bottom",
                data: "click",
                prop: "viewPreview",
                require: true
            }
        ];

        const aiObjs = [
            {
                label: "Use BEM classes?",
                balloon: "Enable this toggle if you wish the generated classes to follow the BEM methodology.",
                balloonPos: "bottom",
                data: "click",
                prop: "bemClasses",
                require: true,
            },
            {
                label: "Use the Bricks/AT Global Variables?",
                balloon: "Enable this toggle if you wish to include your Bricks/AT Variable list to the prompt.",
                balloonPos: "bottom-right",
                data: "click",
                prop: "bricksVariables",
                require: true,
            },
            {
                label: "Select the Categories you want to include:",
                balloon: "Click on the following categories to include the corresponding variables inside the AI prompt",
                balloonPos: "bottom-right",
                data: "select",
                dataArr: self.vueState.globalVariablesCategories,
                prop: "bricksVariablesArr",
                require: self.codepenStates.bricksVariables,
            },
            {
                label: "Use AT's Global Color variables?",
                balloon: "Enable this toggle if you wish to include your AT's Global Variable list to the prompt.",
                balloonPos: "bottom-right",
                data: "click",
                prop: "bricksColors",
                require: true,
            },
            {
                label: "Select the Palette(s) you want to include:",
                balloon: "Click on the following palettes to include the corresponding variables inside the AI prompt",
                balloonPos: "bottom-right",
                data: "select",
                dataArr: self.vueState.colorPalette,
                prop: "bricksColorsArr",
                require: self.codepenStates.bricksColors,
            },
            {
                label: "Generate labels for each element?",
                balloon: "Enable this toggle if you want AI to update the labels of all the generated elements in the structure.",
                balloonPos: "bottom-right",
                data: "click",
                prop: "elementsLabels",
                require: true,
            }
        ];
        
        const objs = [
            {
                label: "Include ID's?",
                balloon: "If this option is checked, the original ID of each element will be imported.",
                balloonPos: "bottom",
                data: "click",
                prop: "includesIds",
                require: true,
            },
            {
                label: "Exclude ID's that contain:",
                balloon: "Type keywords that will exclude the ID's to be imported. For multiple keywords, separate each word by a comma.",
                balloonPos: "bottom",
                data: "input",
                prop: "excludeIds",
                require: self.codepenStates.includesIds,
                placeholder: 'brx-,brxe-',
            },
            {
                label: "Include Classes?",
                balloon: "If this option is checked, the original classes of each element will be imported.",
                balloonPos: "bottom",
                data: "click",
                prop: "includesClasses",
                require: true,
            },
            {
                label: "Exclude Classes that contain:",
                balloon: "Type keywords that will exclude the classes to be imported. For multiple keywords, separate each word by a comma.",
                balloonPos: "bottom",
                data: "input",
                prop: "excludeClasses",
                require: self.codepenStates.includesClasses,
                placeholder: 'brx-,brxe-',
            },
            {
                label: "Generate Global Classes?",
                balloon: "By default, if a class is not present in the Global Class list, it will be added as a CSS Class. If you enable this option, it will create a dedicated Global Class instead.",
                balloonPos: "bottom-right",
                data: "click",
                prop: "createGlobalClasses",
                require: self.codepenStates.includesClasses,
            },
            {
                label: "Include Attributes?",
                balloon: "If this option is checked, the original attributes of each element will be imported.",
                balloonPos: "bottom",
                data: "click",
                prop: "includesAttributes",
                require: true,
            },
            {
                label: "Exclude Attributes that contain:",
                balloon: "Type keywords that will exclude the attributes to be imported. For multiple keywords, separate each word by a comma.",
                balloonPos: "bottom",
                data: "input",
                prop: "excludeAttributes",
                require: self.codepenStates.includesAttributes,
                placeholder: 'href,src',
            },
        ]

        function mountControl(obj){
            let content = '';
            if(obj.data === "click" && obj.require){
                content += `<div class="gridUI__input-wrapper">
                        <label class="has-tooltip">
                            <span>${obj.label}</span>
                            <div data-balloon="${obj.balloon}" data-balloon-pos="${obj.balloonPos}" data-balloon-length="medium">
                                <i class="fas fa-circle-question"></i>
                            </div>
                        </label>
                        <i class="fas fa-toggle-${self.codepenStates[obj.prop] === true ? 'on' : 'off'}" data-click="${obj.prop}"></i>
                    </div>`
            }
            if(obj.data === "input" && obj.require){
                content += `<div class="gridUI__input-wrapper brxc-input">
                        <label class="has-tooltip">
                            <span>${obj.label}</span>
                            <div data-balloon="${obj.balloon}" data-balloon-pos="${obj.balloonPos}" data-balloon-length="medium">
                                <i class="fas fa-circle-question"></i>
                            </div>
                        </label>
                        <input class="brxc-input-text" data-input="${obj.prop}" value="${self.codepenStates[obj.prop]}" placeholder="${obj.placeholder}"/>
                    </div>`
            }

            if(obj.data === "select" && obj.require){
                content += `<div class="gridUI__input-wrapper brxc-input select">
                        <label class="has-tooltip">
                            <span>${obj.label}</span>
                            <div data-balloon="${obj.balloon}" data-balloon-pos="${obj.balloonPos}" data-balloon-length="medium">
                                <i class="fas fa-circle-question"></i>
                            </div>
                        </label>
                        <div class="brxc-overlay__action-btn-wrapper">`
                        obj.dataArr.forEach(el => {
                            content += `<div class="brxc-overlay__action-btn${self.codepenStates[obj.prop].includes(el.id) ? ' active' : ''}" data-select="${obj.prop}" data-id="${el.id}">${el.name}</div>`
                        })
                        content += `</div></div>`;
            }

            return content;
        }

        content += `<div class="brxc-cpconverter__setting-container">
                        <span class="gridUI__title">Modal SETTINGS</span>
                        ${modalObjs.map(obj => {
                            return mountControl(obj)
                        }).join('')}
                    </div>`
        if(self.helpers.isAIActive() && self.globalSettings.isAIApiKeyEmpty !== ""){
            content += `<div class="brxc-cpconverter__setting-container">
                        <span class="gridUI__title">AI PROMPT SETTINGS</span>
                        ${aiObjs.map(obj => {
                            return mountControl(obj)
                        }).join('')}
                    </div>`
        }          

        content += `<div class="brxc-cpconverter__setting-container">
                        <span class="gridUI__title">IMPORT SETTINGS</span>
                        ${objs.map(obj => {
                            return mountControl(obj)
                        }).join('')}
                    </div>`
        
        canvas.innerHTML = content;
        
        // Listeners
        canvas.querySelectorAll('[data-click]').forEach(input => {
            input.addEventListener('click', (e) => {
                const main = document.querySelector('#brxcCpImporterMain');
                const prop = input.dataset.click;
                switch(prop){
                    case "viewEditors":
                        const viewEditors = self.codepenStates.viewEditors;
                        if(viewEditors){
                            main.style.setProperty('--editors', '0fr')
                        } else {
                            main.style.setProperty('--editors', '1fr')
                        }
                        break;
                    case "viewPreview":
                        const viewPreview = self.codepenStates.viewPreview;

                        if(viewPreview){
                            main.style.setProperty('--preview', '0fr')
                        } else {
                            main.style.setProperty('--preview', '3fr')
                        }
                        break;
                }
                self.codepenStates[prop] = !self.codepenStates[prop];
                self.codepenImporterInit();
            })
        })
        canvas.querySelectorAll('[data-input]').forEach(input => {
            input.addEventListener('input', (e) => {
                const prop = input.dataset.input;
                self.codepenStates[prop] = e.target.value;
            })
        })
        canvas.querySelectorAll('[data-select]').forEach(input => {
            input.addEventListener('click', (e) => {
                const prop = input.dataset.select;
                const id = input.dataset.id;
        
                // Check if the array doesn't contain the ID and push it if not present
                if (!self.codepenStates[prop].includes(id)) {
                    self.codepenStates[prop].push(id);
                } else {
                    // Remove the id from the array if it exists
                    const index = self.codepenStates[prop].indexOf(id);
                    if (index !== -1) {
                        self.codepenStates[prop].splice(index, 1);
                    }
                }
                self.codepenImporterInit();
            });
        });
    },
    htmlImporter: function (cmValues, states) {
        const self = this;
        const rootId = self.vueGlobalProp.$_generateId();
        const contentType = self.helpers.getTemplateType();
    
        // Check if activeElement exists and determine if it's on the root
        const activeElement = self.vueState.activeElement;
        const isParent = self.builderStates.isElementActive ? self.helpers.isElementOnRoot(activeElement.parent) : false;
    
        // Determine the parent ID
        let parentId;
    
        if (!activeElement || (isParent && !self.vueGlobalProp.$_isNestable())) {
            // If activeElement is undefined or it's on the root and not nestable
            parentId = 0;
        } else if (self.vueGlobalProp.$_isNestable()) {
            // If nestable, use active ID as parent
            parentId = self.vueState.activeId;
            self.helpers.getElementObject(parentId).children.push(rootId);
        } else {
            // Use the parent of the active element as parent
            parentId = activeElement.parent;
            self.helpers.getElementObject(parentId).children.push(rootId);
        }
    
        // Parse HTML string into an object array
        const arr = self.helpers.parseHtmlStringToObjectArray(rootId, parentId, cmValues, states);
    
        // Concat parsed elements into the correct content structure
        if (self.helpers.isComponentActive()) {
            self.vueState.activeComponent.elements = self.vueState.activeComponent.elements.concat(arr.reverse());
        } else {
            self.vueState[contentType] = self.vueState[contentType].concat(arr.reverse());
        }
    
        // Notify and open the imported element
        setTimeout(() => {
            self.openElement(rootId);
            self.vueGlobalProp.$_showMessage('Structure imported Successfully!');
        }, 10);
    },
    
    codepenImporter: function(){
        const self = this;
        const modal = document.querySelector('#brxcCodePenImporter');
        const cms = modal.querySelectorAll('.CodeMirror');
        const cmValues = {
            html: cms[0].CodeMirror.getValue() !== "" ? cms[0].CodeMirror.getValue() : false,
            css: cms[1].CodeMirror.getValue() !== "" ? cms[1].CodeMirror.getValue() : false,
            js: cms[2].CodeMirror.getValue() !== "" ? cms[2].CodeMirror.getValue() : false,
        }
        self.htmlImporter(cmValues, self.codepenStates);
    },
    generatedAIStructureStates: {
        mainPrompt: '',
        elementsLabels: true,
        includesIds: true,
        excludeIds: '',
        includesClasses: true,
        excludeClasses: '',
        createGlobalClasses: true,
        bemClasses: true,
        bricksVariables: false,
        bricksVariablesArr: [],
        bricksColors: false,
        bricksColorsArr: [],
        includesTexts: true,
        includesAttributes: true,
        excludeAttributes: '',
    },
    generatedAIStructureInit: function(){
        const self = this;
        const canvas = document.querySelector('#brxcAIGeneratedStructureCanvas');
        if(!canvas) return;

        const objs = [
            {
                label: "Generate Global Classes?",
                balloon: "By default, if a class is not present in the Global Class list, it will be added as a CSS Class. If you enable this option, it will create a dedicated Global Class instead.",
                data: "click",
                prop: "createGlobalClasses",
                require: true,
            },
            {
                label: "Use BEM classes?",
                balloon: "Enable this toggle if you wish the generated classes to follow the BEM methodology.",
                data: "click",
                prop: "bemClasses",
                require: true,
            },
            {
                label: "Use the Bricks/AT Global Variables?",
                balloon: "Enable this toggle if you wish to include your Bricks/AT Variable list to the prompt.",
                data: "click",
                prop: "bricksVariables",
                require: true,
            },
            {
                label: "Select the Categories you want to include:",
                balloon: "Click on the following categories to include the corresponding variables inside the AI prompt",
                data: "select",
                dataArr: self.vueState.globalVariablesCategories,
                prop: "bricksVariablesArr",
                require: self.generatedAIStructureStates.bricksVariables,
            },
            {
                label: "Use AT's Global Color variables?",
                balloon: "Enable this toggle if you wish to include your AT's Global Variable list to the prompt.",
                data: "click",
                prop: "bricksColors",
                require: true,
            },
            {
                label: "Select the Palette(s) you want to include:",
                balloon: "Click on the following palettes to include the corresponding variables inside the AI prompt",
                data: "select",
                dataArr: self.vueState.colorPalette,
                prop: "bricksColorsArr",
                require: self.generatedAIStructureStates.bricksColors,
            },
            {
                label: "Generate labels for each element?",
                balloon: "Enable this toggle if you want AI to update the labels of all the generated elements in the structure.",
                data: "click",
                prop: "elementsLabels",
                require: true,
            },
        ]
        let content = `<div class="gridUI__left-col">
                            <div class="gridUI__input-wrapper brxc-input">
                                <label class="has-tooltip">
                                    <span>Main prompt</span>
                                    <div data-balloon="Describe here how the HTML tree should be structured. Be as specific as possible for better results." data-balloon-pos="bottom" data-balloon-length="medium">
                                        <i class="fas fa-circle-question"></i>
                                    </div>
                                </label>
                                <textarea class="brxc-input-text" data-input="mainPrompt" placeholder="Type your prompt here..."/>${self.generatedAIStructureStates['mainPrompt']}</textarea>
                            </div>
                        </div>
                        <div class="gridUI__right-col"><span class="gridUI__title">AI SETTINGS</span>`;
        objs.forEach(obj => {
            if(obj.data === "click" && obj.require){
                content += `<div class="gridUI__input-wrapper">
                        <label class="has-tooltip">
                            <span>${obj.label}</span>
                            <div data-balloon="${obj.balloon}" data-balloon-pos="bottom" data-balloon-length="medium">
                                <i class="fas fa-circle-question"></i>
                            </div>
                        </label>
                        <i class="fas fa-toggle-${self.generatedAIStructureStates[obj.prop] === true ? 'on' : 'off'}" data-click="${obj.prop}"></i>
                    </div>`
            }
            if(obj.data === "input" && obj.require){
                content += `<div class="gridUI__input-wrapper brxc-input">
                        <label class="has-tooltip">
                            <span>${obj.label}</span>
                            <div data-balloon="${obj.balloon}" data-balloon-pos="bottom" data-balloon-length="medium">
                                <i class="fas fa-circle-question"></i>
                            </div>
                        </label>
                        <textarea class="brxc-input-text" data-input="${obj.prop}" placeholder="${obj.placeholder}"/>${self.generatedAIStructureStates[obj.prop]}</textarea>
                    </div>`
            }
            if(obj.data === "select" && obj.require){
                content += `<div class="gridUI__input-wrapper brxc-input select">
                        <label class="has-tooltip">
                            <span>${obj.label}</span>
                            <div data-balloon="${obj.balloon}" data-balloon-pos="bottom" data-balloon-length="medium">
                                <i class="fas fa-circle-question"></i>
                            </div>
                        </label>
                        <div class="brxc-overlay__action-btn-wrapper">`
                        obj.dataArr.forEach(el => {
                            content += `<div class="brxc-overlay__action-btn${self.generatedAIStructureStates[obj.prop].includes(el.id) ? ' active' : ''}" data-select="${obj.prop}" data-id="${el.id}">${el.name}</div>`
                        })
                        content += `</div></div>`;
            }
        })
        content += `</div>`;
        
        canvas.innerHTML = content;

        // Listeners
        canvas.querySelectorAll('[data-click]').forEach(input => {
            input.addEventListener('click', (e) => {
                const prop = input.dataset.click;
                self.generatedAIStructureStates[prop] = !self.generatedAIStructureStates[prop];
                self.generatedAIStructureInit();
            })
        })
        canvas.querySelectorAll('[data-input]').forEach(input => {
            input.addEventListener('input', (e) => {
                const prop = input.dataset.input;
                self.generatedAIStructureStates[prop] = e.target.value;
            })
        })
        canvas.querySelectorAll('[data-select]').forEach(input => {
            input.addEventListener('click', (e) => {
                const prop = input.dataset.select;
                const id = input.dataset.id;
        
                // Check if the array doesn't contain the ID and push it if not present
                if (!self.generatedAIStructureStates[prop].includes(id)) {
                    self.generatedAIStructureStates[prop].push(id);
                } else {
                    // Remove the id from the array if it exists
                    const index = self.generatedAIStructureStates[prop].indexOf(id);
                    if (index !== -1) {
                        self.generatedAIStructureStates[prop].splice(index, 1);
                    }
                }
                self.generatedAIStructureInit();
            });
        });
    },
    generatePromptForHTMLbyAI: function(target, states) {
        const self = this;
        target.classList.add('disable');
    
        // Construct the initial description with all the details.
        let description = `Generate HTML structure and CSS and Javascript code based on the following user's request:" + ${states.mainPrompt}`;
        if (states.bemClasses) description += ` For each element, add a class that follows the BEM standards.`;
        if (states.elementsLabels) description += ` For each element, add a data-attribute named 'data-bricks-label' and set a short meaningful value into it - possibly related to the associated class and capitalize the text.`;
        
        // Construct detailed descriptions for each property using the state variables
        let cssDescription = "The CSS code corresponding to the HTML structure. Make it responsive on all devices.";
        let jsDescription = "The JavaScript code corresponding to the HTML structure. If no JavaScript is necessary, return an empty string.";
        if (states.bricksVariables) {
            const vars = self.vueState.globalVariables;
            const cats = self.vueState.globalVariablesCategories.filter(el => states.bricksVariablesArr.includes(el.id));
            let string = '';
            cats.forEach(cat => {
                const filteredVars = vars.filter(el => el.category === cat.id).map(el => `--${el.name}`).join(',');
                string += `category **${cat.name}**:${filteredVars}; `;
            });
            cssDescription  += ` Use the following CSS variables where it makes the most sense: ${string}.`;
        }
    
        if (states.bricksColors) {
            const palettes = self.vueState.colorPalette.filter(el => states.bricksColorsArr.includes(el.id));
            let string = '';
            palettes.forEach(palette => {
                const hasATColors = (Array.isArray(palette.colors) ? palette.colors : []).filter(el => el.hasOwnProperty('rawValue'));
                if (hasATColors.length > 0) {
                    const filteredColors = hasATColors.map(el => `--${self.helpers.getColorName(el, palette.prefix)}`).join(',');
                    string += `palette **${palette.name}**:${filteredColors}; `;
                }
            });
            cssDescription += ` For the CSS, use the following CSS variables when using a color: ${string}.`;
        }
    
        // First Request: Get the best function description from the "Prompt Engineer".
        const firstRequestBody = {
            model: self.globalSettings.defaultAIModel,
            messages: [
                {
                    role: "system",
                    content: "You are a Prompt Engineer. Your task is to refine and shorten descriptions for OpenAI function calls to make them optimal. It's really important that your refined description doesn't exceed the 1000 strings length limit imposed by OpenAI."
                },
                {
                    role: "user",
                    content: description,
                }
            ]
        };
    
        jQuery.ajax({
            type: 'POST',
            url: openai_ajax_req.ajax_url,
            data: {
                action: 'openai_ajax_function',
                nonce: openai_ajax_req.nonce
            },
            success: function(response) {
                const fetchDescription = async () => {
                    const rawResponse = await fetch('https://api.openai.com/v1/chat/completions', {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                            'Authorization' : 'Bearer ' + response,
                        },
                        body: JSON.stringify(firstRequestBody)
                    });
                    const content = await rawResponse.json();
                    if(content.error){
                        self.insertErrorMessage('brxcGenerateAIStructure', false, '#brxcGenerateAIStructureOverlay', content.error.message);
                        target.classList.remove('disable');
                    } else {
                        const result = content.choices[0].message.content.trim(); // The optimized function description
                        self.generateHTMLAndCSS(target, states, {result: result, css: cssDescription, js: jsDescription}); // Call the second function with the optimized description
                    }
                };
                fetchDescription();
            },
            error: function(response){
                self.vueGlobalProp.$_showMessage('Something went wrong with the OpenAI AJAX request: ' + response);
                target.classList.remove('disable');
            }
        });
    },
    
    generateHTMLAndCSS: function(target, states, obj) {
        const self = this;
        const requestBody = {
            model: self.globalSettings.defaultAIModel,
            messages: [
                {
                    role: "system",
                    content: "You are an expert web designer with advanced knowledge in HTML and CSS. Your job is to generate clean, accessible code for any prompt."
                },
                {
                    role: "user",
                    content: states.mainPrompt,
                }
            ],
            functions: [
                {
                    name: "generateHtmlAndCss",
                    description: obj.result,
                    parameters: {
                        type: "object",
                        properties: {
                            html: {
                                type: "string",
                                description: "The HTML structure for the user's request. Use attributes to make it compliant with accessibility standards."
                            },
                            css: {
                                type: "string",
                                description: obj.css
                            },
                            js: {
                                type: "string",
                                description: obj.js
                            }
                        },
                        required: ["html", "css", 'js']
                    }
                }
            ],
            function_call: { name: "generateHtmlAndCss" }
        };

        jQuery.ajax({
            type: 'POST',
            url: openai_ajax_req.ajax_url,
            data: {
                action: 'openai_ajax_function',
                nonce: openai_ajax_req.nonce
            },
            success: function(response) {
                const fetchDescription = async () => {
                    const rawResponse = await fetch('https://api.openai.com/v1/chat/completions', {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                            'Authorization' : 'Bearer ' + response,
                        },
                        body: JSON.stringify(requestBody)
                    });
                    const content = await rawResponse.json();
                    if(content.error){
                        self.insertErrorMessage('brxcGenerateAIStructure', false, '#brxcGenerateAIStructureOverlay', content.error.message);
                        target.classList.remove('disable');
                    } else {
                        const result = content.choices[0].message;
                        if (result.function_call) {
                            const content = JSON.parse(result.function_call.arguments);
                            const obj = {
                                html: content.html,
                                css: content.css,
                                js: content.js,
                            }
                            self.htmlImporter(obj, states);
                            target.classList.remove('disable');
                            self.closeModal(target, target.target, '#brxcGenerateAIStructureOverlay');
                        }
                    }
                };
                fetchDescription();
            },
            error: function(response){
                self.vueGlobalProp.$_showMessage('Something went wrong with the OpenAI AJAX request: ' + response);
                target.classList.remove('disable');
            }
        });
    },
    remoteTemplatesStates: {
        data: [],
        search: '',
        active: {
            url: bricksData.siteUrl,
            name: "My Templates",
            default: true,
        },
        cats: [],
        activeCat: 'All',
        layout: '2-col',
    },
    openRemoteTemplatesModal: function(firstOpen = true, forceOpen = false){
        const self = this;

        // Close if it exists
        const existing = document.querySelector('#brxcRemoteTemplatesOverlay[data-active=true]');
        if(existing && !forceOpen) {
            self.closeTemplateModal();
            return;
        }
        if(firstOpen) {
            self.zoomOutStates.previous = self.vueState.previewScaleMax;
            self.topbarStates.tweaks.includes('zoom-out') ? self.zoomOut(true) : '';
        }

        // Get data
        const maybeExist = self.remoteTemplatesStates.data.find(el => el && el.url === self.remoteTemplatesStates.active.url);
        if(maybeExist){
            setTimeout(() => self.renderTemplate(), 0);
        } else {
            self.remoteTemplatesStates.active.default === true ? 
            self.getTemplateData() :
            self.getRemoteTemplateData(self.remoteTemplatesStates.active);
        }

        if(firstOpen){
            document.body.classList.add('at-quick-remote-template');
            self.openModal({target: false, id: '#brxcRemoteTemplatesOverlay', focus: '#brxcRemoteTemplatesUI__panel input[type=text]', forced: 'calc(var(--at-remote-template-margin) - 50px)'});
        }
    },
    getRemoteTemplateData: function(active){
        const self = this;
        const loader = document.querySelector('#brxcRemoteTemplatesUI__loader');
        if(loader) loader.classList.add('active');
        const dataObj = {
            action: 'get_remote_templates_data_ajax_function',
            nonce: openai_ajax_req.nonce,
            templateSource: active.url,
        };

        function getTemplateDataByAjax(){
            return new Promise((resolve, reject) => {
                jQuery.ajax({
                    url: openai_ajax_req.ajax_url,
                    data: dataObj,
                    method: "POST",
                    success: function (response) {
                        resolve(
                            self.remoteTemplateProcessResponse(response.data)
                        );
                    },
                    error: function (data) {
                        reject('Something went wrong.');
                    }
                });
            });
        }
        getTemplateDataByAjax()
    
    },
    getTemplateData: function(){
        const self = this;
        const loader = document.querySelector('#brxcRemoteTemplatesUI__loader');
        if(loader) loader.classList.add('active');

        const dataObj = {
            action: 'get_templates_data_ajax_function',
            nonce: openai_ajax_req.nonce,
        };

        function getTemplateDataByAjax(){
            return new Promise((resolve, reject) => {
                jQuery.ajax({
                    url: openai_ajax_req.ajax_url,
                    data: dataObj,
                    method: "POST",
                    success: function (response) {
                        resolve(
                            self.templateProcessResponse(response.data)
                        );
                    },
                    error: function (data) {
                        reject('Something went wrong.');
                    }
                });
            });
        }
        getTemplateDataByAjax()
    
    },
    convertToLogicalProperties: function (obj) {
        const keyTransformations = {
            _margin: {
                newKey: "_marginLogical",
                map: { top: "block-start", bottom: "block-end", left: "inline-start", right: "inline-end" }
            },
            _padding: {
                newKey: "_paddingLogical",
                map: { top: "block-start", bottom: "block-end", left: "inline-start", right: "inline-end" }
            },
            _border: {
                width: {
                    newKey: "_borderWidthLogical",
                    map: { top: "block-start-width", bottom: "block-end-width", left: "inline-start-width", right: "inline-end-width" }
                },
                radius: {
                    newKey: "_borderRadiusLogical",
                    map: { top: "start-start-radius", bottom: "end-start-radius", left: "end-end-radius", right: "start-end-radius" }
                },
                style: { newKey: "_borderStyle" },
                color: { newKey: "_borderColor" }
            },
            _top: { newKey: "_insetLogical", subKey: "block-start" },
            _bottom: { newKey: "_insetLogical", subKey: "block-end" },
            _left: { newKey: "_insetLogical", subKey: "inline-start" },
            _right: { newKey: "_insetLogical", subKey: "inline-end" },
            _width: { newKey: "_inlineSize" },
            _widthMin: { newKey: "_inlineSizeMin" },
            _widthMax: { newKey: "_inlineSizeMax" },
            _height: { newKey: "_blockSize" },
            _heightMin: { newKey: "_blockSizeMin" },
            _heightMax: { newKey: "_blockSizeMax" }
        };
    
        const transformedObj = {};
    
        Object.entries(obj).forEach(([key, value]) => {
            // Extract the base key and suffix (e.g., "_margin:desktop" → base "_margin", suffix ":desktop")
            const [baseKey, ...suffixParts] = key.split(":");
            const suffix = suffixParts.length ? `:${suffixParts.join(":")}` : "";
    
            const transform = keyTransformations[baseKey];
    
            if (transform) {
                if (transform.newKey) {
                    // Direct property transformation (e.g., _width → _inlineSize)
                    if (transform.map) {
                        // Transform subkeys if mapping exists (e.g., _margin.top → _marginLogical.block-start)
                        transformedObj[transform.newKey + suffix] = Object.fromEntries(
                            Object.entries(value).map(([subKey, val]) => [transform.map[subKey] || subKey, val])
                        );
                    } else if (transform.subKey) {
                        // Transform a single property into a nested one (e.g., _top → _insetLogical.block-start)
                        if (!transformedObj[transform.newKey + suffix]) {
                            transformedObj[transform.newKey + suffix] = {};
                        }
                        transformedObj[transform.newKey + suffix][transform.subKey] = value;
                    } else {
                        // Direct key replacement (e.g., _width → _inlineSize)
                        transformedObj[transform.newKey + suffix] = value;
                    }
                } else {
                    // Handle cases where baseKey has nested properties (e.g., _border)
                    Object.entries(value).forEach(([subKey, subValue]) => {
                        const subTransform = transform[subKey];
                        if (subTransform?.newKey) {
                            if (subTransform.map) {
                                // Convert nested subkeys (e.g., _border.width.top → _borderWidthLogical.block-start)
                                transformedObj[subTransform.newKey + suffix] = Object.fromEntries(
                                    Object.entries(subValue).map(([innerKey, innerVal]) => [subTransform.map[innerKey] || innerKey, innerVal])
                                );
                            } else {
                                // Direct key transformation (e.g., _border.style → _borderStyle)
                                transformedObj[subTransform.newKey + suffix] = subValue;
                            }
                        } else {
                            // Preserve unmodified properties
                            if (!transformedObj[key + suffix]) {
                                transformedObj[key + suffix] = {};
                            }
                            transformedObj[key + suffix][subKey] = subValue;
                        }
                    });
                }
            } else {
                // Preserve unchanged properties
                transformedObj[key] = value;
            }
        });
    
        return transformedObj;
    },
    convertObjToLogical: function(includeChildren = false){
        const self = this;

        function convertObj(id){
            const obj = self.helpers.getElementObject(id);
            if(!obj) return;

            obj.settings = self.convertToLogicalProperties(obj.settings);
            const hasGlobalClasses = obj.settings.hasOwnProperty('_cssGlobalClasses') && obj.settings._cssGlobalClasses.length > 0;
            if(hasGlobalClasses){
                obj.settings._cssGlobalClasses.forEach(cls => {
                    const clsObj = self.vueGlobalProp.$_getGlobalClass(cls);
                    clsObj.settings = self.convertToLogicalProperties(clsObj.settings);
                })
            }

            // Children
            if(includeChildren && obj.children && Array.isArray(obj.children) && obj.children.length > 0){
                obj.children.forEach(child => {
                    convertObj(child)
                })
            }
        }

        convertObj(self.vueState.activeElement.id)

    },
    convertTemplateData: function(target, els, callback, position = false){
        const self = this;
        if(target) target.classList.add('disable');
        
        if(self.globalSettings.defaultElementFeatures.includes('logical-properties')){
            els.forEach(el => {
                if(!el.hasOwnProperty('settings')) return;
                el.settings = self.convertToLogicalProperties(el.settings);
            })  
        }

        const dataObj = {
            action: 'convert_template_data_ajax_function',
            nonce: bricksData.nonce,
            atnonce: openai_ajax_req.nonce,
            importImages: 'true',
            templateData: JSON.stringify(els),
        };

        function convertTemplateDataByAjax(){
                jQuery.ajax({
                    url: openai_ajax_req.ajax_url,
                    data: dataObj,
                    method: "POST",
                    success: function (response) {
                        if (typeof callback === 'function') {
                            callback({
                                response: response,
                                position: position
                            }); 
                        }
                        if(target) target.classList.remove('disable');
                    },
                    error: function (response) {
                        console.log(response);
                        if(target) target.classList.remove('disable');
                    }
                });
            
        }
        convertTemplateDataByAjax()
    
    },
    insertTemplateData: function(obj){
        const self = this;
        const contentType = self.helpers.getTemplateType();
        let content = self.helpers.getContent(true);
        let elements = obj.response.data.elements;
        elements = self.helpers.assignNewIdsToElements(elements);
        
        if(obj.position !== false){
            self.vueState[contentType] = self.helpers.insertAfterNthParent(
                content,
                elements,
                obj.position
            );
            
        } else {
            let elements = obj.response.data.elements;
            elements[0].parent = 0;
            self.vueState[contentType] = JSON.parse(JSON.stringify(content.concat(elements)));
        }
    },
    saveTemplateData: function(el){
        const self = this;

        const obj = {
            'templateTitle': el.title,
            'templateBundle': el.bundles,
            'templateTags': el.tags,
            'templateType': el.type,
            'content': JSON.stringify(el.content),
        }

        const firstObj = {
            action: 'convert_template_data_ajax_function',
            nonce: bricksData.nonce,
            atnonce: openai_ajax_req.nonce,
            templateData: obj.content,
            importImages: 'true',
        };

        const secondObj = {
            action: 'save_template_data_ajax_function',
            nonce: bricksData.nonce,
            atnonce: openai_ajax_req.nonce,
        }

        function handleGlobalClasses(obj) {
            if (obj.hasOwnProperty('global_classes') && obj.global_classes.length > 0) {
                obj.global_classes.forEach(cls => {
                    if (!self.vueState.globalClasses.some(el => el.id === cls.id)) {

                        // Convert to logical properties
                        if(self.globalSettings.defaultElementFeatures.includes('logical-properties')){
                            if(!cls.hasOwnProperty('settings')) return;
                            cls.settings = self.convertToLogicalProperties(cls.settings);
                        }

                        self.vueState.globalClasses.push(cls);
                    }
                });
            }
        }

        function saveTemplateDataByAjax(ajaxObj, firstRun){
                jQuery.ajax({
                    url: openai_ajax_req.ajax_url,
                    data: ajaxObj,
                    method: "POST",
                    success: function (response) {
                        if(firstRun){
                            obj.content = response.data.elements;
                            secondObj.templateData = JSON.stringify(obj);
                            saveTemplateDataByAjax(secondObj, false)
                        } else{
                            handleGlobalClasses(el);
                            self.helpers.saveChanges('globalClasses');
                            self.helpers.saveChanges('globalClassesLocked');
                            self.vueGlobalProp.$_savePost();
                            self.vueGlobalProp.$_showMessage(`'${obj.templateTitle}' has been saved in My Templates!`);
                        }
                    },
                    error: function (response) {
                        console.log(response);
                    }
                });
            
        }
        saveTemplateDataByAjax(firstObj, true)
    
    },
    remoteTemplateProcessResponse: function(data){
        const self = this;
        if(typeof data.timestamp === 'number'){
            data.url = self.remoteTemplatesStates.active.url;
            data.default = false;
            if(self.remoteTemplatesStates.active.name) data.name = self.remoteTemplatesStates.active.name;
            self.remoteTemplatesStates.data.push(data);
            self.renderTemplate();
        }
    },
    templateProcessResponse: function(data){
        const self = this;
        if(Array.isArray(data)){
            const obj = [];
            obj.url = bricksData.siteUrl;
            obj.name = 'My Templates';
            obj.default = true;
            obj.templates = data;
            obj.bundles = Object.fromEntries([...new Set(data.flatMap(el => el.bundles))].map(tag => [tag, tag]));

            self.remoteTemplatesStates.data.push(obj);
            self.renderTemplate();
        }
    },
    renderTemplate: function(){
        const self = this;
        const loader = document.querySelector('#brxcRemoteTemplatesUI__loader');
        self.remoteTemplateHeader();
        self.remoteTemplateCats();
        self.remoteTemplatePanel();
        if(loader) loader.classList.remove('active');
    },
    remoteTemplateHeader: function(){
        const self = this;
        const canvas = document.querySelector("#brxcRemoteTemplatesUI__header");
        if(!canvas) return;

        const activeData = self.remoteTemplatesStates.data.find(el => el && el.url === self.remoteTemplatesStates.active.url);
        if(!activeData) return;

        let content = '<div id="brxcRemoteTemplateHeaderWrapper">';

        const sources = [{name:'My Templates', url: bricksData.siteUrl},{name:"Community Templates", url: "https://bricksbuilder.io/"}].concat(bricksData.remoteTemplateSettings.filter(el => el.hasOwnProperty('url') && el.url !== "https://bricksbuilder.io/"))

        sources.forEach(el => {
            content += `<div class="brxc-overlay__action-btn${el.url === activeData.url ? ' primary' : ' secondary'}" data-url="${el.url}">${el.name ? el.name : el.url}</div>`
        })
        content += `<div class="brxc-overlay__action-btn ${self.remoteTemplatesStates.layout === "1-col" ? 'primary' : 'secondary'} layout" data-balloon="1-col" data-balloon-pos="left"><span class="bricks-svg-wrapper"><i class="ti-layout-column3-alt"></i></span></div>`;
        content += `<div class="brxc-overlay__action-btn ${self.remoteTemplatesStates.layout === "2-col" ? 'primary' : 'secondary'} layout" data-balloon="2-col" data-balloon-pos="left"><span class="bricks-svg-wrapper"><i class="ti-layout-column2-alt"></i></span></div>`;
        content += '</div>';

        canvas.innerHTML = content;

        // Listeners
        const wrapper = canvas.querySelector('#brxcRemoteTemplateHeaderWrapper');
        wrapper.addEventListener('click', (e) => {
            // Change source
            self.remoteTemplatesStates.activeCat = "All";
            const item = e.target.closest('[data-url]');
            if(item) {
                self.remoteTemplatesStates.activeCat = "All";
                self.remoteTemplatesStates.active = sources.find(el => el.url === item.dataset.url);
                self.openRemoteTemplatesModal(false, true);
            };

            // Set cols
            const layoutBtn = e.target.closest('.brxc-overlay__action-btn.layout');
            if(layoutBtn){
                self.remoteTemplatesStates.layout = layoutBtn.dataset.balloon;
                self.remoteTemplateHeader();
                self.remoteTemplatePanel();
            }
        })
    },
    remoteTemplateCats: function(){
        const self = this;
        const canvas = document.querySelector('#brxcRemoteTemplatesUI__cat-canvas');
        if(!canvas) return;

        const activeData = self.remoteTemplatesStates.data.find(el => el && el.url === self.remoteTemplatesStates.active.url);
        if(!activeData) return;

        let count = 0;

        function isActive (cat) {
            if(cat === self.remoteTemplatesStates.activeCat) return true;
            return false;
        }

        let content = '<ul>';

        // All
        count = activeData.templates.length;
        content += `<li class="${self.remoteTemplatesStates.activeCat === "All" ? 'active' : ''}"${self.remoteTemplatesStates.activeCat === "All" ? ' data-active="true"' : ''} data-id="All" onClick="ADMINBRXC.remoteTemplatesFilterCat(event)"><input type="text" value="All" readonly/><span class="count">${count}</span></li>`
        
        // Categories
        for (const [key, value] of Object.entries(activeData.bundles)){
            const keys = Object.keys(activeData.bundles);
            count = Array.from(activeData.templates).filter(el => el && el.bundles.includes(key)).length;
            content += `<li class="${isActive(key) ? 'active' : ''}"${isActive(key) ? ' data-active="true"' : ''} data-id="${key}" onClick="ADMINBRXC.remoteTemplatesFilterCat(event)"><input type="text" value="${value}" readonly/><span class="count">${count}</span></li>`
        }
            
        content += '</ul>';
        canvas.innerHTML = content;
    },
    remoteTemplatesFilterCat: function(item){
        const self = this;
        self.remoteTemplatesStates.activeCat = item.target.dataset.id;
        self.renderTemplate();
    },
    remoteTemplatePanel: function (target = false) {
        const self = this;
    
        if (target) clearSearchInput(target);
    
        const canvas = document.querySelector('#brxcRemoteTemplatesUI__panel-canvas');
        if(!canvas) return;
        
        const activeData = getActiveData();
        if (!activeData) return;
    
        let templates = filterTemplates(activeData.templates);
    
        renderTemplates(canvas, templates);
    
        const wrapper = canvas.querySelector('#brxcRemoteTemplatesPanelWrapper');
        if (wrapper) initializeWrapperSortable(wrapper, activeData);
        
        function clearSearchInput(target) {
            target.parentElement.querySelector('input').value = '';
        }
    
        function getActiveData() {
            return self.remoteTemplatesStates.data.find(el => el && el.url === self.remoteTemplatesStates.active.url);
        }
    
        function filterTemplates(templates) {
            if (self.remoteTemplatesStates.activeCat !== "All") {
                templates = templates.filter(el => el.bundles.includes(self.remoteTemplatesStates.activeCat));
            }
            if (self.remoteTemplatesStates.search !== "") {
                templates = templates.filter(el => el.title.toLowerCase().includes(self.remoteTemplatesStates.search.toLowerCase()));
            }
            return templates;
        }

        function isMyTemplate(){
            return self.remoteTemplatesStates.active.url === bricksData.siteUrl;
        }
    
        function renderTemplates(canvas, templates) {
            const placeholderImg = self.globalSettings.placeholderImg;
            let content = '';
    
            if (templates.length > 0) {
                content = templates.map(template => {
                    const img = template.thumbnail || placeholderImg;
                    return `<div data-id="${template.id}">
                                <div class="brxc-template__img-wrapper">
                                    <img src="${img}" loading="lazy"/>
                                </div>
                                <div class="brxc-template-footer">
                                    <div class="brxc-template-footer__label">
                                        <span>${template.title}</span>
                                        ${!isMyTemplate() ? `<span class="bricks-svg-wrapper save-template" data-balloon="Save in My Templates" data-balloon-pos="top-right"><svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="bricks-svg"><path d="M21.75 23.25H2.25a1.5 1.5 0 0 1 -1.5 -1.5V7.243a3 3 0 0 1 0.879 -2.121l3.492 -3.493A3 3 0 0 1 7.243 0.75H21.75a1.5 1.5 0 0 1 1.5 1.5v19.5a1.5 1.5 0 0 1 -1.5 1.5Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path><path d="M9.75 12.75a3 3 0 1 0 6 0 3 3 0 1 0 -6 0Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path><path d="m12.75 20.25 6.75 0" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path><path d="M8.25 0.75v3a1.5 1.5 0 0 0 1.5 1.5h7.5a1.5 1.5 0 0 0 1.5 -1.5v-3" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path></svg></span>` : ''}
                                    </div>
                                </div>
                            </div>`;
                }).join('');
                content = `<div id="brxcRemoteTemplatesPanelWrapper" class="layout-${self.remoteTemplatesStates.layout}">${content}</div>`;
            } else {
                content = renderNoResults();
            }
    
            canvas.innerHTML = content;
        }
    
        function renderNoResults() {
            return `<div class="notification">
                        <span class="bricks-svg-wrapper" data-name="no-results">
                            <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="bricks-svg">
                                <path d="M0.75 12a11.25 11.25 0 1 0 22.5 0 11.25 11.25 0 1 0 -22.5 0Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"></path>
                                <path d="M15.665 18.75a0.76 0.76 0 0 0 0.744 -0.9 4.5 4.5 0 0 0 -8.818 0 0.759 0.759 0 0 0 0.744 0.9Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"></path>
                                <path d="m6.75 6.75 3 3 -3.75 0" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"></path>
                                <path d="m17.25 6.75 -3 3 3.75 0" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"></path>
                            </svg>
                        </span>
                        <div class="message"><p>No templates found.</p></div>
                    </div>`;
        }
    
        function initializeWrapperSortable(wrapper, activeData) {
            let targetSortable;
    
            new Sortable(wrapper, {
                group: {
                    name: 'shared',
                    put: false,
                    pull: 'clone',
                },
                selectedClass: "sortable-selected",
                handle: ".brxc-template__img-wrapper",
                animation: 150,
                helper: 'clone',
                filter: ".no-handle",
                onStart: () => initializeTargetSortable(),
                onEnd: (evt) => handleDragEnd(evt, activeData, targetSortable),
            });
    
            wrapper.addEventListener('click', (e) => handleTemplateClick(e, activeData));
        }
    
        function initializeTargetSortable() {
            const target = FRAMEBRXC.content.body.querySelector('main#brx-content');
            targetSortable = new Sortable(target, {
                group: 'shared',
                pull: 'clone',
                selectedClass: "sortable-selected",
                animation: 150,
                helper: 'clone',
                filter: ".no-handle",
            });
        }
    
        function handleDragEnd(evt, activeData, targetSortable) {
            const rootPosition = evt.newIndex;
            const items = FRAMEBRXC.content.body.querySelectorAll('main#brx-content > *');
            const newItem = items[rootPosition];
            if(!newItem) return console.log('Abort: no element found.')

            const obj = activeData.templates.find(el => el.id === parseInt(newItem.dataset.id));
            if(!obj) return console.log('Abort: no element found.')

            const objContent = obj.content ?? obj.footer ?? obj.header ?? null;
            if(objContent === null) return console.log('Abort: no content found.');

            const target = document.querySelector(`#brxcRemoteTemplatesPanelWrapper [data-id="${newItem.dataset.id}"]`) ?? false;
    
            newItem.remove();
            handleGlobalClasses(obj);

  
            self.convertTemplateData(
                target, 
                objContent, 
                (responseData) => {
                    self.insertTemplateData({
                      response: responseData.response,
                      position: rootPosition
                    });
                },
                rootPosition
            );

            refocusSearch();
    
            if (targetSortable) {
                targetSortable.destroy();
                targetSortable = null;
            }
        }
    
        function handleGlobalClasses(obj) {
            if (obj.hasOwnProperty('global_classes') && obj.global_classes.length > 0) {
                obj.global_classes.forEach(cls => {
                    if (!self.vueState.globalClasses.some(el => el.id === cls.id)) {
                        if(self.globalSettings.defaultElementFeatures.includes('logical-properties')){
                            if(!cls.hasOwnProperty('settings')) return;
                            cls.settings = self.convertToLogicalProperties(cls.settings);
                        }
                        self.vueState.globalClasses.push(cls);
                    }
                });
            }
        }
    
        function refocusSearch() {
            const search = document.querySelector('#brxcRemoteTemplatesUI__panel input[type=text]');
            if (search) {
                search.focus();
                search.setSelectionRange(0, search.value.length);
            }
        }
    
        function handleTemplateClick(e, activeData) {
            const target = e.target;

            const item = target.closest('[data-id]');
            if (!item) {
                console.log('[data-id] not found in Remote Template modal.');
                return;
            }
            const obj = activeData.templates.find(el => el.id === parseInt(item.dataset.id));

            if(target.classList.contains('save-template')){
                self.saveTemplateData(obj);
                refocusSearch();
            } else {
                const objContent = obj.content ?? obj.footer ?? obj.header ?? null;
                if(objContent === null) return console.log('Abort: no content found.')

                handleGlobalClasses(obj);
                self.convertTemplateData(
                    item, 
                    objContent, 
                    (responseData) => {
                        self.insertTemplateData({
                          response: responseData.response,
                          position: false
                        });
                    }
                );
                refocusSearch();
            }
        }
    },
    zoomOutStates: {
        scaleActive: true,
        previous: 1,
        active: false,
        defaultScaleMax: 0.4
    },
    zoomOut: function(forceOpen = false, forceClose = false){
        const self = this;
        const target = document.querySelector('#bricks-toolbar li.zoom-out')
        const icon = target?.querySelector('i');
        if(!self.zoomOutStates.active) self.zoomOutStates.previous = self.vueState.previewScaleMax;
        if(!self.zoomOutStates.active) self.zoomOutStates.scaleActive = self.vueState.previewScaleActive
        self.zoomOutStates.active = !self.zoomOutStates.active;
        if((self.zoomOutStates.active || forceOpen === true) && !forceClose){
            self.vueState.previewScaleActive = true;
            self.vueState.previewScaleMax = self.zoomOutStates.defaultScaleMax;

            if(FRAMEBRXC && FRAMEBRXC.content){
                FRAMEBRXC.content.body.classList.add('at-zoom-out');
                FRAMEBRXC.content.body.querySelectorAll('.brx-draggable').forEach(el => {
                    el.classList.remove('brx-draggable');
                })
            }

            // Icons
            if(target && icon){
                icon.className = 'bricks-svg ti-zoom-in';
                target.classList.add('enabled');
            }
        } else{
            self.vueState.previewScaleActive = self.zoomOutStates.scaleActive
            self.vueState.previewScaleMax = self.zoomOutStates.previous;

            if(FRAMEBRXC && FRAMEBRXC.content){
                FRAMEBRXC.content.body.classList.remove('at-zoom-out');
            }
            self.zoomOutStates.active = false;

            // Icons
            if(target && icon){
                icon.className = 'bricks-svg ti-zoom-out';
                target.classList.remove('enabled');
            }
        }
    },
    zoomOutRemoveDraggable: function(){
        const self = this;
        if(!self.zoomOutStates.active) return;
        FRAMEBRXC.content.body.querySelectorAll('.brx-draggable').forEach(el => {
            el.classList.remove('brx-draggable');
        })
    },
    colorControls: function(){
        const self = this;
        self.vue._context.components['control-color'].data = function() {
            return {
                changed: !1,
                showPopup: !1,
                storedColor: void 0,
                randomId: this.$_generateId(),
                colorMode: "raw",
                deleteColor: !1,
                editColorIndex: !1,
                inputSaturationStyles: null,
                inputLightnessStyles: null,
                inputAlphaStyles: null,
                inputRaw: null,
                inputHex: null,
                inputHue: 0,
                inputSaturation: 100,
                inputLightness: 50,
                inputRed: 0,
                inputGreen: 0,
                inputBlue: 0,
                inputAlpha: 1,
                placeholderRaw: "",
                activePaletteId: void 0,
                paletteAction: void 0,
                paletteName: "",
                colorName: "",
                colorsView: "list",
                importResults: [],
                colorsFromRaw: {},
                isPopulatingFromRaw: !1
            }
        }
    },
    // iconControlsSVG: function(){
    //     const self = this;
    //     if(!bricksData.loadData.userCan.uploadSvg) return;

    //     const svgFirst = Object.values(self.globalSettings.defaultElementFeatures).includes("icon-svg");


    //     if(!svgFirst) return;
    //     // Set default icon library to SVG on all elements
    //     for (const [key, element] of Object.entries(bricksData.elements)) {
    //         for (const [controlKey, control] of Object.entries(element.controls)) {
    //             if (control.type === "icon" && "default" in control) {
    //                 control.default = { library: "svg" };
    //             }
    //         }
    //     }


    //     Set value to the element when the component is mounted
    //     self.vue._context.components['control-icon'].watch.showPopup = function(e) {
    //         var t = this;
    //         const settings = t._.props.value
    //         if(e && (void 0 === settings || Object.keys(settings).length < 2)){
    //             this.library || (this.searchFor = ""),
    //             this.$emit("input", {
    //                 library: this.library,
    //             })
    //         }
    //         this.$nextTick((function() {
    //                 if (e) {
    //                     var n = !!t.$refs.icons && t.$refs.icons.querySelector(".active");
    //                     n && (t.$refs.icons.scrollTop = n.offsetTop)
    //                 }
    //             }
    //         ))
    //     }
        
    // },
    searchStructureStates: {
        search: '',
        cat: 'all',
    },
    setSearchStructure: function(){
        const self = this;
        if(!self.structurePanelStates.tweaks.includes('filterable-structure')){
            document.body.classList.remove('filterable-structure');
            document.querySelector('#brxcSearchStructureContainer')?.remove();
        } else {
            const structure = document.querySelector('#bricks-structure #brxcStructureTopContainer');
            if (!structure) return;
        
            document.body.classList.add('filterable-structure');
            const existing = structure.querySelector('#brxcSearchStructureContainer');
            if (existing) existing.remove();
        
            const options = [
                { value: 'all', label: 'All' },
                { value: 'element-name', label: 'Name' },
                { value: 'element-label', label: 'Label' },
                { value: 'html-tag', label: 'HTML Tag' },
                { value: 'global-class', label: 'Global Class' },
                { value: 'css-class', label: 'CSS Class' },
                { value: 'text-content', label: 'Text Content' },
                { value: 'css-id', label: 'CSS ID' },
                { value: 'bricks-id', label: 'Bricks ID' },
                { value: 'data-attribute', label: 'Data Attribute' }
            ];
        
            const search = document.createElement('DIV');
            search.id = 'brxcSearchStructureContainer';
            search.innerHTML = `
                <div id="brxcSearchStructureSelect" class="brxc-select-new max-width hidden">
                    <div id="brxcSearchStructureSelectWrapper" class="brxc-select-new__wrapper">
                        ${options.map(opt => 
                            `<div data-value="${opt.value}"${opt.value === 'all' ? ' class="active"' : ''}><span>${opt.label}</span></div>`
                        ).join('')}
                    </div>
                </div>
                <div id="brxcSearchStructureWrapper" class="brxc-overlay__search-box">
                    <input id="brxcSearchStructure" type="text" class="iso-search" name="dynamic-data-search" placeholder="Search...">
                    <div class="iso-search-icon">
                        <i class="bricks-svg ti-search"></i>
                    </div>
                    <div class="iso-reset" data-balloon="Reset" data-balloon-pos="left" onclick="this.previousElementSibling.previousElementSibling.value = '';ADMINBRXC.searchStructureStates.search = '';ADMINBRXC.searchStructure();">
                        <i class="bricks-svg fas fa-undo"></i>
                    </div>
                </div>`;
        
            structure.insertBefore(search, structure.firstChild);

            //Listeners

            const select = search.querySelector('.brxc-select-new');
            self.helpers.selectControl(select, (target) => {
                self.searchStructureStates.cat = target.dataset.value;
                self.searchStructure();
            })

            const input = search.querySelector('#brxcSearchStructure');
            if(input){
                input.addEventListener('input', (e) => {
                    self.searchStructureStates.search = e.target.value;
                    self.searchStructure();
                })
            }
        }
    },
    searchStructure: function(){
        const self = this;

        const structure = document.querySelector('#bricks-structure');
        if(!structure) return;

        const elements = structure.querySelectorAll('.element[data-id]');
        if(elements.length < 1) return;

        if(self.searchStructureStates.search === '') {
            //structure.removeAttribute('data-is-searching');
            document.body.classList.remove('searching-in-structure');
            elements.forEach(el => {el.removeAttribute('data-search-active')})
            return;
        }
        
        //structure.setAttribute('data-is-searching', 'true');
        document.body.classList.add('searching-in-structure');
        const searchTerm = self.searchStructureStates.search.toLowerCase();

        function matchCondition(option){
            return self.searchStructureStates.cat === "all" || self.searchStructureStates.cat === option;
        }
        function isVisible(id){
            const obj = self.helpers.getElementObject(id)
            const elementObj = self.vueGlobalProp.$_getElementConfig(obj.name);
            const nameMatch = matchCondition('element-name') && elementObj.label.toLowerCase().includes(searchTerm);
            const labelMatch = matchCondition('element-label') && (obj.label ? obj.label.toLowerCase().includes(searchTerm) : self.vueGlobalProp.$_getElementConfig(obj.name)?.label.toLowerCase().includes(searchTerm));
            const tagMatch = matchCondition('html-tag') && (obj.hasOwnProperty('settings') && obj.settings.tag ? obj.settings.tag.toLowerCase().includes(searchTerm) : self.vueGlobalProp.$_getElementConfig(obj.name)?.tag.toLowerCase().includes(searchTerm));
            const globalClassMatch = matchCondition('global-class') && obj.hasOwnProperty('settings') && obj.settings.hasOwnProperty('_cssGlobalClasses') ? obj.settings._cssGlobalClasses.some(el => self.vueGlobalProp.$_getGlobalClass(el)?.name.toLowerCase().includes(searchTerm)) : false;
            const cssClassMatch = matchCondition('css-class') && obj.hasOwnProperty('settings') && obj.settings.hasOwnProperty('_cssClasses') ? obj.settings._cssClasses.toLowerCase().includes(searchTerm) : false;
            const textMatch = matchCondition('text-content') && obj.hasOwnProperty('settings') && obj.settings.hasOwnProperty('text') ? obj.settings.text.toLowerCase().includes(searchTerm) : false;
            const idMatch = matchCondition('bricks-id') && obj.id.toLowerCase().includes(searchTerm);
            const cssIdMatch = matchCondition('css-id') && obj.hasOwnProperty('settings') && obj.settings.hasOwnProperty('_cssId') ? obj.settings._cssId.toLowerCase().includes(searchTerm) : false;
            const dataAttributeMatch = matchCondition('data-attribute') && obj.hasOwnProperty('settings') && obj.settings.hasOwnProperty('_attributes') ? JSON.stringify(obj.settings._attributes).toLowerCase().includes(searchTerm) : false;
            return nameMatch || labelMatch || tagMatch || globalClassMatch || cssClassMatch || textMatch || idMatch || cssIdMatch || dataAttributeMatch;

        }

        elements.forEach(el => {
            const elId = el.dataset.id;
            if(isVisible(elId)){
                el.setAttribute('data-search-active', 'true');
            } else {
                el.removeAttribute('data-search-active');
            }
        })
    },
    // delaySaveBtn: function(){
    //     const self = this;
    //     const btn = document.querySelector('#bricks-toolbar li.save');
    //     if(!btn) return;

    //     btn.addEventListener('click', (e) => {
    //         e.preventDefault();
    //         e.stopPropagation();
    //         setTimeout(() => {
    //             self.vueGlobalProp.$_savePost({
    //                 skipNotifications: !0
    //             })
    //         },350)
    //     }, true)
    // },

    removeControlGroups: function() {
        for (const [key, element] of Object.entries(bricksData.elements)) {
            if (!element.controlGroups) continue;
            
            const groupsToRemove = Object.keys(element.controlGroups).filter(group => {
                return !Object.values(element.controls).some(control => 
                    control.tab === "style" && control.group === group
                );
            });
    
            groupsToRemove.forEach(group => {
                delete bricksData.elements[key].controlGroups[group];
            });
        }
    },
    frameworkStates: {
        prefix: 'at-',
        viewOptions: false,
        excludedVariables: [],
        excludedColors: [],
        excludedClasses: [],
        scrollTop: 0,
    },
    getFrameworkValues: function(callback = false){
        const self = this;
        const dataObj = {
            action: 'get_framework_values_ajax_function',
            nonce: openai_ajax_req.nonce,
        };

        function safeParse(value) {
            try {
                return typeof value === "string" ? JSON.parse(value) : value;
            } catch (e) {
                console.log(value);
                console.error("JSON parse error:", e);
                return value; // Return the original value if parsing fails
            }
        }

        function getFrameWorkValuesByAjax(){
            return new Promise((resolve, reject) => {
                jQuery.ajax({
                    url: openai_ajax_req.ajax_url,
                    data: dataObj,
                    method: "POST",
                    success: function (response) {
                        const values = response['data']['values'];
                        window.brxcATFramework = {
                            values: {
                                variables: safeParse(values['variables']),
                                variables_cat: safeParse(values['variables_cat']),
                                global_classes: safeParse(values['global_classes']),
                                global_classes_cat: safeParse(values['global_classes_cat']),
                                global_colors: safeParse(values['global_colors']),
                                theme_settings: safeParse(values['theme_settings']),
                                theme_settings_new: safeParse(values['theme_settings_new']),
                                advanced_css: safeParse(values['advanced_css']),
                                recipes: safeParse(values['recipes']),
                            }
                        };
                        if(callback) callback();

                        // window.brxcATFramework.values.global_colors.forEach(palette => {
                        //     palette.colors.forEach(el => {
                        //         el.at_framework = true;
                        //         el.at_version = "1.0.0";
                        //     })
                        // })

                        // console.log(JSON.stringify(window.brxcATFramework.values.global_colors));

                        resolve(response);
                    },
                    error: function (data) {
                        reject('Something went wrong.');
                    }
                });
            });
        }
        getFrameWorkValuesByAjax()
    },
    setFrameworkOptions: function(){
        const self = this;
        self.getFrameworkValues(() => {
            self.mountFrameworkOptions();
        })
    },
    mountFrameworkSettingsContent: function(){
        const self = this;
        let content = '';
        content += `
            <div class="brxc-framework__settings-container">
                <div data-control="info">
                    <span>In this window, you can assign a custom prefix to all variables, global classes, and global colors imported by the AT Framework.
Before proceeding, please note that prefixes are only applied during the import process—changing the prefix afterward will not affect any existing variables, classes, or colors already present on your site.

Additionally, modifying the prefix may cause incompatibility with third-party content, such as premade design kits.
We strongly recommend keeping the default "at-" prefix unless you're sure about what you're doing.</span>
                </div>
                <div class="brxc-prefix-container">
                    <div class="brxc-label">Custom Prefix</div>
                    <input type="text" id="brxcFrameworkPrefix" value="${self.frameworkStates.prefix}">
                </div>
            <div>`
        return content;
    },
    mountFrameworkOptionsContent: function(){
        const self = this;
        let content = '';
        function generateRow(obj) {

            const hasUpdate = obj.categories?.some(cat => cat.installed && cat.upToDate === false);
            const hasDifference = obj.categories?.some(cat => cat.installed && cat.hasDifferences === true);
            return `<li>
                <div class="brxc-property">
                    <div class="label-wrapper">
                        <i class="bricks-svg icon ${obj.icon}"></i>
                        <span class="label">${obj.title}</span>
                        <div data-balloon="Open in manager" data-balloon-pos="right">
                            <i class="bricks-svg link fas fa-external-link-alt" onclick="${obj.open}"></i>
                        </div>
                    </div>
                    ${!obj.required ? `<span data-control="info">${obj.requiredText}</span>` : ''}
                    <span class="info">${obj.info}</span>
                    ${hasUpdate ? `<span class="update-info">Some options have <strong>updates available</strong>. Don’t worry — updating won’t affect any custom changes you've made on existing values, but will only import newly available values from the framework.</span>` : ''}
                    ${!hasUpdate && hasDifference ? `<span class="difference-info"><strong>Differences detected:</strong> ${obj.hasDiffMessage}</span>` : ''}
                    ${obj.hasOwnProperty('categories') ? `
                    <div class="brxc-categories" data-prop="${obj.property}">
                        ${obj.toggleAll ? `
                        <div data-id="all">
                            <div class="bricks-svg" data-balloon-pos="bottom">
                                <i class="fas fa-toggle-${obj.categories.map(cat => cat.installed).some(el => !el) ? 'off' : 'on'}"></i>
                            </div>
                            <span>Toggle All</span>
                        </div>` : ''}
                        ${obj.categories.map(cat => `
                            <div data-id="${cat.id}">
                                ${cat.installed && cat.upToDate === false
                                    ? `<div class="update-button" data-id="${cat.id}">Update</div>`
                                    : `<div class="bricks-svg" data-balloon-pos="bottom">
                                        <i class="fas fa-toggle-${cat.installed ? 'on' : 'off'}"></i>
                                    </div>`}
                                <span class="${cat.hasDifferences && cat.upToDate ? 'orange' : ''}">
                                    ${cat.label}
                                    ${cat.hasOwnProperty('count') ? `<span class="count">(${cat.count})</span>` : ''}
                                </span>
                            </div>
                        `).join('')}
                    </div>` : ''}
                </div>
            </li>`;
        }        

        content += `<ul>
                        <div data-control="info">
                            <p>Any newly added variable will ${self.frameworkStates.prefix === "" ? 'not contain any prefix' : `contain <strong>'${self.frameworkStates.prefix}'</strong> as prefix`}. You can change this behavior in the <a href="#" onClick="event.preventDefault();ADMINBRXC.frameworkStates.viewOptions = !ADMINBRXC.frameworkStates.viewOptions;ADMINBRXC.mountFrameworkOptions()">framework settings</span></a>.
                        </div>`;
        content += generateRow({
            title: 'Global CSS Variables',
            property: 'variables',
            icon: "fas fa-square-root-variable",
            open: "ADMINBRXC.openModal({target: false, id: '#brxcCSSVariableManagerOverlay', focus: '#brxcCSSVariableManagerOverlay input[type=text].class-filter', callback: () => {ADMINBRXC.cssVariablesStates.search = '';ADMINBRXC.cssVariablesStates.view = 'full';ADMINBRXC.setCSSVariableManager();}});",
            info: 'A collection of predefined CSS variables that ensure design consistency across your website. These variables control spacing, typography, grids, buttons, links, borders, and more.',
            required: bricksData.disableVariablesManager === "",
            requiredText: 'The CSS Variables Manager needs to be enabled within the Bricks Settings',
            categories: Array.from(new Map(brxcATFramework.values.variables.map(item => [item.category, {
                id: item.category,
                label: self.helpers.getGlobalVariableCategoryNameById(item.category, brxcATFramework.values.variables_cat),
                count: brxcATFramework.values.variables.filter(i => i.category === item.category).length,
                installed: self.vueState.globalVariables.some(el => el && el.at_framework === true && el.category === item.category),
                upToDate: self.helpers.getHighestFrameworkVersion(self.vueState.globalVariables.filter(el => el && el.at_framework === true && el.category === item.category) ?? []) === self.helpers.getHighestFrameworkVersion(brxcATFramework.values.variables.filter(i => i.category === item.category)),
                hasDifferences: !brxcATFramework.values.variables
                .filter(i => i.category === item.category)
                .every(variable => self.vueState.globalVariables.some(el => el.id === variable.id))
              }])).values()),
              hasDiffMessage: `The variables installed on the website differ from those in the framework. This may be due to a framework update or changes you've made to the imported values. <br>To restore the default framework variables, reimport them by toggling the "oranged" options off and on. Please note that this operation will remove any modifications you've made.`,
            toggleAll: true,
        });
        content += generateRow({
            title: 'Global Colors',
            property: 'global_colors',
            icon: "fas fa-palette",
            open: "ADMINBRXC.openModal({target: false, id: '#brxcColorManagerOverlay', callback: () => {ADMINBRXC.setColorManager();}});",
            info: 'A collection of globally managed color variables, including primary, secondary, accent, and neutral colors — along with their shades, tints, transparent versions, and dark mode variations.',
            importFn: 'ADMINBRXC.frameworkImportColors()',
            removeFn: "ADMINBRXC.frameworkRemove('global_colors')",
            required: self.globalSettings.themeSettingsTabs.includes('global-colors'),
            requiredText: 'The Global Colors need to be enabled within the AT Theme Settings > General',
            categories: brxcATFramework.values.global_colors.map(item => {return {
                id: item.id, 
                label: item.name, 
                count: item.colors.length,
                installed: self.vueState.colorPalette.some(el => el && el.id === item.id),
                upToDate: self.helpers.getHighestFrameworkVersion(self.vueState.colorPalette.find(el => el.id === item.id)?.colors ?? []) === self.helpers.getHighestFrameworkVersion(item.colors),
                hasDifferences: !item.colors.every(color => self.vueState.colorPalette.find(el => el.id === item.id)?.colors.some(installed => installed.id === color.id))
            }}),
            hasDiffMessage: `Some colors available from the framework are missing from those on your website. This may be due to a framework update or changes you've made to the imported AT Color Palettes. <br>To restore the default framework colors, reimport them by toggling the "oranged" options off and on. Please note that this operation will remove any modifications you've made.`,
            toggleAll: true,
        });
        content += generateRow({
            title: 'Global Classes',
            property: 'global_classes',
            icon: "ion-md-options",
            open: "ADMINBRXC.openClassManager('global');",
            info: 'A set of well-structured utility classes designed to streamline your styling process. These classes are particularly useful for styling buttons, applying different color sets, setting accessibility-focused styles, and even customizing elements like unordered lists.',
            required: bricksData.disableClassManager === "" && bricksData.disableGlobalClasses === "",
            requiredText: 'The Global Classes & the Global Class Manager need to be enabled within the Bricks Settings',
            categories: Array.from(new Map(brxcATFramework.values.global_classes.map(item => [item.category, {
                id: item.category,
                label: self.helpers.getGlobalVariableCategoryNameById(item.category, brxcATFramework.values.global_classes_cat),
                count: brxcATFramework.values.global_classes.filter(i => i.category === item.category).length,
                installed: self.vueState.globalClasses.filter(el => el?.category === item.category).some(el => el && el.settings?.at_framework === true),
                upToDate: self.helpers.getHighestFrameworkVersion(
                    self.vueState.globalClasses.filter(el => el && el.settings.at_framework === true && el.category === item.category) ?? []
                ) === self.helpers.getHighestFrameworkVersion(
                    brxcATFramework.values.global_classes.filter(i => i.category === item.category) ?? []
                ),
                hasDifferences: (() => {
                    const installed = self.vueState.globalClasses.filter(el => el?.category === item.category);
                    const available = brxcATFramework.values.global_classes.filter(i => i.category === item.category);
            
                    // Check if any _cssCustom value differs
                    return available.some(availableItem => {
                        const matchedInstalled = installed.find(installedItem => installedItem.id === availableItem.id);
                        return matchedInstalled && matchedInstalled.settings?._cssCustom !== availableItem.settings?._cssCustom;
                    });
                })()
            }])).values()),
            hasDiffMessage: `Some global class CSS from the framework differs from the version installed on your website. This may be due to a framework update or custom changes you've made to the AT global classes. <br>To restore the default framework global classes, reimport them by toggling the "oranged" options off and on. Please note that this operation will remove any modifications you've made.`,
            toggleAll: true,
        });
        content += generateRow({
            title: 'Theme Styles',
            property: 'theme_settings',
            icon: "fas fa-paint-roller",
            open: "ADMINBRXC.vueState.activePanel = 'theme-styles'",
            info: 'A preconfigured theme style that comes with AT’s variables and colors, allowing you to start designing immediately without manual setup.',
            required: true,
            requiredText: '',
            categories: brxcATFramework.values.theme_settings_new.map(item => {return {
                id: item.key, 
                label: item.label, 
                count: Object.keys(item.props).length,
                installed: Object.keys(self.vueState.themeStyles?.at_framework?.settings || {}).includes(item.key),
                upToDate: true,
                hasDifferences: new Set([...Object.keys(self.vueState.themeStyles?.at_framework?.settings?.[item.key] || {}), ...Object.keys(item.props || {})]).size !== Object.keys(self.vueState.themeStyles?.at_framework?.settings?.[item.key] || {}).length
            }}),
            hasDiffMessage: `Some Theme Style setting available from the framework is not installed on your site. This may be due to a framework update or changes you've made to the Theme Style. <br>To restore the default framework Theme Style, reimport them by toggling the "oranged" options off and on. Please note that this operation will remove any modifications you've made.`,
            toggleAll: true,
        });
        content += generateRow({
            title: 'Advanced CSS Stylesheet',
            property: 'advanced_css',
            icon: "fas fa-code",
            open: "ADMINBRXC.advancedCSSStates.view = 'stylesheet';ADMINBRXC.openModal({target: false, id: '#brxcCSSOverlay', focus: '#brxcCSSOverlay input.class-filter', callback: () => {ADMINBRXC.advancedCSSInit();}});",
            info: 'A dedicated stylesheet where all global CSS declarations are stored and applied site-wide.',
            required: true,
            requiredText: '',
            categories: Array.from(new Map(brxcATFramework.values.advanced_css
                .filter(el => el.id !== "at_framework_overrides")
                .map(item => [item.id, {
                id: item.category,
                label: item.label,
                count: 1,
                installed: brxcAdvancedCSSDefault.some(el => el?.id === item.id && !el.hasOwnProperty('removed')) || false,
                upToDate: !!brxcAdvancedCSSDefault.find(el => el?.id === "at_framework" && !el.hasOwnProperty('removed') && el?.at_version === brxcATFramework.values.advanced_css.find(el => el.id === "at_framework")?.at_version) || false,
                hasDifferences: brxcAdvancedCSSDefault.find(el => el?.id === "at_framework" && !el.hasOwnProperty('removed'))?.contentCss !== brxcATFramework.values.advanced_css.find(el => el.id === "at_framework")?.contentCss || false
              }])).values()),
            hasDiffMessage: `The CSS content in global.css installed on the website differs from the version in the framework. This may be due to a framework update or changes you've made to the global.css file. <br>To restore the default framework CSS code, reimport them by toggling the "oranged" options off and on. Please note that this operation will remove any modifications you've made.`,
            toggleAll: false,
        });
        content += generateRow({
            title: 'Advanced CSS Recipes',
            property: 'recipes',
            icon: "fas fa-burger",
            open: "ADMINBRXC.advancedCSSStates.view = 'recipes';ADMINBRXC.openModal({target: false, id: '#brxcCSSOverlay', focus: '#brxcCSSOverlay input.class-filter', callback: () => {ADMINBRXC.advancedCSSInit();}});",
            info: 'Predefined CSS snippets that help you apply complex styles and layouts to elements effortlessly—without the need for extensive manual coding.',
            required: true,
            requiredText: '',
            categories: Array.from(new Map(brxcATFramework.values.recipes.map(item => [item.category, {
                id: "at_recipes",
                label: "AT Recipes",
                count: brxcATFramework.values.recipes.length,
                installed: brxcAdvancedCSSDefault.some(el => el.typeLabel === "recipe" && el.category === "at framework"),
                upToDate: self.helpers.getHighestFrameworkVersion(brxcAdvancedCSSDefault.filter(el => el.typeLabel === "recipe" && el.category === "at framework") ?? []) === self.helpers.getHighestFrameworkVersion(brxcATFramework.values.recipes ?? []),
                hasDifferences: (() => {
                    const installedRecipes = brxcAdvancedCSSDefault.filter(el => el.typeLabel === "recipe" && el.category === "at framework" && !el.hasOwnProperty('removed'));
                    const allMatch = brxcATFramework.values.recipes.every(recipe => {
                        const matched = installedRecipes.find(el => el.id === recipe.id);
                        return matched && css_beautify(matched.contentCss, { indent_size: 2 }) === css_beautify(recipe.contentCss, { indent_size: 2 });
                    });
                    const allInstalled = brxcATFramework.values.recipes.every(recipe => 
                        installedRecipes.some(el => el.id === recipe.id)
                    );
                    return !allMatch || !allInstalled;
                })()
              }])).values()),
            hasDiffMessage: `Some recipes are missing, or the CSS of some installed recipes differs from the versions in the framework. This may be due to a framework update or changes you've made to the recipes. <br>To restore the default framework values, reimport them by toggling the "oranged" options off and on. Please note that this operation will remove any modifications you've made.`,
            toggleAll: false,
        });
        content += `</ul>`;
        return content;
    },
    mountFrameworkOptions: function(){
        const self = this;
        document.querySelector('#brxc-framework-options__wrapper')?.remove() // remove existing

        let wrapper = document.createElement('div');
        wrapper.setAttribute('id', 'brxc-framework-options__wrapper');
        let content = '';
        content += `<div class="header">
                        <span class="title">AT Framework</span>
                        <span class="bricks-svg-wrapper settings${self.frameworkStates.viewOptions ? ' active' : ''}" data-balloon="Settings" data-balloon-pos="bottom" onclick="ADMINBRXC.frameworkStates.viewOptions = !ADMINBRXC.frameworkStates.viewOptions;ADMINBRXC.mountFrameworkOptions()"><i class="fas fa-gear"></i></span>
                        <span class="bricks-svg-wrapper save" data-balloon="Save" data-balloon-pos="bottom" onclick="ADMINBRXC.saveFramework()"><i class="fas fa-floppy-disk"></i></span>
                        <span class="bricks-svg-wrapper close" data-balloon="Close" data-balloon-pos="bottom"><svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="bricks-svg"><path d="M400,145.49l-33.49,-33.49l-110.51,110.51l-110.51,-110.51l-33.49,33.49l110.51,110.51l-110.51,110.51l33.49,33.49l110.51,-110.51l110.51,110.51l33.49,-33.49l-110.51,-110.51l110.51,-110.51Z" fill="currentColor"></path></svg></span>
                    </div>`
        content += self.frameworkStates.viewOptions ? self.mountFrameworkSettingsContent() : self.mountFrameworkOptionsContent();
        wrapper.innerHTML = content
        const toolbar = document.querySelector('.brx-body.main')
        toolbar.appendChild(wrapper);
        wrapper.scrollTop = self.frameworkStates.scrollTop;

        // listeners
        wrapper = document.querySelector('#brxc-framework-options__wrapper');
        if(!wrapper) return;

        // Custom Prefix
        const prefixInput = wrapper.querySelector('#brxcFrameworkPrefix');
        if(prefixInput){
            prefixInput.addEventListener('input', (e) => {
                self.frameworkStates.prefix = e.target.value;
            })
        }

        const categories = wrapper.querySelectorAll('.brxc-categories');
        categories.forEach(category => {
            category.addEventListener('click', (e) => {
                const parent = e.target.closest('[data-id]');
                if(e.target.classList.contains('update-button')){
                    self.importFrameworkSetting({
                        prop: category.dataset.prop,
                        key: parent.dataset.id
                    }, true);
                    return;
                }
                if(e.target.classList.contains('fa-toggle-off')) {
                    // ToggleAll
                    self.importFrameworkSetting({
                        prop: category.dataset.prop,
                        key: parent.dataset.id
                    });
                } else if(e.target.classList.contains('fa-toggle-on')){
                        e.target.classList.add('fa-check')
                        e.target.classList.remove('fa-toggle-on')
                        e.target.parentElement.setAttribute('data-balloon', 'Confirm?');
                    setTimeout(() => {
                        e.target.classList.remove('fa-check')
                        e.target.classList.add('fa-toggle-on')
                        e.target.parentElement.removeAttribute('data-balloon')
                    }, 2000)
                } else if(e.target.classList.contains('fa-check')){
                    self.removeFrameworkSetting({
                        prop: category.dataset.prop,
                        key: parent.dataset.id
                    })
                }
            })
        })

        // Close popup
        const close = wrapper?.querySelector('.close');
        close?.addEventListener('click', () => {
            wrapper?.remove();
        })
    },
    importFrameworkSetting: function(settings, isUpdating = false){
        const self = this;
        switch(settings.prop){
            case "variables":
                self.frameworkImportVariables(settings.key)
                break;
            case "global_classes":
                self.frameworkImportClasses(settings.key)
                break;
            case "global_colors":
                self.frameworkImportColors(settings.key)
                break;
            case "theme_settings":
                self.frameworkImportTheme(settings.key, isUpdating);
                break;
            case "advanced_css":
                self.frameworkImportAdvancedCSS(isUpdating)
                break;
            case "recipes":
                self.frameworkImportRecipes();
                break;
        }
    },
    frameworkImportVariables: function(cat){
        const self = this;
        
        self.generateClampSettings(false);

        const categoriesMap = new Map(self.vueState.globalVariablesCategories.map(cat => [cat.id, cat]));
        const variablesMap = new Map(self.vueState.globalVariables.map(variable => [variable.id, variable]));

        let arr = brxcATFramework.values.variables
        if(cat !== "all") arr = arr.filter(el => el.category === cat);

        const overrideKeys = ['at_version'];
        
        arr.forEach(el => {

            // Add missing categories
            if (!categoriesMap.has(el.category)) {
                const newCategory = brxcATFramework.values.variables_cat.find(cat => cat.id === el.category);
                if (newCategory) {
                    self.vueState.globalVariablesCategories.push(newCategory);
                    categoriesMap.set(newCategory.id, newCategory); // Update map
                }
            }

            // Add missing variables
            if (!variablesMap.has(el.id)) {
                if(self.frameworkStates.prefix !== "at-") {
                    el.name = el.name.replace('at-', self.frameworkStates.prefix);
                    el.value = el.name.replaceAll('var(--at-', `'var(--${self.frameworkStates.prefix}`);
                    if(el.hasOwnProperty('label')){
                        el.label = el.label.replace('at-', self.frameworkStates.prefix)
                    }
                }
                self.vueState.globalVariables.push(el);
                variablesMap.set(el.id, el); // Update map
            // Add missing properties to existing variables
            } else {
                const existingVar = variablesMap.get(el.id);
                Object.keys(el).forEach(key => {
                    if (overrideKeys.includes(key)) {
                        existingVar[key] = el[key]; // Override specific keys
                    } else if (!(key in existingVar)) {
                        existingVar[key] = el[key]; // Add missing properties
                    }
                });
            }
        });
        
        setTimeout(() => {
            self.frameworkStates.scrollTop = document.querySelector('#brxc-framework-options__wrapper')?.scrollTop;
            self.mountFrameworkOptions();
        },10)
    },
    frameworkImportClasses: function(cat){
        const self = this;
        const categoriesMap = new Map(self.vueState.globalClassesCategories.map(cat => [cat.id, cat]));
        const classesMap = new Map(self.vueState.globalClasses.map(variable => [variable.id, variable]));
        
        let arr = brxcATFramework.values.global_classes;
        if(cat !== "all") arr = arr.filter(el => el.category === cat);
        
        arr.forEach(el => {

            // Add missing categories
            if (!categoriesMap.has(el.category)) {
                const newCategory = brxcATFramework.values.global_classes_cat.find(cat => cat.id === el.category);
                if (newCategory) {
                    self.vueState.globalClassesCategories.push(newCategory);
                    categoriesMap.set(newCategory.id, newCategory); // Update map
                }
            }

            // Add missing class
            if (!classesMap.has(el.id)) {
                if(self.frameworkStates.prefix !== "at-") {
                    el.name = el.name.replace('at-', self.frameworkStates.prefix);
                    if(el.settings.hasOwnProperty('_cssCustom')){
                        el.settings._cssCustom = el.settings._cssCustom.replaceAll('var(--at-', `var(--${self.frameworkStates.prefix}`)
                    }
                }
                self.vueState.globalClasses.push(el);
                if(!self.vueState.globalClassesLocked.includes(el.id)) self.vueState.globalClassesLocked.push(el.id)
                classesMap.set(el.id, el); // Update map
            }
        });

        setTimeout(() => {
            self.frameworkStates.scrollTop = document.querySelector('#brxc-framework-options__wrapper')?.scrollTop;
            self.mountFrameworkOptions();
        },10)
    },
    frameworkImportColors: function(cat){
        const self = this;
        let arr = brxcATFramework.values.global_colors;
        if(cat !== "all") arr = arr.filter(el => el.id === cat)
        
        arr.forEach(newPalette => {

            const existingPalette = self.vueState.colorPalette.find(p => p.id === newPalette.id);
            newPalette.prefix = self.frameworkStates.prefix;

            if (!existingPalette) {
                // Add entire new palette if not present
                self.vueState.colorPalette.push({ ...newPalette });
            } else {
                // Merge missing colors if palette exists
                if (!Array.isArray(existingPalette.colors)) {
                    existingPalette.colors = [];
                }

                const newColors = newPalette.colors?.filter(
                    newColor => !existingPalette.colors.some(existingColor => existingColor.id === newColor.id)
                ) || [];

                if (newColors.length > 0) {
                    existingPalette.colors.push(...newColors);
                }
            }
        });

        self.colorStates.activePalette = "at_framework_palette";

        setTimeout(() => {
            self.generateColorCSS();
            self.generateBuilderCSS();
            self.frameworkStates.scrollTop = document.querySelector('#brxc-framework-options__wrapper')?.scrollTop;
            self.mountFrameworkOptions();
        },10)
    },
    frameworkImportTheme: function(key){
        const self = this;
        let hasChanges = false;
        let arr = brxcATFramework.values.theme_settings_new;
        if(key !== "all") arr = arr.filter(el => el.key === key)

        // Create object if it's missing
        if (!self.vueState.themeStyles.hasOwnProperty('at_framework') ) {
            if(self.vueState.themeStyles.length === 0) {
                self.vueState.themeStyles = {};
            }
            self.vueState.themeStyles.at_framework = {};
            self.vueState.themeStyles.at_framework.label = "AT Framework";
            self.vueState.themeStyles.at_framework.settings = {};
            self.vueState.themeStyles.at_framework.settings._custom = true;
            self.vueState.themeStyles.at_framework.settings.conditions = {}
            self.vueState.themeStyles.at_framework.settings.conditions.conditions = [
                {
                    "id": "nqprte",
                    "main": "any"
                }
            ];
            hasChanges = true;
        }
        
        arr.forEach(newSetting => {
            self.vueState.themeStyles.at_framework.settings[newSetting.key] = JSON.parse(JSON.stringify(newSetting.props));
        });
        if(hasChanges) self.vueState.themeStyleActive = "at_framework";
        self.helpers.saveChanges('themeStyles');
        
        setTimeout(() => {
            self.frameworkStates.scrollTop = document.querySelector('#brxc-framework-options__wrapper')?.scrollTop;
            self.mountFrameworkOptions();
            self.vueState.rerenderControls = Date.now()
        },10)
    },
    frameworkImportAdvancedCSS: function(isUpdating){
        const self = this;

        // Global
        const existingGlobal = brxcAdvancedCSSDefault.find(el => el.id === "at_framework");
        if(existingGlobal){
            const index = brxcAdvancedCSSDefault.indexOf(existingGlobal);
            brxcAdvancedCSSDefault.splice(index, 1);
        };

        const global = brxcATFramework.values.advanced_css.find(el => el.id === "at_framework");
        if(self.frameworkStates.prefix !== "at-") global.contentCss = global.contentCss.replaceAll('--at-', `--${self.frameworkStates.prefix}`).replaceAll('.at-', `.${self.frameworkStates.prefix}`);
        delete global['removed'];
        global['hasChanged'] = true;
        if(isUpdating) global.at_version = brxcATFramework.values.advanced_css.find(el => el.id === "at_framework")?.at_version

        brxcAdvancedCSSDefault.push(global);

        // Overrides
        const existingOverrides = brxcAdvancedCSSDefault.find(el => el.id === "at_framework_overrides");
        if(!existingOverrides){
            const override = brxcATFramework.values.advanced_css.find(el => el.id === "at_framework_overrides");
            delete override['removed'];
            override['hasChanged'] = true;

            brxcAdvancedCSSDefault.push(override);
        };

        setTimeout(() => {
            self.frameworkStates.scrollTop = document.querySelector('#brxc-framework-options__wrapper')?.scrollTop;
            self.mountFrameworkOptions();
        },10)
    },
    frameworkImportRecipes: function(){
        const self = this;
        const recipesMap = new Map(brxcAdvancedCSSDefault.map(item => [item.id, item]));

        brxcATFramework.values.recipes.forEach(el => {
            // Add missing recipes
            if (!recipesMap.has(el.id)) {
                if(self.frameworkStates.prefix !== "at-") el.contentCss = el.contentCss.replaceAll('--at-', `--${self.frameworkStates.prefix}`).replaceAll('.at-', `.${self.frameworkStates.prefix}`);
                brxcAdvancedCSSDefault.push(el);
                recipesMap.set(el.id, el); // Update map
            }
        });

        setTimeout(() => {
            self.frameworkStates.scrollTop = document.querySelector('#brxc-framework-options__wrapper')?.scrollTop;
            self.mountFrameworkOptions();
        },10)
    },
    removeFrameworkSetting: function(settings){
        const self = this;
        let usedCategoryIds;
        switch(settings.prop){
            case "variables":
                // Variables
                self.vueState.globalVariables = self.vueState.globalVariables.filter(el => {
                    return settings.key === "all"
                        ? el.at_framework !== true
                        : !(el.at_framework === true && el.category === settings.key);
                });
                
                
                // Categories
                usedCategoryIds = new Set(self.vueState.globalVariables.map(el => el.category));
                self.vueState.globalVariablesCategories = self.vueState.globalVariablesCategories.filter(
                    el => !el.hasOwnProperty('at_framework') || usedCategoryIds.has(el.id)
                );
            break;

            case "global_classes":
                // Classes
                let usedIds = self.vueState.globalClasses.
                    filter(el => {
                        return settings.key === "all"
                            ? el?.settings?.at_framework === true
                            : el?.settings?.at_framework === true && el?.category === settings.key;
                    })
                    .map(el => el.id);

                self.vueState.globalClasses = self.vueState.globalClasses.filter(el => !usedIds.includes(el?.id));
                self.vueState.globalClassesLocked = self.vueState.globalClassesLocked.filter(el => !usedIds.includes(el));

                
                // Categories
                usedCategoryIds = new Set(self.vueState.globalClasses.map(el => el.category));
                self.vueState.globalClassesCategories = self.vueState.globalClassesCategories.filter(
                    el => !el.hasOwnProperty('at_framework') || usedCategoryIds.has(el.id)
                );
            break;
            case "global_colors":   
                let palettes = self.vueState.colorPalette.filter(el => el.hasOwnProperty('at_framework') && el.at_framework === true)
                if(settings.key !== "all") palettes = palettes.filter(el => el.id === settings.key);
                palettes.forEach(palette => {
                    palette.colors = (Array.isArray(palette.colors) ? palette.colors : []).filter(el => !el.hasOwnProperty('at_framework'));
                    if(palette.colors.length === 0){
                        const paletteIndex = self.vueState.colorPalette.indexOf(palette);
                        self.vueState.colorPalette.splice(paletteIndex, 1);
                    }

                })

                const firstPalette = self.vueState.colorPalette[0] || false;
                self.colorStates.activePalette = firstPalette ? firstPalette.id : '';
                

                self.generateColorCSS();
                self.generateBuilderCSS();
            break;

            case "theme_settings":   
                const themeSettings = brxcATFramework.values.theme_settings_new;
                let themeKeys = themeSettings.map(el => el.key);
                if(settings.key !== "all") themeKeys = themeKeys.filter(el => el === settings.key);
                themeKeys.forEach(key => {
                    if(self.vueState.themeStyles.at_framework.settings.hasOwnProperty(key)){
                        const atSetting = themeSettings.find(el => el.key === key);
                        const atKeys = Object.keys(atSetting.props);
                        atKeys.forEach(atKey => {
                            delete self.vueState.themeStyles.at_framework.settings[key][atKey]
                        })
                        if(Object.keys(self.vueState.themeStyles.at_framework.settings[key]).length < 1){
                            delete self.vueState.themeStyles.at_framework.settings[key]
                        }
                    }
                })
            break;

            case "advanced_css":   
                const styleSheet = brxcAdvancedCSSDefault.find(el => el.id == 'at_framework');
                    if(styleSheet) {
                        styleSheet['removed'] = "true";
                    }
            break;
            
            case "recipes":   
                brxcAdvancedCSSDefault = brxcAdvancedCSSDefault.filter(el => el.typeLabel !== "recipe" || !el.hasOwnProperty('at_framework'));
            break;
            
        }

        setTimeout(() => {
            self.frameworkStates.scrollTop = document.querySelector('#brxc-framework-options__wrapper')?.scrollTop;
            self.mountFrameworkOptions();
            self.vueState.rerenderControls = Date.now()
        },10)
    },
    saveFramework: function(){
        const self = this;
        self.regenerateAdvancedCSS(false);
    },
    generateClampSettings: function(showMessage = true){
        const self = this;
        const category = {
            id: "at_clamp-settings",
            name: "AT - Clamp Settings",
            description: "The following variables are used in all clamp() functions generated by Advanced Themer across your website. Avoid removing them completely, as doing so may break your frontend layout."
        };
        const variables = [
            {
                id: "at_min-viewport",
                name: "min-viewport",
                label: "Minimum Viewport",
                value: "360",
                category: "at_clamp-settings"
            },
            {
                id: "at_max-viewport",
                name: "max-viewport",
                label: "Maximum Viewport",
                value: "1600",
                category: "at_clamp-settings"
            },
            {
                id: "at_base-font",
                name: "base-font",
                label: "Base Font",
                value: "10",
                category: "at_clamp-settings"
            },
            {
                id: "at_clamp-unit",
                name: "clamp-unit",
                label: "Clamp Unit",
                value: "1vw",
                category: "at_clamp-settings"
            }
        ];

        if(!self.vueState.globalVariablesCategories.find(el => el.id === category.id)){
            self.vueState.globalVariablesCategories.push(category);
        }
        let count = 0;
        variables.forEach(variable => {
            const existingVar = self.vueState.globalVariables.find(el => el.id === variable.id);
            if(!existingVar){
                self.vueState.globalVariables.push(variable);
                count++;
            } else {
                Object.keys(variable).forEach(key => {
                    if (!(key in existingVar)) {
                        existingVar[key] = variable[key];
                    }
                });
            }
        })
        if(showMessage){
            count === 0 ? self.vueGlobalProp.$_showMessage('ABORT: CLAMP VARIABLES ALREADY EXIST!') : self.vueGlobalProp.$_showMessage(`${count} CLAMP SETTINGS CREATED SUCCESSFULLY!`)
        }

        self.setCSSVariableManager();
    },
    stickyCssStates: {
        active: false,
        activeId: false,
        activeBreakpoint: false,
        activePseudo: false,
        activePanelGroup: false,
        computedValues: false,
        forceMount: false,
        forcedSwitch: false,
    },
    setStickyCSS: function(){
        const self = this;
        const panel = document.querySelector('#brxcStructureBottomContainer');
        if(!panel) return;

        const existing = document.querySelector('#brxc-sticky-css');
        if(existing) return;

        const stickyCss = document.createElement('DIV');
        stickyCss.id = 'brxc-sticky-css';

        // LocalStorage
        const storedState = self.helpers.getLocalStorage();
        if(storedState.stickyCssHeight){
            stickyCss.style.height = `${storedState.stickyCssHeight}px`;
        }
        stickyCss.innerHTML = `
        <div id="brxc-sticky-css-resizable"></div>
        <div data-controlkey="_cssStickyCSS">
            <div class="control control-textarea">
                <div class="control-inner has-label">
                    <label title="Sticky CSS" for="_cssStickyCSS" data-balloon-break="">
                        <div class="brxc-sticky-css__control-wrappper">
                            <div data-balloon="Selector" data-balloon-pos="top"><div id="brxcStickyCSSSelect" class="brxc-select-new max-width hidden"><div id="brxcStickyCSSSelectWrapper" class="brxc-select-new__wrapper"></div></div></div>
                            <div class="plain-classes-icon" data-balloon="Plain Classes" data-balloon-pos="top" onclick="event.preventDefault();event.stopPropagation();ADMINBRXC.openPlainClassesModal(event, &quot;#brxcPlainClassesOverlay&quot;)"><span class="symbol counter">P</span></div>
                        </div>
                    </label>
                    <div data-control="textarea" class="" type="textarea">
                        <textarea class="" rows="5" placeholder="Write your CSS here." spellcheck="false" data-mounted="true" style="display: none;"></textarea>
                    </div>
                </div>
            </div>
        </div>`

        panel.appendChild(stickyCss);

        // Resize
        const resizeBar = document.querySelector('#brxc-sticky-css-resizable');
        const container = stickyCss

        let isResizing = false;
        let startY, startHeight;

        resizeBar.addEventListener('mousedown', (event) => {
            isResizing = true;
            startY = event.clientY;
            startHeight = container.offsetHeight;
            document.body.style.userSelect = 'none'; 
        });
        
        document.addEventListener('mousemove', (event) => {
            if (!isResizing) return;
            
            const deltaY = startY - event.clientY; 
            const newHeight = Math.max(200, startHeight + deltaY);
        
            container.style.height = `${newHeight}px`;

            // LocalStorage
            self.helpers.setLocalStorage('stickyCssHeight', newHeight )
        });
        
        document.addEventListener('mouseup', () => {
            isResizing = false;
            document.body.style.userSelect = '';
        });

        // Select
        const select = document.querySelector('#brxc-sticky-css .brxc-select-new');
        self.helpers.selectControl(select, (target) => {
            const closest = target.closest('[data-value]')
            if(closest && closest.dataset.value){
                if (closest.getAttribute('data-id-level') === "true") {
                    self.vueState.activeClass = {};
                } else {
                    self.vueState.activeClass = self.vueGlobalProp.$_getGlobalClass(closest.dataset.value);
                }
                self.vueState.rerenderControls = Date.now();
            }
        })

    },
    setStickyCSSEditor: function(observer = false){
        const self = this;
        const canvas = document.querySelector('#brxc-sticky-css');
        if(!canvas) return;

        const existing = canvas.querySelector('.CodeMirror');
        if(existing) existing.remove();
        
        const textAreaTarget = canvas.querySelector('textarea');
        const options = self.codeMirrorOptions(false);
        options.mode = self.globalSettings.superPowerCSSEnableSass === "1" ? 'text/x-scss' : 'css';
        options.readOnly = false;
        options.styleActiveLine = true;
        options.autoCloseBrackets = true;
        options.matchBrackets = true;
        options.selfContain = true;
        options.autofocus = false
        options.search = { bottom: false };
        options.profile = "xhtml";
        const MyCM = CodeMirror.fromTextArea(textAreaTarget, options);
        MyCM.getWrapperElement().setAttribute("data-type", "at");
        emmetCodeMirror(MyCM);
        MyCM.setOption('gutters', []);
        // Expand
        setTimeout(() => {
            if(bricksData.disablePanelAutoExpand === "" && self.vueState.activePanelGroup === "_css") self.vueState.isPanelExpanded = true;
            self.addIconsToStickyCSS('[data-controlkey=_cssStickyCSS]');
            self.addMessageToSuperpowerCSS();
            self.populateCSSVariables();
            if(!self.stickyCssStates.computedValues) self.addListenersToSuperPowerCSS(MyCM, `[data-controlkey=_cssStickyCSS]`);
            MyCM.scrollIntoView({ line: MyCM.lineCount() - 1, ch: 0 });
            MyCM.scrollIntoView({ line: 0, ch: 0 });
            if(observer) observer.disconnect();
            self.superPowerStates.AIbackup = '';
            self.superPowerStates.editAI = false;
            self.superPowerStates.AIprompt = '';
            self.superPowerStates.searchBookmark = '';
            //self.superPowerCSSAIMount(textAreaTarget, MyCM, 'css');
            
        },120);

        setTimeout(() => {
            MyCM.refresh();
        },300)
    },
    setStickyCSSObject: function(){
        const self = this;
        const existing = document.querySelector('#brxc-sticky-css');

        self.stickyCssStates.forcedSwitch = false;

        if(!self.stickyCssStates.active || (!self.stickyCssStates.forceMount && (!self.builderStates.isElementActive || self.vueState.activePanel !== "element")) ) {
            self.stickyCssStates.activeId = false
            self.stickyCssStates.activeBreakpoint = false
            self.stickyCssStates.activePseudo = false
            self.stickyCssStates.activePanelGroup = false
            document.body.classList.remove('at-has-sticky-css');
            existing?.remove();
            const msg = document.querySelector('#brxcStickyCSSSwitchMsg');
            msg?.remove();
            return;
        }

        const isCssTab = self.vueState.activePanelGroup === "_css" && self.vueState.activePanelTab === "style"

        if(isCssTab) {
            self.stickyCssStates.computedValues = true;
            self.stickyCssStates.forcedSwitch = true;
        }

        const sameId = self.stickyCssStates.activeId === self.builderStates.activeObject?.id
        const sameBreakpoint = self.stickyCssStates.activeBreakpoint === self.vueState.breakpointActive
        const samePseudo = self.stickyCssStates.activePseudo === self.vueState.pseudoClassActive
        const samePanel = self.stickyCssStates.activePanelGroup === self.vueState.activePanelGroup
        const noChanges = sameId && sameBreakpoint && samePseudo && samePanel;

        if(self.stickyCssStates.forceMount || !noChanges){
            function mountEditor(){
                self.setStickyCSS()
                self.setStickyCSSEditor();
                self.stickyCSSUpdateSelectors();
                const MyCM = document.querySelector('#brxc-sticky-css .CodeMirror').CodeMirror;
                self.updateSuperPowerCSS(MyCM, self.stickyCssStates.computedValues)
                self.stickyCSSHandleSwitchMsg();
                document.body.classList.add('at-has-sticky-css');
            }

            if(self.stickyCssStates.timeoutMount === true){
                setTimeout(() => {
                    mountEditor();
                },100)
            } else {
                mountEditor();
            }
        }

        self.stickyCssStates.activeId = self.builderStates.activeObject?.id
        self.stickyCssStates.activeBreakpoint = self.vueState.breakpointActive
        self.stickyCssStates.activePseudo = self.vueState.pseudoClassActive
        self.stickyCssStates.activePanelGroup = self.vueState.activePanelGroup
        self.stickyCssStates.forceMount = false;
        self.stickyCssStates.timeoutMount = false;
    },
    stickyCSSHandleSwitchMsg: function(){
        const self = this;
        const container = document.querySelector('#brxcStructureBottomContainer')
        if(!container) return;

        const existing = document.querySelector('#brxcStickyCSSSwitchMsg');
        const showMsg = self.stickyCssStates.forcedSwitch && self.vueState.activePanelGroup == "_css" && self.vueState.activePanelTab === "style";
        if(showMsg){
            if(existing) return;
            const msg = document.createElement('DIV');
            msg.id = "brxcStickyCSSSwitchMsg";
            msg.innerHTML = `<div data-control="info">CSS Tab detected! Mode switched to "Computed CSS".</div>`
            //container.insertBefore(msg, container.children[1]);
            container.appendChild(msg)
        } else {
            if(existing) existing.remove();
        }
    },
    stickyCSSUpdateSelectors: function(){
        const self = this;
        const canvas = document.querySelector('#brxc-sticky-css');
        if (!canvas) return;

        const select = canvas.querySelector('#brxcStickyCSSSelectWrapper');
        if (!select) return;

        const activeId = self.builderStates.activeObject?.id;
        let content = `<div class="active"><span>${self.helpers.getFinalSelector() ?? ''}</span></div>`;

        if (self.vueState.activeElement?.settings?._cssGlobalClasses?.length > 0) {
            content += self.vueState.activeElement.settings._cssGlobalClasses
                .map(el => self.vueGlobalProp.$_getGlobalClass(el))
                .filter(clsObj => clsObj && clsObj.id !== activeId)
                .map(clsObj => `<div data-value="${clsObj.id}"><span>.${clsObj.name}</span></div>`)
                .join('');
        }
        if(self.builderStates.activeElement.id !== activeId){
            const elementObj = self.builderStates.activeElement;
            const cssId = elementObj.settings.hasOwnProperty('_cssId') ? `#${elementObj.settings._cssId}` : `#brxe-${elementObj.id}`
            content += `<div data-id-level="true" data-value="${self.builderStates.activeElement.id}"><span>${cssId}</span></div>`;
        }

        // Ensure select updates correctly
        select.innerHTML = content;
    },
    toggleStickyCSS: function(){
    const self = this;

        self.stickyCssStates.active = !self.stickyCssStates.active;

        // Update localStorage
        self.helpers.setLocalStorage('stickyCss', self.stickyCssStates.active )

        self.setStickyCSSObject();

        // Update UI
        self.setHeaderStructurePanel()
    },
    updateStickyCSS: function(){
        const self = this;
        const MyCM = document.querySelector('#bricks-structure [data-controlkey="_cssStickyCSS"] .CodeMirror')?.CodeMirror;
        if(!MyCM) return;

        MyCM.setValue(self.helpers.currentObjGeneratedCSS());

    },
    tagBtnStates:{
        active: null
    },
    setTagBtnListener: function(e) {
            const self = this;
            const isButton = e.target.classList.contains('brxc-tag-btn');
            const isTagInput = e.target.classList.contains('brxc-custom-tag-input');
            const isOptionInput = e.target.classList.contains('brxc-custom-tag-option');

            if(!isButton && !isTagInput && !isOptionInput) {
                return;
            }

            e.preventDefault();
            e.stopPropagation();


            if(isTagInput){
                return;
            }

            const clickedElement = e.target.closest('.element');
            const activeElementId = clickedElement?.dataset.id;

            if(isOptionInput){
                self.setTagInStructurePanel(activeElementId, e.target.dataset.value);
                return
            }

            // Remove existing dropdown for a new click
            const existingDropdown = document.querySelector('.brxc-tag-btn + ul.dropdown');
            existingDropdown?.remove();
    
            // Remove existing dropdown if the same element is clicked again
            if (activeElementId === self.tagBtnStates.active && !isOptionInput) {
                self.tagBtnStates.active = null;
                return;
            }
    
            // Set active element and show dropdown
            self.tagBtnStates.active = activeElementId;
            self.appendTagBtnDropDown(e.target);

    },
    appendTagBtnDropDown: function (target) {
        const self = this;
        const structure = document.querySelector('#bricks-structure .bricks-structure-list');
        const wrapper = target.closest(".brxc-tag-btn-wrapper");
        const element = target.closest(".element");
    
        if (!structure || !wrapper || !element) return;
    
        // Remove existing dropdown on the same element
        const existingBtn = element.querySelector("ul.dropdown");
        if (existingBtn) {
            return existingBtn.remove();
        }
    
        // Remove all active dropdowns
        structure.querySelectorAll('.tag-dropdown-active').forEach(el => {
            el.classList.remove('tag-dropdown-active');
            const existingDropdown = el.querySelector('ul.dropdown');
            if (existingDropdown) existingDropdown.remove();
        });
    
        // Get element data
        const id = element.dataset.id;
        const obj = self.helpers.getElementObject(id);
        const tag = self.helpers.getElementTag(obj);
        if (!tag) return;
    
        const elementConfig = bricksData.elements[obj.name]?.controls || {};
        const optionType = elementConfig.tag?.type || false;
        let options = elementConfig.tag?.options || false;
    
        // Create dropdown container
        const ul = document.createElement("ul");
        ul.className = 'dropdown';
    
        // Build options
        if (optionType === "select" && options && typeof options === "object") {
            Object.entries(options).forEach(([value, label], index) => {
                if (index === 0) {
                    const li = document.createElement('li');
                    li.className = 'no-hover';
                    li.dataset.id = id;
                    li.innerHTML = `<input type="text" class="brxc-custom-tag-input" placeholder="Type an HTML tag and hit ENTER" value="" onkeydown="ADMINBRXC.setCustomTagInStructurePanel(this, event, 'select')"/>`;
                    ul.appendChild(li);
                }
                const li = document.createElement('li');
                li.className = 'brxc-custom-tag-option hover';
                li.dataset.id = id;
                li.setAttribute('data-value', value);
                li.textContent = label;
                ul.appendChild(li);
            });
        } else if (optionType === "text") {
            const li = document.createElement('li');
            li.className = 'brxc-custom-tag-option no-hover';
            li.dataset.id = id;
            li.innerHTML = `<input type="text" class="brxc-custom-tag-input" placeholder="Type an HTML tag and hit ENTER" value="" onkeydown="ADMINBRXC.setCustomTagInStructurePanel(this, event, 'text')"/>`;
            ul.appendChild(li);
        } else {
            const li = document.createElement('li');
            li.className = 'no-hover';
            li.innerHTML = `<div data-control="info">The HTML tag of this element cannot be changed.</div>`;
            ul.appendChild(li);
        }
    
        // Append and focus input
        wrapper.appendChild(ul);
        element.classList.add('tag-dropdown-active');
    
        const newInput = ul.querySelector('input[type="text"]');
        if (newInput) {
            newInput.focus();
            newInput.setSelectionRange(0, newInput.value.length);
        }
    
        // Handle outside click to close dropdown
        const handleOutsideClick = (e) => {
            if (!ul.contains(e.target) && !target.contains(e.target)) {
                self.tagBtnStates.active = null;
                ul.remove();
                element.classList.remove('tag-dropdown-active');
                window.removeEventListener('click', handleOutsideClick);
            }
        };
    
        // Delay binding to avoid catching current click
        setTimeout(() => {
            window.addEventListener('click', handleOutsideClick);
        }, 0);
    },
    setPanelElementListeners: function(){
        const self = this;
        const panelElements = document.querySelector('#bricks-panel');
        if(!panelElements) return;

        const arr = Object.values(self.globalSettings.classFeatures);

        function matchElement(target, config) {
            return config.includedFields.some(field => {
                if (typeof field === 'string') {
                    const matchedElement = target.closest(field);
                    return matchedElement && !config.excludedFields.some(excluded => matchedElement.matches(excluded));
                } else if (typeof field === 'object' && field.selector) {
                    const matchedElement = target.closest(field.selector);
                    if (matchedElement) {
                        const hasValidChild = field.hasChild.some(child => matchedElement.querySelector(child));
                        return hasValidChild && !config.excludedFields.some(excluded => matchedElement.matches(excluded));
                    }
                }
                return false;
            });
        }
        // Prevent Bricks from opening color popup on right-click
        let preventColorClick = false;
        panelElements.addEventListener('click', (e) => {
            const target = e.target;
            if(preventColorClick && target.closest('[data-control="color"]')){
                e.stopPropagation();
                e.preventDefault();
                preventColorClick = false;
                return;
            }
            // Grid Builder (before setTimeout so stopPropagation prevents native Bricks grid builder)
            if(Object.values(self.globalSettings.elementFeatures).includes("grid-builder") && target.closest('.has-visual-grid-builder .control-action-button')){
                e.stopPropagation();
                e.preventDefault();
                ADMINBRXC.openModal({target: false, id: "#brxcGridUIOverlay", callback: () => {ADMINBRXC.gridBuilderInit();}})
                return;
            }
            setTimeout(() => {
                // Variable Picker (V Icon)
                if(arr.includes("variable-picker") && ["icon", "both"].includes(self.globalSettings.classFeatures.variablePickerType) && target.classList.contains('variable-picker-button')){
                    if(target.previousElementSibling.classList.contains('CodeMirror')) return;
                    e.stopPropagation();
                    e.preventDefault();
                    const input = target.closest('[data-control]')?.querySelector('input');
                    self.openVariableModal({target: input, clickTarget: input, id: "#brxcVariableOverlay", focus: "#brxcVariableOverlay input.iso-search", type: "variable"});
                    return;
                }

                // Dynamic Data (skip if direct child of color control — that's the color picker button)
                if (Object.values(self.globalSettings.elementFeatures).includes("dynamic-data-modal") && matchElement(target, self.fields.dynamicDataModal)) {
                    e.stopPropagation();
                    e.preventDefault();
                    const dynamicInput = target.parentElement.querySelector('.has-dynamic-data, textarea, input[type="text"]');
                    self.dynamicDataStates.input = dynamicInput;
                    self.dynamicDataStates.cursorPos = dynamicInput?.selectionStart ?? dynamicInput?.value?.length ?? 0;
                    self.dynamicDataStates.search = '';
                    self.openModal({target: false, id: "#brxcDynamicDataModalOverlay", focus: '#brxcDynamicDataModalOverlay input[type="text"]', callback: () => {
                        self.dynamicDataInit();
                    }})
                    return;
                }
    
                // Update Sticky CSS
                if(self.stickyCssStates.computedValues){
                    self.updateStickyCSS();
                }

            },0)
        }, true)

        // set the preventColorClick flag for the click event
        panelElements.addEventListener('mousedown', (e) => {
            if(e.button === 2 && arr.includes("variable-color-picker") && e.target.closest('[data-control="color"]')){
                preventColorClick = true;
                e.stopPropagation();
            }
        }, true)
        panelElements.addEventListener('contextmenu', (e) => {
            const target = e.target;

            // Variable Picker (Right Click)
            if(arr.includes("variable-picker") && ["mouse", "both"].includes(self.globalSettings.classFeatures.variablePickerType) && matchElement(target, self.fields.CSSVariabe)){
                e.preventDefault();
                self.openVariableModal({target: target, clickTarget: target, id: "#brxcVariableOverlay", focus: "#brxcVariableOverlay input.iso-search", type: "variable"});
                return;
            }

            // Color Picker
            if (arr.includes("variable-color-picker") && matchElement(target, self.fields.colors)) {
                const dataControl = target.closest('[data-control="color"]');
                if(dataControl){
                    e.preventDefault();
                    e.stopPropagation();
                    const input = dataControl.querySelector('.bricks-control-preview');
                    const rawInput = dataControl.querySelector('.color-input input');
                    if(rawInput){
                        self.openVariableModal({target: rawInput, clickTarget: input, id: "#brxcVariableOverlay", focus: "#brxcVariableOverlay input.iso-search", type: "color"});
                    }
                };
                return;
            }

            // Control Group Copy/Paste
            if(target.closest('.control-group-title')){
                e.preventDefault();
                const controlGroup = e.target.parentElement.dataset.controlGroup;
                self.openContextualMenu(e, () => {return self.controlGroupContextualMenu(e, self.vueState.activePanelTab, controlGroup)}, "right", "control-group")
            }

            // Style/Content Copy/Paste
            if(target.closest('#bricks-panel-tabs')){
                e.preventDefault();
                const tabs = target.closest('#bricks-panel-tabs');
                const tab = tabs.children[0].contains(target) ? 'Content' : 'Style';
                const controlGroup = e.target.parentElement.dataset.controlGroup;
                self.openContextualMenu(e, () => {return self.controlGroupContextualMenu(e, tab, controlGroup)}, "right", "control-group")
            }
        })
        panelElements.addEventListener('focusin', (e) => {
            const target = e.target;

            // Variable Autocomplete
            if (Object.values(self.globalSettings.classFeatures).includes("autocomplete-variable") && matchElement(target, self.fields.CSSVariabe) && !target.classList.contains('autocomplete-active')) {
                target.classList.add('autocomplete-active');
                self.populateCSSVariables();
                self.autocomplete(target, self.cssVariables, "style");
            }

            // Autoformat Values
            if (Object.values(self.globalSettings.classFeatures).includes('autoformat-field-values') && matchElement(target, self.fields.CSSVariabe) && !target.classList.contains('autoformat-active')) {
                target.classList.add('autoformat-active');
                target.addEventListener('blur', () => {
                    const control = target.closest('[data-controlkey]')
                    self.autoformat(target, control);
                    const evt = new Event('input');
                    target.dispatchEvent(evt);
                })
            }
        })

        panelElements.addEventListener('keyup', (e) => {
            if(self.stickyCssStates.active && self.stickyCssStates.computedValues){
                self.updateStickyCSS();
            }
        })
    },
    setIframeListeners: function(){
        const self = this;
        setTimeout(() => {
            const iBody = FRAMEBRXC.content;
            if(!iBody) return;

            // Click
            iBody.addEventListener('click', (e) => {
                // Focus Mode
                const shortcut = self.vueState.isMac ? e.metaKey && e.shiftKey : e.ctrlKey && e.shiftKey;
                const element = e.target.closest('[data-id]');
                if(shortcut && element){
                     e.preventDefault();
                    e.stopPropagation()

                    self.focusModeStates.active = element.dataset.id;
                    const parent = element.parentElement.closest('[data-id]');
                    if(parent){
                        self.focusModeStates.parent = parent.dataset.id;
                    }
                    self.setFocusMode();
                }
            }, true);
        }, 2000)
    },
    setStructurePanelListeners: function(){
        const self = this;
        const structure = document.querySelector('#bricks-structure');
        if(!structure) return;

        // Click
        structure.addEventListener("click", (e) => {
            // Tag Manager
            self.setTagBtnListener(e);

            // Focus Mode
            const shortcut = self.vueState.isMac ? e.metaKey && e.shiftKey : e.ctrlKey && e.shiftKey;
            const element = e.target.closest('.element');
            if(shortcut && element) {
                e.preventDefault();
                e.stopPropagation()

                self.focusModeStates.active = element.dataset.id;
                const parent = element.parentElement.closest('.element');
                if(parent){
                    self.focusModeStates.parent = parent.dataset.id;
                }
                self.setFocusMode();
            }

        }, true)
        
        // Double Click
        structure.addEventListener("dblclick", (e) => {
            // Edit Component
            const target = e.target;

            if(self.structurePanelStates.tweaks.includes('db-click-edit-component') && !self.helpers.isComponentActive() && target.closest('.element.component')){
                const isComponent = target.closest('.element.component')
                const elId = isComponent.dataset.id;
                const componentId = self.helpers.getElementObject(elId).id;
                self.vueGlobalProp.$_setActiveComponent(componentId);
            }

        }, true)
    },
    controlGroupCopyPasteStates: {
        obj: {
            css: {},
            element: {}
        },
    },
    controlGroupContextualMenu: function(event, tab, group = false){
        const self = this;
        const elName = self.builderStates.activeElement?.name;
        const elementConfig = self.vueGlobalProp.$_getElementConfig(elName)
        const label = self.helpers.capitalizeStrings(elementConfig.controlGroups[group]?.title || tab);
        tab = tab.toLowerCase();
        const hasPasteValue = group ? Object.keys(self.controlGroupCopyPasteStates.obj.css).concat(Object.keys(self.controlGroupCopyPasteStates.obj.element)).some(el => {
            return elementConfig.controls[el]?.group === group
        }) : true;
        const isBulkActive = !!self.helpers.isBulkEdit()

        return `
            <ul>
                <li onclick="ADMINBRXC.copyElementSettings('${tab}','${group}')">Copy ${label} Settings</li>
                <li class="${!hasPasteValue ? 'disabled' : ''}" onclick="ADMINBRXC.pasteElementSettings('${tab}','${group}')">Paste ${label} Settings</li>
                <li class="${isBulkActive ? 'disabled' : ''}" onclick="ADMINBRXC.extendElementSettings('${tab}','${group}')">Extend ${label} Settings to same DOM-level Elements</li>
                <li class="delete" onclick="ADMINBRXC.resetElementSettings('${tab}','${group}')">Reset ${label} Settings</li>
            </ul>`;
    },
    copyElementSettings: function(tab = "style", group = false){
        const self = this;
        const elName = self.builderStates.activeElement?.name;
        const settings = self.builderStates.activeObject?.settings;
        if(!settings || !elName) return;

        const elControls = self.vueGlobalProp.$_getElementConfig(elName)?.controls;
        const cssObj = {};
        const elementObj = {};

        // css
        Object.entries(settings).forEach(entry => {
            const entryKey = entry[0].split(':')[0];
            if(typeof elControls[entryKey] === "undefined" || !elControls[entryKey].hasOwnProperty('css')) return;

            const target = self.helpers.createTargetWithPseudo(entryKey);

            if(entry[0] !== target || tab !== elControls[entryKey].tab || (group && group !== "false" && elControls[entryKey].group !== group)) return;
            
            cssObj[entryKey] = JSON.parse(JSON.stringify(entry[1]));
        })
        // element
        Object.entries(self.builderStates.activeElement.settings).forEach(entry => {
            const entryKey = entry[0].split(':')[0];
            if(typeof elControls[entryKey] === "undefined" || elControls[entryKey].hasOwnProperty('css')) return;

            if(tab !== elControls[entryKey].tab || (group && group !== "false" && elControls[entryKey].group !== group)) return;
            
            elementObj[entryKey] = JSON.parse(JSON.stringify(entry[1]));
        })

        self.controlGroupCopyPasteStates.obj.css = cssObj;
        self.controlGroupCopyPasteStates.obj.element = elementObj;
    },
    pasteElementSettings: function(tab = "style", group = false){
        const self = this;
        const elementObjs = self.helpers.isBulkEdit() ? self.vueState.selectedElements : [self.builderStates.activeElement];
        
        elementObjs.forEach(obj => {
            const elControls = self.vueGlobalProp.$_getElementConfig(obj.name)?.controls;
            if(!elControls) return;

            if (self.helpers.isClassActive()) obj = self.builderStates.activeObject
            if(Object.getPrototypeOf(obj.settings).length === 0) obj.settings = {};

            // css
            Object.entries(self.controlGroupCopyPasteStates.obj.css).forEach(entry => {
                const entryKey = entry[0]

                if(!elControls.hasOwnProperty(entryKey) || tab !== elControls[entryKey].tab || (group && group !== "false" && elControls[entryKey].group !== group)) return;
                
                const target = self.helpers.createTargetWithPseudo(entryKey);
                const targetObject = !self.helpers.isBulkEdit() && obj.id === self.vueState.activeElement.id && self.helpers.isClassActive() ? self.builderStates.activeObject : obj; 
                targetObject.settings[target] = entry[1];
                
            })

            // element
            Object.entries(self.controlGroupCopyPasteStates.obj.element).forEach(entry => {
                const entryKey = entry[0]

                if(!elControls.hasOwnProperty(entryKey) || tab !== elControls[entryKey].tab || (group && group !== "false" && elControls[entryKey].group !== group)) return;
                
                const target = entry[0];
                obj.settings[target] = entry[1];
                
            })
                
        })
        
        self.vueState.rerenderControls = Date.now();
    },
    extendElementSettings: function(tab = "style", group = false){
        const self = this;
        const el = self.builderStates.activeElement;
        const settings = self.builderStates.activeObject?.settings;
        if(!el || !settings) return;

        const contentType = self.helpers.getTemplateType();
        const elParentObject = el.parent === 0 ? false : self.helpers.getElementObject(el.parent);
        const elChildren = elParentObject ? elParentObject.children : self.vueState[contentType].filter(el => el.parent === 0).map(el => el.id)

        const elControls = self.vueGlobalProp.$_getElementConfig(el.name)?.controls;
        const cssObj = {};
        const elementObj = {};

        // css
        Object.entries(settings).forEach(entry => {
            const entryKey = entry[0].split(':')[0];
            if(typeof elControls[entryKey] === "undefined" || !elControls[entryKey].hasOwnProperty('css')) return;

            const target = self.helpers.createTargetWithPseudo(entryKey);

            if(entry[0] !== target || tab !== elControls[entryKey].tab || (group && group !== "false" && elControls[entryKey].group !== group)) return;
            
            cssObj[entryKey] = JSON.parse(JSON.stringify(entry[1]));
        })
        // element
        Object.entries(self.builderStates.activeElement.settings).forEach(entry => {
            const entryKey = entry[0].split(':')[0];
            if(typeof elControls[entryKey] === "undefined" || elControls[entryKey].hasOwnProperty('css')) return;

            if(tab !== elControls[entryKey].tab || (group && group !== "false" && elControls[entryKey].group !== group)) return;
            
            elementObj[entryKey] = JSON.parse(JSON.stringify(entry[1]));
        })

        const originalSettings = {
            css: cssObj,
            element: elementObj
        }
        originalSettings.css = cssObj;
        originalSettings.element = elementObj;
;

        // Loop through each child
        elChildren.forEach(child => {
            if(child === el.id) return;

            const childObject = self.helpers.getElementObject(child);
            const childControls = self.vueGlobalProp.$_getElementConfig(childObject.name)?.controls;
            if(Object.getPrototypeOf(childObject.settings).length === 0) childObject.settings = {};

            // css
            Object.entries(originalSettings.css).forEach(entry => {
                const entryKey = entry[0]

                if(!childControls.hasOwnProperty(entryKey) || tab !== childControls[entryKey].tab || (group && group !== "false" && childControls[entryKey].group !== group)) return;
                
                const target = self.helpers.createTargetWithPseudo(entryKey);
                childObject.settings[target] = entry[1];
                
            })

            // element
            Object.entries(originalSettings.element).forEach(entry => {
                const entryKey = entry[0]

                if(!childControls.hasOwnProperty(entryKey) || tab !== childControls[entryKey].tab || (group && group !== "false" && childControls[entryKey].group !== group)) return;
                
                const target = entry[0];
                childObject.settings[target] = entry[1];
            })
        })

        self.vueState.rerenderControls = Date.now();
    },
    resetElementSettings: function(tab = "style", group = false){
        const self = this;
        const el = self.builderStates.activeElement;
        const settings = self.builderStates.activeObject?.settings;
        if(!el || !settings) return;

        const elControls = self.vueGlobalProp.$_getElementConfig(el.name)?.controls;
        const elementObjs = self.helpers.isBulkEdit() ? self.vueState.selectedElements : [self.builderStates.activeElement];
        const cssObj = {};
        const elementObj = {};

        // css
        Object.entries(settings).forEach(entry => {
            const entryKey = entry[0].split(':')[0];
            if(typeof elControls[entryKey] === "undefined" || !elControls[entryKey].hasOwnProperty('css')) return;

            const target = self.helpers.createTargetWithPseudo(entryKey);

            if(entry[0] !== target || tab !== elControls[entryKey].tab || (group && group !== "false" && elControls[entryKey].group !== group)) return;
            
            cssObj[entryKey] = JSON.parse(JSON.stringify(entry[1]));
        })
        // element
        Object.entries(self.builderStates.activeElement.settings).forEach(entry => {
            const entryKey = entry[0].split(':')[0];
            if(typeof elControls[entryKey] === "undefined" || elControls[entryKey].hasOwnProperty('css')) return;

            if(tab !== elControls[entryKey].tab || (group && group !== "false" && elControls[entryKey].group !== group)) return;
            
            elementObj[entryKey] = JSON.parse(JSON.stringify(entry[1]));
        })

        const originalSettings = {
            css: cssObj,
            element: elementObj
        }
        originalSettings.css = cssObj;
        originalSettings.element = elementObj;
;

        // Loop through each child
        elementObjs.forEach(child => {
            const childControls = self.vueGlobalProp.$_getElementConfig(child.name)?.controls;

            // css
            Object.entries(originalSettings.css).forEach(entry => {
                const entryKey = entry[0]

                if(!childControls.hasOwnProperty(entryKey) || tab !== childControls[entryKey].tab || (group && group !== "false" && childControls[entryKey].group !== group)) return;
                
                const target = self.helpers.createTargetWithPseudo(entryKey);
                const targetObject = child.id === self.vueState.activeElement.id && self.helpers.isClassActive() ? self.builderStates.activeObject : child; 
                delete targetObject.settings[target];
                
            })

            // element
            Object.entries(originalSettings.element).forEach(entry => {
                const entryKey = entry[0]

                if(!childControls.hasOwnProperty(entryKey) || tab !== childControls[entryKey].tab || (group && group !== "false" && childControls[entryKey].group !== group)) return;
                
                const target = entry[0];
                delete child.settings[target];
            })
        })

        self.vueState.rerenderControls = Date.now();
    },
    initLocalStorage: function(){
        const self = this;

        // Ovverride localStorage from DB
        const saveUXSettingsToDB = self.globalSettings.saveUXSettingsToDB;
        const localStorageFromDB = self.globalSettings.builderSettings;
        if(saveUXSettingsToDB && !!localStorageFromDB){
            localStorage.setItem('brxc-builder-states', localStorageFromDB);
        }

        const ls = self.helpers.getLocalStorage();


        // Topbar Icons
        if(ls.topbarIcons){
            self.topbarStates.icons = ls.topbarIcons;
        }

        // Topbar Icons
        if(ls.topbarTweaks){
            self.topbarStates.tweaks = ls.topbarTweaks;
        }

        //Structure Header Icons
        if(ls.structureIcons){
            self.structurePanelStates.icons = ls.structureIcons;
        }

        //Structure Tweaks
        if(ls.structureTweaks){
            self.structurePanelStates.tweaks = ls.structureTweaks;
        }

        //Sticky CSS
        if(ls.stickyCss === true){
            self.stickyCssStates.active = true;
        } 

        if(ls.stickyCssComputed){
            self.stickyCssStates.computedValues = ls.stickyCssComputed
        }

        // Visitibility Floating Bar
        if(ls.visibilityFloatingBar === true){
            self.hideElementStates.active = true;
        }
        
        //Responsive Slider
        if(ls.responsiveSlider === true){
            self.responsiveSliderStates.active = true;
        }

        // Elements Tag
        if(ls.hasOwnProperty('elementsTag')){
            self.elementsTagStates.mode = ls.elementsTag
        }

        // Right Shortcut Keyboard
        if(ls.rightShortcutKeyboard){
            self.rightShortcutStates.keyboard = ls.rightShortcutKeyboard;
        }

        // Lock Element in Structure
        if(ls.lockDraggableElements){
            self.lockDraggableElementsStates.active = ls.lockDraggableElements
        }

        // Notes
        if(ls.structureNotes){
            self.noteStates.active = ls.structureNotes
        }

        // Elements Columns
        if(Object.values(self.globalSettings.elementFeatures).includes('resize-elements-icons') && ls.elementsColumns){
            self.elementsColStates.col = ls.elementsColumns;
        }

        // Focus Mode Preview
        if(ls.hasOwnProperty('focusModePreview')){
            self.focusModeStates.preview = ls.focusModePreview;
        }
    },
    appendStructureContainer: function(){
        const panel = document.querySelector('#bricks-structure');
        if(!panel) return;

        const panelContent = panel.querySelector('main.panel-content');
        if(!panelContent) return;

        const existingBottom = panel.querySelector('#brxcStructureBottomContainer');
        if(!existingBottom){
            const container = document.createElement('DIV');
            container.id = 'brxcStructureBottomContainer';
            panelContent.appendChild(container);
        }

        const existingTop = panel.querySelector('#brxcStructureTopContainer');
        if(!existingTop){
            const container = document.createElement('DIV');
            container.id = 'brxcStructureTopContainer';
            panel.insertBefore(container, panel.firstChild);
        }
    },
    setControlGroupVisibility: function(){
        if(bricksData.loadData.globalSettings.builderControlGroupVisibility !== 'always'){
            document.body.classList.add('at-group-control-off');
        }
    },
    init: function(){
        const self = this;
        self.vueState.brxc = [];
        let arr = null;

        // Global Classes
        self.handleGlobalClassesOnLoad();

        // elements
        if(self.globalSettings.defaultElementFeatures.includes('remove-style-controls')) self.removeControlGroups();

        // States
        self.initStates();
    
        // Observers
        self.initObservers();
        self.initContextualMenuObservers();

        // Functions
        self.setColorVariablesOnLoad();
        self.generateVariableCSS('global');
        self.generateVariableCSS('theme');
        self.generateBuilderCSS();
        self.setIsotope('body');
        self.setCodeMirror();
        self.setControlsOptions();
        self.setAlertMsg();
        self.hideEmptyElementCategory();

        // LocalStorage
        self.initLocalStorage();

        // Topbar
        self.initToolbar();
        self.topbarStates.tweaks.forEach(tweak => self.runTopbarTweaks(tweak))

        // Classes Importer
        self.importedClasses();


        // Builder Tweaks
        //// Topbar
        if(self.helpers.isBuilderTweaksTabActive('global-features')){
            // self.initGridGuide();
            self.setResponsiveHelper();
            self.populateClassCategories();
        }

        //// Structure Panels
        if(self.helpers.isBuilderTweaksTabActive('structure-panel')){
            self.appendStructureContainer();
            //self.setTagBtnListener();
            self.setLockElements();
            self.setContextualMenuItems();
            self.setHeaderStructurePanel()
            self.setRightShortcutCol();
            self.setColorsforStructureIndicators();
            self.setColorsforStructureParents();
            self.populateNestableElements();
            self.draggableStructurePanel();
            //self.setFocusModeListener();
            self.setSearchStructure();
            self.setStructurePanelListeners()
            self.setIframeListeners()
            //self.stickyCssStates.active ? self.setStickyCSS() : '';
        } 

        //// Classes and Styles
        if(self.helpers.isBuilderTweaksTabActive('classes-and-styles')){
            arr = Object.values(self.globalSettings.classFeatures);
            arr.includes("disable-id-styles") ? document.body.classList.add('at-disable-styles') : '';
            arr.includes("reorder-classes") ? self.reorderClasses() : '';
            arr.includes("group-classes-by-lock-status") ? self.groupClassesByLockStatus() : '';
            arr.includes("locked-class-indicator") ? document.body.classList.add('at-locked-classes', "true") : '';
            if (arr.includes("autocomplete-variable") ){
                self.populateCSSVariables();
            }
            arr.includes("variable-picker") ? document.body.classList.add('at-variable-picker') : '';
            
        }

        //// Elements
        if(self.helpers.isBuilderTweaksTabActive('elements')){
            arr = Object.values(self.globalSettings.elementFeatures)
            self.setPanelElementListeners();
            arr.includes("pseudo-shortcut") ? self.setDefaultPseudoClasses() : '';
            if(arr.includes("resize-elements-icons")) {
                self.setElementsColumns();
                self.setColumnNumber(false);
            }
            if(arr.includes("superpower-custom-css")) {
                document.body.classList.add('at-superpower-css');
                //self.delaySaveBtn()
            }
            if(arr.includes("expand-spacing")) {
                document.body.classList.add('at-expand-spacing');
            }
            if(arr.includes("dynamic-data-modal")) {
                document.body.classList.add('at-dynamic-data-modal');
            }
            if(arr.includes("color-default-raw")){
                self.colorControls();
            }
            Object.values(self.globalSettings.defaultElementFeatures.length > 0) ? self.setDefaultElements() : '';
            self.setControlGroupVisibility();
        }

        // Keyboard Shortcuts
        if(self.helpers.isBuilderTweaksTabActive('keyboard-shortcuts')){
            arr = Object.values(self.globalSettings.keyboardShortcuts.options)
            arr.includes("move-element") ?self.setStructurePanelKeyboardShortcuts() : '';
            arr.includes("open-at-modal") ? self.setKeyboardShortcuts() : '';
            self.setGlobalKeyboardsh();
        }
        
        // Run state functions
        self.runStates();
        self.runStateFunctions();
    }
}
window.addEventListener('load', () => {
    // Init
    ADMINBRXC.init()
    document.querySelectorAll('.brxc-overlay__wrapper').forEach(el => el.removeAttribute('style'));
    // const isPanelShortcuts = ADMINBRXC.helpers.isBuilderTweaksTabActive() && Object.values(ADMINBRXC.globalSettings.elementShortcutIcons).includes("tabs-shortcuts") && !ADMINBRXC.vueState.hasOwnProperty('showElementControlShortcuts');
    // isPanelShortcuts ? document.body.classList.add('at-has-panel-shortcuts') : '';

    //FRAME
    FRAMEBRXC.content = document.querySelector('#bricks-builder-iframe').contentDocument;
    FRAMEBRXC.vue = document.querySelector('#bricks-builder-iframe').contentDocument.querySelector('.brx-body').__vue_app__;
    FRAMEBRXC.vueGlobalProp = document.querySelector('#bricks-builder-iframe').contentDocument.querySelector('.brx-body').__vue_app__.config.globalProperties;
    FRAMEBRXC.vueState = document.querySelector('#bricks-builder-iframe').contentDocument.querySelector('.brx-body').__vue_app__.config.globalProperties.$_state;
    ADMINBRXC.selectorPickerInit();
})

// ADMINBRXC.vue._context.components['control-gradient'].data

