Webtoon Dark Mode

Switch Webtoons background to black for a more comfortable reading experience.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==UserScript==
// @name         Webtoon Dark Mode
// @name:zh-TW   Webtoon 深色模式
// @name:zh-CN   Webtoon 深色模式
// @name:ja      Webtoon ダークモード
// @name:ko      웹툰 다크 모드
// @namespace    http://tampermonkey.net/
// @version      3.2
// @description  Switch Webtoons background to black for a more comfortable reading experience.
// @description:zh-TW 將 Webtoons 網頁背景轉換為黑色,提供舒適的閱讀體驗
// @description:zh-CN 将 Webtoons 网页背景转换为黑色,提供舒适的阅读体验
// @description:ja Webtoonのウェブ背景を黒に変更し、快適な読書体験を提供します。
// @description:ko 웹툰 웹페이지 배경을 블랙으로 전환하여 더욱 편안한 감상 경험을 제공합니다.
// @author       Hzbrrbmin + Gemini
// @match        https://www.webtoons.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=webtoons.com
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    const css = `
        /* 1. 基礎背景與文字顏色設定 */
        html, body, #wrap, #container, #content, .left_area, .right_area, .detail_body, .detail_header, .viewer_header {
            background-color: #121212 !important;
            color: #e0e0e0 !important;
        }

        /* 2. 頂部與底部導航 */
        #header, #footer {
            background-color: #000000 !important;
            border-bottom: 1px solid #333 !important;
            border-top: 1px solid #333 !important;
        }

        /* 3. 閱讀器背景 */
        #viewer_wrapper, .viewer_lst .viewer_img, #viewer, .viewer_img {
            background-color: #000000 !important;
        }

        /* 4. 確保圖片透明 */
        img {
            background-color: transparent !important;
        }

        /* 5. 文字與連結顏色 */
        a, h1, h2, h3, h4, span, p, .subj, .sub_title, .author, .date, .tx, .info_area .title {
            color: #e0e0e0 !important;
        }

        /* 6. 處理特定區塊白色殘留與背景漸層 */
        #bottomEpisodeList.episode_area,
        #noticeArea.notice_area,
        .foot_app,
        .snb_wrap,
        .viewer_info_area,
        #container.bg,
        .cont_box,
        .detail_body.banner,
        .detail_body.challenge,
        .detail_body.banner .detail_lst,
        .detail_body.challenge .detail_lst,
        .episode_lst,
        .discover_lst,
        .ct_box .cont_box2 .inner_wrap,
        .redeem_wrap .redeem_area,
        .notice_area2 {
            background-color: #121212 !important;
            background-image: none !important;
            background: #121212 !important;
            border-color: #333 !important;
        }

        .discover_lst li { background-color: #121212 !important; }

        /* 7. 移除官方漸層遮罩 */
        .bg_detail, .detail_body:before { background: none !important; }

        /* =============== 集數列表懸浮反白問題 =============== */

        .episode_lst li:hover, .episode_lst li a:hover, .episode_lst li.hover > a,
        .discover_lst li:hover, .discover_lst li a:hover,
        html body .detail_body .detail_lst ul#_listUl li._episodeItem:hover,
        html body .detail_body .detail_lst ul#_listUl li._episodeItem:hover > a,
        html body .detail_body .detail_lst ul#_listUl li._episodeItem a:hover,
        html body .detail_body .detail_lst ul#_listUl li._episodeItem.on,
        html body .detail_body .detail_lst ul#_listUl li._episodeItem.on > a {
            background-color: #222222 !important;
            background: #222222 !important;
            background-image: none !important;
            border-color: #333 !important;
        }

        /* 徹底關閉並清空官方藏在這裡的隱形遮罩 */
        .episode_lst li:hover::after, .episode_lst li:hover::before,
        .episode_lst li a:hover::after, .episode_lst li a:hover::before,
        .discover_lst li:hover::after, .discover_lst li:hover::before,
        html body .detail_body .detail_lst ul#_listUl li._episodeItem::after,
        html body .detail_body .detail_lst ul#_listUl li._episodeItem::before,
        html body .detail_body .detail_lst ul#_listUl li._episodeItem a::after,
        html body .detail_body .detail_lst ul#_listUl li._episodeItem a::before {
            display: none !important;
            background: none !important;
            content: none !important;
        }

        /* 強制懸浮時內部的文字也保持淺色 */
        .episode_lst li:hover *, .episode_lst li a:hover *, .discover_lst li:hover *,
        html body .detail_body .detail_lst ul#_listUl li._episodeItem:hover *,
        html body .detail_body .detail_lst ul#_listUl li._episodeItem a:hover * {
            color: #e0e0e0 !important;
        }

        /* =============== 彈出視窗 (Modals / Dialogs) =============== */

        .ly_wrap .ly_box, .ly_box {
            background-color: #1e1e1e !important;
            border: 1px solid #333 !important;
            box-shadow: 0 4px 12px rgba(0,0,0,0.5) !important;
        }
        .ly_wrap .ly_box *, .ly_box * { color: #e0e0e0 !important; }

        /* =============== 帳號、登入與表單區塊 =============== */

        .ly_loginbox, .ly_loginbox .loginbox_cont { background-color: #1e1e1e !important; border-color: #333 !important; }
        .ly_loginbox .loginbox_cont li { border-color: #333 !important; }
        .ly_loginbox .loginbox_cont li a, .ly_loginbox .loginbox_cont li button { color: #e0e0e0 !important; background-color: transparent !important; }
        .ly_loginbox .loginbox_cont li:hover { background-color: #2a2a2a !important; }
        .ly_loginbox .loginbox_cont li:hover a, .ly_loginbox .loginbox_cont li:hover button { color: #ffffff !important; }

        .account_wrap, .account_wrap .account_area, #nicknameDefaultArea, #nicknameEditArea {
            background-color: #121212 !important; background-image: none !important; border-color: #333 !important;
        }
        .account_wrap *, .account_area * { color: #e0e0e0 !important; }

        .account_area .change_btn,
        .account_area .edit_btn,
        .account_area .check_btn {
            color: #dddddd !important;
            background-color: transparent !important;
            border: 1px solid rgba(255, 255, 255, 0.4) !important;
            transition: all 0.2s ease !important;
        }

        .account_area .change_btn:hover,
        .account_area .edit_btn:hover,
        .account_area .check_btn:hover {
            color: #ffffff !important;
            border-color: #ffffff !important;
            background-color: rgba(255, 255, 255, 0.08) !important;
        }

        .input_box input,
        input.input_account,
        .redeem_area input[type="text"] {
            background-color: #1a1a1a !important;
            color: #ffffff !important;
            border: 1px solid #444 !important;
        }
        .input_box input:focus, input.input_account:focus, .redeem_area input[type="text"]:focus {
            outline: none !important;
            border-color: #888 !important;
        }

        /* =============== 公告表格 (Notice Table) =============== */

        .tb_notice, .tb_notice th, .tb_notice td, .tb_notice tbody tr {
            background-color: #121212 !important;
            border-color: #333 !important;
            color: #e0e0e0 !important;
        }

        .tb_notice tbody tr:hover, .tb_notice tbody tr:hover td {
            background-color: #2a2a2a !important;
        }

        /* =============== 側邊欄「評分區」 =============== */

        #_asideDetail.aside.detail .grade_area, .aside .grade_area { background: transparent !important; }
        #_asideDetail.aside.detail .grade_area *, .aside .grade_area * { color: #e0e0e0 !important; }
        .aside .grade_area [class*="star"], .aside .grade_area [class*="ico"] { filter: invert(1) brightness(2) !important; }

        /* =============== 分享區與各種「加入最愛」按鈕處理 =============== */

        .spi_area { background: transparent !important; border: none !important; }

        #likeItButton,
        #footer_favorites,
        .detail_header .btn_favorite {
            color: #dddddd !important;
            background-color: transparent !important;
            border: 1px solid rgba(255, 255, 255, 0.4) !important;
            opacity: 1 !important;
            transition: all 0.2s ease !important;
            box-sizing: border-box !important;
        }

        #likeItButton:not(.on) [class*="ico"],
        #footer_favorites:not(.on) [class*="ico"],
        .detail_header .btn_favorite:not(.on) [class*="ico"] { filter: brightness(0) invert(1) opacity(0.8) !important; }

        #likeItButton:hover, #footer_favorites:hover, .detail_header .btn_favorite:hover {
            color: #ffffff !important; border-color: #ffffff !important; background-color: rgba(255, 255, 255, 0.08) !important;
        }
        #likeItButton:hover [class*="ico"], #footer_favorites:hover [class*="ico"], .detail_header .btn_favorite:hover [class*="ico"] {
            filter: brightness(0) invert(1) opacity(1) !important;
        }

        #likeItButton.on, #footer_favorites.on, .detail_header .btn_favorite.on {
            color: #ffffff !important; border-color: #ffffff !important;
        }
        #likeItButton.on [class*="ico"], #footer_favorites.on [class*="ico"], #footer_favorites.on .ico_plus3, .detail_header .btn_favorite.on [class*="ico"] {
            filter: brightness(0) invert(1) opacity(1) !important;
        }

        #likeItButton *, #footer_favorites *, .detail_header .btn_favorite * { color: inherit; }

        /* =============== 留言區與編輯器 =============== */

        .wcc_ReplyFolder__root { background-color: #121212 !important; border-top: 1px solid #333 !important; }
        .wcc_ReplyFolder__root * { color: #e0e0e0 !important; }

        .wcc_Editor__root, .TextEditor_EditorCore-module__root {
            background-color: #1a1a1a !important; border: 1px solid #444 !important; border-radius: 6px !important;
        }
        .wcc_Editor__root *, .TextEditor_EditorCore-module__root * { color: #ffffff !important; }

        .lk_lang._selectedLanguage, .wcc_ReplyFolderToggle__root, .wcc_CommentReaction__root, .wcc_CommentReaction__action {
            color: #cccccc !important; opacity: 1 !important; background: transparent !important;
        }
        .lk_lang._selectedLanguage:hover, .wcc_ReplyFolderToggle__root:hover, .wcc_CommentReaction__action:hover { color: #ffffff !important; }

        .wcc_CommentItem__root, .wcc_CommentList__list { border-color: #333 !important; }

        /* =============== 底部語言選擇下拉選單 =============== */

        html body #footer .foot_menu .language .ly_lang {
            background-color: #1e1e1e !important;
            border: 1px solid #333 !important;
            box-shadow: 0 -4px 12px rgba(0, 0, 0, 0.5) !important;
        }
        html body #footer .foot_menu .language .ly_lang li { border-color: #333 !important; }
        html body #footer .foot_menu .language .ly_lang li a { color: #e0e0e0 !important; background-color: transparent !important; transition: all 0.2s ease !important; }
        html body #footer .foot_menu .language .ly_lang li:hover { background-color: #2a2a2a !important; }
        html body #footer .foot_menu .language .ly_lang li:hover a { color: #ffffff !important; }

        /* =============== 頂部搜尋框 (Search Area) =============== */

        /* 將搜尋框外層與背景黑化 */
        html body #header .search_area,
        html body #header .search_area._searchArea {
            background-color: #1a1a1a !important;
            border: 1px solid #444 !important;
        }

        /* 確保輸入框內打字的背景是透明/深色,且文字為白色 */
        html body #header .search_area input[type="text"] {
            background-color: transparent !important;
            color: #ffffff !important;
        }

        /* 如果有自動完成的下拉選單 (Autocomplete list),一併黑化 */
        html body #header .search_area .auto_lst {
            background-color: #1e1e1e !important;
            border: 1px solid #333 !important;
            box-shadow: 0 4px 12px rgba(0,0,0,0.5) !important;
        }
        html body #header .search_area .auto_lst li a {
            color: #e0e0e0 !important;
        }
        html body #header .search_area .auto_lst li:hover {
            background-color: #2a2a2a !important;
        }

        /* 搜尋按鈕圖示 (通常是黑色的放大鏡雪碧圖),強制反白提亮 */
        html body #header .search_area .btn_search,
        html body #header .search_area [class*="ico_search"] {
            filter: invert(1) brightness(2) !important;
        }
        /* =============== 搜尋框內層容器 (Input Box 夾心層) =============== */

        /* 針對頂部搜尋框與獨立搜尋頁面的「內層輸入框容器」強制黑化 */
        html body #searchWrap .big_search.search_area .input_box,
        html body #header .search_area .input_box,
        html body .search_area._searchArea .input_box._inputArea {
            background-color: #1a1a1a !important; /* 配合外層的深灰色 */
            background-image: none !important;
            border-color: #444 !important;
        }

        /* 確保超大搜尋框 (big_search) 的輸入文字也是白色的 */
        html body #searchWrap .big_search.search_area input[type="text"] {
            background-color: transparent !important;
            color: #ffffff !important;
        }

        /* 獨立搜尋頁面的超大放大鏡按鈕也一起反白提亮 */
        html body #searchWrap .big_search.search_area .btn_search {
            filter: invert(1) brightness(2) !important;
        }

        /* =============== 超大搜尋框啟動狀態 (Active/On 狀態) =============== */
        /* 針對獨立搜尋頁面,當滑鼠點擊正在輸入時的背景強制黑化 */
        html body #searchWrap .big_search.search_area.on {
            background-color: #1a1a1a !important;
            border-color: #555 !important; /* 邊框稍微亮一點點,提示正在輸入 */
            box-shadow: 0 0 8px rgba(255, 255, 255, 0.1) !important; /* 加一點微弱的光暈代替原本的白底 */
        }

        /* =============== 搜尋自動完成下拉選單 (Autocomplete) 懸浮反白 =============== */

        /* 1. 確保自動完成下拉選單整體的底色與邊框是深色 */
        html body .search_area .ly_autocomplete._searchLayer {
            background-color: #1e1e1e !important;
            border: 1px solid #333 !important;
            box-shadow: 0 4px 12px rgba(0,0,0,0.5) !important;
        }

        /* 2. 清除選單內選項預設的白底,並確保文字為淺色 */
        html body .search_area .ly_autocomplete._searchLayer li {
            background-color: transparent !important;
        }
        html body .search_area .ly_autocomplete._searchLayer li a.link {
            color: #e0e0e0 !important;
        }

        /* 3. 針對你提供的精準路徑:強制覆蓋懸浮 (Hover) 狀態的背景為深灰色 */
        html body .search_area .ly_autocomplete._searchLayer ul.list_autocomplete li:hover,
        html body .search_area .ly_autocomplete._searchLayer ul.list_autocomplete li:hover > a,
        html body .search_area .ly_autocomplete._searchLayer ul.list_autocomplete li a.link:hover {
            background-color: #2a2a2a !important;
            background-image: none !important;
        }

        /* 4. 確保懸浮時裡面的關鍵字 (包含被高亮標記的字) 不會反黑,且背景透明 */
        html body .search_area .ly_autocomplete._searchLayer ul.list_autocomplete li:hover *,
        html body .search_area .ly_autocomplete._searchLayer ul.list_autocomplete li a.link:hover * {
            color: #ffffff !important;
            background-color: transparent !important;
        }

        /* =============== 搜尋歷史紀錄與創作者清單懸浮反白 =============== */

        /* 1. 確保歷史紀錄面板整體的底色與邊框是深色 */
        html body #header .search_area ul#gnb_search_box.ly_autocomplete._searchLayer._searchHistory,
        html body #searchWrap .search_area div#search_box.ly_autocomplete._searchLayer._searchHistory {
            background-color: #1e1e1e !important;
            border: 1px solid #333 !important;
            box-shadow: 0 4px 12px rgba(0,0,0,0.5) !important;
        }

        /* 2. 針對創作者 (list_creator) 與歷史紀錄 (lst_history) 的選項強制懸浮黑化 */
        html body .search_area .ly_autocomplete._searchLayer ul.list_creator li:hover,
        html body .search_area .ly_autocomplete._searchLayer ul.list_creator li a:hover,
        html body .search_area .ly_autocomplete._searchLayer ul.lst_history li:hover,
        html body .search_area .ly_autocomplete._searchLayer ul.lst_history li a:hover {
            background-color: #2a2a2a !important;
            background-image: none !important;
        }

        /* 3. 確保這些清單內的文字 (包含歷史紀錄旁邊的刪除叉叉) 懸浮時依然是清晰的白色 */
        html body .search_area .ly_autocomplete._searchLayer ul.list_creator li:hover *,
        html body .search_area .ly_autocomplete._searchLayer ul.list_creator li a:hover *,
        html body .search_area .ly_autocomplete._searchLayer ul.lst_history li:hover *,
        html body .search_area .ly_autocomplete._searchLayer ul.lst_history li a:hover * {
            color: #ffffff !important;
            background-color: transparent !important;
        }

    `;

    const style = document.createElement('style');
    style.type = 'text/css';
    style.appendChild(document.createTextNode(css));
    document.head.appendChild(style);

    /* =============== 解除右鍵與複製封印補丁 =============== */

    // 1. 強制解除 CSS 的文字與圖片選取限制
    const unblockCss = `
        * {
            -webkit-user-select: auto !important;
            -moz-user-select: auto !important;
            -ms-user-select: auto !important;
            user-select: auto !important;
            -webkit-touch-callout: default !important;
        }
    `;
    const unblockStyle = document.createElement('style');
    unblockStyle.type = 'text/css';
    unblockStyle.appendChild(document.createTextNode(unblockCss));
    document.head.appendChild(unblockStyle);

    // 2. 在「捕獲階段 (Capture Phase)」攔截並消除官方的阻擋事件
    const blockedEvents = ['contextmenu', 'selectstart', 'dragstart', 'copy', 'cut'];
    blockedEvents.forEach(eventName => {
        document.addEventListener(eventName, function(e) {
            e.stopPropagation(); // 阻止事件傳遞給 Webtoon 的阻擋程式
        }, true);
    });

    // 3. 清除直接綁定在 HTML 標籤上的舊式阻擋屬性
    document.oncontextmenu = null;
    document.body.oncontextmenu = null;
    document.ondragstart = null;
    document.body.ondragstart = null;

})();