Pinterest Dark Mode Toggle

A customizable AMOLED dark theme for Pinterest

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

Advertisement:

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

Advertisement:

// ==UserScript==
// @name         Pinterest Dark Mode Toggle
// @namespace    https://github.com/thetalhachy/pinterest-amoled-dark-mode
// @version      1.0.0
// @description  A customizable AMOLED dark theme for Pinterest
// @author       Talha Mohammad Chowdhury
// @license      AGPL-3.0-or-later
// @match        https://www.pinterest.com/*
// @grant        GM_addStyle
// @grant        GM_getValue
// @grant        GM_setValue
// ==/UserScript==

(function () {
    'use strict';

    const ID = {
        STYLE:  'pdm-style',
        TOAST:  'pdm-toast',
        BTN:    'pdm-btn',
        MENU:   'pdm-menu',
    };

    const KEY = {
        ENABLED:   'pdm_enabled',
        ACCENT:    'pdm_accent',
        CONTRAST:  'pdm_contrast',
    };

    const CLS = 'pdm-dark';

    // Accent colour options: [label, r, g, b]
    const ACCENTS = [
        { label: '🔴', r: 220, g: 50,  b: 50  },
        { label: '🟠', r: 210, g: 100, b: 20  },
        { label: '🟣', r: 130, g: 60,  b: 220 },
        { label: '🔵', r: 40,  g: 120, b: 220 },
        { label: '🟢', r: 40,  g: 180, b: 100 },
        { label: '⚪', r: 180, g: 180, b: 180 },
    ];

    let enabled        = GM_getValue(KEY.ENABLED,  true);
    let accentIndex    = GM_getValue(KEY.ACCENT,   0);       // index into ACCENTS
    let contrastLevel  = GM_getValue(KEY.CONTRAST, 1);       // 0 = soft, 1 = mid, 2 = AMOLED

    function bgFromContrast() {
        // Returns the base background colour for the chosen contrast level
        return ['#1a1a1a', '#0f0f0f', '#000000'][contrastLevel];
    }

    function surfaceFromContrast() {
        return ['#242424', '#161616', '#0d0d0d'][contrastLevel];
    }

    function accentRGB() {
        const a = ACCENTS[accentIndex];
        return `${a.r},${a.g},${a.b}`;
    }

    function buildCSS() {
        const bg      = bgFromContrast();
        const surface = surfaceFromContrast();
        const acc     = accentRGB();

        return `

/* ── BASE ─────────────────────────────────────────────────── */

html.pdm-dark,
html.pdm-dark body,
html.pdm-dark #__PWS_ROOT__ {
    background: ${bg} !important;
    color: #e6e6e6 !important;
}

/* ── BLANKET RESET ──────────────────────────────────────────
   Make all structural elements transparent so the body
   colour shows through. Specific surfaces are set below.
──────────────────────────────────────────────────────────── */

html.pdm-dark div,
html.pdm-dark section,
html.pdm-dark main,
html.pdm-dark article,
html.pdm-dark aside,
html.pdm-dark footer,
html.pdm-dark li,
html.pdm-dark ul,
html.pdm-dark ol,
html.pdm-dark form,
html.pdm-dark label {
    background-color: transparent !important;
    border-color: rgba(255,255,255,0.06) !important;
    color: #e6e6e6 !important;
}

/* ── TYPOGRAPHY ─────────────────────────────────────────────── */

html.pdm-dark span,
html.pdm-dark p,
html.pdm-dark h1,
html.pdm-dark h2,
html.pdm-dark h3,
html.pdm-dark h4,
html.pdm-dark h5,
html.pdm-dark h6,
html.pdm-dark button,
html.pdm-dark a,
html.pdm-dark a:visited {
    color: #e6e6e6 !important;
}

html.pdm-dark a:hover {
    color: rgba(${acc},0.9) !important;
}

html.pdm-dark .tappable,
html.pdm-dark .small,
html.pdm-dark .meta,
html.pdm-dark .description {
    color: rgba(230,230,230,0.6) !important;
}

/* ── HEADER / NAV ───────────────────────────────────────────── */

html.pdm-dark header,
html.pdm-dark header[role="banner"],
html.pdm-dark nav,
html.pdm-dark nav[role="navigation"],
html.pdm-dark [data-test-id="header"],
html.pdm-dark .Header,
html.pdm-dark .topNav,
html.pdm-dark .zCH5,
html.pdm-dark .zI7,
html.pdm-dark .X8m,
html.pdm-dark .CCY,
html.pdm-dark .S9a,
html.pdm-dark .SHI,
html.pdm-dark .ujU {
    background: linear-gradient(180deg, ${surface} 0%, ${bg} 100%) !important;
    border-bottom: 1px solid rgba(255,255,255,0.05) !important;
    backdrop-filter: blur(20px) !important;
    -webkit-backdrop-filter: blur(20px) !important;
    color: #e6e6e6 !important;
}

/* ── CATEGORY / TAB BAR ─────────────────────────────────────── */

html.pdm-dark [role="tablist"],
html.pdm-dark div[role="navigation"] {
    background: ${surface} !important;
    border-bottom: 1px solid rgba(255,255,255,0.05) !important;
}

/* ── SEARCH ──────────────────────────────────────────────────── */

html.pdm-dark input,
html.pdm-dark textarea,
html.pdm-dark select,
html.pdm-dark input[type="search"],
html.pdm-dark input[placeholder*="Search"],
html.pdm-dark [data-test-id="search-box"],
html.pdm-dark .searchBox,
html.pdm-dark .SearchBox,
html.pdm-dark .XiG,
html.pdm-dark .tBJ,
html.pdm-dark .Jea,
html.pdm-dark .JME {
    background: rgba(28,28,30,0.95) !important;
    color: #e6e6e6 !important;
    border: 1px solid rgba(255,255,255,0.1) !important;
    backdrop-filter: blur(10px) !important;
    -webkit-backdrop-filter: blur(10px) !important;
}

html.pdm-dark input::placeholder,
html.pdm-dark textarea::placeholder {
    color: rgba(200,200,200,0.4) !important;
}

html.pdm-dark .SearchResults,
html.pdm-dark [data-test-id="search-results"],
html.pdm-dark .zI7.iyn,
html.pdm-dark .Jea .Jea {
    background: rgba(14,14,16,0.98) !important;
    border: 1px solid rgba(255,255,255,0.08) !important;
    backdrop-filter: blur(20px) !important;
    -webkit-backdrop-filter: blur(20px) !important;
}

/* ── PINS / CARDS ────────────────────────────────────────────── */

html.pdm-dark [data-test-id="pin"],
html.pdm-dark .pin,
html.pdm-dark .pinWrapper {
    background: transparent !important;
}

html.pdm-dark .XtM,
html.pdm-dark .YRc,
html.pdm-dark .KS5,
html.pdm-dark .Pj7 {
    background: ${surface} !important;
    border-color: rgba(255,255,255,0.06) !important;
}

html.pdm-dark .Modal,
html.pdm-dark .modal,
html.pdm-dark [data-test-id="closeup-body"],
html.pdm-dark [data-test-id="pin-closeup-modal"] {
    background: ${surface} !important;
    box-shadow: 0 8px 40px rgba(0,0,0,0.8) !important;
}

/* ── NEVER TOUCH MEDIA ───────────────────────────────────────── */

html.pdm-dark img,
html.pdm-dark video,
html.pdm-dark picture,
html.pdm-dark canvas {
    filter: none !important;
    background: transparent !important;
}

/* ── SVG ICONS ───────────────────────────────────────────────── */

html.pdm-dark svg:not(:root) {
    fill: #e6e6e6 !important;
    stroke: none !important;
    background: transparent !important;
}

/* ── SAVE BUTTON ─────────────────────────────────────────────── */

html.pdm-dark button[aria-label*="Save"],
html.pdm-dark [data-test-id="save-button"],
html.pdm-dark .zI7.iyn.Hsu,
html.pdm-dark .HnA {
    background: rgba(${acc},0.88) !important;
    color: #fff !important;
    font-weight: 600 !important;
    backdrop-filter: blur(4px) !important;
    -webkit-backdrop-filter: blur(4px) !important;
    border: 1px solid rgba(255,255,255,0.2) !important;
    box-shadow: 0 2px 8px rgba(0,0,0,0.4) !important;
    transition: transform 0.15s ease, box-shadow 0.15s ease !important;
}

html.pdm-dark button[aria-label*="Save"]:hover,
html.pdm-dark [data-test-id="save-button"]:hover,
html.pdm-dark .zI7.iyn.Hsu:hover,
html.pdm-dark .HnA:hover {
    background: rgba(${acc},0.98) !important;
    transform: translateY(-1px) !important;
    box-shadow: 0 4px 16px rgba(${acc},0.4) !important;
}

/* ── MENUS / DROPDOWNS / TOOLTIPS / DIALOGS ─────────────────── */

html.pdm-dark [role="dialog"],
html.pdm-dark [role="menu"],
html.pdm-dark [role="listbox"],
html.pdm-dark [role="tooltip"],
html.pdm-dark .Overlay,
html.pdm-dark .Tooltip,
html.pdm-dark .Popover,
html.pdm-dark .Dropdown,
html.pdm-dark .dropdown,
html.pdm-dark .Menu,
html.pdm-dark .menu,
html.pdm-dark .Picker,
html.pdm-dark .picker {
    background: rgba(12,12,14,0.97) !important;
    color: #e6e6e6 !important;
    border: 1px solid rgba(255,255,255,0.09) !important;
    backdrop-filter: blur(22px) !important;
    -webkit-backdrop-filter: blur(22px) !important;
    box-shadow: 0 8px 32px rgba(0,0,0,0.55) !important;
}

html.pdm-dark .RCK,
html.pdm-dark .Hsu,
html.pdm-dark .wsz,
html.pdm-dark .QhT,
html.pdm-dark .C9q,
html.pdm-dark [data-test-id="board-dropdown"],
html.pdm-dark [data-test-id="board-picker"],
html.pdm-dark [data-test-id="dropdown"],
html.pdm-dark [data-test-id="menu"],
html.pdm-dark [data-test-id="popover"],
html.pdm-dark [data-test-id="tooltip"] {
    background: rgba(13,13,15,0.98) !important;
    border: 1px solid rgba(255,255,255,0.1) !important;
    backdrop-filter: blur(22px) !important;
    -webkit-backdrop-filter: blur(22px) !important;
}

html.pdm-dark [role="menuitem"],
html.pdm-dark [role="option"] {
    background: transparent !important;
    color: #e6e6e6 !important;
}

html.pdm-dark [role="menuitem"]:hover,
html.pdm-dark [role="option"]:hover {
    background: rgba(255,255,255,0.07) !important;
}

/* ── PROFILE HEADER ──────────────────────────────────────────── */

html.pdm-dark .ProfilePageHeader,
html.pdm-dark [data-test-id="profile-header"],
html.pdm-dark .qiB,
html.pdm-dark [data-test-id="self-profile-header"] {
    background: ${bg} !important;
}

/* ── NOTIFICATION BADGE ──────────────────────────────────────── */

html.pdm-dark [data-test-id="notifications-count"],
html.pdm-dark .badge,
html.pdm-dark .Badge,
html.pdm-dark .notificationBadge {
    background: rgba(${acc},1) !important;
    color: #fff !important;
    border: 2px solid ${bg} !important;
}

/* ── INLINE STYLE OVERRIDES ──────────────────────────────────── */

html.pdm-dark [style*="background: rgb(255, 255, 255)"],
html.pdm-dark [style*="background: rgb(250, 250, 250)"],
html.pdm-dark [style*="background: rgb(249, 249, 249)"],
html.pdm-dark [style*="background-color: rgb(255, 255, 255)"],
html.pdm-dark [style*="background-color: rgb(250, 250, 250)"],
html.pdm-dark [style*="background-color: rgb(249, 249, 249)"],
html.pdm-dark [style*="background:#fff"],
html.pdm-dark [style*="background: #fff"],
html.pdm-dark [style*="background:#ffffff"],
html.pdm-dark [style*="background: #ffffff"] {
    background-color: ${surface} !important;
}

/* ── SCROLLBARS ──────────────────────────────────────────────── */

html.pdm-dark ::-webkit-scrollbar { width: 8px; height: 8px; }
html.pdm-dark ::-webkit-scrollbar-track  { background: ${bg}; }
html.pdm-dark ::-webkit-scrollbar-thumb  { background: rgba(255,255,255,0.12); border-radius: 8px; }
html.pdm-dark ::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.22); }
html.pdm-dark * { scrollbar-color: rgba(255,255,255,0.12) ${bg}; }

/* Moon button */
#pdm-btn {
    position: fixed;
    bottom: 24px;
    right: 24px;
    z-index: 2147483647;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    border: 1px solid rgba(255,255,255,0.14);
    background: rgba(18,18,20,0.92);
    color: #e6e6e6;
    font-size: 20px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 4px 18px rgba(0,0,0,0.5);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    transition: transform 0.16s ease, box-shadow 0.16s ease;
    padding: 0;
    line-height: 1;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
#pdm-btn:hover {
    transform: scale(1.1);
    box-shadow: 0 6px 24px rgba(0,0,0,0.65);
}
#pdm-btn.pdm-menu-open {
    background: rgba(38,38,42,0.98);
    border-color: rgba(255,255,255,0.22);
}

/* Settings card */
#pdm-menu {
    position: fixed;
    bottom: 80px;
    right: 24px;
    z-index: 2147483646;
    width: 220px;
    background: rgba(16,16,18,0.97);
    border: 1px solid rgba(255,255,255,0.1);
    border-radius: 16px;
    padding: 14px 16px 18px;
    box-shadow: 0 12px 40px rgba(0,0,0,0.7);
    backdrop-filter: blur(24px);
    -webkit-backdrop-filter: blur(24px);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    color: #e6e6e6;
    /* hide / show */
    opacity: 0;
    transform: translateY(8px) scale(0.97);
    pointer-events: none;
    transition: opacity 0.2s ease, transform 0.2s ease;
}
#pdm-menu.pdm-menu-visible {
    opacity: 1;
    transform: translateY(0) scale(1);
    pointer-events: all;
}

/* Section label */
.pdm-label {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: rgba(200,200,200,0.45);
    margin: 0 0 8px;
}

/* Divider */
.pdm-divider {
    height: 1px;
    background: rgba(255,255,255,0.07);
    margin: 14px 0;
}

/* THEME row */
.pdm-theme-row {
    display: flex;
    gap: 6px;
}
.pdm-theme-btn {
    flex: 1;
    padding: 7px 0;
    border-radius: 9px;
    border: 1px solid rgba(255,255,255,0.1);
    background: rgba(255,255,255,0.05);
    color: #bbb;
    font-size: 12px;
    cursor: pointer;
    text-align: center;
    transition: background 0.15s, border-color 0.15s, color 0.15s;
    line-height: 1.3;
}
.pdm-theme-btn:hover {
    background: rgba(255,255,255,0.1);
    color: #e6e6e6;
}
.pdm-theme-btn.pdm-active {
    background: rgba(255,255,255,0.14);
    border-color: rgba(255,255,255,0.3);
    color: #fff;
    font-weight: 600;
}

/* ACCENT row */
.pdm-accent-row {
    display: flex;
    gap: 5px;
    flex-wrap: wrap;
}
.pdm-accent-dot {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    border: 2px solid transparent;
    cursor: pointer;
    font-size: 17px;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: transform 0.14s ease, border-color 0.14s ease;
}
.pdm-accent-dot:hover {
    transform: scale(1.18);
}
.pdm-accent-dot.pdm-active {
    border-color: rgba(255,255,255,0.55);
    transform: scale(1.18);
}

/* CONTRAST slider */
.pdm-contrast-row {
    display: flex;
    gap: 5px;
}
.pdm-contrast-btn {
    flex: 1;
    padding: 6px 0;
    border-radius: 8px;
    border: 1px solid rgba(255,255,255,0.08);
    background: rgba(255,255,255,0.04);
    color: #aaa;
    font-size: 11px;
    cursor: pointer;
    text-align: center;
    transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.pdm-contrast-btn:hover {
    background: rgba(255,255,255,0.09);
    color: #e6e6e6;
}
.pdm-contrast-btn.pdm-active {
    background: rgba(255,255,255,0.13);
    border-color: rgba(255,255,255,0.28);
    color: #fff;
    font-weight: 600;
}

/* Close button — pinned to top-right corner of card */
#pdm-close {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    border: 1px solid rgba(255,255,255,0.1);
    background: rgba(255,255,255,0.06);
    color: #aaa;
    font-size: 14px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.14s, color 0.14s;
    padding: 0;
    line-height: 1;
}
#pdm-close:hover {
    background: rgba(255,255,255,0.12);
    color: #fff;
}

/* Toast */
#pdm-toast {
    position: fixed;
    bottom: 80px;
    right: 24px;
    z-index: 2147483645;
    background: rgba(18,18,20,0.95);
    color: #e6e6e6;
    border: 1px solid rgba(255,255,255,0.1);
    border-radius: 10px;
    padding: 7px 13px;
    font-size: 12px;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    box-shadow: 0 4px 20px rgba(0,0,0,0.5);
    pointer-events: none;
    opacity: 0;
    transform: translateY(6px);
    transition: opacity 0.2s ease, transform 0.2s ease;
}
#pdm-toast.pdm-show {
    opacity: 1;
    transform: translateY(0);
}

`;
    }  // end buildCSS()

    const StyleManager = {

        inject() {
            this.remove();   // always rebuild from current state
            if (typeof GM_addStyle === 'function') {
                GM_addStyle(buildCSS());
                const styles = document.querySelectorAll('style');
                const el = styles[styles.length - 1];
                if (el) el.id = ID.STYLE;
            } else {
                this._createElement();
            }
        },

        _createElement() {
            const el = document.createElement('style');
            el.id = ID.STYLE;
            el.textContent = buildCSS();
            (document.head || document.documentElement).appendChild(el);
        },

        remove() {
            const el = document.getElementById(ID.STYLE);
            if (el) el.remove();
        },

        apply() {
            const html = document.documentElement;
            if (enabled) {
                html.classList.add(CLS);
                this.inject();
            } else {
                html.classList.remove(CLS);
                this.remove();
            }
        },

        ensureAlive() {
            if (!enabled) return;
            if (!document.getElementById(ID.STYLE)) this._createElement();
            if (!document.documentElement.classList.contains(CLS))
                document.documentElement.classList.add(CLS);
        },

        fixInlineStyles() {
            if (!enabled) return;
            const WHITE = ['rgb(255, 255, 255)', 'rgb(250, 250, 250)', 'rgb(249, 249, 249)'];
            const surface = surfaceFromContrast();
            document.querySelectorAll('*').forEach(el => {
                if (['IMG','VIDEO','CANVAS'].includes(el.tagName)) return;
                const bg = el.style.backgroundColor || el.style.background;
                if (bg && WHITE.some(w => bg.includes(w)))
                    el.style.setProperty('background-color', surface, 'important');
            });
        },

        fixHeader() {
            if (!enabled) return;
            const bg      = bgFromContrast();
            const surface = surfaceFromContrast();
            const sels = [
                'header[role="banner"]', 'nav[role="navigation"]',
                '[data-test-id="header"]',
                '.zCH5','.zI7','.X8m','.CCY','.S9a','.SHI','.ujU',
            ];
            sels.forEach(sel => {
                document.querySelectorAll(sel).forEach(el => {
                    el.style.setProperty('background', `linear-gradient(180deg,${surface},${bg})`, 'important');
                    el.style.setProperty('backdrop-filter', 'blur(20px)', 'important');
                    el.style.setProperty('-webkit-backdrop-filter', 'blur(20px)', 'important');
                });
            });
        },

        fixSearchInputs() {
            if (!enabled) return;
            ['input[type="search"]','input[placeholder*="Search"]','[data-test-id="search-box"]']
                .forEach(sel => {
                    document.querySelectorAll(sel).forEach(el => {
                        el.style.setProperty('background', 'rgba(28,28,30,0.95)', 'important');
                        el.style.setProperty('color', '#e6e6e6', 'important');
                    });
                });
        },
    };

    const Observer = {
        _obs: null, _raf: null,
        start() {
            this._obs = new MutationObserver(() => {
                if (this._raf) return;
                this._raf = requestAnimationFrame(() => {
                    this._raf = null;
                    StyleManager.ensureAlive();
                    StyleManager.fixInlineStyles();
                });
            });
            this._obs.observe(document.documentElement, {
                childList: true, subtree: true,
                attributes: true, attributeFilter: ['style','class'],
            });
        },
        stop() {
            if (this._obs) { this._obs.disconnect(); this._obs = null; }
            if (this._raf) { cancelAnimationFrame(this._raf); this._raf = null; }
        },
    };

    let fixerInterval = null;

    function startFixer() {
        if (fixerInterval) return;
        fixerInterval = setInterval(() => {
            StyleManager.fixHeader();
            StyleManager.fixSearchInputs();
            StyleManager.fixInlineStyles();
        }, 2500);
    }

    function stopFixer() {
        clearInterval(fixerInterval);
        fixerInterval = null;
    }

    function showToast(msg) {
        let t = document.getElementById(ID.TOAST);
        if (!t) {
            t = document.createElement('div');
            t.id = ID.TOAST;
            document.body.appendChild(t);
        }
        t.textContent = msg;
        t.classList.add('pdm-show');
        clearTimeout(t._timer);
        t._timer = setTimeout(() => t.classList.remove('pdm-show'), 1800);
    }

    let menuOpen = false;

    function buildMenu() {
        if (document.getElementById(ID.MENU)) return;

        const menu = document.createElement('div');
        menu.id = ID.MENU;

        menu.innerHTML = `

            <!-- CLOSE — absolutely positioned top-right -->
            <button id="pdm-close">✕</button>

            <!-- THEME -->
            <p class="pdm-label">Theme</p>
            <div class="pdm-theme-row">
                <button class="pdm-theme-btn" data-theme="light">☀️<br>Light</button>
                <button class="pdm-theme-btn" data-theme="dark">🌙<br>Dark</button>
            </div>

            <div class="pdm-divider"></div>

            <!-- ACCENT -->
            <p class="pdm-label">Accent colour</p>
            <div class="pdm-accent-row" id="pdm-accent-row"></div>

            <div class="pdm-divider"></div>

            <!-- CONTRAST -->
            <p class="pdm-label">Contrast</p>
            <div class="pdm-contrast-row">
                <button class="pdm-contrast-btn" data-contrast="0">Soft</button>
                <button class="pdm-contrast-btn" data-contrast="1">Mid</button>
                <button class="pdm-contrast-btn" data-contrast="2">AMOLED</button>
            </div>
        `;

        document.body.appendChild(menu);

        // Populate accent dots
        const accentRow = menu.querySelector('#pdm-accent-row');
        ACCENTS.forEach((a, i) => {
            const dot = document.createElement('button');
            dot.className = 'pdm-accent-dot' + (i === accentIndex ? ' pdm-active' : '');
            dot.textContent = a.label;
            dot.title = a.label;
            dot.addEventListener('click', () => setAccent(i));
            accentRow.appendChild(dot);
        });

        // Theme buttons
        menu.querySelectorAll('.pdm-theme-btn').forEach(btn => {
            const t = btn.dataset.theme;
            if ((t === 'dark') === enabled) btn.classList.add('pdm-active');
            btn.addEventListener('click', () => {
                const wantDark = t === 'dark';
                if (enabled !== wantDark) toggleEnabled();
                refreshMenuState();
            });
        });

        // Contrast buttons
        menu.querySelectorAll('.pdm-contrast-btn').forEach(btn => {
            const c = parseInt(btn.dataset.contrast);
            if (c === contrastLevel) btn.classList.add('pdm-active');
            btn.addEventListener('click', () => setContrast(c));
        });

        // Close button
        menu.querySelector('#pdm-close').addEventListener('click', closeMenu);
    }

    function refreshMenuState() {
        const menu = document.getElementById(ID.MENU);
        if (!menu) return;

        // Theme buttons
        menu.querySelectorAll('.pdm-theme-btn').forEach(btn => {
            btn.classList.toggle('pdm-active', (btn.dataset.theme === 'dark') === enabled);
        });

        // Accent dots
        menu.querySelectorAll('.pdm-accent-dot').forEach((dot, i) => {
            dot.classList.toggle('pdm-active', i === accentIndex);
        });

        // Contrast
        menu.querySelectorAll('.pdm-contrast-btn').forEach(btn => {
            btn.classList.toggle('pdm-active', parseInt(btn.dataset.contrast) === contrastLevel);
        });
    }

    function openMenu() {
        buildMenu();
        menuOpen = true;
        document.getElementById(ID.BTN).classList.add('pdm-menu-open');
        requestAnimationFrame(() => {
            document.getElementById(ID.MENU).classList.add('pdm-menu-visible');
        });
    }

    function closeMenu() {
        menuOpen = false;
        const btn  = document.getElementById(ID.BTN);
        const menu = document.getElementById(ID.MENU);
        if (btn)  btn.classList.remove('pdm-menu-open');
        if (menu) menu.classList.remove('pdm-menu-visible');
    }

    function toggleMenu() {
        menuOpen ? closeMenu() : openMenu();
    }

    function toggleEnabled() {
        enabled = !enabled;
        GM_setValue(KEY.ENABLED, enabled);
        StyleManager.apply();
        if (enabled) { startFixer(); Observer.start(); doFixes(); }
        else          { stopFixer(); Observer.stop(); }
        showToast(enabled ? 'Dark mode ON' : 'Dark mode OFF');
    }

    function setAccent(i) {
        accentIndex = i;
        GM_setValue(KEY.ACCENT, i);
        StyleManager.apply();
        refreshMenuState();
    }

    function setContrast(c) {
        contrastLevel = c;
        GM_setValue(KEY.CONTRAST, c);
        StyleManager.apply();
        refreshMenuState();
        if (enabled) doFixes();
    }

    function doFixes() {
        setTimeout(() => {
            StyleManager.fixHeader();
            StyleManager.fixSearchInputs();
            StyleManager.fixInlineStyles();
        }, 120);
    }

    function createButton() {
        if (document.getElementById(ID.BTN)) return;
        const btn = document.createElement('button');
        btn.id = ID.BTN;
        btn.title = 'Pinterest Dark Mode settings';
        btn.textContent = '🌙';
        btn.addEventListener('click', (e) => {
            e.stopPropagation();
            toggleMenu();
        });
        document.body.appendChild(btn);
    }

    // Close menu when clicking outside
    document.addEventListener('click', (e) => {
        if (!menuOpen) return;
        const menu = document.getElementById(ID.MENU);
        const btn  = document.getElementById(ID.BTN);
        if (menu && !menu.contains(e.target) && btn && !btn.contains(e.target)) {
            closeMenu();
        }
    });

    window.addEventListener('scroll', () => {
        if (enabled) StyleManager.fixHeader();
    }, { passive: true });

    if (typeof GM_registerMenuCommand === 'function') {
        GM_registerMenuCommand('Pinterest Dark Mode Settings', toggleMenu);
    }

    // Apply CSS immediately before page paint
    StyleManager.apply();

    function onReady() {
        createButton();
        if (enabled) {
            doFixes();
            startFixer();
            Observer.start();
        }
    }

    window.addEventListener('load', () => {
        if (enabled) {
            StyleManager.apply();
            doFixes();
        }
    });

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', onReady, { once: true });
    } else {
        onReady();
    }

})();