Sinflix Modifier

Enhances SinFlix pages with Google & MyDramaList search icons, BuzzHeavier ID auto-linking, back-to-top button, inline search, customizable section ordering, and a SinFlix chat button. On pst.moe: clickable links, copy-all-links per resolution, and Mega.nz bypass circles (click to instantly bypass & download, or copy all bypass links). On mega.nz file pages: floating bypass download button that skips Mega quota limits.

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Sinflix Modifier
// @namespace    https://greasyfork.org/en/users/1490967-asurpbs
// @version      26.4.17.1
// @description  Enhances SinFlix pages with Google & MyDramaList search icons, BuzzHeavier ID auto-linking, back-to-top button, inline search, customizable section ordering, and a SinFlix chat button. On pst.moe: clickable links, copy-all-links per resolution, and Mega.nz bypass circles (click to instantly bypass & download, or copy all bypass links). On mega.nz file pages: floating bypass download button that skips Mega quota limits.
// @license      MIT
// @author       asurpbs
// @match        https://rentry.co/sin-flix
// @match        https://text.is/Sinflix
// @match        https://pst.moe/paste/*
// @match        https://buzzheavier.com/*
// @match        https://mega.nz/file/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addStyle
// @grant        GM_xmlhttpRequest
// @run-at       document-start
// @copyright    2026, mthlpbs (https://greasyfork.org/en/users/1490967-asurpbs)
// ==/UserScript==

(function() {
    'use strict';

    // --- Configuration ---
    const config = {
        showGoogleCircle: GM_getValue('showGoogleCircle', true),
        showMdlCircle: GM_getValue('showMdlCircle', true),
        convertBuzzheavierLinks: GM_getValue('convertBuzzheavierLinks', true),
        showBackToTopButton: GM_getValue('showBackToTopButton', true),
        // NEW: Add setting for link opening style, defaulting to 'popup'
        linkOpenStyle: GM_getValue('linkOpenStyle', 'popup'),
        // NEW: Add setting for moving Currently Airing to top
        moveCurrentlyAiringToTop: GM_getValue('moveCurrentlyAiringToTop', false),
        // NEW: Add setting for SinFlix chat box button
        showChatBoxButton: GM_getValue('showChatBoxButton', true),
        // NEW: Add setting for chat box opening style, defaulting to 'tab'
        chatBoxOpenStyle: GM_getValue('chatBoxOpenStyle', 'popup'),
        // NEW: pst.moe enhancements
        pstMoeEnhancements: GM_getValue('pstMoeEnhancements', true),
        // NEW: Google search keyword suffix
        googleSearchSuffix: GM_getValue('googleSearchSuffix', 'TV Series'),
        // NEW: Buzzheavier enhancements
        buzzheavierEnhancements: GM_getValue('buzzheavierEnhancements', false),
        buzzSplitQuality: GM_getValue('buzzSplitQuality', false),
        buzzDirectDownload: GM_getValue('buzzDirectDownload', false),
        buzzCopyLinks: GM_getValue('buzzCopyLinks', false),
        // NEW: Mega.nz bypass
        megaBypass: GM_getValue('megaBypass', true),
        // NEW: Mega.nz floating download button
        megaNzButton: GM_getValue('megaNzButton', true),
        // NEW: Top search bar with Dynamic Island animation
        showTopSearchBar: GM_getValue('showTopSearchBar', true)
    };

    // --- Style Definitions ---
    GM_addStyle(`
        /* --- Buzzheavier Tool Buttons --- */
        .bh-actions {
            display: inline-flex;
            gap: 4px;
            margin-left: 12px;
            vertical-align: middle;
            opacity: 0.7;
            transition: opacity 0.2s ease;
        }
        .bh-actions.single-page {
            opacity: 0.9;
            margin-left: 8px;
        }
        .bh-actions.single-page:hover {
            opacity: 1;
        }
        tr.editable:hover .bh-actions {
            opacity: 1;
        }
        .bh-btn {
            cursor: pointer;
            border: none;
            background: transparent;
            padding: 4px;
            border-radius: 6px;
            display: flex;
            align-items: center;
            justify-content: center;
            color: inherit;
            transition: all 0.2s ease;
        }
        .bh-actions.single-page .bh-btn {
            color: #ccc;
            padding: 6px;
        }
        .bh-btn:hover {
            background-color: rgba(255, 255, 255, 0.15);
            transform: scale(1.1);
            color: #fff;
            box-shadow: 0 0 8px rgba(0,0,0,0.2);
        }
        .bh-btn.play-btn:hover { color: #4ade80; }
        .bh-btn.copy-btn:hover { color: #60a5fa; }
        .bh-btn.dl-btn:hover   { color: #f472b6; }
        .bh-btn svg {
            width: 18px;
            height: 18px;
            fill: currentColor;
            stroke: currentColor;
            stroke-width: 0;
        }
        .bh-actions.single-page .bh-btn svg {
            width: 20px;
            height: 20px;
        }
        .bh-btn.loading svg {
            animation: spin 0.8s linear infinite;
            fill: #fbbf24;
        }
        @keyframes spin { 100% { transform: rotate(360deg); } }

        /* --- pst.moe Enhancements --- */
        .sinflix-res-header {
            display: inline-flex;
            align-items: center;
            gap: 10px;
            font-weight: bold;
            margin: 8px 0;
        }
        .sinflix-copy-btn {
            background: #2a2b2c;
            color: #e8eaed;
            border: 1px solid #5f6368;
            padding: 4px 10px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 11px;
            font-family: inherit;
            transition: all 0.2s;
        }
        .sinflix-copy-btn:hover {
            background: #1a73e8;
            border-color: #1a73e8;
            color: white;
        }

        /* --- Mega Bypass Circle --- */
        .sinflix-mega-circle {
            display: inline-block;
            width: 13px;
            height: 13px;
            border-radius: 50%;
            background: #9aa0a6;
            cursor: pointer;
            vertical-align: middle;
            margin-left: 5px;
            opacity: 0.5;
            transition: opacity 0.2s ease, transform 0.2s ease, background 0.2s ease;
            flex-shrink: 0;
        }
        .sinflix-mega-circle:hover {
            opacity: 1;
            transform: scale(1.25);
            background: #34a853;
        }
        .sinflix-mega-bypass-header {
            display: inline-flex;
            align-items: center;
            gap: 10px;
            margin: 6px 0;
        }
        .sinflix-copy-bypass-btn {
            background: #2a2b2c;
            color: #e8eaed;
            border: 1px solid #9aa0a6;
            padding: 4px 10px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 11px;
            font-family: inherit;
            transition: all 0.2s;
        }
        .sinflix-copy-bypass-btn:hover {
            background: #34a853;
            border-color: #34a853;
            color: white;
        }

        /* --- FileDitch download circle --- */
        .sinflix-fd-dl-circle {
            display: inline-block;
            width: 13px;
            height: 13px;
            border-radius: 50%;
            background: #f97316;
            cursor: pointer;
            vertical-align: middle;
            margin-left: 4px;
            opacity: 0.55;
            transition: opacity 0.2s ease, transform 0.2s ease, background 0.2s ease;
            flex-shrink: 0;
        }
        .sinflix-fd-dl-circle:hover { opacity: 1; transform: scale(1.3); background: #fb923c; }
        .sinflix-fd-dl-circle.fd-loading {
            opacity: 0.35;
            cursor: wait;
            animation: fd-pulse 0.9s ease-in-out infinite alternate;
        }
        @keyframes fd-pulse {
            from { opacity: 0.25; transform: scale(0.85); }
            to   { opacity: 0.65; transform: scale(1.05); }
        }

        /* --- Prevent section flash on load --- */
        .entry-text article h4 {
            opacity: 0;
            transition: opacity 0.1s ease-in-out;
        }
        .entry-text article h4.sinflix-visible {
            opacity: 1;
        }
        .entry-text article.sinflix-processed h4 {
            opacity: 1;
        }

        /* --- Rentry content box rounded corners --- */
        .col-12.long-words {
            border-radius: 12px;
            overflow: hidden;
        }
        .entry-text {
            border-radius: 12px;
            overflow: hidden;
        }

        /* --- Settings Button --- */
        /* Settings button is inside the search capsule when capsule is ON */
        #kdrama-settings-button {
            position: fixed;
            top: 20px;
            right: 20px;
            width: 40px;
            height: 40px;
            z-index: 10001;
            background: rgba(50, 50, 50, 0.4);
            backdrop-filter: blur(6px);
            border-radius: 12px;
            box-shadow: 0 4px 10px rgba(0,0,0,0.15);
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            transition: background 0.3s ease;
        }
        #kdrama-settings-button:hover {
            background: rgba(80, 80, 80, 0.6);
        }

        /* --- Modal Styles --- */
        #kdrama-settings-modal {
            display: none;
            position: fixed;
            z-index: 10002;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0,0,0,0.5);
            backdrop-filter: blur(4px);
            justify-content: center;
            align-items: center;
            font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
            opacity: 0;
            transition: opacity 0.2s ease-out;
        }
        #kdrama-settings-modal.show {
            opacity: 1;
        }
        .kdrama-modal-content {
            background: #202124;
            color: #e8eaed;
            padding: 0;
            border-radius: 8px;
            width: 95%;
            max-width: 520px;
            max-height: 90vh;
            box-shadow: 0 8px 32px rgba(0,0,0,0.6);
            border: 1px solid #3c4043;
            position: relative;
            overflow: hidden;
            transform: scale(0.9);
            transition: transform 0.2s ease-out;
        }
        #kdrama-settings-modal.show .kdrama-modal-content {
            transform: scale(1);
        }

        .kdrama-modal-header {
            background: #2d2e30;
            color: #e8eaed;
            padding: 16px 20px;
            border-radius: 8px 8px 0 0;
            position: relative;
            border-bottom: 1px solid #3c4043;
        }
        .kdrama-modal-header h2 {
            margin: 0;
            font-size: 18px;
            font-weight: 500;
            display: flex;
            align-items: center;
            gap: 8px;
            color: #e8eaed;
        }
        .kdrama-modal-header .header-icon {
            width: 20px;
            height: 20px;
        }
        #kdrama-settings-close {
            position: absolute;
            right: 16px;
            top: 50%;
            transform: translateY(-50%);
            width: 28px;
            height: 28px;
            border-radius: 4px;
            background: transparent;
            border: none;
            color: #9aa0a6;
            font-size: 18px;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: background 0.2s ease, color 0.2s ease;
        }
        #kdrama-settings-close:hover {
            background: #3c4043;
            color: #e8eaed;
        }

        .kdrama-modal-body {
            padding: 20px;
            max-height: 60vh;
            overflow-y: auto;
            background: #202124;
        }
        .kdrama-modal-body::-webkit-scrollbar {
            width: 8px;
        }
        .kdrama-modal-body::-webkit-scrollbar-track {
            background: #2d2e30;
            border-radius: 4px;
        }
        .kdrama-modal-body::-webkit-scrollbar-thumb {
            background: #5f6368;
            border-radius: 4px;
        }
        .kdrama-modal-body::-webkit-scrollbar-thumb:hover {
            background: #80868b;
        }

        /* Settings Sections */
        .kdrama-settings-section {
            margin-bottom: 32px;
        }
        .kdrama-settings-section:last-child {
            margin-bottom: 0;
        }
        .kdrama-section-title {
            font-size: 16px;
            font-weight: 500;
            color: #9aa0a6;
            margin: 0 0 12px 0;
            display: flex;
            align-items: center;
            gap: 8px;
            text-transform: uppercase;
            letter-spacing: 0.5px;
        }
        .kdrama-section-title .section-icon {
            width: 16px;
            height: 16px;
        }

        .kdrama-toggle-item {
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 12px 16px;
            background: #2d2e30;
            border-radius: 6px;
            margin-bottom: 8px;
            border: 1px solid #3c4043;
            transition: all 0.2s ease;
        }
        .kdrama-toggle-item:last-child {
            margin-bottom: 0;
        }
        .kdrama-toggle-item:hover {
            background: #35363a;
            border-color: #5f6368;
        }

        .kdrama-toggle-info {
            flex: 1;
        }
        .kdrama-toggle-label {
            font-size: 14px;
            font-weight: 500;
            margin: 0 0 2px 0;
            color: #e8eaed;
        }
        .kdrama-toggle-description {
            font-size: 12px;
            color: #9aa0a6;
            margin: 0;
            line-height: 1.3;
        }

        /* Custom Toggle Switch */
        .kdrama-toggle-switch {
            position: relative;
            width: 50px;
            height: 26px;
            margin-left: 16px;
        }
        .kdrama-toggle-switch input {
            opacity: 0;
            width: 0;
            height: 0;
        }
        .kdrama-toggle-slider {
            position: absolute;
            cursor: pointer;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background-color: #5f6368;
            transition: 0.3s;
            border-radius: 26px;
        }
        .kdrama-toggle-slider:before {
            position: absolute;
            content: "";
            height: 18px;
            width: 18px;
            left: 4px;
            bottom: 4px;
            background-color: #ffffff;
            transition: 0.3s;
            border-radius: 50%;
            box-shadow: 0 2px 4px rgba(0,0,0,0.3);
        }
        .kdrama-toggle-switch input:checked + .kdrama-toggle-slider {
            background: #1a73e8;
        }
        .kdrama-toggle-switch input:checked + .kdrama-toggle-slider:before {
            transform: translateX(24px);
        }

        .kdrama-text-input {
            width: 100%;
            background: #3c4043;
            border: 1px solid #5f6368;
            color: #e8eaed;
            padding: 8px 12px;
            border-radius: 4px;
            font-size: 14px;
            box-sizing: border-box;
            transition: all 0.2s ease;
            font-family: inherit;
        }
        .kdrama-text-input:focus {
            outline: none;
            border-color: #1a73e8;
            background: #202124;
        }

        .kdrama-radio-group {
            background: #2d2e30;
            border-radius: 6px;
            padding: 16px;
            border: 1px solid #3c4043;
            margin-bottom: 16px;
        }
        .kdrama-radio-group-title {
            font-size: 14px;
            font-weight: 500;
            color: #e8eaed;
            margin: 0 0 12px 0;
        }
        .kdrama-radio-options {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 12px;
        }
        .kdrama-radio-option {
            position: relative;
        }
        .kdrama-radio-option input[type="radio"] {
            opacity: 0;
            position: absolute;
            width: 100%;
            height: 100%;
            margin: 0;
            cursor: pointer;
        }
        .kdrama-radio-option-label {
            display: flex;
            align-items: center;
            gap: 8px;
            padding: 10px 12px;
            background: #3c4043;
            border: 1px solid #5f6368;
            border-radius: 4px;
            cursor: pointer;
            transition: all 0.2s ease;
            font-size: 13px;
            font-weight: 400;
            color: #e8eaed;
        }
        .kdrama-radio-option input:checked + .kdrama-radio-option-label {
            background: #1a73e8;
            border-color: #1a73e8;
            color: white;
        }
        .kdrama-radio-option-label:hover {
            background: #484a4d;
            border-color: #80868b;
        }
        .kdrama-radio-option input:checked + .kdrama-radio-option-label:hover {
            background: #1557b0;
            border-color: #1557b0;
        }
        .kdrama-radio-option-icon {
            width: 14px;
            height: 14px;
        }

        .kdrama-modal-footer {
            padding: 16px 20px;
            background: #2d2e30;
            border-radius: 0 0 8px 8px;
            border-top: 1px solid #3c4043;
        }
        #kdrama-save-button {
            background: #1a73e8;
            color: white;
            padding: 10px 20px;
            font-size: 14px;
            font-weight: 500;
            border-radius: 4px;
            border: none;
            cursor: pointer;
            width: 100%;
            transition: background 0.2s ease;
        }
        #kdrama-save-button:hover {
            background: #1557b0;
        }
        #kdrama-save-button:active {
            background: #1142a0;
        }

        .kdrama-circle-container {
            display: inline-flex;
            align-items: center;
            gap: 3px;
            margin-right: 5px;
            vertical-align: middle;
            position: relative;
            top: -1px;
        }
        .kdrama-circle {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 18px;
            height: 18px;
            border-radius: 7px;
            border: none;
            cursor: pointer;
            font-size: 10px;
            font-weight: 700;
            font-family: "Segoe UI", system-ui, sans-serif;
            letter-spacing: -0.2px;
            line-height: 1;
            opacity: 0.28;
            transition: opacity 0.18s ease, transform 0.18s ease, background 0.18s ease, box-shadow 0.18s ease;
            user-select: none;
            flex-shrink: 0;
        }
        .kdrama-circle:hover {
            opacity: 1;
            transform: scale(1.18);
        }
        .google-circle {
            background: rgba(66, 133, 244, 0.15);
            color: #4285f4;
            border: 1px solid rgba(66, 133, 244, 0.3);
        }
        .google-circle::after { content: "G"; }
        .google-circle:hover {
            background: #4285f4;
            color: #fff;
            border-color: #4285f4;
            box-shadow: 0 2px 8px rgba(66, 133, 244, 0.45);
        }
        .mdl-circle {
            background: rgba(0, 150, 136, 0.12);
            color: #00897b;
            border: 1px solid rgba(0, 150, 136, 0.28);
        }
        .mdl-circle::after { content: "M"; }
        .mdl-circle:hover {
            background: #00897b;
            color: #fff;
            border-color: #00897b;
            box-shadow: 0 2px 8px rgba(0, 150, 136, 0.45);
        }

        /* --- Floating Buttons (Back to Top & Search) --- */
        .kdrama-float-button {
            position: fixed;
            width: 44px;
            height: 44px;
            border-radius: 50%;
            border: 1px solid rgba(255, 255, 255, 0.2) !important;
            outline: none !important;
            background: rgba(30, 30, 30, 0.4);
            backdrop-filter: blur(12px);
            -webkit-backdrop-filter: blur(12px);
            color: white;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            z-index: 10003;
            user-select: none;
            transition: background-color 0.3s ease, opacity 0.3s ease, border 0.3s ease, bottom 0.5s cubic-bezier(0.4, 0.0, 0.2, 1);
            opacity: 0;
            pointer-events: none;
            right: 20px;
        }
        .kdrama-float-button.show {
            opacity: 1;
            pointer-events: auto; /* Enable interaction when shown */
        }
        .kdrama-float-button:hover,
        .kdrama-float-button:focus,
        .kdrama-float-button:active {
            background: rgba(50, 50, 50, 0.6);
            border: 1px solid rgba(255, 255, 255, 0.35) !important;
            outline: none !important;
            transform: scale(1.05);
            transition: background-color 0.3s ease, opacity 0.3s ease, border 0.3s ease, bottom 0.5s cubic-bezier(0.4, 0.0, 0.2, 1), transform 0.2s ease;
        }
        #kdrama-back-to-top {
            bottom: 30px;
        }
        #kdrama-search-button {
            bottom: 30px; /* Will be dynamically positioned */
        }
        #kdrama-chat-button {
            bottom: 84px; /* Will be dynamically positioned */
        }

        /* --- Floating Notification --- */
        .kdrama-notification {
            position: fixed;
            top: 20px;
            left: 50%;
            transform: translateX(-50%);
            background: rgba(0, 0, 0, 0.9);
            color: white;
            padding: 12px 20px;
            border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
            z-index: 10005;
            font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
            font-size: 14px;
            opacity: 0;
            transition: opacity 0.3s ease, transform 0.3s ease;
            pointer-events: none;
            backdrop-filter: blur(10px);
            border: 1px solid rgba(255, 255, 255, 0.1);
        }
        .kdrama-notification.show {
            opacity: 1;
            transform: translateX(-50%) translateY(10px);
        }
        .kdrama-notification.success {
            background: rgba(34, 139, 34, 0.9);
            border-color: rgba(34, 139, 34, 0.3);
        }
        .kdrama-notification.error {
            background: rgba(220, 20, 60, 0.9);
            border-color: rgba(220, 20, 60, 0.3);
        }
        .kdrama-notification.info {
            background: rgba(30, 144, 255, 0.9);
            border-color: rgba(30, 144, 255, 0.3);
        }

        /* --- Top Search Bar (Dynamic Island) --- */
        #sfx-top-searchbar-wrap {
            position: fixed;
            top: 14px;
            left: 50%;
            transform: translateX(-50%);
            z-index: 10006;
            /* Dynamic Island pill shape */
            width: min(560px, calc(100vw - 32px));
            height: 48px;
            border-radius: 28px;
            background: rgba(18, 18, 22, 0.82);
            backdrop-filter: blur(20px) saturate(180%);
            -webkit-backdrop-filter: blur(20px) saturate(180%);
            border: 1px solid rgba(255,255,255,0.13);
            box-shadow: 0 4px 32px rgba(0,0,0,0.45), 0 0 0 1px rgba(0,0,0,0.3);
            display: flex;
            align-items: center;
            padding: 0 16px;
            gap: 10px;
            overflow: hidden;
            cursor: text;
            /* Transition for all morphing */
            transition:
                width 0.55s cubic-bezier(0.34, 1.38, 0.64, 1),
                height 0.55s cubic-bezier(0.34, 1.38, 0.64, 1),
                border-radius 0.55s cubic-bezier(0.34, 1.38, 0.64, 1),
                background 0.4s ease,
                box-shadow 0.4s ease,
                top 0.55s cubic-bezier(0.34, 1.38, 0.64, 1),
                opacity 0.35s ease;
        }
        #sfx-top-searchbar-wrap.sfx-collapsed {
            width: 192px;
            height: 34px;
            border-radius: 17px;
            border: 1px solid rgba(255,255,255,0.07);
            background: rgba(22, 22, 26, 0.72);
            backdrop-filter: blur(12px);
            -webkit-backdrop-filter: blur(12px);
            cursor: pointer;
            box-shadow: none;
            padding: 0 14px 0 10px;
            justify-content: center;
            gap: 6px;
            overflow: hidden;
        }
        #sfx-top-searchbar-wrap.sfx-collapsed:hover {
            background: rgba(38, 38, 44, 0.82);
            border-color: rgba(255,255,255,0.13);
            transform: translateX(-50%) scale(1.03);
        }
        #sfx-top-searchbar-wrap.sfx-expanding {
            /* Briefly scale up a touch during expansion */
        }
        #sfx-top-search-icon {
            display: flex;
            align-items: center;
            justify-content: center;
            flex-shrink: 0;
            color: rgba(255,255,255,0.55);
            pointer-events: none;
            transition: color 0.3s ease;
        }
        #sfx-top-searchbar-wrap:hover #sfx-top-search-icon {
            color: rgba(255,255,255,0.85);
        }
        /* Collapsed: icon stays in normal flex flow, centred by justify-content on parent */
        #sfx-top-searchbar-wrap.sfx-collapsed #sfx-top-search-icon {
            color: rgba(255,255,255,0.38);
            flex-shrink: 0;
        }
        #sfx-top-searchbar-wrap.sfx-collapsed #sfx-top-search-icon svg {
            width: 13px;
            height: 13px;
        }
        #sfx-top-searchbar-wrap.sfx-collapsed:hover #sfx-top-search-icon {
            color: rgba(255,255,255,0.65);
        }
        /* Collapsed label */
        #sfx-top-search-label {
            font-size: 12px;
            font-weight: 400;
            font-family: "Segoe UI", system-ui, sans-serif;
            color: rgba(255,255,255,0.32);
            white-space: nowrap;
            letter-spacing: 0.3px;
            /* Hidden in expanded state — use max-width so transition works (auto is not animatable) */
            max-width: 0;
            opacity: 0;
            overflow: hidden;
            pointer-events: none;
            transition: opacity 0.35s ease, max-width 0.45s cubic-bezier(0.34, 1.38, 0.64, 1);
        }
        #sfx-top-searchbar-wrap.sfx-collapsed #sfx-top-search-label {
            max-width: 100px;
            opacity: 1;
        }
        #sfx-top-searchbar-wrap.sfx-collapsed:hover #sfx-top-search-label {
            color: rgba(255,255,255,0.62);
        }
        #sfx-top-search-input {
            flex: 1;
            background: transparent;
            border: none;
            outline: none;
            color: #fff;
            font-size: 15px;
            font-family: "Segoe UI", system-ui, sans-serif;
            caret-color: #a78bfa;
            min-width: 0;
            transition: opacity 0.3s ease, width 0.4s ease;
        }
        #sfx-top-search-input::placeholder {
            color: rgba(255,255,255,0.38);
        }
        #sfx-top-searchbar-wrap.sfx-collapsed #sfx-top-search-input {
            opacity: 0;
            pointer-events: none;
            width: 0;
            overflow: hidden;
            flex: none;
            padding: 0;
            margin: 0;
        }
        #sfx-top-search-count {
            font-size: 12px;
            color: rgba(255,255,255,0.45);
            white-space: nowrap;
            flex-shrink: 0;
            transition: opacity 0.3s ease, width 0.4s ease;
        }
        #sfx-top-searchbar-wrap.sfx-collapsed #sfx-top-search-count {
            opacity: 0;
            pointer-events: none;
            width: 0;
            overflow: hidden;
            flex: none;
            padding: 0;
            margin: 0;
        }
        .sfx-top-nav-btn {
            background: none;
            border: none;
            color: rgba(255,255,255,0.55);
            width: 28px;
            height: 28px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            flex-shrink: 0;
            transition: background 0.2s, color 0.2s, opacity 0.3s, width 0.4s;
        }
        .sfx-top-nav-btn:hover:not(:disabled) {
            background: rgba(255,255,255,0.12);
            color: #fff;
        }
        .sfx-top-nav-btn:disabled { opacity: 0.25; cursor: not-allowed; }
        #sfx-top-searchbar-wrap.sfx-collapsed .sfx-top-nav-btn {
            opacity: 0;
            pointer-events: none;
            width: 0;
            overflow: hidden;
            flex: none;
            padding: 0;
            margin: 0;
        }
        #sfx-top-search-close {
            background: none;
            border: none;
            color: rgba(255,255,255,0.45);
            font-size: 18px;
            line-height: 1;
            cursor: pointer;
            flex-shrink: 0;
            padding: 0 2px;
            transition: color 0.2s, opacity 0.3s, width 0.4s;
        }
        #sfx-top-search-close:hover { color: #fff; }
        #sfx-top-searchbar-wrap.sfx-collapsed #sfx-top-search-close {
            opacity: 0;
            pointer-events: none;
            width: 0;
            overflow: hidden;
            flex: none;
            padding: 0;
            margin: 0;
        }

        /* --- Capsule action buttons (settings + chat) --- */
        .sfx-cap-sep {
            display: none;
        }
        .sfx-cap-action {
            background: none !important;
            border: none !important;
            outline: none !important;
            box-shadow: none !important;
            -webkit-appearance: none;
            color: rgba(255,255,255,0.38);
            width: 26px;
            height: 26px;
            border-radius: 0 !important;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            flex-shrink: 0;
            padding: 0;
            transition: color 0.18s ease;
        }
        .sfx-cap-action:hover,
        .sfx-cap-action:focus,
        .sfx-cap-action:active {
            background: none !important;
            border: none !important;
            outline: none !important;
            box-shadow: none !important;
            color: rgba(255,255,255,0.85);
        }
        .sfx-cap-action svg {
            width: 14px;
            height: 14px;
        }
        /* In expanded state: shrink separator+actions slightly so they don't dominate */
        #sfx-top-searchbar-wrap:not(.sfx-collapsed) .sfx-cap-sep {
            height: 14px;
        }
        #kdrama-search-modal {
            position: fixed;
            bottom: 0;
            left: 0;
            width: 100%;
            z-index: 10004;
            background: rgba(0, 0, 0, 0.7);
            backdrop-filter: blur(10px);
            -webkit-backdrop-filter: blur(10px);
            box-shadow: 0 -4px 15px rgba(0,0,0,0.3);
            padding: 15px 20px;
            box-sizing: border-box;
            display: flex;
            justify-content: center;
            align-items: center;
            opacity: 0;
            pointer-events: none;
            transition: opacity 0.2s ease-in-out;
        }
        #kdrama-search-modal.show {
            opacity: 1;
            pointer-events: auto;
        }
        .kdrama-search-controls {
            position: relative;
            width: calc(100% - 60px);
            max-width: 500px;
            display: flex;
            align-items: center;
            background-color: transparent;
            border-radius: 8px;
        }
        .kdrama-search-input-wrapper {
            position: relative;
            flex-grow: 1;
            display: flex;
            align-items: center;
        }
        #kdrama-search-input {
            width: 100%;
            padding: 12px 15px 12px 40px;
            border: none;
            border-radius: 8px;
            background-color: #333;
            color: white;
            font-size: 16px;
            outline: none;
            box-sizing: border-box;
        }
        #kdrama-search-input:focus {
            outline: 1px solid #0078D4;
        }
        #kdrama-search-input::placeholder {
            color: #bbb;
        }
        .kdrama-search-icon {
            position: absolute;
            left: 12px;
            color: #bbb;
            font-size: 18px;
            pointer-events: none;
        }
        .kdrama-search-nav-buttons {
            display: flex;
            align-items: center;
            margin-left: 10px;
            gap: 5px;
        }
        .kdrama-search-nav-button {
            background: none;
            border: none;
            color: white;
            width: 32px;
            height: 32px;
            border-radius: 6px;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            opacity: 0.7;
            transition: background-color 0.2s, opacity 0.2s;
        }
        .kdrama-search-nav-button:hover:not(:disabled) {
            background-color: rgba(255, 255, 255, 0.1);
            opacity: 1;
        }
        .kdrama-search-nav-button:disabled {
            opacity: 0.3;
            cursor: not-allowed;
        }
        #kdrama-search-close {
            background: none;
            border: none;
            color: white;
            font-size: 24px;
            cursor: pointer;
            margin-left: 15px;
            line-height: 1;
            opacity: 0.7;
            transition: opacity 0.2s;
        }
        #kdrama-search-close:hover {
            opacity: 1;
        }

        /* --- Highlight style --- */
        .kdrama-highlight {
            background-color: #FFEB3B;
            color: black;
            font-weight: bold;
            padding: 2px 0;
            border-radius: 2px;
        }
        .kdrama-highlight.current {
            background-color: #4CAF50;
            color: white;
            box-shadow: 0 0 8px rgba(76, 175, 80, 0.8);
        }
        code .kdrama-highlight {
            background-color: #383131;
            color: #e0aeb4;
        }
        code .kdrama-highlight.current {
            background-color: #6a5e5e;
            color: #e0aeb4;
        }
    `);

    // --- Enhanced Drama Detection Patterns ---
    const dramaPatterns = [
        // Pattern for lines with (reup) or (redo) prefix, broken by HTML tags.
        /^(?:\(reup\)|\(redo\))?\s*([^[]+?)\s*\[/,
        // NEW: Pattern for drama names followed by mixed brackets like (AMZN...] with episode info
        /^(?:\(reup\)|\(redo\))?\s*([^([]+?)\s*[\[(][^\])]*[\])][\s\S]*?\((?:e?\d+(?:\s+of\s+\d+)?|\d+)ep\)\s*-/i,
        // NEW: Pattern for lines WITHOUT a prefix, broken by HTML tags.
        /^([a-zA-Z0-9][^[]*?)\s*\[/,
        // NEW: Pattern for drama names followed by "- coming soon"
        /^(?:\(reup\)|\(redo\))?\s*([^-]+?)\s*-\s*coming\s+soon/i,
        // NEW: Pattern for drama names followed by just "-" (nothing or whitespace after)
        /^(?:\(reup\)|\(redo\))?\s*([^-]+?)\s*-\s*$/,
        /^(?:\(reup\)|\(redo\))?\s*([^[]+?)\s*\[.*?\]\s*\((?:e?\d+(?:\s+of\s+\d+)?|\d+)ep\)\s*-/i,
        /^(?:\(reup\)|\(redo\))?\s*([^[]+?(?:\s+S\d+)?)\s*\[.*?\]\s*\(\d+ep\)\s*-/i,
        /^(?:\(reup\)|\(redo\))?\s*([^[]+?)\s*\[.*?\]\s*\(e\d+\s+of\s+\d+\)\s*-/i,
        /^(?:\(reup\)|\(redo\))?\s*([^[]+?)\s*\[.*?\]\s*\(.*?ep.*?\)\s*-/i,
        /^(?:\(reup\)|\(redo\))?\s*([^[]+?)\s*\[.*?\]\s*\((?:e?\d+(?:\s+of\s+\d+)?|\d+)ep\)/i
    ];

    // --- Helper function to extract drama name ---
    function extractDramaName(text) {
        const cleanText = text.trim();
        if (cleanText.length < 10) return null;
        for (const pattern of dramaPatterns) {
            const match = cleanText.match(pattern);
            if (match && match[1]) {
                let dramaName = match[1].trim().replace(/:$/, '').trim().replace(/\s+/g, ' ');
                // Allow drama names as short as 1 character (like "M" or "DP")
                if (dramaName.length > 0 && dramaName.length < 200) return dramaName;
            }
        }
        return null;
    }

    // --- Helper function to open windows in the center of the screen ---
    function openInCenter(url, title) {
        const popWidth = 1000,
            popHeight = 700;

        // Get the actual screen dimensions
        const screenWidth = window.screen.availWidth || window.screen.width;
        const screenHeight = window.screen.availHeight || window.screen.height;

        // Calculate center position
        const left = Math.round((screenWidth / 2) - (popWidth / 2));
        const top = Math.round((screenHeight / 2) - (popHeight / 2));

        // Ensure the window doesn't go off-screen
        const finalLeft = Math.max(0, left);
        const finalTop = Math.max(0, top);

        const features = `width=${popWidth},height=${popHeight},top=${finalTop},left=${finalLeft},resizable=yes,scrollbars=yes,status=no,toolbar=no,menubar=no,location=no`;
        window.open(url, title, features);
    }

    // --- Helper function to show floating notifications ---
    function showNotification(message, type = 'info', duration = 3000) {
        // Remove any existing notification
        const existingNotification = document.querySelector('.kdrama-notification');
        if (existingNotification) {
            existingNotification.remove();
        }

        // Create new notification
        const notification = document.createElement('div');
        notification.className = `kdrama-notification ${type}`;
        notification.textContent = message;

        document.body.appendChild(notification);

        // Trigger animation
        setTimeout(() => {
            notification.classList.add('show');
        }, 10);

        // Auto-remove after specified duration
        setTimeout(() => {
            notification.classList.remove('show');
            setTimeout(() => {
                if (notification.parentNode) {
                    notification.remove();
                }
            }, 300);
        }, duration);
    }

    // --- Helper function to copy text to clipboard ---
    async function copyToClipboard(text) {
        try {
            if (navigator.clipboard && window.isSecureContext) {
                await navigator.clipboard.writeText(text);
                return true;
            } else {
                // Fallback for older browsers or non-secure contexts
                const textArea = document.createElement('textarea');
                textArea.value = text;
                textArea.style.position = 'fixed';
                textArea.style.left = '-999999px';
                textArea.style.top = '-999999px';
                document.body.appendChild(textArea);
                textArea.focus();
                textArea.select();

                const result = document.execCommand('copy');
                document.body.removeChild(textArea);
                return result;
            }
        } catch (err) {
            console.error('Failed to copy text: ', err);
            return false;
        }
    }

    // --- Function to get MDL first result URL for copying ---
    async function getMdlFirstResultUrl(searchUrl, dramaName) {
        try {
            // Show loading indicator
            const circles = document.querySelectorAll('.mdl-circle');
            circles.forEach(circle => {
                if (circle.title.includes(dramaName)) {
                    circle.style.opacity = '0.5';
                    circle.style.cursor = 'wait';
                }
            });

            const response = await new Promise((resolve, reject) => {
                GM_xmlhttpRequest({
                    method: 'GET',
                    url: searchUrl,
                    timeout: 5000,
                    headers: {
                        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
                        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                        'Accept-Language': 'en-US,en;q=0.5',
                        'Cache-Control': 'no-cache'
                    },
                    onload: function(response) {
                        resolve(response);
                    },
                    onerror: function(error) {
                        reject(error);
                    },
                    ontimeout: function() {
                        reject(new Error('Request timed out'));
                    }
                });
            });

            // Reset circle appearance
            circles.forEach(circle => {
                if (circle.title.includes(dramaName)) {
                    circle.style.opacity = '';
                    circle.style.cursor = 'pointer';
                }
            });

            if (response.status !== 200) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }

            const htmlText = response.responseText;
            const resultMatch = htmlText.match(/<div[^>]+id="mdl-\d+"[^>]*>[\s\S]*?<h6[^>]*class="[^"]*title[^"]*"[^>]*>[\s\S]*?<a[^>]+href="([^"]+)"/);

            if (resultMatch) {
                return `https://mydramalist.com${resultMatch[1]}`;
            } else {
                // Fallback: try simpler regex patterns
                const simpleMatch = htmlText.match(/<a[^>]+href="(\/\d+-[^"]+)"[^>]*>[^<]*<\/a>/);
                if (simpleMatch) {
                    return `https://mydramalist.com${simpleMatch[1]}`;
                }
            }

            return null;
        } catch (error) {
            // Reset circle appearance
            const circles = document.querySelectorAll('.mdl-circle');
            circles.forEach(circle => {
                if (circle.title.includes(dramaName)) {
                    circle.style.opacity = '';
                    circle.style.cursor = 'pointer';
                }
            });

            console.error('Sinflix Modifier: Error getting MDL first result:', error);
            return null;
        }
    }

    // --- Function to load MDL page in background and open first result ---
    async function loadMdlPageAndOpenFirstResult(searchUrl, dramaName) {
        try {
            // Show loading indicator (update circle appearance)
            const circles = document.querySelectorAll('.mdl-circle');
            circles.forEach(circle => {
                if (circle.title.includes(dramaName)) {
                    circle.style.opacity = '0.5';
                    circle.style.cursor = 'wait';
                }
            });

            // Use GM_xmlhttpRequest with optimizations for speed
            const response = await new Promise((resolve, reject) => {
                GM_xmlhttpRequest({
                    method: 'GET',
                    url: searchUrl,
                    timeout: 5000, // Reduced timeout to 5 seconds
                    headers: {
                        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
                        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                        'Accept-Language': 'en-US,en;q=0.5',
                        'Cache-Control': 'no-cache'
                    },
                    onload: function(response) {
                        resolve(response);
                    },
                    onerror: function(error) {
                        reject(error);
                    },
                    ontimeout: function() {
                        reject(new Error('Request timed out'));
                    },
                    // Speed optimization: Only process first few KB of response
                    onprogress: function(response) {
                        // If we've received enough data and found what we need, we can stop
                        if (response.responseText && response.responseText.length > 10000) {
                            // Try to find the first result in the partial response
                            const partialMatch = response.responseText.match(/<h6[^>]*class="[^"]*title[^"]*"[^>]*>[\s\S]*?<a[^>]+href="([^"]+)"/);
                            if (partialMatch) {
                                // Found it early! Create a mock response
                                const mockResponse = {
                                    status: 200,
                                    responseText: response.responseText,
                                    firstResultFound: partialMatch[1]
                                };
                                resolve(mockResponse);
                                return;
                            }
                        }
                    }
                });
            });

            if (response.status !== 200) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }

            let firstResultUrl = null;

            // Check if we found the result during onprogress
            if (response.firstResultFound) {
                firstResultUrl = `https://mydramalist.com${response.firstResultFound}`;
            } else {
                // Fast parsing using regex instead of DOMParser for better performance
                const htmlText = response.responseText;

                // Look for the first result using optimized regex
                const resultMatch = htmlText.match(/<div[^>]+id="mdl-\d+"[^>]*>[\s\S]*?<h6[^>]*class="[^"]*title[^"]*"[^>]*>[\s\S]*?<a[^>]+href="([^"]+)"/);

                if (resultMatch) {
                    firstResultUrl = `https://mydramalist.com${resultMatch[1]}`;
                } else {
                    // Fallback: try simpler regex patterns
                    const simpleMatch = htmlText.match(/<a[^>]+href="(\/\d+-[^"]+)"[^>]*>[^<]*<\/a>/);
                    if (simpleMatch) {
                        firstResultUrl = `https://mydramalist.com${simpleMatch[1]}`;
                    }
                }
            }

            // Reset circle appearance
            circles.forEach(circle => {
                if (circle.title.includes(dramaName)) {
                    circle.style.opacity = '';
                    circle.style.cursor = 'pointer';
                }
            });

            if (firstResultUrl) {
                // Open first result in popup
                if (config.linkOpenStyle === 'popup') {
                    openInCenter(firstResultUrl, `sinflix_mdl_${dramaName}`);
                } else {
                    window.open(firstResultUrl, '_blank');
                }
            } else {
                // No results found, fallback to search page
                console.log('Sinflix Modifier: No results found on MDL, opening search page');
                if (config.linkOpenStyle === 'popup') {
                    openInCenter(searchUrl, 'sinflix_mdl_search');
                } else {
                    window.open(searchUrl, '_blank');
                }
            }
        } catch (error) {
            console.error('Sinflix Modifier: Error loading MDL page:', error);

            // Reset circle appearance and fallback to search page
            const circles = document.querySelectorAll('.mdl-circle');
            circles.forEach(circle => {
                if (circle.title.includes(dramaName)) {
                    circle.style.opacity = '';
                    circle.style.cursor = 'pointer';
                }
            });

            // Fallback to opening search page
            if (config.linkOpenStyle === 'popup') {
                openInCenter(searchUrl, 'sinflix_mdl_search');
            } else {
                window.open(searchUrl, '_blank');
            }
        }
    }

    // --- Helper: convert a mega.nz URL to the bypass download URL ---
    function getMegaBypassUrl(megaUrl) {
        // Uses the wldbs workers API: base64-encode the URL, no extra fetch needed
        return `https://mega.wldbs.workers.dev/download?url=${btoa(megaUrl)}`;
    }


    // --- Helper: trigger background download without full page navigation ---
    function triggerDownload(url) {
        const a = document.createElement('a');
        a.href = url;
        // Using download attribute with empty string hints the browser to save it
        a.download = '';
        a.style.display = 'none';
        document.body.appendChild(a);
        a.click();
        // Small delay to ensure the browser processes the click before removal
        setTimeout(() => document.body.removeChild(a), 100);
    }

    // --- pst.moe Enhancements ---
    function enhancePstMoeContent() {
        if (!config.pstMoeEnhancements) return false;
        if (window.location.hostname !== 'pst.moe') return false;

        const preElement = document.querySelector('pre');
        if (!preElement) return false;

        // Guard against double-processing
        if (preElement.dataset.sinflixProcessed) return true;
        preElement.dataset.sinflixProcessed = 'true';

        const resolutionLinks = {};
        const resolutionMegaLinks = {};
        let currentResolution = null;

        // URL regex — matches http(s) URLs up to whitespace
        const linkRegex = /(https?:\/\/[^\s]+)/g;

        // --- Pre-scan: detect which resolution sections contain mega.nz links ---
        // This determines which header buttons to render before the DOM is built.
        const resolutionsWithMega = new Set();
        const resolutionsWithLinks = new Set();
        const resolutionMegaLinksMap = {};
        {
            let scanRes = null;
            const scanLines = preElement.textContent.split('\n');
            for (const scanLine of scanLines) {
                const rMatch = scanLine.trim().match(/^---\s+(.*?)\s+---/);
                if (rMatch) { scanRes = rMatch[1]; continue; }
                if (!scanRes) continue;
                const urlMatch = scanLine.match(/(https?:\/\/[^\s]+)/g);
                if (urlMatch) {
                    resolutionsWithLinks.add(scanRes);
                    const megaUrls = urlMatch.filter(u => u.includes('mega.nz/file/'));
                    if (megaUrls.length > 0) {
                        resolutionsWithMega.add(scanRes);
                        if (!resolutionMegaLinksMap[scanRes]) resolutionMegaLinksMap[scanRes] = [];
                        resolutionMegaLinksMap[scanRes].push(...megaUrls);
                    }
                }
            }
        }

        /**
         * Process a plain-text string and return a DocumentFragment containing:
         *  - resolution-header <span> elements (with Copy buttons) for "--- ... ---" lines
         *  - <a> elements for URLs (+ optional mega bypass circles)
         *  - plain Text nodes for everything else
         * Preserves all original whitespace / newlines.
         */
        function processTextContent(text) {
            const fragment = document.createDocumentFragment();
            const lines = text.split('\n');

            lines.forEach((line, lineIdx) => {
                // --- Resolution header line ---
                const resMatch = line.trim().match(/^---\s+(.*?)\s+---/);
                if (resMatch) {
                    currentResolution = resMatch[1];
                    if (!resolutionLinks[currentResolution]) resolutionLinks[currentResolution] = [];
                    if (!resolutionMegaLinks[currentResolution]) resolutionMegaLinks[currentResolution] = [];

                    const resSpan = document.createElement('span');
                    resSpan.className = 'sinflix-res-header';

                    const textNode = document.createTextNode(line.trim() + ' ');
                    resSpan.appendChild(textNode);

                    // Show mega.nz copy buttons when section has mega links
                    if (resolutionsWithMega.has(currentResolution)) {
                        const copyBtn = document.createElement('button');
                        copyBtn.className = 'sinflix-copy-btn';
                        copyBtn.dataset.res = currentResolution;
                        copyBtn.textContent = 'Copy All Links';
                        resSpan.appendChild(copyBtn);

                        if (config.megaBypass) {
                            resSpan.appendChild(document.createTextNode(' '));
                            const bypassBtn = document.createElement('button');
                            bypassBtn.className = 'sinflix-copy-bypass-btn';
                            bypassBtn.dataset.bypassRes = currentResolution;
                            bypassBtn.textContent = 'Copy Bypass Links';
                            resSpan.appendChild(bypassBtn);
                        }
                    }

                    fragment.appendChild(resSpan);
                    fragment.appendChild(document.createTextNode('\n'));
                    return;
                }

                // --- Normal line: split on URLs ---
                linkRegex.lastIndex = 0;
                let lastIndex = 0;
                let match;
                while ((match = linkRegex.exec(line)) !== null) {
                    // Text before the URL
                    if (match.index > lastIndex) {
                        fragment.appendChild(document.createTextNode(line.slice(lastIndex, match.index)));
                    }

                    const rawUrl = match[0];
                    const cleanUrl = rawUrl.replace(/"/g, '%22');

                    // Track links per resolution
                    if (currentResolution) {
                        resolutionLinks[currentResolution].push(cleanUrl);
                        if (cleanUrl.includes('mega.nz/file/')) {
                            resolutionMegaLinks[currentResolution].push(cleanUrl);
                        }
                    }

                    // Create <a> element
                    const anchor = document.createElement('a');
                    anchor.href = cleanUrl;
                    anchor.target = '_blank';
                    anchor.rel = 'noopener noreferrer';
                    anchor.textContent = rawUrl;
                    fragment.appendChild(anchor);

                    // Append bypass circle for mega links
                    if (config.megaBypass && cleanUrl.includes('mega.nz/file/')) {
                        const circle = document.createElement('span');
                        circle.className = 'sinflix-mega-circle';
                        circle.title = 'Bypass & download via mega.wldbs.workers.dev';
                        circle.dataset.megaUrl = cleanUrl;
                        fragment.appendChild(circle);
                    }

                    // Append download circle for FileDitch links
                    if (config.showFdCircle && cleanUrl.includes('fileditchfiles.me')) {
                        const dlCircle = document.createElement('span');
                        dlCircle.className = 'sinflix-fd-dl-circle';
                        dlCircle.title = '\u2b07 Download via FileDitch (auto-clicks download & closes)';
                        dlCircle.dataset.fdUrl = cleanUrl;
                        fragment.appendChild(dlCircle);
                    }

                    lastIndex = match.index + match[0].length;
                }

                // Remaining text after last URL (or the whole line if no URL)
                if (lastIndex < line.length) {
                    fragment.appendChild(document.createTextNode(line.slice(lastIndex)));
                }

                // Re-add the newline that split() removed (skip after very last line)
                if (lineIdx < lines.length - 1) {
                    fragment.appendChild(document.createTextNode('\n'));
                }
            });

            return fragment;
        }

        // Walk child nodes of <pre>, replacing only Text nodes.
        // Element nodes (Pygments <span class="gu"> etc.) are left untouched.
        const childNodes = Array.from(preElement.childNodes);
        for (const node of childNodes) {
            if (node.nodeType === Node.TEXT_NODE) {
                const fragment = processTextContent(node.textContent);
                preElement.replaceChild(fragment, node);
            }
            // Element nodes: leave as-is to preserve syntax highlighting
        }

        if (config.showFdCircle) {
            document.querySelectorAll('.sinflix-fd-dl-circle').forEach(circle => {
                circle.addEventListener('click', () => {
                    if (circle.classList.contains('fd-loading')) return;
                    circle.classList.add('fd-loading');
                    const w = window.open(circle.dataset.fdUrl + '#sfx=dl', '_blank',
                        'width=900,height=650,menubar=no,toolbar=no,status=no,location=yes');
                    showNotification('Opening FileDitch\u2026 will auto-download & close.', 'info', 5000);
                    setTimeout(() => circle.classList.remove('fd-loading'), 18000);
                    if (!w) showNotification('Popup blocked! Allow popups for pst.moe.', 'error', 6000);
                });
            });
        }

        document.querySelectorAll('.sinflix-copy-btn').forEach(btn => {
            btn.addEventListener('click', (e) => {
                const res = e.target.getAttribute('data-res');
                // Copy only the mega.nz links from this section
                const megaLinks = resolutionMegaLinksMap[res] || [];
                if (megaLinks.length > 0) {
                    showNotification('Copying links...', 'info');
                    navigator.clipboard.writeText(megaLinks.join('\n')).then(() => {
                        showNotification(`${megaLinks.length} link(s) copied!`, 'success');
                        const oldText = e.target.innerText;
                        e.target.innerText = 'Copied!';
                        setTimeout(() => { e.target.innerText = oldText; }, 2000);
                    }).catch(() => {
                        showNotification('Failed to copy links!', 'error');
                    });
                }
            });
        });

        // --- Copy Bypass Links buttons ---
        if (config.megaBypass) {
            document.querySelectorAll('.sinflix-copy-bypass-btn').forEach(btn => {
                btn.addEventListener('click', (e) => {
                    const res = e.target.getAttribute('data-bypass-res');
                    const megaLinks = resolutionMegaLinksMap[res] || [];
                    if (megaLinks.length === 0) {
                        showNotification('No Mega.nz links found in this section.', 'error');
                        return;
                    }
                    const bypassLinks = megaLinks.map(url => getMegaBypassUrl(url));
                    const textToCopy = bypassLinks.join('\n');
                    showNotification('Copying bypass links...', 'info');
                    navigator.clipboard.writeText(textToCopy).then(() => {
                        showNotification(`${bypassLinks.length} link(s) copied!`, 'success');
                        const oldText = e.target.innerText;
                        e.target.innerText = 'Copied!';
                        setTimeout(() => { e.target.innerText = oldText; }, 2000);
                    }).catch(() => {
                        showNotification('Failed to copy links!', 'error');
                    });
                });
            });

            // --- Mega bypass: grey circle click → trigger bypass download ---
            document.querySelectorAll('.sinflix-mega-circle').forEach(circle => {
                circle.addEventListener('click', (e) => {
                    e.stopPropagation();
                    const megaUrl = circle.getAttribute('data-mega-url');
                    if (!megaUrl) return;
                    const bypassUrl = getMegaBypassUrl(megaUrl);
                    showNotification('Download started…', 'success', 2000);
                    triggerDownload(bypassUrl);
                });
            });
        }

        return true;
    }

    // --- Buzzheavier Enhancements ---
    function enhanceBuzzheavierContent() {
        if (!config.buzzheavierEnhancements) return false;
        if (!window.location.hostname.includes('buzzheavier.com')) return false;

        const isHomePage = window.location.pathname.length > 1 && !window.location.pathname.endsWith('/download') && document.querySelector('#tbody');
        const isSinglePage = document.querySelector('#preview') && document.querySelector('a[href$="/download"]');

        const ICONS = {
            play: '<svg viewBox="0 0 24 24"><path d="M8 5.14v14l11-7-11-7z"/></svg>',
            copy: '<svg viewBox="0 0 24 24"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg>',
            downloadSimple: '<svg viewBox="0 0 24 24"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/></svg>',
            check: '<svg viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>',
            loading: '<svg viewBox="0 0 24 24"><path d="M12 4V2A10 10 0 0 0 2 12h2a8 8 0 0 1 8-8z"/></svg>'
        };



        const fetchDirectLink = (url, callback) => {
            const domain = new URL(url).origin;
            const downloadUrl = url.replace(/\/$/, '') + '/download';
            GM_xmlhttpRequest({
                method: "HEAD",
                url: downloadUrl,
                headers: {
                    "hx-current-url": url,
                    "hx-request": "true",
                    "referer": url
                },
                onload: function(response) {
                    let redirectPath = null;
                    const headers = response.responseHeaders;
                    const headerMatch = headers.match(/hx-redirect:\s*(.*)/i);
                    if (headerMatch && headerMatch[1]) {
                        redirectPath = headerMatch[1].trim();
                    }
                    if (redirectPath) {
                        let finalUrl = redirectPath.startsWith('http') ? redirectPath : domain + redirectPath;
                        callback(finalUrl);
                    } else {
                        showNotification("Failed to obtain direct link.", "error");
                        callback(null);
                    }
                },
                onerror: function(err) {
                    showNotification("Network error obtaining link.", "error");
                    callback(null);
                }
            });
        };

        const handleAction = (type, pageUrl, btnElement) => {
            if (btnElement.classList.contains('loading')) return;
            const originalIcon = btnElement.innerHTML;
            btnElement.innerHTML = ICONS.loading;
            btnElement.classList.add('loading');

            fetchDirectLink(pageUrl, (directUrl) => {
                btnElement.classList.remove('loading');
                if (!directUrl) {
                    btnElement.innerHTML = originalIcon;
                    return;
                }
                if (type === 'copy') {
                    navigator.clipboard.writeText(directUrl).then(() => {
                        btnElement.innerHTML = ICONS.check;
                        setTimeout(() => { btnElement.innerHTML = originalIcon; }, 2000);
                    });
                } else if (type === 'download') {
                    btnElement.innerHTML = originalIcon;
                    window.location.assign(directUrl);
                }
            });
        };

        const createActionBtn = (icon, title, type, fileUrl, extraClass) => {
            const btn = document.createElement('button');
            btn.className = `bh-btn ${extraClass || ''}`;
            btn.title = title;
            btn.innerHTML = icon;
            btn.onclick = (e) => {
                e.preventDefault();
                e.stopPropagation();
                handleAction(type, fileUrl, btn);
            };
            return btn;
        };

        const copyLinks = (linksArray, btnElement) => {
            if (!linksArray || linksArray.length === 0) return;
            showNotification('Copying links... Please wait!', 'info');

            let directLinks = [];
            let processed = 0;
            let total = linksArray.length;

            linksArray.forEach(pageUrl => {
                fetchDirectLink(pageUrl, (directUrl) => {
                    processed++;
                    if (directUrl) {
                        directLinks.push(directUrl);
                    }
                    if (processed === total) {
                        if (directLinks.length > 0) {
                            navigator.clipboard.writeText(directLinks.join('\n')).then(() => {
                                showNotification('All direct links copied successfully!', 'success');
                                const oldText = btnElement.innerText;
                                btnElement.innerText = 'Copied!';
                                setTimeout(() => btnElement.innerText = oldText, 2000);
                            }).catch(() => {
                                showNotification('Failed to copy links!', 'error');
                            });
                        } else {
                            showNotification('No direct links found!', 'error');
                        }
                    }
                });
            });
        };

        if (isHomePage) {
            const tbody = document.querySelector('#tbody');
            if (tbody && config.buzzSplitQuality) {
                const rows = Array.from(tbody.querySelectorAll('tr.editable'));
                const qualities = { '1080p': [], '720p': [], '540p': [], '480p': [], 'Other': [] };

                rows.forEach(row => {
                    const linkEl = row.querySelector('a[href^="/"]');
                    if (!linkEl) return;

                    const name = linkEl.innerText.toLowerCase();
                    let matched = false;
                    for (const q of Object.keys(qualities)) {
                        if (q !== 'Other' && name.includes(q)) {
                            qualities[q].push(row);
                            matched = true;
                            break;
                        }
                    }
                    if (!matched) qualities['Other'].push(row);
                });

                const parentTable = tbody.closest('table');
                const container = parentTable.parentNode;
                const headerRow = parentTable.querySelector('thead').outerHTML;
                const tableClass = parentTable.className;

                parentTable.style.display = 'none';

                Object.keys(qualities).forEach(key => {
                    if (qualities[key].length > 0) {
                        const wrapper = document.createElement('div');
                        wrapper.className = 'w-full relative shadow overflow-hidden sm:rounded-lg overflow-x-auto my-6';

                        let copyAllBtnHtml = '';
                        if (config.buzzCopyLinks) {
                            copyAllBtnHtml = `<button class="sinflix-copy-btn btn btn-sm btn-outline-primary float-right" data-q="${key}">Copy Links</button>`;
                        }

                        wrapper.innerHTML = `
                            <h3 class="p-3 text-lg font-bold bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 flex justify-between items-center border-b border-gray-200 dark:border-gray-700">
                                ${key}
                                ${copyAllBtnHtml}
                            </h3>
                            <table class="${tableClass}" style="margin-top: 0">
                                ${headerRow}
                                <tbody id="tbody-${key}">
                                </tbody>
                            </table>
                        `;
                        container.insertBefore(wrapper, parentTable);

                        const newTbody = wrapper.querySelector(`#tbody-${key}`);
                        const linksForQuality = [];

                        qualities[key].forEach(row => {
                            newTbody.appendChild(row);
                            const linkEl = row.querySelector('a[href^="/"]');
                            if (!linkEl) return;

                            const fileUrl = linkEl.href;
                            linksForQuality.push(fileUrl);

                            if (!row.querySelector('.bh-actions')) {
                                const actionsContainer = document.createElement('div');
                                actionsContainer.className = 'bh-actions';

                                if (config.buzzCopyLinks) {
                                    actionsContainer.appendChild(createActionBtn(ICONS.copy, 'Copy Direct Link', 'copy', fileUrl, 'copy-btn'));
                                }
                                if (config.buzzDirectDownload) {
                                    actionsContainer.appendChild(createActionBtn(ICONS.downloadSimple, 'Direct Download', 'download', fileUrl, 'dl-btn'));
                                }
                                linkEl.parentNode.appendChild(actionsContainer);
                            }
                        });

                        const copyBtn = wrapper.querySelector(`.sinflix-copy-btn[data-q="${key}"]`);
                        if (copyBtn) {
                            copyBtn.addEventListener('click', function() {
                                copyLinks(linksForQuality, this);
                            });
                        }
                    }
                });
            } else if (tbody) {
                const rows = Array.from(tbody.querySelectorAll('tr.editable'));
                const allLinks = [];

                rows.forEach(row => {
                    const linkEl = row.querySelector('a[href^="/"]');
                    if (!linkEl) return;
                    const fileUrl = linkEl.href;
                    allLinks.push(fileUrl);

                    if (!row.querySelector('.bh-actions')) {
                        const actionsContainer = document.createElement('div');
                        actionsContainer.className = 'bh-actions';

                        if (config.buzzCopyLinks) {
                            actionsContainer.appendChild(createActionBtn(ICONS.copy, 'Copy Direct Link', 'copy', fileUrl, 'copy-btn'));
                        }
                        if (config.buzzDirectDownload) {
                            actionsContainer.appendChild(createActionBtn(ICONS.downloadSimple, 'Direct Download', 'download', fileUrl, 'dl-btn'));
                        }
                        linkEl.parentNode.appendChild(actionsContainer);
                    }
                });

                if (config.buzzCopyLinks) {
                    const parentTable = tbody.closest('table');
                    const copyBtn = document.createElement('button');
                    copyBtn.className = 'sinflix-copy-btn btn btn-sm bg-blue-600 text-white px-3 py-1 rounded my-2';
                    copyBtn.innerText = 'Copy All Links';
                    copyBtn.onclick = function() { copyLinks(allLinks, this); };
                    parentTable.parentNode.insertBefore(copyBtn, parentTable);
                }
            }
        } else if (isSinglePage) {
            const dlBtn = document.querySelector('a.gay-button') || document.querySelector('a[href$="/download"]');
            if (dlBtn && !document.querySelector('.bh-actions.single-page')) {
                const fileUrl = window.location.href;
                const container = document.createElement('div');
                container.className = 'bh-actions single-page';

                if (config.buzzCopyLinks) {
                    container.appendChild(createActionBtn(ICONS.copy, 'Copy Direct Link', 'copy', fileUrl, 'copy-btn'));
                }
                if (dlBtn.parentNode) {
                    dlBtn.parentNode.insertBefore(container, dlBtn.nextSibling);
                }
            }
        }

        return true;
    }
    // --- Main Processing Function ---
    function enhancePageContent() {
        const content = document.querySelector('.entry-text article');
        if (!content) {
            console.log('Sinflix Modifier: Content not found, retrying...');
            return false;
        }
        const currentVersion = 'v6.4.1_selective_popup';
        if (content.dataset.enhancedv === currentVersion) {
            console.log(`Sinflix Modifier: Content already enhanced (${currentVersion}). Skipping.`);
            return true;
        }
        console.log(`Sinflix Modifier (${currentVersion}): Processing...`);
        content.dataset.enhancedv = currentVersion;

        // NEW: Reorder sections FIRST, before any other processing
        if (config.moveCurrentlyAiringToTop) {
            reorderSections();
        }

        const buzzRegex = /\b(?![a-zA-Z]{12}\b)([a-zA-Z0-9]{12})\b/g;

        if (config.showGoogleCircle || config.showMdlCircle) {
            document.querySelectorAll('.kdrama-circle-container').forEach(el => el.remove());
            const textNodes = [];
            const walker = document.createTreeWalker(content, NodeFilter.SHOW_TEXT, {
                acceptNode: n => (!n.parentNode.closest('a, .kdrama-highlight, .kdrama-search-icon, .kdrama-circle-container') && n.nodeValue.trim().length > 0) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT
            });
            let node;
            while (node = walker.nextNode()) textNodes.push(node);

            textNodes.forEach(textNode => {
                let fullText = textNode.textContent.replace(/=\r?\n/g, '').replace(/=([0-9A-Fa-f]{2})/g, (m, p1) => {
                    try { return String.fromCharCode(parseInt(p1, 16)); } catch(e) { return m; }
                });
                const lines = fullText.split('\n');
                let fragment = document.createDocumentFragment();
                let lastOffset = 0;
                let processedAnyLine = false;

                lines.forEach(line => {
                    const dramaName = extractDramaName(line);
                    if (dramaName) {
                        const lineStartIndex = fullText.indexOf(line, lastOffset);
                        if (lineStartIndex > lastOffset) fragment.appendChild(document.createTextNode(fullText.substring(lastOffset, lineStartIndex)));

                        const container = document.createElement('span');
                        container.className = 'kdrama-circle-container';

                        if (config.showGoogleCircle) {
                            const searchQuery = `${dramaName} ${config.googleSearchSuffix}`.trim();
                            const googleUrl = `https://www.google.com/search?q=${encodeURIComponent(searchQuery)}`;
                            const googleCircle = document.createElement('span');
                            googleCircle.className = 'kdrama-circle google-circle';
                            googleCircle.title = `Search '${dramaName}' on Google`;
                            googleCircle.onclick = (e) => {
                                e.stopPropagation();
                                //  USE SETTING: Check which style the user prefers
                                if (config.linkOpenStyle === 'popup') {
                                    openInCenter(googleUrl, 'sinflix_Google Search');
                                } else {
                                    window.open(googleUrl, '_blank');
                                }
                            };
                            container.appendChild(googleCircle);
                        }

                        if (config.showMdlCircle) {
                            const mdlUrl = `https://mydramalist.com/search?q=${encodeURIComponent(dramaName)}&adv=titles&ty=68&co=3&so=relevance`;
                            const mdlCircle = document.createElement('span');
                            mdlCircle.className = 'kdrama-circle mdl-circle';
                            mdlCircle.title = `Search '${dramaName}' on MyDramaList\nCtrl+Click to copy first result link`;
                            mdlCircle.onclick = async (e) => {
                                e.stopPropagation();

                                // Check if Ctrl key is pressed
                                if (e.ctrlKey) {
                                    showNotification('Getting the link...', 'info');
                                    const firstResultUrl = await getMdlFirstResultUrl(mdlUrl, dramaName);

                                    if (firstResultUrl) {
                                        const success = await copyToClipboard(firstResultUrl);
                                        if (success) {
                                            showNotification('Link copied to clipboard!', 'success');
                                        } else {
                                            showNotification('Failed to copy link to clipboard', 'error');
                                        }
                                    } else {
                                        showNotification('No results found for this drama', 'error');
                                    }
                                    return;
                                }

                                // Normal click behavior - Load page in background and get first result
                                loadMdlPageAndOpenFirstResult(mdlUrl, dramaName);
                            };
                            container.appendChild(mdlCircle);
                        }
                        fragment.appendChild(container);
                        fragment.appendChild(document.createTextNode(line));
                        processedAnyLine = true;
                    } else {
                        const lineStartIndex = fullText.indexOf(line, lastOffset);
                        if (lineStartIndex > lastOffset) fragment.appendChild(document.createTextNode(fullText.substring(lastOffset, lineStartIndex)));
                        fragment.appendChild(document.createTextNode(line));
                    }
                    fragment.appendChild(document.createTextNode('\n'));
                    lastOffset = fullText.indexOf(line, lastOffset) + line.length + 1;
                });
                if (lastOffset < fullText.length) fragment.appendChild(document.createTextNode(fullText.substring(lastOffset)));
                if (processedAnyLine && textNode.parentNode) textNode.parentNode.replaceChild(fragment, textNode);
            });
        }

        if (config.convertBuzzheavierLinks) {
             const linkWalker = document.createTreeWalker(content, NodeFilter.SHOW_TEXT, { acceptNode: n => n.parentNode.nodeName !== 'A' ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT });
             const linkNodes = [];
             let n;
             while (n = linkWalker.nextNode()) {
                 buzzRegex.lastIndex = 0;
                 if (buzzRegex.test(n.textContent)) linkNodes.push(n);
             }
             linkNodes.forEach(node => {
                 if (!document.body.contains(node) || node.parentNode.nodeName === 'A') return;
                 const fragment = document.createDocumentFragment();
                 const text = node.textContent;
                 let lastIndex = 0;
                 buzzRegex.lastIndex = 0;
                 let match;
                 while ((match = buzzRegex.exec(text)) !== null) {
                     if (match.index > lastIndex) fragment.appendChild(document.createTextNode(text.slice(lastIndex, match.index)));
                     const link = document.createElement('a');
                     link.href = `https://buzzheavier.com/${match[1]}`;
                     link.textContent = link.href;
                     link.target = '_blank';
                     fragment.appendChild(link);
                     lastIndex = match.index + match[0].length;
                 }
                 if (lastIndex < text.length) fragment.appendChild(document.createTextNode(text.slice(lastIndex)));
                 if (fragment.hasChildNodes() && node.parentNode) node.parentNode.replaceChild(fragment, node);
             });
        }

        // NEW: Process existing links to apply special behavior only to specific links
        const existingLinks = content.querySelectorAll('a[href]');
        existingLinks.forEach(link => {
            // Skip links that are already processed or are internal links
            if (link.dataset.sinflixProcessed || link.href.startsWith('#') || link.href.startsWith('javascript:')) return;

            link.dataset.sinflixProcessed = 'true';

            // Special handling for SinFlix chat box link
            if (link.href.includes('my.cbox.ws/sin-flix')) {
                // Remove existing target and click handlers
                link.removeAttribute('target');

                // Add new click handler based on chat box preference
                link.addEventListener('click', (e) => {
                    e.preventDefault();
                    e.stopPropagation();

                    openInCenter(link.href, 'sinflix_chat');
                });
            }
            // For all other links, leave them as they are (normal behavior)
        });

        console.log('Sinflix Modifier: Processing complete. ✨');

        // Mark content as processed to show all headers
        content.classList.add('sinflix-processed');

        return true;
    }

    // --- Immediate early reordering function ---
    function tryEarlyReorder() {
        if (!config.moveCurrentlyAiringToTop) return;

        const content = document.querySelector('.entry-text article');
        if (content && content.dataset.sectionsReordered !== 'true') {
            reorderSections();
        }
    }

    // --- Section Reordering Function ---
    function reorderSections() {
        const content = document.querySelector('.entry-text article');
        if (!content) {
            console.log('Sinflix Modifier: Content not found for reordering');
            return;
        }

        // Check if already reordered to avoid duplicate processing
        if (content.dataset.sectionsReordered === 'true') {
            return;
        }

        try {
            // Find all h4 elements that represent section headers
            const headersNodeList = content.querySelectorAll('h4');
            const headers = Array.from(headersNodeList);
            let currentlyAiringHeader = null;
            let insertBeforeHeader = null;

            // Find the "Currently Airing" header
            for (const header of headers) {
                if (header.textContent.trim().toLowerCase().includes('currently airing')) {
                    currentlyAiringHeader = header;
                    break;
                }
            }

            if (!currentlyAiringHeader) {
                console.log('Sinflix Modifier: "Currently Airing" section not found');
                headers.forEach(h => h.classList.add('sinflix-visible'));
                content.dataset.sectionsReordered = 'true';
                return;
            }

            // Find the insertion point dynamically:
            // The first h4 that is NOT the page-title header (index 0) and NOT Currently Airing.
            // This works regardless of what the second section is named.
            const firstH4 = headers[0];
            for (const header of headers) {
                if (header === firstH4) continue;          // skip page title
                if (header === currentlyAiringHeader) continue; // skip itself
                insertBeforeHeader = header;
                break;
            }

            if (!insertBeforeHeader) {
                console.log('Sinflix Modifier: No valid insertion point found for reordering');
                headers.forEach(h => h.classList.add('sinflix-visible'));
                content.dataset.sectionsReordered = 'true';
                return;
            }

            // Check if Currently Airing is already before the insertion point
            const airingIndex = headers.indexOf(currentlyAiringHeader);
            const insertIndex = headers.indexOf(insertBeforeHeader);

            if (airingIndex < insertIndex) {
                console.log('Sinflix Modifier: Currently Airing is already at the top');
                content.dataset.sectionsReordered = 'true';
                headers.forEach(h => h.classList.add('sinflix-visible'));
                return;
            }

            // Collect all content belonging to the "Currently Airing" section
            // (everything between the h4 and the next h4)
            const currentlyAiringContent = [];
            let currentElement = currentlyAiringHeader.nextElementSibling;
            while (currentElement && currentElement.tagName !== 'H4') {
                currentlyAiringContent.push(currentElement);
                currentElement = currentElement.nextElementSibling;
            }

            // Remove "Currently Airing" section from its current position
            currentlyAiringHeader.remove();
            currentlyAiringContent.forEach(el => el.remove());

            // Re-insert before the target section
            const parentElement = insertBeforeHeader.parentNode;
            parentElement.insertBefore(currentlyAiringHeader, insertBeforeHeader);

            let insertAfter = currentlyAiringHeader;
            currentlyAiringContent.forEach(el => {
                parentElement.insertBefore(el, insertAfter.nextSibling);
                insertAfter = el;
            });

            // Add a visual separator after the moved section if one doesn't already exist
            if (insertAfter.nextSibling && insertAfter.nextSibling.tagName !== 'HR') {
                const separator = document.createElement('hr');
                parentElement.insertBefore(separator, insertAfter.nextSibling);
            }

            // Mark as reordered to prevent duplicate processing
            content.dataset.sectionsReordered = 'true';

            // Reveal all headers now that reordering is complete
            content.querySelectorAll('h4').forEach(h => h.classList.add('sinflix-visible'));

            console.log('Sinflix Modifier: Successfully moved "Currently Airing" section to top');
        } catch (error) {
            console.error('Sinflix Modifier: Error reordering sections:', error);
            // Show all headers in case of error
            content.querySelectorAll('h4').forEach(h => h.classList.add('sinflix-visible'));
        }
    }

    // --- Settings UI ---
    function createSettingsUI() {
        const settingsButton = document.createElement('div');
        settingsButton.id = 'kdrama-settings-button';
        settingsButton.innerHTML = `<svg fill="currentColor" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"/></svg>`;
        // Only show the fixed settings button when the top search capsule is OFF
        if (!config.showTopSearchBar) {
            document.body.appendChild(settingsButton);
        }

        const modal = document.createElement('div');
        modal.id = 'kdrama-settings-modal';
        modal.innerHTML = `
            <div class="kdrama-modal-content">
                <div class="kdrama-modal-header">
                    <h2>
                        <svg class="header-icon" viewBox="0 0 24 24" fill="currentColor">
                            <path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"/>
                        </svg>
                        SinFlix Modifier Settings
                    </h2>
                    <button id="kdrama-settings-close">&times;</button>
                </div>

                <div class="kdrama-modal-body">
                    <!-- Features Section -->
                    <div class="kdrama-settings-section">
                        <h3 class="kdrama-section-title">
                            <svg class="section-icon" viewBox="0 0 24 24" fill="currentColor">
                                <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
                            </svg>
                            Features
                        </h3>

                        <div class="kdrama-toggle-item">
                            <div class="kdrama-toggle-info">
                                <div class="kdrama-toggle-label">Google Search Icons</div>
                                <div class="kdrama-toggle-description">Show blue circle icons for Google search next to drama titles</div>
                            </div>
                            <label class="kdrama-toggle-switch">
                                <input type="checkbox" id="setting-google" ${config.showGoogleCircle ? 'checked' : ''}>
                                <span class="kdrama-toggle-slider"></span>
                            </label>
                        </div>

                        <div class="kdrama-setting-item" style="margin-bottom: 20px;">
                            <div class="kdrama-toggle-info" style="margin-bottom: 8px;">
                                <div class="kdrama-toggle-label">Google Search Keyword Suffix</div>
                                <div class="kdrama-toggle-description">Appended to title when searching (e.g. "TV Series")</div>
                            </div>
                            <input type="text" id="setting-google-suffix" class="kdrama-text-input" value="${config.googleSearchSuffix.replace(/"/g, '&quot;')}" placeholder="TV Series">
                        </div>

                        <div class="kdrama-toggle-item">
                            <div class="kdrama-toggle-info">
                                <div class="kdrama-toggle-label">MyDramaList Search Icons</div>
                                <div class="kdrama-toggle-description">Show purple circle icons for MyDramaList search next to drama titles</div>
                            </div>
                            <label class="kdrama-toggle-switch">
                                <input type="checkbox" id="setting-mdl" ${config.showMdlCircle ? 'checked' : ''}>
                                <span class="kdrama-toggle-slider"></span>
                            </label>
                        </div>

                        <div class="kdrama-toggle-item">
                            <div class="kdrama-toggle-info">
                                <div class="kdrama-toggle-label">BuzzHeavier Link Conversion</div>
                                <div class="kdrama-toggle-description">Automatically convert BuzzHeavier IDs to clickable links</div>
                            </div>
                            <label class="kdrama-toggle-switch">
                                <input type="checkbox" id="setting-buzz" ${config.convertBuzzheavierLinks ? 'checked' : ''}>
                                <span class="kdrama-toggle-slider"></span>
                            </label>
                        </div>
                    </div>

                    <!-- Interface Section -->
                    <div class="kdrama-settings-section">
                        <h3 class="kdrama-section-title">
                            <svg class="section-icon" viewBox="0 0 24 24" fill="currentColor">
                                <path d="M3 17v2h6v-2H3zM3 5v2h10V5H3zm10 16v-2h8v-2h-8v-2h-2v6h2zM7 9v2H3v2h4v2h2V9H7zm14 4v-2H11v2h10zm-6-4h2V7h4V5h-4V3h-2v6z"/>
                            </svg>
                            Interface
                        </h3>

                        <div class="kdrama-toggle-item">
                            <div class="kdrama-toggle-info">
                                <div class="kdrama-toggle-label">Back to Top Button</div>
                                <div class="kdrama-toggle-description">Show floating button to quickly scroll to top of page</div>
                            </div>
                            <label class="kdrama-toggle-switch">
                                <input type="checkbox" id="setting-back-to-top" ${config.showBackToTopButton ? 'checked' : ''}>
                                <span class="kdrama-toggle-slider"></span>
                            </label>
                        </div>

                        <div class="kdrama-toggle-item">
                            <div class="kdrama-toggle-info">
                                <div class="kdrama-toggle-label">SinFlix Chat Button</div>
                                <div class="kdrama-toggle-description">Show floating button for quick access to SinFlix community chat</div>
                            </div>
                            <label class="kdrama-toggle-switch">
                                <input type="checkbox" id="setting-chat-box" ${config.showChatBoxButton ? 'checked' : ''}>
                                <span class="kdrama-toggle-slider"></span>
                            </label>
                        </div>

                        <div class="kdrama-toggle-item">
                            <div class="kdrama-toggle-info">
                                <div class="kdrama-toggle-label">Move "Currently Airing" to Top</div>
                                <div class="kdrama-toggle-description">Automatically move the Currently Airing section to the top of the page</div>
                            </div>
                            <label class="kdrama-toggle-switch">
                                <input type="checkbox" id="setting-move-airing" ${config.moveCurrentlyAiringToTop ? 'checked' : ''}>
                                <span class="kdrama-toggle-slider"></span>
                            </label>
                        </div>

                        <div class="kdrama-toggle-item">
                            <div class="kdrama-toggle-info">
                                <div class="kdrama-toggle-label">Top Search Bar</div>
                                <div class="kdrama-toggle-description">Show a Dynamic Island-style search bar at the top. Morphs into a circle icon after 5s or on scroll</div>
                            </div>
                            <label class="kdrama-toggle-switch">
                                <input type="checkbox" id="setting-top-searchbar" ${config.showTopSearchBar ? 'checked' : ''}>
                                <span class="kdrama-toggle-slider"></span>
                            </label>
                        </div>
                    </div>

                    <!-- pst.moe Section -->
                    <div class="kdrama-settings-section">
                        <h3 class="kdrama-section-title">
                            <svg class="section-icon" viewBox="0 0 24 24" fill="currentColor">
                                <path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"/>
                            </svg>
                            pst.moe
                        </h3>

                        <div class="kdrama-toggle-item">
                            <div class="kdrama-toggle-info">
                                <div class="kdrama-toggle-label">Enable pst.moe Enhancements</div>
                                <div class="kdrama-toggle-description">Convert links into hyperlinks and add "Copy All Links" option</div>
                            </div>
                            <label class="kdrama-toggle-switch">
                                <input type="checkbox" id="setting-pstmoe" ${config.pstMoeEnhancements ? 'checked' : ''}>
                                <span class="kdrama-toggle-slider"></span>
                            </label>
                        </div>

                        <div class="kdrama-toggle-item">
                            <div class="kdrama-toggle-info">
                                <div class="kdrama-toggle-label">Mega.nz Link Bypass</div>
                                <div class="kdrama-toggle-description">Add grey ● circle next to each Mega link to bypass & download instantly. Also adds "Copy Links" per section.</div>
                            </div>
                            <label class="kdrama-toggle-switch">
                                <input type="checkbox" id="setting-mega-bypass" ${config.megaBypass ? 'checked' : ''}>
                                <span class="kdrama-toggle-slider"></span>
                            </label>
                        </div>

${'showFdCircle' in config ? `
                        <div class="kdrama-toggle-item">
                            <div class="kdrama-toggle-info">
                                <div class="kdrama-toggle-label">FileDitch Download Circles</div>
                                <div class="kdrama-toggle-description">Show an orange &#9679; circle next to each fileditchfiles.me link. Clicking opens the page, auto-clicks the download button, and closes the window.</div>
                            </div>
                            <label class="kdrama-toggle-switch">
                                <input type="checkbox" id="setting-fd-resolve" ${config.showFdCircle ? 'checked' : ''}>
                                <span class="kdrama-toggle-slider"></span>
                            </label>
                        </div>
                    </div>` : '</div>'}

                    <!-- Mega.nz Section -->
                    <div class="kdrama-settings-section">
                        <h3 class="kdrama-section-title">
                            <svg class="section-icon" viewBox="0 0 24 24" fill="currentColor">
                                <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
                            </svg>
                            Mega.nz
                        </h3>

                        <div class="kdrama-toggle-item">
                            <div class="kdrama-toggle-info">
                                <div class="kdrama-toggle-label">Bypass Download Button</div>
                                <div class="kdrama-toggle-description">Show a floating button on mega.nz file pages to download via bypass instantly</div>
                            </div>
                            <label class="kdrama-toggle-switch">
                                <input type="checkbox" id="setting-mega-nz-btn" ${config.megaNzButton ? 'checked' : ''}>
                                <span class="kdrama-toggle-slider"></span>
                            </label>
                        </div>
                    </div>

                    <!-- Buzzheavier Section -->
                    <div class="kdrama-settings-section">
                        <h3 class="kdrama-section-title">
                            <svg class="section-icon" viewBox="0 0 24 24" fill="currentColor">
                                <path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/>
                            </svg>
                            Buzzheavier
                        </h3>

                        <div class="kdrama-toggle-item">
                            <div class="kdrama-toggle-info">
                                <div class="kdrama-toggle-label">Enable Buzzheavier Features</div>
                                <div class="kdrama-toggle-description">Master switch for Buzzheavier enhancements</div>
                            </div>
                            <label class="kdrama-toggle-switch">
                                <input type="checkbox" id="setting-buzz-main" ${config.buzzheavierEnhancements ? 'checked' : ''}>
                                <span class="kdrama-toggle-slider"></span>
                            </label>
                        </div>

                        <div class="kdrama-toggle-item">
                            <div class="kdrama-toggle-info">
                                <div class="kdrama-toggle-label">Split by Quality</div>
                                <div class="kdrama-toggle-description">Divide folder table into multiple tables based on resolution</div>
                            </div>
                            <label class="kdrama-toggle-switch">
                                <input type="checkbox" id="setting-buzz-split" ${config.buzzSplitQuality ? 'checked' : ''}>
                                <span class="kdrama-toggle-slider"></span>
                            </label>
                        </div>

                        <div class="kdrama-toggle-item">
                            <div class="kdrama-toggle-info">
                                <div class="kdrama-toggle-label">Direct Download Links</div>
                                <div class="kdrama-toggle-description">Add direct download button next to file links</div>
                            </div>
                            <label class="kdrama-toggle-switch">
                                <input type="checkbox" id="setting-buzz-dl" ${config.buzzDirectDownload ? 'checked' : ''}>
                                <span class="kdrama-toggle-slider"></span>
                            </label>
                        </div>

                        <div class="kdrama-toggle-item">
                            <div class="kdrama-toggle-info">
                                <div class="kdrama-toggle-label">Copy Links Button</div>
                                <div class="kdrama-toggle-description">Add button to copy all download links from table/page</div>
                            </div>
                            <label class="kdrama-toggle-switch">
                                <input type="checkbox" id="setting-buzz-copy" ${config.buzzCopyLinks ? 'checked' : ''}>
                                <span class="kdrama-toggle-slider"></span>
                            </label>
                        </div>

                    </div>

                    <!-- Link Behavior Section -->
                    <div class="kdrama-settings-section">
                        <h3 class="kdrama-section-title">
                            <svg class="section-icon" viewBox="0 0 24 24" fill="currentColor">
                                <path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"/>
                            </svg>
                            Link Behavior
                        </h3>

                        <div class="kdrama-radio-group">
                            <div class="kdrama-radio-group-title">Search Circle Icons Opening Style</div>
                            <div class="kdrama-radio-options">
                                <div class="kdrama-radio-option">
                                    <input type="radio" name="linkStyle" value="popup" id="link-popup">
                                    <label for="link-popup" class="kdrama-radio-option-label">
                                        <svg class="kdrama-radio-option-icon" viewBox="0 0 24 24" fill="currentColor">
                                            <path d="M19 7h-3V6a4 4 0 0 0-8 0v1H5a1 1 0 0 0-1 1v11a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8a1 1 0 0 0-1-1zM10 6a2 2 0 0 1 4 0v1h-4V6zm6 14a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V9h2v1a1 1 0 0 0 2 0V9h4v1a1 1 0 0 0 2 0V9h2v11z"/>
                                        </svg>
                                        Popup Window
                                    </label>
                                </div>
                                <div class="kdrama-radio-option">
                                    <input type="radio" name="linkStyle" value="tab" id="link-tab">
                                    <label for="link-tab" class="kdrama-radio-option-label">
                                        <svg class="kdrama-radio-option-icon" viewBox="0 0 24 24" fill="currentColor">
                                            <path d="M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M18,20H6V4H13V9H18V20Z"/>
                                        </svg>
                                        New Tab
                                    </label>
                                </div>
                            </div>
                        </div>

                        <div class="kdrama-radio-group" style="margin-top: 16px;">
                            <div class="kdrama-radio-group-title">Chat Box Opening Style</div>
                            <div class="kdrama-radio-options">
                                <div class="kdrama-radio-option">
                                    <input type="radio" name="chatBoxStyle" value="popup" id="chat-popup">
                                    <label for="chat-popup" class="kdrama-radio-option-label">
                                        <svg class="kdrama-radio-option-icon" viewBox="0 0 24 24" fill="currentColor">
                                            <path d="M19 7h-3V6a4 4 0 0 0-8 0v1H5a1 1 0 0 0-1 1v11a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8a1 1 0 0 0-1-1zM10 6a2 2 0 0 1 4 0v1h-4V6zm6 14a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V9h2v1a1 1 0 0 0 2 0V9h4v1a1 1 0 0 0 2 0V9h2v11z"/>
                                        </svg>
                                        Popup Window
                                    </label>
                                </div>
                                <div class="kdrama-radio-option">
                                    <input type="radio" name="chatBoxStyle" value="tab" id="chat-tab">
                                    <label for="chat-tab" class="kdrama-radio-option-label">
                                        <svg class="kdrama-radio-option-icon" viewBox="0 0 24 24" fill="currentColor">
                                            <path d="M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M18,20H6V4H13V9H18V20Z"/>
                                        </svg>
                                        New Tab
                                    </label>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="kdrama-modal-footer">
                    <button id="kdrama-save-button">
                        <svg style="width: 18px; height: 18px; margin-right: 8px; vertical-align: middle;" viewBox="0 0 24 24" fill="currentColor">
                            <path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/>
                        </svg>
                        Save Settings & Refresh
                    </button>
                </div>
            </div>
        `;
        document.body.appendChild(modal);

        //  NEW: Set the correct radio button based on saved config
        document.querySelector(`input[name="linkStyle"][value="${config.linkOpenStyle}"]`).checked = true;
        document.querySelector(`input[name="chatBoxStyle"][value="${config.chatBoxOpenStyle}"]`).checked = true;

        const saveButton = document.getElementById('kdrama-save-button');
        const closeBtn = document.getElementById('kdrama-settings-close');

        settingsButton.addEventListener('click', (e) => {
            e.preventDefault();
            e.stopPropagation();
            modal.style.display = 'flex';
            // Add a small delay for the animation
            setTimeout(() => modal.classList.add('show'), 10);
        });

        modal.addEventListener('click', (e) => {
            if (e.target === modal) {
                modal.classList.remove('show');
                setTimeout(() => modal.style.display = 'none', 200);
            }
        });

        closeBtn.addEventListener('click', (e) => {
            e.preventDefault();
            e.stopPropagation();
            modal.classList.remove('show');
            setTimeout(() => modal.style.display = 'none', 200);
        });

        // Additional escape key handler for settings modal
        document.addEventListener('keydown', (e) => {
            if (e.key === 'Escape' && modal.style.display === 'flex') {
                modal.classList.remove('show');
                setTimeout(() => modal.style.display = 'none', 200);
                e.preventDefault();
            }
        });

        saveButton.addEventListener('click', (e) => {
            e.preventDefault();
            // Save checkbox values
            GM_setValue('showGoogleCircle', document.getElementById('setting-google').checked);
            GM_setValue('showMdlCircle', document.getElementById('setting-mdl').checked);
            GM_setValue('convertBuzzheavierLinks', document.getElementById('setting-buzz').checked);
            GM_setValue('showBackToTopButton', document.getElementById('setting-back-to-top').checked);
            GM_setValue('moveCurrentlyAiringToTop', document.getElementById('setting-move-airing').checked);
            GM_setValue('showChatBoxButton', document.getElementById('setting-chat-box').checked);
            GM_setValue('pstMoeEnhancements', document.getElementById('setting-pstmoe').checked);
            GM_setValue('megaBypass', document.getElementById('setting-mega-bypass').checked);
            GM_setValue('megaNzButton', document.getElementById('setting-mega-nz-btn').checked);
            const fdEl = document.getElementById('setting-fd-resolve');
            if (fdEl) GM_setValue('showFdCircle', fdEl.checked);

            //  NEW: Save the selected radio button values
            const selectedStyle = document.querySelector('input[name="linkStyle"]:checked').value;
            GM_setValue('linkOpenStyle', selectedStyle);

            const selectedChatBoxStyle = document.querySelector('input[name="chatBoxStyle"]:checked').value;
            GM_setValue('chatBoxOpenStyle', selectedChatBoxStyle);

            GM_setValue('googleSearchSuffix', document.getElementById('setting-google-suffix').value);

            // NEW: Buzzheavier Save
            GM_setValue('buzzheavierEnhancements', document.getElementById('setting-buzz-main').checked);
            GM_setValue('buzzSplitQuality', document.getElementById('setting-buzz-split').checked);
            GM_setValue('buzzDirectDownload', document.getElementById('setting-buzz-dl').checked);
            GM_setValue('buzzCopyLinks', document.getElementById('setting-buzz-copy').checked);

            const customSchemeEl = document.getElementById('setting-buzz-custom-scheme');
            if (customSchemeEl) GM_setValue('buzzCustomScheme', customSchemeEl.value);

            // NEW: Top search bar toggle
            GM_setValue('showTopSearchBar', document.getElementById('setting-top-searchbar').checked);

            location.reload();
        });
    }

    // --- Floating Action Buttons (Back to Top & Search) ---
    let highlightedElements = [];
    let currentMatchIndex = -1;

    function createFloatingButtons() {
        const backToTopBtn = document.createElement('button');
        backToTopBtn.id = 'kdrama-back-to-top';
        backToTopBtn.className = 'kdrama-float-button';
        backToTopBtn.setAttribute('aria-label', 'Back to top');
        backToTopBtn.title = 'Back to top';
        backToTopBtn.innerHTML = `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" style="display: block; margin: auto;"><polyline points="6 15 12 9 18 15"></polyline></svg>`;
        document.body.appendChild(backToTopBtn);

        // Chat button: only show as floating button when top search capsule is OFF
        let chatBtn = null;
        if (config.showChatBoxButton && !config.showTopSearchBar) {
            chatBtn = document.createElement('button');
            chatBtn.id = 'kdrama-chat-button';
            chatBtn.className = 'kdrama-float-button show';
            chatBtn.setAttribute('aria-label', 'Open SinFlix Chat');
            chatBtn.title = 'SinFlix Chat';
            chatBtn.innerHTML = `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m3 21 1.9-5.7a8.5 8.5 0 1 1 3.8 3.8z"></path></svg>`;
            document.body.appendChild(chatBtn);
        }

        function updateButtonPositions() {
            const baseBottom = 30;
            const buttonSpacing = 54;

            // Position chat button if enabled
            if (config.showChatBoxButton && chatBtn) {
                chatBtn.style.bottom = `${baseBottom}px`;
            }

            // Position back-to-top button at the top of the stack (it will handle its own visibility)
            const topPosition = config.showChatBoxButton ? baseBottom + buttonSpacing : baseBottom;
            backToTopBtn.style.bottom = `${topPosition}px`;
        }

        function updateButtonPositionsWithAnimation() {
            const baseBottom = 30;
            const buttonSpacing = 54;
            let currentBottom = baseBottom;

            // Calculate positions based on visible buttons
            const isBackToTopVisible = backToTopBtn.classList.contains('show');

            if (isBackToTopVisible) {
                // Back-to-top is visible, so other buttons move up
                backToTopBtn.style.bottom = `${currentBottom}px`;
                currentBottom += buttonSpacing;
            }

            // Chat button position (if enabled)
            if (config.showChatBoxButton && chatBtn) {
                chatBtn.style.bottom = `${currentBottom}px`;
            }
        }
        updateButtonPositions();

        window.addEventListener('scroll', () => {
            const scrollThreshold = 200;
            const shouldShowBackToTop = window.scrollY > scrollThreshold && config.showBackToTopButton;
            const isCurrentlyShowing = backToTopBtn.classList.contains('show');

            if (shouldShowBackToTop && !isCurrentlyShowing) {
                // Show back-to-top button and animate other buttons
                backToTopBtn.classList.add('show');
                updateButtonPositionsWithAnimation();
            } else if (!shouldShowBackToTop && isCurrentlyShowing) {
                // Hide back-to-top button and animate other buttons
                backToTopBtn.classList.remove('show');
                updateButtonPositionsWithAnimation();
            }
        });

        backToTopBtn.addEventListener('click', () => {
            window.scrollTo({ top: 0, behavior: 'smooth' });
        });

        // NEW: Add chat button click handler
        if (config.showChatBoxButton && chatBtn) {
            chatBtn.addEventListener('click', () => {
                const chatUrl = 'https://my.cbox.ws/sin-flix';
                openInCenter(chatUrl, 'sinflix_chat');
            });
        }
    }

    // --- Top Search Bar (Dynamic Island) ---
    function createTopSearchBar() {
        if (!config.showTopSearchBar) return;

        // The wrapper pill/circle
        const wrap = document.createElement('div');
        wrap.id = 'sfx-top-searchbar-wrap';

        // Search icon
        const iconEl = document.createElement('span');
        iconEl.id = 'sfx-top-search-icon';
        iconEl.innerHTML = `<svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>`;
        wrap.appendChild(iconEl);

        // Collapsed label (hidden when expanded, visible when collapsed)
        const labelEl = document.createElement('span');
        labelEl.id = 'sfx-top-search-label';
        labelEl.textContent = 'Search';
        wrap.appendChild(labelEl);

        // Text input
        const input = document.createElement('input');
        input.id = 'sfx-top-search-input';
        input.type = 'text';
        input.placeholder = 'Search on page…';
        input.setAttribute('autocomplete', 'off');
        input.setAttribute('spellcheck', 'false');
        wrap.appendChild(input);

        // Match counter
        const counter = document.createElement('span');
        counter.id = 'sfx-top-search-count';
        wrap.appendChild(counter);

        // Prev / Next buttons
        const prevBtn = document.createElement('button');
        prevBtn.className = 'sfx-top-nav-btn';
        prevBtn.title = 'Previous match';
        prevBtn.disabled = true;
        prevBtn.innerHTML = `<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="18 15 12 9 6 15"/></svg>`;
        wrap.appendChild(prevBtn);

        const nextBtn = document.createElement('button');
        nextBtn.className = 'sfx-top-nav-btn';
        nextBtn.title = 'Next match';
        nextBtn.disabled = true;
        nextBtn.innerHTML = `<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="6 9 12 15 18 9"/></svg>`;
        wrap.appendChild(nextBtn);

        // Close / collapse button
        const closeBtn = document.createElement('button');
        closeBtn.id = 'sfx-top-search-close';
        closeBtn.title = 'Dismiss search bar';
        closeBtn.innerHTML = '&times;';
        wrap.appendChild(closeBtn);

        // Separator between search controls and utility icons
        const capSep = document.createElement('span');
        capSep.className = 'sfx-cap-sep';
        wrap.appendChild(capSep);

        // Settings icon button (inside capsule)
        const capSettings = document.createElement('button');
        capSettings.className = 'sfx-cap-action';
        capSettings.title = 'Settings';
        capSettings.innerHTML = `<svg viewBox="0 0 24 24" fill="currentColor"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"/></svg>`;
        capSettings.addEventListener('click', (e) => {
            e.stopPropagation();
            const modal = document.getElementById('kdrama-settings-modal');
            if (modal) { modal.style.display = 'flex'; setTimeout(() => modal.classList.add('show'), 10); }
        });
        wrap.appendChild(capSettings);

        // Chat icon button (inside capsule, only if enabled)
        if (config.showChatBoxButton) {
            const capChat = document.createElement('button');
            capChat.className = 'sfx-cap-action';
            capChat.title = 'SinFlix Chat';
            capChat.innerHTML = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m3 21 1.9-5.7a8.5 8.5 0 1 1 3.8 3.8z"></path></svg>`;
            capChat.addEventListener('click', (e) => {
                e.stopPropagation();
                const chatUrl = 'https://my.cbox.ws/sin-flix';
                openInCenter(chatUrl, 'sinflix_chat');
            });
            wrap.appendChild(capChat);
        }

        document.body.appendChild(wrap);

        // ---- State: start collapsed ----
        let isCollapsed = true;
        wrap.classList.add('sfx-collapsed');
        let sfxHighlights = [];
        let sfxCurrentIdx = -1;

        // ---- Collapse / expand helpers ----
        function collapse() {
            if (isCollapsed) return;
            isCollapsed = true;
            wrap.classList.add('sfx-collapsed');
            input.blur();
        }

        function expand() {
            if (!isCollapsed) return;
            isCollapsed = false;
            wrap.classList.remove('sfx-collapsed');
            // Small bounce feedback
            wrap.classList.add('sfx-expanding');
            setTimeout(() => wrap.classList.remove('sfx-expanding'), 600);
            // Focus input after animation settles
            setTimeout(() => input.focus(), 200);
        }

        // ---- Search highlight logic ----
        function clearSfxHighlights() {
            sfxHighlights.forEach(el => {
                const parent = el.parentNode;
                if (parent) {
                    parent.replaceChild(document.createTextNode(el.textContent), el);
                    parent.normalize();
                }
            });
            sfxHighlights = [];
            sfxCurrentIdx = -1;
        }

        function runSfxSearch(query) {
            clearSfxHighlights();

            if (!query || query.length < 1) {
                counter.textContent = '';
                prevBtn.disabled = true;
                nextBtn.disabled = true;
                return;
            }

            const lq = query.toLowerCase();

            // Only search inside the article content (drama list)
            const article = document.querySelector('.entry-text article');
            if (!article) {
                counter.textContent = 'No content';
                return;
            }

            // Walk text nodes inside the article, skipping links and script/style
            const walker = document.createTreeWalker(article, NodeFilter.SHOW_TEXT, {
                acceptNode: n => {
                    const el = n.parentElement;
                    if (!el) return NodeFilter.FILTER_REJECT;
                    const tag = el.tagName;
                    if (['SCRIPT','STYLE','NOSCRIPT','A'].includes(tag)) return NodeFilter.FILTER_REJECT;
                    if (el.closest('a')) return NodeFilter.FILTER_REJECT; // skip nested link text
                    return n.textContent.trim() ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
                }
            });

            const textNodes = [];
            let node;
            while ((node = walker.nextNode())) textNodes.push(node);

            textNodes.forEach(tn => {
                const fullText = tn.textContent;
                // Process line by line — only highlight within drama name lines
                const lines = fullText.split('\n');
                let anyMatch = false;
                const frag = document.createDocumentFragment();

                lines.forEach((line, lineIdx) => {
                    const dramaName = extractDramaName(line);
                    if (dramaName && dramaName.toLowerCase().includes(lq)) {
                        // This line has a drama name that matches — highlight occurrences of query
                        const lLine = line.toLowerCase();
                        let last = 0;
                        let pos = lLine.indexOf(lq);
                        while (pos !== -1) {
                            if (pos > last) frag.appendChild(document.createTextNode(line.slice(last, pos)));
                            const mark = document.createElement('mark');
                            mark.className = 'kdrama-highlight';
                            mark.textContent = line.slice(pos, pos + lq.length);
                            frag.appendChild(mark);
                            sfxHighlights.push(mark);
                            last = pos + lq.length;
                            pos = lLine.indexOf(lq, last);
                        }
                        if (last < line.length) frag.appendChild(document.createTextNode(line.slice(last)));
                        anyMatch = true;
                    } else {
                        frag.appendChild(document.createTextNode(line));
                    }
                    // Re-add the newline between lines (but not after the very last)
                    if (lineIdx < lines.length - 1) frag.appendChild(document.createTextNode('\n'));
                });

                if (anyMatch && tn.parentNode) tn.parentNode.replaceChild(frag, tn);
            });

            if (sfxHighlights.length === 0) {
                counter.textContent = 'No results';
                prevBtn.disabled = true;
                nextBtn.disabled = true;
            } else {
                sfxCurrentIdx = 0;
                jumpToSfxMatch(0);
                prevBtn.disabled = false;
                nextBtn.disabled = false;
            }
        }

        function jumpToSfxMatch(idx) {
            sfxHighlights.forEach((el, i) => el.classList.toggle('current', i === idx));
            const el = sfxHighlights[idx];
            if (el) {
                el.scrollIntoView({ behavior: 'smooth', block: 'center' });
                counter.textContent = `${idx + 1} / ${sfxHighlights.length}`;
            }
        }

        // ---- Events ----
        let searchDebounce = null;
        const triggerSearch = () => {
            clearTimeout(searchDebounce);
            searchDebounce = setTimeout(() => runSfxSearch(input.value.trim()), 280);
        };

        input.addEventListener('input', triggerSearch);

        // Collapse on blur only when no active search results.
        // While results are shown the user needs the bar to navigate between them.
        input.addEventListener('blur', e => {
            if (sfxHighlights.length > 0) return;      // keep open while navigating results
            if (wrap.contains(e.relatedTarget)) return; // keep open when focusing bar buttons
            collapse();
        });

        input.addEventListener('keydown', e => {
            if (e.key === 'Enter') {
                if (sfxHighlights.length === 0) return;
                sfxCurrentIdx = e.shiftKey
                    ? (sfxCurrentIdx - 1 + sfxHighlights.length) % sfxHighlights.length
                    : (sfxCurrentIdx + 1) % sfxHighlights.length;
                jumpToSfxMatch(sfxCurrentIdx);
            } else if (e.key === 'Escape') {
                collapse();
            }
        });

        prevBtn.addEventListener('click', () => {
            if (sfxHighlights.length === 0) return;
            sfxCurrentIdx = (sfxCurrentIdx - 1 + sfxHighlights.length) % sfxHighlights.length;
            jumpToSfxMatch(sfxCurrentIdx);
            input.focus();
        });

        nextBtn.addEventListener('click', () => {
            if (sfxHighlights.length === 0) return;
            sfxCurrentIdx = (sfxCurrentIdx + 1) % sfxHighlights.length;
            jumpToSfxMatch(sfxCurrentIdx);
            input.focus();
        });

        closeBtn.addEventListener('click', e => {
            e.stopPropagation();
            clearSfxHighlights();
            input.value = '';
            counter.textContent = '';
            prevBtn.disabled = true;
            nextBtn.disabled = true;
            collapse();
        });

        // Clicking the collapsed circle expands it
        wrap.addEventListener('click', e => {
            if (isCollapsed) {
                expand();
            }
        });

        // Collapse on user scroll only when no active search results.
        let scrollListenerActive = false;
        setTimeout(() => { scrollListenerActive = true; }, 300);
        window.addEventListener('scroll', () => {
            if (!scrollListenerActive) return;
            if (sfxHighlights.length > 0) return; // keep open while navigating results
            if (!isCollapsed) collapse();
        }, { passive: true });

        // Clicking anywhere outside the bar always collapses it (even with active results).
        document.addEventListener('click', e => {
            if (!isCollapsed && !wrap.contains(e.target)) {
                collapse();
            }
        }, { capture: true, passive: true });
    }


    // --- FileDitch page handler: auto-clicks the download button and closes the popup ---
    // Runs on fileditchfiles.me when the page is opened by the orange circle button.
    function handleFileDitchPage() {
        if (!window.location.hostname.includes('fileditchfiles.me')) return;
        if (!window.opener) return;

        function tryClick() {
            const btn = document.querySelector('a.btn.btn-main[download], a.btn-main[download]');
            if (!btn || !btn.href) return false;
            btn.click();
            setTimeout(() => { try { window.close(); } catch(_) {} }, 3000);
            return true;
        }

        if (!tryClick()) {
            // Button not in DOM yet — wait for it
            const obs = new MutationObserver(() => {
                if (tryClick()) obs.disconnect();
            });
            obs.observe(document.body || document.documentElement, { childList: true, subtree: true });
            // Give up after 15s and close
            setTimeout(() => { obs.disconnect(); try { window.close(); } catch(_) {} }, 15000);
        }
    }

    // --- Mega.nz Floating Bypass Button ---
    function enhanceMegaNzPage() {
        if (!config.megaNzButton) return;
        if (!window.location.hostname.includes('mega.nz')) return;
        // Only act on file pages
        if (!window.location.href.includes('/file/')) return;

        GM_addStyle(`
            #sinflix-mega-bypass-btn {
                position: fixed;
                bottom: 28px;
                left: 50%;
                transform: translateX(-50%);
                z-index: 99999;
                display: inline-flex;
                align-items: center;
                gap: 10px;
                padding: 0 24px;
                height: 48px;
                border-radius: 24px;
                border: 1px solid rgba(217, 39, 46, 0.45);
                background: rgba(28, 28, 28, 0.92);
                backdrop-filter: blur(14px);
                -webkit-backdrop-filter: blur(14px);
                color: #ffffff;
                font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
                font-size: 14px;
                font-weight: 600;
                letter-spacing: 0.2px;
                cursor: pointer;
                white-space: nowrap;
                box-shadow: 0 4px 24px rgba(0,0,0,0.55), inset 0 1px 0 rgba(255,255,255,0.06);
                transition: background 0.2s ease, border-color 0.2s ease,
                            box-shadow 0.2s ease, transform 0.15s ease;
                user-select: none;
            }
            #sinflix-mega-bypass-btn:hover {
                background: rgba(217, 39, 46, 0.88);
                border-color: rgba(217, 39, 46, 0.9);
                box-shadow: 0 6px 28px rgba(217,39,46,0.35), 0 2px 8px rgba(0,0,0,0.4);
                transform: translateX(-50%) translateY(-2px);
            }
            #sinflix-mega-bypass-btn:active {
                transform: translateX(-50%) translateY(0px);
                box-shadow: 0 2px 12px rgba(217,39,46,0.25);
            }
            #sinflix-mega-bypass-btn .sfx-mega-icon {
                width: 18px;
                height: 18px;
                opacity: 0.9;
                flex-shrink: 0;
            }
            #sinflix-mega-bypass-btn .sfx-mega-badge {
                font-size: 10px;
                font-weight: 700;
                color: #d9272e;
                background: rgba(217,39,46,0.15);
                border: 1px solid rgba(217,39,46,0.35);
                border-radius: 4px;
                padding: 1px 5px;
                letter-spacing: 0.5px;
                text-transform: uppercase;
            }
        `);

        const btn = document.createElement('button');
        btn.id = 'sinflix-mega-bypass-btn';
        btn.title = 'Download via bypass — skips Mega quota limits';
        btn.innerHTML = `
            <svg class="sfx-mega-icon" viewBox="0 0 24 24" fill="none"
                 stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
                <polyline points="7 10 12 15 17 10"/>
                <line x1="12" y1="15" x2="12" y2="3"/>
            </svg>
            <span>Download</span>
            <span class="sfx-mega-badge">Bypass</span>`;

        // Wait for body to be ready then append
        const appendBtn = () => document.body && document.body.appendChild(btn);
        if (document.body) appendBtn();
        else document.addEventListener('DOMContentLoaded', appendBtn);

        btn.addEventListener('click', () => {
            const bypassUrl = getMegaBypassUrl(window.location.href);
            showNotification('Download started…', 'success', 2500);
            triggerDownload(bypassUrl);
        });
    }

    // --- Enhanced Initialization ---
    function initialize() {
        if (window.location.hostname === 'pst.moe') {
            try {
                enhancePstMoeContent();
            } catch (e) {
                console.error('Sinflix Modifier error during pst.moe enhancement:', e);
            }
            // For pst.moe, we just setup the UI and stop rentry-specific logic
            createSettingsUI();
            return;
        }

        if (window.location.hostname.includes('fileditchfiles.me')) {
            try { handleFileDitchPage(); } catch(e) {
                console.error('Sinflix Modifier error on fileditchfiles.me:', e);
            }
            return;
        }

        if (window.location.hostname.includes('mega.nz')) {
            try {
                enhanceMegaNzPage();
            } catch (e) {
                console.error('Sinflix Modifier error during mega.nz enhancement:', e);
            }
            // No settings gear on mega.nz — keep the page clean
            return;
        }

        if (window.location.hostname.includes('buzzheavier.com')) {
            try {
                enhanceBuzzheavierContent();
            } catch (e) {
                console.error('Sinflix Modifier error during buzzheavier enhancement:', e);
            }
            createSettingsUI();
            return;
        }

        // Immediate content enhancement - no delay
        try {
            enhancePageContent();
        } catch (e) {
            console.error('Sinflix Modifier error during immediate enhancement:', e);
        }



        createSettingsUI();
        createFloatingButtons();
        createTopSearchBar();

        const settingsModal = document.getElementById('kdrama-settings-modal');
        window.addEventListener('scroll', () => {
            if (settingsModal && settingsModal.style.display === 'flex') {
                if (document.activeElement !== document.getElementById('kdrama-search-input')) {
                    settingsModal.style.display = 'none';
                }
            }
        });

        // Single late-fallback retry in case the MutationObserver missed the content
        // (e.g. content was already in the DOM but not yet observed). Fires after
        // the page is fully interactive to avoid blocking early user input.
        setTimeout(() => {
            try {
                enhancePageContent();
            } catch (e) {
                console.error('Sinflix Modifier error during fallback enhancement:', e);
            }
        }, 1200);

        if (typeof MutationObserver !== 'undefined') {
            // Debounce: wait 150ms after the last mutation before processing.
            // This prevents dozens of expensive TreeWalker scans from firing
            // back-to-back during the initial page load, which would block
            // the main thread and make clicks unresponsive.
            let mutationTimer = null;
            const debouncedEnhance = () => {
                clearTimeout(mutationTimer);
                mutationTimer = setTimeout(() => {
                    try {
                        enhancePageContent();
                    } catch (e) {
                        console.error('Sinflix Modifier error during MutationObserver processing:', e);
                    }
                }, 150);
            };

            const observer = new MutationObserver((mutations) => {
                let shouldProcess = false;
                mutations.forEach((mutation) => {
                    if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                        if (mutation.target.closest('.entry-text article') || mutation.target.matches('.entry-text article')) {
                            shouldProcess = true;
                        }
                    }
                });

                if (shouldProcess) {
                    debouncedEnhance();
                }
            });

            const content = document.querySelector('.entry-text article');
            if (content) {
                observer.observe(content, { childList: true, subtree: true });
                // Also process immediately if content already exists
                try {
                    enhancePageContent();
                } catch (e) {
                    console.error('Sinflix Modifier error during immediate content processing:', e);
                }
            } else {
                const bodyObserver = new MutationObserver((mutations, obs) => {
                    if (document.querySelector('.entry-text article')) {
                        obs.disconnect();
                        const foundContent = document.querySelector('.entry-text article');
                        observer.observe(foundContent, { childList: true, subtree: true });
                        debouncedEnhance();
                    }
                });
                bodyObserver.observe(document.body, { childList: true, subtree: true });
            }
        }
    }

    // Initialize the script — single entry point to avoid main-thread contention.
    // Previously, enhancePageContent() was fired 5+ times simultaneously
    // (script-start, readystatechange, DOMContentLoaded, setInterval × N),
    // blocking the main thread for 1-2 s and making clicks/scrolls unresponsive.
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initialize);
    } else {
        initialize();
    }
})();
// ---