TradingView Theme Customizer

Customize TradingView theme colors

// ==UserScript==
// @name         TradingView Theme Customizer
// @namespace    https://greasyfork.org/en/users/742563-666-999
// @version      1.2
// @description  Customize TradingView theme colors
// @author       666 999
// @match        https://www.tradingview.com/*
// @grant        GM_addStyle
// @grant        GM_setValue
// @grant        GM_getValue
// @run-at       document-end
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    const COMMON_STYLES = `
    padding: 0;
    border: none;
    margin-top: none;
    width: 18px;
    height: 18px;
  `;

    GM_addStyle(`
    input[type="color"]::-webkit-color-swatch-wrapper {
      ${COMMON_STYLES}
    }

    input[type="color"]::-webkit-color-swatch,
    input[type="color"]::-moz-color-swatch {
      ${COMMON_STYLES}
    }


    /* this part is a total mess tbh, don't try making sense of it */


    .chart-page .chart-container-border {
        background-color: var(--tv-color-pane-background) !important;
    }


    /*watchlist background color*/
    [class*="listContainer-"]>div>div>[class*="wrap-"]>[class*="symbol-"],
    [class*="listContainer-"]>div>div>[class*="wrap-"]>[class*="separator-"]>[class*="innerWrapper-"],
    [class*="listContainer-"]>div>div>[class*="wrap-"]>[class*="separator-"],
    [class*="scrollable-"]>[class*="tree-"]>[class*="listContainer-"],
    [class*="list-"]>[class*="wrap-"]>[class*="wrap-"]>[class*="tableHeader-"]>[class*="columnHeader-"],
    .widgetbar-page.active>[class*="widget-"]>[class*="widgetHeader-"],
    .widgetbar-widgetbody>[class*="wrap-"]>[class*="wrap-"]>[class*="tableHeader-"],
    .widgetbar-widgetbody>[class*="wrap-"]>[class*="wrap-"]>[class*="tableHeader-"]>span,
    .widgetbar-widgetbody>[class*="container-"]>[class*="wrapper-"],
    .widgetbar-widget,
    .widgetbar-widgetheader,
    .msg-window,
    .pc-data .pc-item.pinned,
    .widgetbar-widget>[class*="widgetHeader-"]>[class*="switcherWrapper-"],
    .widgetbar-widget>[class*="widgetHeader-"]>[class*="switcher-wrapper-"],
    .widgetbar-widgetbody>[class*="container-"]>[class*="headerContainer-"]>[class*="switcher-wrapper-"],
    [class*="space-"]>[class*="tree-"]>[class*="listContainer-"]>div>div>[class*="wrap-"],
    [class*="counterItem-"][class*="zero-"].apply-common-tooltip>[class*="indicator-"]>[class*="content-"],
    [class*="button-"][class*="disabled-"],
    [class*="button-"][class*="disabled-"]:active,
    [class*="button-"][class*="disabled-"]:before {
      background-color: var(--tv-custom-watchlist-color) !important;
    }


    /*watchlist hover highlight color*/
    [class*="listContainer-"]>div>div>[class*="wrap-"]>[class*="symbol-"]:hover,
    [class*="space-"]>[class*="tree-"]>[class*="listContainer-"]>div>div>[class*="wrap-"]:hover {
      background-color: var(--tv-custom-watchlist-highlight-color) !important;
    }

    /*watchlist rows*/
    [class*="listContainer-"]>div>div>[class*="wrap-"]>[class*="symbol-"] {
      border-bottom: 1px solid var(--tv-custom-watchlist-outline-color) !important;
      border-top: 1px solid var(--tv-custom-watchlist-outline-color) !important;
    }


    [class*="listContainer-"]>div>div>[class*="wrap-"]>[class*="separator-"]:not([class*="separator-"][class*="firstItem-"]) {
      border-top: 1px solid var(--tv-custom-watchlist-outline-color) !important;
    }


    /*watchlist outline, corners*/
    .widgetbar-pages,
    .widgetbar-pages-no-tabs,
    [class*="footerPanel-"]>[class*="tabbar-"]>[class*="tabs-"],
    .layout__area--right {
      border-color: var(--tv-custom-watchlist-outline-color) !important;
    }

    /*bottom drawer line*/
    .widgetbar-wrap,
    .tv-messages>.msg-divider {
      background-color: var(--tv-custom-watchlist-highlight-color) !important;
    }

    /*watchlist bottom drawer line*/
    .widgetbar-page.active>[class*="widgetbar-widget"][class*="widget-"] {
      border-top-color: var(--tv-custom-watchlist-highlight-color) !important;
    }

    /*watchlist symbols text color, symbol title, header icons*/
    [class*="listContainer-"]>div>div>[class*="wrap-"]>[class*="symbol-"] [class*="inner-"],
    [class*="headerButton-"][class*="button-"],
    .widgetbar-headerspace .button {
      color: var(--tv-custom-watchlist-text-color) !important;
    }


    /*watchlist selected symbol outline color + charts selected indicator border*/
    [class*="symbol-"]>[class*="indicators-"][class*="active-"]:after,
    [class*="selected-"] [class*="buttons-"],
    [class*="selected-"] [class*="buttons-"][class*="button-"]:not(:first-child),
    [class*="selected-"] [class*="buttonsWrapper-"],
    [class*="selected-"] [class*="titlesWrapper-"] {
      border-color: var(--tv-custom-watchlist-selection-color) !important;
    }


    /*layers selected color*/
    [class*="container-"].chart-data-window>[class*="wrapper-"]>[class*="container-"]>[class*="active-"] [class*="header-"],
    .widgetbar-widgetbody>[class*="wrap-"]>[class*="space-"]>[class*="tree-"]>[class*="listContainer-"]>div>div>[class*="wrap-"][class*="selected-"] {
      background-color: var(--tv-color-toolbar-button-text-active) !important;
    }


    /*alert outline color*/
    .widgetbar-widgetbody>[class*="container-"]>[class*="body-"]>div>[class*="list-"] div>[class*="itemBody-"][class*="focused-"],
    [data-name="alert-log-item"][class*="itemBody-"][class*="focused-"] {
      outline: 2px solid var(--tv-custom-watchlist-selection-color) !important;
    }


    /*alerts and layers>data hover color*/
    .widgetbar-widgetbody>[class*="container-"]>[class*="body-"]>[class*="wrapper-"]>[class*="list-"]>div>[class*="itemBody-"]:hover,
    [data-name="alert-log-item"][class*="itemBody-"]:hover,
    .widgetbar-widgetbody>[class*="container-"]>[class*="wrapper-"]>[class*="container-"]>[class*="view-"][class*="hoverEnable-"]:hover {
      background: var(--tv-color-platform-background) !important;
    }


    /*ideas and stream ideas and stream hover color*/
    .tv-notes-widget__data>.tv-notes-widget__note-block:hover,
    .tv-notifications-widget-item:hover,
    [class*="stream-list-"][class*="scroll-"]>div>.responsive-container-media-mf-phone-vertical.responsive-container-base>[class*="card-"]:hover {
      background-color: var(--tv-color-platform-background) !important;
    }

    .tv-notes-widget__note-block:hover .desc:after {
      background: var(--tv-color-platform-background) !important;
    }


    .tv-notes-widget__note-block .desc:after {
      background: var(--tv-color-pane-background) !important;
    }


    /*selected layer bg color*/
    [class*="space-"]>[class*="tree-"]>[class*="listContainer-"]>div>div>[class*="wrap-"][class*="selected-"],
    {
    background-color: var(--tv-custom-watchlist-selection-color) !important;
    }


    /*templates hover*/

    #header-toolbar-study-templates>[class*="item-"]:hover:before {
      content: '';
      /* Required for pseudo-elements */
      width: 28px;
      /* Set the width of the circle */
      height: 28px;
      /* Set the height of the circle */
      border-radius: 50%;
      /* Make the circle round */
      background-color: var(--tv-custom-template-hover-color);
      /* Set the background color to the filled color */
      z-index: -1;
      /* Ensure the circle is behind the content */
    }

    #header-toolbar-study-templates>[class*="item-"]:hover:after {
      position: absolute;
      content: '';
      /* Required for pseudo-elements */
      width: 20px;
      /* Set the width of the inner circle */
      height: 20px;
      /* Set the height of the inner circle */
      border-radius: 50%;
      /* Make the inner circle round */
      border: 1px solid var(--tv-color-toolbar-button-text-hover);
      /* Set the border properties to create an outline */
      background-color: transparent;
      mix-blend-mode: normal;
      z-index: 1;
      /* Ensure the inner circle is above the filled circle */
    }


    #header-toolbar-study-templates>[class*="item-"]:hover {
      z-index: 1;
      color: var(--tv-color-toolbar-button-text-hover) !important;
    }


    /*left toolbar hover arrows*/
    [class*="control-"] [class*="arrow-"] {
      color: var(--tv-color-toolbar-button-text) !important;
    }

    [class*="control-"] [class*="arrow-"]:hover {
      color: var(--tv-color-toolbar-button-text-hover) !important;
    }

    [class*="isOpened-"] [class*="control-"] [class*="arrow-"] {
      color: var(--tv-color-toolbar-button-text-hover) !important;
    }


    /*watch and hot lists hover*/
    [data-name="watchlists-button"]:hover:not([class*="isOpened"]),
    .widgetbar-widget-hotlist>[class*="widgetHeader-"]>[class*="button-"]:hover:not([class*="isOpened"]) {
      color: var(--tv-color-toolbar-button-text-hover) !important;
    }


    /*fav toolbar button hover*/
    .tv-favorited-drawings-toolbar__widget.apply-common-tooltip:hover {
      color: var(--tv-color-toolbar-button-text-hover) !important;
    }


    /*hotlist button hover and some others?*/
    .widgetbar-headerspace .button:hover {
      background-color: var(--tv-color-toolbar-button-background-hover) !important;
    }

    .widgetbar-headerspace .button:hover:not(:active):not(.active) {
      color: var(--tv-color-toolbar-button-text-hover) !important;
    }


    /*fav toolbar clicked*/
    [class*="theme-"] .tv-favorited-drawings-toolbar__widget:active {
      color: var(--tv-color-toolbar-button-text-clicked) !important;
    }


    /*some widgetbar button hover color */
    [class*="headerButton-"][class*="button-"]:hover:not(:active) {
      color: var(--tv-color-toolbar-button-text-hover) !important;
    }

    /*global button clicked color*/
    [class*="button-"][class*="isInteractive-"][class*="isOpened-"],
    [class*="button-"]:active,
    [class*="button-"][class*="isOpened-"],
    .widgetbar-headerspace .button:hover,
    #header-toolbar-study-templates>[class*="item-"]:active {
      color: var(--tv-color-toolbar-button-text-clicked) !important;
    }

    #header-toolbar-study-templates>[class*="item-"]:active:after {
      border: 1px solid var(--tv-color-toolbar-button-text-clicked);
    }


    /* chat @ toggle */
    .widgetbar-headerspace .button.active {
      color: var(--tv-color-toolbar-button-text-clicked) !important;
      background-color: var(--tv-color-toolbar-button-background-hover) !important;
    }


    /*watchlist columns & groups names*/
    .widgetbar-widgetbody>[class*="wrap-"]>[class*="wrap-"]>[class*="tableHeader-"]>[class*="columnHeader-"][class*="symbolName-"]>[class*="label-"],
    [class*="wrap-"]>[class*="content-"]>[class*="scrollable-"]>[class*="tree-"]>[class*="listContainer-"]>div>div>[class*="wrap-"]>[class*="separator-"]>[class*="innerWrapper-"]>[class*="label-"] {
      mix-blend-mode: exclusion;
      color: #888 !important;
    }


    /*bg of settings, symbols, indicators, alerts*/
    [data-dialog-name="Symbol Search"]>[class*="wrap-"][class*="small-"][class*="newStyles-"],
    [data-dialog-name="Chart settings"],
    [data-name="globalSearch"],
    [class*="replayWrapper-"],
    [data-outside-boundary-for="watchlist-symbol-search-dialog"]>[class*="dialog-"]>[class*="wrapper-"]>[class*="wrap-"][class*="small-"],
    [class*="dialog-"] {
      background-color: var(--tv-color-pane-background) !important;
    }


    [class*="itemRow-"]:hover [class*="cell-"] {
      background-color: var(--tv-color-platform-background) !important;
    }

    [class*="itemRow-"]:hover [class*="cell-"][class*="highlighted-"] {
      background-color: var(--tv-color-platform-background) !important;
    }


    /*symbols bubbles bg color*/
    [class*="bubble-"][class*="appearance-default-"]:not([class*="bubble-"][class*="appearance-default-"][class*="active-"][class*="bubble-"]) {
      background-color: var(--tv-color-platform-background) !important;
    }

    /*symbols footnote bg color, currencies search header*/
    [data-outside-boundary-for="symbol-search-items-dialog"]>[class*="dialog-"]>[class*="wrapper-"]>[class*="footer-"],
    [data-outside-boundary-for="watchlist-symbol-search-dialog"]>[class*="dialog-"]>[class*="wrapper-"]>[class*="footer-"],
    [data-name="menu-inner"]>[class*="header-"] {
      background-color: var(--tv-color-popup-background) !important;
    }


    [data-name="menu-inner"]>[class*="action-"][class*="active-"] {
        background-color: var(--tv-color-toolbar-button-text-active) !important;
    }


    [data-name="menu-inner"]>[class*="action-"][class*="active-"]>[class*="labelAndDescription-"]>[class*="label-"] {
        color: var(--tv-color-popup-element-text-active) !important;
    }


    /*active settings/indicators tab*/
    [data-outside-boundary-for="series-properties-dialog"]>[class*="dialog-"]>[class*="wrapper-"]>[class*="content-"]>[class*="container-"]>[class*="accessible-"][class*="active-"],
    [data-outside-boundary-for="indicators-dialog"]>[class*="dialog-"]>[class*="wrapper-"]>[class*="wrapper-"]>[class*="container-"]>[class*="tab-"][class*="active-"] {
      background-color: var(--tv-color-toolbar-button-text-active) !important;
    }

    /*active settings/indicators tab text*/
    [data-outside-boundary-for="series-properties-dialog"]>[class*="dialog-"]>[class*="wrapper-"]>[class*="content-"]>[class*="container-"]>[class*="accessible-"][class*="active-"] [class*="title-"],
    [data-outside-boundary-for="series-properties-dialog"]>[class*="dialog-"]>[class*="wrapper-"]>[class*="content-"]>[class*="container-"]>[class*="accessible-"][class*="active-"] [class*="icon-"],
    [data-outside-boundary-for="indicators-dialog"]>[class*="dialog-"]>[class*="wrapper-"]>[class*="wrapper-"]>[class*="container-"]>[class*="tab-"][class*="active-"] [class*="title-"],
    [data-outside-boundary-for="indicators-dialog"]>[class*="dialog-"]>[class*="wrapper-"]>[class*="wrapper-"]>[class*="container-"]>[class*="tab-"][class*="active-"] [class*="icon-"] {
      color: var(--tv-color-toolbar-button-text-clicked) !important;
    }


    /*settings/indicators tab hover*/
    [data-outside-boundary-for="series-properties-dialog"]>[class*="dialog-"]>[class*="wrapper-"]>[class*="content-"]>[class*="container-"]>[class*="accessible-"]:hover:not([class*="active-"]),
    [data-outside-boundary-for="indicators-dialog"]>[class*="dialog-"]>[class*="wrapper-"]>[class*="wrapper-"]>[class*="container-"]>[class*="tab-"]:hover:not([class*="active-"]) {
      color: var(--tv-color-toolbar-button-text-hover) !important;
      background-color: var(--tv-color-toolbar-button-background-hover) !important;
    }


    /* save indicator template */
    [class*="autocomplete-"]>[class*="suggestions-"] {
      background-color: var(--tv-color-pane-background) !important;
    }

    [class*="autocomplete-"]>[class*="suggestions-"] [class*="suggestion-"]:hover {
      color: var(--tv-color-toolbar-button-text-hover) !important;
      background-color: var(--tv-color-toolbar-button-background-hover) !important;
    }

    [class*="autocomplete-"]>[class*="suggestions-"] [class*="suggestion-"]:hover {
      color: var(--tv-color-toolbar-button-text-hover) !important;
      background-color: var(--tv-color-toolbar-button-background-hover) !important;
    }

    [class*="autocomplete-"]>[class*="suggestions-"] [class*="suggestion-"][class*="selected-"] {
      color: var(--tv-color-toolbar-button-text-clicked) !important;
      background-color: var(--tv-color-toolbar-button-text-active) !important;
    }


    /*chart indicator tilte*/
    [class*="chart-widget__top"] [class*="selected-"] [class*="titlesWrapper-"],
    [class*="chart-widget__top"] [class*="selected-"] [class*="buttons-"],
    [class*="chart-widget__top"] [class*="withAction-"] [class*="titlesWrapper-"],
    [class*="chart-widget__top"] [class*="withAction-"] [class*="buttons-"] {
      background-color: var(--tv-color-toolbar-save-layout-loader) !important;
    }

    [class*="chart-widget__top"] [class*="button-"]:hover:after {
      background-color: var(--tv-color-toolbar-button-background-hover) !important;
    }

    [class*="chart-widget__top"] [class*="buttonIcon-"]:hover {
      color: var(--tv-color-toolbar-button-text-hover) !important;
    }

    [class*="chart-widget__top"] [class*="buttonIcon-"]:hover:after {
      color: var(--tv-color-toolbar-button-text-hover) !important;
    }


    /*switcher button*/

    [class*="light-tab-button"][class*="selected-"] {
      background-color: var(--tv-color-pane-background) !important;
    }


    [class*="light-tabs-"],
    [class*="light-tab-button"] {
      background-color: var(--tv-color-toolbar-save-layout-loader) !important;
    }


    [class*="light-tab-button"]:hover:not([class*="light-tab-button"][class*="selected-"]) {
      background-color: var(--tv-color-toolbar-button-text) !important;
    }


    /* publish button hover */
    .publish-chart-button[class*="button-"] [class*="bg-"]:hover {
      background-color: var(--tv-color-toolbar-button-background-hover) !important;
      color: var(--tv-color-toolbar-button-text-hover) !important;
    }


    /* chat highlight hover */
    .ch-highlight-user:hover,
    .ch-is-author:hover,
    .ch-item:hover,
    .msg-data .msg-item:hover:not(.msg-data .msg-item.active) {
      background: var(--tv-color-platform-background) !important;
    }

    /* pub chat separator */
    [class*="chat-wrapper-"]>[class*="widget-"]>[class*="split-widget-"]>[class*="divider-"] {
      border-color: var(--tv-color-platform-background) !important;
    }

    /* chat active */
    .pc-data .pc-item.active {
      background: var(--tv-color-toolbar-button-text-active) !important;
    }


    [data-outside-boundary-for="go-to-date-dialog"]>[class*="dialog-"],
    [class*="calendar-"] {
      background-color: var(--tv-color-pane-background) !important;
    }

    [class*="calendar-"]>[class*="sub-header-"] {
      background-color: var(--tv-color-platform-background) !important;
    }


    /* Animation for menu extension */
    #themeMenu {
      transition: width 0.1s linear;
    }
  `);

    const MENU_WIDTH_EXTENDED = '574px';
    const MENU_WIDTH_COLLAPSED = '220px';
    const BUY_COFFEE_WIDTH = '424px';

    const COLOR_GROUPS = {
        color1: [
            '--tv-color-pane-background',
            '--tv-color-toolbar-divider-background',
            '--tv-color-popup-element-divider-background',
            '--tv-custom-watchlist-color',
            '--tv-alerts-widget-list-item-background',
            '--counter-indicator-background-color',
        ],
        color2: [
            '--tv-color-toolbar-save-layout-loader',
            '--tv-color-popup-background',
            '--tv-color-popup-element-toolbox-background-hover',
        ],
        color3: [
            '--tv-color-platform-background',
            '--tv-custom-watchlist-highlight-color',
            '--tv-custom-watchlist-outline-color',
                ],
        color4: [
            '--tv-color-toolbar-button-text',
            '--tv-color-popup-element-text',
            '--tv-color-popup-element-toolbox-text',
            '--tv-custom-watchlist-text-color',
        ],
        color5: [
            '--tv-color-toolbar-button-text-hover',
            '--tv-custom-watchlist-outline-color2',
            '--tv-color-popup-element-text-hover',
            '--tv-color-popup-element-secondary-text',
            '--tv-color-popup-element-hint-text',
            '--tv-color-popup-element-toolbox-text-hover',
            '--tv-color-popup-element-toolbox-text-active-hover',
        ],
        color6: [
            '--tv-color-toolbar-button-background-hover',
            '--tv-color-toolbar-button-background-expanded',
            '--tv-color-toolbar-button-background-active-hover',
            '--tv-color-popup-element-background-hover',
            '--tv-custom-watchlist-hover-bgcolor',
            '--tv-custom-template-hover-color',
        ],
        color7: [
            '--tv-color-item-active-text',
            '--tv-color-popup-element-text-active',
            '--tv-color-toolbar-button-text-clicked', // new
        ],
        color8: [
            '--tv-custom-watchlist-selection-color',
            '--tv-color-toolbar-button-text-active',
            '--tv-color-toolbar-button-text-active-hover',
            '--tv-color-toolbar-toggle-button-background-active',
            '--tv-color-popup-element-background-active',
            '--control-button-color-content',
        ],
        color9: [
            '--tv-color-toolbar-toggle-button-background-active-hover',
            '--tv-color-popup-element-toolbox-background-active-hover',
        ],
        color10: ['--tv-color-toolbar-button-background-active'],
        //new ones, WIP
        /*color11: [
                 //'--tv-color-toolbar-button-background',
                 //'--tv-color-toolbar-button-text-clicked',
                 //'--tv-color-toolbar-button-background-clicked'
        ],*/
    };

    const TITLES = {
        color1: 'Pane',
        color2: 'Favorites Toolbar & Menu',
        color3: 'Background & Symbol Highlight',
        color4: 'Buttons & Symbol Names',
        color5: 'Button Hover',
        color6: 'Button Hover Background',
        color7: 'Active Item Name / Button Click',
        color8: 'Active Button / Item',
        color9: 'Active Bottom Button Hover',
        color10: 'Active Button Of Right Panel',
    };

    const DEFAULT_COLORS = {
        color1: '#2e2f37', color2: '#321a24', color3: '#1b1c24', color4: '#da8bb1', color5: '#ff0000',
        color6: '#f48fb1', color7: '#000000', color8: '#cc285f', color9: '#4dd0e1', color10: '#1b1c24',
    };

    // tradingview's pink theme
    const PRESET_COLORS_2 = {
        color1: '#fbdff4', color2: '#868993', color3: '#d1c4e9', color4: '#88184f', color5: '#4a148c',
        color6: '#f48fb1', color7: '#0606ff', color8: '#ff0000', color9: '#ff00ff', color10: '#f9b9e9',
    };

    const PRESET_COLORS_3 = {
        color1: '#000000', color2: '#1c1c1c', color3: '#003338', color4: '#17bee8', color5: '#24f07c',
        color6: '#000000', color7: '#000000', color8: '#ff8838', color9: '#941600', color10: '#000000',
    };

    // Initialize savedColors with stored settings or DEFAULT_COLORS
    const savedColors = GM_getValue('customColors') || { ...DEFAULT_COLORS };

    // Helper Function: Copy Text to Clipboard
    function copyToClipboard(text) {
        const textarea = document.createElement('textarea');
        textarea.value = text;
        document.body.appendChild(textarea);
        textarea.select();
        document.execCommand('copy');
        document.body.removeChild(textarea);
    }

    // Function to display a right-top speech balloon
    function displayBalloon(menu, message) {
        // Remove existing balloon if present
        const existingBalloon = document.getElementById('balloon');
        if (existingBalloon) {
            menu.removeChild(existingBalloon);
        }

        // Create a balloon container
        const balloon = document.createElement('div');
        balloon.id = 'balloon';
        balloon.style.position = 'absolute';
        balloon.style.top = '74px';
        balloon.style.right = '30%';
        balloon.style.zIndex = '1002';

        // Create the balloon content
        const content = document.createElement('div');
        content.textContent = message;
        content.style.background = 'darkgrey';
        content.style.color = '#222';
        content.style.padding = '10px';
        content.style.borderRadius = '5px';

        // Append the content to the balloon container
        balloon.appendChild(content);

        // Create a tail element using ::before pseudo-element
        const tail = document.createElement('div');
        tail.id = 'tail';
        tail.style.position = 'absolute';
        tail.style.borderStyle = 'solid';
        tail.style.borderWidth = '10px';
        tail.style.borderColor = 'transparent transparent transparent darkgrey';
        tail.style.top = '23.5%';
        tail.style.left = '100%';

        balloon.appendChild(tail);

        // Append the balloon to the menu container
        menu.appendChild(balloon);

        // Hide the balloon after a short delay (e.g., 1.5 seconds)
        setTimeout(() => {
            menu.removeChild(balloon);
        }, 1500);
    }

    // Add a variable to store the menu position
    let menuPosition = { top: '95px', left: '56px' };
    // Helper Function: Make Menu Movable
    function makeMovable(menu, applyThemeMenuStyles) {
        let isDragging = false;
        let offsetX, offsetY;

        menu.addEventListener('mousedown', (event) => {
            isDragging = true;
            offsetX = event.clientX - menu.getBoundingClientRect().left;
            offsetY = event.clientY - menu.getBoundingClientRect().top;
        });

        document.addEventListener('mousemove', (event) => {
            if (isDragging) {
                menu.style.left = event.clientX - offsetX + 'px';
                menu.style.top = event.clientY - offsetY + 'px';
            }
        });

        document.addEventListener('mouseup', () => {
            if (isDragging) {
                // Update the menu position when dragging stops
                menuPosition = { top: menu.style.top, left: menu.style.left };
            }
            isDragging = false;
        });
    }

    // Helper Function: Apply Colors to Theme
    function applyColors() {
        Object.entries(COLOR_GROUPS).forEach(([group, properties]) => {
            properties.forEach((property) => {
                document.documentElement.style.setProperty(property, savedColors[group] || DEFAULT_COLORS[group]);
            });
        });
    }

    // Helper Function: Apply Theme Menu Styles
    function applyThemeMenuStyles(menu, isExtended) {
        const menuWidth = isExtended ? MENU_WIDTH_EXTENDED : MENU_WIDTH_COLLAPSED;
        menu.style.width = menuWidth;
        menu.style.overflow = 'hidden';
        menu.style.position = 'fixed';
        // Update menu position directly
        menu.style.top = menuPosition.top;
        menu.style.left = menuPosition.left;
        menu.style.padding = '10px';
        menu.style.color = savedColors.color4 || DEFAULT_COLORS.color4;
        menu.style.background = savedColors.color2 || DEFAULT_COLORS.color2;
        menu.style.border = `1px solid ${savedColors.color8 || DEFAULT_COLORS.color8}`;
        menu.style.zIndex = '1000';
        menu.style.display = 'flex';
        menu.style.flexDirection = 'column';
        menu.style.borderRadius = '5px';

        // Make the menu movable
        makeMovable(menu);

        // "Buy me a coffee" section
        const hiddenPart = document.createElement('div');
        hiddenPart.style.width = BUY_COFFEE_WIDTH;
        hiddenPart.style.overflow = 'hidden';
        hiddenPart.style.position = 'absolute';
        hiddenPart.style.top = '0';
        hiddenPart.style.right = `-${BUY_COFFEE_WIDTH}`;
        hiddenPart.style.left = '220px';
        hiddenPart.style.background = savedColors.color2 || DEFAULT_COLORS.color2;
        hiddenPart.style.color = savedColors.color4 || DEFAULT_COLORS.color4;

        const buyCoffeeText = document.createElement('p');
        buyCoffeeText.style.fontFamily = 'Consolas, monospace';
        buyCoffeeText.style.fontSize = '14px';
        buyCoffeeText.innerHTML = '<span style="font-size: 12px;">Consider support or buying me coffee</span>\
        <br><br>\
        /\\_____/\\<br>\
        /&nbsp;&nbsp;o&nbsp;&nbsp;&nbsp;o&nbsp;&nbsp;\\<br>\
        (&nbsp;==&nbsp;&nbsp;^&nbsp;&nbsp;==&nbsp;)<br>\
        )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<br>\
        (&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)<br>\
        (&nbsp;(&nbsp;&nbsp;)&nbsp;&nbsp;&nbsp;(&nbsp;&nbsp;)&nbsp;)<br>\
        (__(__)___(__)__)<br>\
        ';
        buyCoffeeText.style.padding = '7px';
        buyCoffeeText.style.textAlign = 'center';

        const trc20Text = document.createElement('span');
        trc20Text.style.fontSize = '11px';
        trc20Text.innerHTML = 'USDT TRC20: ';

        const trc20Address = document.createElement('span');
        trc20Address.textContent = 'TSvizdjmrtXjYEEcUDzbvwLSLEbAJYXARA';
        trc20Address.style.cursor = 'pointer';
        trc20Address.addEventListener('click', function () {
            copyToClipboard(trc20Address.textContent);
            displayBalloon(menu, 'TRC-20 address copied to clipboard');
        });

        const ethText = document.createElement('span');
        ethText.style.fontSize = '11px';
        ethText.innerHTML = '<br>USDT on Polygon(ERC20) & BSC(BEP20):<br>';

        const ethAddress = document.createElement('span');
        ethAddress.textContent = '0x32Cc052782E3A42Fcb25D7242E2FA5F8B0c3583B';
        ethAddress.style.cursor = 'pointer';
        ethAddress.addEventListener('click', function () {
            copyToClipboard(ethAddress.textContent);
            displayBalloon(menu, 'ERC-20/BEP-20 address copied to clipboard');
        });

        const advText = document.createElement('span');
        advText.style.fontSize = '11px';
        advText.innerHTML = '<br>USD Advcash: ';
        advText.style.marginRight = '0px';

        const advAddress = document.createElement('span');
        advAddress.textContent = 'U 9415 5458 0453';
        advAddress.style.cursor = 'pointer';
        advAddress.addEventListener('click', function () {
            copyToClipboard(advAddress.textContent);
            displayBalloon(menu, 'Advcash address copied to clipboard');
        });

        buyCoffeeText.appendChild(trc20Text); trc20Text.appendChild(trc20Address);
        buyCoffeeText.appendChild(ethText); ethText.appendChild(ethAddress);
        buyCoffeeText.appendChild(advText); advText.appendChild(advAddress);
        hiddenPart.appendChild(buyCoffeeText);
        menu.appendChild(hiddenPart);
    }

    // Helper Function: Toggle Menu Extension
    function toggleMenuExtension(menu, hiddenPart) {
        const isExtended = menu.style.width === MENU_WIDTH_EXTENDED;
        applyThemeMenuStyles(menu, !isExtended);

        const newRightPosition = isExtended ? `-${BUY_COFFEE_WIDTH}` : '0';
        hiddenPart.style.right = newRightPosition;
    }

    // Helper Function: Update Theme Styles without Affecting Menu Extension
    function updateThemeStyles(menu) {
        const menuWidth = menu.style.width;
        applyThemeMenuStyles(menu);
        menu.style.width = menuWidth;
    }

    // Helper Function: Create Button Element
    function createButton(text, width, gridColumn, gridRow, clickHandler) {
        const button = document.createElement('button');
        button.textContent = text;
        button.style.width = width;
        button.style.gridColumn = gridColumn;
        button.style.gridRow = gridRow;
        button.style.backgroundColor = 'dimgrey';
        button.style.border = 'none';
        button.style.borderRadius = '2px';
        button.style.height = '25px';
        button.addEventListener('click', clickHandler);
        return button;
    }

    // Main Function: Open Theme Menu
    function openThemeMenu() {
        const existingMenu = document.getElementById('themeMenu');

        // If the menu is already open, close it
        if (existingMenu) {
            document.body.removeChild(existingMenu);
            return;
        }

        // If the menu is not open, create and open it
        const menu = document.createElement('div');
        menu.id = 'themeMenu';
        applyThemeMenuStyles(menu);

        // Add a small button at the top right corner
        const toggleButton = createButton('☕', '32px', 'auto', 'auto', function () {
            toggleMenuExtension(menu);
        });
        toggleButton.style.position = 'absolute';
        toggleButton.style.top = '5px';
        toggleButton.style.right = '1px';
        toggleButton.style.background = 'transparent';
        toggleButton.style.border = 'none';
        toggleButton.style.padding = '0';
        toggleButton.style.cursor = 'pointer';
        toggleButton.style.zIndex = '1001';
        menu.appendChild(toggleButton);

        Object.entries(COLOR_GROUPS).forEach(([group, properties]) => {
            const option = document.createElement('div');
            option.style.display = 'flex';
            option.style.marginBottom = '4px';

            const label = document.createElement('label');
            label.textContent = `- ${TITLES[group]}`;
            label.style.marginRight = '4px';
            label.style.fontFamily = 'Calibri';
            label.style.fontSize = '14px';

            const colorPicker = document.createElement('input');
            colorPicker.type = 'color';
            colorPicker.value = savedColors[group] || DEFAULT_COLORS[group];
            colorPicker.style = COMMON_STYLES;
            colorPicker.setAttribute('data-group', group);
            colorPicker.addEventListener('input', function () {
                savedColors[group] = this.value;
                applyColors();
                updateThemeStyles(menu);
            });

            option.appendChild(colorPicker);
            option.appendChild(label);
            menu.appendChild(option);
        });
        const updateColorPickers = function () {
            Object.entries(COLOR_GROUPS).forEach(([group, properties]) => {
                const colorPicker = document.querySelector(`input[type="color"][data-group="${group}"]`);
                if (colorPicker) {
                    colorPicker.value = savedColors[group] || DEFAULT_COLORS[group];
                }
            });
        };

        // Flex container for importExportLabel and importExportInput
        const flexContainer = document.createElement('div');
        flexContainer.style.display = 'flex';
        flexContainer.style.flexDirection = 'column';
        flexContainer.style.marginBottom = '4px';

        const importExportInput = document.createElement('input');
        importExportInput.type = 'text';
        importExportInput.placeholder = 'theme settings here';
        importExportInput.style.border = '1px solid darkgrey';
        importExportInput.style.padding = '3px';
        importExportInput.style.background = 'darkgrey';
        importExportInput.style.color = '#222';
        importExportInput.style.borderRadius = '2px';
        importExportInput.style.fontFamily = 'Consolas';
        importExportInput.style.fontSize = '13px';
        importExportInput.style.zIndex = '1000';

        // Import/Export Section
        const importExportSection = document.createElement('div');
        importExportSection.style.display = 'grid';
        importExportSection.style.gridTemplateColumns = 'repeat(5, 1fr)';
        importExportSection.style.gridGap = '2px';
        importExportSection.style.marginBottom = '4px';

        const importButton = createButton('Import', '120px', '1 / span 1', '1', function () {
            const importedColors = importExportInput.value.trim();
            if (!importedColors) {
                // If the input field is empty
                displayBalloon(menu, 'Put settings in the field');
                return;
            }

            const importedArray = importedColors.split(/[\s-]+/);

            if (importedArray.length !== Object.keys(COLOR_GROUPS).length) {
                // If the input has incorrect number of color values
                displayBalloon(menu, 'Incorrect input');
                return;
            }

            // Check if all values are valid hex color codes
            const isValidHex = importedArray.every(color => /^#[0-9A-F]{6}$/i.test(color));

            if (isValidHex) {
                Object.keys(COLOR_GROUPS).forEach((group, index) => {
                    savedColors[group] = importedArray[index] || DEFAULT_COLORS[group];
                });
                applyColors();
                updateThemeStyles(menu);
                updateColorPickers();
                displayBalloon(menu, 'Theme imported');
            } else {
                // If any color value is not a valid hex code
                displayBalloon(menu, 'Incorrect input');
            }
        });

        // Import/Export Section: Export Button
        const exportButton = createButton('Export', '120px', '1 / span 1', '2', function () {
            const exportedColors = Object.keys(COLOR_GROUPS)
            .map((group) => savedColors[group] || DEFAULT_COLORS[group])
            .join(' ');
            importExportInput.value = exportedColors;
            copyToClipboard(exportedColors);
            // Show "Copied to clipboard" balloon
            displayBalloon(menu, 'Settings copied to clipboard');
        });

        // Save Button
        const saveButton = createButton('Save', '120px', '1 / span 1', '3', function () {
            GM_setValue('customColors', savedColors);
            applyColors();
            //document.body.removeChild(menu);
            // Show "Copied to clipboard" balloon
            displayBalloon(menu, 'Theme saved');
        });

        menu.appendChild(flexContainer);
        flexContainer.appendChild(importExportInput);
        menu.appendChild(importExportSection);
        importExportSection.appendChild(importButton);
        importExportSection.appendChild(exportButton);

        // Empty column
        const importExportEmptyColumn = document.createElement('label');
        importExportEmptyColumn.style.gridColumn = '2 / span 1';
        importExportEmptyColumn.style.minWidth = '146px';
        importExportSection.appendChild(importExportEmptyColumn);

        // Preset Buttons - Save
        for (let i = 1; i <= 3; i++) {
            const saveCustomButton = createButton(`💾 Custom ${i}`, '100px', `${i + 2} / span 1`, '1', function () {
                savePreset(i);
                displayBalloon(menu, `Preset saved as Custom ${i}`);
            });
            importExportSection.appendChild(saveCustomButton);
        }

        // Preset Buttons - Load
        for (let i = 1; i <= 3; i++) {
            const loadCustomButton = createButton(`🔼 Custom ${i}`, '100px', `${i + 2} / span 1`, '2', function () {
                loadPreset(i);
                displayBalloon(menu, `Custom preset ${i} loaded`);
            });
            importExportSection.appendChild(loadCustomButton);
        }

        // Preset Buttons - Presets
        const presets = [
            { label: '🔼 Preset 1', width: '100px', gridColumn: '3 / span 1', gridRow: '3', colors: DEFAULT_COLORS },
            { label: '🔼 Preset 2', width: '100px', gridColumn: '4 / span 1', gridRow: '3', colors: PRESET_COLORS_2 },
            { label: '🔼 Preset 3', width: '100px', gridColumn: '5 / span 1', gridRow: '3', colors: PRESET_COLORS_3 },
        ];

        presets.forEach((preset) => {
            const presetButton = createButton(preset.label, preset.width, preset.gridColumn, preset.gridRow, function () {
                Object.keys(COLOR_GROUPS).forEach((group) => {
                    savedColors[group] = preset.colors[group];
                });
                applyColors();
                updateThemeStyles(menu);
                updateColorPickers();
                displayBalloon(menu, `${preset.label.substring(2)} loaded`);
            });
            importExportSection.appendChild(presetButton);
        });

        // Helper Function: Save Preset
        function savePreset(presetNumber) {
            const presetKey = `customPreset${presetNumber}`;
            GM_setValue(presetKey, savedColors);
        }

        // Helper Function: Load Preset
        function loadPreset(presetNumber) {
            const presetKey = `customPreset${presetNumber}`;
            const presetColors = GM_getValue(presetKey);
            Object.keys(COLOR_GROUPS).forEach((group) => {
                savedColors[group] = presetColors[group];
            });
            applyColors();
            updateThemeStyles(menu);
            updateColorPickers();
        }
        // Create a new paragraph element
        const paragraph = document.createElement('p');

        // Set the text content of the paragraph
        paragraph.innerHTML = 'TradingView<br>Theme<br>Customizer<br><br>v1.2';

        // Style the paragraph if needed
        paragraph.style.fontFamily = 'Consolas';
        paragraph.style.fontSize = '13px';
        paragraph.style.color = savedColors.color4 || DEFAULT_COLORS.color4;
        paragraph.style.position = 'absolute';
        paragraph.style.bottom = '16px';
        paragraph.style.left = '140px';

        // Append the paragraph to the menu
        menu.appendChild(paragraph);

        importExportSection.appendChild(saveButton);
        document.body.appendChild(menu);
    }

    // Helper Function: Add Theme Button
    function addThemeButton() {
        const button = document.createElement('button');
        button.style.position = 'fixed';
        button.style.top = '5px';
        button.style.left = '12px';
        button.style.background = 'transparent';
        button.style.padding = '0';
        button.style.cursor = 'pointer';
        button.style.borderLeft = `5px solid ${savedColors.color4 || DEFAULT_COLORS.color4}`;
        button.style.borderTop = `5px solid ${savedColors.color4 || DEFAULT_COLORS.color4}`;
        button.style.borderRight = '5px solid transparent';
        button.style.borderBottom = '5px solid transparent';

        // Hover styles
        button.addEventListener('mouseover', function () {
            button.style.borderLeft = `5px solid ${savedColors.color5 || DEFAULT_COLORS.color5}`;
            button.style.borderTop = `5px solid ${savedColors.color5 || DEFAULT_COLORS.color5}`;
        });

        button.addEventListener('mouseout', function () {
            button.style.borderLeft = `5px solid ${savedColors.color4 || DEFAULT_COLORS.color4}`;
            button.style.borderTop = `5px solid ${savedColors.color4 || DEFAULT_COLORS.color4}`;
        });

        button.addEventListener('click', openThemeMenu);
        document.body.appendChild(button);
    }

    // Main Execution
    applyColors();
    addThemeButton();
})();