Hentai Reader

A high-performance universal reader for image galleries, now with mobile and touch device support, plus infinite scroll, immersive reader mode, and smart image loading, with ongoing multi-site support (E-Hentai, 18comic, 4KHD).

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Advertisement:

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

Advertisement:

// ==UserScript==
// @name               Hentai Reader
// @name:zh-CN         绅士阅读器
// @namespace          http://tampermonkey.net/
// @version            3.2.0
// @author             Leovikii
// @description        A high-performance universal reader for image galleries, now with mobile and touch device support, plus infinite scroll, immersive reader mode, and smart image loading, with ongoing multi-site support (E-Hentai, 18comic, 4KHD).
// @description:zh-CN  面向图库的高性能通用阅读器,现已适配移动端与触控设备。支持无限卷轴、沉浸式阅读器与智能图片加载,多网站持续适配(E-Hentai、禁漫天堂、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));};

  const photoswipeCss = "/*! PhotoSwipe main CSS by Dmytro Semenov | photoswipe.com */.pswp{--pswp-bg: #000;--pswp-placeholder-bg: #222;--pswp-root-z-index: 100000;--pswp-preloader-color: rgba(79, 79, 79, .4);--pswp-preloader-color-secondary: rgba(255, 255, 255, .9);--pswp-icon-color: #fff;--pswp-icon-color-secondary: #4f4f4f;--pswp-icon-stroke-color: #4f4f4f;--pswp-icon-stroke-width: 2px;--pswp-error-text-color: var(--pswp-icon-color)}.pswp{position:fixed;top:0;left:0;width:100%;height:100%;z-index:var(--pswp-root-z-index);display:none;touch-action:none;outline:0;opacity:.003;contain:layout style size;-webkit-tap-highlight-color:rgba(0,0,0,0)}.pswp:focus{outline:0}.pswp *{box-sizing:border-box}.pswp img{max-width:none}.pswp--open{display:block}.pswp,.pswp__bg{transform:translateZ(0);will-change:opacity}.pswp__bg{opacity:.005;background:var(--pswp-bg)}.pswp,.pswp__scroll-wrap{overflow:hidden}.pswp__scroll-wrap,.pswp__bg,.pswp__container,.pswp__item,.pswp__content,.pswp__img,.pswp__zoom-wrap{position:absolute;top:0;left:0;width:100%;height:100%}.pswp__img,.pswp__zoom-wrap{width:auto;height:auto}.pswp--click-to-zoom.pswp--zoom-allowed .pswp__img{cursor:-webkit-zoom-in;cursor:-moz-zoom-in;cursor:zoom-in}.pswp--click-to-zoom.pswp--zoomed-in .pswp__img{cursor:move;cursor:-webkit-grab;cursor:-moz-grab;cursor:grab}.pswp--click-to-zoom.pswp--zoomed-in .pswp__img:active{cursor:-webkit-grabbing;cursor:-moz-grabbing;cursor:grabbing}.pswp--no-mouse-drag.pswp--zoomed-in .pswp__img,.pswp--no-mouse-drag.pswp--zoomed-in .pswp__img:active,.pswp__img{cursor:-webkit-zoom-out;cursor:-moz-zoom-out;cursor:zoom-out}.pswp__container,.pswp__img,.pswp__button,.pswp__counter{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.pswp__item{z-index:1;overflow:hidden}.pswp__hidden{display:none!important}.pswp__content{pointer-events:none}.pswp__content>*{pointer-events:auto}.pswp__error-msg-container{display:grid}.pswp__error-msg{margin:auto;font-size:1em;line-height:1;color:var(--pswp-error-text-color)}.pswp .pswp__hide-on-close{opacity:.005;will-change:opacity;transition:opacity var(--pswp-transition-duration) cubic-bezier(.4,0,.22,1);z-index:10;pointer-events:none}.pswp--ui-visible .pswp__hide-on-close{opacity:1;pointer-events:auto}.pswp__button{position:relative;display:block;width:50px;height:60px;padding:0;margin:0;overflow:hidden;cursor:pointer;background:none;border:0;box-shadow:none;opacity:.85;-webkit-appearance:none;-webkit-touch-callout:none}.pswp__button:hover,.pswp__button:active,.pswp__button:focus{transition:none;padding:0;background:none;border:0;box-shadow:none;opacity:1}.pswp__button:disabled{opacity:.3;cursor:auto}.pswp__icn{fill:var(--pswp-icon-color);color:var(--pswp-icon-color-secondary)}.pswp__icn{position:absolute;top:14px;left:9px;width:32px;height:32px;overflow:hidden;pointer-events:none}.pswp__icn-shadow{stroke:var(--pswp-icon-stroke-color);stroke-width:var(--pswp-icon-stroke-width);fill:none}.pswp__icn:focus{outline:0}div.pswp__img--placeholder,.pswp__img--with-bg{background:var(--pswp-placeholder-bg)}.pswp__top-bar{position:absolute;left:0;top:0;width:100%;height:60px;display:flex;flex-direction:row;justify-content:flex-end;z-index:10;pointer-events:none!important}.pswp__top-bar>*{pointer-events:auto;will-change:opacity}.pswp__button--close{margin-right:6px}.pswp__button--arrow{position:absolute;width:75px;height:100px;top:50%;margin-top:-50px}.pswp__button--arrow:disabled{display:none;cursor:default}.pswp__button--arrow .pswp__icn{top:50%;margin-top:-30px;width:60px;height:60px;background:none;border-radius:0}.pswp--one-slide .pswp__button--arrow{display:none}.pswp--touch .pswp__button--arrow{visibility:hidden}.pswp--has_mouse .pswp__button--arrow{visibility:visible}.pswp__button--arrow--prev{right:auto;left:0}.pswp__button--arrow--next{right:0}.pswp__button--arrow--next .pswp__icn{left:auto;right:14px;transform:scaleX(-1)}.pswp__button--zoom{display:none}.pswp--zoom-allowed .pswp__button--zoom{display:block}.pswp--zoomed-in .pswp__zoom-icn-bar-v{display:none}.pswp__preloader{position:relative;overflow:hidden;width:50px;height:60px;margin-right:auto}.pswp__preloader .pswp__icn{opacity:0;transition:opacity .2s linear;animation:pswp-clockwise .6s linear infinite}.pswp__preloader--active .pswp__icn{opacity:.85}@keyframes pswp-clockwise{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.pswp__counter{height:30px;margin-top:15px;margin-inline-start:20px;font-size:14px;line-height:30px;color:var(--pswp-icon-color);text-shadow:1px 1px 3px var(--pswp-icon-color-secondary);opacity:.85}.pswp--one-slide .pswp__counter{display:none}";
  importCSS(photoswipeCss);
  const globalCss = ":root{--hr-accent: #F596AA;--hr-accent-hover: #F7ABBE}html.hr-instant-scroll,html.hr-instant-scroll body{scroll-behavior:auto!important}@keyframes hr-spin{to{transform:rotate(360deg)}}.hr-spinner{animation:hr-spin 1s linear infinite}html.scroll-mode body{margin:0}html.scroll-mode #gdt{display:flex;flex-direction:column;align-items:center;width:100%;max-width:1200px;margin:auto;padding-bottom:100px}.hr-page-batch{width:100%;display:flex;flex-direction:column;align-items:center;margin-bottom:60px}html.hr-reader-open .hr-page-batch{visibility:hidden}.r-img{display:block;width:auto;max-width:100%;margin-bottom:20px;background:transparent;box-shadow:0 0 20px #00000080;position:relative;content-visibility:auto;contain-intrinsic-size:auto 100vh}.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;content-visibility:auto;contain-intrinsic-size:auto 400px}.r-ph.loading{color:#888;border-color:#555}.r-ph.error{color:#d44;border-color:#d44}";
  importCSS(globalCss);
  var _GM_getValue = (() => typeof GM_getValue != "undefined" ? GM_getValue : void 0)();
  var _GM_setValue = (() => typeof GM_setValue != "undefined" ? GM_setValue : void 0)();
  const CFG = {
    nextPage: "3000px 0px",
    maxConcurrent: 3
  };
  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),
      clickToEnterReader: _GM_getValue("clickToEnterReader", true),
      autoPlayInterval: _GM_getValue("autoPlayInterval", 5e3),
      thumbnailPosition: _GM_getValue("thumbnailPosition", "bottom")
    };
  }
  class Store {
constructor() {
      this.listeners = new Map();
      this.activeAdapter = null;
      this.currPage = 1;
      this.perPage = 20;
      this.imageOffset = 0;
      this.nextUrl = null;
      this.prevUrl = null;
      this.isFetching = false;
      this.galleryItems = [];
      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);
      return () => {
        const listeners = this.listeners.get(event);
        listeners == null ? void 0 : listeners.delete(listener);
        if ((listeners == null ? void 0 : listeners.size) === 0) this.listeners.delete(event);
      };
    }
    emit(event) {
      var _a;
      (_a = this.listeners.get(event)) == null ? void 0 : _a.forEach((fn) => fn());
    }
  }
  const store = new Store();
  const systemClock = {
    now: () => Date.now(),
    setTimeout: (callback, delay) => setTimeout(callback, delay),
    clearTimeout: (id) => clearTimeout(id)
  };
  class NetLimiter {
    constructor(maxConcurrent, clock = systemClock) {
      this.queue = [];
      this.active = 0;
      this.pausedUntil = 0;
      this.seq = 0;
      this.pauseTimer = null;
      this.maxConcurrent = maxConcurrent;
      this.clock = clock;
    }
run(task, priority = 0) {
      return new Promise((resolve, reject) => {
        this.queue.push({
          run: task,
          resolve,
          reject,
          priority,
          seq: this.seq++
        });
        this.pump();
      });
    }
pauseFor(ms) {
      const until = this.clock.now() + ms;
      if (until <= this.pausedUntil) return;
      this.pausedUntil = until;
      this.schedulePauseWake(true);
    }
cancel(predicate) {
      if (this.queue.length === 0) return;
      const kept = [];
      for (const job of this.queue) {
        if (predicate(job.priority, job.seq)) {
          job.reject({ cancelled: true });
        } else {
          kept.push(job);
        }
      }
      this.queue = kept;
    }
    pump() {
      const now = this.clock.now();
      if (now < this.pausedUntil) {
        this.schedulePauseWake();
        return;
      }
      if (this.pauseTimer !== null) {
        this.clock.clearTimeout(this.pauseTimer);
        this.pauseTimer = null;
      }
      while (this.active < this.maxConcurrent && this.queue.length > 0) {
        let bestIdx = 0;
        for (let i = 1; i < this.queue.length; i++) {
          const cand = this.queue[i];
          const best = this.queue[bestIdx];
          if (cand.priority > best.priority || cand.priority === best.priority && cand.seq < best.seq) {
            bestIdx = i;
          }
        }
        const job = this.queue.splice(bestIdx, 1)[0];
        this.active++;
        Promise.resolve().then(() => job.run()).then(
          (value) => {
            job.resolve(value);
            this.active--;
            this.pump();
          },
          (reason) => {
            job.reject(reason);
            this.active--;
            this.pump();
          }
        );
      }
    }
    schedulePauseWake(reschedule = false) {
      if (reschedule && this.pauseTimer !== null) {
        this.clock.clearTimeout(this.pauseTimer);
        this.pauseTimer = null;
      }
      if (this.pauseTimer !== null) return;
      const delay = Math.max(0, this.pausedUntil - this.clock.now() + 10);
      this.pauseTimer = this.clock.setTimeout(() => {
        this.pauseTimer = null;
        this.pump();
      }, delay);
    }
  }
  const LOAD_PRIORITY = {
    scroll: 0,
    warmup: 5,
    thumbnail: 10,
    pageHtml: 50,
    foreground: 100
  };
  function paginationUrl(doc, marker) {
    const pagination = doc.querySelector(".ptt");
    if (!pagination) return null;
    const link = Array.from(pagination.querySelectorAll("td a")).find((anchor) => (anchor.textContent ?? "").includes(marker));
    return (link == null ? void 0 : link.href) ?? null;
  }
  function getEHentaiNextUrl(doc) {
    return paginationUrl(doc, ">");
  }
  function getEHentaiPrevUrl(doc) {
    return paginationUrl(doc, "<");
  }
  function extractEHentaiItems(doc) {
    return Array.from(doc.querySelectorAll("#gdt a")).map((element) => {
      const anchor = element;
      const url = anchor.href;
      let thumb;
      let thumbX;
      let thumbY;
      let thumbW;
      let thumbH;
      const sprite = anchor.querySelector('div[style*="background"]');
      if (sprite) {
        const style = sprite.getAttribute("style") || "";
        const source = style.match(/url\(['"]?([^)'"]+)['"]?\)/);
        if (source) thumb = source[1];
        const afterUrl = style.slice(style.indexOf(source ? source[0] : "") + (source ? source[0].length : 0));
        const position = afterUrl.match(/(-?\d+)(?:px)?\s+(-?\d+)(?:px)?/);
        if (position) {
          thumbX = Math.abs(parseInt(position[1], 10));
          thumbY = Math.abs(parseInt(position[2], 10));
        }
        const width = style.match(/width:\s*(\d+)px/);
        const height = style.match(/height:\s*(\d+)px/);
        if (width) thumbW = parseInt(width[1], 10);
        if (height) thumbH = parseInt(height[1], 10);
      } else {
        const img = anchor.querySelector("img");
        if ((img == null ? void 0 : img.src) && !img.src.endsWith("x.gif")) thumb = img.src;
      }
      let preview = { kind: "none" };
      if (thumb && thumbW !== void 0 && thumbH !== void 0 && (thumbX !== void 0 || thumbY !== void 0)) {
        preview = {
          kind: "sprite",
          src: thumb,
          crop: {
            x: thumbX ?? 0,
            y: thumbY ?? 0,
            width: thumbW,
            height: thumbH
          }
        };
      } else if (thumb) {
        preview = {
          kind: "url",
          src: thumb,
          ...thumbW !== void 0 && thumbH !== void 0 ? { size: { width: thumbW, height: thumbH } } : {}
        };
      }
      return { key: url, viewerUrl: url, preview };
    });
  }
  function parseEHentaiPageMetadata(doc, itemCount) {
    var _a;
    let totalPages = 1;
    for (const cell of Array.from(doc.querySelectorAll(".ptt td"))) {
      const page = parseInt(cell.textContent ?? "", 10);
      if (!Number.isNaN(page) && page > totalPages) totalPages = page;
    }
    const range = ((_a = doc.querySelector(".gpc")) == null ? void 0 : _a.textContent) ?? "";
    const match = range.match(/([\d,]+)\s*-\s*([\d,]+)[^\d]+([\d,]+)/);
    if (!match) return { totalPages };
    const start = parseInt(match[1].replace(/,/g, ""), 10);
    const end = parseInt(match[2].replace(/,/g, ""), 10);
    const total = parseInt(match[3].replace(/,/g, ""), 10);
    const imageOffset = start - 1;
    let perPage;
    if (start === 1) perPage = end;
    else if (end < total) perPage = end - start + 1;
    else if (totalPages > 1) perPage = Math.round(imageOffset / (totalPages - 1));
    else perPage = itemCount;
    return { totalPages, imageOffset, perPage };
  }
  function buildEHentaiViewerUrl(url, nlToken) {
    if (!nlToken) return url;
    return `${url}${url.includes("?") ? "&" : "?"}nl=${nlToken}`;
  }
  function parseEHentaiViewer(doc) {
    var _a;
    const image = doc.querySelector("#img");
    if (!(image == null ? void 0 : image.src)) return null;
    const onerror = image.getAttribute("onerror") || "";
    const token = (_a = onerror.match(/nl\(['"]([^'"]+)['"]\)/)) == null ? void 0 : _a[1];
    return { src: image.src, ...token ? { nl: token } : {} };
  }
  const parser$1 = new DOMParser();
  const PAGE_FETCH_PRIORITY = LOAD_PRIORITY.pageHtml;
  const ehLimiter = new NetLimiter(CFG.maxConcurrent);
  function limitedFetch(url, priority = 0, signal) {
    return ehLimiter.run(() => fetch(url, { signal }), priority);
  }
  const EHentaiAdapter = {
    name: "E-Hentai/ExHentai",
    match(url) {
      return /https?:\/\/(e-|ex)hentai\.org\/(g|s)\//.test(url);
    },
    async loadInitialPage(doc, url) {
      const items = extractEHentaiItems(doc);
      const metadata = parseEHentaiPageMetadata(doc, items.length);
      return {
        pageUrl: url,
        items,
        nextUrl: getEHentaiNextUrl(doc),
        prevUrl: getEHentaiPrevUrl(doc),
        totalPages: metadata.totalPages,
        position: {
          startIndex: metadata.imageOffset ?? 0,
          pageSize: metadata.perPage ?? items.length
        }
      };
    },
    async resolveImage(url, nlToken, priority = 0) {
      const response = await limitedFetch(buildEHentaiViewerUrl(url, nlToken), priority);
      if (response.status === 429 || response.status === 503) {
        ehLimiter.pauseFor(5e3);
        throw new Error(`Rate limited: HTTP ${response.status}`);
      }
      if (!response.ok) throw new Error(`HTTP ${response.status}`);
      const html = await response.text();
      const doc = parser$1.parseFromString(html, "text/html");
      const viewer = parseEHentaiViewer(doc);
      if (!viewer) throw new Error("Image not found");
      return viewer;
    },
    async loadPage(url, signal) {
      const response = await limitedFetch(url, PAGE_FETCH_PRIORITY, signal);
      if (!response.ok) throw new Error("Failed to fetch page");
      const html = await response.text();
      const doc = parser$1.parseFromString(html, "text/html");
      return {
        pageUrl: url,
        items: extractEHentaiItems(doc),
        nextUrl: getEHentaiNextUrl(doc),
        prevUrl: getEHentaiPrevUrl(doc)
      };
    },
    getContainer() {
      return document.querySelector("#gdt") || document.querySelector(".gm");
    },
    hideOriginalElements() {
      const hiddenSelectors = [
        ".c1",
        ".c2",
        ".c3",
        ".c4",
        ".c5",
        ".c6",
        ".c7",
        ".c8",
        ".ptt",
        ".ptb",
        ".gdtl",
        ".gdtm",
        "#gdo",
        "#cdiv",
        "table.itg"
      ];
      document.querySelectorAll(hiddenSelectors.join(",")).forEach((element) => {
        element.style.display = "none";
      });
    },
    cancelPrefetch(_keepUrls) {
      ehLimiter.cancel((priority) => priority <= 10);
    },
    onReaderClose(globalIndex, context) {
      if (context.scrollMode) return;
      const targetPage = Math.floor(globalIndex / context.pageSize);
      const url = new URL(window.location.href);
      const currentPage = parseInt(url.searchParams.get("p") || "0", 10);
      if (targetPage !== currentPage) {
        url.searchParams.set("p", String(targetPage));
        window.location.href = url.toString();
      }
    }
  };
  function extract4KHDImages(doc) {
    const images = Array.from(doc.querySelectorAll(
      "figure.wp-block-image img, #basicExample img, .entry-content p img"
    ));
    return images.map((image) => {
      const img = image;
      let src = img.getAttribute("data-src") || img.getAttribute("data-lazy-src") || img.src;
      let thumb = src;
      thumb = thumb.replace(/i\d\.wp\.com\//, "");
      thumb = thumb.replace("pic.4khd.com", "img.4khd.com");
      thumb = thumb.replace(/\/w\d+-rw\//, "/w300-h300-rw/");
      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 {
        key: src,
        viewerUrl: src,
        preview: { kind: "url", src: thumb }
      };
    }).filter((item) => item.viewerUrl && !item.viewerUrl.includes("avatar"));
  }
  function findPageLink(doc, direction, currentUrl) {
    const pageBox = doc.querySelector(".page-link-box, .pagination, .nav-links, .nav-previous");
    if (!pageBox) return null;
    const current = pageBox.querySelector(".current, .active") || Array.from(pageBox.querySelectorAll("span")).find((span) => !span.querySelector("a"));
    if (current) {
      const currentPageNum = parseInt(current.textContent || "1", 10);
      const targetPage = direction === "next" ? currentPageNum + 1 : currentPageNum - 1;
      if (!Number.isNaN(currentPageNum) && targetPage >= 1) {
        const link = Array.from(pageBox.querySelectorAll("a")).find(
          (anchor) => parseInt(anchor.textContent || "0", 10) === targetPage
        );
        if ((link == null ? void 0 : link.href) && link.href !== currentUrl) return link.href;
      }
    }
    const selector = direction === "next" ? "a.next, a.next.page-numbers" : "a.prev, a.prev.page-numbers";
    const fallback = pageBox.querySelector(selector) || doc.querySelector(selector);
    if ((fallback == null ? void 0 : fallback.href) && fallback.href !== currentUrl) return fallback.href;
    return null;
  }
  function get4KHDNextUrl(doc, currentUrl) {
    return findPageLink(doc, "next", currentUrl);
  }
  function get4KHDPrevUrl(doc, currentUrl) {
    return findPageLink(doc, "prev", currentUrl);
  }
  const parser = new DOMParser();
  const FourKHDAdapter = {
    name: "4KHD",
    match(url) {
      return url.includes("4khd.com") || url.includes("xxtt.ink") || url.includes("uuss.uk") || url.includes("ssuu.uk");
    },
    async loadInitialPage(doc, url) {
      const items = 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;
        }
      }
      const perPage = items.length > 0 ? items.length : 20;
      return {
        pageUrl: url,
        items,
        nextUrl: get4KHDNextUrl(doc, url),
        prevUrl: get4KHDPrevUrl(doc, url),
        totalPages: totalPage,
        position: {
          startIndex: (currentPageNum - 1) * perPage,
          pageSize: perPage
        }
      };
    },
    async resolveImage(url) {
      return { src: url };
    },
    async loadPage(url, signal) {
      const response = await fetch(url, { signal });
      if (!response.ok) throw new Error("Failed to fetch page");
      const html = await response.text();
      const doc = parser.parseFromString(html, "text/html");
      const items = extract4KHDImages(doc);
      return {
        pageUrl: url,
        items,
        nextUrl: get4KHDNextUrl(doc, url),
        prevUrl: get4KHDPrevUrl(doc, url)
      };
    },
    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";
      });
    }
  };
  function isMaterializeData(value) {
    if (!value || typeof value !== "object") return false;
    const data = value;
    return data.kind === "18comic-scramble" && typeof data.aid === "string" && typeof data.imageId === "string";
  }
  function resolve18ComicSource(url) {
    const parsed = new URL(url);
    const aid = parsed.searchParams.get("18aid");
    const scrambleId = parsed.searchParams.get("18scid");
    parsed.searchParams.delete("18aid");
    parsed.searchParams.delete("18scid");
    const src = parsed.toString();
    if (src.includes(".gif") || !aid || !scrambleId || Number(aid) < Number(scrambleId)) {
      return { src };
    }
    const fileName = parsed.pathname.split("/").pop() || "";
    const imageId = fileName.split(".")[0];
    if (!imageId) return { src };
    return {
      src,
      materializeData: { kind: "18comic-scramble", aid, imageId }
    };
  }
  async function materialize18ComicImage(resolved, signal, deps) {
    if (!isMaterializeData(resolved.materializeData)) return resolved;
    const sourceBlob = await deps.fetchBlob(resolved.src, signal);
    if (signal.aborted) throw new DOMException("Materialization cancelled", "AbortError");
    const bitmap = await deps.createBitmap(sourceBlob);
    try {
      const { aid, imageId } = resolved.materializeData;
      const segments = deps.getSegmentCount(aid, imageId);
      if (!segments) throw new Error("18comic segment count is unavailable");
      if (segments <= 1) return { src: resolved.src };
      const canvas = deps.createCanvas(bitmap.width, bitmap.height);
      const context = canvas.getContext("2d");
      if (!context) throw new Error("18comic 2D canvas context is unavailable");
      context.fillStyle = "#ffffff";
      context.fillRect(0, 0, bitmap.width, bitmap.height);
      const remainder = bitmap.height % segments;
      const segmentHeight = Math.floor(bitmap.height / segments);
      let sourceY = bitmap.height - remainder - segmentHeight;
      let destinationY = remainder + segmentHeight;
      context.drawImage(
        bitmap,
        0,
        sourceY,
        bitmap.width,
        remainder + segmentHeight,
        0,
        0,
        bitmap.width,
        remainder + segmentHeight
      );
      for (let index = 1; index < segments; index++) {
        sourceY -= segmentHeight;
        context.drawImage(
          bitmap,
          0,
          sourceY,
          bitmap.width,
          segmentHeight,
          0,
          destinationY,
          bitmap.width,
          segmentHeight
        );
        destinationY += segmentHeight;
      }
      if (signal.aborted) throw new DOMException("Materialization cancelled", "AbortError");
      const output = await canvas.convertToBlob({ type: "image/jpeg", quality: 0.85 });
      return { src: deps.createObjectUrl(output), ownsObjectUrl: true };
    } finally {
      bitmap.close();
    }
  }
  function create18ComicBrowserMaterializer(getSegmentCount) {
    const deps = {
      async fetchBlob(src, signal) {
        const response = await fetch(src, { signal });
        if (!response.ok) throw new Error(`Failed to fetch image: HTTP ${response.status}`);
        return response.blob();
      },
      createBitmap: (blob) => createImageBitmap(blob),
      createCanvas: (width, height) => new OffscreenCanvas(width, height),
      createObjectUrl: (blob) => URL.createObjectURL(blob),
      getSegmentCount
    };
    return (resolved, signal) => materialize18ComicImage(resolved, signal, deps);
  }
  function extractChapterItems(doc, pageUrl, useUnsafeFallback, suppressNativeDecode) {
    const html = doc.documentElement.innerHTML;
    const aidMatch = html.match(/aid\s*=\s*['"]?(\d+)['"]?/);
    const scrambleMatch = html.match(/scramble_id\s*=\s*['"]?(\d+)['"]?/);
    const aid = (aidMatch == null ? void 0 : aidMatch[1]) || (useUnsafeFallback && unsafeWindow.aid ? String(unsafeWindow.aid) : "");
    const scrambleId = (scrambleMatch == null ? void 0 : scrambleMatch[1]) || (useUnsafeFallback && unsafeWindow.scramble_id ? String(unsafeWindow.scramble_id) : "");
    const items = [];
    const seenUrls = new Set();
    const images = doc.querySelectorAll(".scramble-page img[id], .owl-item .center img[id]");
    images.forEach((element) => {
      const image = element;
      const source = image.getAttribute("data-original") || image.getAttribute("data-src") || image.src;
      if (!source) return;
      const url = new URL(source, pageUrl);
      if (aid) url.searchParams.set("18aid", aid);
      if (scrambleId) url.searchParams.set("18scid", scrambleId);
      const viewerUrl = url.toString();
      if (!seenUrls.has(viewerUrl)) {
        seenUrls.add(viewerUrl);
        items.push({ key: viewerUrl, viewerUrl, preview: { kind: "none" } });
      }
      if (suppressNativeDecode) {
        try {
          image.getBoundingClientRect = () => ({
            top: 999999,
            left: 0,
            right: 0,
            bottom: 999999,
            width: 0,
            height: 0,
            x: 0,
            y: 0,
            toJSON: () => {
            }
          });
        } catch {
        }
      }
    });
    return items;
  }
  function getNextUrl(doc) {
    var _a;
    const active = doc.querySelector(".pagination li.active");
    const pageLink = (_a = active == null ? void 0 : active.nextElementSibling) == null ? void 0 : _a.querySelector("a:not(.prevnext)");
    if (pageLink) return pageLink.href;
    const nextChapter = Array.from(doc.querySelectorAll('.menu-bolock-ul a[href^="/photo/"]')).find((anchor) => {
      var _a2;
      return (_a2 = anchor.textContent) == null ? void 0 : _a2.includes("涓嬩竴");
    });
    return nextChapter ? nextChapter.href : null;
  }
  function getPrevUrl(doc) {
    var _a;
    const active = doc.querySelector(".pagination li.active");
    const pageLink = (_a = active == null ? void 0 : active.previousElementSibling) == null ? void 0 : _a.querySelector("a:not(.prevnext)");
    if (pageLink) return pageLink.href;
    const prevChapter = Array.from(doc.querySelectorAll('.menu-bolock-ul a[href^="/photo/"]')).find((anchor) => {
      var _a2;
      return (_a2 = anchor.textContent) == null ? void 0 : _a2.includes("涓婁竴");
    });
    return prevChapter ? prevChapter.href : null;
  }
  const materialize = create18ComicBrowserMaterializer((aid, imageId) => {
    if (!unsafeWindow.get_num) return void 0;
    return unsafeWindow.get_num(btoa(aid), btoa(imageId));
  });
  const Comic18Adapter = {
    name: "18comic",
    match(url) {
      return url.includes("18comic.vip") || url.includes("18comic.ink");
    },
    async loadInitialPage(doc, pageUrl) {
      return {
        pageUrl,
        items: extractChapterItems(doc, pageUrl, true, true),
        nextUrl: getNextUrl(doc),
        prevUrl: getPrevUrl(doc)
      };
    },
    async loadPage(url, signal) {
      const response = await fetch(url, { signal });
      if (!response.ok) throw new Error(`Failed to fetch page: HTTP ${response.status}`);
      const html = await response.text();
      const doc = new DOMParser().parseFromString(html, "text/html");
      return {
        pageUrl: url,
        items: extractChapterItems(doc, url, false, false),
        nextUrl: getNextUrl(doc),
        prevUrl: getPrevUrl(doc)
      };
    },
    async resolveImage(url) {
      try {
        return resolve18ComicSource(url);
      } catch {
        return { src: url };
      }
    },
    async materializeImage(resolved, signal) {
      return materialize(resolved, signal);
    },
    getContainer() {
      return document.querySelector(".scramble-page") || document.body;
    },
    hideOriginalElements() {
      const pages = Array.from(document.querySelectorAll(".scramble-page"));
      for (let index = 1; index < pages.length; index++) pages[index].remove();
      document.querySelectorAll(".owl-carousel").forEach((element) => element.remove());
    }
  };
  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;
    }
  };
  class EmptyGalleryPageError extends Error {
    constructor(url) {
      super(`Gallery page has no items: ${url}`);
      this.name = "EmptyGalleryPageError";
    }
  }
  class GalleryPageLoader {
    constructor(adapter) {
      this.inFlight = new Map();
      this.loadedUrls = new Set();
      this.adapter = adapter;
    }
    async loadInitialPage(doc, url) {
      const page = this.normalize(url, await this.adapter.loadInitialPage(doc, url));
      this.markLoaded(url, page.pageUrl);
      return page;
    }
    loadPage(url, signal) {
      if (this.loadedUrls.has(url)) return Promise.resolve(null);
      const existing = this.inFlight.get(url);
      if (existing) return existing;
      const request = this.adapter.loadPage(url, signal).then((page) => {
        if (page.items.length === 0) throw new EmptyGalleryPageError(url);
        const normalized = this.normalize(url, page);
        this.markLoaded(url, normalized.pageUrl);
        return normalized;
      }).finally(() => {
        this.inFlight.delete(url);
      });
      this.inFlight.set(url, request);
      return request;
    }
    hasLoaded(url) {
      return this.loadedUrls.has(url);
    }
    markLoaded(...urls) {
      for (const url of urls) {
        if (url) this.loadedUrls.add(url);
      }
    }
    normalize(requestedUrl, page) {
      const isLoop = (url) => !!url && (url === requestedUrl || url === page.pageUrl || this.loadedUrls.has(url));
      return {
        ...page,
        nextUrl: isLoop(page.nextUrl) ? null : page.nextUrl,
        prevUrl: isLoop(page.prevUrl) ? null : page.prevUrl
      };
    }
  }
  const defaultPolicy = {
    resolveAttempts: 4,
    nodeRetries: 3,
    plainRetries: 2,
    retryDelay: 1e3,
    cacheEntries: 80
  };
  class ImageLoadService {
    constructor(deps, policy = {}) {
      this.active = new Map();
      this.cache = new Map();
      this.phases = new Map();
      this.listeners = new Map();
      this.deps = deps;
      this.policy = { ...defaultPolicy, ...policy };
    }
    acquire(url, options) {
      var _a, _b;
      const token = Symbol(options.intent);
      const cached = this.cache.get(url);
      if (cached) {
        this.touchCache(url, cached);
        cached.leases.add(token);
        this.setPhase(url, "ready");
        return this.createLease(url, token, Promise.resolve(cached.asset));
      }
      let load = this.active.get(url);
      if (load) {
        load.leases.add(token);
        if (options.priority > load.priority) {
          load.priority = options.priority;
          (_b = (_a = this.deps).promote) == null ? void 0 : _b.call(_a, url, options.priority);
        }
        return this.createLease(url, token, load.result);
      }
      const controller = new AbortController();
      load = {
        controller,
        leases: new Set([token]),
        priority: options.priority,
        result: Promise.resolve(null)
      };
      load.result = this.run(url, load).finally(() => {
        if (this.active.get(url) === load) this.active.delete(url);
      });
      this.active.set(url, load);
      return this.createLease(url, token, load.result);
    }
    getPhase(url) {
      return this.phases.get(url) ?? "idle";
    }
    getCached(url) {
      var _a;
      return (_a = this.cache.get(url)) == null ? void 0 : _a.asset;
    }
    getLatestCached() {
      let latest;
      for (const entry of this.cache.values()) latest = entry.asset;
      return latest;
    }
getStats() {
      let activeLeases = 0;
      let cachedLeases = 0;
      let leasedCacheEntries = 0;
      let ownedObjectUrls = 0;
      let listeners = 0;
      for (const load of this.active.values()) activeLeases += load.leases.size;
      for (const entry of this.cache.values()) {
        cachedLeases += entry.leases.size;
        if (entry.leases.size > 0) leasedCacheEntries++;
        if (entry.asset.ownsObjectUrl) ownedObjectUrls++;
      }
      for (const subscribers of this.listeners.values()) listeners += subscribers.size;
      return {
        activeLoads: this.active.size,
        cachedEntries: this.cache.size,
        activeLeases,
        cachedLeases,
        leasedCacheEntries,
        ownedObjectUrls,
        phases: this.phases.size,
        listeners
      };
    }
    async run(url, load) {
      var _a, _b, _c, _d;
      const signal = load.controller.signal;
      let resolved = null;
      for (let attempt = 0; attempt < this.policy.resolveAttempts && !signal.aborted; attempt++) {
        this.setPhase(url, "resolving");
        const candidate = await this.resolve(url, void 0, attempt > 0, load.priority);
        resolved = await this.materialize(url, candidate, load);
        if (resolved == null ? void 0 : resolved.src) break;
        if (attempt + 1 < this.policy.resolveAttempts) await this.wait(signal);
      }
      if (!(resolved == null ? void 0 : resolved.src) || signal.aborted) {
        this.discard(url, resolved);
        return this.finishWithoutAsset(url, signal);
      }
      let loaded = await this.tryLoad(url, resolved, load);
      let currentNl = resolved.nl;
      for (let attempt = 0; !loaded && currentNl && attempt < this.policy.nodeRetries && !signal.aborted; attempt++) {
        const candidate = await this.resolve(url, currentNl, true, load.priority);
        const next = await this.materialize(url, candidate, load);
        if (!(next == null ? void 0 : next.src)) break;
        this.discard(url, resolved);
        currentNl = next.nl;
        resolved = next;
        loaded = await this.tryLoad(url, next, load);
      }
      for (let attempt = 0; !loaded && attempt < this.policy.plainRetries && !signal.aborted; attempt++) {
        await this.wait(signal);
        if (signal.aborted) break;
        const candidate = await this.resolve(url, void 0, true, load.priority);
        const next = await this.materialize(url, candidate, load);
        if (!(next == null ? void 0 : next.src)) continue;
        this.discard(url, resolved);
        resolved = next;
        loaded = await this.tryLoad(url, next, load);
      }
      if (!loaded || signal.aborted) {
        this.discard(url, resolved);
        return this.finishWithoutAsset(url, signal);
      }
      const asset = {
        ...resolved,
        width: loaded.width,
        height: loaded.height
      };
      this.cache.set(url, { asset, leases: load.leases });
      (_b = (_a = this.deps).setResolvedSource) == null ? void 0 : _b.call(_a, url, asset.src);
      try {
        (_d = (_c = this.deps).onReady) == null ? void 0 : _d.call(_c, url, asset);
      } catch {
      }
      this.touchCache(url, this.cache.get(url));
      this.setPhase(url, "ready");
      this.trimCache();
      return asset;
    }
    async tryLoad(url, resolved, load) {
      if (load.controller.signal.aborted) return null;
      this.setPhase(url, "downloading");
      try {
        return await this.deps.loadBytes(resolved.src, load.controller.signal);
      } catch {
        return null;
      }
    }
    async resolve(url, nlToken, force, priority) {
      try {
        return await this.deps.resolve(url, nlToken, force, priority);
      } catch {
        return null;
      }
    }
    async materialize(url, resolved, load) {
      if (!(resolved == null ? void 0 : resolved.src) || load.controller.signal.aborted) return resolved;
      if (!this.deps.materialize) return resolved;
      try {
        const materialized = await this.deps.materialize(
          url,
          resolved,
          load.controller.signal,
          load.priority
        );
        if (!materialized) this.discard(url, resolved);
        return materialized;
      } catch {
        this.discard(url, resolved);
        return null;
      }
    }
    discard(url, resolved) {
      var _a, _b, _c, _d;
      if (!(resolved == null ? void 0 : resolved.ownsObjectUrl)) return;
      (_b = (_a = this.deps).invalidateResolved) == null ? void 0 : _b.call(_a, url, resolved.src);
      (_d = (_c = this.deps).revokeObjectUrl) == null ? void 0 : _d.call(_c, resolved.src);
    }
    finishWithoutAsset(url, signal) {
      this.setPhase(url, signal.aborted ? "cancelled" : "error");
      return null;
    }
    async wait(signal) {
      if (signal.aborted) return;
      const delay = this.deps.delay ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
      await new Promise((resolve) => {
        const finish = () => {
          signal.removeEventListener("abort", finish);
          resolve();
        };
        signal.addEventListener("abort", finish, { once: true });
        delay(this.policy.retryDelay).then(finish, finish);
      });
    }
    createLease(url, token, result) {
      let released = false;
      const ownedListeners = new Set();
      const service = this;
      return {
        url,
        result,
        get phase() {
          return service.getPhase(url);
        },
        subscribe(listener) {
          let listeners = service.listeners.get(url);
          if (!listeners) {
            listeners = new Set();
            service.listeners.set(url, listeners);
          }
          listeners.add(listener);
          ownedListeners.add(listener);
          listener(service.getPhase(url));
          return () => {
            listeners.delete(listener);
            ownedListeners.delete(listener);
            if (listeners.size === 0) service.listeners.delete(url);
          };
        },
        release() {
          var _a, _b;
          if (released) return;
          released = true;
          for (const listener of ownedListeners) (_a = service.listeners.get(url)) == null ? void 0 : _a.delete(listener);
          ownedListeners.clear();
          if (((_b = service.listeners.get(url)) == null ? void 0 : _b.size) === 0) service.listeners.delete(url);
          service.release(url, token);
        }
      };
    }
    release(url, token) {
      const active = this.active.get(url);
      if ((active == null ? void 0 : active.leases.delete(token)) && active.leases.size === 0) {
        active.controller.abort();
        this.active.delete(url);
        this.setPhase(url, "cancelled");
        return;
      }
      const cached = this.cache.get(url);
      if (cached == null ? void 0 : cached.leases.delete(token)) this.trimCache();
    }
    setPhase(url, phase) {
      var _a;
      if (this.phases.get(url) === phase) return;
      this.phases.set(url, phase);
      (_a = this.listeners.get(url)) == null ? void 0 : _a.forEach((listener) => listener(phase));
    }
    touchCache(url, entry) {
      this.cache.delete(url);
      this.cache.set(url, entry);
    }
    trimCache() {
      var _a, _b, _c, _d, _e, _f;
      if (this.cache.size <= this.policy.cacheEntries) return;
      for (const [url, entry] of this.cache) {
        if (this.cache.size <= this.policy.cacheEntries) break;
        if (entry.leases.size > 0) continue;
        this.cache.delete(url);
        (_b = (_a = this.deps).invalidateResolved) == null ? void 0 : _b.call(_a, url, entry.asset.src);
        (_d = (_c = this.deps).onEvict) == null ? void 0 : _d.call(_c, url, entry.asset);
        if (entry.asset.ownsObjectUrl) {
          (_f = (_e = this.deps).revokeObjectUrl) == null ? void 0 : _f.call(_e, entry.asset.src);
        }
        if (!this.active.has(url)) this.phases.delete(url);
      }
    }
  }
  class MaterializeScheduler {
    constructor(maxConcurrent) {
      this.queue = [];
      this.active = 0;
      this.sequence = 0;
      this.maxConcurrent = maxConcurrent;
    }
    run(key, task, priority, signal) {
      if (signal.aborted) return Promise.reject(new DOMException("Materialization cancelled", "AbortError"));
      return new Promise((resolve, reject) => {
        const job = {
          key,
          priority,
          sequence: this.sequence++,
          signal,
          task,
          resolve,
          reject,
          onAbort: () => {
          }
        };
        job.onAbort = () => {
          const index = this.queue.indexOf(job);
          if (index === -1) return;
          this.queue.splice(index, 1);
          reject(new DOMException("Materialization cancelled", "AbortError"));
        };
        signal.addEventListener("abort", job.onAbort, { once: true });
        this.queue.push(job);
        this.pump();
      });
    }
    promote(key, priority) {
      for (const job of this.queue) {
        if (job.key === key && priority > job.priority) job.priority = priority;
      }
    }
    pump() {
      while (this.active < this.maxConcurrent && this.queue.length > 0) {
        let bestIndex = 0;
        for (let index = 1; index < this.queue.length; index++) {
          const candidate = this.queue[index];
          const best = this.queue[bestIndex];
          if (candidate.priority > best.priority || candidate.priority === best.priority && candidate.sequence < best.sequence) {
            bestIndex = index;
          }
        }
        const job = this.queue.splice(bestIndex, 1)[0];
        job.signal.removeEventListener("abort", job.onAbort);
        if (job.signal.aborted) {
          job.reject(new DOMException("Materialization cancelled", "AbortError"));
          continue;
        }
        this.active++;
        Promise.resolve().then(job.task).then(job.resolve, job.reject).finally(() => {
          this.active--;
          this.pump();
        });
      }
    }
  }
  const materializeScheduler = new MaterializeScheduler(CFG.maxConcurrent);
  function loadImageBytes(src, signal) {
    return new Promise((resolve, reject) => {
      const img = new Image();
      img.decoding = "async";
      const cleanup = () => {
        signal.removeEventListener("abort", onAbort);
        img.onload = null;
        img.onerror = null;
      };
      const onAbort = () => {
        cleanup();
        img.src = "data:,";
        reject(new DOMException("Image load cancelled", "AbortError"));
      };
      img.onload = () => {
        const dimensions = { width: img.naturalWidth, height: img.naturalHeight };
        cleanup();
        resolve(dimensions);
      };
      img.onerror = () => {
        cleanup();
        reject(new Error(`Image byte load failed: ${src}`));
      };
      signal.addEventListener("abort", onAbort, { once: true });
      if (signal.aborted) onAbort();
      else img.src = src;
    });
  }
  const imageLoadService = new ImageLoadService({
    resolve: async (url, nlToken, _force, priority) => {
      var _a;
      return ((_a = store.activeAdapter) == null ? void 0 : _a.resolveImage(url, nlToken, priority)) ?? null;
    },
    materialize: (url, resolved, signal, priority) => {
      var _a;
      const materialize2 = (_a = store.activeAdapter) == null ? void 0 : _a.materializeImage;
      if (!materialize2) return Promise.resolve(resolved);
      return materializeScheduler.run(
        url,
        () => materialize2(resolved, signal),
        priority,
        signal
      );
    },
    loadBytes: loadImageBytes,
    promote: (url, priority) => {
      materializeScheduler.promote(url, priority);
    },
    revokeObjectUrl: (src) => URL.revokeObjectURL(src)
  });
  function acquireImage(url, options) {
    return imageLoadService.acquire(url, options);
  }
  function getCachedImage(url) {
    return imageLoadService.getCached(url);
  }
  function getLatestCachedImage() {
    return imageLoadService.getLatestCached();
  }
  function cancelImagePrefetch(keepUrls) {
    var _a, _b;
    (_b = (_a = store.activeAdapter) == null ? void 0 : _a.cancelPrefetch) == null ? void 0 : _b.call(_a, keepUrls);
  }
  const imageLoadedListeners = new Set();
  function notifyScrollImageLoaded(event) {
    imageLoadedListeners.forEach((listener) => listener(event));
  }
  function subscribeScrollImageLoaded(listener) {
    imageLoadedListeners.add(listener);
    return () => imageLoadedListeners.delete(listener);
  }
  function validGeometry(geometry) {
    return Number.isFinite(geometry.width) && Number.isFinite(geometry.height) && geometry.width > 0 && geometry.height > 0;
  }
  function findScrollItem(itemKey, fallbackIndex, preferred) {
    if ((preferred == null ? void 0 : preferred.isConnected) && (preferred.dataset.itemKey === itemKey || preferred.dataset.viewerUrl === itemKey || preferred.dataset.url === itemKey)) {
      return preferred;
    }
    const items = Array.from(document.querySelectorAll(".r-img, .r-ph"));
    return items.find(
      (element) => element.dataset.itemKey === itemKey || element.dataset.viewerUrl === itemKey || element.dataset.url === itemKey
    ) ?? items[fallbackIndex] ?? null;
  }
  function applyKnownImageGeometry(element, geometry) {
    if (!validGeometry(geometry)) return false;
    const width = Math.round(geometry.width);
    const height = Math.round(geometry.height);
    element.style.aspectRatio = `${width} / ${height}`;
    element.style.width = "100%";
    element.style.maxWidth = `${width}px`;
    element.style.height = "auto";
    if (element.classList.contains("r-ph")) {
      element.style.minHeight = "0";
      element.style.marginBottom = "20px";
    }
    return true;
  }
  function withInstantDocumentScroll(action) {
    const rootBehavior = document.documentElement.style.scrollBehavior;
    const bodyBehavior = document.body.style.scrollBehavior;
    const alreadyForced = document.documentElement.classList.contains("hr-instant-scroll");
    document.documentElement.classList.add("hr-instant-scroll");
    document.documentElement.style.scrollBehavior = "auto";
    document.body.style.scrollBehavior = "auto";
    try {
      action();
    } finally {
      document.documentElement.style.scrollBehavior = rootBehavior;
      document.body.style.scrollBehavior = bodyBehavior;
      if (!alreadyForced) document.documentElement.classList.remove("hr-instant-scroll");
    }
  }
  function restoreDocumentScroll(top) {
    if (!Number.isFinite(top) || Math.abs(window.scrollY - top) < 2) return;
    withInstantDocumentScroll(() => window.scrollTo({ top, behavior: "auto" }));
  }
  function isScrollItemCentered(target, tolerance = 2) {
    const rect = target.getBoundingClientRect();
    const centeredTop = (window.innerHeight - rect.height) / 2;
    return Math.abs(rect.top - centeredTop) < tolerance;
  }
  function jumpToScrollItem(target) {
    if (!target.isConnected) return;
    const rect = target.getBoundingClientRect();
    const top = window.scrollY + rect.top - (window.innerHeight - rect.height) / 2;
    withInstantDocumentScroll(() => window.scrollTo({
      top: Math.max(0, top),
      behavior: "auto"
    }));
  }
  function restoreReaderScroll(request) {
    for (const geometry of request.nearbyGeometry ?? []) {
      const element = findScrollItem(geometry.key, geometry.index, geometry.preferred);
      if (element) applyKnownImageGeometry(element, geometry);
    }
    if (!request.target) {
      restoreDocumentScroll(request.entryScrollY);
      return;
    }
    const target = findScrollItem(
      request.target.key,
      request.target.index,
      request.target.preferred
    );
    if (target && !isScrollItemCentered(target)) jumpToScrollItem(target);
  }
  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 lazyLoadObserver = null;
  const placeholderLeases = new WeakMap();
  const imageElementLeases = new WeakMap();
  function loadPlaceholderImage(placeholder) {
    const url = placeholder.dataset.url;
    const adapter = store.activeAdapter;
    if (!url || !adapter) return;
    if (placeholder.dataset.isFetching === "true") {
      return;
    }
    placeholder.dataset.isFetching = "true";
    placeholder.dataset.lazyLoaded = "true";
    const pIndex = parseInt(placeholder.dataset.pIndex || "0", 10);
    const index = parseInt(placeholder.dataset.index || "0", 10);
    const lease = acquireImage(url, { intent: "scroll", priority: LOAD_PRIORITY.scroll });
    placeholderLeases.set(placeholder, lease);
    lease.result.then((asset) => {
      var _a;
      if (placeholderLeases.get(placeholder) !== lease) return;
      if (!asset) {
        setErrorState(placeholder, pIndex, index);
        return;
      }
      const img = document.createElement("img");
      img.className = "r-img";
      img.decoding = "async";
      img.dataset.viewerUrl = url;
      if (placeholder.dataset.itemKey) img.dataset.itemKey = placeholder.dataset.itemKey;
      img.dataset.realSrc = asset.src;
      if (placeholder.dataset.thumb) img.dataset.thumbSrc = placeholder.dataset.thumb;
      if (placeholder.dataset.thumbW) img.dataset.thumbW = placeholder.dataset.thumbW;
      if (placeholder.dataset.thumbH) img.dataset.thumbH = placeholder.dataset.thumbH;
      if (placeholder.dataset.thumbX !== void 0) img.dataset.thumbX = placeholder.dataset.thumbX;
      if (placeholder.dataset.thumbY !== void 0) img.dataset.thumbY = placeholder.dataset.thumbY;
      applyKnownImageGeometry(img, asset);
      img.onload = () => {
        if (img.dataset.locked || img.naturalWidth <= 0) return;
        applyKnownImageGeometry(img, {
          width: img.naturalWidth,
          height: img.naturalHeight
        });
        img.dataset.locked = "true";
      };
      img.onerror = () => {
        var _a2;
        (_a2 = imageElementLeases.get(img)) == null ? void 0 : _a2.release();
        imageElementLeases.delete(img);
        if (img.parentNode) img.parentNode.replaceChild(placeholder, img);
        setErrorState(placeholder, pIndex, index);
      };
      img.src = asset.src;
      (_a = placeholder.parentNode) == null ? void 0 : _a.replaceChild(img, placeholder);
      if (asset.ownsObjectUrl) {
        placeholderLeases.delete(placeholder);
        imageElementLeases.set(img, lease);
      }
      const itemKey = placeholder.dataset.itemKey;
      const itemIndex = itemKey ? store.galleryItems.findIndex((item) => item.key === itemKey) : store.galleryItems.findIndex((item) => item.viewerUrl === url);
      if (itemIndex !== -1) {
        notifyScrollImageLoaded({ index: itemIndex, element: img, viewerUrl: url });
      }
    }).catch(() => {
      setErrorState(placeholder, pIndex, index);
    }).finally(() => {
      if (placeholderLeases.get(placeholder) === lease) {
        placeholderLeases.delete(placeholder);
        lease.release();
      }
    });
  }
  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: "2000px 0px 2000px 0px" });
  }
  function pauseLazyLoad() {
    lazyLoadObserver == null ? void 0 : lazyLoadObserver.disconnect();
  }
  function resumeLazyLoad() {
    if (!lazyLoadObserver) return;
    document.querySelectorAll(".r-ph").forEach((ph) => {
      if (!ph.dataset.lazyLoaded) lazyLoadObserver.observe(ph);
    });
  }
  function processBatch(items, pIndex, container, prepend = false, pageUrl) {
    var _a;
    const batchDiv = document.createElement("div");
    batchDiv.className = "hr-page-batch";
    if (pageUrl) {
      batchDiv.dataset.pageUrl = pageUrl;
    }
    const fragment = document.createDocumentFragment();
    initLazyLoad();
    let targetContainer = container;
    if (!targetContainer) {
      targetContainer = document.querySelector("#gdt-hidden") || ((_a = store.activeAdapter) == null ? void 0 : _a.getContainer()) || document.querySelector(".scroll-mode .entry-content, .scroll-mode .wp-block-post-content, .scroll-mode .post-content") || document.body;
    }
    items.forEach((item, index) => {
      const url = item.viewerUrl;
      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);
      placeholder.dataset.itemKey = item.key;
      if (item.dimensions) {
        applyKnownImageGeometry(placeholder, item.dimensions);
      }
      if (item.preview.kind === "url") {
        placeholder.dataset.thumb = item.preview.src;
        if (item.preview.size) {
          placeholder.dataset.thumbW = String(item.preview.size.width);
          placeholder.dataset.thumbH = String(item.preview.size.height);
        }
      } else if (item.preview.kind === "sprite") {
        placeholder.dataset.thumb = item.preview.src;
        placeholder.dataset.thumbW = String(item.preview.crop.width);
        placeholder.dataset.thumbH = String(item.preview.crop.height);
        placeholder.dataset.thumbX = String(item.preview.crop.x);
        placeholder.dataset.thumbY = String(item.preview.crop.y);
      }
      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;">
          <svg class="hr-spinner" style="color: #F596AA; width: 20px; height: 20px;" 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);
      }
    });
    batchDiv.appendChild(fragment);
    if (prepend && targetContainer.firstChild) {
      store.galleryItems = [...items, ...store.galleryItems];
      targetContainer.insertBefore(batchDiv, targetContainer.firstChild);
    } else {
      store.galleryItems.push(...items);
      targetContainer.appendChild(batchDiv);
    }
  }
  function setupAutoScroll(pageLoader) {
    const scrollSent = document.createElement("div");
    document.body.appendChild(scrollSent);
    const pageObs = new IntersectionObserver((entries) => {
      if (entries[0].isIntersecting && store.nextUrl && !store.isFetching) {
        const requestedUrl = store.nextUrl;
        store.isFetching = true;
        pageLoader.loadPage(requestedUrl).then((page) => {
          var _a;
          if (!page) {
            store.nextUrl = null;
            pageObs.disconnect();
            return;
          }
          store.currPage++;
          processBatch(page.items, store.currPage, ((_a = store.activeAdapter) == null ? void 0 : _a.getContainer()) || document.querySelector(".scroll-mode .entry-content, .scroll-mode .wp-block-post-content, .scroll-mode .post-content") || document.body, false, page.pageUrl);
          store.nextUrl = page.nextUrl;
          if (!store.nextUrl) pageObs.disconnect();
        }).catch((err) => {
          if (err instanceof EmptyGalleryPageError) {
            store.nextUrl = null;
            pageObs.disconnect();
          }
        }).finally(() => {
          store.isFetching = false;
        });
      }
    }, { rootMargin: CFG.nextPage });
    pageObs.observe(scrollSent);
  }
  const readerCss = '.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;pointer-events:auto}.sp-close-btn{transform:scale(var(--hr-scale, 1));transform-origin:top right}.sp-close-btn:hover{background:#555555e6;transform:scale(calc(1.1 * var(--hr-scale, 1)))}.sp-hidden-by-pswp{opacity:0!important;pointer-events:none!important}.sp-sidebar-track{position:absolute;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-track.position-bottom{bottom:12px;left:10%;width:80%;height:12px}.sp-sidebar-track.position-top{top:12px;left:10%;width:80%;height:12px}.sp-sidebar-track.position-left{left:12px;top:10%;height:80%;width:12px}.sp-sidebar-track.position-right{right:12px;top:10%;height:80%;width:12px}.sp-sidebar-thumb{position:absolute;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-track.position-bottom .sp-sidebar-thumb,.sp-sidebar-track.position-top .sp-sidebar-thumb{top:0;height:100%;min-width:60px}.sp-sidebar-track.position-left .sp-sidebar-thumb,.sp-sidebar-track.position-right .sp-sidebar-thumb{left:0;width:100%;min-height:60px}.sp-sidebar-label{position:absolute;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.position-bottom .sp-sidebar-label{bottom:calc(100% + 16px);left:50%;transform:translate(-50%)}.sp-sidebar-track.position-top .sp-sidebar-label{top:calc(100% + 16px);left:50%;transform:translate(-50%)}.sp-sidebar-track.position-left .sp-sidebar-label{left:calc(100% + 16px);top:50%;transform:translateY(-50%)}.sp-sidebar-track.position-right .sp-sidebar-label{right:calc(100% + 16px);top:50%;transform:translateY(-50%)}.sp-sidebar-track:hover .sp-sidebar-label{opacity:1}.sp-thumb-panel{position:absolute;background:#141414f2;border-radius:8px;border:1px solid rgba(255,255,255,.1);box-shadow:0 -4px 16px #00000080;pointer-events:none;display:flex;z-index:11;opacity:0;transition:opacity .3s,transform .3s cubic-bezier(.2,.8,.2,1);-webkit-user-select:none;user-select:none}.sp-thumb-panel.position-top{top:32px;left:50%;transform:translate(-50%) translateY(-20px);flex-direction:row;max-width:calc(80% / var(--hr-scale, 1));width:fit-content;height:116px}.sp-thumb-panel.position-top{transform-origin:top center;transform:translate(-50%) translateY(-20px) scale(var(--hr-scale, 1))}.sp-thumb-panel.position-top.active{opacity:1;transform:translate(-50%) translateY(0) scale(var(--hr-scale, 1));pointer-events:auto}.sp-thumb-panel.position-bottom{bottom:32px;left:50%;transform-origin:bottom center;transform:translate(-50%) translateY(20px) scale(var(--hr-scale, 1));flex-direction:row;max-width:calc(80% / var(--hr-scale, 1));width:fit-content;height:116px}.sp-thumb-panel.position-bottom.active{opacity:1;transform:translate(-50%) translateY(0) scale(var(--hr-scale, 1));pointer-events:auto}.sp-thumb-panel.position-left{left:32px;top:50%;transform-origin:left center;transform:translateY(-50%) translate(-20px) scale(var(--hr-scale, 1));flex-direction:column;max-height:calc(80% / var(--hr-scale, 1));height:fit-content;width:116px}.sp-thumb-panel.position-left.active{opacity:1;transform:translateY(-50%) translate(0) scale(var(--hr-scale, 1));pointer-events:auto}.sp-thumb-panel.position-right{right:32px;top:50%;transform-origin:right center;transform:translateY(-50%) translate(20px) scale(var(--hr-scale, 1));flex-direction:column;max-height:calc(80% / var(--hr-scale, 1));height:fit-content;width:116px}.sp-thumb-panel.position-right.active{opacity:1;transform:translateY(-50%) translate(0) scale(var(--hr-scale, 1));pointer-events:auto}.sp-thumb-viewport{flex:1;min-width:0;min-height:0;position:relative;border-radius:inherit;overflow:auto;overscroll-behavior:none;-webkit-overflow-scrolling:touch;scrollbar-width:none}.sp-thumb-viewport::-webkit-scrollbar{display:none}.sp-thumb-content{position:relative;width:100%;height:100%}.sp-thumb-item{position:absolute;border-radius:4px;overflow:hidden;cursor:pointer;border:2px solid transparent;transition:border-color .15s;box-sizing:border-box}.sp-thumb-panel.position-bottom .sp-thumb-item,.sp-thumb-panel.position-top .sp-thumb-item{top:8px;left:0;width:72px;height:calc(100% - 16px)}.sp-thumb-panel.position-left .sp-thumb-item,.sp-thumb-panel.position-right .sp-thumb-item{left:8px;top:0;width:calc(100% - 16px);height:72px}.sp-thumb-item:hover{border-color:#fff6}.sp-thumb-item.sp-thumb-active{border-color:var(--hr-accent)}.sp-thumb-img{width:100%;height:100%;object-fit:cover;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-ph.loading{color:#aaa;gap:6px}.sp-thumb-ph.loading:after{content:"";width:10px;height:10px;border:2px solid rgba(255,255,255,.2);border-top-color:var(--hr-accent);border-radius:50%;animation:hr-spin 1s linear infinite}.sp-thumb-ph.error{color:#ef8080}.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-counter{position:absolute;display:flex;align-items:center;justify-content:center;background:#1e1e1ebf;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);color:#fff;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;font-size:12px;font-weight:500;letter-spacing:.5px;padding:4px 10px;border-radius:12px;border:1px solid rgba(255,255,255,.15);box-shadow:0 4px 12px #0000004d;pointer-events:none;z-index:20;white-space:nowrap}.sp-thumb-panel.position-bottom .sp-thumb-counter{top:-36px;left:50%;transform:translate(-50%)}.sp-thumb-panel.position-top .sp-thumb-counter{bottom:-36px;left:50%;transform:translate(-50%)}.sp-thumb-panel.position-left .sp-thumb-counter,.sp-thumb-panel.position-right .sp-thumb-counter{bottom:-44px;left:50%;transform:translate(-50%);font-size:14px;padding:6px 16px;border-radius:16px}:root.hr-mobile .sp-thumb-panel.position-bottom{bottom:16px;max-width:calc(90% / var(--hr-scale, 1));height:130px}:root.hr-mobile .sp-thumb-panel.position-top{top:16px;max-width:calc(90% / var(--hr-scale, 1));height:130px}:root.hr-mobile .sp-thumb-panel.position-left{left:16px;max-height:calc(90% / var(--hr-scale, 1));width:130px}:root.hr-mobile .sp-thumb-panel.position-right{right:16px;max-height:calc(90% / var(--hr-scale, 1));width:130px}:root.hr-mobile .sp-thumb-panel.position-bottom .sp-thumb-item,:root.hr-mobile .sp-thumb-panel.position-top .sp-thumb-item{width:86px;height:calc(100% - 10px);top:5px}:root.hr-mobile .sp-thumb-panel.position-left .sp-thumb-item,:root.hr-mobile .sp-thumb-panel.position-right .sp-thumb-item{width:calc(100% - 10px);height:86px;left:5px}.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{transform:translate(-50%) scale(var(--hr-scale, 1))}.sp-hud-container.show{opacity:1;pointer-events:auto;transform:translate(-50%) scale(var(--hr-scale, 1))}.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}.pswp__error-msg-container,.pswp__error-msg{display:none!important}';
  importCSS(readerCss);
  const AHEAD = 5;
  const BEHIND = 2;
  function createPrefetchController(session) {
    const downloads = new Map();
    let lastCenter = -1;
    function urlAt(index) {
      var _a;
      return (_a = session.itemAt(index)) == null ? void 0 : _a.viewerUrl;
    }
    function ensureDownload(url) {
      if (downloads.has(url)) return;
      const lease = acquireImage(url, { intent: "warmup", priority: LOAD_PRIORITY.warmup });
      downloads.set(url, lease);
      lease.result.then(() => {
        if (downloads.get(url) !== lease) return;
        downloads.delete(url);
        lease.release();
      }).catch(() => {
        if (downloads.get(url) !== lease) return;
        downloads.delete(url);
        lease.release();
      });
    }
    function abort(url) {
      var _a;
      (_a = downloads.get(url)) == null ? void 0 : _a.release();
      downloads.delete(url);
    }
    function setWindow(center, direction) {
      const total = session.imageCount;
      if (total === 0) return;
      const lo = Math.max(0, center - (direction === 1 ? BEHIND : AHEAD));
      const hi = Math.min(total - 1, center + (direction === 1 ? AHEAD : BEHIND));
      const wanted = new Set();
      for (let i = lo; i <= hi; i++) {
        const url = urlAt(i);
        if (url) wanted.add(url);
      }
      for (const url of Array.from(downloads.keys())) {
        if (!wanted.has(url)) abort(url);
      }
      const jumped = lastCenter < 0 || Math.abs(center - lastCenter) > AHEAD + BEHIND;
      if (jumped) cancelImagePrefetch(wanted);
      lastCenter = center;
      for (let d = 0; d <= Math.max(hi - center, center - lo); d++) {
        const forward = center + direction * d;
        if (forward >= lo && forward <= hi) {
          const url = urlAt(forward);
          if (url) ensureDownload(url);
        }
        const back = center - direction * d;
        if (d > 0 && back >= lo && back <= hi) {
          const url = urlAt(back);
          if (url) ensureDownload(url);
        }
      }
    }
    function warmup(indices) {
      for (const i of indices) {
        const url = urlAt(i);
        if (url) ensureDownload(url);
      }
    }
    function clear() {
      for (const url of Array.from(downloads.keys())) abort(url);
      lastCenter = -1;
    }
    return { setWindow, warmup, clear };
  }
  const WHEEL_DECAY = 0.82;
  const MIN_VELOCITY = 20;
  const MAX_VELOCITY = 150;
  const TURN_INTERVAL_SLOW = 150;
  const TURN_INTERVAL_FAST = 50;
  const GESTURE_GAP = 150;
  function createWheelPager(config) {
    let wheelVelocity = 0;
    let scrollRafId = null;
    let lastTurnTime = 0;
    let gestureConsumed = false;
    let lastWheelTime = 0;
    function stop() {
      if (scrollRafId !== null) {
        cancelAnimationFrame(scrollRafId);
        scrollRafId = null;
      }
      wheelVelocity = 0;
    }
    function scrollTick(now) {
      scrollRafId = null;
      wheelVelocity *= WHEEL_DECAY;
      if (Math.abs(wheelVelocity) < MIN_VELOCITY) {
        wheelVelocity = 0;
        return;
      }
      const dir = wheelVelocity > 0 ? 1 : -1;
      if (gestureConsumed) {
        scrollRafId = requestAnimationFrame(scrollTick);
        return;
      }
      const v = Math.min(MAX_VELOCITY, Math.abs(wheelVelocity));
      const t = Math.sqrt((v - MIN_VELOCITY) / (MAX_VELOCITY - MIN_VELOCITY));
      const interval = TURN_INTERVAL_SLOW + t * (TURN_INTERVAL_FAST - TURN_INTERVAL_SLOW);
      if (now - lastTurnTime >= interval) {
        const target = config.getCurrentIndex() + dir;
        if (target < 0) {
          stop();
          config.onEdgeBackward();
          return;
        }
        if (target >= config.getImageCount()) {
          stop();
          config.onEdgeForward();
          return;
        }
        config.stopMotion();
        config.goTo(target);
        lastTurnTime = now;
        if (config.isPageLoading(target)) {
          gestureConsumed = true;
        }
      }
      scrollRafId = requestAnimationFrame(scrollTick);
    }
    function onWheel(event) {
      if (config.isCurrentZoomed()) return;
      event.preventDefault();
      let delta = event.deltaY;
      if (event.deltaMode === 1) delta *= 33;
      else if (event.deltaMode === 2) delta *= window.innerHeight;
      const now = event.timeStamp;
      if (now - lastWheelTime > GESTURE_GAP) {
        gestureConsumed = false;
      }
      lastWheelTime = now;
      if (Math.sign(delta) !== Math.sign(wheelVelocity) && wheelVelocity !== 0) {
        wheelVelocity = 0;
      }
      wheelVelocity = Math.max(-MAX_VELOCITY, Math.min(MAX_VELOCITY, wheelVelocity + delta));
      if (scrollRafId === null) {
        scrollRafId = requestAnimationFrame(scrollTick);
      }
    }
    return { onWheel, stop };
  }
  function createAutoPlay(nextImageFn, context) {
    let timer = null;
    function start() {
      if (timer) clearInterval(timer);
      if (context.isAutoPlayEnabled()) {
        timer = setInterval(nextImageFn, context.getAutoPlayInterval());
      }
    }
    function stop() {
      if (timer) {
        clearInterval(timer);
        timer = null;
      }
    }
    function reset() {
      if (context.isAutoPlayEnabled()) {
        stop();
        start();
      }
    }
    function stopAtEnd() {
      context.setAutoPlayEnabled(false);
      stop();
    }
    return { start, stop, reset, stopAtEnd };
  }
  const isZH = navigator.language.toLowerCase().includes("zh");
  const i18n = {
readerMode: isZH ? "阅读器模式" : "Reader Mode",
    settings: isZH ? "设置" : "Settings",
    backToTop: isZH ? "回到顶部" : "Back to Top",
    play: isZH ? "播放" : "Play",
    pause: isZH ? "暂停" : "Pause",
scrollMode: isZH ? "卷轴模式" : "Scroll Mode",
    autoEnter: isZH ? "自动进入阅读器" : "Auto Enter Reader",
    clickToEnter: isZH ? "点击图片进入阅读器" : "Click Image to Enter Reader",
    playSpeed: isZH ? "自动翻页间隔 (秒)" : "Auto Play Interval (s)",
    thumbnailPosition: isZH ? "缩略图位置" : "Thumbnail Position",
    posBottom: isZH ? "底部" : "Bottom",
    posTop: isZH ? "顶部" : "Top",
    posLeft: isZH ? "左侧" : "Left",
    posRight: isZH ? "右侧" : "Right",
    downloading: isZH ? "下载中..." : "Downloading...",
    loadFailed: isZH ? "加载失败" : "Load Failed",
    waitImagesToLoad: isZH ? "请等待图片加载" : "Please wait for images to load",
    resolvingImage: isZH ? "解析图片真实地址中..." : "Resolving Image URL..."
  };
  function createReaderPaginationController(session, deps, context) {
    function checkNearEnd() {
      if (!context.getNextUrl() || context.isPageFetching()) return;
      const remainingImages = session.imageCount - session.currentIndex;
      if (remainingImages <= 5) loadNext();
    }
    function loadNext() {
      const requestedUrl = context.getNextUrl();
      if (!requestedUrl || context.isPageFetching()) return;
      let shouldContinue = false;
      context.setPageFetching(true);
      deps.onLoading("next");
      deps.pageLoader.loadPage(requestedUrl).then((page) => {
        if (!page) {
          context.setNextUrl(null);
          deps.onIdle();
          return;
        }
        deps.appendPage(page);
        deps.syncImages();
        deps.onIdle();
        shouldContinue = true;
      }).catch((err) => {
        if (err instanceof EmptyGalleryPageError) {
          context.setNextUrl(null);
          deps.onIdle();
          return;
        }
        console.error("[Single Page] Load failed", err);
        deps.onError("next", loadNext);
      }).finally(() => {
        context.setPageFetching(false);
        if (shouldContinue) checkNearEnd();
      });
    }
    function loadPrev() {
      const requestedUrl = context.getPrevUrl();
      if (!requestedUrl || context.isPageFetching()) return;
      context.setPageFetching(true);
      deps.onLoading("prev");
      deps.pageLoader.loadPage(requestedUrl).then((page) => {
        if (!page) {
          context.setPrevUrl(null);
          deps.onIdle();
          return;
        }
        deps.prependPage(page);
        deps.syncImages();
        deps.afterPrepend(page.items.length);
        deps.onIdle();
      }).catch((err) => {
        if (err instanceof EmptyGalleryPageError) {
          context.setPrevUrl(null);
          deps.onIdle();
          return;
        }
        console.error("[Single Page] Load prev failed", err);
        deps.onError("prev", loadPrev);
      }).finally(() => {
        context.setPageFetching(false);
      });
    }
    return { loadNext, loadPrev, checkNearEnd };
  }
  function createReaderImageController(session, deps) {
    const byteState = new Map();
    const leases = new Map();
    let disposed = false;
    function urlAt(index) {
      var _a;
      const itemUrl = (_a = session.itemAt(index)) == null ? void 0 : _a.viewerUrl;
      if (itemUrl) return itemUrl;
      const el = session.elementAt(index);
      return (el == null ? void 0 : el.dataset.url) || (el == null ? void 0 : el.dataset.viewerUrl) || void 0;
    }
    function indexOfUrl(url) {
      return session.indexOfViewerUrl(url);
    }
    function getPhase(index) {
      var _a;
      const url = urlAt(index);
      if (!url) return "error";
      if (byteState.get(url) === "error") return "error";
      const servicePhase = (_a = leases.get(url)) == null ? void 0 : _a.lease.phase;
      if (servicePhase === "error" || servicePhase === "cancelled") return "error";
      if (servicePhase === "resolving") return "resolving";
      if (servicePhase === "downloading") return "downloading";
      if (byteState.get(url) === "loaded" || deps.getSlideContentState(index) === "loaded") {
        return "loaded";
      }
      return "downloading";
    }
    function notify(url) {
      const index = indexOfUrl(url);
      if (index !== -1) deps.onPhaseChange(index, getPhase(index));
    }
    function ensureLease(index, viewerUrl) {
      if (!viewerUrl || leases.has(viewerUrl) || disposed) return;
      const distance = Math.abs(index - deps.getCurrentIndex());
      const lease = acquireImage(viewerUrl, {
        intent: distance === 0 ? "foreground" : "neighbor",
        priority: LOAD_PRIORITY.foreground - distance
      });
      leases.set(viewerUrl, { lease, unsubscribe: () => {
      } });
      const unsubscribe = lease.subscribe(() => notify(viewerUrl));
      leases.set(viewerUrl, { lease, unsubscribe });
      lease.result.then((asset) => {
        var _a;
        if (disposed || ((_a = leases.get(viewerUrl)) == null ? void 0 : _a.lease) !== lease) return;
        const liveIndex = indexOfUrl(viewerUrl);
        if (!asset || liveIndex === -1) {
          byteState.set(viewerUrl, "error");
          notify(viewerUrl);
          return;
        }
        byteState.set(viewerUrl, "loaded");
        notify(viewerUrl);
        deps.refreshSlide(liveIndex);
        deps.onAssetReady(liveIndex);
      }).catch(() => {
        if (disposed) return;
        byteState.set(viewerUrl, "error");
        notify(viewerUrl);
      });
    }
    function getItemData(index) {
      var _a;
      const el = session.elementAt(index);
      const item = session.itemAt(index);
      if (!el) return { src: "", w: 0, h: 0 };
      const viewerUrl = (item == null ? void 0 : item.viewerUrl) || el.dataset.url || el.dataset.viewerUrl || "";
      const fallbackSrc = el.dataset.realSrc || el.src || "";
      const cachedAsset = getCachedImage(viewerUrl);
      const resolvedSrc = (cachedAsset == null ? void 0 : cachedAsset.src) || fallbackSrc;
      let dim = cachedAsset ? { w: cachedAsset.width, h: cachedAsset.height } : void 0;
      if (!dim && (item == null ? void 0 : item.dimensions)) {
        dim = { w: item.dimensions.width, h: item.dimensions.height };
      }
      if (!dim && el.tagName === "IMG") {
        const htmlImg = el;
        if (htmlImg.complete && htmlImg.naturalWidth > 0) {
          dim = { w: htmlImg.naturalWidth, h: htmlImg.naturalHeight };
        }
      }
      if (!dim) {
        const fallbackW = window.innerWidth;
        const previewSize = (item == null ? void 0 : item.preview.kind) === "url" ? item.preview.size : (item == null ? void 0 : item.preview.kind) === "sprite" ? item.preview.crop : void 0;
        let fallbackRatio = 1.414;
        if (previewSize && previewSize.width > 0 && previewSize.height > 0) {
          fallbackRatio = previewSize.height / previewSize.width;
        } else {
          const latestCached = getLatestCachedImage();
          if (latestCached && latestCached.width > 0 && latestCached.height > 0) {
            fallbackRatio = latestCached.height / latestCached.width;
          }
        }
        dim = { w: fallbackW, h: fallbackW * fallbackRatio };
      }
      const trueDimKnown = !!(item == null ? void 0 : item.dimensions) || !!cachedAsset || el.tagName === "IMG" && el.complete && el.naturalWidth > 0;
      const msrc = (item == null ? void 0 : item.preview.kind) === "url" ? item.preview.src : void 0;
      if (viewerUrl) ensureLease(index, viewerUrl);
      const serviceReady = ((_a = leases.get(viewerUrl)) == null ? void 0 : _a.lease.phase) === "ready";
      if (serviceReady && resolvedSrc && !resolvedSrc.includes("x.gif") && trueDimKnown) {
        return { src: resolvedSrc, msrc, w: dim.w, h: dim.h };
      }
      return { src: "", msrc, w: dim.w, h: dim.h };
    }
    function handleContentLoad(index) {
      const url = urlAt(index);
      if (!url || byteState.get(url) === "loaded") return;
      byteState.set(url, "loading");
      notify(url);
    }
    function handleLoadComplete(index, isError) {
      const url = urlAt(index);
      if (!url) return;
      byteState.set(url, isError ? "error" : "loaded");
      notify(url);
    }
    function releaseOutside(center) {
      for (const [url, held] of leases) {
        const index = indexOfUrl(url);
        if (index !== -1 && Math.abs(index - center) <= 2) continue;
        held.unsubscribe();
        held.lease.release();
        leases.delete(url);
      }
    }
    function dispose() {
      disposed = true;
      for (const held of leases.values()) {
        held.unsubscribe();
        held.lease.release();
      }
      leases.clear();
    }
    return {
      urlAt,
      getItemData,
      getPhase,
      isLoading: (index) => {
        const phase = getPhase(index);
        return phase === "resolving" || phase === "downloading";
      },
      handleContentLoad,
      handleLoadComplete,
      releaseOutside,
      dispose
    };
  }
  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>` : `<svg class="hr-spinner" style="color: ${color}; width: 18px; height: 18px;" 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 };
  }
  function createThumbnailPlan(item, loadedSource) {
    switch (item.preview.kind) {
      case "url":
        return { src: item.preview.src, requestFullImage: false };
      case "sprite":
        return { src: item.preview.src, crop: item.preview.crop, requestFullImage: false };
      case "derived":
      case "none":
        return loadedSource ? { src: loadedSource, requestFullImage: false } : { requestFullImage: true };
    }
  }
  const VISIBLE_COUNT = 15;
  const BUFFER = 3;
  const PRELOAD_SETTLE_MS = 300;
  function createThumbnailPanel(onIndexChange, onScrollToBottom, onScrollToTop, options) {
    var _a;
    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 lastCenteredIndex = -1;
    let clickedFromPanel = false;
    let lastContentSize = "";
    let lastContentVertical = null;
    const itemPool = [];
    const activeItems = new Map();
    let hideTimeout;
    let isPanelActive = false;
    let preloadTimer = null;
    let userScrollArmed = false;
    function openPanel(keepOpen = false) {
      var _a2, _b;
      if (options.getImageCount() === 0) return;
      clearTimeout(hideTimeout);
      isPanelActive = true;
      thumbPanel.classList.add("active");
      const isTouchDevice = "ontouchstart" in window || navigator.maxTouchPoints > 0;
      if (keepOpen) {
        if (isTouchDevice) {
          (_a2 = options.onMobileInteractionStart) == null ? void 0 : _a2.call(options);
        }
      } else {
        if (isTouchDevice) {
          (_b = options.onMobileInteractionEnd) == null ? void 0 : _b.call(options);
        } else {
          hideTimeout = setTimeout(() => {
            closePanel();
          }, 2e3);
        }
      }
    }
    function clearThumbnailPreloadTimer() {
      if (preloadTimer) {
        clearTimeout(preloadTimer);
        preloadTimer = null;
      }
    }
    function cancelThumbnailPreloadWork() {
      var _a2;
      clearThumbnailPreloadTimer();
      (_a2 = options.cancelThumbnailPreloads) == null ? void 0 : _a2.call(options);
    }
    function closePanel() {
      isPanelActive = false;
      userScrollArmed = false;
      thumbPanel.classList.remove("active");
      clearThumbnailPreloadTimer();
    }
    thumbPanel.addEventListener("pointerenter", (e) => {
      if (e.pointerType === "mouse") openPanel(true);
    });
    thumbPanel.addEventListener("pointerleave", (e) => {
      if (e.pointerType === "mouse") openPanel(false);
    });
    thumbPanel.addEventListener("pointermove", (e) => {
      if (e.pointerType === "mouse") openPanel(true);
    });
    (_a = options.subscribeThumbnailChange) == null ? void 0 : _a.call(options, (idx) => {
      if (activeItems.has(idx)) {
        renderItemContent(activeItems.get(idx), idx);
      }
    });
    function isVertical() {
      const pos = options.getThumbnailPosition();
      return pos === "left" || pos === "right";
    }
    function getItemSize() {
      return document.documentElement.classList.contains("hr-mobile") ? 96 : 80;
    }
    function vpSize() {
      if (isVertical()) {
        return viewport.offsetHeight || Math.min(VISIBLE_COUNT * getItemSize(), options.getImageCount() * getItemSize());
      } else {
        return viewport.offsetWidth || Math.min(VISIBLE_COUNT * getItemSize(), options.getImageCount() * getItemSize());
      }
    }
    function maxOffset() {
      return Math.max(0, options.getImageCount() * getItemSize() - vpSize());
    }
    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);
    }
    const THUMB_CACHE_MAX = 60;
    const thumbCache = new Map();
    function getCachedThumb(src) {
      const c = thumbCache.get(src);
      if (c) {
        thumbCache.delete(src);
        thumbCache.set(src, c);
      }
      return c;
    }
    function putCachedThumb(src, canvas) {
      thumbCache.set(src, canvas);
      if (thumbCache.size > THUMB_CACHE_MAX) {
        const oldest = thumbCache.keys().next().value;
        if (oldest !== void 0) thumbCache.delete(oldest);
      }
    }
    function makeThumbCanvas(source, natW, natH, crop) {
      let w = crop ? crop.w : natW;
      let h = crop ? crop.h : natH;
      if (w > 300) {
        h = h * 300 / w;
        w = 300;
      }
      const c = document.createElement("canvas");
      c.width = w;
      c.height = h;
      const ctx = c.getContext("2d");
      if (ctx) {
        if (crop) {
          ctx.drawImage(source, crop.x, crop.y, crop.w, crop.h, 0, 0, w, h);
        } else {
          ctx.drawImage(source, 0, 0, w, h);
        }
      }
      return c;
    }
    function blitToCanvas(dest, cache) {
      dest.width = cache.width;
      dest.height = cache.height;
      const ctx = dest.getContext("2d");
      if (ctx) ctx.drawImage(cache, 0, 0);
    }
    function renderItemContent(el, index) {
      var _a2, _b, _c, _d;
      el.dataset.index = String(index);
      el.classList.toggle("sp-thumb-active", index === options.getCurrentIndex());
      const img = options.getImageAt(index);
      const item = options.getItemAt(index);
      const isLoadedImg = img && img.tagName === "IMG" && img.complete && img.naturalWidth > 0;
      const preloadedAsset = (_a2 = options.getPreloadedAsset) == null ? void 0 : _a2.call(options, index);
      const loadedSource = (preloadedAsset == null ? void 0 : preloadedAsset.src) || (isLoadedImg ? img.dataset.realSrc || img.src : void 0);
      const plan = item ? createThumbnailPlan(item, loadedSource) : {};
      const thumbSrc = plan.src || "";
      const isDerived = (item == null ? void 0 : item.preview.kind) === "none" || (item == null ? void 0 : item.preview.kind) === "derived";
      const crop = plan.crop ? {
        x: plan.crop.x,
        y: plan.crop.y,
        w: plan.crop.width,
        h: plan.crop.height
      } : void 0;
      const cacheKey = isDerived && item ? `derived:${item.key}` : crop ? `${thumbSrc}#${crop.x},${crop.y},${crop.w},${crop.h}` : thumbSrc;
      const cached = cacheKey ? getCachedThumb(cacheKey) : void 0;
      if (cached || thumbSrc) {
        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);
        }
        if (thumbCanvas.dataset.src !== cacheKey) {
          thumbCanvas.dataset.src = cacheKey;
          if (cached) {
            blitToCanvas(thumbCanvas, cached);
            if (isDerived && preloadedAsset) (_b = options.finishThumbnailPreload) == null ? void 0 : _b.call(options, index);
          } else if (isDerived && isLoadedImg && loadedSource === thumbSrc) {
            const c = makeThumbCanvas(img, img.naturalWidth, img.naturalHeight);
            putCachedThumb(cacheKey, c);
            blitToCanvas(thumbCanvas, c);
            if (preloadedAsset) (_c = options.finishThumbnailPreload) == null ? void 0 : _c.call(options, index);
          } else {
            const tempImg = new Image();
            tempImg.decoding = "async";
            tempImg.onload = () => {
              var _a3;
              const c = makeThumbCanvas(tempImg, tempImg.naturalWidth, tempImg.naturalHeight, crop);
              putCachedThumb(cacheKey, c);
              if (thumbCanvas.dataset.src === cacheKey) {
                blitToCanvas(thumbCanvas, c);
              }
              if (isDerived) (_a3 = options.finishThumbnailPreload) == null ? void 0 : _a3.call(options, index);
            };
            tempImg.onerror = () => {
              var _a3;
              if (isDerived) (_a3 = options.finishThumbnailPreload) == null ? void 0 : _a3.call(options, index, true);
            };
            tempImg.src = thumbSrc;
          }
        }
        const label = el.querySelector(".sp-thumb-label");
        if (label) label.textContent = String(options.getDisplayNumber(index));
      } else {
        let ph = el.querySelector(".sp-thumb-ph");
        if (!ph) {
          el.innerHTML = "";
          ph = document.createElement("div");
          ph.className = "sp-thumb-ph";
          el.appendChild(ph);
        }
        const phase = ((_d = options.getPreloadPhase) == null ? void 0 : _d.call(options, index)) ?? "idle";
        ph.classList.toggle("loading", phase === "loading");
        ph.classList.toggle("error", phase === "error");
        ph.textContent = phase === "error" ? `${options.getDisplayNumber(index)} !` : String(options.getDisplayNumber(index));
      }
    }
    function getScrollOffset() {
      return isVertical() ? viewport.scrollTop : viewport.scrollLeft;
    }
    function visiblePreloadIndices() {
      const total = options.getImageCount();
      const itemSize = getItemSize();
      const offset = getScrollOffset();
      const viewportSize = vpSize();
      const first = Math.max(0, Math.floor(offset / itemSize));
      const last = Math.min(total - 1, Math.ceil((offset + viewportSize) / itemSize) - 1);
      const center = offset + viewportSize / 2;
      const indices = [];
      for (let index = first; index <= last; index++) {
        const item = options.getItemAt(index);
        if (!item || item.preview.kind !== "none" && item.preview.kind !== "derived") continue;
        if (getCachedThumb(`derived:${item.key}`)) continue;
        const element = options.getImageAt(index);
        if ((element == null ? void 0 : element.tagName) === "IMG" && element.complete && element.naturalWidth > 0) continue;
        indices.push(index);
      }
      return indices.sort((a, b) => {
        const distanceA = Math.abs((a + 0.5) * itemSize - center);
        const distanceB = Math.abs((b + 0.5) * itemSize - center);
        return distanceA - distanceB || a - b;
      });
    }
    function scheduleThumbnailPreload() {
      cancelThumbnailPreloadWork();
      preloadTimer = setTimeout(() => {
        var _a2;
        preloadTimer = null;
        userScrollArmed = false;
        if (!isPanelActive) return;
        (_a2 = options.preloadThumbnails) == null ? void 0 : _a2.call(options, visiblePreloadIndices());
      }, PRELOAD_SETTLE_MS);
    }
    let isProgrammaticScroll = false;
    let programmaticScrollTimer;
    function setScrollOffset(val) {
      const current = getScrollOffset();
      if (Math.abs(current - val) < 1) return;
      isProgrammaticScroll = true;
      if (programmaticScrollTimer) clearTimeout(programmaticScrollTimer);
      programmaticScrollTimer = setTimeout(() => {
        isProgrammaticScroll = false;
      }, 50);
      if (isVertical()) {
        viewport.scrollTop = val;
      } else {
        viewport.scrollLeft = val;
      }
    }
    function renderVisibleItems() {
      const total = options.getImageCount();
      if (total === 0) return;
      const vp = vpSize();
      const itemSize = getItemSize();
      const wantSize = `${total * itemSize + 16}px`;
      const vertical = isVertical();
      if (lastContentSize !== wantSize || lastContentVertical !== vertical) {
        if (vertical) {
          content.style.width = "100%";
          content.style.height = wantSize;
        } else {
          content.style.width = wantSize;
          content.style.height = "100%";
        }
        lastContentSize = wantSize;
        lastContentVertical = vertical;
      }
      const scrollOffset = getScrollOffset();
      const startIdx = Math.max(0, Math.floor(scrollOffset / itemSize) - BUFFER);
      const endIdx = Math.min(total - 1, Math.ceil((scrollOffset + vp) / itemSize) + 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);
        }
        if (isVertical()) {
          el.style.transform = `translateY(${i * itemSize + 8}px)`;
        } else {
          el.style.transform = `translateX(${i * itemSize + 8}px)`;
        }
        renderItemContent(el, i);
      }
    }
    function centerOnCurrent() {
      const vp = vpSize();
      const itemSize = getItemSize();
      const target = options.getCurrentIndex() * itemSize - vp / 2 + itemSize / 2;
      setScrollOffset(target);
    }
    function ensureVisible() {
      const vp = vpSize();
      const itemSize = getItemSize();
      const itemStart = options.getCurrentIndex() * itemSize;
      const itemEnd = itemStart + itemSize;
      const currentScroll = getScrollOffset();
      if (itemStart < currentScroll) {
        setScrollOffset(itemStart);
      } else if (itemEnd > currentScroll + vp) {
        setScrollOffset(itemEnd - vp);
      }
    }
    function update() {
      const total = options.getImageCount();
      if (total === 0) return;
      const currentIndex = options.getCurrentIndex();
      if (currentIndex !== lastCenteredIndex) {
        userScrollArmed = false;
        cancelThumbnailPreloadWork();
        if (clickedFromPanel) {
          ensureVisible();
          clickedFromPanel = false;
        } else {
          centerOnCurrent();
        }
        lastCenteredIndex = currentIndex;
      }
      renderVisibleItems();
      const displayLabel = `${options.getDisplayNumber(currentIndex)} / ${options.getDisplayNumber(total - 1)}`;
      counter.textContent = displayLabel;
    }
    let lastScrollPos = 0;
    let scrollRafPending = false;
    viewport.addEventListener("scroll", () => {
      if (scrollRafPending) return;
      scrollRafPending = true;
      requestAnimationFrame(() => {
        scrollRafPending = false;
        renderVisibleItems();
        if (isProgrammaticScroll) {
          isProgrammaticScroll = false;
          if (programmaticScrollTimer) clearTimeout(programmaticScrollTimer);
          lastScrollPos = getScrollOffset();
          return;
        }
        if (!userScrollArmed) return;
        scheduleThumbnailPreload();
        const currentScroll = getScrollOffset();
        const isScrollingUp = currentScroll < lastScrollPos;
        const isScrollingDown = currentScroll > lastScrollPos;
        if (onScrollToTop && currentScroll <= 5 && isScrollingUp) {
          onScrollToTop();
        } else if (onScrollToBottom && currentScroll >= maxOffset() - 5 && isScrollingDown) {
          onScrollToBottom();
        }
        lastScrollPos = currentScroll;
        openPanel(true);
        clearTimeout(hideTimeout);
        hideTimeout = setTimeout(() => openPanel(false), 500);
      });
    }, { passive: true });
    thumbPanel.addEventListener("wheel", (e) => {
      e.stopPropagation();
    }, { passive: true });
    viewport.addEventListener("wheel", (e) => {
      userScrollArmed = true;
      if (Math.abs(e.deltaY) > Math.abs(e.deltaX)) {
        const prevScroll = getScrollOffset();
        if (!isVertical()) {
          e.preventDefault();
          viewport.scrollBy({ left: e.deltaY, behavior: "auto" });
        }
        const mOffset = maxOffset();
        if (prevScroll <= 0 && e.deltaY < 0 && onScrollToTop) {
          onScrollToTop();
        } else if (prevScroll >= mOffset - 1 && e.deltaY > 0 && onScrollToBottom) {
          onScrollToBottom();
        }
      }
    }, { passive: false });
    let isDragging = false;
    let hasDragged = false;
    let startX = 0;
    let startY = 0;
    let startScroll = 0;
    let lastTime = 0;
    let lastClientX = 0;
    let lastClientY = 0;
    let velocityX = 0;
    let velocityY = 0;
    let inertiaRaf = 0;
    let dragPointerId = null;
    viewport.addEventListener("pointerdown", (e) => {
      if (e.pointerType !== "mouse" || e.button !== 0) return;
      cancelAnimationFrame(inertiaRaf);
      isDragging = true;
      dragPointerId = e.pointerId;
      hasDragged = false;
      startX = e.clientX;
      startY = e.clientY;
      startScroll = isVertical() ? viewport.scrollTop : viewport.scrollLeft;
      lastClientX = e.clientX;
      lastClientY = e.clientY;
      lastTime = performance.now();
      velocityX = 0;
      velocityY = 0;
      viewport.style.cursor = "grabbing";
    });
    window.addEventListener("pointermove", (e) => {
      if (!isDragging || e.pointerId !== dragPointerId) return;
      if (Math.abs(e.clientX - startX) > 5 || Math.abs(e.clientY - startY) > 5) {
        hasDragged = true;
        userScrollArmed = true;
      }
      e.preventDefault();
      const now = performance.now();
      const dt = now - lastTime;
      if (dt > 5) {
        const dx = e.clientX - lastClientX;
        const dy = e.clientY - lastClientY;
        velocityX = 0.6 * velocityX + 0.4 * (-dx / dt);
        velocityY = 0.6 * velocityY + 0.4 * (-dy / dt);
        lastClientX = e.clientX;
        lastClientY = e.clientY;
        lastTime = now;
      }
      const mOffset = maxOffset();
      if (isVertical()) {
        const newScroll = startScroll - (e.clientY - startY);
        viewport.scrollTop = newScroll;
        if (startScroll <= 0 && newScroll < -30 && onScrollToTop) {
          onScrollToTop();
          startScroll = 0;
          startY = e.clientY;
        } else if (startScroll >= mOffset - 1 && newScroll > mOffset + 30 && onScrollToBottom) {
          onScrollToBottom();
          startScroll = mOffset;
          startY = e.clientY;
        }
      } else {
        const newScroll = startScroll - (e.clientX - startX);
        viewport.scrollLeft = newScroll;
        if (startScroll <= 0 && newScroll < -30 && onScrollToTop) {
          onScrollToTop();
          startScroll = 0;
          startX = e.clientX;
        } else if (startScroll >= mOffset - 1 && newScroll > mOffset + 30 && onScrollToBottom) {
          onScrollToBottom();
          startScroll = mOffset;
          startX = e.clientX;
        }
      }
    });
    function endMouseDrag(withInertia) {
      if (!isDragging) return;
      isDragging = false;
      dragPointerId = null;
      viewport.style.cursor = "";
      if (!withInertia) {
        velocityX = 0;
        velocityY = 0;
        return;
      }
      const timeSinceLastMove = performance.now() - lastTime;
      if (timeSinceLastMove > 50) {
        velocityX = 0;
        velocityY = 0;
      }
      let virtualScroll = isVertical() ? viewport.scrollTop : viewport.scrollLeft;
      const startInertia = () => {
        const v = isVertical() ? velocityY : velocityX;
        if (Math.abs(v) < 0.05) return;
        const mOffset = maxOffset();
        virtualScroll += v * 16;
        if (isVertical()) {
          viewport.scrollTop = virtualScroll;
          if (virtualScroll < -30 && onScrollToTop) {
            onScrollToTop();
            return;
          }
          if (virtualScroll > mOffset + 30 && onScrollToBottom) {
            onScrollToBottom();
            return;
          }
          velocityY *= 0.95;
          if (virtualScroll < 0 || virtualScroll > mOffset) velocityY *= 0.8;
        } else {
          viewport.scrollLeft = virtualScroll;
          if (virtualScroll < -30 && onScrollToTop) {
            onScrollToTop();
            return;
          }
          if (virtualScroll > mOffset + 30 && onScrollToBottom) {
            onScrollToBottom();
            return;
          }
          velocityX *= 0.95;
          if (virtualScroll < 0 || virtualScroll > mOffset) velocityX *= 0.8;
        }
        inertiaRaf = requestAnimationFrame(startInertia);
      };
      inertiaRaf = requestAnimationFrame(startInertia);
    }
    window.addEventListener("pointerup", (e) => {
      if (e.pointerId === dragPointerId) endMouseDrag(true);
    });
    window.addEventListener("pointercancel", (e) => {
      if (e.pointerId === dragPointerId) endMouseDrag(false);
    });
    let touchStartX = 0;
    let touchStartY = 0;
    viewport.addEventListener("touchstart", (e) => {
      touchStartX = e.touches[0].clientX;
      touchStartY = e.touches[0].clientY;
    }, { passive: true });
    viewport.addEventListener("touchmove", (e) => {
      userScrollArmed = true;
      const currentScroll = getScrollOffset();
      const mOffset = maxOffset();
      if (isVertical()) {
        const dy = e.touches[0].clientY - touchStartY;
        if (currentScroll <= 0 && dy > 40 && onScrollToTop) {
          onScrollToTop();
          touchStartY = e.touches[0].clientY;
        } else if (currentScroll >= mOffset - 1 && dy < -40 && onScrollToBottom) {
          onScrollToBottom();
          touchStartY = e.touches[0].clientY;
        }
      } else {
        const dx = e.touches[0].clientX - touchStartX;
        if (currentScroll <= 0 && dx > 40 && onScrollToTop) {
          onScrollToTop();
          touchStartX = e.touches[0].clientX;
        } else if (currentScroll >= mOffset - 1 && dx < -40 && onScrollToBottom) {
          onScrollToBottom();
          touchStartX = e.touches[0].clientX;
        }
      }
    }, { passive: true });
    content.addEventListener("click", (e) => {
      if (hasDragged) {
        e.preventDefault();
        e.stopPropagation();
        return;
      }
      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 < options.getImageCount()) {
          clickedFromPanel = true;
          onIndexChange(index);
        }
      }
    });
    window.addEventListener("resize", () => {
      userScrollArmed = false;
      cancelThumbnailPreloadWork();
      if (options.getImageCount() > 0) {
        renderVisibleItems();
      }
    }, { passive: true });
    options.subscribeSettingsChanged(() => {
      userScrollArmed = false;
      cancelThumbnailPreloadWork();
      centerOnCurrent();
      renderVisibleItems();
    });
    return {
      getElement: () => thumbPanel,
      update,
      openPanel,
      closePanel,
      isActive: () => isPanelActive,
      resetCentering: () => {
        lastCenteredIndex = -1;
      }
    };
  }
  function createProgressTrack(onIndexChange, panelIsActive, options) {
    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);
    let cachedTrackSize = 0;
    let isDragging = false;
    let dragStartPos = 0;
    let thumbStartPos = 0;
    let previousBodyUserSelect = null;
    function isVertical() {
      const pos = options.getThumbnailPosition();
      return pos === "left" || pos === "right";
    }
    function refreshTrackSize() {
      cachedTrackSize = isVertical() ? progressTrack.offsetHeight : progressTrack.offsetWidth;
    }
    window.addEventListener("resize", refreshTrackSize, { passive: true });
    options.subscribeSettingsChanged(() => {
      progressThumb.style.width = "";
      progressThumb.style.height = "";
      progressThumb.style.left = "";
      progressThumb.style.top = "";
      refreshTrackSize();
    });
    function update() {
      const imageCount = options.getImageCount();
      if (imageCount === 0) return;
      if (!cachedTrackSize) refreshTrackSize();
      const trackSize = cachedTrackSize;
      let thumbSize;
      if (imageCount <= 10) {
        thumbSize = 60;
      } else if (imageCount <= 50) {
        thumbSize = Math.max(60, trackSize * (10 / imageCount));
      } else {
        thumbSize = Math.max(60, trackSize * (5 / imageCount));
      }
      const currentIndex = options.getCurrentIndex();
      const scrollProgress = currentIndex / Math.max(1, imageCount - 1);
      const maxThumbPos = trackSize - thumbSize;
      const thumbPos = scrollProgress * maxThumbPos;
      if (isVertical()) {
        progressThumb.style.height = `${thumbSize}px`;
        progressThumb.style.top = `${thumbPos}px`;
      } else {
        progressThumb.style.width = `${thumbSize}px`;
        progressThumb.style.left = `${thumbPos}px`;
      }
      const displayLabel = `${options.getDisplayNumber(currentIndex)} / ${options.getDisplayNumber(imageCount - 1)}`;
      progressLabel.textContent = displayLabel;
    }
    progressTrack.onclick = (e) => {
      if (e.target === progressThumb) return;
      const rect = progressTrack.getBoundingClientRect();
      let scrollProgress = 0;
      if (isVertical()) {
        const clickY = e.clientY - rect.top;
        scrollProgress = Math.min(1, Math.max(0, clickY / rect.height));
      } else {
        const clickX = e.clientX - rect.left;
        scrollProgress = Math.min(1, Math.max(0, clickX / rect.width));
      }
      const imageCount = options.getImageCount();
      const targetIndex = Math.round(scrollProgress * (imageCount - 1));
      if (targetIndex >= 0 && targetIndex < imageCount) {
        onIndexChange(targetIndex);
      }
    };
    progressThumb.onmousedown = (e) => {
      e.preventDefault();
      e.stopPropagation();
      isDragging = true;
      if (isVertical()) {
        dragStartPos = e.clientY;
        thumbStartPos = progressThumb.offsetTop;
      } else {
        dragStartPos = e.clientX;
        thumbStartPos = progressThumb.offsetLeft;
      }
      previousBodyUserSelect = document.body.style.userSelect;
      document.body.style.userSelect = "none";
    };
    document.addEventListener("mousemove", (e) => {
      if (!isDragging) return;
      const delta = isVertical() ? e.clientY - dragStartPos : e.clientX - dragStartPos;
      const newPos = thumbStartPos + delta;
      const trackSize = cachedTrackSize;
      const thumbSize = isVertical() ? progressThumb.offsetHeight : progressThumb.offsetWidth;
      const maxPos = trackSize - thumbSize;
      const clampedPos = Math.max(0, Math.min(maxPos, newPos));
      const scrollProgress = maxPos > 0 ? clampedPos / maxPos : 0;
      const imageCount = options.getImageCount();
      const targetIndex = Math.round(scrollProgress * (imageCount - 1));
      if (targetIndex >= 0 && targetIndex < imageCount && targetIndex !== options.getCurrentIndex()) {
        onIndexChange(targetIndex);
      }
    });
    function endProgressDrag(wake = true) {
      if (!isDragging) return;
      isDragging = false;
      document.body.style.userSelect = previousBodyUserSelect ?? "";
      previousBodyUserSelect = null;
      if (wake) wakeUp();
    }
    document.addEventListener("mouseup", () => endProgressDrag());
    window.addEventListener("blur", () => endProgressDrag(false));
    progressThumb.onclick = (e) => e.stopPropagation();
    let progressWakeTimer = null;
    function wakeUp() {
      if (panelIsActive()) return;
      progressTrack.classList.add("active");
      if (progressWakeTimer) clearTimeout(progressWakeTimer);
      progressWakeTimer = setTimeout(() => {
        progressTrack.classList.remove("active");
      }, 1500);
    }
    function sleep() {
      progressTrack.classList.remove("active");
      if (progressWakeTimer) clearTimeout(progressWakeTimer);
    }
    return {
      getElement: () => progressTrack,
      update,
      wakeUp,
      sleep
    };
  }
  function createMouseTracker(panel, progress, getThumbnailPosition) {
    const isTouchDevice = window.matchMedia("(hover: none)").matches;
    if (isTouchDevice) return;
    const SENSITIVITY = 140;
    document.addEventListener("mousemove", (e) => {
      if (!document.querySelector(".pswp")) return;
      if (e.clientX < 0 || e.clientY < 0 || e.clientX >= window.innerWidth - 1 || e.clientY >= window.innerHeight - 1) {
        panel.closePanel();
        return;
      }
      const pos = getThumbnailPosition();
      let distanceToEdge = Infinity;
      switch (pos) {
        case "bottom":
          distanceToEdge = window.innerHeight - e.clientY;
          break;
        case "top":
          distanceToEdge = e.clientY;
          break;
        case "left":
          distanceToEdge = e.clientX;
          break;
        case "right":
          distanceToEdge = window.innerWidth - e.clientX;
          break;
      }
      if (distanceToEdge <= SENSITIVITY) {
        if (!panel.isActive()) {
          panel.openPanel();
          progress.sleep();
        }
      } else {
        if (panel.isActive()) {
          panel.closePanel();
        }
      }
    });
    document.addEventListener("mouseout", (e) => {
      if (!e.relatedTarget) panel.closePanel();
    });
    document.documentElement.addEventListener("mouseleave", () => {
      panel.closePanel();
    });
  }
  function createSidebar(onIndexChange, onScrollToBottom, onScrollToTop, options) {
    const panel = createThumbnailPanel(onIndexChange, onScrollToBottom, onScrollToTop, options);
    const progress = createProgressTrack(onIndexChange, panel.isActive, options);
    createMouseTracker(panel, progress, options.getThumbnailPosition);
    function update() {
      panel.update();
      progress.update();
    }
    function applyPositionClasses() {
      const newPos = options.getThumbnailPosition();
      panel.getElement().classList.remove(`position-top`, `position-bottom`, `position-left`, `position-right`);
      progress.getElement().classList.remove(`position-top`, `position-bottom`, `position-left`, `position-right`);
      panel.getElement().classList.add(`position-${newPos}`);
      progress.getElement().classList.add(`position-${newPos}`);
    }
    applyPositionClasses();
    options.subscribeSettingsChanged(applyPositionClasses);
    return {
      update,
      getElements: () => [progress.getElement(), panel.getElement()],
      wakeUpProgressBar: progress.wakeUp,
      openPanel: panel.openPanel,
      closePanel: panel.closePanel,
      resetCentering: panel.resetCentering
    };
  }
  function createReaderShell(options) {
    const hud = createStatusHUD();
    const sidebar = createSidebar(
      options.onIndexChange,
      options.onScrollToBottom,
      options.onScrollToTop,
      {
        onMobileInteractionStart: options.onMobileInteractionStart,
        onMobileInteractionEnd: options.onMobileInteractionEnd,
        subscribeThumbnailChange: options.thumbnailController.subscribeChange,
        preloadThumbnails: options.thumbnailController.preload,
        cancelThumbnailPreloads: options.thumbnailController.cancelPreloads,
        finishThumbnailPreload: options.thumbnailController.finishPreload,
        getPreloadedAsset: options.thumbnailController.getPreloadedAsset,
        getPreloadPhase: options.thumbnailController.getPreloadPhase,
        getImageCount: options.getImageCount,
        getCurrentIndex: options.getCurrentIndex,
        getImageAt: options.getImageAt,
        getItemAt: options.getItemAt,
        getDisplayNumber: options.getDisplayNumber,
        getThumbnailPosition: options.getThumbnailPosition,
        subscribeSettingsChanged: options.subscribeSettingsChanged
      }
    );
    function mount(driver, counter) {
      driver.registerCounter(counter);
      const sidebarElements = sidebar.getElements();
      sidebarElements.forEach((element) => {
        element.style.pointerEvents = "auto";
        element.dataset.readerWheelBlock = "";
      });
      driver.appendUi([...sidebarElements, hud.getElement()]);
      const unsubscribeVisibility = driver.observeUiVisibility((isVisible) => {
        sidebarElements.forEach((element) => {
          element.classList.toggle("sp-hidden-by-pswp", !isVisible);
        });
        if (window.matchMedia("(hover: none)").matches) {
          if (isVisible) sidebar.openPanel(false);
          else sidebar.closePanel();
        }
      });
      return () => {
        unsubscribeVisibility();
        sidebar.closePanel();
        options.thumbnailController.cancelPreloads();
      };
    }
    return {
      update: sidebar.update,
      resetCentering: sidebar.resetCentering,
      showStatus: hud.show,
      hideStatus: hud.hide,
      mount
    };
  }
  class ReaderSession {
    constructor(getItems) {
      this.images = [];
      this.index = 0;
      this.navigated = false;
      this.previousIndex = -1;
      this.getItems = getItems;
    }
    syncImages(images) {
      const changed = images.length !== this.images.length || images.some((image, index) => image !== this.images[index]);
      if (!changed) return false;
      this.images = images;
      return true;
    }
    replaceImage(index, image) {
      if (index < 0 || index >= this.images.length) return;
      this.images[index] = image;
    }
    setCurrentIndex(index, trackNavigation = true) {
      if (trackNavigation && this.previousIndex !== -1 && this.previousIndex !== index) {
        this.navigated = true;
      }
      this.previousIndex = index;
      this.index = index;
    }
    reset(startIndex) {
      this.navigated = false;
      this.previousIndex = startIndex;
      this.index = startIndex;
    }
    prepend(count) {
      this.index += count;
      this.previousIndex = this.index;
    }
    get currentIndex() {
      return this.index;
    }
    get lastIndex() {
      return this.previousIndex;
    }
    get hasNavigated() {
      return this.navigated;
    }
    get imageCount() {
      return this.images.length;
    }
    elementAt(index) {
      return this.images[index];
    }
    itemAt(index) {
      return this.getItems()[index];
    }
    indexOfViewerUrl(url) {
      return this.getItems().findIndex((item) => item.viewerUrl === url);
    }
    snapshotImages() {
      return this.images;
    }
  }
  function createThumbnailController(session, scroll, deps) {
    const acquire = deps.acquire;
    const maxConcurrent = Math.max(1, deps.maxConcurrent ?? 2);
    const entries = new Map();
    const listeners = new Set();
    let pending = [];
    let active = 0;
    function notify(index) {
      listeners.forEach((listener) => listener(index));
    }
    function releaseEntry(entry) {
      var _a, _b;
      (_a = entry.releaseSlot) == null ? void 0 : _a.call(entry);
      entry.releaseSlot = void 0;
      (_b = entry.lease) == null ? void 0 : _b.release();
      entry.lease = void 0;
      entry.asset = void 0;
    }
    function pump() {
      while (active < maxConcurrent && pending.length > 0) {
        const index = pending.shift();
        const entry = entries.get(index);
        const item = session.itemAt(index);
        if (!entry || entry.phase !== "loading" || !item) continue;
        active++;
        let slotHeld = true;
        entry.releaseSlot = () => {
          if (!slotHeld) return;
          slotHeld = false;
          active--;
        };
        const lease = acquire(item.viewerUrl, {
          intent: "thumbnail",
          priority: deps.priority
        });
        entry.lease = lease;
        lease.result.then((asset) => {
          if (entries.get(index) !== entry) return;
          if (!asset) {
            releaseEntry(entry);
            entry.phase = "error";
          } else {
            entry.asset = asset;
            entry.phase = "ready";
          }
          notify(index);
        }).catch(() => {
          if (entries.get(index) !== entry) return;
          releaseEntry(entry);
          entry.phase = "error";
          notify(index);
        }).finally(() => {
          var _a;
          (_a = entry.releaseSlot) == null ? void 0 : _a.call(entry);
          entry.releaseSlot = void 0;
          pump();
        });
      }
    }
    function cancelPreloads() {
      pending = [];
      const changed = Array.from(entries.keys());
      entries.forEach(releaseEntry);
      entries.clear();
      changed.forEach(notify);
      pump();
    }
    function preload(indices) {
      cancelPreloads();
      const unique = new Set();
      for (const index of indices) {
        if (unique.has(index)) continue;
        const item = session.itemAt(index);
        if (!item || item.preview.kind !== "none" && item.preview.kind !== "derived") continue;
        const element = session.elementAt(index);
        if ((element == null ? void 0 : element.tagName) === "IMG" && element.complete && element.naturalWidth > 0) continue;
        unique.add(index);
        entries.set(index, { phase: "loading" });
        pending.push(index);
        notify(index);
      }
      pump();
    }
    function finishPreload(index, failed = false) {
      const entry = entries.get(index);
      if (!entry) return;
      releaseEntry(entry);
      if (failed) {
        entry.phase = "error";
      } else {
        entries.delete(index);
      }
      notify(index);
    }
    return {
      preload,
      cancelPreloads,
      finishPreload,
      getPreloadedAsset(index) {
        var _a;
        return (_a = entries.get(index)) == null ? void 0 : _a.asset;
      },
      getPreloadPhase(index) {
        var _a;
        return ((_a = entries.get(index)) == null ? void 0 : _a.phase) ?? "idle";
      },
      subscribeChange(listener) {
        listeners.add(listener);
        const unsubscribeScroll = scroll.subscribeImageLoaded((event) => listener(event.index));
        return () => {
          listeners.delete(listener);
          unsubscribeScroll();
        };
      }
    };
  }
  const RETURN_GEOMETRY_RADIUS = 5;
  function createReaderController(deps) {
    let pswp = null;
    let isActive = false;
    let isReinitializing = false;
    let overflowSnapshot = null;
    const session = new ReaderSession(deps.context.getGalleryItems);
    let onMobileInteractionStart = () => {
    };
    let onMobileInteractionEnd = () => {
    };
    let entryScrollY = 0;
    let entryItemKey = "";
    function itemKeyAt(index) {
      var _a;
      const element = session.elementAt(index);
      return ((_a = session.itemAt(index)) == null ? void 0 : _a.key) || (element == null ? void 0 : element.dataset.itemKey) || (element == null ? void 0 : element.dataset.viewerUrl) || (element == null ? void 0 : element.dataset.url) || "";
    }
    function syncImages() {
      const freshImages = Array.from(document.querySelectorAll(".r-img, .r-ph"));
      if (session.syncImages(freshImages)) {
        shell.update();
        if (pswp) {
          const c = pswp.currentIndex;
          for (let i = c - 1; i <= c + 1; i++) {
            if (i >= 0 && i < session.imageCount) pswp.refreshSlide(i);
          }
        }
      }
    }
    const prefetch = createPrefetchController(session);
    const thumbnailController = createThumbnailController(session, deps.scroll, {
      acquire: acquireImage,
      priority: LOAD_PRIORITY.thumbnail
    });
    const autoPlay = createAutoPlay(() => pswp == null ? void 0 : pswp.next(), deps.context);
    let pagination;
    const shell = createReaderShell({
      onIndexChange: (index) => {
        session.setCurrentIndex(index);
        pswp == null ? void 0 : pswp.goTo(index);
        autoPlay.reset();
      },
      onScrollToBottom: () => pagination.loadNext(),
      onScrollToTop: () => pagination.loadPrev(),
      onMobileInteractionStart: () => onMobileInteractionStart(),
      onMobileInteractionEnd: () => onMobileInteractionEnd(),
      thumbnailController,
      getImageCount: () => session.imageCount,
      getCurrentIndex: () => session.currentIndex,
      getImageAt: (index) => session.elementAt(index),
      getItemAt: (index) => session.itemAt(index),
      getDisplayNumber: (index) => deps.context.getImageOffset() + index + 1,
      getThumbnailPosition: deps.context.getThumbnailPosition,
      subscribeSettingsChanged: deps.context.subscribeSettingsChanged
    });
    pagination = createReaderPaginationController(session, {
      pageLoader: deps.pageLoader,
      appendPage: deps.onLoadNextPage,
      prependPage: deps.onLoadPrevPage,
      syncImages,
      afterPrepend: (itemCount) => {
        isReinitializing = true;
        session.prepend(itemCount);
        deps.context.setImageOffset(Math.max(0, deps.context.getImageOffset() - itemCount));
        if (pswp) {
          pswp.stopMotion();
          pswp.goTo(session.currentIndex);
        }
        isReinitializing = false;
      },
      onLoading: () => shell.showStatus({ status: "loading", text: i18n.downloading }),
      onIdle: () => shell.hideStatus(),
      onError: (_direction, retry) => {
        shell.showStatus({ status: "error", text: i18n.loadFailed, onClick: () => {
          shell.hideStatus();
          retry();
        } });
      }
    }, deps.context);
    function open(startIdx) {
      if (isActive) return;
      session.syncImages(Array.from(document.querySelectorAll(".r-img, .r-ph")));
      if (session.imageCount === 0) {
        alert(i18n.waitImagesToLoad);
        return;
      }
      let startIndex = startIdx ?? 0;
      if (startIdx === void 0) {
        if (deps.context.isScrollMode()) {
          let minDistance = Infinity;
          session.snapshotImages().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 {
          startIndex = session.currentIndex;
        }
      }
      entryScrollY = window.scrollY;
      entryItemKey = itemKeyAt(startIndex);
      session.reset(startIndex);
      isActive = true;
      overflowSnapshot = {
        documentElement: document.documentElement.style.overflow,
        body: document.body.style.overflow
      };
      document.documentElement.style.overflow = "hidden";
      document.body.style.overflow = "hidden";
      deps.context.emitReaderModeChanged();
      if (deps.context.isScrollMode()) {
        deps.scroll.pause();
        document.documentElement.classList.add("hr-reader-open");
      }
      shell.resetCentering();
      initPhotoSwipe(startIndex);
      if (deps.context.isAutoPlayEnabled()) {
        autoPlay.start();
      }
    }
    function initPhotoSwipe(startIndex) {
      let mobileUiTimeout;
      function triggerMobileUITimeout() {
        const isTouchDevice = "ontouchstart" in window || navigator.maxTouchPoints > 0;
        if (!isTouchDevice) return;
        clearTimeout(mobileUiTimeout);
        mobileUiTimeout = setTimeout(() => {
          pswp == null ? void 0 : pswp.hideUi();
        }, 2e3);
      }
      function cancelMobileUITimeout() {
        clearTimeout(mobileUiTimeout);
      }
      onMobileInteractionStart = cancelMobileUITimeout;
      onMobileInteractionEnd = triggerMobileUITimeout;
      function handleScreenClick(point, defaultCenterAction) {
        const width = window.innerWidth;
        if (point.x < width * 0.3) {
          if ((pswp == null ? void 0 : pswp.currentIndex) === 0 && deps.context.getPrevUrl() && !deps.context.isPageFetching()) {
            pagination.loadPrev();
          } else {
            pswp == null ? void 0 : pswp.prev();
          }
        } else if (point.x > width * 0.7) {
          if ((pswp == null ? void 0 : pswp.currentIndex) === session.imageCount - 1 && deps.context.getNextUrl() && !deps.context.isPageFetching()) {
            pagination.loadNext();
          } else {
            pswp == null ? void 0 : pswp.next();
          }
        } else {
          if (defaultCenterAction === "zoom" && (pswp == null ? void 0 : pswp.canToggleCurrentZoom())) {
            pswp.toggleCurrentZoom(point);
          } else {
            const isNowVisible = pswp == null ? void 0 : pswp.toggleUi();
            if (isNowVisible) triggerMobileUITimeout();
          }
        }
      }
      pswp = deps.createDriver({
        startIndex,
        onBackgroundClick: (point) => handleScreenClick(point, "toggle"),
        onImageClick: (point) => handleScreenClick(point, "zoom"),
        onTap: (point) => handleScreenClick(point, "toggle")
      });
      pswp.on("zoomLevelsUpdate", (e) => {
        const zl = e.zoomLevels;
        if (zl.initial > zl.fit) zl.fit = zl.initial;
      });
      const unsubscribeImageLoaded = deps.scroll.subscribeImageLoaded(({ index, element }) => {
        session.replaceImage(index, element);
        if (pswp && index >= 0 && index < session.imageCount) {
          pswp.refreshSlide(index);
        }
      });
      pswp.on("destroy", () => {
        clearTimeout(mobileUiTimeout);
        onMobileInteractionStart = () => {
        };
        onMobileInteractionEnd = () => {
        };
        unsubscribeImageLoaded();
      });
      function showImagePhase(phase) {
        switch (phase) {
          case "error":
            shell.showStatus({ status: "error", text: i18n.loadFailed });
            break;
          case "resolving":
            shell.showStatus({ status: "loading", text: i18n.resolvingImage });
            break;
          case "downloading":
            shell.showStatus({ status: "loading", text: i18n.downloading });
            break;
          case "loaded":
            shell.hideStatus();
            break;
        }
      }
      const imageController = createReaderImageController(session, {
        getCurrentIndex: () => (pswp == null ? void 0 : pswp.currentIndex) ?? session.currentIndex,
        getSlideContentState: (index) => pswp == null ? void 0 : pswp.getSlideContentState(index),
        refreshSlide: (index) => pswp == null ? void 0 : pswp.refreshSlide(index),
        onPhaseChange: (index, phase) => {
          if ((pswp == null ? void 0 : pswp.currentIndex) === index) showImagePhase(phase);
        },
        onAssetReady: (index) => {
          if ((pswp == null ? void 0 : pswp.currentIndex) === index && deps.context.isAutoPlayEnabled()) autoPlay.start();
        }
      });
      function refreshHudForCurrent() {
        if (!pswp) return;
        showImagePhase(imageController.getPhase(pswp.currentIndex));
      }
      pswp.on("destroy", () => imageController.dispose());
      pswp.on("contentLoadImage", (e) => {
        var _a;
        if (typeof ((_a = e.content) == null ? void 0 : _a.index) === "number") imageController.handleContentLoad(e.content.index);
      });
      pswp.on("loadComplete", (e) => {
        var _a;
        if (typeof ((_a = e.content) == null ? void 0 : _a.index) === "number") {
          imageController.handleLoadComplete(e.content.index, e.isError);
        }
      });
      pswp.on("numItems", (e) => {
        e.numItems = session.imageCount;
      });
      pswp.on("itemData", (e) => {
        e.itemData = imageController.getItemData(e.index);
      });
      const wheelPager = createWheelPager({
        getCurrentIndex: () => (pswp == null ? void 0 : pswp.currentIndex) ?? session.currentIndex,
        isCurrentZoomed: () => (pswp == null ? void 0 : pswp.isCurrentZoomed()) ?? false,
        goTo: (index) => pswp == null ? void 0 : pswp.goTo(index),
        stopMotion: () => pswp == null ? void 0 : pswp.stopMotion(),
        getImageCount: () => session.imageCount,
        isPageLoading: (index) => imageController.isLoading(index),
        onEdgeForward: () => {
          if (deps.context.getNextUrl() && !deps.context.isPageFetching()) pagination.loadNext();
        },
        onEdgeBackward: () => {
          if (deps.context.getPrevUrl() && !deps.context.isPageFetching()) pagination.loadPrev();
        }
      });
      pswp.on("destroy", () => wheelPager.stop());
      pswp.on("change", () => {
        if (isReinitializing) {
          return;
        }
        if (pswp) {
          const previousIndex = session.lastIndex;
          const isNavigatingBackwards = pswp.currentIndex < previousIndex;
          session.setCurrentIndex(pswp.currentIndex);
          shell.update();
          pagination.checkNearEnd();
          refreshHudForCurrent();
          if (session.currentIndex <= 3 && deps.context.getPrevUrl() && session.hasNavigated && isNavigatingBackwards) {
            pagination.loadPrev();
          }
          if (deps.context.isAutoPlayEnabled()) {
            autoPlay.stop();
            if (pswp.currentIndex >= session.imageCount - 1 && !deps.context.getNextUrl()) {
              autoPlay.stopAtEnd();
            } else {
              if (pswp.isCurrentContentLoaded()) {
                autoPlay.start();
              }
            }
          }
          prefetch.setWindow(pswp.currentIndex, isNavigatingBackwards ? -1 : 1);
          imageController.releaseOutside(pswp.currentIndex);
        }
      });
      pswp.on("uiRegister", () => {
        if (!pswp) return;
        const unmountShell = shell.mount(
          pswp,
          (index) => `${deps.context.getImageOffset() + index + 1} / ${deps.context.getImageOffset() + session.imageCount}`
        );
        const removeWheel = pswp.installWheel((event) => wheelPager.onWheel(event));
        const removeEdgeSwipe = pswp.installEdgeSwipe({
          onBackward: () => {
            if ((pswp == null ? void 0 : pswp.currentIndex) === 0 && deps.context.getPrevUrl() && !deps.context.isPageFetching()) {
              pagination.loadPrev();
            }
          },
          onForward: () => {
            if ((pswp == null ? void 0 : pswp.currentIndex) === session.imageCount - 1 && deps.context.getNextUrl() && !deps.context.isPageFetching()) {
              pagination.loadNext();
            }
          }
        });
        pswp.on("destroy", () => {
          removeWheel();
          removeEdgeSwipe();
          unmountShell();
        });
        triggerMobileUITimeout();
      });
      pswp.on("close", () => {
        close();
      });
      pswp.init();
      prefetch.setWindow(startIndex, 1);
    }
    function close() {
      autoPlay.stop();
      deps.context.setAutoPlayEnabled(false);
      isActive = false;
      prefetch.clear();
      if (overflowSnapshot) {
        document.documentElement.style.overflow = overflowSnapshot.documentElement;
        document.body.style.overflow = overflowSnapshot.body;
        overflowSnapshot = null;
      }
      if (deps.context.isScrollMode()) {
        const currentKey = itemKeyAt(session.currentIndex);
        const returnedToEntry = !!entryItemKey && currentKey === entryItemKey;
        if (session.hasNavigated && !returnedToEntry) {
          const item = session.itemAt(session.currentIndex);
          const key = (item == null ? void 0 : item.key) || currentKey;
          const firstGeometryIndex = Math.max(0, session.currentIndex - RETURN_GEOMETRY_RADIUS);
          const lastGeometryIndex = Math.min(
            session.imageCount - 1,
            session.currentIndex + RETURN_GEOMETRY_RADIUS
          );
          const nearbyGeometry = [];
          for (let index = firstGeometryIndex; index <= lastGeometryIndex; index++) {
            const nearbyItem = session.itemAt(index);
            const cachedAsset = nearbyItem && getCachedImage(nearbyItem.viewerUrl);
            if (!nearbyItem || !cachedAsset) continue;
            nearbyGeometry.push({
              key: nearbyItem.key,
              index,
              preferred: session.elementAt(index),
              width: cachedAsset.width,
              height: cachedAsset.height
            });
          }
          deps.scroll.restore({
            entryScrollY,
            nearbyGeometry,
            target: {
              key,
              index: session.currentIndex,
              preferred: session.elementAt(session.currentIndex)
            }
          });
        } else {
          deps.scroll.restore({ entryScrollY });
        }
        document.documentElement.classList.remove("hr-reader-open");
        deps.scroll.resume();
      }
      if (pswp) {
        const p = pswp;
        pswp = null;
        try {
          p.destroy();
        } catch (err) {
          console.error("[Hentai-Reader] Error destroying PhotoSwipe:", err);
        }
      }
      deps.context.emitReaderModeChanged();
      deps.context.onReaderClose(deps.context.getImageOffset() + session.currentIndex);
    }
    deps.context.subscribeSettingsChanged(() => {
      if (!isActive) return;
      if (deps.context.isAutoPlayEnabled()) {
        autoPlay.start();
      } else {
        autoPlay.stop();
      }
    });
    deps.context.subscribeReaderModeChanged(() => {
      if (!isActive || !pswp) return;
      const el = document.querySelector(".pswp__counter");
      if (el) {
        el.innerHTML = `${deps.context.getImageOffset() + pswp.currentIndex + 1} / ${deps.context.getImageOffset() + session.imageCount}`;
      }
    });
    function warmupInitial(count) {
      if (isActive) return;
      session.syncImages(Array.from(document.querySelectorAll(".r-img, .r-ph")));
      if (session.imageCount === 0) return;
      const indices = [];
      for (let i = 0; i < Math.min(count, session.imageCount); i++) {
        indices.push(i);
      }
      prefetch.warmup(indices);
    }
    return {
      open,
      close,
      isActive: () => isActive,
      warmupInitial
    };
  }
function createElement(className, tagName, appendToEl) {
    const el = document.createElement(tagName);
    if (className) {
      el.className = className;
    }
    if (appendToEl) {
      appendToEl.appendChild(el);
    }
    return el;
  }
  function equalizePoints(p1, p2) {
    p1.x = p2.x;
    p1.y = p2.y;
    if (p2.id !== void 0) {
      p1.id = p2.id;
    }
    return p1;
  }
  function roundPoint(p) {
    p.x = Math.round(p.x);
    p.y = Math.round(p.y);
  }
  function getDistanceBetween(p1, p2) {
    const x = Math.abs(p1.x - p2.x);
    const y = Math.abs(p1.y - p2.y);
    return Math.sqrt(x * x + y * y);
  }
  function pointsEqual(p1, p2) {
    return p1.x === p2.x && p1.y === p2.y;
  }
  function clamp(val, min, max) {
    return Math.min(Math.max(val, min), max);
  }
  function toTransformString(x, y, scale) {
    let propValue = `translate3d(${x}px,${y || 0}px,0)`;
    if (scale !== void 0) {
      propValue += ` scale3d(${scale},${scale},1)`;
    }
    return propValue;
  }
  function setTransform(el, x, y, scale) {
    el.style.transform = toTransformString(x, y, scale);
  }
  const defaultCSSEasing = "cubic-bezier(.4,0,.22,1)";
  function setTransitionStyle(el, prop, duration, ease) {
    el.style.transition = prop ? `${prop} ${duration}ms ${ease || defaultCSSEasing}` : "none";
  }
  function setWidthHeight(el, w, h) {
    el.style.width = typeof w === "number" ? `${w}px` : w;
    el.style.height = typeof h === "number" ? `${h}px` : h;
  }
  function removeTransitionStyle(el) {
    setTransitionStyle(el);
  }
  function decodeImage(img) {
    if ("decode" in img) {
      return img.decode().catch(() => {
      });
    }
    if (img.complete) {
      return Promise.resolve(img);
    }
    return new Promise((resolve, reject) => {
      img.onload = () => resolve(img);
      img.onerror = reject;
    });
  }
  const LOAD_STATE = {
    IDLE: "idle",
    LOADING: "loading",
    LOADED: "loaded",
    ERROR: "error"
  };
  function specialKeyUsed(e) {
    return "button" in e && e.button === 1 || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey;
  }
  function getElementsFromOption(option, legacySelector, parent = document) {
    let elements = [];
    if (option instanceof Element) {
      elements = [option];
    } else if (option instanceof NodeList || Array.isArray(option)) {
      elements = Array.from(option);
    } else {
      const selector = typeof option === "string" ? option : legacySelector;
      if (selector) {
        elements = Array.from(parent.querySelectorAll(selector));
      }
    }
    return elements;
  }
  function isSafari() {
    return !!(navigator.vendor && navigator.vendor.match(/apple/i));
  }
  let supportsPassive = false;
  try {
    window.addEventListener("test", null, Object.defineProperty({}, "passive", {
      get: () => {
        supportsPassive = true;
      }
    }));
  } catch (e) {
  }
  class DOMEvents {
    constructor() {
      this._pool = [];
    }
add(target, type, listener, passive) {
      this._toggleListener(target, type, listener, passive);
    }
remove(target, type, listener, passive) {
      this._toggleListener(target, type, listener, passive, true);
    }
removeAll() {
      this._pool.forEach((poolItem) => {
        this._toggleListener(poolItem.target, poolItem.type, poolItem.listener, poolItem.passive, true, true);
      });
      this._pool = [];
    }
_toggleListener(target, type, listener, passive, unbind, skipPool) {
      if (!target) {
        return;
      }
      const methodName = unbind ? "removeEventListener" : "addEventListener";
      const types = type.split(" ");
      types.forEach((eType) => {
        if (eType) {
          if (!skipPool) {
            if (unbind) {
              this._pool = this._pool.filter((poolItem) => {
                return poolItem.type !== eType || poolItem.listener !== listener || poolItem.target !== target;
              });
            } else {
              this._pool.push({
                target,
                type: eType,
                listener,
                passive
              });
            }
          }
          const eventOptions = supportsPassive ? {
            passive: passive || false
          } : false;
          target[methodName](eType, listener, eventOptions);
        }
      });
    }
  }
  function getViewportSize(options, pswp) {
    if (options.getViewportSizeFn) {
      const newViewportSize = options.getViewportSizeFn(options, pswp);
      if (newViewportSize) {
        return newViewportSize;
      }
    }
    return {
      x: document.documentElement.clientWidth,



y: window.innerHeight
    };
  }
  function parsePaddingOption(prop, options, viewportSize, itemData, index) {
    let paddingValue = 0;
    if (options.paddingFn) {
      paddingValue = options.paddingFn(viewportSize, itemData, index)[prop];
    } else if (options.padding) {
      paddingValue = options.padding[prop];
    } else {
      const legacyPropName = "padding" + prop[0].toUpperCase() + prop.slice(1);
      if (options[legacyPropName]) {
        paddingValue = options[legacyPropName];
      }
    }
    return Number(paddingValue) || 0;
  }
  function getPanAreaSize(options, viewportSize, itemData, index) {
    return {
      x: viewportSize.x - parsePaddingOption("left", options, viewportSize, itemData, index) - parsePaddingOption("right", options, viewportSize, itemData, index),
      y: viewportSize.y - parsePaddingOption("top", options, viewportSize, itemData, index) - parsePaddingOption("bottom", options, viewportSize, itemData, index)
    };
  }
  class PanBounds {
constructor(slide) {
      this.slide = slide;
      this.currZoomLevel = 1;
      this.center =
{
        x: 0,
        y: 0
      };
      this.max =
{
        x: 0,
        y: 0
      };
      this.min =
{
        x: 0,
        y: 0
      };
    }
update(currZoomLevel) {
      this.currZoomLevel = currZoomLevel;
      if (!this.slide.width) {
        this.reset();
      } else {
        this._updateAxis("x");
        this._updateAxis("y");
        this.slide.pswp.dispatch("calcBounds", {
          slide: this.slide
        });
      }
    }
_updateAxis(axis) {
      const {
        pswp
      } = this.slide;
      const elSize = this.slide[axis === "x" ? "width" : "height"] * this.currZoomLevel;
      const paddingProp = axis === "x" ? "left" : "top";
      const padding = parsePaddingOption(paddingProp, pswp.options, pswp.viewportSize, this.slide.data, this.slide.index);
      const panAreaSize = this.slide.panAreaSize[axis];
      this.center[axis] = Math.round((panAreaSize - elSize) / 2) + padding;
      this.max[axis] = elSize > panAreaSize ? Math.round(panAreaSize - elSize) + padding : this.center[axis];
      this.min[axis] = elSize > panAreaSize ? padding : this.center[axis];
    }
reset() {
      this.center.x = 0;
      this.center.y = 0;
      this.max.x = 0;
      this.max.y = 0;
      this.min.x = 0;
      this.min.y = 0;
    }
correctPan(axis, panOffset) {
      return clamp(panOffset, this.max[axis], this.min[axis]);
    }
  }
  const MAX_IMAGE_WIDTH = 4e3;
  class ZoomLevel {
constructor(options, itemData, index, pswp) {
      this.pswp = pswp;
      this.options = options;
      this.itemData = itemData;
      this.index = index;
      this.panAreaSize = null;
      this.elementSize = null;
      this.fit = 1;
      this.fill = 1;
      this.vFill = 1;
      this.initial = 1;
      this.secondary = 1;
      this.max = 1;
      this.min = 1;
    }
update(maxWidth, maxHeight, panAreaSize) {
      const elementSize = {
        x: maxWidth,
        y: maxHeight
      };
      this.elementSize = elementSize;
      this.panAreaSize = panAreaSize;
      const hRatio = panAreaSize.x / elementSize.x;
      const vRatio = panAreaSize.y / elementSize.y;
      this.fit = Math.min(1, hRatio < vRatio ? hRatio : vRatio);
      this.fill = Math.min(1, hRatio > vRatio ? hRatio : vRatio);
      this.vFill = Math.min(1, vRatio);
      this.initial = this._getInitial();
      this.secondary = this._getSecondary();
      this.max = Math.max(this.initial, this.secondary, this._getMax());
      this.min = Math.min(this.fit, this.initial, this.secondary);
      if (this.pswp) {
        this.pswp.dispatch("zoomLevelsUpdate", {
          zoomLevels: this,
          slideData: this.itemData
        });
      }
    }
_parseZoomLevelOption(optionPrefix) {
      const optionName = (
optionPrefix + "ZoomLevel"
      );
      const optionValue = this.options[optionName];
      if (!optionValue) {
        return;
      }
      if (typeof optionValue === "function") {
        return optionValue(this);
      }
      if (optionValue === "fill") {
        return this.fill;
      }
      if (optionValue === "fit") {
        return this.fit;
      }
      return Number(optionValue);
    }
_getSecondary() {
      let currZoomLevel = this._parseZoomLevelOption("secondary");
      if (currZoomLevel) {
        return currZoomLevel;
      }
      currZoomLevel = Math.min(1, this.fit * 3);
      if (this.elementSize && currZoomLevel * this.elementSize.x > MAX_IMAGE_WIDTH) {
        currZoomLevel = MAX_IMAGE_WIDTH / this.elementSize.x;
      }
      return currZoomLevel;
    }
_getInitial() {
      return this._parseZoomLevelOption("initial") || this.fit;
    }
_getMax() {
      return this._parseZoomLevelOption("max") || Math.max(1, this.fit * 4);
    }
  }
  class Slide {
constructor(data, index, pswp) {
      this.data = data;
      this.index = index;
      this.pswp = pswp;
      this.isActive = index === pswp.currIndex;
      this.currentResolution = 0;
      this.panAreaSize = {
        x: 0,
        y: 0
      };
      this.pan = {
        x: 0,
        y: 0
      };
      this.isFirstSlide = this.isActive && !pswp.opener.isOpen;
      this.zoomLevels = new ZoomLevel(pswp.options, data, index, pswp);
      this.pswp.dispatch("gettingData", {
        slide: this,
        data: this.data,
        index
      });
      this.content = this.pswp.contentLoader.getContentBySlide(this);
      this.container = createElement("pswp__zoom-wrap", "div");
      this.holderElement = null;
      this.currZoomLevel = 1;
      this.width = this.content.width;
      this.height = this.content.height;
      this.heavyAppended = false;
      this.bounds = new PanBounds(this);
      this.prevDisplayedWidth = -1;
      this.prevDisplayedHeight = -1;
      this.pswp.dispatch("slideInit", {
        slide: this
      });
    }
setIsActive(isActive) {
      if (isActive && !this.isActive) {
        this.activate();
      } else if (!isActive && this.isActive) {
        this.deactivate();
      }
    }
append(holderElement) {
      this.holderElement = holderElement;
      this.container.style.transformOrigin = "0 0";
      if (!this.data) {
        return;
      }
      this.calculateSize();
      this.load();
      this.updateContentSize();
      this.appendHeavy();
      this.holderElement.appendChild(this.container);
      this.zoomAndPanToInitial();
      this.pswp.dispatch("firstZoomPan", {
        slide: this
      });
      this.applyCurrentZoomPan();
      this.pswp.dispatch("afterSetContent", {
        slide: this
      });
      if (this.isActive) {
        this.activate();
      }
    }
    load() {
      this.content.load(false);
      this.pswp.dispatch("slideLoad", {
        slide: this
      });
    }
appendHeavy() {
      const {
        pswp
      } = this;
      if (this.heavyAppended || !pswp.opener.isOpen || pswp.mainScroll.isShifted() || !this.isActive && false) {
        return;
      }
      if (this.pswp.dispatch("appendHeavy", {
        slide: this
      }).defaultPrevented) {
        return;
      }
      this.heavyAppended = true;
      this.content.append();
      this.pswp.dispatch("appendHeavyContent", {
        slide: this
      });
    }
activate() {
      this.isActive = true;
      this.appendHeavy();
      this.content.activate();
      this.pswp.dispatch("slideActivate", {
        slide: this
      });
    }
deactivate() {
      this.isActive = false;
      this.content.deactivate();
      if (this.currZoomLevel !== this.zoomLevels.initial) {
        this.calculateSize();
      }
      this.currentResolution = 0;
      this.zoomAndPanToInitial();
      this.applyCurrentZoomPan();
      this.updateContentSize();
      this.pswp.dispatch("slideDeactivate", {
        slide: this
      });
    }
destroy() {
      this.content.hasSlide = false;
      this.content.remove();
      this.container.remove();
      this.pswp.dispatch("slideDestroy", {
        slide: this
      });
    }
    resize() {
      if (this.currZoomLevel === this.zoomLevels.initial || !this.isActive) {
        this.calculateSize();
        this.currentResolution = 0;
        this.zoomAndPanToInitial();
        this.applyCurrentZoomPan();
        this.updateContentSize();
      } else {
        this.calculateSize();
        this.bounds.update(this.currZoomLevel);
        this.panTo(this.pan.x, this.pan.y);
      }
    }
updateContentSize(force) {
      const scaleMultiplier = this.currentResolution || this.zoomLevels.initial;
      if (!scaleMultiplier) {
        return;
      }
      const width = Math.round(this.width * scaleMultiplier) || this.pswp.viewportSize.x;
      const height = Math.round(this.height * scaleMultiplier) || this.pswp.viewportSize.y;
      if (!this.sizeChanged(width, height) && !force) {
        return;
      }
      this.content.setDisplayedSize(width, height);
    }
sizeChanged(width, height) {
      if (width !== this.prevDisplayedWidth || height !== this.prevDisplayedHeight) {
        this.prevDisplayedWidth = width;
        this.prevDisplayedHeight = height;
        return true;
      }
      return false;
    }
getPlaceholderElement() {
      var _this$content$placeho;
      return (_this$content$placeho = this.content.placeholder) === null || _this$content$placeho === void 0 ? void 0 : _this$content$placeho.element;
    }
zoomTo(destZoomLevel, centerPoint, transitionDuration, ignoreBounds) {
      const {
        pswp
      } = this;
      if (!this.isZoomable() || pswp.mainScroll.isShifted()) {
        return;
      }
      pswp.dispatch("beforeZoomTo", {
        destZoomLevel,
        centerPoint,
        transitionDuration
      });
      pswp.animations.stopAllPan();
      const prevZoomLevel = this.currZoomLevel;
      if (!ignoreBounds) {
        destZoomLevel = clamp(destZoomLevel, this.zoomLevels.min, this.zoomLevels.max);
      }
      this.setZoomLevel(destZoomLevel);
      this.pan.x = this.calculateZoomToPanOffset("x", centerPoint, prevZoomLevel);
      this.pan.y = this.calculateZoomToPanOffset("y", centerPoint, prevZoomLevel);
      roundPoint(this.pan);
      const finishTransition = () => {
        this._setResolution(destZoomLevel);
        this.applyCurrentZoomPan();
      };
      if (!transitionDuration) {
        finishTransition();
      } else {
        pswp.animations.startTransition({
          isPan: true,
          name: "zoomTo",
          target: this.container,
          transform: this.getCurrentTransform(),
          onComplete: finishTransition,
          duration: transitionDuration,
          easing: pswp.options.easing
        });
      }
    }
toggleZoom(centerPoint) {
      this.zoomTo(this.currZoomLevel === this.zoomLevels.initial ? this.zoomLevels.secondary : this.zoomLevels.initial, centerPoint, this.pswp.options.zoomAnimationDuration);
    }
setZoomLevel(currZoomLevel) {
      this.currZoomLevel = currZoomLevel;
      this.bounds.update(this.currZoomLevel);
    }
calculateZoomToPanOffset(axis, point, prevZoomLevel) {
      const totalPanDistance = this.bounds.max[axis] - this.bounds.min[axis];
      if (totalPanDistance === 0) {
        return this.bounds.center[axis];
      }
      if (!point) {
        point = this.pswp.getViewportCenterPoint();
      }
      if (!prevZoomLevel) {
        prevZoomLevel = this.zoomLevels.initial;
      }
      const zoomFactor = this.currZoomLevel / prevZoomLevel;
      return this.bounds.correctPan(axis, (this.pan[axis] - point[axis]) * zoomFactor + point[axis]);
    }
panTo(panX, panY) {
      this.pan.x = this.bounds.correctPan("x", panX);
      this.pan.y = this.bounds.correctPan("y", panY);
      this.applyCurrentZoomPan();
    }
isPannable() {
      return Boolean(this.width) && this.currZoomLevel > this.zoomLevels.fit;
    }
isZoomable() {
      return Boolean(this.width) && this.content.isZoomable();
    }
applyCurrentZoomPan() {
      this._applyZoomTransform(this.pan.x, this.pan.y, this.currZoomLevel);
      if (this === this.pswp.currSlide) {
        this.pswp.dispatch("zoomPanUpdate", {
          slide: this
        });
      }
    }
    zoomAndPanToInitial() {
      this.currZoomLevel = this.zoomLevels.initial;
      this.bounds.update(this.currZoomLevel);
      equalizePoints(this.pan, this.bounds.center);
      this.pswp.dispatch("initialZoomPan", {
        slide: this
      });
    }
_applyZoomTransform(x, y, zoom) {
      zoom /= this.currentResolution || this.zoomLevels.initial;
      setTransform(this.container, x, y, zoom);
    }
    calculateSize() {
      const {
        pswp
      } = this;
      equalizePoints(this.panAreaSize, getPanAreaSize(pswp.options, pswp.viewportSize, this.data, this.index));
      this.zoomLevels.update(this.width, this.height, this.panAreaSize);
      pswp.dispatch("calcSlideSize", {
        slide: this
      });
    }
getCurrentTransform() {
      const scale = this.currZoomLevel / (this.currentResolution || this.zoomLevels.initial);
      return toTransformString(this.pan.x, this.pan.y, scale);
    }
_setResolution(newResolution) {
      if (newResolution === this.currentResolution) {
        return;
      }
      this.currentResolution = newResolution;
      this.updateContentSize();
      this.pswp.dispatch("resolutionChanged");
    }
  }
  const PAN_END_FRICTION = 0.35;
  const VERTICAL_DRAG_FRICTION = 0.6;
  const MIN_RATIO_TO_CLOSE = 0.4;
  const MIN_NEXT_SLIDE_SPEED = 0.5;
  function project(initialVelocity, decelerationRate) {
    return initialVelocity * decelerationRate / (1 - decelerationRate);
  }
  class DragHandler {
constructor(gestures) {
      this.gestures = gestures;
      this.pswp = gestures.pswp;
      this.startPan = {
        x: 0,
        y: 0
      };
    }
    start() {
      if (this.pswp.currSlide) {
        equalizePoints(this.startPan, this.pswp.currSlide.pan);
      }
      this.pswp.animations.stopAll();
    }
    change() {
      const {
        p1,
        prevP1,
        dragAxis
      } = this.gestures;
      const {
        currSlide
      } = this.pswp;
      if (dragAxis === "y" && this.pswp.options.closeOnVerticalDrag && currSlide && currSlide.currZoomLevel <= currSlide.zoomLevels.fit && !this.gestures.isMultitouch) {
        const panY = currSlide.pan.y + (p1.y - prevP1.y);
        if (!this.pswp.dispatch("verticalDrag", {
          panY
        }).defaultPrevented) {
          this._setPanWithFriction("y", panY, VERTICAL_DRAG_FRICTION);
          const bgOpacity = 1 - Math.abs(this._getVerticalDragRatio(currSlide.pan.y));
          this.pswp.applyBgOpacity(bgOpacity);
          currSlide.applyCurrentZoomPan();
        }
      } else {
        const mainScrollChanged = this._panOrMoveMainScroll("x");
        if (!mainScrollChanged) {
          this._panOrMoveMainScroll("y");
          if (currSlide) {
            roundPoint(currSlide.pan);
            currSlide.applyCurrentZoomPan();
          }
        }
      }
    }
    end() {
      const {
        velocity
      } = this.gestures;
      const {
        mainScroll,
        currSlide
      } = this.pswp;
      let indexDiff = 0;
      this.pswp.animations.stopAll();
      if (mainScroll.isShifted()) {
        const mainScrollShiftDiff = mainScroll.x - mainScroll.getCurrSlideX();
        const currentSlideVisibilityRatio = mainScrollShiftDiff / this.pswp.viewportSize.x;
        if (velocity.x < -MIN_NEXT_SLIDE_SPEED && currentSlideVisibilityRatio < 0 || velocity.x < 0.1 && currentSlideVisibilityRatio < -0.5) {
          indexDiff = 1;
          velocity.x = Math.min(velocity.x, 0);
        } else if (velocity.x > MIN_NEXT_SLIDE_SPEED && currentSlideVisibilityRatio > 0 || velocity.x > -0.1 && currentSlideVisibilityRatio > 0.5) {
          indexDiff = -1;
          velocity.x = Math.max(velocity.x, 0);
        }
        mainScroll.moveIndexBy(indexDiff, true, velocity.x);
      }
      if (currSlide && currSlide.currZoomLevel > currSlide.zoomLevels.max || this.gestures.isMultitouch) {
        this.gestures.zoomLevels.correctZoomPan(true);
      } else {
        this._finishPanGestureForAxis("x");
        this._finishPanGestureForAxis("y");
      }
    }
_finishPanGestureForAxis(axis) {
      const {
        velocity
      } = this.gestures;
      const {
        currSlide
      } = this.pswp;
      if (!currSlide) {
        return;
      }
      const {
        pan,
        bounds
      } = currSlide;
      const panPos = pan[axis];
      const restoreBgOpacity = this.pswp.bgOpacity < 1 && axis === "y";
      const decelerationRate = 0.995;
      const projectedPosition = panPos + project(velocity[axis], decelerationRate);
      if (restoreBgOpacity) {
        const vDragRatio = this._getVerticalDragRatio(panPos);
        const projectedVDragRatio = this._getVerticalDragRatio(projectedPosition);
        if (vDragRatio < 0 && projectedVDragRatio < -MIN_RATIO_TO_CLOSE || vDragRatio > 0 && projectedVDragRatio > MIN_RATIO_TO_CLOSE) {
          this.pswp.close();
          return;
        }
      }
      const correctedPanPosition = bounds.correctPan(axis, projectedPosition);
      if (panPos === correctedPanPosition) {
        return;
      }
      const dampingRatio = correctedPanPosition === projectedPosition ? 1 : 0.82;
      const initialBgOpacity = this.pswp.bgOpacity;
      const totalPanDist = correctedPanPosition - panPos;
      this.pswp.animations.startSpring({
        name: "panGesture" + axis,
        isPan: true,
        start: panPos,
        end: correctedPanPosition,
        velocity: velocity[axis],
        dampingRatio,
        onUpdate: (pos) => {
          if (restoreBgOpacity && this.pswp.bgOpacity < 1) {
            const animationProgressRatio = 1 - (correctedPanPosition - pos) / totalPanDist;
            this.pswp.applyBgOpacity(clamp(initialBgOpacity + (1 - initialBgOpacity) * animationProgressRatio, 0, 1));
          }
          pan[axis] = Math.floor(pos);
          currSlide.applyCurrentZoomPan();
        }
      });
    }
_panOrMoveMainScroll(axis) {
      const {
        p1,
        dragAxis,
        prevP1,
        isMultitouch
      } = this.gestures;
      const {
        currSlide,
        mainScroll
      } = this.pswp;
      const delta = p1[axis] - prevP1[axis];
      const newMainScrollX = mainScroll.x + delta;
      if (!delta || !currSlide) {
        return false;
      }
      if (axis === "x" && !currSlide.isPannable() && !isMultitouch) {
        mainScroll.moveTo(newMainScrollX, true);
        return true;
      }
      const {
        bounds
      } = currSlide;
      const newPan = currSlide.pan[axis] + delta;
      if (this.pswp.options.allowPanToNext && dragAxis === "x" && axis === "x" && !isMultitouch) {
        const currSlideMainScrollX = mainScroll.getCurrSlideX();
        const mainScrollShiftDiff = mainScroll.x - currSlideMainScrollX;
        const isLeftToRight = delta > 0;
        const isRightToLeft = !isLeftToRight;
        if (newPan > bounds.min[axis] && isLeftToRight) {
          const wasAtMinPanPosition = bounds.min[axis] <= this.startPan[axis];
          if (wasAtMinPanPosition) {
            mainScroll.moveTo(newMainScrollX, true);
            return true;
          } else {
            this._setPanWithFriction(axis, newPan);
          }
        } else if (newPan < bounds.max[axis] && isRightToLeft) {
          const wasAtMaxPanPosition = this.startPan[axis] <= bounds.max[axis];
          if (wasAtMaxPanPosition) {
            mainScroll.moveTo(newMainScrollX, true);
            return true;
          } else {
            this._setPanWithFriction(axis, newPan);
          }
        } else {
          if (mainScrollShiftDiff !== 0) {
            if (mainScrollShiftDiff > 0) {
              mainScroll.moveTo(Math.max(newMainScrollX, currSlideMainScrollX), true);
              return true;
            } else if (mainScrollShiftDiff < 0) {
              mainScroll.moveTo(Math.min(newMainScrollX, currSlideMainScrollX), true);
              return true;
            }
          } else {
            this._setPanWithFriction(axis, newPan);
          }
        }
      } else {
        if (axis === "y") {
          if (!mainScroll.isShifted() && bounds.min.y !== bounds.max.y) {
            this._setPanWithFriction(axis, newPan);
          }
        } else {
          this._setPanWithFriction(axis, newPan);
        }
      }
      return false;
    }


_getVerticalDragRatio(panY) {
      var _this$pswp$currSlide$, _this$pswp$currSlide;
      return (panY - ((_this$pswp$currSlide$ = (_this$pswp$currSlide = this.pswp.currSlide) === null || _this$pswp$currSlide === void 0 ? void 0 : _this$pswp$currSlide.bounds.center.y) !== null && _this$pswp$currSlide$ !== void 0 ? _this$pswp$currSlide$ : 0)) / (this.pswp.viewportSize.y / 3);
    }
_setPanWithFriction(axis, potentialPan, customFriction) {
      const {
        currSlide
      } = this.pswp;
      if (!currSlide) {
        return;
      }
      const {
        pan,
        bounds
      } = currSlide;
      const correctedPan = bounds.correctPan(axis, potentialPan);
      if (correctedPan !== potentialPan || customFriction) {
        const delta = Math.round(potentialPan - pan[axis]);
        pan[axis] += delta * (customFriction || PAN_END_FRICTION);
      } else {
        pan[axis] = potentialPan;
      }
    }
  }
  const UPPER_ZOOM_FRICTION = 0.05;
  const LOWER_ZOOM_FRICTION = 0.15;
  function getZoomPointsCenter(p, p1, p2) {
    p.x = (p1.x + p2.x) / 2;
    p.y = (p1.y + p2.y) / 2;
    return p;
  }
  class ZoomHandler {
constructor(gestures) {
      this.gestures = gestures;
      this._startPan = {
        x: 0,
        y: 0
      };
      this._startZoomPoint = {
        x: 0,
        y: 0
      };
      this._zoomPoint = {
        x: 0,
        y: 0
      };
      this._wasOverFitZoomLevel = false;
      this._startZoomLevel = 1;
    }
    start() {
      const {
        currSlide
      } = this.gestures.pswp;
      if (currSlide) {
        this._startZoomLevel = currSlide.currZoomLevel;
        equalizePoints(this._startPan, currSlide.pan);
      }
      this.gestures.pswp.animations.stopAllPan();
      this._wasOverFitZoomLevel = false;
    }
    change() {
      const {
        p1,
        startP1,
        p2,
        startP2,
        pswp
      } = this.gestures;
      const {
        currSlide
      } = pswp;
      if (!currSlide) {
        return;
      }
      const minZoomLevel = currSlide.zoomLevels.min;
      const maxZoomLevel = currSlide.zoomLevels.max;
      if (!currSlide.isZoomable() || pswp.mainScroll.isShifted()) {
        return;
      }
      getZoomPointsCenter(this._startZoomPoint, startP1, startP2);
      getZoomPointsCenter(this._zoomPoint, p1, p2);
      let currZoomLevel = 1 / getDistanceBetween(startP1, startP2) * getDistanceBetween(p1, p2) * this._startZoomLevel;
      if (currZoomLevel > currSlide.zoomLevels.initial + currSlide.zoomLevels.initial / 15) {
        this._wasOverFitZoomLevel = true;
      }
      if (currZoomLevel < minZoomLevel) {
        if (pswp.options.pinchToClose && !this._wasOverFitZoomLevel && this._startZoomLevel <= currSlide.zoomLevels.initial) {
          const bgOpacity = 1 - (minZoomLevel - currZoomLevel) / (minZoomLevel / 1.2);
          if (!pswp.dispatch("pinchClose", {
            bgOpacity
          }).defaultPrevented) {
            pswp.applyBgOpacity(bgOpacity);
          }
        } else {
          currZoomLevel = minZoomLevel - (minZoomLevel - currZoomLevel) * LOWER_ZOOM_FRICTION;
        }
      } else if (currZoomLevel > maxZoomLevel) {
        currZoomLevel = maxZoomLevel + (currZoomLevel - maxZoomLevel) * UPPER_ZOOM_FRICTION;
      }
      currSlide.pan.x = this._calculatePanForZoomLevel("x", currZoomLevel);
      currSlide.pan.y = this._calculatePanForZoomLevel("y", currZoomLevel);
      currSlide.setZoomLevel(currZoomLevel);
      currSlide.applyCurrentZoomPan();
    }
    end() {
      const {
        pswp
      } = this.gestures;
      const {
        currSlide
      } = pswp;
      if ((!currSlide || currSlide.currZoomLevel < currSlide.zoomLevels.initial) && !this._wasOverFitZoomLevel && pswp.options.pinchToClose) {
        pswp.close();
      } else {
        this.correctZoomPan();
      }
    }
_calculatePanForZoomLevel(axis, currZoomLevel) {
      const zoomFactor = currZoomLevel / this._startZoomLevel;
      return this._zoomPoint[axis] - (this._startZoomPoint[axis] - this._startPan[axis]) * zoomFactor;
    }
correctZoomPan(ignoreGesture) {
      const {
        pswp
      } = this.gestures;
      const {
        currSlide
      } = pswp;
      if (!(currSlide !== null && currSlide !== void 0 && currSlide.isZoomable())) {
        return;
      }
      if (this._zoomPoint.x === 0) {
        ignoreGesture = true;
      }
      const prevZoomLevel = currSlide.currZoomLevel;
      let destinationZoomLevel;
      let currZoomLevelNeedsChange = true;
      if (prevZoomLevel < currSlide.zoomLevels.initial) {
        destinationZoomLevel = currSlide.zoomLevels.initial;
      } else if (prevZoomLevel > currSlide.zoomLevels.max) {
        destinationZoomLevel = currSlide.zoomLevels.max;
      } else {
        currZoomLevelNeedsChange = false;
        destinationZoomLevel = prevZoomLevel;
      }
      const initialBgOpacity = pswp.bgOpacity;
      const restoreBgOpacity = pswp.bgOpacity < 1;
      const initialPan = equalizePoints({
        x: 0,
        y: 0
      }, currSlide.pan);
      let destinationPan = equalizePoints({
        x: 0,
        y: 0
      }, initialPan);
      if (ignoreGesture) {
        this._zoomPoint.x = 0;
        this._zoomPoint.y = 0;
        this._startZoomPoint.x = 0;
        this._startZoomPoint.y = 0;
        this._startZoomLevel = prevZoomLevel;
        equalizePoints(this._startPan, initialPan);
      }
      if (currZoomLevelNeedsChange) {
        destinationPan = {
          x: this._calculatePanForZoomLevel("x", destinationZoomLevel),
          y: this._calculatePanForZoomLevel("y", destinationZoomLevel)
        };
      }
      currSlide.setZoomLevel(destinationZoomLevel);
      destinationPan = {
        x: currSlide.bounds.correctPan("x", destinationPan.x),
        y: currSlide.bounds.correctPan("y", destinationPan.y)
      };
      currSlide.setZoomLevel(prevZoomLevel);
      const panNeedsChange = !pointsEqual(destinationPan, initialPan);
      if (!panNeedsChange && !currZoomLevelNeedsChange && !restoreBgOpacity) {
        currSlide._setResolution(destinationZoomLevel);
        currSlide.applyCurrentZoomPan();
        return;
      }
      pswp.animations.stopAllPan();
      pswp.animations.startSpring({
        isPan: true,
        start: 0,
        end: 1e3,
        velocity: 0,
        dampingRatio: 1,
        naturalFrequency: 40,
        onUpdate: (now) => {
          now /= 1e3;
          if (panNeedsChange || currZoomLevelNeedsChange) {
            if (panNeedsChange) {
              currSlide.pan.x = initialPan.x + (destinationPan.x - initialPan.x) * now;
              currSlide.pan.y = initialPan.y + (destinationPan.y - initialPan.y) * now;
            }
            if (currZoomLevelNeedsChange) {
              const newZoomLevel = prevZoomLevel + (destinationZoomLevel - prevZoomLevel) * now;
              currSlide.setZoomLevel(newZoomLevel);
            }
            currSlide.applyCurrentZoomPan();
          }
          if (restoreBgOpacity && pswp.bgOpacity < 1) {
            pswp.applyBgOpacity(clamp(initialBgOpacity + (1 - initialBgOpacity) * now, 0, 1));
          }
        },
        onComplete: () => {
          currSlide._setResolution(destinationZoomLevel);
          currSlide.applyCurrentZoomPan();
        }
      });
    }
  }
  function didTapOnMainContent(event) {
    return !!
event.target.closest(".pswp__container");
  }
  class TapHandler {
constructor(gestures) {
      this.gestures = gestures;
    }
click(point, originalEvent) {
      const targetClassList = (
originalEvent.target.classList
      );
      const isImageClick = targetClassList.contains("pswp__img");
      const isBackgroundClick = targetClassList.contains("pswp__item") || targetClassList.contains("pswp__zoom-wrap");
      if (isImageClick) {
        this._doClickOrTapAction("imageClick", point, originalEvent);
      } else if (isBackgroundClick) {
        this._doClickOrTapAction("bgClick", point, originalEvent);
      }
    }
tap(point, originalEvent) {
      if (didTapOnMainContent(originalEvent)) {
        this._doClickOrTapAction("tap", point, originalEvent);
      }
    }
doubleTap(point, originalEvent) {
      if (didTapOnMainContent(originalEvent)) {
        this._doClickOrTapAction("doubleTap", point, originalEvent);
      }
    }
_doClickOrTapAction(actionName, point, originalEvent) {
      var _this$gestures$pswp$e;
      const {
        pswp
      } = this.gestures;
      const {
        currSlide
      } = pswp;
      const actionFullName = (
actionName + "Action"
      );
      const optionValue = pswp.options[actionFullName];
      if (pswp.dispatch(actionFullName, {
        point,
        originalEvent
      }).defaultPrevented) {
        return;
      }
      if (typeof optionValue === "function") {
        optionValue.call(pswp, point, originalEvent);
        return;
      }
      switch (optionValue) {
        case "close":
        case "next":
          pswp[optionValue]();
          break;
        case "zoom":
          currSlide === null || currSlide === void 0 || currSlide.toggleZoom(point);
          break;
        case "zoom-or-close":
          if (currSlide !== null && currSlide !== void 0 && currSlide.isZoomable() && currSlide.zoomLevels.secondary !== currSlide.zoomLevels.initial) {
            currSlide.toggleZoom(point);
          } else if (pswp.options.clickToCloseNonZoomable) {
            pswp.close();
          }
          break;
        case "toggle-controls":
          (_this$gestures$pswp$e = this.gestures.pswp.element) === null || _this$gestures$pswp$e === void 0 || _this$gestures$pswp$e.classList.toggle("pswp--ui-visible");
          break;
      }
    }
  }
  const AXIS_SWIPE_HYSTERISIS = 10;
  const DOUBLE_TAP_DELAY = 300;
  const MIN_TAP_DISTANCE = 25;
  class Gestures {
constructor(pswp) {
      this.pswp = pswp;
      this.dragAxis = null;
      this.p1 = {
        x: 0,
        y: 0
      };
      this.p2 = {
        x: 0,
        y: 0
      };
      this.prevP1 = {
        x: 0,
        y: 0
      };
      this.prevP2 = {
        x: 0,
        y: 0
      };
      this.startP1 = {
        x: 0,
        y: 0
      };
      this.startP2 = {
        x: 0,
        y: 0
      };
      this.velocity = {
        x: 0,
        y: 0
      };
      this._lastStartP1 = {
        x: 0,
        y: 0
      };
      this._intervalP1 = {
        x: 0,
        y: 0
      };
      this._numActivePoints = 0;
      this._ongoingPointers = [];
      this._touchEventEnabled = "ontouchstart" in window;
      this._pointerEventEnabled = !!window.PointerEvent;
      this.supportsTouch = this._touchEventEnabled || this._pointerEventEnabled && navigator.maxTouchPoints > 1;
      this._numActivePoints = 0;
      this._intervalTime = 0;
      this._velocityCalculated = false;
      this.isMultitouch = false;
      this.isDragging = false;
      this.isZooming = false;
      this.raf = null;
      this._tapTimer = null;
      if (!this.supportsTouch) {
        pswp.options.allowPanToNext = false;
      }
      this.drag = new DragHandler(this);
      this.zoomLevels = new ZoomHandler(this);
      this.tapHandler = new TapHandler(this);
      pswp.on("bindEvents", () => {
        pswp.events.add(
          pswp.scrollWrap,
          "click",
this._onClick.bind(this)
        );
        if (this._pointerEventEnabled) {
          this._bindEvents("pointer", "down", "up", "cancel");
        } else if (this._touchEventEnabled) {
          this._bindEvents("touch", "start", "end", "cancel");
          if (pswp.scrollWrap) {
            pswp.scrollWrap.ontouchmove = () => {
            };
            pswp.scrollWrap.ontouchend = () => {
            };
          }
        } else {
          this._bindEvents("mouse", "down", "up");
        }
      });
    }
_bindEvents(pref, down, up, cancel) {
      const {
        pswp
      } = this;
      const {
        events
      } = pswp;
      const cancelEvent = cancel ? pref + cancel : "";
      events.add(
        pswp.scrollWrap,
        pref + down,
this.onPointerDown.bind(this)
      );
      events.add(
        window,
        pref + "move",
this.onPointerMove.bind(this)
      );
      events.add(
        window,
        pref + up,
this.onPointerUp.bind(this)
      );
      if (cancelEvent) {
        events.add(
          pswp.scrollWrap,
          cancelEvent,
this.onPointerUp.bind(this)
        );
      }
    }
onPointerDown(e) {
      const isMousePointer = e.type === "mousedown" || e.pointerType === "mouse";
      if (isMousePointer && e.button > 0) {
        return;
      }
      const {
        pswp
      } = this;
      if (!pswp.opener.isOpen) {
        e.preventDefault();
        return;
      }
      if (pswp.dispatch("pointerDown", {
        originalEvent: e
      }).defaultPrevented) {
        return;
      }
      if (isMousePointer) {
        pswp.mouseDetected();
        this._preventPointerEventBehaviour(e, "down");
      }
      pswp.animations.stopAll();
      this._updatePoints(e, "down");
      if (this._numActivePoints === 1) {
        this.dragAxis = null;
        equalizePoints(this.startP1, this.p1);
      }
      if (this._numActivePoints > 1) {
        this._clearTapTimer();
        this.isMultitouch = true;
      } else {
        this.isMultitouch = false;
      }
    }
onPointerMove(e) {
      this._preventPointerEventBehaviour(e, "move");
      if (!this._numActivePoints) {
        return;
      }
      this._updatePoints(e, "move");
      if (this.pswp.dispatch("pointerMove", {
        originalEvent: e
      }).defaultPrevented) {
        return;
      }
      if (this._numActivePoints === 1 && !this.isDragging) {
        if (!this.dragAxis) {
          this._calculateDragDirection();
        }
        if (this.dragAxis && !this.isDragging) {
          if (this.isZooming) {
            this.isZooming = false;
            this.zoomLevels.end();
          }
          this.isDragging = true;
          this._clearTapTimer();
          this._updateStartPoints();
          this._intervalTime = Date.now();
          this._velocityCalculated = false;
          equalizePoints(this._intervalP1, this.p1);
          this.velocity.x = 0;
          this.velocity.y = 0;
          this.drag.start();
          this._rafStopLoop();
          this._rafRenderLoop();
        }
      } else if (this._numActivePoints > 1 && !this.isZooming) {
        this._finishDrag();
        this.isZooming = true;
        this._updateStartPoints();
        this.zoomLevels.start();
        this._rafStopLoop();
        this._rafRenderLoop();
      }
    }
_finishDrag() {
      if (this.isDragging) {
        this.isDragging = false;
        if (!this._velocityCalculated) {
          this._updateVelocity(true);
        }
        this.drag.end();
        this.dragAxis = null;
      }
    }
onPointerUp(e) {
      if (!this._numActivePoints) {
        return;
      }
      this._updatePoints(e, "up");
      if (this.pswp.dispatch("pointerUp", {
        originalEvent: e
      }).defaultPrevented) {
        return;
      }
      if (this._numActivePoints === 0) {
        this._rafStopLoop();
        if (this.isDragging) {
          this._finishDrag();
        } else if (!this.isZooming && !this.isMultitouch) {
          this._finishTap(e);
        }
      }
      if (this._numActivePoints < 2 && this.isZooming) {
        this.isZooming = false;
        this.zoomLevels.end();
        if (this._numActivePoints === 1) {
          this.dragAxis = null;
          this._updateStartPoints();
        }
      }
    }
_rafRenderLoop() {
      if (this.isDragging || this.isZooming) {
        this._updateVelocity();
        if (this.isDragging) {
          if (!pointsEqual(this.p1, this.prevP1)) {
            this.drag.change();
          }
        } else {
          if (!pointsEqual(this.p1, this.prevP1) || !pointsEqual(this.p2, this.prevP2)) {
            this.zoomLevels.change();
          }
        }
        this._updatePrevPoints();
        this.raf = requestAnimationFrame(this._rafRenderLoop.bind(this));
      }
    }
_updateVelocity(force) {
      const time = Date.now();
      const duration = time - this._intervalTime;
      if (duration < 50 && !force) {
        return;
      }
      this.velocity.x = this._getVelocity("x", duration);
      this.velocity.y = this._getVelocity("y", duration);
      this._intervalTime = time;
      equalizePoints(this._intervalP1, this.p1);
      this._velocityCalculated = true;
    }
_finishTap(e) {
      const {
        mainScroll
      } = this.pswp;
      if (mainScroll.isShifted()) {
        mainScroll.moveIndexBy(0, true);
        return;
      }
      if (e.type.indexOf("cancel") > 0) {
        return;
      }
      if (e.type === "mouseup" || e.pointerType === "mouse") {
        this.tapHandler.click(this.startP1, e);
        return;
      }
      const tapDelay = this.pswp.options.doubleTapAction ? DOUBLE_TAP_DELAY : 0;
      if (this._tapTimer) {
        this._clearTapTimer();
        if (getDistanceBetween(this._lastStartP1, this.startP1) < MIN_TAP_DISTANCE) {
          this.tapHandler.doubleTap(this.startP1, e);
        }
      } else {
        equalizePoints(this._lastStartP1, this.startP1);
        this._tapTimer = setTimeout(() => {
          this.tapHandler.tap(this.startP1, e);
          this._clearTapTimer();
        }, tapDelay);
      }
    }
_clearTapTimer() {
      if (this._tapTimer) {
        clearTimeout(this._tapTimer);
        this._tapTimer = null;
      }
    }
_getVelocity(axis, duration) {
      const displacement = this.p1[axis] - this._intervalP1[axis];
      if (Math.abs(displacement) > 1 && duration > 5) {
        return displacement / duration;
      }
      return 0;
    }
_rafStopLoop() {
      if (this.raf) {
        cancelAnimationFrame(this.raf);
        this.raf = null;
      }
    }
_preventPointerEventBehaviour(e, pointerType) {
      const preventPointerEvent = this.pswp.applyFilters("preventPointerEvent", true, e, pointerType);
      if (preventPointerEvent) {
        e.preventDefault();
      }
    }
_updatePoints(e, pointerType) {
      if (this._pointerEventEnabled) {
        const pointerEvent = (
e
        );
        const pointerIndex = this._ongoingPointers.findIndex((ongoingPointer) => {
          return ongoingPointer.id === pointerEvent.pointerId;
        });
        if (pointerType === "up" && pointerIndex > -1) {
          this._ongoingPointers.splice(pointerIndex, 1);
        } else if (pointerType === "down" && pointerIndex === -1) {
          this._ongoingPointers.push(this._convertEventPosToPoint(pointerEvent, {
            x: 0,
            y: 0
          }));
        } else if (pointerIndex > -1) {
          this._convertEventPosToPoint(pointerEvent, this._ongoingPointers[pointerIndex]);
        }
        this._numActivePoints = this._ongoingPointers.length;
        if (this._numActivePoints > 0) {
          equalizePoints(this.p1, this._ongoingPointers[0]);
        }
        if (this._numActivePoints > 1) {
          equalizePoints(this.p2, this._ongoingPointers[1]);
        }
      } else {
        const touchEvent = (
e
        );
        this._numActivePoints = 0;
        if (touchEvent.type.indexOf("touch") > -1) {
          if (touchEvent.touches && touchEvent.touches.length > 0) {
            this._convertEventPosToPoint(touchEvent.touches[0], this.p1);
            this._numActivePoints++;
            if (touchEvent.touches.length > 1) {
              this._convertEventPosToPoint(touchEvent.touches[1], this.p2);
              this._numActivePoints++;
            }
          }
        } else {
          this._convertEventPosToPoint(
e,
            this.p1
          );
          if (pointerType === "up") {
            this._numActivePoints = 0;
          } else {
            this._numActivePoints++;
          }
        }
      }
    }
_updatePrevPoints() {
      equalizePoints(this.prevP1, this.p1);
      equalizePoints(this.prevP2, this.p2);
    }
_updateStartPoints() {
      equalizePoints(this.startP1, this.p1);
      equalizePoints(this.startP2, this.p2);
      this._updatePrevPoints();
    }
_calculateDragDirection() {
      if (this.pswp.mainScroll.isShifted()) {
        this.dragAxis = "x";
      } else {
        const diff = Math.abs(this.p1.x - this.startP1.x) - Math.abs(this.p1.y - this.startP1.y);
        if (diff !== 0) {
          const axisToCheck = diff > 0 ? "x" : "y";
          if (Math.abs(this.p1[axisToCheck] - this.startP1[axisToCheck]) >= AXIS_SWIPE_HYSTERISIS) {
            this.dragAxis = axisToCheck;
          }
        }
      }
    }
_convertEventPosToPoint(e, p) {
      p.x = e.pageX - this.pswp.offset.x;
      p.y = e.pageY - this.pswp.offset.y;
      if ("pointerId" in e) {
        p.id = e.pointerId;
      } else if (e.identifier !== void 0) {
        p.id = e.identifier;
      }
      return p;
    }
_onClick(e) {
      if (this.pswp.mainScroll.isShifted()) {
        e.preventDefault();
        e.stopPropagation();
      }
    }
  }
  const MAIN_SCROLL_END_FRICTION = 0.35;
  class MainScroll {
constructor(pswp) {
      this.pswp = pswp;
      this.x = 0;
      this.slideWidth = 0;
      this._currPositionIndex = 0;
      this._prevPositionIndex = 0;
      this._containerShiftIndex = -1;
      this.itemHolders = [];
    }
resize(resizeSlides) {
      const {
        pswp
      } = this;
      const newSlideWidth = Math.round(pswp.viewportSize.x + pswp.viewportSize.x * pswp.options.spacing);
      const slideWidthChanged = newSlideWidth !== this.slideWidth;
      if (slideWidthChanged) {
        this.slideWidth = newSlideWidth;
        this.moveTo(this.getCurrSlideX());
      }
      this.itemHolders.forEach((itemHolder, index) => {
        if (slideWidthChanged) {
          setTransform(itemHolder.el, (index + this._containerShiftIndex) * this.slideWidth);
        }
        if (resizeSlides && itemHolder.slide) {
          itemHolder.slide.resize();
        }
      });
    }
resetPosition() {
      this._currPositionIndex = 0;
      this._prevPositionIndex = 0;
      this.slideWidth = 0;
      this._containerShiftIndex = -1;
    }
appendHolders() {
      this.itemHolders = [];
      for (let i = 0; i < 3; i++) {
        const el = createElement("pswp__item", "div", this.pswp.container);
        el.setAttribute("role", "group");
        el.setAttribute("aria-roledescription", "slide");
        el.setAttribute("aria-hidden", "true");
        el.style.display = i === 1 ? "block" : "none";
        this.itemHolders.push({
          el
});
      }
    }
canBeSwiped() {
      return this.pswp.getNumItems() > 1;
    }
moveIndexBy(diff, animate, velocityX) {
      const {
        pswp
      } = this;
      let newIndex = pswp.potentialIndex + diff;
      const numSlides = pswp.getNumItems();
      if (pswp.canLoop()) {
        newIndex = pswp.getLoopedIndex(newIndex);
        const distance = (diff + numSlides) % numSlides;
        if (distance <= numSlides / 2) {
          diff = distance;
        } else {
          diff = distance - numSlides;
        }
      } else {
        if (newIndex < 0) {
          newIndex = 0;
        } else if (newIndex >= numSlides) {
          newIndex = numSlides - 1;
        }
        diff = newIndex - pswp.potentialIndex;
      }
      pswp.potentialIndex = newIndex;
      this._currPositionIndex -= diff;
      pswp.animations.stopMainScroll();
      const destinationX = this.getCurrSlideX();
      if (!animate) {
        this.moveTo(destinationX);
        this.updateCurrItem();
      } else {
        pswp.animations.startSpring({
          isMainScroll: true,
          start: this.x,
          end: destinationX,
          velocity: velocityX || 0,
          naturalFrequency: 30,
          dampingRatio: 1,
onUpdate: (x) => {
            this.moveTo(x);
          },
          onComplete: () => {
            this.updateCurrItem();
            pswp.appendHeavy();
          }
        });
        let currDiff = pswp.potentialIndex - pswp.currIndex;
        if (pswp.canLoop()) {
          const currDistance = (currDiff + numSlides) % numSlides;
          if (currDistance <= numSlides / 2) {
            currDiff = currDistance;
          } else {
            currDiff = currDistance - numSlides;
          }
        }
        if (Math.abs(currDiff) > 1) {
          this.updateCurrItem();
        }
      }
      return Boolean(diff);
    }
getCurrSlideX() {
      return this.slideWidth * this._currPositionIndex;
    }
isShifted() {
      return this.x !== this.getCurrSlideX();
    }
updateCurrItem() {
      var _this$itemHolders$;
      const {
        pswp
      } = this;
      const positionDifference = this._prevPositionIndex - this._currPositionIndex;
      if (!positionDifference) {
        return;
      }
      this._prevPositionIndex = this._currPositionIndex;
      pswp.currIndex = pswp.potentialIndex;
      let diffAbs = Math.abs(positionDifference);
      let tempHolder;
      if (diffAbs >= 3) {
        this._containerShiftIndex += positionDifference + (positionDifference > 0 ? -3 : 3);
        diffAbs = 3;
        this.itemHolders.forEach((itemHolder) => {
          var _itemHolder$slide;
          (_itemHolder$slide = itemHolder.slide) === null || _itemHolder$slide === void 0 || _itemHolder$slide.destroy();
          itemHolder.slide = void 0;
        });
      }
      for (let i = 0; i < diffAbs; i++) {
        if (positionDifference > 0) {
          tempHolder = this.itemHolders.shift();
          if (tempHolder) {
            this.itemHolders[2] = tempHolder;
            this._containerShiftIndex++;
            setTransform(tempHolder.el, (this._containerShiftIndex + 2) * this.slideWidth);
            pswp.setContent(tempHolder, pswp.currIndex - diffAbs + i + 2);
          }
        } else {
          tempHolder = this.itemHolders.pop();
          if (tempHolder) {
            this.itemHolders.unshift(tempHolder);
            this._containerShiftIndex--;
            setTransform(tempHolder.el, this._containerShiftIndex * this.slideWidth);
            pswp.setContent(tempHolder, pswp.currIndex + diffAbs - i - 2);
          }
        }
      }
      if (Math.abs(this._containerShiftIndex) > 50 && !this.isShifted()) {
        this.resetPosition();
        this.resize();
      }
      pswp.animations.stopAllPan();
      this.itemHolders.forEach((itemHolder, i) => {
        if (itemHolder.slide) {
          itemHolder.slide.setIsActive(i === 1);
        }
      });
      pswp.currSlide = (_this$itemHolders$ = this.itemHolders[1]) === null || _this$itemHolders$ === void 0 ? void 0 : _this$itemHolders$.slide;
      pswp.contentLoader.updateLazy(positionDifference);
      if (pswp.currSlide) {
        pswp.currSlide.applyCurrentZoomPan();
      }
      pswp.dispatch("change");
    }
moveTo(x, dragging) {
      if (!this.pswp.canLoop() && dragging) {
        let newSlideIndexOffset = (this.slideWidth * this._currPositionIndex - x) / this.slideWidth;
        newSlideIndexOffset += this.pswp.currIndex;
        const delta = Math.round(x - this.x);
        if (newSlideIndexOffset < 0 && delta > 0 || newSlideIndexOffset >= this.pswp.getNumItems() - 1 && delta < 0) {
          x = this.x + delta * MAIN_SCROLL_END_FRICTION;
        }
      }
      this.x = x;
      if (this.pswp.container) {
        setTransform(this.pswp.container, x);
      }
      this.pswp.dispatch("moveMainScroll", {
        x,
        dragging: dragging !== null && dragging !== void 0 ? dragging : false
      });
    }
  }
  const KeyboardKeyCodesMap = {
    Escape: 27,
    z: 90,
    ArrowLeft: 37,
    ArrowUp: 38,
    ArrowRight: 39,
    ArrowDown: 40,
    Tab: 9
  };
  const getKeyboardEventKey = (key, isKeySupported) => {
    return isKeySupported ? key : KeyboardKeyCodesMap[key];
  };
  class Keyboard {
constructor(pswp) {
      this.pswp = pswp;
      this._wasFocused = false;
      pswp.on("bindEvents", () => {
        if (pswp.options.trapFocus) {
          if (!pswp.options.initialPointerPos) {
            this._focusRoot();
          }
          pswp.events.add(
            document,
            "focusin",
this._onFocusIn.bind(this)
          );
        }
        pswp.events.add(
          document,
          "keydown",
this._onKeyDown.bind(this)
        );
      });
      const lastActiveElement = (
document.activeElement
      );
      pswp.on("destroy", () => {
        if (pswp.options.returnFocus && lastActiveElement && this._wasFocused) {
          lastActiveElement.focus();
        }
      });
    }
_focusRoot() {
      if (!this._wasFocused && this.pswp.element) {
        this.pswp.element.focus();
        this._wasFocused = true;
      }
    }
_onKeyDown(e) {
      const {
        pswp
      } = this;
      if (pswp.dispatch("keydown", {
        originalEvent: e
      }).defaultPrevented) {
        return;
      }
      if (specialKeyUsed(e)) {
        return;
      }
      let keydownAction;
      let axis;
      let isForward = false;
      const isKeySupported = "key" in e;
      switch (isKeySupported ? e.key : e.keyCode) {
        case getKeyboardEventKey("Escape", isKeySupported):
          if (pswp.options.escKey) {
            keydownAction = "close";
          }
          break;
        case getKeyboardEventKey("z", isKeySupported):
          keydownAction = "toggleZoom";
          break;
        case getKeyboardEventKey("ArrowLeft", isKeySupported):
          axis = "x";
          break;
        case getKeyboardEventKey("ArrowUp", isKeySupported):
          axis = "y";
          break;
        case getKeyboardEventKey("ArrowRight", isKeySupported):
          axis = "x";
          isForward = true;
          break;
        case getKeyboardEventKey("ArrowDown", isKeySupported):
          isForward = true;
          axis = "y";
          break;
        case getKeyboardEventKey("Tab", isKeySupported):
          this._focusRoot();
          break;
      }
      if (axis) {
        e.preventDefault();
        const {
          currSlide
        } = pswp;
        if (pswp.options.arrowKeys && axis === "x" && pswp.getNumItems() > 1) {
          keydownAction = isForward ? "next" : "prev";
        } else if (currSlide && currSlide.currZoomLevel > currSlide.zoomLevels.fit) {
          currSlide.pan[axis] += isForward ? -80 : 80;
          currSlide.panTo(currSlide.pan.x, currSlide.pan.y);
        }
      }
      if (keydownAction) {
        e.preventDefault();
        pswp[keydownAction]();
      }
    }
_onFocusIn(e) {
      const {
        template
      } = this.pswp;
      if (template && document !== e.target && template !== e.target && !template.contains(
e.target
      )) {
        template.focus();
      }
    }
  }
  const DEFAULT_EASING = "cubic-bezier(.4,0,.22,1)";
  class CSSAnimation {
constructor(props) {
      var _props$prop;
      this.props = props;
      const {
        target,
        onComplete,
        transform,
        onFinish = () => {
        },
        duration = 333,
        easing = DEFAULT_EASING
      } = props;
      this.onFinish = onFinish;
      const prop = transform ? "transform" : "opacity";
      const propValue = (_props$prop = props[prop]) !== null && _props$prop !== void 0 ? _props$prop : "";
      this._target = target;
      this._onComplete = onComplete;
      this._finished = false;
      this._onTransitionEnd = this._onTransitionEnd.bind(this);
      this._helperTimeout = setTimeout(() => {
        setTransitionStyle(target, prop, duration, easing);
        this._helperTimeout = setTimeout(() => {
          target.addEventListener("transitionend", this._onTransitionEnd, false);
          target.addEventListener("transitioncancel", this._onTransitionEnd, false);
          this._helperTimeout = setTimeout(() => {
            this._finalizeAnimation();
          }, duration + 500);
          target.style[prop] = propValue;
        }, 30);
      }, 0);
    }
_onTransitionEnd(e) {
      if (e.target === this._target) {
        this._finalizeAnimation();
      }
    }
_finalizeAnimation() {
      if (!this._finished) {
        this._finished = true;
        this.onFinish();
        if (this._onComplete) {
          this._onComplete();
        }
      }
    }
destroy() {
      if (this._helperTimeout) {
        clearTimeout(this._helperTimeout);
      }
      removeTransitionStyle(this._target);
      this._target.removeEventListener("transitionend", this._onTransitionEnd, false);
      this._target.removeEventListener("transitioncancel", this._onTransitionEnd, false);
      if (!this._finished) {
        this._finalizeAnimation();
      }
    }
  }
  const DEFAULT_NATURAL_FREQUENCY = 12;
  const DEFAULT_DAMPING_RATIO = 0.75;
  class SpringEaser {
constructor(initialVelocity, dampingRatio, naturalFrequency) {
      this.velocity = initialVelocity * 1e3;
      this._dampingRatio = dampingRatio || DEFAULT_DAMPING_RATIO;
      this._naturalFrequency = naturalFrequency || DEFAULT_NATURAL_FREQUENCY;
      this._dampedFrequency = this._naturalFrequency;
      if (this._dampingRatio < 1) {
        this._dampedFrequency *= Math.sqrt(1 - this._dampingRatio * this._dampingRatio);
      }
    }
easeFrame(deltaPosition, deltaTime) {
      let displacement = 0;
      let coeff;
      deltaTime /= 1e3;
      const naturalDumpingPow = Math.E ** (-this._dampingRatio * this._naturalFrequency * deltaTime);
      if (this._dampingRatio === 1) {
        coeff = this.velocity + this._naturalFrequency * deltaPosition;
        displacement = (deltaPosition + coeff * deltaTime) * naturalDumpingPow;
        this.velocity = displacement * -this._naturalFrequency + coeff * naturalDumpingPow;
      } else if (this._dampingRatio < 1) {
        coeff = 1 / this._dampedFrequency * (this._dampingRatio * this._naturalFrequency * deltaPosition + this.velocity);
        const dumpedFCos = Math.cos(this._dampedFrequency * deltaTime);
        const dumpedFSin = Math.sin(this._dampedFrequency * deltaTime);
        displacement = naturalDumpingPow * (deltaPosition * dumpedFCos + coeff * dumpedFSin);
        this.velocity = displacement * -this._naturalFrequency * this._dampingRatio + naturalDumpingPow * (-this._dampedFrequency * deltaPosition * dumpedFSin + this._dampedFrequency * coeff * dumpedFCos);
      }
      return displacement;
    }
  }
  class SpringAnimation {
constructor(props) {
      this.props = props;
      this._raf = 0;
      const {
        start,
        end,
        velocity,
        onUpdate,
        onComplete,
        onFinish = () => {
        },
        dampingRatio,
        naturalFrequency
      } = props;
      this.onFinish = onFinish;
      const easer = new SpringEaser(velocity, dampingRatio, naturalFrequency);
      let prevTime = Date.now();
      let deltaPosition = start - end;
      const animationLoop = () => {
        if (this._raf) {
          deltaPosition = easer.easeFrame(deltaPosition, Date.now() - prevTime);
          if (Math.abs(deltaPosition) < 1 && Math.abs(easer.velocity) < 50) {
            onUpdate(end);
            if (onComplete) {
              onComplete();
            }
            this.onFinish();
          } else {
            prevTime = Date.now();
            onUpdate(deltaPosition + end);
            this._raf = requestAnimationFrame(animationLoop);
          }
        }
      };
      this._raf = requestAnimationFrame(animationLoop);
    }
destroy() {
      if (this._raf >= 0) {
        cancelAnimationFrame(this._raf);
      }
      this._raf = 0;
    }
  }
  class Animations {
    constructor() {
      this.activeAnimations = [];
    }
startSpring(props) {
      this._start(props, true);
    }
startTransition(props) {
      this._start(props);
    }
_start(props, isSpring) {
      const animation = isSpring ? new SpringAnimation(
props
      ) : new CSSAnimation(
props
      );
      this.activeAnimations.push(animation);
      animation.onFinish = () => this.stop(animation);
      return animation;
    }
stop(animation) {
      animation.destroy();
      const index = this.activeAnimations.indexOf(animation);
      if (index > -1) {
        this.activeAnimations.splice(index, 1);
      }
    }
    stopAll() {
      this.activeAnimations.forEach((animation) => {
        animation.destroy();
      });
      this.activeAnimations = [];
    }
stopAllPan() {
      this.activeAnimations = this.activeAnimations.filter((animation) => {
        if (animation.props.isPan) {
          animation.destroy();
          return false;
        }
        return true;
      });
    }
    stopMainScroll() {
      this.activeAnimations = this.activeAnimations.filter((animation) => {
        if (animation.props.isMainScroll) {
          animation.destroy();
          return false;
        }
        return true;
      });
    }






isPanRunning() {
      return this.activeAnimations.some((animation) => {
        return animation.props.isPan;
      });
    }
  }
  class ScrollWheel {
constructor(pswp) {
      this.pswp = pswp;
      pswp.events.add(
        pswp.element,
        "wheel",
this._onWheel.bind(this)
      );
    }
_onWheel(e) {
      e.preventDefault();
      const {
        currSlide
      } = this.pswp;
      let {
        deltaX,
        deltaY
      } = e;
      if (!currSlide) {
        return;
      }
      if (this.pswp.dispatch("wheel", {
        originalEvent: e
      }).defaultPrevented) {
        return;
      }
      if (e.ctrlKey || this.pswp.options.wheelToZoom) {
        if (currSlide.isZoomable()) {
          let zoomFactor = -deltaY;
          if (e.deltaMode === 1) {
            zoomFactor *= 0.05;
          } else {
            zoomFactor *= e.deltaMode ? 1 : 2e-3;
          }
          zoomFactor = 2 ** zoomFactor;
          const destZoomLevel = currSlide.currZoomLevel * zoomFactor;
          currSlide.zoomTo(destZoomLevel, {
            x: e.clientX,
            y: e.clientY
          });
        }
      } else {
        if (currSlide.isPannable()) {
          if (e.deltaMode === 1) {
            deltaX *= 18;
            deltaY *= 18;
          }
          currSlide.panTo(currSlide.pan.x - deltaX, currSlide.pan.y - deltaY);
        }
      }
    }
  }
  function addElementHTML(htmlData) {
    if (typeof htmlData === "string") {
      return htmlData;
    }
    if (!htmlData || !htmlData.isCustomSVG) {
      return "";
    }
    const svgData = htmlData;
    let out = '<svg aria-hidden="true" class="pswp__icn" viewBox="0 0 %d %d" width="%d" height="%d">';
    out = out.split("%d").join(
svgData.size || 32
    );
    if (svgData.outlineID) {
      out += '<use class="pswp__icn-shadow" xlink:href="#' + svgData.outlineID + '"/>';
    }
    out += svgData.inner;
    out += "</svg>";
    return out;
  }
  class UIElement {
constructor(pswp, data) {
      var _container;
      const name = data.name || data.className;
      let elementHTML = data.html;
      if (pswp.options[name] === false) {
        return;
      }
      if (typeof pswp.options[name + "SVG"] === "string") {
        elementHTML = pswp.options[name + "SVG"];
      }
      pswp.dispatch("uiElementCreate", {
        data
      });
      let className = "";
      if (data.isButton) {
        className += "pswp__button ";
        className += data.className || `pswp__button--${data.name}`;
      } else {
        className += data.className || `pswp__${data.name}`;
      }
      let tagName = data.isButton ? data.tagName || "button" : data.tagName || "div";
      tagName =
tagName.toLowerCase();
      const element = createElement(className, tagName);
      if (data.isButton) {
        if (tagName === "button") {
          element.type = "button";
        }
        let {
          title
        } = data;
        const {
          ariaLabel
        } = data;
        if (typeof pswp.options[name + "Title"] === "string") {
          title = pswp.options[name + "Title"];
        }
        if (title) {
          element.title = title;
        }
        const ariaText = ariaLabel || title;
        if (ariaText) {
          element.setAttribute("aria-label", ariaText);
        }
      }
      element.innerHTML = addElementHTML(elementHTML);
      if (data.onInit) {
        data.onInit(element, pswp);
      }
      if (data.onClick) {
        element.onclick = (e) => {
          if (typeof data.onClick === "string") {
            pswp[data.onClick]();
          } else if (typeof data.onClick === "function") {
            data.onClick(e, element, pswp);
          }
        };
      }
      const appendTo = data.appendTo || "bar";
      let container = pswp.element;
      if (appendTo === "bar") {
        if (!pswp.topBar) {
          pswp.topBar = createElement("pswp__top-bar pswp__hide-on-close", "div", pswp.scrollWrap);
        }
        container = pswp.topBar;
      } else {
        element.classList.add("pswp__hide-on-close");
        if (appendTo === "wrapper") {
          container = pswp.scrollWrap;
        }
      }
      (_container = container) === null || _container === void 0 || _container.appendChild(pswp.applyFilters("uiElement", element, data));
    }
  }
  function initArrowButton(element, pswp, isNextButton) {
    element.classList.add("pswp__button--arrow");
    element.setAttribute("aria-controls", "pswp__items");
    pswp.on("change", () => {
      if (!pswp.options.loop) {
        if (isNextButton) {
          element.disabled = !(pswp.currIndex < pswp.getNumItems() - 1);
        } else {
          element.disabled = !(pswp.currIndex > 0);
        }
      }
    });
  }
  const arrowPrev = {
    name: "arrowPrev",
    className: "pswp__button--arrow--prev",
    title: "Previous",
    order: 10,
    isButton: true,
    appendTo: "wrapper",
    html: {
      isCustomSVG: true,
      size: 60,
      inner: '<path d="M29 43l-3 3-16-16 16-16 3 3-13 13 13 13z" id="pswp__icn-arrow"/>',
      outlineID: "pswp__icn-arrow"
    },
    onClick: "prev",
    onInit: initArrowButton
  };
  const arrowNext = {
    name: "arrowNext",
    className: "pswp__button--arrow--next",
    title: "Next",
    order: 11,
    isButton: true,
    appendTo: "wrapper",
    html: {
      isCustomSVG: true,
      size: 60,
      inner: '<use xlink:href="#pswp__icn-arrow"/>',
      outlineID: "pswp__icn-arrow"
    },
    onClick: "next",
    onInit: (el, pswp) => {
      initArrowButton(el, pswp, true);
    }
  };
  const closeButton = {
    name: "close",
    title: "Close",
    order: 20,
    isButton: true,
    html: {
      isCustomSVG: true,
      inner: '<path d="M24 10l-2-2-6 6-6-6-2 2 6 6-6 6 2 2 6-6 6 6 2-2-6-6z" id="pswp__icn-close"/>',
      outlineID: "pswp__icn-close"
    },
    onClick: "close"
  };
  const zoomButton = {
    name: "zoom",
    title: "Zoom",
    order: 10,
    isButton: true,
    html: {
      isCustomSVG: true,
inner: '<path d="M17.426 19.926a6 6 0 1 1 1.5-1.5L23 22.5 21.5 24l-4.074-4.074z" id="pswp__icn-zoom"/><path fill="currentColor" class="pswp__zoom-icn-bar-h" d="M11 16v-2h6v2z"/><path fill="currentColor" class="pswp__zoom-icn-bar-v" d="M13 12h2v6h-2z"/>',
      outlineID: "pswp__icn-zoom"
    },
    onClick: "toggleZoom"
  };
  const loadingIndicator = {
    name: "preloader",
    appendTo: "bar",
    order: 7,
    html: {
      isCustomSVG: true,
inner: '<path fill-rule="evenodd" clip-rule="evenodd" d="M21.2 16a5.2 5.2 0 1 1-5.2-5.2V8a8 8 0 1 0 8 8h-2.8Z" id="pswp__icn-loading"/>',
      outlineID: "pswp__icn-loading"
    },
    onInit: (indicatorElement, pswp) => {
      let isVisible;
      let delayTimeout = null;
      const toggleIndicatorClass = (className, add) => {
        indicatorElement.classList.toggle("pswp__preloader--" + className, add);
      };
      const setIndicatorVisibility = (visible) => {
        if (isVisible !== visible) {
          isVisible = visible;
          toggleIndicatorClass("active", visible);
        }
      };
      const updatePreloaderVisibility = () => {
        var _pswp$currSlide;
        if (!((_pswp$currSlide = pswp.currSlide) !== null && _pswp$currSlide !== void 0 && _pswp$currSlide.content.isLoading())) {
          setIndicatorVisibility(false);
          if (delayTimeout) {
            clearTimeout(delayTimeout);
            delayTimeout = null;
          }
          return;
        }
        if (!delayTimeout) {
          delayTimeout = setTimeout(() => {
            var _pswp$currSlide2;
            setIndicatorVisibility(Boolean((_pswp$currSlide2 = pswp.currSlide) === null || _pswp$currSlide2 === void 0 ? void 0 : _pswp$currSlide2.content.isLoading()));
            delayTimeout = null;
          }, pswp.options.preloaderDelay);
        }
      };
      pswp.on("change", updatePreloaderVisibility);
      pswp.on("loadComplete", (e) => {
        if (pswp.currSlide === e.slide) {
          updatePreloaderVisibility();
        }
      });
      if (pswp.ui) {
        pswp.ui.updatePreloaderVisibility = updatePreloaderVisibility;
      }
    }
  };
  const counterIndicator = {
    name: "counter",
    order: 5,
    onInit: (counterElement, pswp) => {
      pswp.on("change", () => {
        counterElement.innerText = pswp.currIndex + 1 + pswp.options.indexIndicatorSep + pswp.getNumItems();
      });
    }
  };
  function setZoomedIn(el, isZoomedIn) {
    el.classList.toggle("pswp--zoomed-in", isZoomedIn);
  }
  class UI {
constructor(pswp) {
      this.pswp = pswp;
      this.isRegistered = false;
      this.uiElementsData = [];
      this.items = [];
      this.updatePreloaderVisibility = () => {
      };
      this._lastUpdatedZoomLevel = void 0;
    }
    init() {
      const {
        pswp
      } = this;
      this.isRegistered = false;
      this.uiElementsData = [closeButton, arrowPrev, arrowNext, zoomButton, loadingIndicator, counterIndicator];
      pswp.dispatch("uiRegister");
      this.uiElementsData.sort((a, b) => {
        return (a.order || 0) - (b.order || 0);
      });
      this.items = [];
      this.isRegistered = true;
      this.uiElementsData.forEach((uiElementData) => {
        this.registerElement(uiElementData);
      });
      pswp.on("change", () => {
        var _pswp$element;
        (_pswp$element = pswp.element) === null || _pswp$element === void 0 || _pswp$element.classList.toggle("pswp--one-slide", pswp.getNumItems() === 1);
      });
      pswp.on("zoomPanUpdate", () => this._onZoomPanUpdate());
    }
registerElement(elementData) {
      if (this.isRegistered) {
        this.items.push(new UIElement(this.pswp, elementData));
      } else {
        this.uiElementsData.push(elementData);
      }
    }
_onZoomPanUpdate() {
      const {
        template,
        currSlide,
        options
      } = this.pswp;
      if (this.pswp.opener.isClosing || !template || !currSlide) {
        return;
      }
      let {
        currZoomLevel
      } = currSlide;
      if (!this.pswp.opener.isOpen) {
        currZoomLevel = currSlide.zoomLevels.initial;
      }
      if (currZoomLevel === this._lastUpdatedZoomLevel) {
        return;
      }
      this._lastUpdatedZoomLevel = currZoomLevel;
      const currZoomLevelDiff = currSlide.zoomLevels.initial - currSlide.zoomLevels.secondary;
      if (Math.abs(currZoomLevelDiff) < 0.01 || !currSlide.isZoomable()) {
        setZoomedIn(template, false);
        template.classList.remove("pswp--zoom-allowed");
        return;
      }
      template.classList.add("pswp--zoom-allowed");
      const potentialZoomLevel = currZoomLevel === currSlide.zoomLevels.initial ? currSlide.zoomLevels.secondary : currSlide.zoomLevels.initial;
      setZoomedIn(template, potentialZoomLevel <= currZoomLevel);
      if (options.imageClickAction === "zoom" || options.imageClickAction === "zoom-or-close") {
        template.classList.add("pswp--click-to-zoom");
      }
    }
  }
  function getBoundsByElement(el) {
    const thumbAreaRect = el.getBoundingClientRect();
    return {
      x: thumbAreaRect.left,
      y: thumbAreaRect.top,
      w: thumbAreaRect.width
    };
  }
  function getCroppedBoundsByElement(el, imageWidth, imageHeight) {
    const thumbAreaRect = el.getBoundingClientRect();
    const hRatio = thumbAreaRect.width / imageWidth;
    const vRatio = thumbAreaRect.height / imageHeight;
    const fillZoomLevel = hRatio > vRatio ? hRatio : vRatio;
    const offsetX = (thumbAreaRect.width - imageWidth * fillZoomLevel) / 2;
    const offsetY = (thumbAreaRect.height - imageHeight * fillZoomLevel) / 2;
    const bounds = {
      x: thumbAreaRect.left + offsetX,
      y: thumbAreaRect.top + offsetY,
      w: imageWidth * fillZoomLevel
    };
    bounds.innerRect = {
      w: thumbAreaRect.width,
      h: thumbAreaRect.height,
      x: offsetX,
      y: offsetY
    };
    return bounds;
  }
  function getThumbBounds(index, itemData, instance) {
    const event = instance.dispatch("thumbBounds", {
      index,
      itemData,
      instance
    });
    if (event.thumbBounds) {
      return event.thumbBounds;
    }
    const {
      element
    } = itemData;
    let thumbBounds;
    let thumbnail;
    if (element && instance.options.thumbSelector !== false) {
      const thumbSelector = instance.options.thumbSelector || "img";
      thumbnail = element.matches(thumbSelector) ? element : (
element.querySelector(thumbSelector)
      );
    }
    thumbnail = instance.applyFilters("thumbEl", thumbnail, itemData, index);
    if (thumbnail) {
      if (!itemData.thumbCropped) {
        thumbBounds = getBoundsByElement(thumbnail);
      } else {
        thumbBounds = getCroppedBoundsByElement(thumbnail, itemData.width || itemData.w || 0, itemData.height || itemData.h || 0);
      }
    }
    return instance.applyFilters("thumbBounds", thumbBounds, itemData, index);
  }
  class PhotoSwipeEvent {
constructor(type, details) {
      this.type = type;
      this.defaultPrevented = false;
      if (details) {
        Object.assign(this, details);
      }
    }
    preventDefault() {
      this.defaultPrevented = true;
    }
  }
  class Eventable {
    constructor() {
      this._listeners = {};
      this._filters = {};
      this.pswp = void 0;
      this.options = void 0;
    }
addFilter(name, fn, priority = 100) {
      var _this$_filters$name, _this$_filters$name2, _this$pswp;
      if (!this._filters[name]) {
        this._filters[name] = [];
      }
      (_this$_filters$name = this._filters[name]) === null || _this$_filters$name === void 0 || _this$_filters$name.push({
        fn,
        priority
      });
      (_this$_filters$name2 = this._filters[name]) === null || _this$_filters$name2 === void 0 || _this$_filters$name2.sort((f1, f2) => f1.priority - f2.priority);
      (_this$pswp = this.pswp) === null || _this$pswp === void 0 || _this$pswp.addFilter(name, fn, priority);
    }
removeFilter(name, fn) {
      if (this._filters[name]) {
        this._filters[name] = this._filters[name].filter((filter) => filter.fn !== fn);
      }
      if (this.pswp) {
        this.pswp.removeFilter(name, fn);
      }
    }
applyFilters(name, ...args) {
      var _this$_filters$name3;
      (_this$_filters$name3 = this._filters[name]) === null || _this$_filters$name3 === void 0 || _this$_filters$name3.forEach((filter) => {
        args[0] = filter.fn.apply(this, args);
      });
      return args[0];
    }
on(name, fn) {
      var _this$_listeners$name, _this$pswp2;
      if (!this._listeners[name]) {
        this._listeners[name] = [];
      }
      (_this$_listeners$name = this._listeners[name]) === null || _this$_listeners$name === void 0 || _this$_listeners$name.push(fn);
      (_this$pswp2 = this.pswp) === null || _this$pswp2 === void 0 || _this$pswp2.on(name, fn);
    }
off(name, fn) {
      var _this$pswp3;
      if (this._listeners[name]) {
        this._listeners[name] = this._listeners[name].filter((listener) => fn !== listener);
      }
      (_this$pswp3 = this.pswp) === null || _this$pswp3 === void 0 || _this$pswp3.off(name, fn);
    }
dispatch(name, details) {
      var _this$_listeners$name2;
      if (this.pswp) {
        return this.pswp.dispatch(name, details);
      }
      const event = (
new PhotoSwipeEvent(name, details)
      );
      (_this$_listeners$name2 = this._listeners[name]) === null || _this$_listeners$name2 === void 0 || _this$_listeners$name2.forEach((listener) => {
        listener.call(this, event);
      });
      return event;
    }
  }
  class Placeholder {
constructor(imageSrc, container) {
      this.element = createElement("pswp__img pswp__img--placeholder", imageSrc ? "img" : "div", container);
      if (imageSrc) {
        const imgEl = (
this.element
        );
        imgEl.decoding = "async";
        imgEl.alt = "";
        imgEl.src = imageSrc;
        imgEl.setAttribute("role", "presentation");
      }
      this.element.setAttribute("aria-hidden", "true");
    }
setDisplayedSize(width, height) {
      if (!this.element) {
        return;
      }
      if (this.element.tagName === "IMG") {
        setWidthHeight(this.element, 250, "auto");
        this.element.style.transformOrigin = "0 0";
        this.element.style.transform = toTransformString(0, 0, width / 250);
      } else {
        setWidthHeight(this.element, width, height);
      }
    }
    destroy() {
      var _this$element;
      if ((_this$element = this.element) !== null && _this$element !== void 0 && _this$element.parentNode) {
        this.element.remove();
      }
      this.element = null;
    }
  }
  class Content {
constructor(itemData, instance, index) {
      this.instance = instance;
      this.data = itemData;
      this.index = index;
      this.element = void 0;
      this.placeholder = void 0;
      this.slide = void 0;
      this.displayedImageWidth = 0;
      this.displayedImageHeight = 0;
      this.width = Number(this.data.w) || Number(this.data.width) || 0;
      this.height = Number(this.data.h) || Number(this.data.height) || 0;
      this.isAttached = false;
      this.hasSlide = false;
      this.isDecoding = false;
      this.state = LOAD_STATE.IDLE;
      if (this.data.type) {
        this.type = this.data.type;
      } else if (this.data.src) {
        this.type = "image";
      } else {
        this.type = "html";
      }
      this.instance.dispatch("contentInit", {
        content: this
      });
    }
    removePlaceholder() {
      if (this.placeholder && !this.keepPlaceholder()) {
        setTimeout(() => {
          if (this.placeholder) {
            this.placeholder.destroy();
            this.placeholder = void 0;
          }
        }, 1e3);
      }
    }
load(isLazy, reload) {
      if (this.slide && this.usePlaceholder()) {
        if (!this.placeholder) {
          const placeholderSrc = this.instance.applyFilters(
            "placeholderSrc",

this.data.msrc && this.slide.isFirstSlide ? this.data.msrc : false,
            this
          );
          this.placeholder = new Placeholder(placeholderSrc, this.slide.container);
        } else {
          const placeholderEl = this.placeholder.element;
          if (placeholderEl && !placeholderEl.parentElement) {
            this.slide.container.prepend(placeholderEl);
          }
        }
      }
      if (this.element && !reload) {
        return;
      }
      if (this.instance.dispatch("contentLoad", {
        content: this,
        isLazy
      }).defaultPrevented) {
        return;
      }
      if (this.isImageContent()) {
        this.element = createElement("pswp__img", "img");
        if (this.displayedImageWidth) {
          this.loadImage(isLazy);
        }
      } else {
        this.element = createElement("pswp__content", "div");
        this.element.innerHTML = this.data.html || "";
      }
      if (reload && this.slide) {
        this.slide.updateContentSize(true);
      }
    }
loadImage(isLazy) {
      var _this$data$src, _this$data$alt;
      if (!this.isImageContent() || !this.element || this.instance.dispatch("contentLoadImage", {
        content: this,
        isLazy
      }).defaultPrevented) {
        return;
      }
      const imageElement = (
this.element
      );
      this.updateSrcsetSizes();
      if (this.data.srcset) {
        imageElement.srcset = this.data.srcset;
      }
      imageElement.src = (_this$data$src = this.data.src) !== null && _this$data$src !== void 0 ? _this$data$src : "";
      imageElement.alt = (_this$data$alt = this.data.alt) !== null && _this$data$alt !== void 0 ? _this$data$alt : "";
      this.state = LOAD_STATE.LOADING;
      if (imageElement.complete) {
        this.onLoaded();
      } else {
        imageElement.onload = () => {
          this.onLoaded();
        };
        imageElement.onerror = () => {
          this.onError();
        };
      }
    }
setSlide(slide) {
      this.slide = slide;
      this.hasSlide = true;
      this.instance = slide.pswp;
    }
onLoaded() {
      this.state = LOAD_STATE.LOADED;
      if (this.slide && this.element) {
        this.instance.dispatch("loadComplete", {
          slide: this.slide,
          content: this
        });
        if (this.slide.isActive && this.slide.heavyAppended && !this.element.parentNode) {
          this.append();
          this.slide.updateContentSize(true);
        }
        if (this.state === LOAD_STATE.LOADED || this.state === LOAD_STATE.ERROR) {
          this.removePlaceholder();
        }
      }
    }
onError() {
      this.state = LOAD_STATE.ERROR;
      if (this.slide) {
        this.displayError();
        this.instance.dispatch("loadComplete", {
          slide: this.slide,
          isError: true,
          content: this
        });
        this.instance.dispatch("loadError", {
          slide: this.slide,
          content: this
        });
      }
    }
isLoading() {
      return this.instance.applyFilters("isContentLoading", this.state === LOAD_STATE.LOADING, this);
    }
isError() {
      return this.state === LOAD_STATE.ERROR;
    }
isImageContent() {
      return this.type === "image";
    }
setDisplayedSize(width, height) {
      if (!this.element) {
        return;
      }
      if (this.placeholder) {
        this.placeholder.setDisplayedSize(width, height);
      }
      if (this.instance.dispatch("contentResize", {
        content: this,
        width,
        height
      }).defaultPrevented) {
        return;
      }
      setWidthHeight(this.element, width, height);
      if (this.isImageContent() && !this.isError()) {
        const isInitialSizeUpdate = !this.displayedImageWidth && width;
        this.displayedImageWidth = width;
        this.displayedImageHeight = height;
        if (isInitialSizeUpdate) {
          this.loadImage(false);
        } else {
          this.updateSrcsetSizes();
        }
        if (this.slide) {
          this.instance.dispatch("imageSizeChange", {
            slide: this.slide,
            width,
            height,
            content: this
          });
        }
      }
    }
isZoomable() {
      return this.instance.applyFilters("isContentZoomable", this.isImageContent() && this.state !== LOAD_STATE.ERROR, this);
    }
updateSrcsetSizes() {
      if (!this.isImageContent() || !this.element || !this.data.srcset) {
        return;
      }
      const image = (
this.element
      );
      const sizesWidth = this.instance.applyFilters("srcsetSizesWidth", this.displayedImageWidth, this);
      if (!image.dataset.largestUsedSize || sizesWidth > parseInt(image.dataset.largestUsedSize, 10)) {
        image.sizes = sizesWidth + "px";
        image.dataset.largestUsedSize = String(sizesWidth);
      }
    }
usePlaceholder() {
      return this.instance.applyFilters("useContentPlaceholder", this.isImageContent(), this);
    }
lazyLoad() {
      if (this.instance.dispatch("contentLazyLoad", {
        content: this
      }).defaultPrevented) {
        return;
      }
      this.load(true);
    }
keepPlaceholder() {
      return this.instance.applyFilters("isKeepingPlaceholder", this.isLoading(), this);
    }
destroy() {
      this.hasSlide = false;
      this.slide = void 0;
      if (this.instance.dispatch("contentDestroy", {
        content: this
      }).defaultPrevented) {
        return;
      }
      this.remove();
      if (this.placeholder) {
        this.placeholder.destroy();
        this.placeholder = void 0;
      }
      if (this.isImageContent() && this.element) {
        this.element.onload = null;
        this.element.onerror = null;
        this.element = void 0;
      }
    }
displayError() {
      if (this.slide) {
        var _this$instance$option, _this$instance$option2;
        let errorMsgEl = createElement("pswp__error-msg", "div");
        errorMsgEl.innerText = (_this$instance$option = (_this$instance$option2 = this.instance.options) === null || _this$instance$option2 === void 0 ? void 0 : _this$instance$option2.errorMsg) !== null && _this$instance$option !== void 0 ? _this$instance$option : "";
        errorMsgEl =
this.instance.applyFilters("contentErrorElement", errorMsgEl, this);
        this.element = createElement("pswp__content pswp__error-msg-container", "div");
        this.element.appendChild(errorMsgEl);
        this.slide.container.innerText = "";
        this.slide.container.appendChild(this.element);
        this.slide.updateContentSize(true);
        this.removePlaceholder();
      }
    }
append() {
      if (this.isAttached || !this.element) {
        return;
      }
      this.isAttached = true;
      if (this.state === LOAD_STATE.ERROR) {
        this.displayError();
        return;
      }
      if (this.instance.dispatch("contentAppend", {
        content: this
      }).defaultPrevented) {
        return;
      }
      const supportsDecode = "decode" in this.element;
      if (this.isImageContent()) {
        if (supportsDecode && this.slide && (!this.slide.isActive || isSafari())) {
          this.isDecoding = true;
          this.element.decode().catch(() => {
          }).finally(() => {
            this.isDecoding = false;
            this.appendImage();
          });
        } else {
          this.appendImage();
        }
      } else if (this.slide && !this.element.parentNode) {
        this.slide.container.appendChild(this.element);
      }
    }
activate() {
      if (this.instance.dispatch("contentActivate", {
        content: this
      }).defaultPrevented || !this.slide) {
        return;
      }
      if (this.isImageContent() && this.isDecoding && !isSafari()) {
        this.appendImage();
      } else if (this.isError()) {
        this.load(false, true);
      }
      if (this.slide.holderElement) {
        this.slide.holderElement.setAttribute("aria-hidden", "false");
      }
    }
deactivate() {
      this.instance.dispatch("contentDeactivate", {
        content: this
      });
      if (this.slide && this.slide.holderElement) {
        this.slide.holderElement.setAttribute("aria-hidden", "true");
      }
    }
remove() {
      this.isAttached = false;
      if (this.instance.dispatch("contentRemove", {
        content: this
      }).defaultPrevented) {
        return;
      }
      if (this.element && this.element.parentNode) {
        this.element.remove();
      }
      if (this.placeholder && this.placeholder.element) {
        this.placeholder.element.remove();
      }
    }
appendImage() {
      if (!this.isAttached) {
        return;
      }
      if (this.instance.dispatch("contentAppendImage", {
        content: this
      }).defaultPrevented) {
        return;
      }
      if (this.slide && this.element && !this.element.parentNode) {
        this.slide.container.appendChild(this.element);
      }
      if (this.state === LOAD_STATE.LOADED || this.state === LOAD_STATE.ERROR) {
        this.removePlaceholder();
      }
    }
  }
  const MIN_SLIDES_TO_CACHE = 5;
  function lazyLoadData(itemData, instance, index) {
    const content = instance.createContentFromData(itemData, index);
    let zoomLevel;
    const {
      options
    } = instance;
    if (options) {
      zoomLevel = new ZoomLevel(options, itemData, -1);
      let viewportSize;
      if (instance.pswp) {
        viewportSize = instance.pswp.viewportSize;
      } else {
        viewportSize = getViewportSize(options, instance);
      }
      const panAreaSize = getPanAreaSize(options, viewportSize, itemData, index);
      zoomLevel.update(content.width, content.height, panAreaSize);
    }
    content.lazyLoad();
    if (zoomLevel) {
      content.setDisplayedSize(Math.ceil(content.width * zoomLevel.initial), Math.ceil(content.height * zoomLevel.initial));
    }
    return content;
  }
  function lazyLoadSlide(index, instance) {
    const itemData = instance.getItemData(index);
    if (instance.dispatch("lazyLoadSlide", {
      index,
      itemData
    }).defaultPrevented) {
      return;
    }
    return lazyLoadData(itemData, instance, index);
  }
  class ContentLoader {
constructor(pswp) {
      this.pswp = pswp;
      this.limit = Math.max(pswp.options.preload[0] + pswp.options.preload[1] + 1, MIN_SLIDES_TO_CACHE);
      this._cachedItems = [];
    }
updateLazy(diff) {
      const {
        pswp
      } = this;
      if (pswp.dispatch("lazyLoad").defaultPrevented) {
        return;
      }
      const {
        preload
      } = pswp.options;
      const isForward = diff === void 0 ? true : diff >= 0;
      let i;
      for (i = 0; i <= preload[1]; i++) {
        this.loadSlideByIndex(pswp.currIndex + (isForward ? i : -i));
      }
      for (i = 1; i <= preload[0]; i++) {
        this.loadSlideByIndex(pswp.currIndex + (isForward ? -i : i));
      }
    }
loadSlideByIndex(initialIndex) {
      const index = this.pswp.getLoopedIndex(initialIndex);
      let content = this.getContentByIndex(index);
      if (!content) {
        content = lazyLoadSlide(index, this.pswp);
        if (content) {
          this.addToCache(content);
        }
      }
    }
getContentBySlide(slide) {
      let content = this.getContentByIndex(slide.index);
      if (!content) {
        content = this.pswp.createContentFromData(slide.data, slide.index);
        this.addToCache(content);
      }
      content.setSlide(slide);
      return content;
    }
addToCache(content) {
      this.removeByIndex(content.index);
      this._cachedItems.push(content);
      if (this._cachedItems.length > this.limit) {
        const indexToRemove = this._cachedItems.findIndex((item) => {
          return !item.isAttached && !item.hasSlide;
        });
        if (indexToRemove !== -1) {
          const removedItem = this._cachedItems.splice(indexToRemove, 1)[0];
          removedItem.destroy();
        }
      }
    }
removeByIndex(index) {
      const indexToRemove = this._cachedItems.findIndex((item) => item.index === index);
      if (indexToRemove !== -1) {
        this._cachedItems.splice(indexToRemove, 1);
      }
    }
getContentByIndex(index) {
      return this._cachedItems.find((content) => content.index === index);
    }
    destroy() {
      this._cachedItems.forEach((content) => content.destroy());
      this._cachedItems = [];
    }
  }
  class PhotoSwipeBase extends Eventable {
getNumItems() {
      var _this$options;
      let numItems = 0;
      const dataSource = (_this$options = this.options) === null || _this$options === void 0 ? void 0 : _this$options.dataSource;
      if (dataSource && "length" in dataSource) {
        numItems = dataSource.length;
      } else if (dataSource && "gallery" in dataSource) {
        if (!dataSource.items) {
          dataSource.items = this._getGalleryDOMElements(dataSource.gallery);
        }
        if (dataSource.items) {
          numItems = dataSource.items.length;
        }
      }
      const event = this.dispatch("numItems", {
        dataSource,
        numItems
      });
      return this.applyFilters("numItems", event.numItems, dataSource);
    }
createContentFromData(slideData, index) {
      return new Content(slideData, this, index);
    }
getItemData(index) {
      var _this$options2;
      const dataSource = (_this$options2 = this.options) === null || _this$options2 === void 0 ? void 0 : _this$options2.dataSource;
      let dataSourceItem = {};
      if (Array.isArray(dataSource)) {
        dataSourceItem = dataSource[index];
      } else if (dataSource && "gallery" in dataSource) {
        if (!dataSource.items) {
          dataSource.items = this._getGalleryDOMElements(dataSource.gallery);
        }
        dataSourceItem = dataSource.items[index];
      }
      let itemData = dataSourceItem;
      if (itemData instanceof Element) {
        itemData = this._domElementToItemData(itemData);
      }
      const event = this.dispatch("itemData", {
        itemData: itemData || {},
        index
      });
      return this.applyFilters("itemData", event.itemData, index);
    }
_getGalleryDOMElements(galleryElement) {
      var _this$options3, _this$options4;
      if ((_this$options3 = this.options) !== null && _this$options3 !== void 0 && _this$options3.children || (_this$options4 = this.options) !== null && _this$options4 !== void 0 && _this$options4.childSelector) {
        return getElementsFromOption(this.options.children, this.options.childSelector, galleryElement) || [];
      }
      return [galleryElement];
    }
_domElementToItemData(element) {
      const itemData = {
        element
      };
      const linkEl = (
element.tagName === "A" ? element : element.querySelector("a")
      );
      if (linkEl) {
        itemData.src = linkEl.dataset.pswpSrc || linkEl.href;
        if (linkEl.dataset.pswpSrcset) {
          itemData.srcset = linkEl.dataset.pswpSrcset;
        }
        itemData.width = linkEl.dataset.pswpWidth ? parseInt(linkEl.dataset.pswpWidth, 10) : 0;
        itemData.height = linkEl.dataset.pswpHeight ? parseInt(linkEl.dataset.pswpHeight, 10) : 0;
        itemData.w = itemData.width;
        itemData.h = itemData.height;
        if (linkEl.dataset.pswpType) {
          itemData.type = linkEl.dataset.pswpType;
        }
        const thumbnailEl = element.querySelector("img");
        if (thumbnailEl) {
          var _thumbnailEl$getAttri;
          itemData.msrc = thumbnailEl.currentSrc || thumbnailEl.src;
          itemData.alt = (_thumbnailEl$getAttri = thumbnailEl.getAttribute("alt")) !== null && _thumbnailEl$getAttri !== void 0 ? _thumbnailEl$getAttri : "";
        }
        if (linkEl.dataset.pswpCropped || linkEl.dataset.cropped) {
          itemData.thumbCropped = true;
        }
      }
      return this.applyFilters("domItemData", itemData, element, linkEl);
    }
lazyLoadData(itemData, index) {
      return lazyLoadData(itemData, this, index);
    }
  }
  const MIN_OPACITY = 3e-3;
  class Opener {
constructor(pswp) {
      this.pswp = pswp;
      this.isClosed = true;
      this.isOpen = false;
      this.isClosing = false;
      this.isOpening = false;
      this._duration = void 0;
      this._useAnimation = false;
      this._croppedZoom = false;
      this._animateRootOpacity = false;
      this._animateBgOpacity = false;
      this._placeholder = void 0;
      this._opacityElement = void 0;
      this._cropContainer1 = void 0;
      this._cropContainer2 = void 0;
      this._thumbBounds = void 0;
      this._prepareOpen = this._prepareOpen.bind(this);
      pswp.on("firstZoomPan", this._prepareOpen);
    }
    open() {
      this._prepareOpen();
      this._start();
    }
    close() {
      if (this.isClosed || this.isClosing || this.isOpening) {
        return;
      }
      const slide = this.pswp.currSlide;
      this.isOpen = false;
      this.isOpening = false;
      this.isClosing = true;
      this._duration = this.pswp.options.hideAnimationDuration;
      if (slide && slide.currZoomLevel * slide.width >= this.pswp.options.maxWidthToAnimate) {
        this._duration = 0;
      }
      this._applyStartProps();
      setTimeout(() => {
        this._start();
      }, this._croppedZoom ? 30 : 0);
    }
_prepareOpen() {
      this.pswp.off("firstZoomPan", this._prepareOpen);
      if (!this.isOpening) {
        const slide = this.pswp.currSlide;
        this.isOpening = true;
        this.isClosing = false;
        this._duration = this.pswp.options.showAnimationDuration;
        if (slide && slide.zoomLevels.initial * slide.width >= this.pswp.options.maxWidthToAnimate) {
          this._duration = 0;
        }
        this._applyStartProps();
      }
    }
_applyStartProps() {
      const {
        pswp
      } = this;
      const slide = this.pswp.currSlide;
      const {
        options
      } = pswp;
      if (options.showHideAnimationType === "fade") {
        options.showHideOpacity = true;
        this._thumbBounds = void 0;
      } else if (options.showHideAnimationType === "none") {
        options.showHideOpacity = false;
        this._duration = 0;
        this._thumbBounds = void 0;
      } else if (this.isOpening && pswp._initialThumbBounds) {
        this._thumbBounds = pswp._initialThumbBounds;
      } else {
        this._thumbBounds = this.pswp.getThumbBounds();
      }
      this._placeholder = slide === null || slide === void 0 ? void 0 : slide.getPlaceholderElement();
      pswp.animations.stopAll();
      this._useAnimation = Boolean(this._duration && this._duration > 50);
      this._animateZoom = Boolean(this._thumbBounds) && (slide === null || slide === void 0 ? void 0 : slide.content.usePlaceholder()) && (!this.isClosing || !pswp.mainScroll.isShifted());
      if (!this._animateZoom) {
        this._animateRootOpacity = true;
        if (this.isOpening && slide) {
          slide.zoomAndPanToInitial();
          slide.applyCurrentZoomPan();
        }
      } else {
        var _options$showHideOpac;
        this._animateRootOpacity = (_options$showHideOpac = options.showHideOpacity) !== null && _options$showHideOpac !== void 0 ? _options$showHideOpac : false;
      }
      this._animateBgOpacity = !this._animateRootOpacity && this.pswp.options.bgOpacity > MIN_OPACITY;
      this._opacityElement = this._animateRootOpacity ? pswp.element : pswp.bg;
      if (!this._useAnimation) {
        this._duration = 0;
        this._animateZoom = false;
        this._animateBgOpacity = false;
        this._animateRootOpacity = true;
        if (this.isOpening) {
          if (pswp.element) {
            pswp.element.style.opacity = String(MIN_OPACITY);
          }
          pswp.applyBgOpacity(1);
        }
        return;
      }
      if (this._animateZoom && this._thumbBounds && this._thumbBounds.innerRect) {
        var _this$pswp$currSlide;
        this._croppedZoom = true;
        this._cropContainer1 = this.pswp.container;
        this._cropContainer2 = (_this$pswp$currSlide = this.pswp.currSlide) === null || _this$pswp$currSlide === void 0 ? void 0 : _this$pswp$currSlide.holderElement;
        if (pswp.container) {
          pswp.container.style.overflow = "hidden";
          pswp.container.style.width = pswp.viewportSize.x + "px";
        }
      } else {
        this._croppedZoom = false;
      }
      if (this.isOpening) {
        if (this._animateRootOpacity) {
          if (pswp.element) {
            pswp.element.style.opacity = String(MIN_OPACITY);
          }
          pswp.applyBgOpacity(1);
        } else {
          if (this._animateBgOpacity && pswp.bg) {
            pswp.bg.style.opacity = String(MIN_OPACITY);
          }
          if (pswp.element) {
            pswp.element.style.opacity = "1";
          }
        }
        if (this._animateZoom) {
          this._setClosedStateZoomPan();
          if (this._placeholder) {
            this._placeholder.style.willChange = "transform";
            this._placeholder.style.opacity = String(MIN_OPACITY);
          }
        }
      } else if (this.isClosing) {
        if (pswp.mainScroll.itemHolders[0]) {
          pswp.mainScroll.itemHolders[0].el.style.display = "none";
        }
        if (pswp.mainScroll.itemHolders[2]) {
          pswp.mainScroll.itemHolders[2].el.style.display = "none";
        }
        if (this._croppedZoom) {
          if (pswp.mainScroll.x !== 0) {
            pswp.mainScroll.resetPosition();
            pswp.mainScroll.resize();
          }
        }
      }
    }
_start() {
      if (this.isOpening && this._useAnimation && this._placeholder && this._placeholder.tagName === "IMG") {
        new Promise((resolve) => {
          let decoded = false;
          let isDelaying = true;
          decodeImage(
this._placeholder
          ).finally(() => {
            decoded = true;
            if (!isDelaying) {
              resolve(true);
            }
          });
          setTimeout(() => {
            isDelaying = false;
            if (decoded) {
              resolve(true);
            }
          }, 50);
          setTimeout(resolve, 250);
        }).finally(() => this._initiate());
      } else {
        this._initiate();
      }
    }
_initiate() {
      var _this$pswp$element, _this$pswp$element2;
      (_this$pswp$element = this.pswp.element) === null || _this$pswp$element === void 0 || _this$pswp$element.style.setProperty("--pswp-transition-duration", this._duration + "ms");
      this.pswp.dispatch(this.isOpening ? "openingAnimationStart" : "closingAnimationStart");
      this.pswp.dispatch(
"initialZoom" + (this.isOpening ? "In" : "Out")
      );
      (_this$pswp$element2 = this.pswp.element) === null || _this$pswp$element2 === void 0 || _this$pswp$element2.classList.toggle("pswp--ui-visible", this.isOpening);
      if (this.isOpening) {
        if (this._placeholder) {
          this._placeholder.style.opacity = "1";
        }
        this._animateToOpenState();
      } else if (this.isClosing) {
        this._animateToClosedState();
      }
      if (!this._useAnimation) {
        this._onAnimationComplete();
      }
    }
_onAnimationComplete() {
      const {
        pswp
      } = this;
      this.isOpen = this.isOpening;
      this.isClosed = this.isClosing;
      this.isOpening = false;
      this.isClosing = false;
      pswp.dispatch(this.isOpen ? "openingAnimationEnd" : "closingAnimationEnd");
      pswp.dispatch(
"initialZoom" + (this.isOpen ? "InEnd" : "OutEnd")
      );
      if (this.isClosed) {
        pswp.destroy();
      } else if (this.isOpen) {
        var _pswp$currSlide;
        if (this._animateZoom && pswp.container) {
          pswp.container.style.overflow = "visible";
          pswp.container.style.width = "100%";
        }
        (_pswp$currSlide = pswp.currSlide) === null || _pswp$currSlide === void 0 || _pswp$currSlide.applyCurrentZoomPan();
      }
    }
_animateToOpenState() {
      const {
        pswp
      } = this;
      if (this._animateZoom) {
        if (this._croppedZoom && this._cropContainer1 && this._cropContainer2) {
          this._animateTo(this._cropContainer1, "transform", "translate3d(0,0,0)");
          this._animateTo(this._cropContainer2, "transform", "none");
        }
        if (pswp.currSlide) {
          pswp.currSlide.zoomAndPanToInitial();
          this._animateTo(pswp.currSlide.container, "transform", pswp.currSlide.getCurrentTransform());
        }
      }
      if (this._animateBgOpacity && pswp.bg) {
        this._animateTo(pswp.bg, "opacity", String(pswp.options.bgOpacity));
      }
      if (this._animateRootOpacity && pswp.element) {
        this._animateTo(pswp.element, "opacity", "1");
      }
    }
_animateToClosedState() {
      const {
        pswp
      } = this;
      if (this._animateZoom) {
        this._setClosedStateZoomPan(true);
      }
      if (this._animateBgOpacity && pswp.bgOpacity > 0.01 && pswp.bg) {
        this._animateTo(pswp.bg, "opacity", "0");
      }
      if (this._animateRootOpacity && pswp.element) {
        this._animateTo(pswp.element, "opacity", "0");
      }
    }
_setClosedStateZoomPan(animate) {
      if (!this._thumbBounds) return;
      const {
        pswp
      } = this;
      const {
        innerRect
      } = this._thumbBounds;
      const {
        currSlide,
        viewportSize
      } = pswp;
      if (this._croppedZoom && innerRect && this._cropContainer1 && this._cropContainer2) {
        const containerOnePanX = -viewportSize.x + (this._thumbBounds.x - innerRect.x) + innerRect.w;
        const containerOnePanY = -viewportSize.y + (this._thumbBounds.y - innerRect.y) + innerRect.h;
        const containerTwoPanX = viewportSize.x - innerRect.w;
        const containerTwoPanY = viewportSize.y - innerRect.h;
        if (animate) {
          this._animateTo(this._cropContainer1, "transform", toTransformString(containerOnePanX, containerOnePanY));
          this._animateTo(this._cropContainer2, "transform", toTransformString(containerTwoPanX, containerTwoPanY));
        } else {
          setTransform(this._cropContainer1, containerOnePanX, containerOnePanY);
          setTransform(this._cropContainer2, containerTwoPanX, containerTwoPanY);
        }
      }
      if (currSlide) {
        equalizePoints(currSlide.pan, innerRect || this._thumbBounds);
        currSlide.currZoomLevel = this._thumbBounds.w / currSlide.width;
        if (animate) {
          this._animateTo(currSlide.container, "transform", currSlide.getCurrentTransform());
        } else {
          currSlide.applyCurrentZoomPan();
        }
      }
    }
_animateTo(target, prop, propValue) {
      if (!this._duration) {
        target.style[prop] = propValue;
        return;
      }
      const {
        animations
      } = this.pswp;
      const animProps = {
        duration: this._duration,
        easing: this.pswp.options.easing,
        onComplete: () => {
          if (!animations.activeAnimations.length) {
            this._onAnimationComplete();
          }
        },
        target
      };
      animProps[prop] = propValue;
      animations.startTransition(animProps);
    }
  }
  const defaultOptions = {
    allowPanToNext: true,
    spacing: 0.1,
    loop: true,
    pinchToClose: true,
    closeOnVerticalDrag: true,
    hideAnimationDuration: 333,
    showAnimationDuration: 333,
    zoomAnimationDuration: 333,
    escKey: true,
    arrowKeys: true,
    trapFocus: true,
    returnFocus: true,
    maxWidthToAnimate: 4e3,
    clickToCloseNonZoomable: true,
    imageClickAction: "zoom-or-close",
    bgClickAction: "close",
    tapAction: "toggle-controls",
    doubleTapAction: "zoom",
    indexIndicatorSep: " / ",
    preloaderDelay: 2e3,
    bgOpacity: 0.8,
    index: 0,
    errorMsg: "The image cannot be loaded",
    preload: [1, 2],
    easing: "cubic-bezier(.4,0,.22,1)"
  };
  class PhotoSwipe extends PhotoSwipeBase {
constructor(options) {
      super();
      this.options = this._prepareOptions(options || {});
      this.offset = {
        x: 0,
        y: 0
      };
      this._prevViewportSize = {
        x: 0,
        y: 0
      };
      this.viewportSize = {
        x: 0,
        y: 0
      };
      this.bgOpacity = 1;
      this.currIndex = 0;
      this.potentialIndex = 0;
      this.isOpen = false;
      this.isDestroying = false;
      this.hasMouse = false;
      this._initialItemData = {};
      this._initialThumbBounds = void 0;
      this.topBar = void 0;
      this.element = void 0;
      this.template = void 0;
      this.container = void 0;
      this.scrollWrap = void 0;
      this.currSlide = void 0;
      this.events = new DOMEvents();
      this.animations = new Animations();
      this.mainScroll = new MainScroll(this);
      this.gestures = new Gestures(this);
      this.opener = new Opener(this);
      this.keyboard = new Keyboard(this);
      this.contentLoader = new ContentLoader(this);
    }
init() {
      if (this.isOpen || this.isDestroying) {
        return false;
      }
      this.isOpen = true;
      this.dispatch("init");
      this.dispatch("beforeOpen");
      this._createMainStructure();
      let rootClasses = "pswp--open";
      if (this.gestures.supportsTouch) {
        rootClasses += " pswp--touch";
      }
      if (this.options.mainClass) {
        rootClasses += " " + this.options.mainClass;
      }
      if (this.element) {
        this.element.className += " " + rootClasses;
      }
      this.currIndex = this.options.index || 0;
      this.potentialIndex = this.currIndex;
      this.dispatch("firstUpdate");
      this.scrollWheel = new ScrollWheel(this);
      if (Number.isNaN(this.currIndex) || this.currIndex < 0 || this.currIndex >= this.getNumItems()) {
        this.currIndex = 0;
      }
      if (!this.gestures.supportsTouch) {
        this.mouseDetected();
      }
      this.updateSize();
      this.offset.y = window.pageYOffset;
      this._initialItemData = this.getItemData(this.currIndex);
      this.dispatch("gettingData", {
        index: this.currIndex,
        data: this._initialItemData,
        slide: void 0
      });
      this._initialThumbBounds = this.getThumbBounds();
      this.dispatch("initialLayout");
      this.on("openingAnimationEnd", () => {
        const {
          itemHolders
        } = this.mainScroll;
        if (itemHolders[0]) {
          itemHolders[0].el.style.display = "block";
          this.setContent(itemHolders[0], this.currIndex - 1);
        }
        if (itemHolders[2]) {
          itemHolders[2].el.style.display = "block";
          this.setContent(itemHolders[2], this.currIndex + 1);
        }
        this.appendHeavy();
        this.contentLoader.updateLazy();
        this.events.add(window, "resize", this._handlePageResize.bind(this));
        this.events.add(window, "scroll", this._updatePageScrollOffset.bind(this));
        this.dispatch("bindEvents");
      });
      if (this.mainScroll.itemHolders[1]) {
        this.setContent(this.mainScroll.itemHolders[1], this.currIndex);
      }
      this.dispatch("change");
      this.opener.open();
      this.dispatch("afterInit");
      return true;
    }
getLoopedIndex(index) {
      const numSlides = this.getNumItems();
      if (this.options.loop) {
        if (index > numSlides - 1) {
          index -= numSlides;
        }
        if (index < 0) {
          index += numSlides;
        }
      }
      return clamp(index, 0, numSlides - 1);
    }
    appendHeavy() {
      this.mainScroll.itemHolders.forEach((itemHolder) => {
        var _itemHolder$slide;
        (_itemHolder$slide = itemHolder.slide) === null || _itemHolder$slide === void 0 || _itemHolder$slide.appendHeavy();
      });
    }
goTo(index) {
      this.mainScroll.moveIndexBy(this.getLoopedIndex(index) - this.potentialIndex);
    }
next() {
      this.goTo(this.potentialIndex + 1);
    }
prev() {
      this.goTo(this.potentialIndex - 1);
    }
zoomTo(...args) {
      var _this$currSlide;
      (_this$currSlide = this.currSlide) === null || _this$currSlide === void 0 || _this$currSlide.zoomTo(...args);
    }
toggleZoom() {
      var _this$currSlide2;
      (_this$currSlide2 = this.currSlide) === null || _this$currSlide2 === void 0 || _this$currSlide2.toggleZoom();
    }
close() {
      if (!this.opener.isOpen || this.isDestroying) {
        return;
      }
      this.isDestroying = true;
      this.dispatch("close");
      this.events.removeAll();
      this.opener.close();
    }
destroy() {
      var _this$element;
      if (!this.isDestroying) {
        this.options.showHideAnimationType = "none";
        this.close();
        return;
      }
      this.dispatch("destroy");
      this._listeners = {};
      if (this.scrollWrap) {
        this.scrollWrap.ontouchmove = null;
        this.scrollWrap.ontouchend = null;
      }
      (_this$element = this.element) === null || _this$element === void 0 || _this$element.remove();
      this.mainScroll.itemHolders.forEach((itemHolder) => {
        var _itemHolder$slide2;
        (_itemHolder$slide2 = itemHolder.slide) === null || _itemHolder$slide2 === void 0 || _itemHolder$slide2.destroy();
      });
      this.contentLoader.destroy();
      this.events.removeAll();
    }
refreshSlideContent(slideIndex) {
      this.contentLoader.removeByIndex(slideIndex);
      this.mainScroll.itemHolders.forEach((itemHolder, i) => {
        var _this$currSlide$index, _this$currSlide3;
        let potentialHolderIndex = ((_this$currSlide$index = (_this$currSlide3 = this.currSlide) === null || _this$currSlide3 === void 0 ? void 0 : _this$currSlide3.index) !== null && _this$currSlide$index !== void 0 ? _this$currSlide$index : 0) - 1 + i;
        if (this.canLoop()) {
          potentialHolderIndex = this.getLoopedIndex(potentialHolderIndex);
        }
        if (potentialHolderIndex === slideIndex) {
          this.setContent(itemHolder, slideIndex, true);
          if (i === 1) {
            var _itemHolder$slide3;
            this.currSlide = itemHolder.slide;
            (_itemHolder$slide3 = itemHolder.slide) === null || _itemHolder$slide3 === void 0 || _itemHolder$slide3.setIsActive(true);
          }
        }
      });
      this.dispatch("change");
    }
setContent(holder, index, force) {
      if (this.canLoop()) {
        index = this.getLoopedIndex(index);
      }
      if (holder.slide) {
        if (holder.slide.index === index && !force) {
          return;
        }
        holder.slide.destroy();
        holder.slide = void 0;
      }
      if (!this.canLoop() && (index < 0 || index >= this.getNumItems())) {
        return;
      }
      const itemData = this.getItemData(index);
      holder.slide = new Slide(itemData, index, this);
      if (index === this.currIndex) {
        this.currSlide = holder.slide;
      }
      holder.slide.append(holder.el);
    }
getViewportCenterPoint() {
      return {
        x: this.viewportSize.x / 2,
        y: this.viewportSize.y / 2
      };
    }
updateSize(force) {
      if (this.isDestroying) {
        return;
      }
      const newViewportSize = getViewportSize(this.options, this);
      if (!force && pointsEqual(newViewportSize, this._prevViewportSize)) {
        return;
      }
      equalizePoints(this._prevViewportSize, newViewportSize);
      this.dispatch("beforeResize");
      equalizePoints(this.viewportSize, this._prevViewportSize);
      this._updatePageScrollOffset();
      this.dispatch("viewportSize");
      this.mainScroll.resize(this.opener.isOpen);
      if (!this.hasMouse && window.matchMedia("(any-hover: hover)").matches) {
        this.mouseDetected();
      }
      this.dispatch("resize");
    }
applyBgOpacity(opacity) {
      this.bgOpacity = Math.max(opacity, 0);
      if (this.bg) {
        this.bg.style.opacity = String(this.bgOpacity * this.options.bgOpacity);
      }
    }
mouseDetected() {
      if (!this.hasMouse) {
        var _this$element2;
        this.hasMouse = true;
        (_this$element2 = this.element) === null || _this$element2 === void 0 || _this$element2.classList.add("pswp--has_mouse");
      }
    }
_handlePageResize() {
      this.updateSize();
      if (/iPhone|iPad|iPod/i.test(window.navigator.userAgent)) {
        setTimeout(() => {
          this.updateSize();
        }, 500);
      }
    }
_updatePageScrollOffset() {
      this.setScrollOffset(0, window.pageYOffset);
    }
setScrollOffset(x, y) {
      this.offset.x = x;
      this.offset.y = y;
      this.dispatch("updateScrollOffset");
    }
_createMainStructure() {
      this.element = createElement("pswp", "div");
      this.element.setAttribute("tabindex", "-1");
      this.element.setAttribute("role", "dialog");
      this.template = this.element;
      this.bg = createElement("pswp__bg", "div", this.element);
      this.scrollWrap = createElement("pswp__scroll-wrap", "section", this.element);
      this.container = createElement("pswp__container", "div", this.scrollWrap);
      this.scrollWrap.setAttribute("aria-roledescription", "carousel");
      this.container.setAttribute("aria-live", "off");
      this.container.setAttribute("id", "pswp__items");
      this.mainScroll.appendHolders();
      this.ui = new UI(this);
      this.ui.init();
      (this.options.appendToEl || document.body).appendChild(this.element);
    }
getThumbBounds() {
      return getThumbBounds(this.currIndex, this.currSlide ? this.currSlide.data : this._initialItemData, this);
    }
canLoop() {
      return this.options.loop && this.getNumItems() > 2;
    }
_prepareOptions(options) {
      if (window.matchMedia("(prefers-reduced-motion), (update: slow)").matches) {
        options.showHideAnimationType = "none";
        options.zoomAnimationDuration = 0;
      }
      return {
        ...defaultOptions,
        ...options
      };
    }
  }
  class PhotoSwipeDriver {
    constructor(options) {
      this.instance = new PhotoSwipe({
        index: options.startIndex,
        counter: false,
        bgOpacity: 1,
        spacing: 0.1,
        loop: false,
        wheelToZoom: false,
        preload: [1, 1],
        closeOnVerticalDrag: true,
        arrowPrev: false,
        arrowNext: false,
        doubleTapAction: false,
        initialZoomLevel: (zoomLevelObject) => {
          if (!zoomLevelObject.panAreaSize || !zoomLevelObject.elementSize) return zoomLevelObject.fit;
          const hRatio = zoomLevelObject.panAreaSize.x / zoomLevelObject.elementSize.x;
          const vRatio = zoomLevelObject.panAreaSize.y / zoomLevelObject.elementSize.y;
          return hRatio < vRatio ? hRatio : vRatio;
        },
        secondaryZoomLevel: (zoomLevelObject) => {
          if (!zoomLevelObject.panAreaSize || !zoomLevelObject.elementSize) return zoomLevelObject.fit * 1.5;
          const hRatio = zoomLevelObject.panAreaSize.x / zoomLevelObject.elementSize.x;
          return hRatio * 1.5;
        },
        maxZoomLevel: (zoomLevelObject) => {
          if (!zoomLevelObject.panAreaSize || !zoomLevelObject.elementSize) return 4;
          const hRatio = zoomLevelObject.panAreaSize.x / zoomLevelObject.elementSize.x;
          return Math.max(hRatio * 3, 4);
        },
        bgClickAction: (point) => options.onBackgroundClick(point),
        imageClickAction: (point) => options.onImageClick(point),
        tapAction: (point) => options.onTap(point)
      });
    }
    get currentIndex() {
      return this.instance.currIndex;
    }
    on(event, listener) {
      this.instance.on(event, listener);
    }
    init() {
      this.instance.init();
    }
    destroy() {
      this.instance.destroy();
    }
    next() {
      this.instance.next();
    }
    prev() {
      this.instance.prev();
    }
    goTo(index) {
      this.instance.goTo(index);
    }
    refreshSlide(index) {
      this.instance.refreshSlideContent(index);
    }
    stopMotion() {
      var _a, _b;
      (_b = (_a = this.instance.mainScroll) == null ? void 0 : _a.stop) == null ? void 0 : _b.call(_a);
    }
    getSlideContentState(index) {
      var _a, _b, _c;
      const instance = this.instance;
      const slide = ((_a = instance.slides) == null ? void 0 : _a[index]) ?? ((_b = instance.getSlideByIndex) == null ? void 0 : _b.call(instance, index));
      return (_c = slide == null ? void 0 : slide.content) == null ? void 0 : _c.state;
    }
    isCurrentContentLoaded() {
      var _a, _b;
      return ((_b = (_a = this.instance.currSlide) == null ? void 0 : _a.content) == null ? void 0 : _b.state) === "loaded";
    }
    isCurrentZoomed() {
      const slide = this.instance.currSlide;
      return !!slide && slide.currZoomLevel > slide.zoomLevels.initial;
    }
    isCurrentAtInitialZoom() {
      const slide = this.instance.currSlide;
      return !!slide && slide.currZoomLevel <= slide.zoomLevels.initial;
    }
    canToggleCurrentZoom() {
      const slide = this.instance.currSlide;
      return !!slide && slide.isZoomable() && slide.zoomLevels.secondary !== slide.zoomLevels.initial;
    }
    toggleCurrentZoom(point) {
      var _a;
      (_a = this.instance.currSlide) == null ? void 0 : _a.toggleZoom(point);
    }
    hideUi() {
      var _a;
      (_a = this.instance.element) == null ? void 0 : _a.classList.remove("pswp--ui-visible");
    }
    toggleUi() {
      var _a;
      return ((_a = this.instance.element) == null ? void 0 : _a.classList.toggle("pswp--ui-visible")) ?? false;
    }
    appendUi(elements) {
      const root = this.instance.element;
      if (!root) return;
      for (const element of elements) root.appendChild(element);
    }
    registerCounter(render) {
      var _a;
      (_a = this.instance.ui) == null ? void 0 : _a.registerElement({
        name: "custom-counter",
        order: 5,
        onInit: (element, instance) => {
          element.className = "pswp__counter";
          const update = () => {
            element.innerHTML = render(instance.currIndex);
          };
          update();
          instance.on("change", update);
        }
      });
    }
    observeUiVisibility(listener) {
      const root = this.instance.element;
      if (!root) return () => {
      };
      const notify = () => listener(root.classList.contains("pswp--ui-visible"));
      const observer = new MutationObserver(notify);
      observer.observe(root, { attributes: true, attributeFilter: ["class"] });
      notify();
      return () => observer.disconnect();
    }
    installWheel(listener) {
      const root = this.instance.element;
      if (!root) return () => {
      };
      const onWheel = (event) => {
        const target = event.target;
        if (target == null ? void 0 : target.closest("[data-reader-wheel-block]")) return;
        listener(event);
      };
      document.addEventListener("wheel", onWheel, { passive: false, capture: true });
      return () => document.removeEventListener("wheel", onWheel, { capture: true });
    }
    installEdgeSwipe(options) {
      const root = this.instance.element;
      if (!root) return () => {
      };
      let touchStartX = 0;
      let touchStartY = 0;
      const onStart = (event) => {
        if (event.touches.length !== 1) return;
        touchStartX = event.touches[0].clientX;
        touchStartY = event.touches[0].clientY;
      };
      const onEnd = (event) => {
        if (event.changedTouches.length !== 1 || !this.isCurrentAtInitialZoom()) return;
        const deltaX = event.changedTouches[0].clientX - touchStartX;
        const deltaY = event.changedTouches[0].clientY - touchStartY;
        if (Math.abs(deltaX) <= 50 || Math.abs(deltaY) >= Math.abs(deltaX)) return;
        if (deltaX > 0) options.onBackward();
        else options.onForward();
      };
      root.addEventListener("touchstart", onStart, { passive: true });
      root.addEventListener("touchend", onEnd, { passive: true });
      return () => {
        root.removeEventListener("touchstart", onStart);
        root.removeEventListener("touchend", onEnd);
      };
    }
  }
  function createPhotoSwipeDriver(options) {
    return new PhotoSwipeDriver(options);
  }
  function createReader(pageLoader) {
    const reader = createReaderController({
      pageLoader,
      createDriver: createPhotoSwipeDriver,
      scroll: {
        pause: pauseLazyLoad,
        resume: resumeLazyLoad,
        requestImage: loadPlaceholderImage,
        subscribeImageLoaded: subscribeScrollImageLoaded,
        restore: restoreReaderScroll
      },
      context: {
        getGalleryItems: () => store.galleryItems,
        isScrollMode: () => store.settings.scrollMode,
        isAutoPlayEnabled: () => store.autoPlay,
        setAutoPlayEnabled: (enabled) => {
          if (store.autoPlay === enabled) return;
          store.autoPlay = enabled;
          store.emit("settingsChanged");
        },
        getAutoPlayInterval: () => store.settings.autoPlayInterval,
        getThumbnailPosition: () => store.settings.thumbnailPosition,
        getImageOffset: () => store.imageOffset,
        setImageOffset: (offset) => {
          store.imageOffset = offset;
        },
        getNextUrl: () => store.nextUrl,
        setNextUrl: (url) => {
          store.nextUrl = url;
        },
        getPrevUrl: () => store.prevUrl,
        setPrevUrl: (url) => {
          store.prevUrl = url;
        },
        isPageFetching: () => store.isFetching,
        setPageFetching: (fetching) => {
          store.isFetching = fetching;
        },
        subscribeSettingsChanged: (listener) => store.on("settingsChanged", listener),
        subscribeReaderModeChanged: (listener) => store.on("readerModeChanged", listener),
        emitReaderModeChanged: () => store.emit("readerModeChanged"),
        onReaderClose: (globalIndex) => {
          var _a, _b;
          return (_b = (_a = store.activeAdapter) == null ? void 0 : _a.onReaderClose) == null ? void 0 : _b.call(_a, globalIndex, {
            scrollMode: store.settings.scrollMode,
            pageSize: store.perPage
          });
        }
      },
      onLoadNextPage: (page) => {
        store.currPage++;
        processBatch(page.items, store.currPage, void 0, false, page.pageUrl);
        store.nextUrl = page.nextUrl;
      },
      onLoadPrevPage: (page) => {
        store.currPage--;
        processBatch(page.items, store.currPage, void 0, true, page.pageUrl);
        store.prevUrl = page.prevUrl;
      }
    });
    return reader;
  }
  const floatControlCss = ".bookmark-control{position:fixed;z-index:2147483647;display:flex;flex-direction:column;align-items:center;background:#1e1e1e99;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid rgba(255,255,255,.1);border-radius:24px;padding:16px 8px;gap:16px;transition:opacity .3s,left .3s cubic-bezier(.2,.8,.2,1),right .3s cubic-bezier(.2,.8,.2,1);box-shadow:0 4px 16px #0000004d;-webkit-user-select:none;user-select:none;touch-action:none;transform:translateY(-50%) scale(var(--hr-scale, 1))}.bookmark-control.hidden{opacity:0;pointer-events:none}.bookmark-control:not(.dragging){opacity:.4}.bookmark-control:not(.dragging):active{opacity:1}@media(hover:hover){.bookmark-control:not(.dragging):hover{opacity:1}}.bookmark-control.left-side{left:0;border-radius:0 28px 28px 0;border-left:none;padding:16px 8px 16px 4px;transform-origin:left center}.bookmark-control.right-side{right:0;border-radius:28px 0 0 28px;border-right:none;padding:16px 4px 16px 8px;transform-origin:right center}.bm-btn{width:44px;height:44px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s;background:transparent;color:#fff}.bm-btn:hover{background:#ffffff1a;transform:scale(1.1)}.bookmark-control .bm-btn svg{width:24px;height:24px;opacity:.8}.bookmark-control .bm-btn svg:not([fill=none]),.bookmark-control .bm-btn svg:not([fill=none]) *{fill:currentColor!important;stroke:none!important}.bookmark-control .bm-btn svg[fill=none],.bookmark-control .bm-btn svg[fill=none] *{fill:none!important;stroke:currentColor!important}.bm-btn:hover svg{opacity:1}.bm-mode-btn{background:var(--hr-accent);width:48px;height:48px;box-shadow:0 2px 8px #f596aa66}.bm-mode-btn:hover{background:var(--hr-accent-hover);box-shadow:0 4px 12px #f596aa99;transform:scale(1.05)}.bm-mode-btn svg{width:26px;height:26px;opacity:1}:root.hr-mobile .bookmark-control{padding:12px 8px;gap:12px;border-radius:24px}:root.hr-mobile .bookmark-control.left-side{padding:12px 8px 12px 6px;border-radius:0 24px 24px 0}:root.hr-mobile .bookmark-control.right-side{padding:12px 6px 12px 8px;border-radius:24px 0 0 24px}:root.hr-mobile .bm-btn{width:46px;height:46px}:root.hr-mobile .bm-btn svg{width:26px;height:26px}:root.hr-mobile .bm-mode-btn{width:52px;height:52px}:root.hr-mobile .bm-mode-btn svg{width:28px;height:28px}";
  importCSS(floatControlCss);
  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" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"></path><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"></path></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 19h4V5H6v14zm8-14v14h4V5h-4z"/></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 svgScroll = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="2" width="18" height="20" rx="2" ry="2"></rect><line x1="3" y1="15" x2="21" y2="15"></line><line x1="12" y1="2" x2="10" y2="15"></line><path d="M9 19h.01"></path><path d="M15 19h.01"></path><path d="M11 19.5a1.5 1.5 0 0 0 2 0"></path></svg>`;
  const svgClose = `<svg class="pswp__icn" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>`;
  const settingsPanelCss = ".settings-backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background:#00000080;z-index:2147483648;opacity:0;pointer-events:none;transition:opacity .3s;backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px)}.settings-backdrop{width:calc(100% / var(--hr-scale, 1));height:calc(100% / var(--hr-scale, 1));transform:scale(var(--hr-scale, 1));transform-origin:top left}.settings-backdrop.show{opacity:1;pointer-events:auto}.settings-bottom-sheet{position:absolute;bottom:-100%;left:0;width:100%;background:#1a1a1a;border-radius:24px 24px 0 0;padding:0 20px 30px;box-sizing:border-box;transition:bottom .3s cubic-bezier(.2,.8,.2,1);box-shadow:0 -4px 20px #00000080;border-top:1px solid rgba(255,255,255,.05)}.settings-backdrop.show .settings-bottom-sheet{bottom:0}:root:not(.hr-mobile) .settings-bottom-sheet{max-width:480px;left:50%;transform:translate(-50%);border-radius:16px 16px 0 0;border:1px solid rgba(255,255,255,.05);border-bottom:none}@media(hover:hover)and (pointer:fine){:root:not(.hr-mobile) .settings-backdrop{background:none;backdrop-filter:none;-webkit-backdrop-filter:none}:root:not(.hr-mobile) .settings-bottom-sheet{position:absolute;width:340px;max-width:none;border-radius:16px;border:1px solid rgba(255,255,255,.1);box-shadow:0 10px 40px #00000080;padding:0 20px 20px;transition:opacity .2s,transform .2s;opacity:0;pointer-events:none;bottom:auto!important;left:auto;transform:scale(.95)}:root:not(.hr-mobile) .settings-backdrop.show .settings-bottom-sheet{opacity:1;pointer-events:auto;transform:scale(1)}}.settings-sheet-header{position:relative;width:100%;height:48px;display:flex;justify-content:center;align-items:center;margin-bottom:20px;border-bottom:1px solid rgba(255,255,255,.05)}.settings-title{font-size:18px;font-weight:600;color:#fff;margin:0}.settings-close-btn{position:absolute;right:0;top:0;bottom:0;margin:auto;width:36px;height:36px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:background .2s;color:#fff9}.settings-close-btn:hover{background:#ffffff1a;color:#fff}.settings-close-btn svg{width:22px;height:22px;stroke:currentColor}.settings-item{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px;font-size:15px;color:#eee}.settings-item:last-child{margin-bottom:0}.settings-label{margin-right:10px;white-space:nowrap;font-weight:500}.toggle-switch{width:44px;height:24px;background:#333;border-radius:12px;position:relative;cursor:pointer;transition:background .3s}.toggle-switch.on{background:var(--hr-accent)}.toggle-slider{width:20px;height:20px;background:#fff;border-radius:50%;position:absolute;top:2px;left:2px;transition:left .3s;box-shadow:0 1px 3px #0000004d}.toggle-switch.on .toggle-slider{left:22px}.stepper-control{display:flex;align-items:center;background:#ffffff14;border-radius:8px;overflow:hidden}.stepper-btn{display:flex;align-items:center;justify-content:center;width:36px;height:36px;color:#fff;cursor:pointer;-webkit-user-select:none;user-select:none;font-size:22px;transition:background .2s}.stepper-btn:hover{background:#ffffff26}.stepper-btn:active{background:#ffffff40}.interval-input{width:50px;background:transparent;border:none;border-left:1px solid rgba(255,255,255,.1);border-right:1px solid rgba(255,255,255,.1);border-radius:0;color:#fff;padding:6px 0;font-size:15px;text-align:center;height:36px;box-sizing:border-box;outline:none}.interval-input::-webkit-outer-spin-button,.interval-input::-webkit-inner-spin-button{-webkit-appearance:none;-moz-appearance:none;appearance:none;margin:0}.interval-input[type=number]{-moz-appearance:textfield;-webkit-appearance:textfield;appearance:textfield}.interval-input:focus{background:#ffffff0d}.segment-control{display:flex;background:#ffffff14;border-radius:8px;padding:4px;gap:4px}.segment-item{padding:6px 8px;border-radius:6px;font-size:13px;color:#fff9;cursor:pointer;transition:all .2s ease;-webkit-user-select:none;user-select:none;font-weight:500;white-space:nowrap}.segment-item:hover{color:#ffffffe6}.segment-item.active{background:#ffffff26;color:#fff;box-shadow:0 2px 6px #0003}:root.hr-mobile .settings-sheet-header{height:40px;margin-bottom:10px}:root.hr-mobile .settings-title{font-size:17px}:root.hr-mobile .settings-close-btn{width:36px;height:36px}:root.hr-mobile .settings-close-btn svg{width:20px;height:20px}:root.hr-mobile .settings-item{margin-bottom:14px;font-size:15px;font-weight:600;gap:12px}:root.hr-mobile .settings-item:last-child{margin-bottom:0}:root.hr-mobile .toggle-switch{width:48px;height:28px;border-radius:14px;flex-shrink:0}:root.hr-mobile .toggle-slider{width:24px;height:24px;top:2px;left:2px}:root.hr-mobile .toggle-switch.on .toggle-slider{left:22px}:root.hr-mobile .stepper-control{border-radius:10px}:root.hr-mobile .stepper-btn{width:44px;height:34px;font-size:20px;font-weight:400}:root.hr-mobile .interval-input{width:52px;height:34px;font-size:17px;font-weight:600}:root.hr-mobile .segment-control{padding:3px;gap:3px;border-radius:10px;display:flex;flex:1;min-width:180px}:root.hr-mobile .segment-item{flex:1;padding:7px 6px;font-size:14px;border-radius:8px;font-weight:600;text-align:center;display:flex;justify-content:center;align-items:center;white-space:nowrap}:root.hr-mobile .settings-bottom-sheet{padding:0 20px 20px}";
  importCSS(settingsPanelCss);
  const SETTINGS = [
    { label: i18n.scrollMode, key: "scrollMode" },
    { label: i18n.autoEnter, key: "autoEnterSinglePage" },
    { label: i18n.clickToEnter, key: "clickToEnterReader" }
  ];
  function createSettingsPanel(anchorElement) {
    const backdrop = document.createElement("div");
    backdrop.className = "settings-backdrop";
    const bottomSheet = document.createElement("div");
    bottomSheet.className = "settings-bottom-sheet";
    const sheetHeader = document.createElement("div");
    sheetHeader.className = "settings-sheet-header";
    const title = document.createElement("div");
    title.className = "settings-title";
    title.textContent = i18n.settings;
    const closeBtn = document.createElement("div");
    closeBtn.className = "settings-close-btn";
    closeBtn.innerHTML = svgClose.replace('class="pswp__icn"', "");
    closeBtn.onclick = (e) => {
      e.stopPropagation();
      hide();
    };
    sheetHeader.appendChild(title);
    sheetHeader.appendChild(closeBtn);
    bottomSheet.appendChild(sheetHeader);
    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 = (e) => {
        e.stopPropagation();
        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);
      bottomSheet.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.className = "stepper-control";
    const minusBtn = document.createElement("div");
    minusBtn.className = "stepper-btn";
    minusBtn.textContent = "−";
    const intervalInput = document.createElement("input");
    intervalInput.type = "number";
    intervalInput.className = "interval-input";
    intervalInput.min = "1";
    intervalInput.max = "60";
    intervalInput.step = "1";
    intervalInput.value = String(store.settings.autoPlayInterval / 1e3);
    intervalInput.onclick = (e) => e.stopPropagation();
    const plusBtn = document.createElement("div");
    plusBtn.className = "stepper-btn";
    plusBtn.textContent = "+";
    const updateInterval = (val) => {
      if (!isNaN(val) && val >= 1 && val <= 60) {
        intervalInput.value = String(val);
        store.updateSetting("autoPlayInterval", val * 1e3);
      }
    };
    intervalInput.onchange = (e) => {
      updateInterval(parseFloat(e.target.value));
    };
    minusBtn.onclick = (e) => {
      e.stopPropagation();
      let current = parseFloat(intervalInput.value);
      if (isNaN(current)) current = 5;
      updateInterval(Math.max(5, current - 5));
    };
    plusBtn.onclick = (e) => {
      e.stopPropagation();
      let current = parseFloat(intervalInput.value);
      if (isNaN(current)) current = 5;
      updateInterval(Math.min(60, current + 5));
    };
    intervalRight.appendChild(minusBtn);
    intervalRight.appendChild(intervalInput);
    intervalRight.appendChild(plusBtn);
    intervalItem.appendChild(intervalLabel);
    intervalItem.appendChild(intervalRight);
    bottomSheet.appendChild(intervalItem);
    const posItem = document.createElement("div");
    posItem.className = "settings-item";
    const posLabel = document.createElement("span");
    posLabel.className = "settings-label";
    posLabel.textContent = i18n.thumbnailPosition;
    const segmentControl = document.createElement("div");
    segmentControl.className = "segment-control";
    const posOptions = [
      { value: "top", label: i18n.posTop },
      { value: "bottom", label: i18n.posBottom },
      { value: "left", label: i18n.posLeft },
      { value: "right", label: i18n.posRight }
    ];
    const segmentItems = [];
    posOptions.forEach((opt) => {
      const item = document.createElement("div");
      item.className = `segment-item${store.settings.thumbnailPosition === opt.value ? " active" : ""}`;
      item.textContent = opt.label;
      item.onclick = (e) => {
        e.stopPropagation();
        if (store.settings.thumbnailPosition === opt.value) return;
        store.updateSetting("thumbnailPosition", opt.value);
        segmentItems.forEach((el) => el.classList.remove("active"));
        item.classList.add("active");
      };
      segmentItems.push(item);
      segmentControl.appendChild(item);
    });
    posItem.appendChild(posLabel);
    posItem.appendChild(segmentControl);
    bottomSheet.appendChild(posItem);
    backdrop.appendChild(bottomSheet);
    const show = () => {
      if (window.matchMedia("(hover: hover) and (pointer: fine)").matches && !document.documentElement.classList.contains("hr-mobile")) {
        const panelWidth = 340;
        const rect = anchorElement.getBoundingClientRect();
        const panelRect = bottomSheet.getBoundingClientRect();
        const panelHeight = panelRect.height || 300;
        let top = rect.top + rect.height / 2 - panelHeight / 2;
        top = Math.max(16, Math.min(window.innerHeight - panelHeight - 16, top));
        bottomSheet.style.top = `${top}px`;
        bottomSheet.style.bottom = "auto";
        if (rect.left < window.innerWidth / 2) {
          bottomSheet.style.left = `${rect.right + 20}px`;
          bottomSheet.style.transformOrigin = "left center";
        } else {
          bottomSheet.style.left = `${rect.left - panelWidth - 20}px`;
          bottomSheet.style.transformOrigin = "right center";
        }
        void bottomSheet.offsetHeight;
      } else {
        bottomSheet.style.cssText = "";
      }
      backdrop.classList.add("show");
    };
    const hide = () => {
      backdrop.classList.remove("show");
    };
    backdrop.onclick = (e) => {
      if (e.target === backdrop) {
        hide();
      }
    };
    const isOpen = () => backdrop.classList.contains("show");
    return {
      getContainerElement: () => backdrop,
      show,
      hide,
      isOpen
    };
  }
  function createFloatControl(readerHandle) {
    const floatControl = document.createElement("div");
    floatControl.className = `bookmark-control${store.settings.showControl ? "" : " hidden"}`;
    let savedPos = { side: "right", topPercent: 50 };
    try {
      const raw = localStorage.getItem("hentai-reader-bookmark-pos");
      if (raw) savedPos = JSON.parse(raw);
    } catch (e) {
    }
    if (savedPos.side === "left") {
      floatControl.classList.add("left-side");
    } else {
      floatControl.classList.add("right-side");
    }
    floatControl.style.top = `${savedPos.topPercent}%`;
    const topBtn = document.createElement("div");
    topBtn.className = "bm-btn bm-top-btn";
    const updateTopBtn = () => {
      if (readerHandle.isActive()) {
        topBtn.innerHTML = store.autoPlay ? svgPause : svgPlay;
        topBtn.title = store.autoPlay ? i18n.pause : i18n.play;
      } else {
        topBtn.innerHTML = svgTop;
        topBtn.title = i18n.backToTop;
      }
    };
    updateTopBtn();
    topBtn.onclick = (e) => {
      e.stopPropagation();
      if (readerHandle.isActive()) {
        store.autoPlay = !store.autoPlay;
        store.emit("settingsChanged");
      } else {
        const firstImg = document.querySelector(".r-img, .r-ph");
        if (firstImg) {
          firstImg.scrollIntoView({ behavior: "smooth", block: "start" });
        } else {
          window.scrollTo({ top: 0, behavior: "smooth" });
        }
      }
    };
    const modeBtn = document.createElement("div");
    modeBtn.className = "bm-btn bm-mode-btn";
    modeBtn.innerHTML = svgReader;
    modeBtn.title = i18n.readerMode;
    modeBtn.onclick = (e) => {
      e.stopPropagation();
      if (readerHandle.isActive()) {
        readerHandle.close();
      } else {
        readerHandle.open();
      }
    };
    store.on("readerModeChanged", () => {
      modeBtn.innerHTML = readerHandle.isActive() ? svgScroll : svgReader;
      updateTopBtn();
    });
    store.on("settingsChanged", () => {
      updateTopBtn();
    });
    const settings = createSettingsPanel(floatControl);
    document.body.appendChild(settings.getContainerElement());
    const settingsBtn = document.createElement("div");
    settingsBtn.className = "bm-btn bm-settings-btn";
    settingsBtn.innerHTML = svgSettings;
    settingsBtn.title = i18n.settings;
    settingsBtn.onclick = (e) => {
      e.stopPropagation();
      if (settings.isOpen()) {
        settings.hide();
      } else {
        settings.show();
      }
    };
    floatControl.appendChild(topBtn);
    floatControl.appendChild(modeBtn);
    floatControl.appendChild(settingsBtn);
    document.body.appendChild(floatControl);
    let isDragging = false;
    let activePointerId = null;
    let startY = 0;
    let startTop = 0;
    let dragMoved = false;
    function endDrag(commit, e) {
      if (!isDragging) return;
      isDragging = false;
      floatControl.classList.remove("dragging");
      if (activePointerId !== null) {
        try {
          floatControl.releasePointerCapture(activePointerId);
        } catch (err) {
        }
        activePointerId = null;
      }
      if (commit && dragMoved) {
        const rect = floatControl.getBoundingClientRect();
        const centerPercent = (rect.top + rect.height / 2) / window.innerHeight * 100;
        const centerX = e ? e.clientX : rect.left + rect.width / 2;
        const side = centerX < window.innerWidth / 2 ? "left" : "right";
        floatControl.style.top = `${centerPercent}%`;
        localStorage.setItem("hentai-reader-bookmark-pos", JSON.stringify({ side, topPercent: centerPercent }));
      }
    }
    floatControl.addEventListener("pointerdown", (e) => {
      if (e.button !== 0 && e.pointerType === "mouse") return;
      isDragging = true;
      dragMoved = false;
      activePointerId = e.pointerId;
      startY = e.clientY;
      const rect = floatControl.getBoundingClientRect();
      startTop = rect.top + rect.height / 2;
      floatControl.classList.add("dragging");
    });
    floatControl.addEventListener("pointermove", (e) => {
      if (!isDragging || e.pointerId !== activePointerId) return;
      const deltaY = e.clientY - startY;
      if (Math.abs(deltaY) > 5) {
        if (!dragMoved) {
          try {
            floatControl.setPointerCapture(e.pointerId);
          } catch (err) {
          }
          if (settings.isOpen()) settings.hide();
        }
        dragMoved = true;
      }
      const newCenterY = startTop + deltaY;
      const maxCenterY = window.innerHeight - floatControl.offsetHeight / 2;
      const minCenterY = floatControl.offsetHeight / 2;
      const clampedY = Math.max(minCenterY, Math.min(maxCenterY, newCenterY));
      floatControl.style.top = `${clampedY}px`;
      if (e.clientX < window.innerWidth / 2) {
        floatControl.classList.remove("right-side");
        floatControl.classList.add("left-side");
      } else {
        floatControl.classList.remove("left-side");
        floatControl.classList.add("right-side");
      }
    });
    floatControl.addEventListener("pointerup", (e) => {
      if (e.pointerId !== activePointerId) return;
      endDrag(true, e);
    });
    floatControl.addEventListener("pointercancel", (e) => {
      if (e.pointerId !== activePointerId) return;
      endDrag(false, e);
    });
    floatControl.addEventListener("click", (e) => {
      if (dragMoved) {
        e.stopPropagation();
        e.preventDefault();
      }
    }, { capture: true });
  }
  const isMobileBrowser = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
  function initViewportScale() {
    const updateScale = () => {
      if (isMobileBrowser) {
        const screenWidth = Math.min(window.screen.width, window.screen.height);
        const layoutWidth = window.innerWidth;
        if (screenWidth < 768) {
          document.documentElement.classList.add("hr-mobile");
        } else {
          document.documentElement.classList.remove("hr-mobile");
        }
        let scale = 1;
        if (layoutWidth > screenWidth && screenWidth > 0) {
          scale = layoutWidth / screenWidth;
        }
        document.documentElement.style.setProperty("--hr-scale", scale.toString());
      } else {
        document.documentElement.classList.remove("hr-mobile");
        document.documentElement.style.setProperty("--hr-scale", "1");
      }
    };
    updateScale();
    window.addEventListener("resize", updateScale);
    window.addEventListener("orientationchange", () => setTimeout(updateScale, 100));
  }
  (async function main() {
    var _a, _b, _c;
    const adapter = SiteManager.getAdapter(window.location.href);
    if (!adapter) {
      return;
    }
    store.activeAdapter = adapter;
    const pageLoader = new GalleryPageLoader(adapter);
    store.reloadSettings();
    if (adapter.name === "18comic" || adapter.name === "4KHD") {
      store.settings.scrollMode = true;
    }
    const initialPage = await pageLoader.loadInitialPage(document, window.location.href);
    if (initialPage.items.length === 0) return;
    initViewportScale();
    store.imageOffset = ((_a = initialPage.position) == null ? void 0 : _a.startIndex) ?? 0;
    store.perPage = ((_b = initialPage.position) == null ? void 0 : _b.pageSize) ?? initialPage.items.length ?? 20;
    store.nextUrl = initialPage.nextUrl;
    store.prevUrl = initialPage.prevUrl;
    if (store.imageOffset > 0 && store.perPage > 0) {
      store.currPage = Math.floor(store.imageOffset / store.perPage) + 1;
    }
    let container = adapter.getContainer();
    if (store.settings.scrollMode) {
      document.documentElement.classList.add("scroll-mode");
      (_c = adapter.hideOriginalElements) == null ? void 0 : _c.call(adapter);
      if (!container) {
        container = document.createElement("div");
        container.id = "gdt";
        document.body.appendChild(container);
      }
      container.innerHTML = "";
      processBatch(initialPage.items, store.currPage, container, false, initialPage.pageUrl);
      setupAutoScroll(pageLoader);
    } else {
      const hiddenBox = document.createElement("div");
      hiddenBox.id = "gdt-hidden";
      hiddenBox.style.display = "none";
      document.body.appendChild(hiddenBox);
      processBatch(initialPage.items, store.currPage, hiddenBox, false, initialPage.pageUrl);
    }
    const readerHandle = createReader(pageLoader);
    createFloatControl(readerHandle);
    if (!store.settings.scrollMode) {
      setTimeout(() => {
        if (!readerHandle.isActive()) readerHandle.warmupInitial(3);
      }, 1500);
    }
    if (store.settings.autoEnterSinglePage) {
      setTimeout(() => readerHandle.open(0), 1e3);
    }
    document.body.addEventListener("click", (e) => {
      if (!store.settings.clickToEnterReader || !store.settings.scrollMode || readerHandle.isActive()) return;
      const target = e.target;
      const imgTarget = target.closest(".r-img, .r-ph");
      if (imgTarget) {
        e.preventDefault();
        e.stopPropagation();
        const allImages = Array.from(document.querySelectorAll(".r-img, .r-ph"));
        const index = allImages.indexOf(imgTarget);
        if (index !== -1) {
          readerHandle.open(index);
        }
      }
    }, true);
  })();

})();