绅士阅读器

多站点通用阅读框架,为 E-Hentai、18comic、4KHD 等提供无限滚动、全屏阅读模式、智能预取与硬件加速解码

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

Advertisement:

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

Advertisement:

// ==UserScript==
// @name               Hentai Reader
// @name:zh-CN         绅士阅读器
// @namespace          http://tampermonkey.net/
// @version            3.0.0
// @author             Viki
// @description        A generalized multi-site reading framework. Provides an enhanced reading experience with infinite scroll, full-screen reader mode, and smart image loading for E-Hentai, 18comic, 4KHD, etc.
// @description:zh-CN  多站点通用阅读框架,为 E-Hentai、18comic、4KHD 等提供无限滚动、全屏阅读模式、智能预取与硬件加速解码
// @license            MIT
// @icon               data:image/png;base64,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
// @homepageURL        https://github.com/Leovikii/Hentai-Reader
// @match              https://e-hentai.org/g/*
// @match              https://exhentai.org/g/*
// @match              https://e-hentai.org/s/*
// @match              https://exhentai.org/s/*
// @match              *://*.4khd.com/*
// @match              *://*.xxtt.ink/*
// @match              *://*.uuss.uk/*
// @match              *://*.ssuu.uk/*
// @match              *://*.18comic.vip/*
// @match              *://*.18comic.ink/*
// @grant              GM_addStyle
// @grant              GM_getValue
// @grant              GM_registerMenuCommand
// @grant              GM_setValue
// @grant              unsafeWindow
// ==/UserScript==

(function () {
  'use strict';

  const d=new Set;const importCSS = async e=>{d.has(e)||(d.add(e),(t=>{typeof GM_addStyle=="function"?GM_addStyle(t):(document.head||document.documentElement).appendChild(document.createElement("style")).append(t);})(e));};

  importCSS(" *,:before,:after{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 rgb(0 0 0 / 0);--un-ring-shadow:0 0 rgb(0 0 0 / 0);--un-shadow-inset: ;--un-shadow:0 0 rgb(0 0 0 / 0);--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgb(147 197 253 / .5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }::backdrop{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 rgb(0 0 0 / 0);--un-ring-shadow:0 0 rgb(0 0 0 / 0);--un-shadow-inset: ;--un-shadow:0 0 rgb(0 0 0 / 0);--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgb(147 197 253 / .5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: } ");

  const stylesCss = ':root{--accent: #F596AA;--accent-hover: #F7ABBE}html.scroll-mode{background-color:#111!important;color:#ccc!important;overflow-x:hidden}html.scroll-mode body{background-color:#111!important;color:#ccc!important;margin:0;overflow:visible!important}html.scroll-mode #gdt{display:flex;flex-direction:column;align-items:center;width:100%;max-width:1200px;margin:auto;padding-bottom:100px}.page-batch{width:100%;display:flex;flex-direction:column;align-items:center;margin-bottom:60px}.r-img{display:block;width:auto;max-width:100%;margin-bottom:20px;background:transparent;box-shadow:0 0 20px #00000080;position:relative}.r-ph{color:#555;margin-bottom:50px;text-align:center;min-height:400px;display:flex;align-items:center;justify-content:center;font-family:sans-serif;font-size:18px;border:1px dashed #333;width:100%;flex-direction:column;gap:10px}.r-ph.loading{color:#888;border-color:#555}.r-ph.error{color:#d44;border-color:#d44}.retry-btn{padding:8px 16px;background:#333;color:#fff;border:none;border-radius:4px;cursor:pointer;font-size:14px;margin-top:10px}.retry-btn:hover{background:#555}.sp-virtualized{content-visibility:hidden}.float-control{position:fixed;right:30px;bottom:30px;z-index:2147483647;display:flex;flex-direction:row;align-items:center;transition:opacity .3s,transform .3s;-webkit-user-select:none;user-select:none;opacity:.4}.float-control:hover{opacity:1}.float-control.hidden{opacity:0;pointer-events:none}.side-btn.top-btn{position:absolute;bottom:calc(100% + 10px);left:50%;transform:translate(-50%);opacity:.3;pointer-events:auto}.float-control:hover .side-btn.top-btn{opacity:.8}.side-btn.top-btn:hover{opacity:1!important;background:#555;transform:translate(-50%) scale(1.1)}.side-btn{width:36px;height:36px;background:#333;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .3s;opacity:0;pointer-events:none}.float-control:hover .side-btn{opacity:1;pointer-events:auto}.side-btn:hover{background:#555;transform:scale(1.1)}.side-btn svg{width:18px;height:18px;fill:#fff}.side-btn.active{background:var(--accent)}.side-btn.active:hover{background:var(--accent-hover)}.auto-play-btn.hidden{display:none}.circle-control{position:relative;width:50px;height:50px;background:#1a1a1a;border:2px solid #555;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .3s;box-shadow:0 4px 12px #00000080;margin:0 6px}.circle-control:hover{border-color:#888;box-shadow:0 6px 16px #000000b3;transform:scale(1.05)}.circle-control svg{width:24px;height:24px;fill:#fff}.settings-btn{cursor:pointer}.settings-panel{position:absolute;bottom:calc(100% + 10px);right:0;background:#1a1a1a;border:1px solid #555;border-radius:8px;padding:12px;min-width:180px;opacity:0;pointer-events:none;transition:all .3s;box-shadow:0 4px 12px #00000080;transform:translateY(5px)}.settings-panel.show{opacity:1;pointer-events:auto;transform:translateY(0)}.settings-item{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px;font-size:13px;color:#ccc}.settings-item:last-child{margin-bottom:0}.settings-label{margin-right:10px;white-space:nowrap}.toggle-switch{width:40px;height:20px;background:#333;border-radius:10px;position:relative;cursor:pointer;transition:background .3s}.toggle-switch.on{background:var(--accent)}.toggle-slider{width:16px;height:16px;background:#fff;border-radius:50%;position:absolute;top:2px;left:2px;transition:left .3s}.toggle-switch.on .toggle-slider{left:22px}.interval-input{width:60px;background:#333;border:1px solid #555;border-radius:4px;color:#fff;padding:4px 8px;font-size:12px;text-align:center}.interval-input:focus{outline:none;border-color:#888}.single-page-overlay{position:fixed;top:0;right:0;bottom:0;left:0;width:100vw;height:100vh;background-color:#000!important;z-index:2147483646;display:none;align-items:center;justify-content:center}.single-page-overlay.active{display:flex}.sp-image-container{width:100%;height:100%;display:flex;align-items:center;justify-content:center;position:relative}.sp-current-image{width:100%;height:100%;object-fit:contain;-webkit-user-select:none;user-select:none;transition:opacity .1s}.sp-current-image:not([src]),.sp-current-image[src=""]{opacity:0}.sp-close-btn{position:absolute;top:20px;right:20px;width:40px;height:40px;background:#333c;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:24px;color:#fff;transition:all .3s;z-index:10}.sp-close-btn:hover{background:#555555e6;transform:scale(1.1)}.sp-sidebar-track{position:absolute;right:12px;top:10%;width:12px;height:80%;background:#2828284d;border-radius:6px;z-index:10;pointer-events:none;opacity:0;transition:opacity .3s,background .3s}.sp-sidebar-track.active{opacity:1;pointer-events:auto}.sp-sidebar-track:hover{background:#32323280}.sp-sidebar-thumb{position:absolute;left:0;width:100%;min-height:60px;background:#fff6;border-radius:6px;transition:background .3s;cursor:grab;-webkit-user-select:none;user-select:none}.sp-sidebar-thumb:hover{background:#fff9}.sp-sidebar-thumb:active{cursor:grabbing;background:#ffffffb3}.sp-sidebar-label{position:absolute;right:calc(100% + 16px);top:50%;transform:translateY(-50%);background:#1a1a1af2;padding:8px 14px;border-radius:8px;color:#fff;font-family:monospace;font-size:14px;white-space:nowrap;opacity:0;pointer-events:none;transition:opacity .3s;box-shadow:0 2px 8px #0000004d}.sp-sidebar-track:hover .sp-sidebar-label{opacity:1}.sp-thumb-panel{position:absolute;right:12px;top:10%;max-height:80%;height:fit-content;width:116px;background:#141414f2;border-radius:8px;border:1px solid rgba(255,255,255,.1);box-shadow:-4px 4px 16px #00000080;overflow:hidden;pointer-events:none;display:flex;flex-direction:column;z-index:11;opacity:0;transform:translate(20px);transition:opacity .3s,transform .3s cubic-bezier(.2,.8,.2,1);-webkit-user-select:none;user-select:none}.sp-thumb-panel.active{opacity:1;transform:translate(0);pointer-events:auto}.sp-thumb-viewport{flex:1;min-height:0;width:100%;overflow:hidden;position:relative}.sp-thumb-content{position:relative;width:100%}.sp-thumb-item{position:absolute;left:8px;width:100px;height:72px;border-radius:4px;overflow:hidden;cursor:pointer;border:2px solid transparent;transition:border-color .15s;box-sizing:border-box}.sp-thumb-item:hover{border-color:#fff6}.sp-thumb-item.sp-thumb-active{border-color:var(--accent)}.sp-thumb-img{width:100%;height:100%;object-fit:cover;pointer-events:none}.sp-thumb-label{position:absolute;bottom:0;right:0;padding:1px 5px;background:#00000080;color:#fff9;font-family:monospace;font-size:11px;border-radius:4px 0 0;pointer-events:none}.sp-thumb-ph{width:100%;height:100%;background:#222;display:flex;align-items:center;justify-content:center;color:#555;font-family:monospace;font-size:13px;-webkit-user-select:none;user-select:none}.sp-thumb-counter{padding:8px 0;text-align:center;color:#999;font-family:monospace;font-size:13px;border-top:1px solid rgba(255,255,255,.08);-webkit-user-select:none;user-select:none}.sp-hud-container{position:absolute;top:40px;left:50%;transform:translate(-50%);z-index:100;opacity:0;pointer-events:none;transition:opacity .3s ease,transform .3s ease}.sp-hud-container.show{opacity:1;pointer-events:auto;transform:translate(-50%)}.sp-hud-box{display:flex;align-items:center;gap:10px;background:#141414b3;border:1px solid rgba(255,255,255,.1);padding:10px 20px;border-radius:30px;box-shadow:0 4px 16px #00000080;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);transition:all .2s}.sp-hud-box.hud-error{background:#b41e1eb3;border-color:#ff64644d}.sp-hud-box.hud-error:hover{background:#dc2828cc}.sp-hud-text{font-size:14px;color:#f3f4f6;font-family:sans-serif;font-weight:500;letter-spacing:.5px;white-space:nowrap;-webkit-user-select:none;user-select:none}.sp-hud-page{font-size:13px;color:#ffffff80;font-family:monospace;letter-spacing:1px;margin-left:6px;padding-left:10px;border-left:1px solid rgba(255,255,255,.2);-webkit-user-select:none;user-select:none}';
  importCSS(stylesCss);
  var _GM_getValue = (() => typeof GM_getValue != "undefined" ? GM_getValue : void 0)();
  var _GM_registerMenuCommand = (() => typeof GM_registerMenuCommand != "undefined" ? GM_registerMenuCommand : void 0)();
  var _GM_setValue = (() => typeof GM_setValue != "undefined" ? GM_setValue : void 0)();
  const CFG = {
    nextPage: "3000px 0px",
    maxRetries: 3,
    retryDelay: 1e3,
    maxConcurrent: 3,
    requestSpacing: 100,
    imageLoadTimeout: 8e3
  };
  function loadSettings(adapterName) {
    const prefix = adapterName ? `${adapterName}_` : "";
    const is4KHD = adapterName === "4KHD";
    const globalScrollMode = _GM_getValue("scrollMode", true);
    return {
      scrollMode: _GM_getValue(`${prefix}scrollMode`, is4KHD ? true : globalScrollMode),
      showControl: _GM_getValue("showControl", true),
      autoEnterSinglePage: _GM_getValue("autoEnterSinglePage", false),
      autoPlayInterval: _GM_getValue("autoPlayInterval", 3e3)
    };
  }
  class Store {
constructor() {
      this.listeners = new Map();
      this.activeAdapter = null;
      this.currPage = 1;
      this.totalPage = 1;
      this.perPage = 20;
      this.imageOffset = 0;
      this.nextUrl = null;
      this.prevUrl = null;
      this.isFetching = false;
      this.nextPagePrefetched = false;
      this.currentImageIndex = 0;
      this.allImages = [];
      this.autoPlayTimer = null;
      this.autoPlay = false;
      this._settings = loadSettings();
    }
    get settings() {
      return this._settings;
    }
    reloadSettings() {
      var _a;
      this._settings = loadSettings((_a = this.activeAdapter) == null ? void 0 : _a.name);
    }
    updateSetting(key, value) {
      this._settings[key] = value;
      if (key === "scrollMode" && this.activeAdapter) {
        _GM_setValue(`${this.activeAdapter.name}_scrollMode`, value);
      } else {
        _GM_setValue(key, value);
      }
      this.emit("settingsChanged");
    }
    on(event, listener) {
      if (!this.listeners.has(event)) {
        this.listeners.set(event, new Set());
      }
      this.listeners.get(event).add(listener);
    }
    emit(event) {
      var _a;
      (_a = this.listeners.get(event)) == null ? void 0 : _a.forEach((fn) => fn());
    }
  }
  const store = new Store();
  const q = (selector, root = document) => root.querySelector(selector);
  const qa = (selector, root = document) => root.querySelectorAll(selector);
  function isImageReady(img) {
    if (img.dataset.realSrc) return true;
    return !!(img && img.src && !img.src.includes("data:") && img.complete && img.naturalWidth > 0);
  }
  let toastContainer = null;
  function showToast(msg, duration = 3e3) {
    if (!toastContainer) {
      toastContainer = document.createElement("div");
      toastContainer.style.position = "fixed";
      toastContainer.style.top = "20px";
      toastContainer.style.left = "50%";
      toastContainer.style.transform = "translateX(-50%)";
      toastContainer.style.zIndex = "2147483647";
      toastContainer.style.pointerEvents = "none";
      toastContainer.style.display = "flex";
      toastContainer.style.flexDirection = "column";
      toastContainer.style.gap = "8px";
      document.body.appendChild(toastContainer);
    }
    const toast = document.createElement("div");
    toast.style.background = "rgba(20, 20, 20, 0.9)";
    toast.style.color = "#fff";
    toast.style.padding = "8px 16px";
    toast.style.borderRadius = "20px";
    toast.style.fontSize = "14px";
    toast.style.boxShadow = "0 4px 12px rgba(0,0,0,0.5)";
    toast.style.border = "1px solid rgba(255,255,255,0.1)";
    toast.style.transition = "opacity 0.3s";
    toast.textContent = msg;
    toastContainer.appendChild(toast);
    setTimeout(() => {
      toast.style.opacity = "0";
      setTimeout(() => {
        toast.remove();
      }, 300);
    }, duration);
  }
  class RequestQueue {
    constructor() {
      this.queue = [];
      this.running = 0;
      this.pausedUntil = 0;
    }
    enqueue(task, priorityFn) {
      return new Promise((resolve, reject) => {
        this.queue.push({ execute: task, resolve, reject, priorityFn });
        this.run();
      });
    }
    pauseGlobally(durationMs) {
      const until = Date.now() + durationMs;
      if (until > this.pausedUntil) {
        this.pausedUntil = until;
      }
    }
    run() {
      if (Date.now() < this.pausedUntil) {
        setTimeout(() => this.run(), this.pausedUntil - Date.now() + 10);
        return;
      }
      if (this.queue.length > 1) {
        this.queue.sort((a, b) => {
          const pa = a.priorityFn ? a.priorityFn() : 0;
          const pb = b.priorityFn ? b.priorityFn() : 0;
          return pb - pa;
        });
      }
      while (this.running < CFG.maxConcurrent && this.queue.length > 0) {
        const task = this.queue.shift();
        this.running++;
        const next = () => {
          this.running--;
          setTimeout(() => this.run(), CFG.requestSpacing);
        };
        task.execute().then((value) => {
          task.resolve(value);
          next();
        }).catch((reason) => {
          task.reject(reason);
          next();
        });
      }
    }
  }
  const requestQueue = new RequestQueue();
  const parser$1 = new DOMParser();
  function getNextUrl$1(doc) {
    const ptt = q(".ptt", doc);
    if (!ptt) return null;
    const nextBtn = Array.from(qa("td a", ptt)).find((a) => (a.textContent ?? "").includes(">"));
    return nextBtn ? nextBtn.href : null;
  }
  function getPrevUrl$1(doc) {
    const ptt = q(".ptt", doc);
    if (!ptt) return null;
    const prevBtn = Array.from(qa("td a", ptt)).find((a) => (a.textContent ?? "").includes("<"));
    return prevBtn ? prevBtn.href : null;
  }
  function extractLinks(doc) {
    return Array.from(qa("#gdt a", doc)).map((a) => {
      const url = a.href;
      let thumb;
      const divWithBg = a.closest('div[style*="background"]');
      if (divWithBg) {
        const style = divWithBg.getAttribute("style") || "";
        const match = style.match(/url\(['"]?([^)'"]+)['"]?\)/);
        if (match) thumb = match[1];
      } else {
        const img = a.querySelector("img");
        if (img && img.src && !img.src.endsWith("x.gif")) {
          thumb = img.src;
        }
      }
      return { url, thumb };
    });
  }
  const EHentaiAdapter = {
    name: "E-Hentai/ExHentai",
    match(url) {
      return /https?:\/\/(e-|ex)hentai\.org\/(g|s)\//.test(url);
    },
    async init(doc) {
      const initLinks = extractLinks(doc);
      let totalPage = 1;
      const gpc = q(".gpc", doc);
      if (gpc) {
        const txt = gpc.textContent ?? "";
        const m = txt.match(/of\s+([\d,]+)\s+images/);
        if (m && m[1]) {
          const totalImgs = parseInt(m[1].replace(/,/g, ""));
          const perPage = initLinks.length || 20;
          totalPage = Math.ceil(totalImgs / perPage);
        }
      } else {
        const allLinks = Array.from(qa(".ptt td a", doc));
        const lastA = allLinks.pop();
        if (lastA) {
          const t = parseInt(lastA.textContent ?? "");
          if (!isNaN(t)) totalPage = t;
        }
      }
      if (gpc) {
        const txt = gpc.textContent ?? "";
        const m = txt.match(/Showing\s+([\d,]+)\s*-\s*([\d,]+)\s+of\s+([\d,]+)/);
        if (m) {
          store.imageOffset = parseInt(m[1].replace(/,/g, "")) - 1;
        }
      }
      return {
        links: initLinks,
        nextUrl: getNextUrl$1(doc),
        prevUrl: getPrevUrl$1(doc),
        totalPage
      };
    },
    async resolveImage(url, nlToken) {
      const fetchUrl = nlToken ? `${url}${url.includes("?") ? "&" : "?"}nl=${nlToken}` : url;
      let retries = 0;
      while (retries <= CFG.maxRetries) {
        try {
          const response = await fetch(fetchUrl);
          if (response.status === 429 || response.status === 503) {
            requestQueue.pauseGlobally(5e3);
            throw { rateLimited: true };
          }
          if (!response.ok) throw new Error(`HTTP ${response.status}`);
          const html = await response.text();
          const doc = parser$1.parseFromString(html, "text/html");
          const imgEl = q("#img", doc);
          const imgSrc = imgEl == null ? void 0 : imgEl.src;
          if (!imgSrc) throw new Error("Image not found");
          const onerror = imgEl.getAttribute("onerror") || "";
          const m = onerror.match(/nl\(['"]([^'"]+)['"]\)/);
          const nextNlToken = m ? m[1] : null;
          return { src: imgSrc, nl: nextNlToken ?? void 0 };
        } catch (err) {
          if (retries < CFG.maxRetries) {
            const isRateLimited = err && typeof err === "object" && "rateLimited" in err;
            const delay = isRateLimited ? 5e3 : CFG.retryDelay * Math.pow(2, retries);
            await new Promise((resolve) => setTimeout(resolve, delay));
            retries++;
          } else {
            return null;
          }
        }
      }
      return null;
    },
    async fetchPage(url) {
      const response = await fetch(url);
      if (!response.ok) throw new Error("Failed to fetch page");
      const html = await response.text();
      const doc = parser$1.parseFromString(html, "text/html");
      const links = extractLinks(doc);
      return {
        links,
        nextUrl: getNextUrl$1(doc),
        prevUrl: getPrevUrl$1(doc)
      };
    },
    getContainer() {
      return document.querySelector("#gdt") || document.querySelector(".gm");
    },
    hideOriginalElements() {
      const HIDDEN_SELECTORS = [
        ".c1",
        ".c2",
        ".c3",
        ".c4",
        ".c5",
        ".c6",
        ".c7",
        ".c8",
        ".ptt",
        ".ptb",
        ".gdtl",
        ".gdtm",
        "#gdo",
        "#cdiv",
        "table.itg"
      ];
      document.querySelectorAll(HIDDEN_SELECTORS.join(",")).forEach((el) => {
        el.style.display = "none";
      });
    }
  };
  const parser = new DOMParser();
  function extract4KHDImages(doc) {
    const images = Array.from(qa("figure.wp-block-image img, #basicExample img, .entry-content p img", doc));
    return images.map((img) => {
      let src = img.src;
      let thumb = src;
      src = src.replace(/i\d\.wp\.com\//, "");
      src = src.replace("pic.4khd.com", "img.4khd.com");
      src = src.replace(/\?.+$/, "");
      src = src.replace(/\/w\d+-rw\//, "/w2500-h2500-rw/");
      return { url: src, thumb };
    }).filter((link) => link.url && !link.url.includes("avatar"));
  }
  function get4KHDNextUrl(doc) {
    const pageBox = doc.querySelector(".page-link-box, .pagination, .nav-links, .nav-previous");
    if (pageBox) {
      const current = pageBox.querySelector(".current, .active") || Array.from(pageBox.querySelectorAll("span")).find((s) => !s.querySelector("a"));
      if (current) {
        const currentPageNum = parseInt(current.textContent || "1", 10);
        if (!isNaN(currentPageNum)) {
          const nextBtn = Array.from(pageBox.querySelectorAll("a")).find((a) => parseInt(a.textContent || "0", 10) === currentPageNum + 1);
          if (nextBtn && nextBtn.href && nextBtn.href !== window.location.href) {
            return nextBtn.href;
          }
        }
      }
      const nextBtnFallback = pageBox.querySelector("a.next") || doc.querySelector("a.next.page-numbers");
      if (nextBtnFallback && nextBtnFallback.href) {
        const url = nextBtnFallback.href;
        if (url !== window.location.href) return url;
      }
    }
    return null;
  }
  function get4KHDPrevUrl(doc) {
    const pageBox = doc.querySelector(".page-link-box, .pagination, .nav-links, .nav-previous");
    if (pageBox) {
      const current = pageBox.querySelector(".current, .active") || Array.from(pageBox.querySelectorAll("span")).find((s) => !s.querySelector("a"));
      if (current) {
        const currentPageNum = parseInt(current.textContent || "1", 10);
        if (!isNaN(currentPageNum) && currentPageNum > 1) {
          const prevBtn = Array.from(pageBox.querySelectorAll("a")).find((a) => parseInt(a.textContent || "0", 10) === currentPageNum - 1);
          if (prevBtn && prevBtn.href && prevBtn.href !== window.location.href) {
            return prevBtn.href;
          }
        }
      }
      const prevBtnFallback = pageBox.querySelector("a.prev") || doc.querySelector("a.prev.page-numbers");
      if (prevBtnFallback && prevBtnFallback.href) {
        const url = prevBtnFallback.href;
        if (url !== window.location.href) return url;
      }
    }
    return null;
  }
  const FourKHDAdapter = {
    name: "4KHD",
    match(url) {
      return url.includes("4khd.com") || url.includes("xxtt.ink") || url.includes("uuss.uk") || url.includes("ssuu.uk");
    },
    async init(doc) {
      const initLinks = extract4KHDImages(doc);
      const totalPage = 1;
      const pageBox = doc.querySelector(".page-link-box, .pagination, .nav-links, .nav-previous");
      let currentPageNum = 1;
      if (pageBox) {
        const current = pageBox.querySelector(".current, .active") || Array.from(pageBox.querySelectorAll("span")).find((s) => !s.querySelector("a"));
        if (current) {
          currentPageNum = parseInt(current.textContent || "1", 10);
          if (isNaN(currentPageNum)) currentPageNum = 1;
        }
      }
      if (currentPageNum > 1) {
        const perPage = initLinks.length > 0 ? initLinks.length : 20;
        store.imageOffset = (currentPageNum - 1) * perPage;
      }
      return {
        links: initLinks,
        nextUrl: get4KHDNextUrl(doc),
        prevUrl: get4KHDPrevUrl(doc),
        totalPage
      };
    },
    async resolveImage(url) {
      return { src: url };
    },
    async fetchPage(url) {
      const response = await fetch(url);
      if (!response.ok) throw new Error("Failed to fetch page");
      const html = await response.text();
      const doc = parser.parseFromString(html, "text/html");
      const links = extract4KHDImages(doc);
      return {
        links,
        nextUrl: get4KHDNextUrl(doc),
        prevUrl: get4KHDPrevUrl(doc)
      };
    },
    getContainer() {
      const entryContent = document.querySelector(".entry-content, .wp-block-post-content");
      if (entryContent) return entryContent;
      const basicExample = document.querySelector("#basicExample");
      if (basicExample && basicExample.parentElement) return basicExample.parentElement;
      return document.querySelector(".post-content");
    },
    hideOriginalElements() {
      const HIDDEN_SELECTORS = [
        ".centbtd",
        ".popup",
        ".wp-container-13",
        ".popup-iframe",
        "#basicExample",
        ".wp-block-image",
        ".page-link-box"
      ];
      document.querySelectorAll(HIDDEN_SELECTORS.join(",")).forEach((el) => {
        el.style.display = "none";
      });
    }
  };
  class Mutex {
    constructor(maxConcurrent) {
      this.maxConcurrent = maxConcurrent;
      this.queue = [];
      this.activeCount = 0;
    }
    async lock() {
      if (this.activeCount < this.maxConcurrent) {
        this.activeCount++;
        return;
      }
      return new Promise((resolve) => this.queue.push(resolve));
    }
    unlock() {
      if (this.queue.length > 0) {
        const next = this.queue.shift();
        next == null ? void 0 : next();
      } else {
        this.activeCount--;
      }
    }
  }
  const decodeMutex = new Mutex(3);
  const Comic18Adapter = {
    name: "18comic",
    match: (url) => {
      return url.includes("18comic.vip") || url.includes("18comic.ink");
    },
    init: async (doc) => {
      const aidMatch = doc.documentElement.innerHTML.match(/aid\s*=\s*['"]?(\d+)['"]?/);
      const scrambleMatch = doc.documentElement.innerHTML.match(/scramble_id\s*=\s*['"]?(\d+)['"]?/);
      const aid = aidMatch ? aidMatch[1] : unsafeWindow.aid ? String(unsafeWindow.aid) : "";
      const scrambleId = scrambleMatch ? scrambleMatch[1] : unsafeWindow.scramble_id ? String(unsafeWindow.scramble_id) : "";
      const links = [];
      const imgs = doc.querySelectorAll(".scramble-page img[id], .owl-item .center img[id]");
      imgs.forEach((img) => {
        const url = img.getAttribute("data-original") || img.getAttribute("data-src") || img.src;
        if (url) {
          const urlObj = new URL(url, window.location.href);
          if (aid) urlObj.searchParams.set("18aid", aid);
          if (scrambleId) urlObj.searchParams.set("18scid", scrambleId);
          const viewerUrl = urlObj.toString();
          links.push({ url: viewerUrl });
          try {
            img.getBoundingClientRect = () => ({
              top: 999999,
              left: 0,
              right: 0,
              bottom: 999999,
              width: 0,
              height: 0,
              x: 0,
              y: 0,
              toJSON: () => {
              }
            });
          } catch (e) {
          }
        }
      });
      return {
        links,
        nextUrl: getNextUrl(doc),
        prevUrl: getPrevUrl(doc)
      };
    },
    fetchPage: async (url) => {
      const res = await fetch(url);
      const html = await res.text();
      const doc = new DOMParser().parseFromString(html, "text/html");
      const aidMatch = html.match(/aid\s*=\s*['"]?(\d+)['"]?/);
      const scrambleMatch = html.match(/scramble_id\s*=\s*['"]?(\d+)['"]?/);
      const aid = aidMatch ? aidMatch[1] : "";
      const scrambleId = scrambleMatch ? scrambleMatch[1] : "";
      const links = [];
      const imgs = doc.querySelectorAll(".scramble-page img[id], .owl-item .center img[id]");
      imgs.forEach((img) => {
        const imgUrl = img.getAttribute("data-original") || img.getAttribute("data-src") || img.src;
        if (imgUrl) {
          const urlObj = new URL(imgUrl, window.location.href);
          if (aid) urlObj.searchParams.set("18aid", aid);
          if (scrambleId) urlObj.searchParams.set("18scid", scrambleId);
          links.push({ url: urlObj.toString() });
        }
      });
      return {
        links,
        nextUrl: getNextUrl(doc),
        prevUrl: getPrevUrl(doc)
      };
    },
    resolveImage: async (urlStr) => {
      try {
        const urlObj = new URL(urlStr);
        const aid = urlObj.searchParams.get("18aid");
        const scrambleId = urlObj.searchParams.get("18scid");
        urlObj.searchParams.delete("18aid");
        urlObj.searchParams.delete("18scid");
        const realUrl = urlObj.toString();
        if (realUrl.includes(".gif") || !aid || !scrambleId || Number(aid) < Number(scrambleId)) {
          return { src: realUrl };
        }
        const res = await fetch(realUrl);
        if (!res.ok) throw new Error("Failed to fetch image");
        const blob = await res.blob();
        const fileName = urlObj.pathname.split("/").pop() || "";
        const id = fileName.split(".")[0];
        if (!id) return { src: realUrl };
        await decodeMutex.lock();
        try {
          const bitmap = await createImageBitmap(blob);
          const imgWidth = bitmap.width;
          const imgHeight = bitmap.height;
          if (!unsafeWindow.get_num) {
            bitmap.close();
            return { src: realUrl };
          }
          const num = unsafeWindow.get_num(btoa(aid), btoa(id));
          if (!num || num <= 1) {
            bitmap.close();
            return { src: realUrl };
          }
          const canvas = new OffscreenCanvas(imgWidth, imgHeight);
          const ctx = canvas.getContext("2d");
          if (!ctx) {
            bitmap.close();
            return { src: realUrl };
          }
          ctx.fillStyle = "#ffffff";
          ctx.fillRect(0, 0, imgWidth, imgHeight);
          const cropHeight = Number(imgHeight % num);
          const sHeight = Math.floor(imgHeight / num);
          let sy = imgHeight - cropHeight - sHeight;
          let dy = cropHeight + sHeight;
          ctx.drawImage(bitmap, 0, sy, imgWidth, cropHeight + sHeight, 0, 0, imgWidth, cropHeight + sHeight);
          for (let i = 1; i < num; ++i) {
            sy -= sHeight;
            ctx.drawImage(bitmap, 0, sy, imgWidth, sHeight, 0, dy, imgWidth, sHeight);
            dy += sHeight;
          }
          bitmap.close();
          const finalBlob = await canvas.convertToBlob({ type: "image/jpeg", quality: 0.85 });
          const finalUrl = URL.createObjectURL(finalBlob);
          return { src: finalUrl };
        } finally {
          decodeMutex.unlock();
        }
      } catch (err) {
        const cleanUrl = new URL(urlStr);
        cleanUrl.searchParams.delete("18aid");
        cleanUrl.searchParams.delete("18scid");
        return { src: cleanUrl.toString() };
      }
    },
    getContainer: () => {
      return document.querySelector(".scramble-page") || document.body;
    },
    hideOriginalElements: () => {
    }
  };
  function getNextUrl(doc) {
    var _a;
    const activeLi = doc.querySelector(".pagination li.active");
    if (activeLi) {
      const nextA = (_a = activeLi.nextElementSibling) == null ? void 0 : _a.querySelector("a:not(.prevnext)");
      if (nextA) return nextA.href;
    }
    const nextChapter = Array.from(doc.querySelectorAll('.menu-bolock-ul a[href^="/photo/"]')).find((a) => {
      var _a2;
      return (_a2 = a.textContent) == null ? void 0 : _a2.includes("下一");
    });
    if (nextChapter) return nextChapter.href;
    return null;
  }
  function getPrevUrl(doc) {
    var _a;
    const activeLi = doc.querySelector(".pagination li.active");
    if (activeLi) {
      const prevA = (_a = activeLi.previousElementSibling) == null ? void 0 : _a.querySelector("a:not(.prevnext)");
      if (prevA) return prevA.href;
    }
    const prevChapter = Array.from(doc.querySelectorAll('.menu-bolock-ul a[href^="/photo/"]')).find((a) => {
      var _a2;
      return (_a2 = a.textContent) == null ? void 0 : _a2.includes("上一");
    });
    if (prevChapter) return prevChapter.href;
    return null;
  }
  const adapters = [EHentaiAdapter, FourKHDAdapter, Comic18Adapter];
  const SiteManager = {
    register(adapter) {
      adapters.push(adapter);
    },
    getAdapter(url, doc = document) {
      return adapters.find((a) => a.match(url, doc)) || null;
    }
  };
  function setErrorState(placeholder, pIndex, index) {
    placeholder.className = "r-ph sp-placeholder error";
    placeholder.innerHTML = `
    <div style="display: flex; flex-direction: column; align-items: center; justify-content: center; transform: translateY(-20px);">
      <div style="display: flex; align-items: center; gap: 10px; background: rgba(200, 40, 40, 0.8); border: 1px solid rgba(255, 255, 255, 0.2); padding: 10px 20px; border-radius: 30px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5); backdrop-filter: blur(8px); margin-bottom: 16px;">
        <svg style="color: #fff; width: 20px; height: 20px;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round">
          <circle cx="12" cy="12" r="10"></circle>
          <line x1="12" y1="8" x2="12" y2="12"></line>
          <line x1="12" y1="16" x2="12.01" y2="16"></line>
        </svg>
        <div style="font-size: 15px; color: #fff; font-weight: 500; letter-spacing: 0.5px;">Load Failed</div>
      </div>
      <div style="font-size: 14px; color: rgba(255, 255, 255, 0.5); font-family: monospace; letter-spacing: 1px;">P${pIndex}-${index + 1}</div>
    </div>
  `;
  }
  let virtualizationObserver = null;
  let lazyLoadObserver = null;
  function initVirtualization() {
    if (virtualizationObserver) return;
    virtualizationObserver = new IntersectionObserver((entries) => {
      entries.forEach((entry) => {
        const img = entry.target;
        if (entry.isIntersecting) {
          img.classList.remove("sp-virtualized");
        } else {
          img.classList.add("sp-virtualized");
        }
      });
    }, { rootMargin: "3000px" });
  }
  function loadPlaceholderImage(placeholder) {
    const url = placeholder.dataset.url;
    const pIndex = parseInt(placeholder.dataset.pIndex);
    const index = parseInt(placeholder.dataset.index);
    const thumb = placeholder.dataset.thumb;
    const adapter = store.activeAdapter;
    if (!adapter) return;
    adapter.resolveImage(url).then((res) => {
      var _a;
      if (res) {
        let showError = function() {
          if (placeholder.parentNode) {
            setErrorState(placeholder, pIndex, index);
            if (img.parentNode) {
              img.parentNode.replaceChild(placeholder, img);
            }
            virtualizationObserver == null ? void 0 : virtualizationObserver.unobserve(img);
          }
        };
        const img = document.createElement("img");
        img.className = "r-img";
        img.dataset.viewerUrl = url;
        img.dataset.realSrc = res.src;
        if (thumb) img.dataset.thumbSrc = thumb;
        if (res.nl) img.dataset.nl = res.nl;
        let currentNlToken = res.nl;
        let autoRetries = 0;
        const MAX_AUTO_RETRIES = 3;
        img.onerror = () => {
          if (currentNlToken && autoRetries < MAX_AUTO_RETRIES) {
            autoRetries++;
            showToast(`P${pIndex}-${index + 1}: Auto requesting new node... (${autoRetries}/${MAX_AUTO_RETRIES})`, 3e3);
            if (placeholder.parentNode) {
              placeholder.className = "r-ph sp-placeholder loading";
              placeholder.innerHTML = `
              <div style="display: flex; flex-direction: column; align-items: center; justify-content: center; transform: translateY(-20px);">
                <div style="display: flex; align-items: center; gap: 10px; background: rgba(20, 20, 20, 0.8); border: 1px solid rgba(255, 255, 255, 0.1); padding: 10px 20px; border-radius: 30px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5); backdrop-filter: blur(8px); margin-bottom: 16px;">
                  <style>@keyframes sp-spin { 100% { transform: rotate(360deg); } }</style>
                  <svg style="color: #F596AA; width: 20px; height: 20px; animation: sp-spin 1s linear infinite;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round">
                    <path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
                  </svg>
                  <div style="font-size: 15px; color: #f3f4f6; font-weight: 500; letter-spacing: 0.5px;">Auto Retrying...</div>
                </div>
                <div style="font-size: 14px; color: rgba(255, 255, 255, 0.5); font-family: monospace; letter-spacing: 1px;">P${pIndex}-${index + 1}</div>
              </div>
            `;
              if (img.parentNode) {
                img.parentNode.replaceChild(placeholder, img);
              }
            }
            adapter.resolveImage(url, currentNlToken).then((newRes) => {
              if (newRes) {
                img.src = newRes.src;
                img.dataset.realSrc = newRes.src;
                currentNlToken = newRes.nl;
                if (placeholder.parentNode) {
                  placeholder.parentNode.replaceChild(img, placeholder);
                }
              } else {
                showError();
              }
            }).catch(showError);
          } else {
            showError();
          }
        };
        img.onload = () => {
          if (!img.dataset.locked && img.naturalWidth > 0) {
            img.style.aspectRatio = `${img.naturalWidth} / ${img.naturalHeight}`;
            img.style.width = "100%";
            img.style.maxWidth = `${img.naturalWidth}px`;
            img.style.height = "auto";
            img.dataset.locked = "true";
          }
        };
        img.src = res.src;
        (_a = placeholder.parentNode) == null ? void 0 : _a.replaceChild(img, placeholder);
        virtualizationObserver == null ? void 0 : virtualizationObserver.observe(img);
      } else {
        setErrorState(placeholder, pIndex, index);
      }
    }).catch(() => {
      setErrorState(placeholder, pIndex, index);
    });
  }
  function initLazyLoad() {
    if (lazyLoadObserver) return;
    lazyLoadObserver = new IntersectionObserver((entries) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          const placeholder = entry.target;
          if (placeholder.dataset.lazyLoaded) return;
          placeholder.dataset.lazyLoaded = "true";
          lazyLoadObserver == null ? void 0 : lazyLoadObserver.unobserve(placeholder);
          loadPlaceholderImage(placeholder);
        }
      });
    }, { rootMargin: "4000px 0px 4000px 0px" });
  }
  function processBatch(links, pIndex, container, prepend = false, pageUrl) {
    const batchDiv = document.createElement("div");
    batchDiv.className = "page-batch";
    if (pageUrl) {
      batchDiv.dataset.pageUrl = pageUrl;
    }
    const fragment = document.createDocumentFragment();
    initVirtualization();
    initLazyLoad();
    let targetContainer = container;
    if (!targetContainer) {
      targetContainer = document.querySelector("#gdt-hidden") || document.querySelector(".scroll-mode #gdt, .scroll-mode .gm, .scroll-mode .entry-content, .scroll-mode .wp-block-post-content, .scroll-mode .post-content") || document.body;
    }
    links.forEach((link, index) => {
      const url = link.url;
      const placeholder = document.createElement("div");
      placeholder.className = "r-ph sp-placeholder loading";
      placeholder.dataset.url = url;
      placeholder.dataset.pIndex = String(pIndex);
      placeholder.dataset.index = String(index);
      if (link.thumb) placeholder.dataset.thumb = link.thumb;
      placeholder.innerHTML = `
      <div style="display: flex; flex-direction: column; align-items: center; justify-content: center; transform: translateY(-20px);">
        <div style="display: flex; align-items: center; gap: 10px; background: rgba(20, 20, 20, 0.8); border: 1px solid rgba(255, 255, 255, 0.1); padding: 10px 20px; border-radius: 30px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5); backdrop-filter: blur(8px); margin-bottom: 16px;">
          <style>@keyframes sp-spin { 100% { transform: rotate(360deg); } }</style>
          <svg style="color: #F596AA; width: 20px; height: 20px; animation: sp-spin 1s linear infinite;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round">
            <path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
          </svg>
          <div style="font-size: 15px; color: #f3f4f6; font-weight: 500; letter-spacing: 0.5px;">Loading...</div>
        </div>
        <div style="font-size: 14px; color: rgba(255, 255, 255, 0.5); font-family: monospace; letter-spacing: 1px;">P${pIndex}-${index + 1}</div>
      </div>
    `;
      fragment.appendChild(placeholder);
      if (store.settings.scrollMode) {
        lazyLoadObserver == null ? void 0 : lazyLoadObserver.observe(placeholder);
      } else {
        placeholder.dataset.lazyLoaded = "true";
        loadPlaceholderImage(placeholder);
      }
    });
    batchDiv.appendChild(fragment);
    if (prepend && targetContainer.firstChild) {
      targetContainer.insertBefore(batchDiv, targetContainer.firstChild);
    } else {
      targetContainer.appendChild(batchDiv);
    }
  }
  function setupAutoScroll() {
    const scrollSent = document.createElement("div");
    document.body.appendChild(scrollSent);
    const pageObs = new IntersectionObserver((entries) => {
      if (entries[0].isIntersecting && store.nextUrl && !store.isFetching) {
        store.isFetching = true;
        store.activeAdapter.fetchPage(store.nextUrl).then(({ links, nextUrl: nUrl }) => {
          store.currPage++;
          processBatch(links, store.currPage, document.querySelector(".scroll-mode #gdt, .scroll-mode .gm, .scroll-mode .entry-content, .scroll-mode .wp-block-post-content, .scroll-mode .post-content") || document.body);
          store.nextUrl = nUrl;
          store.isFetching = false;
          store.nextPagePrefetched = false;
          if (!store.nextUrl) pageObs.disconnect();
        }).catch(() => {
          store.isFetching = false;
        });
      }
    }, { rootMargin: CFG.nextPage });
    pageObs.observe(scrollSent);
  }
  const ITEM_HEIGHT = 80;
  const VISIBLE_COUNT = 12;
  const BUFFER = 3;
  function createSidebar(onIndexChange, onScrollToBottom, onScrollToTop) {
    const progressTrack = document.createElement("div");
    progressTrack.className = "sp-sidebar-track";
    const progressThumb = document.createElement("div");
    progressThumb.className = "sp-sidebar-thumb";
    const progressLabel = document.createElement("div");
    progressLabel.className = "sp-sidebar-label";
    progressTrack.appendChild(progressThumb);
    progressTrack.appendChild(progressLabel);
    const thumbPanel = document.createElement("div");
    thumbPanel.className = "sp-thumb-panel";
    const viewport = document.createElement("div");
    viewport.className = "sp-thumb-viewport";
    const content = document.createElement("div");
    content.className = "sp-thumb-content";
    const counter = document.createElement("div");
    counter.className = "sp-thumb-counter";
    viewport.appendChild(content);
    thumbPanel.appendChild(viewport);
    thumbPanel.appendChild(counter);
    let scrollOffset = 0;
    let lastCenteredIndex = -1;
    let clickedFromPanel = false;
    const itemPool = [];
    const activeItems = new Map();
    let cachedTrackHeight = 0;
    let progressWakeTimer = null;
    let isPanelActive = false;
    function wakeUpProgressBar() {
      if (isPanelActive) return;
      progressTrack.classList.add("active");
      if (progressWakeTimer) clearTimeout(progressWakeTimer);
      progressWakeTimer = setTimeout(() => {
        progressTrack.classList.remove("active");
      }, 1500);
    }
    function closePanel() {
      if (!isPanelActive) return;
      isPanelActive = false;
      thumbPanel.classList.remove("active");
    }
    function openPanel() {
      if (isPanelActive) return;
      isPanelActive = true;
      thumbPanel.classList.add("active");
      progressTrack.classList.remove("active");
      if (progressWakeTimer) clearTimeout(progressWakeTimer);
    }
    document.addEventListener("mousemove", (e) => {
      if (!document.querySelector(".single-page-overlay.active")) return;
      if (isDragging) return;
      if (e.clientX < 0 || e.clientY < 0 || e.clientY >= window.innerHeight - 1) {
        closePanel();
        return;
      }
      const dx = window.innerWidth - e.clientX;
      if (dx <= 140) {
        openPanel();
      } else {
        closePanel();
      }
    });
    document.addEventListener("mouseout", (e) => {
      if (!e.relatedTarget) closePanel();
    });
    document.documentElement.addEventListener("mouseleave", closePanel);
    function refreshTrackHeight() {
      cachedTrackHeight = progressTrack.offsetHeight;
    }
    window.addEventListener("resize", refreshTrackHeight, { passive: true });
    function clamp(val, min, max) {
      return Math.max(min, Math.min(max, val));
    }
    function vpHeight() {
      return viewport.offsetHeight || Math.min(VISIBLE_COUNT * ITEM_HEIGHT, store.allImages.length * ITEM_HEIGHT);
    }
    function maxOffset() {
      return Math.max(0, store.allImages.length * ITEM_HEIGHT - vpHeight());
    }
    function acquireItem() {
      return itemPool.pop() || (() => {
        const el = document.createElement("div");
        el.className = "sp-thumb-item";
        return el;
      })();
    }
    function releaseItem(el) {
      el.remove();
      itemPool.push(el);
    }
    function renderItemContent(el, index) {
      el.dataset.index = String(index);
      el.classList.toggle("sp-thumb-active", index === store.currentImageIndex);
      const img = store.allImages[index];
      if (img && img.src) {
        let thumbCanvas = el.querySelector("canvas.sp-thumb-img");
        if (!thumbCanvas) {
          el.innerHTML = "";
          thumbCanvas = document.createElement("canvas");
          thumbCanvas.className = "sp-thumb-img";
          el.appendChild(thumbCanvas);
          const label2 = document.createElement("span");
          label2.className = "sp-thumb-label";
          el.appendChild(label2);
        }
        const realSrc = img.dataset.thumbSrc || img.dataset.realSrc || img.src;
        if (thumbCanvas.dataset.src !== realSrc) {
          thumbCanvas.dataset.src = realSrc;
          const tempImg = new Image();
          tempImg.onload = () => {
            if (thumbCanvas.dataset.src === realSrc) {
              thumbCanvas.width = tempImg.naturalWidth;
              thumbCanvas.height = tempImg.naturalHeight;
              const ctx = thumbCanvas.getContext("2d");
              if (ctx) {
                ctx.drawImage(tempImg, 0, 0);
              }
            }
          };
          tempImg.src = realSrc;
        }
        const label = el.querySelector(".sp-thumb-label");
        if (label) label.textContent = String(store.imageOffset + index + 1);
      } else {
        if (!el.querySelector(".sp-thumb-ph")) {
          el.innerHTML = "";
          const ph = document.createElement("div");
          ph.className = "sp-thumb-ph";
          ph.textContent = String(store.imageOffset + index + 1);
          el.appendChild(ph);
        }
      }
    }
    function renderVisibleItems() {
      const total = store.allImages.length;
      if (total === 0) return;
      const vp = vpHeight();
      content.style.height = `${total * ITEM_HEIGHT}px`;
      scrollOffset = clamp(scrollOffset, 0, maxOffset());
      const startIdx = Math.max(0, Math.floor(scrollOffset / ITEM_HEIGHT) - BUFFER);
      const endIdx = Math.min(total - 1, Math.ceil((scrollOffset + vp) / ITEM_HEIGHT) + BUFFER);
      for (const [idx, el] of activeItems) {
        if (idx < startIdx || idx > endIdx) {
          releaseItem(el);
          activeItems.delete(idx);
        }
      }
      for (let i = startIdx; i <= endIdx; i++) {
        let el = activeItems.get(i);
        if (!el) {
          el = acquireItem();
          activeItems.set(i, el);
          content.appendChild(el);
        }
        el.style.transform = `translateY(${i * ITEM_HEIGHT}px)`;
        renderItemContent(el, i);
      }
      content.style.transform = `translateY(${-scrollOffset}px)`;
    }
    function centerOnCurrent() {
      const vp = vpHeight();
      const target = store.currentImageIndex * ITEM_HEIGHT - vp / 2 + ITEM_HEIGHT / 2;
      scrollOffset = clamp(target, 0, maxOffset());
    }
    function ensureVisible() {
      const vp = vpHeight();
      const itemTop = store.currentImageIndex * ITEM_HEIGHT;
      const itemBottom = itemTop + ITEM_HEIGHT;
      if (itemTop < scrollOffset) {
        scrollOffset = itemTop;
      } else if (itemBottom > scrollOffset + vp) {
        scrollOffset = itemBottom - vp;
      }
      scrollOffset = clamp(scrollOffset, 0, maxOffset());
    }
    function update() {
      if (store.allImages.length === 0) return;
      if (store.currentImageIndex !== lastCenteredIndex) {
        if (clickedFromPanel) {
          ensureVisible();
          clickedFromPanel = false;
        } else {
          centerOnCurrent();
        }
        lastCenteredIndex = store.currentImageIndex;
      }
      renderVisibleItems();
      const displayLabel = `${store.imageOffset + store.currentImageIndex + 1} / ${store.imageOffset + store.allImages.length}`;
      counter.textContent = displayLabel;
      if (!cachedTrackHeight) refreshTrackHeight();
      const trackHeight = cachedTrackHeight;
      let thumbHeight;
      if (store.allImages.length <= 10) {
        thumbHeight = 60;
      } else if (store.allImages.length <= 50) {
        thumbHeight = Math.max(60, trackHeight * (10 / store.allImages.length));
      } else {
        thumbHeight = Math.max(60, trackHeight * (5 / store.allImages.length));
      }
      const scrollProgress = store.currentImageIndex / Math.max(1, store.allImages.length - 1);
      const maxThumbTop = trackHeight - thumbHeight;
      const thumbTop = scrollProgress * maxThumbTop;
      progressThumb.style.height = `${thumbHeight}px`;
      progressThumb.style.top = `${thumbTop}px`;
      progressLabel.textContent = displayLabel;
    }
    viewport.addEventListener("wheel", (e) => {
      e.preventDefault();
      e.stopPropagation();
      scrollOffset = clamp(scrollOffset + e.deltaY, 0, maxOffset());
      renderVisibleItems();
      if (onScrollToBottom && scrollOffset >= maxOffset() - ITEM_HEIGHT) {
        onScrollToBottom();
      }
      if (onScrollToTop && scrollOffset <= ITEM_HEIGHT) {
        onScrollToTop();
      }
    }, { passive: false });
    content.addEventListener("click", (e) => {
      const item = e.target.closest(".sp-thumb-item");
      if (item == null ? void 0 : item.dataset.index) {
        const index = parseInt(item.dataset.index);
        if (!isNaN(index) && index >= 0 && index < store.allImages.length) {
          clickedFromPanel = true;
          onIndexChange(index);
        }
      }
    });
    progressTrack.onclick = (e) => {
      if (e.target === progressThumb) return;
      const rect = progressTrack.getBoundingClientRect();
      const clickY = e.clientY - rect.top;
      const scrollProgress = Math.min(1, Math.max(0, clickY / rect.height));
      const targetIndex = Math.round(scrollProgress * (store.allImages.length - 1));
      if (targetIndex >= 0 && targetIndex < store.allImages.length) {
        onIndexChange(targetIndex);
      }
    };
    let isDragging = false;
    let dragStartY = 0;
    let thumbStartTop = 0;
    progressThumb.onmousedown = (e) => {
      e.preventDefault();
      e.stopPropagation();
      isDragging = true;
      dragStartY = e.clientY;
      thumbStartTop = progressThumb.offsetTop;
      document.body.style.userSelect = "none";
    };
    document.addEventListener("mousemove", (e) => {
      if (!isDragging) return;
      const deltaY = e.clientY - dragStartY;
      const newTop = thumbStartTop + deltaY;
      const trackHeight = cachedTrackHeight;
      const thumbHeight = progressThumb.offsetHeight;
      const maxTop = trackHeight - thumbHeight;
      const clampedTop = Math.max(0, Math.min(maxTop, newTop));
      const scrollProgress = maxTop > 0 ? clampedTop / maxTop : 0;
      const targetIndex = Math.round(scrollProgress * (store.allImages.length - 1));
      if (targetIndex >= 0 && targetIndex < store.allImages.length && targetIndex !== store.currentImageIndex) {
        onIndexChange(targetIndex);
      }
    });
    document.addEventListener("mouseup", () => {
      if (isDragging) {
        isDragging = false;
        document.body.style.userSelect = "";
        wakeUpProgressBar();
      }
    });
    progressThumb.onclick = (e) => e.stopPropagation();
    return { update, getElements: () => [progressTrack, thumbPanel], wakeUpProgressBar };
  }
  function setupNavigation(deps) {
    function hasLoadingPlaceholders() {
      return document.querySelectorAll(".r-ph").length > 0;
    }
    function syncAllImages() {
      const freshImages = Array.from(qa(".r-img"));
      if (freshImages.length !== store.allImages.length) {
        store.allImages = freshImages;
      }
    }
    function nextImage() {
      if (store.currentImageIndex >= store.allImages.length - 3) {
        syncAllImages();
      }
      if (store.currentImageIndex < store.allImages.length - 1) {
        store.currentImageIndex++;
        deps.updateImage();
        deps.checkAndLoadNextPage();
      } else if (hasLoadingPlaceholders()) {
        deps.updateImage();
        deps.checkAndLoadNextPage();
      } else {
        deps.checkAndLoadNextPage();
        if (store.autoPlay) {
          deps.stopAutoPlayAtEnd();
        }
      }
    }
    function previousImage() {
      if (store.currentImageIndex > 0) {
        store.currentImageIndex--;
        deps.updateImage();
        if (store.autoPlay) {
          deps.resetAutoPlay();
        }
      }
      if (store.currentImageIndex <= 3) {
        deps.checkAndLoadPrevPage();
      }
    }
    let accumulatedDelta = 0;
    let isScrolling = false;
    let lastFlipTime = 0;
    let wheelTimeout;
    const processWheelScroll = () => {
      if (!isScrolling) return;
      const threshold = 70;
      const now = Date.now();
      if (Math.abs(accumulatedDelta) >= threshold && now - lastFlipTime >= 40) {
        if (accumulatedDelta > 0) {
          nextImage();
        } else {
          previousImage();
        }
        accumulatedDelta = accumulatedDelta > 0 ? accumulatedDelta - threshold : accumulatedDelta + threshold;
        lastFlipTime = now;
      }
      if (isScrolling) {
        requestAnimationFrame(processWheelScroll);
      }
    };
    deps.overlay.addEventListener("wheel", (e) => {
      e.preventDefault();
      let normalizedDelta = e.deltaY;
      if (e.deltaMode === 1) {
        normalizedDelta *= 33;
      } else if (e.deltaMode === 2) {
        normalizedDelta *= 800;
      }
      accumulatedDelta += normalizedDelta;
      if (!isScrolling) {
        isScrolling = true;
        processWheelScroll();
      }
      clearTimeout(wheelTimeout);
      wheelTimeout = setTimeout(() => {
        isScrolling = false;
        accumulatedDelta = 0;
      }, 150);
    }, { passive: false });
    document.addEventListener("keydown", (e) => {
      if (!deps.overlay.classList.contains("active")) return;
      if (e.key === "Escape") {
        deps.closeSinglePageMode();
      } else if (e.key === "ArrowDown" || e.key === "ArrowRight") {
        nextImage();
      } else if (e.key === "ArrowUp" || e.key === "ArrowLeft") {
        previousImage();
      }
    });
    return { nextImage, previousImage };
  }
  function createAutoPlay(nextImageFn) {
    function start() {
      if (store.autoPlayTimer) clearInterval(store.autoPlayTimer);
      if (store.autoPlay) {
        store.autoPlayTimer = setInterval(nextImageFn, store.settings.autoPlayInterval);
      }
    }
    function stop() {
      if (store.autoPlayTimer) {
        clearInterval(store.autoPlayTimer);
        store.autoPlayTimer = null;
      }
    }
    function reset() {
      if (store.autoPlay) {
        stop();
        start();
      }
    }
    function stopAtEnd() {
      store.autoPlay = false;
      store.emit("settingsChanged");
      stop();
    }
    return { start, stop, reset, stopAtEnd };
  }
  function createStatusHUD() {
    const container = document.createElement("div");
    container.className = "sp-hud-container";
    function show(config) {
      const isError = config.status === "error";
      const color = isError ? "#ef4444" : "#F596AA";
      const iconSvg = isError ? `<svg style="color: ${color}; width: 18px; height: 18px;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line></svg>` : `<style>@keyframes sp-spin { 100% { transform: rotate(360deg); } }</style><svg style="color: ${color}; width: 18px; height: 18px; animation: sp-spin 1s linear infinite;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M21 12a9 9 0 1 1-6.219-8.56"></path></svg>`;
      container.innerHTML = `
      <div class="sp-hud-box ${isError ? "hud-error" : ""}">
        ${iconSvg}
        <div class="sp-hud-text">${config.text}</div>
        ${config.pageText ? `<div class="sp-hud-page">${config.pageText}</div>` : ""}
      </div>
    `;
      const box = container.querySelector(".sp-hud-box");
      if (config.onClick) {
        box.style.cursor = "pointer";
        box.onclick = config.onClick;
      }
      container.classList.add("show");
    }
    function hide() {
      container.classList.remove("show");
    }
    return { show, hide, getElement: () => container };
  }
  const isZH = navigator.language.toLowerCase().includes("zh");
  const i18n = {
readerMode: isZH ? "阅读器模式" : "Reader Mode",
    autoPlay: isZH ? "自动翻页" : "Auto Play",
    settings: isZH ? "设置" : "Settings",
    backToTop: isZH ? "回到顶部" : "Back to Top",
scrollMode: isZH ? "卷轴模式" : "Scroll Mode",
    autoEnter: isZH ? "自动进入阅读器" : "Auto Enter Reader",
    showControl: isZH ? "显示悬浮控件" : "Show Float Control",
    playSpeed: isZH ? "自动翻页速度" : "Auto Play Speed",
toggle: isZH ? "切换: " : "Toggle: ",
    enabled: isZH ? "已开启" : "Enabled",
    disabled: isZH ? "已关闭" : "Disabled",
waitingForNetwork: isZH ? "等待网络请求..." : "Waiting for network...",
    downloading: isZH ? "下载中..." : "Downloading...",
    loadFailed: isZH ? "加载失败" : "Load Failed",
    waitImagesToLoad: isZH ? "请等待图片加载" : "Please wait for images to load"
  };
  function createSinglePageOverlay(deps) {
    const overlay = document.createElement("div");
    overlay.className = "single-page-overlay";
    const closeBtn = document.createElement("div");
    closeBtn.className = "sp-close-btn";
    closeBtn.innerHTML = "&#10005;";
    const imageContainer = document.createElement("div");
    imageContainer.className = "sp-image-container";
    const currentImage = document.createElement("img");
    currentImage.className = "sp-current-image";
    imageContainer.appendChild(currentImage);
    currentImage.addEventListener("error", () => {
      if (!overlay.classList.contains("active")) return;
      if (!currentImage.src || currentImage.src === location.href) return;
      showError();
    });
    let loadPollTimer = null;
    let loadTimeoutTimer = null;
    let loadObserver = null;
    function clearLoadPoll() {
      if (loadPollTimer) {
        clearInterval(loadPollTimer);
        loadPollTimer = null;
      }
      if (loadTimeoutTimer) {
        clearTimeout(loadTimeoutTimer);
        loadTimeoutTimer = null;
      }
      if (loadObserver) {
        loadObserver.disconnect();
        loadObserver = null;
      }
    }
    const statusHUD = createStatusHUD();
    function showPlaceholder(statusText = "Loading...") {
      statusHUD.show({
        status: "loading",
        text: statusText,
        pageText: `${store.imageOffset + store.currentImageIndex + 1} / ${store.imageOffset + store.allImages.length}`
      });
    }
    function removePlaceholder() {
      statusHUD.hide();
    }
    function showError() {
      clearLoadPoll();
      currentImage.style.display = "none";
      statusHUD.show({
        status: "error",
        text: i18n.loadFailed,
        pageText: `${store.imageOffset + store.currentImageIndex + 1} / ${store.imageOffset + store.allImages.length}`
      });
    }
    function removeErrorUI() {
      statusHUD.hide();
    }
    function syncImages() {
      const freshImages = Array.from(qa(".r-img, .r-ph"));
      if (freshImages.length !== store.allImages.length || freshImages.some((img, i) => img !== store.allImages[i])) {
        store.allImages = freshImages;
        sidebar.update();
      }
    }
    function applyOverlaySrc(imgSrc, currentImg) {
      if (imgSrc && currentImage.dataset.assignedSrc !== imgSrc) {
        currentImage.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
        setTimeout(() => {
          currentImage.src = imgSrc;
          currentImage.dataset.assignedSrc = imgSrc;
          if (!isImageReady(currentImg)) {
            showPlaceholder(i18n.downloading);
          } else {
            removePlaceholder();
          }
        }, 0);
      } else if (!imgSrc && currentImage.dataset.assignedSrc) {
        currentImage.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
        delete currentImage.dataset.assignedSrc;
      }
    }
    function updateImage() {
      clearLoadPoll();
      removeErrorUI();
      const idx = store.currentImageIndex;
      syncImages();
      const img = store.allImages[idx];
      if (!img) {
        showPlaceholder(i18n.waitingForNetwork);
        sidebar.update();
        startLoadPoll(idx);
        return;
      }
      if (img.classList.contains("r-ph") && !img.dataset.lazyLoaded) {
        img.dataset.lazyLoaded = "true";
        loadPlaceholderImage(img);
      }
      const nextImg = store.allImages[idx + 1];
      if (nextImg && nextImg.classList.contains("r-ph") && !nextImg.dataset.lazyLoaded) {
        nextImg.dataset.lazyLoaded = "true";
        loadPlaceholderImage(nextImg);
      }
      const imgSrc = img.dataset.realSrc || img.src;
      applyOverlaySrc(imgSrc, img);
      currentImage.style.display = "block";
      if (!imgSrc) {
        showPlaceholder(i18n.waitingForNetwork);
      }
      sidebar.update();
      if (!isImageReady(img)) {
        startLoadPoll(idx);
      }
    }
    function startLoadPoll(idx) {
      if (store.autoPlay) autoPlay.stop();
      let imageErrored = false;
      let lastKnownImg = store.allImages[idx];
      function onImageReady() {
        if (store.currentImageIndex !== idx) return;
        const img = store.allImages[idx];
        if (img && isImageReady(img)) {
          clearLoadPoll();
          removePlaceholder();
          sidebar.update();
          if (store.autoPlay) autoPlay.start();
        }
      }
      function onImageError() {
        imageErrored = true;
        if (store.autoPlay) {
          tryAutoSkip();
        } else {
          if (store.currentImageIndex === idx) {
            showError();
          }
        }
      }
      function tryAutoSkip() {
        if (store.currentImageIndex !== idx) return;
        const nextIdx = idx + 1;
        if (nextIdx < store.allImages.length) {
          const nextImg = store.allImages[nextIdx];
          if (nextImg && isImageReady(nextImg)) {
            clearLoadPoll();
            store.currentImageIndex = nextIdx;
            updateImage();
            checkAndLoadNextPage();
            if (store.autoPlay) autoPlay.start();
            return;
          }
        }
        if (nextIdx < store.allImages.length || imageErrored) {
          clearLoadPoll();
          store.currentImageIndex = nextIdx < store.allImages.length ? nextIdx : idx;
          updateImage();
          if (nextIdx < store.allImages.length) {
            checkAndLoadNextPage();
          }
        }
      }
      if (lastKnownImg && lastKnownImg.tagName === "IMG") {
        lastKnownImg.addEventListener("load", onImageReady, { once: true });
        lastKnownImg.addEventListener("error", onImageError, { once: true });
      }
      const mainBox = document.querySelector(store.settings.scrollMode ? "#gdt" : "#gdt-hidden");
      if (mainBox) {
        loadObserver = new MutationObserver(() => {
          if (store.currentImageIndex !== idx) {
            clearLoadPoll();
            return;
          }
          syncImages();
          const currentImg = store.allImages[idx];
          if (currentImg) {
            if (currentImg.classList.contains("error")) {
              showError();
              return;
            } else if (currentImg.classList.contains("loading")) {
              showPlaceholder(i18n.downloading);
              return;
            }
            const imgSrc = currentImg.dataset.realSrc || currentImg.src;
            applyOverlaySrc(imgSrc, currentImg);
            if (currentImg !== lastKnownImg) {
              lastKnownImg = currentImg;
              if (currentImg.tagName === "IMG") {
                currentImg.addEventListener("load", onImageReady, { once: true });
                currentImg.addEventListener("error", onImageError, { once: true });
                if (isImageReady(currentImg)) onImageReady();
              }
            }
          }
        });
        loadObserver.observe(mainBox, { childList: true, subtree: true });
      }
      loadPollTimer = setInterval(() => {
        if (store.currentImageIndex !== idx) {
          clearLoadPoll();
          return;
        }
        const currentImg = store.allImages[idx];
        if (currentImg) {
          if (currentImg.classList.contains("error")) {
            showError();
            return;
          } else if (currentImg.classList.contains("loading")) {
            showPlaceholder(i18n.downloading);
            return;
          }
          const imgSrc = currentImg.dataset.realSrc || currentImg.src;
          applyOverlaySrc(imgSrc, currentImg);
          if (currentImg !== lastKnownImg) {
            lastKnownImg = currentImg;
            if (currentImg.tagName === "IMG") {
              currentImg.addEventListener("load", onImageReady, { once: true });
              currentImg.addEventListener("error", onImageError, { once: true });
            }
          }
        }
        onImageReady();
      }, 500);
      if (store.autoPlay) {
        loadTimeoutTimer = setTimeout(() => {
          if (store.currentImageIndex !== idx) return;
          const img = store.allImages[idx];
          if (img && isImageReady(img)) return;
          tryAutoSkip();
        }, CFG.imageLoadTimeout);
      }
    }
    const autoPlay = createAutoPlay(() => nav.nextImage());
    const sidebar = createSidebar((index) => {
      store.currentImageIndex = index;
      updateImage();
      autoPlay.reset();
    }, () => loadNextPage(), () => loadPrevPage());
    const nav = setupNavigation({
      overlay,
      updateImage,
      checkAndLoadNextPage: () => checkAndLoadNextPage(),
      checkAndLoadPrevPage: () => loadPrevPage(),
      resetAutoPlay: () => autoPlay.reset(),
      stopAutoPlayAtEnd: () => autoPlay.stopAtEnd(),
      closeSinglePageMode: () => close()
    });
    overlay.addEventListener("wheel", () => {
      sidebar.wakeUpProgressBar();
    }, { passive: true });
    overlay.appendChild(closeBtn);
    sidebar.getElements().forEach((el) => overlay.appendChild(el));
    overlay.appendChild(statusHUD.getElement());
    overlay.appendChild(imageContainer);
    document.body.appendChild(overlay);
    closeBtn.onclick = () => close();
    function open() {
      var _a, _b;
      store.allImages = Array.from(qa(".r-img, .r-ph"));
      if (store.allImages.length === 0) {
        alert(i18n.waitImagesToLoad);
        return;
      }
      let startIndex = 0;
      if (store.settings.scrollMode) {
        let minDistance = Infinity;
        store.allImages.forEach((img, index) => {
          const rect = img.getBoundingClientRect();
          const viewportCenter = window.innerHeight / 2;
          if (rect.top <= viewportCenter && rect.bottom >= viewportCenter) {
            startIndex = index;
            minDistance = -1;
          } else if (minDistance !== -1) {
            const distanceToCenter = rect.bottom < viewportCenter ? viewportCenter - rect.bottom : rect.top - viewportCenter;
            if (distanceToCenter < minDistance) {
              minDistance = distanceToCenter;
              startIndex = index;
            }
          }
        });
      } else {
        const adapter = store.activeAdapter;
        let nativeImages = [];
        if (adapter == null ? void 0 : adapter.getNativeImages) {
          nativeImages = adapter.getNativeImages();
        } else {
          const container = adapter == null ? void 0 : adapter.getContainer();
          if (container) {
            nativeImages = Array.from(container.querySelectorAll("img")).filter((img) => img.clientWidth > 50 || img.clientHeight > 50);
          }
        }
        if (nativeImages.length > 0) {
          let minDistance = Infinity;
          let bestNativeImg = null;
          nativeImages.forEach((img) => {
            const rect = img.getBoundingClientRect();
            if (rect.width === 0 || rect.height === 0) return;
            const viewportCenter = window.innerHeight / 2;
            if (rect.top <= viewportCenter && rect.bottom >= viewportCenter) {
              bestNativeImg = img;
              minDistance = -1;
            } else if (minDistance !== -1) {
              const distanceToCenter = rect.bottom < viewportCenter ? viewportCenter - rect.bottom : rect.top - viewportCenter;
              if (distanceToCenter < minDistance) {
                minDistance = distanceToCenter;
                bestNativeImg = img;
              }
            }
          });
          if (bestNativeImg) {
            const currentSrc = ((_a = bestNativeImg.dataset) == null ? void 0 : _a.viewerUrl) || ((_b = bestNativeImg.dataset) == null ? void 0 : _b.src) || bestNativeImg.src;
            const foundIdx = store.allImages.findIndex((i) => {
              var _a2, _b2, _c;
              const iSrc = ((_a2 = i.dataset) == null ? void 0 : _a2.viewerUrl) || ((_b2 = i.dataset) == null ? void 0 : _b2.realSrc) || ((_c = i.dataset) == null ? void 0 : _c.src) || i.src;
              return iSrc === currentSrc;
            });
            if (foundIdx !== -1) {
              startIndex = foundIdx;
            }
          }
        } else {
          startIndex = 0;
        }
      }
      store.currentImageIndex = startIndex;
      overlay.classList.add("active");
      document.body.style.overflow = "hidden";
      updateImage();
      store.emit("readerModeChanged");
      if (store.autoPlay) {
        autoPlay.start();
      }
    }
    function close() {
      var _a, _b;
      clearLoadPoll();
      removeErrorUI();
      autoPlay.stop();
      store.autoPlay = false;
      overlay.classList.remove("active");
      document.body.style.overflow = "";
      store.emit("readerModeChanged");
      if (store.settings.scrollMode) {
        const currentImages = Array.from(qa(".r-img, .r-ph"));
        if (store.currentImageIndex >= 0 && store.currentImageIndex < currentImages.length) {
          const targetImg = currentImages[store.currentImageIndex];
          if (targetImg) {
            setTimeout(() => {
              targetImg.scrollIntoView({ behavior: "smooth", block: "center" });
            }, 100);
          }
        }
      } else {
        const adapter = store.activeAdapter;
        let nativeImages = [];
        if (adapter == null ? void 0 : adapter.getNativeImages) {
          nativeImages = adapter.getNativeImages();
        } else {
          const container = adapter == null ? void 0 : adapter.getContainer();
          if (container) {
            nativeImages = Array.from(container.querySelectorAll("img")).filter((img) => img.clientWidth > 50 || img.clientHeight > 50);
          }
        }
        const targetImgFallback = store.allImages[store.currentImageIndex];
        const batchDiv = targetImgFallback == null ? void 0 : targetImgFallback.closest(".page-batch");
        if (batchDiv && batchDiv.dataset.pageUrl) {
          const targetUrl = new URL(batchDiv.dataset.pageUrl, window.location.href);
          const currentUrl = new URL(window.location.href);
          if (targetUrl.pathname !== currentUrl.pathname || targetUrl.search !== currentUrl.search) {
            window.location.href = targetUrl.toString();
            return;
          }
        }
        if (store.currentImageIndex >= 0 && nativeImages.length > 0) {
          const currentSrc = ((_a = targetImgFallback == null ? void 0 : targetImgFallback.dataset) == null ? void 0 : _a.viewerUrl) || ((_b = targetImgFallback == null ? void 0 : targetImgFallback.dataset) == null ? void 0 : _b.realSrc) || (targetImgFallback == null ? void 0 : targetImgFallback.src);
          if (currentSrc) {
            const targetNativeImg = nativeImages.find((img) => {
              var _a2, _b2;
              const nativeSrc = ((_a2 = img.dataset) == null ? void 0 : _a2.viewerUrl) || ((_b2 = img.dataset) == null ? void 0 : _b2.src) || img.src;
              return nativeSrc === currentSrc;
            });
            if (targetNativeImg) {
              setTimeout(() => {
                targetNativeImg.scrollIntoView({ behavior: "smooth", block: "center" });
              }, 100);
              return;
            }
          }
        }
        if ((adapter == null ? void 0 : adapter.name) === "E-Hentai" || (adapter == null ? void 0 : adapter.name) === "ExHentai") {
          const globalIndex = store.imageOffset + store.currentImageIndex;
          if (globalIndex >= 0) {
            const targetPage = Math.floor(globalIndex / store.perPage);
            const url = new URL(window.location.href);
            const currentPage = parseInt(url.searchParams.get("p") || "0");
            if (targetPage !== currentPage) {
              url.searchParams.set("p", String(targetPage));
              window.location.href = url.toString();
            }
          }
        }
      }
    }
    store.on("settingsChanged", () => {
      if (!overlay.classList.contains("active")) return;
      if (store.autoPlay) {
        const img = store.allImages[store.currentImageIndex];
        if (img && isImageReady(img)) {
          autoPlay.start();
        }
      } else {
        autoPlay.stop();
      }
    });
    function loadNextPage() {
      if (!store.nextUrl || store.isFetching) return;
      store.isFetching = true;
      store.activeAdapter.fetchPage(store.nextUrl).then(({ links, nextUrl, prevUrl }) => {
        deps.onLoadNextPage(links, nextUrl, prevUrl);
        syncImages();
        store.isFetching = false;
        checkAndLoadNextPage();
      }).catch((err) => {
        console.error("[Single Page] Load failed", err);
        store.isFetching = false;
      });
    }
    function loadPrevPage() {
      if (!store.prevUrl || store.isFetching) return;
      store.isFetching = true;
      store.activeAdapter.fetchPage(store.prevUrl).then(({ links, prevUrl }) => {
        const prevCount = links.length;
        deps.onLoadPrevPage(links, prevUrl ?? null);
        store.currentImageIndex += prevCount;
        store.imageOffset = Math.max(0, store.imageOffset - prevCount);
        if (prevCount > 0 && store.currentImageIndex === prevCount) {
          store.currentImageIndex--;
        }
        store.allImages = Array.from(qa(".r-img, .r-ph"));
        sidebar.update();
        updateImage();
        store.isFetching = false;
      }).catch((err) => {
        console.error("[Single Page] Load prev failed", err);
        store.isFetching = false;
      });
    }
    function checkAndLoadNextPage() {
      if (!store.nextUrl || store.isFetching) return;
      const remainingImages = store.allImages.length - store.currentImageIndex;
      if (remainingImages <= 10) {
        loadNextPage();
      }
    }
    function jumpTo(index) {
      if (!overlay.classList.contains("active")) return;
      store.currentImageIndex = Math.max(0, Math.min(index, store.allImages.length - 1));
      updateImage();
      autoPlay.reset();
    }
    return {
      open,
      close,
      isActive: () => overlay.classList.contains("active"),
      getOverlayElement: () => overlay,
      jumpTo
    };
  }
  function initSinglePageMode() {
    const spm = createSinglePageOverlay({
      onLoadNextPage: (links, nextUrl) => {
        store.currPage++;
        processBatch(links, store.currPage, void 0, false, store.nextUrl || void 0);
        store.nextUrl = nextUrl;
      },
      onLoadPrevPage: (links, prevUrl) => {
        processBatch(links, store.currPage - 1, void 0, true, store.prevUrl || void 0);
        store.prevUrl = prevUrl;
      }
    });
    return spm;
  }
  const svgSettings = `<svg viewBox="0 0 24 24"><path d="M19.14,12.94c0.04-0.3,0.06-0.61,0.06-0.94c0-0.32-0.02-0.64-0.07-0.94l2.03-1.58c0.18-0.14,0.23-0.41,0.12-0.61 l-1.92-3.32c-0.12-0.22-0.37-0.29-0.59-0.22l-2.39,0.96c-0.5-0.38-1.03-0.7-1.62-0.94L14.4,2.81c-0.04-0.24-0.24-0.41-0.48-0.41 h-3.84c-0.24,0-0.43,0.17-0.47,0.41L9.25,5.35C8.66,5.59,8.12,5.92,7.63,6.29L5.24,5.33c-0.22-0.08-0.47,0-0.59,0.22L2.74,8.87 C2.62,9.08,2.66,9.34,2.86,9.48l2.03,1.58C4.84,11.36,4.8,11.69,4.8,12s0.02,0.64,0.07,0.94l-2.03,1.58 c-0.18,0.14-0.23,0.41-0.12,0.61l1.92,3.32c0.12,0.22,0.37,0.29,0.59,0.22l2.39-0.96c0.5,0.38,1.03,0.7,1.62,0.94l0.36,2.54 c0.05,0.24,0.24,0.41,0.48,0.41h3.84c0.24,0,0.44-0.17,0.47-0.41l0.36-2.54c0.59-0.24,1.13-0.56,1.62-0.94l2.39,0.96 c0.22,0.08,0.47,0,0.59-0.22l1.92-3.32c0.12-0.22,0.07-0.47-0.12-0.61L19.14,12.94z M12,15.6c-1.98,0-3.6-1.62-3.6-3.6 s1.62-3.6,3.6-3.6s3.6,1.62,3.6,3.6S13.98,15.6,12,15.6z"/></svg>`;
  const svgReader = `<svg viewBox="0 0 24 24"><path d="M21 5c-1.11-.35-2.33-.5-3.5-.5-1.95 0-4.05.4-5.5 1.5-1.45-1.1-3.55-1.5-5.5-1.5S2.45 4.9 1 6v14.65c0 .25.25.5.5.5.1 0 .15-.05.25-.05C3.1 20.45 5.05 20 6.5 20c1.95 0 4.05.4 5.5 1.5 1.35-.85 3.8-1.5 5.5-1.5 1.65 0 3.35.3 4.75 1.05.1.05.15.05.25.05.25 0 .5-.25.5-.5V6c-.6-.45-1.25-.75-2-1zm0 13.5c-1.1-.35-2.3-.5-3.5-.5-1.7 0-4.15.65-5.5 1.5V8c1.35-.85 3.8-1.5 5.5-1.5 1.2 0 2.4.15 3.5.5v11.5z"/></svg>`;
  const svgPlay = `<svg viewBox="0 0 24 24"><path d="M8 5v14l11-7z"/></svg>`;
  const svgPause = `<svg viewBox="0 0 24 24"><path d="M6 4h4v16H6V4zm8 0h4v16h-4V4z"/></svg>`;
  const svgTop = `<svg viewBox="0 0 24 24"><path d="M4 4h16v2H4V4zm4 8l1.41 1.41L11 11.83V22h2V11.83l1.59 1.58L16 12l-4-4-4 4z"/></svg>`;
  const SETTINGS = [
    { label: i18n.scrollMode, key: "scrollMode" },
    { label: i18n.showControl, key: "showControl" },
    { label: i18n.autoEnter, key: "autoEnterSinglePage" }
  ];
  function createSettingsPanel() {
    const settingsBtn = document.createElement("div");
    settingsBtn.className = "settings-btn";
    const settingsPanel = document.createElement("div");
    settingsPanel.className = "settings-panel";
    SETTINGS.forEach(({ label, key }) => {
      if (key === "scrollMode" && store.activeAdapter && ["18comic", "4KHD"].includes(store.activeAdapter.name)) {
        return;
      }
      const item = document.createElement("div");
      item.className = "settings-item";
      const labelEl = document.createElement("span");
      labelEl.className = "settings-label";
      labelEl.textContent = label;
      const toggle = document.createElement("div");
      toggle.className = `toggle-switch${store.settings[key] ? " on" : ""}`;
      const slider = document.createElement("div");
      slider.className = "toggle-slider";
      toggle.appendChild(slider);
      toggle.onclick = () => {
        const newValue = !store.settings[key];
        store.updateSetting(key, newValue);
        toggle.classList.toggle("on", newValue);
        if (key === "scrollMode") {
          window.location.reload();
        }
      };
      item.appendChild(labelEl);
      item.appendChild(toggle);
      settingsPanel.appendChild(item);
    });
    const intervalItem = document.createElement("div");
    intervalItem.className = "settings-item";
    const intervalLabel = document.createElement("span");
    intervalLabel.className = "settings-label";
    intervalLabel.textContent = i18n.playSpeed;
    const intervalRight = document.createElement("div");
    intervalRight.style.cssText = "display:flex;align-items:center;gap:4px;";
    const intervalInput = document.createElement("input");
    intervalInput.type = "number";
    intervalInput.className = "interval-input";
    intervalInput.min = "1";
    intervalInput.max = "60";
    intervalInput.step = "0.5";
    intervalInput.value = String(store.settings.autoPlayInterval / 1e3);
    intervalInput.onclick = (e) => e.stopPropagation();
    intervalInput.onchange = (e) => {
      const value = parseFloat(e.target.value);
      if (!isNaN(value) && value >= 1 && value <= 60) {
        store.updateSetting("autoPlayInterval", value * 1e3);
      }
    };
    const intervalUnit = document.createElement("span");
    intervalUnit.textContent = "s";
    intervalUnit.style.cssText = "font-size:12px;color:#888;";
    intervalRight.appendChild(intervalInput);
    intervalRight.appendChild(intervalUnit);
    intervalItem.appendChild(intervalLabel);
    intervalItem.appendChild(intervalRight);
    settingsPanel.appendChild(intervalItem);
    settingsBtn.onclick = (e) => {
      e.stopPropagation();
      settingsPanel.classList.toggle("show");
    };
    document.addEventListener("click", (e) => {
      if (!settingsPanel.contains(e.target) && !settingsBtn.contains(e.target)) {
        settingsPanel.classList.remove("show");
      }
    });
    return {
      getButtonElement: () => settingsBtn,
      getPanelElement: () => settingsPanel
    };
  }
  function createFloatControl(spmHandle) {
    const floatControl = document.createElement("div");
    floatControl.className = `float-control${store.settings.showControl ? "" : " hidden"}`;
    const autoPlayBtn = document.createElement("div");
    autoPlayBtn.className = `side-btn auto-play-btn hidden${store.autoPlay ? " active" : ""}`;
    autoPlayBtn.innerHTML = store.autoPlay ? svgPause : svgPlay;
    autoPlayBtn.title = i18n.autoPlay;
    autoPlayBtn.onclick = (e) => {
      e.stopPropagation();
      const newValue = !store.autoPlay;
      store.autoPlay = newValue;
      store.emit("settingsChanged");
      autoPlayBtn.innerHTML = newValue ? svgPause : svgPlay;
      autoPlayBtn.classList.toggle("active", newValue);
    };
    const circleControl = document.createElement("div");
    circleControl.className = "circle-control";
    circleControl.innerHTML = svgReader;
    circleControl.title = i18n.readerMode;
    circleControl.onclick = (e) => {
      var _a;
      if (e.target !== circleControl && !((_a = circleControl.querySelector("svg")) == null ? void 0 : _a.contains(e.target))) return;
      if (spmHandle.isActive()) {
        spmHandle.close();
      } else {
        spmHandle.open();
      }
    };
    store.on("readerModeChanged", () => {
      if (spmHandle.isActive()) {
        autoPlayBtn.classList.remove("hidden");
        autoPlayBtn.innerHTML = store.autoPlay ? svgPause : svgPlay;
        autoPlayBtn.classList.toggle("active", store.autoPlay);
      } else {
        autoPlayBtn.classList.add("hidden");
      }
    });
    const settings = createSettingsPanel();
    const settingsBtn = settings.getButtonElement();
    settingsBtn.className = "side-btn";
    settingsBtn.innerHTML = svgSettings;
    settingsBtn.title = i18n.settings;
    const topBtn = document.createElement("div");
    topBtn.className = "side-btn top-btn";
    topBtn.innerHTML = svgTop;
    topBtn.title = i18n.backToTop;
    topBtn.onclick = (e) => {
      e.stopPropagation();
      if (spmHandle.isActive()) {
        spmHandle.jumpTo(0);
      } else {
        window.scrollTo({ top: 0, behavior: "smooth" });
        document.documentElement.scrollTo({ top: 0, behavior: "smooth" });
        document.body.scrollTo({ top: 0, behavior: "smooth" });
      }
    };
    circleControl.appendChild(topBtn);
    floatControl.appendChild(autoPlayBtn);
    floatControl.appendChild(circleControl);
    floatControl.appendChild(settingsBtn);
    floatControl.appendChild(settings.getPanelElement());
    document.body.appendChild(floatControl);
  }
  function registerMenuCommands() {
    if (!store.activeAdapter || !["18comic", "4KHD"].includes(store.activeAdapter.name)) {
      _GM_registerMenuCommand(`${i18n.toggle}${i18n.scrollMode}`, () => {
        store.updateSetting("scrollMode", !store.settings.scrollMode);
        alert(`${i18n.scrollMode} ${store.settings.scrollMode ? i18n.enabled : i18n.disabled}`);
        location.reload();
      });
    }
    _GM_registerMenuCommand(`${i18n.toggle}${i18n.showControl}`, () => {
      store.updateSetting("showControl", !store.settings.showControl);
      alert(`${i18n.showControl} ${store.settings.showControl ? i18n.enabled : i18n.disabled}`);
      location.reload();
    });
    _GM_registerMenuCommand(`${i18n.toggle}${i18n.autoEnter}`, () => {
      store.updateSetting("autoEnterSinglePage", !store.settings.autoEnterSinglePage);
      alert(`${i18n.autoEnter} ${store.settings.autoEnterSinglePage ? i18n.enabled : i18n.disabled}`);
      location.reload();
    });
  }
  function initMemoryManager() {
    const mainBox = document.querySelector(store.settings.scrollMode ? "#gdt" : "#gdt-hidden");
    if (mainBox) {
      const domObs = new MutationObserver(() => {
        const images = Array.from(qa(".r-img, .r-ph"));
        let changed = images.length !== store.allImages.length;
        if (!changed) {
          for (let i = 0; i < images.length; i++) {
            if (images[i] !== store.allImages[i]) {
              changed = true;
              break;
            }
          }
        }
        if (changed) {
          store.allImages = images;
        }
      });
      domObs.observe(mainBox, { childList: true, subtree: true });
    }
    setInterval(() => {
      if (store.allImages.length < 40) return;
      if (document.querySelector(".single-page-overlay.active")) return;
      const viewportCenter = window.innerHeight / 2;
      let minDistance = Infinity;
      let closestIndex = store.currentImageIndex;
      store.allImages.forEach((el, i) => {
        const rect = el.getBoundingClientRect();
        if (rect.height > 0) {
          const center = rect.top + rect.height / 2;
          const dist = Math.abs(center - viewportCenter);
          if (dist < minDistance) {
            minDistance = dist;
            closestIndex = i;
          }
        }
      });
      store.currentImageIndex = closestIndex;
      const curr = store.currentImageIndex;
      const buffer = 30;
      store.allImages.forEach((img, i) => {
        const distance = Math.abs(i - curr);
        if (distance > buffer) {
          if (img.tagName === "IMG" && img.hasAttribute("src") && img.complete) {
            img.dataset.recycledSrc = img.getAttribute("src") || "";
            img.removeAttribute("src");
          }
        } else {
          if (img.tagName === "IMG" && !img.hasAttribute("src") && img.dataset.recycledSrc) {
            img.setAttribute("src", img.dataset.recycledSrc);
            delete img.dataset.recycledSrc;
          }
        }
      });
    }, 2e3);
  }
  (async function main() {
    var _a;
    const adapter = SiteManager.getAdapter(window.location.href);
    if (!adapter) {
      return;
    }
    store.activeAdapter = adapter;
    store.reloadSettings();
    if (adapter.name === "18comic" || adapter.name === "4KHD") {
      store.settings.scrollMode = true;
    }
    const initData = await adapter.init(document);
    if (!initData.links || initData.links.length === 0) return;
    store.totalPage = initData.totalPage ?? 1;
    store.nextUrl = initData.nextUrl;
    store.prevUrl = initData.prevUrl;
    store.perPage = initData.links.length;
    let container = adapter.getContainer();
    if (store.settings.scrollMode) {
      document.documentElement.classList.add("scroll-mode");
      (_a = adapter.hideOriginalElements) == null ? void 0 : _a.call(adapter);
      if (!container) {
        container = document.createElement("div");
        container.id = "gdt";
        document.body.appendChild(container);
      }
      container.innerHTML = "";
      processBatch(initData.links, store.currPage, container, false, window.location.href);
      setupAutoScroll();
    } else {
      const hiddenBox = document.createElement("div");
      hiddenBox.id = "gdt-hidden";
      hiddenBox.style.display = "none";
      document.body.appendChild(hiddenBox);
      processBatch(initData.links, store.currPage, hiddenBox, false, window.location.href);
    }
    let spmHandle;
    createFloatControl({
      open: () => spmHandle.open(),
      close: () => spmHandle.close(),
      isActive: () => spmHandle.isActive(),
      getOverlayElement: () => spmHandle.getOverlayElement(),
      jumpTo: (index) => spmHandle.jumpTo(index)
    });
    spmHandle = initSinglePageMode();
    registerMenuCommands();
    if (store.settings.autoEnterSinglePage) {
      setTimeout(() => spmHandle.open(), 1e3);
    }
    initMemoryManager();
  })();

})();