원클릭 다크모드 (Ctrl+Q / Alt+Q)

Ctrl+Q 또는 Alt+Q으로 네이버등의 웹사이트를 다크모드로 전환할 수 있다.

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name         Universal Dark Mode Toggle (Ctrl+Q / Alt+Q)
// @name:ko  원클릭 다크모드 (Ctrl+Q / Alt+Q)
// @namespace    https://github.com/csy8
// @version      1.3
// @description  Toggle dark mode on any website using Ctrl+Q or Alt+Q, or Tampermonkey toolbar menu (Global CSS Override)
// @description:ko  Ctrl+Q 또는 Alt+Q으로 네이버등의 웹사이트를 다크모드로 전환할 수 있다.
// @author       csy8
// @match        *://*/*
// @grant        GM_addStyle
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// @run-at       document-start
// @license MIT
// ==/UserScript==

(function () {
    'use strict';

    try {
        console.log("[Universal Dark Mode] Script Initialized");

        const STORAGE_KEY = 'tm_universal_dark_mode';

        // CSS for Dark Mode
        // Using GM_addStyle for reliable injection
        const DARK_CSS = `
            /* Force dark background and light text on everything */
            html, body, div, table, tr, td, th, ul, li, dl, dt, dd, h1, h2, h3, h4, h5, h6, pre, form, fieldset, input, textarea, p, blockquote, th {
                background-color: #1e1e1e !important;
                color: #d4d4d4 !important;
                border-color: #444 !important;
            }

            /* Wildcard to change EVERYTHING else */
            * {
                background-color: inherit !important;
                color: inherit !important;
                border-color: inherit !important;
                box-shadow: none !important;
                text-shadow: none !important;
            }

            /* Fix links */
            a, a * {
                color: #8ab4f8 !important;
                background-color: transparent !important;
                text-decoration-color: #8ab4f8 !important;
            }

            /* Preserve inputs, images, videos */
            input, textarea, select, button {
                background-color: #2d2d2d !important;
                color: #fff !important;
                border: 1px solid #555 !important;
            }
            /* Revert: Background transparent as per user request */
            img, video, iframe, canvas, svg, embed, object {
                background-color: transparent !important;
                border-radius: 4px !important;
                filter: brightness(0.9) !important;
            }

            /* Fix: Make empty elements transparent to avoid blocking images */
            /* This fixes the black box issue on Naver thumbnails where an overlay/mask div covers the image */
            div:empty, span:empty, a:empty {
                background-color: transparent !important;
            }

            /* Scrollbars */
            ::-webkit-scrollbar { width: 12px; }
            ::-webkit-scrollbar-track { background: #1e1e1e; }
            ::-webkit-scrollbar-thumb { background: #555; border-radius: 6px; }
            * { scrollbar-color: #555 #1e1e1e; }
        `;

        let isDark = GM_getValue(STORAGE_KEY, false);
        let styleElement = null;

        function toggleDarkMode(enable) {
            console.log("[Universal Dark Mode] Toggling to:", enable);
            if (enable) {
                if (!styleElement) {
                    styleElement = GM_addStyle(DARK_CSS);
                }
            } else {
                if (styleElement) {
                    styleElement.remove(); // GM_addStyle returns the <style> element
                    styleElement = null;
                }
            }
            isDark = enable;
            GM_setValue(STORAGE_KEY, enable);
        }

        // Apply immediately if enabled
        if (isDark) {
            toggleDarkMode(true);
        }

        // Keyboard Listener
        document.addEventListener('keydown', (e) => {
            // Check for Ctrl + Q
            if (e.ctrlKey && e.key.toLowerCase() === 'q') {
                console.log("[Universal Dark Mode] Ctrl+Q detected");
                e.preventDefault();
                e.stopPropagation();
                toggleDarkMode(!styleElement);
                // Visual feedback (optional)
                // alert("Dark Mode Toggled");
            }
            // Backup Alt + Q
            else if (e.altKey && e.key.toLowerCase() === 'q') {
                e.preventDefault();
                toggleDarkMode(!styleElement);
            }
        });

        // Register Menu Command
        GM_registerMenuCommand("Toggle Dark Mode (Manual)", () => {
            toggleDarkMode(!styleElement);
        });

        // Debug Menu Command
        GM_registerMenuCommand("Force Enable (Debug)", () => {
            toggleDarkMode(true);
            alert("Dark mode forced ON. Check console for errors.");
        });

    } catch (err) {
        console.error("[Universal Dark Mode] CRITICAL ERROR:", err);
        alert("Dark Mode Script Error: " + err);
    }

})();