cd ..
root@paste:~/gZRAXhL5P$cat paste
paste://gZRAXhL5PPUBLIC
public paste

gZRAXhL5P

—19 views162,468 chars162.4 KB

stdout

Paste content

>_javaauto-detected
// ==UserScript==
// @name         菠萝猫原生阅读自动接续(Via)
// @namespace    local.boluomao.nativepager
// @version      1.8.0
// @description  自动阅读与接续、原位目录、历史进度、手机备份恢复、连读内存控制与广告防护。
// @downloadURL  https://paste.brianrianrehan.com/raw/gZRAXhL5P
// @match        https://www.boluomao1.com/book/*
// @match        https://www.boluomao1.com/read/*
// @match        https://www.rrssk.com/*
// @run-at       document-start
// @grant        none
// @noframes
// ==/UserScript==

/* 不依赖 GM_*;原生阅读未响应时显示兼容阅读层,不自动处理验证码。
 * 与 Via 广告规则配合使用;请停用旧版“菠萝猫纯净连读”脚本。
 */
(function () {
  'use strict';
  if (window.top !== window) return;
  if (location.hostname === 'www.rrssk.com') {
    installSearchResultLinks();
    return;
  }
  if (location.hostname !== 'www.boluomao1.com' ||
      !/^\/(?:book|read)\//.test(location.pathname) || window.__bmNativePagerInstalled) return;
  window.__bmNativePagerInstalled = true;

  var origin = location.origin;
  var searchEntry = new URL('https://www.rrssk.com/boluomao.html');
  var searchNavigationUntil = 0;
  var match = location.pathname.match(/^\/read\/(\d+)\/\d+\.html$/);
  var bookId = match && match[1];
  var state = { source: null, first: null, next: null, pages: [], seen: new Set(),
    reader: null, content: null, status: null, paper: null, toolbar: null, toolbarHandle: null,
    tocPanel: null, tocList: null, tocPages: null, tocStatus: null, tocOpen: false,
    tocPage: 1, tocMax: 1, tocSeq: 0, tocCache: new Map(), tocController: null,
    progressPanel: null, progressList: null, progressStatus: null, progressOpen: false, progressSeq: 0,
    progressTimer: null, progressTouched: false, savedProgress: null, pendingResume: null,
    progressHistory: { furthest: null, recent: [] }, chapterOrders: new Map(), chapterTitles: new Map(), forwardLinks: new Map(),
    busy: false, blocked: false, readSeq: 0, autoEntryTimer: null, autoEntryDone: false,
    compactedPages: 0, compacting: false, backupDownloadAnchor: null, backupDownloadUrl: null,
    error: '', lastRequest: 0, timer: null };

  function installSearchResultLinks() {
    if (window.__bmSearchLinksInstalled) return;
    window.__bmSearchLinksInstalled = true;
    window.addEventListener('click', function (event) {
      if (!event.target || !event.target.closest) return;
      var card = event.target.closest('.book-card');
      if (!card) return;
      var raw = '';
      var handler = card.getAttribute('onclick') || '';
      var opened = handler.match(/^\s*window\.open\(\s*(['"])([^'"]*)\1\s*(?:,\s*(['"])_blank\3\s*)?\)\s*;?\s*$/);
      if (handler && !opened) return;
      if (opened) raw = opened[2];
      else {
        var link = event.target.closest('a[href]') || card.querySelector('a[href]');
        if (link) raw = link.getAttribute('href');
      }
      var searchTarget = currentSearchBook(raw);
      if (!searchTarget) return;
      event.preventDefault(); event.stopImmediatePropagation();
      location.assign(searchTarget.href);
    }, true);
  }

  function currentSearchBook(value) {
    try {
      var wrapper = new URL(value, location.href);
      var raw = value;
      if (wrapper.origin === location.origin && wrapper.searchParams.get('action') === 'go') {
        var encoded = wrapper.searchParams.get('t');
        if (!encoded || encoded.length > 2048) return null;
        raw = atob(encoded);
      }
      var logo = document.querySelector('.logo-text');
      var boluomaoSource = !!logo && /^菠萝猫$/.test(logo.textContent.trim());
      if (/^\/\d+\.html$/.test(raw)) {
        if (!boluomaoSource) return null;
        raw = 'https://www.boluomao1.com/book' + raw;
      } else if (/^\/(?:book|read)\//.test(raw)) {
        if (!boluomaoSource) return null;
        raw = 'https://www.boluomao1.com' + raw;
      }
      var target = new URL(raw);
      if (target.protocol !== 'https:' || target.port || target.username || target.password ||
          !/^(?:www\.)?boluomao(?:1)?\.com$/.test(target.hostname) ||
          !/^\/(?:book\/\d+|read\/\d+\/\d+)\.html$/.test(target.pathname)) return null;
      var valid = true;
      target.searchParams.forEach(function (item, key) {
        if (!/^(?:p|cp)$/.test(key) || !/^[1-9]\d*$/.test(item)) valid = false;
      });
      if (!valid) return null;
      target.hostname = 'www.boluomao1.com';
      return target;
    } catch (_) { return null; }
  }

  function intentionalSearchNavigation(value) {
    try {
      var target = new URL(value);
      return Date.now() <= searchNavigationUntil && target.href === searchEntry.href;
    } catch (_) { return false; }
  }

  // 图片在打包时压缩并直接内置。脚本导入手机后,切换背景无需网络或外部文件。
  var paperImages = {
    amber: 'data:image/jpeg;base64,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',
    sage: 'data:image/jpeg;base64,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'
  };
  var themes = [
    { id: 'ivory', label: '米白', bg: '#faf6eb', text: '#333333', bar: 'rgba(250,246,235,.96)' },
    { id: 'amber', label: '仿 Alook 暖纸', bg: '#e0c5a2', text: '#333333', bar: 'rgba(224,197,162,.96)',
      image: paperImages.amber, tint: 'rgba(221,196,165,.8)' },
    { id: 'sage', label: '浅绿纸', bg: '#d1efd7', text: '#2e3931', bar: 'rgba(209,239,215,.96)',
      image: paperImages.sage, tint: 'rgba(209,239,215,.45)' },
    { id: 'night', label: '夜间', bg: '#141517', text: '#dededc', bar: 'rgba(20,21,23,.96)' }
  ];
  var themeKey = 'bm-reader-theme-v1';
  var currentTheme = 'amber';
  try { currentTheme = localStorage.getItem(themeKey) || 'amber'; } catch (_) {}
  if (!themes.some(function (theme) { return theme.id === currentTheme; })) currentTheme = 'amber';
  var toolbarKey = 'bm-reader-toolbar-collapsed-v1';
  var toolbarCollapsed = false;
  try { toolbarCollapsed = localStorage.getItem(toolbarKey) === '1'; } catch (_) {}
  var tocPageKey = 'bm-reader-catalog-page-' + bookId;
  var progressKey = 'bm-reader-progress-' + bookId;
  var historyKey = 'bm-reader-progress-history-' + bookId + '-v1';
  var chapterOrderKey = 'bm-reader-chapter-order-' + bookId + '-v1';
  var chapterTitleKey = 'bm-reader-chapter-title-' + bookId + '-v1';
  var pendingKey = 'bm-reader-pending-resume-' + bookId;
  try {
    var savedCp = Number(localStorage.getItem(tocPageKey));
    if (savedCp >= 1 && savedCp <= 100 && savedCp % 1 === 0) state.tocPage = savedCp;
  } catch (_) {}
  if (bookId) {
    try {
      var storedOrders = JSON.parse(localStorage.getItem(chapterOrderKey) || '[]');
      if (Array.isArray(storedOrders)) storedOrders.forEach(function (item) {
        if (Array.isArray(item) && /^\/read\/\d+\/\d+\.html$/.test(item[0]) &&
            Number.isInteger(item[1]) && item[1] > 0 && item[1] <= 100000) {
          state.chapterOrders.set(item[0], item[1]);
        }
      });
    } catch (_) {}
    try {
      var storedTitles = JSON.parse(localStorage.getItem(chapterTitleKey) || '[]');
      if (Array.isArray(storedTitles)) storedTitles.forEach(function (item) {
        if (Array.isArray(item) && typeof item[0] === 'string' && typeof item[1] === 'string') {
          state.chapterTitles.set(item[0], cleanChapterTitle(item[1]));
        }
      });
    } catch (_) {}
  }
  try { state.savedProgress = JSON.parse(localStorage.getItem(progressKey) || 'null'); } catch (_) {}
  if (bookId) loadProgressHistory();
  try { state.pendingResume = JSON.parse(sessionStorage.getItem(pendingKey) || 'null'); } catch (_) {}
  var fontKey = 'bm-reader-font-size-v1';
  var fontSize = 22;
  var fontTouch = { button: null, at: 0 };
  try {
    var savedFont = Number(localStorage.getItem(fontKey));
    if (savedFont >= 16 && savedFont <= 34 && savedFont % 1 === 0) fontSize = savedFont;
  } catch (_) {}

  function applyFontSize(size) {
    var anchor = captureFontAnchor();
    fontSize = Math.max(16, Math.min(34, size));
    try { localStorage.setItem(fontKey, String(fontSize)); } catch (_) {}
    if (state.content) state.content.style.setProperty('font-size', fontSize + 'px', 'important');
    restoreFontAnchor(anchor);
    if (!state.toolbar) return;
    var value = state.toolbar.querySelector('[data-bm-font-value]');
    if (value) {
      value.textContent = String(fontSize);
      value.setAttribute('aria-label', '当前字号 ' + fontSize + ' 像素');
    }
    var buttons = state.toolbar.querySelectorAll('[data-bm-font-step]');
    for (var i = 0; i < buttons.length; i++) {
      var step = Number(buttons[i].getAttribute('data-bm-font-step'));
      buttons[i].disabled = step < 0 ? fontSize <= 16 : fontSize >= 34;
      buttons[i].style.setProperty('opacity', buttons[i].disabled ? '.4' : '1', 'important');
    }
  }

  function captureFontAnchor() {
    if (!activeReader() || !state.reader.scrollTop) return null;
    var anchorY = state.reader.getBoundingClientRect().top + Math.min(120, state.reader.clientHeight * .22);
    var paragraphs = state.content.querySelectorAll('p[data-bm-progress-index]');
    for (var i = 0; i < paragraphs.length; i++) {
      var rect = paragraphs[i].getBoundingClientRect();
      if (!(rect.height > 0) || rect.bottom <= anchorY) continue;
      return { node: paragraphs[i], y: anchorY,
        ratio: Math.max(0, Math.min(1, (anchorY - rect.top) / rect.height)) };
    }
    return null;
  }

  function restoreFontAnchor(anchor) {
    if (!anchor || !anchor.node.isConnected || !activeReader()) return;
    var rect = anchor.node.getBoundingClientRect();
    if (!(rect.height > 0)) return;
    var delta = rect.top + rect.height * anchor.ratio - anchor.y;
    if (Number.isFinite(delta)) state.reader.scrollTop += delta;
  }

  function setToolbarCollapsed(collapsed) {
    var previous = toolbarCollapsed;
    toolbarCollapsed = !!collapsed;
    try { localStorage.setItem(toolbarKey, toolbarCollapsed ? '1' : '0'); } catch (_) {}
    if (!state.toolbar || !state.toolbarHandle) return;
    var top = state.reader ? state.reader.scrollTop : 0;
    var height = state.toolbar.getBoundingClientRect().height || state.toolbar.offsetHeight || 48;
    state.toolbar.hidden = toolbarCollapsed;
    state.toolbar.style.setProperty('display', toolbarCollapsed ? 'none' : 'flex', 'important');
    state.toolbarHandle.hidden = !toolbarCollapsed;
    state.toolbarHandle.style.setProperty('display', toolbarCollapsed ? 'block' : 'none', 'important');
    if (state.reader && previous !== toolbarCollapsed) {
      if (toolbarCollapsed) state.reader.scrollTop = Math.max(0, top - height);
      else if (top > 0) state.reader.scrollTop = top +
        (state.toolbar.getBoundingClientRect().height || state.toolbar.offsetHeight || height);
    }
  }

  function themeFor(id) {
    for (var i = 0; i < themes.length; i++) if (themes[i].id === id) return themes[i];
    return themes[1];
  }

  function themeBackground(theme) {
    if (!theme.image) return 'none';
    var image = 'url("' + theme.image + '")';
    return theme.tint ? 'linear-gradient(' + theme.tint + ',' + theme.tint + '),' + image : image;
  }

  function applyTheme(id) {
    var theme = themeFor(id);
    currentTheme = theme.id;
    try { localStorage.setItem(themeKey, currentTheme); } catch (_) {}
    if (!state.reader || !state.paper) return;
    state.reader.setAttribute('data-bm-reader-theme', theme.id);
    state.reader.style.setProperty('background-color', theme.bg, 'important');
    state.reader.style.setProperty('color', theme.text, 'important');
    state.paper.style.setProperty('background-color', theme.bg, 'important');
    state.paper.style.setProperty('background-image', themeBackground(theme), 'important');
    state.toolbar.style.setProperty('background-color', theme.bar, 'important');
    var buttons = state.toolbar.querySelectorAll('[data-bm-theme-choice]');
    for (var i = 0; i < buttons.length; i++) {
      var selected = buttons[i].getAttribute('data-bm-theme-choice') === theme.id;
      buttons[i].setAttribute('aria-pressed', selected ? 'true' : 'false');
      buttons[i].style.setProperty('border-color', selected ? (theme.id === 'night' ? '#eee' : '#48423a') : '#aaa', 'important');
      buttons[i].style.setProperty('box-shadow', selected ? '0 0 0 2px ' + theme.bar : 'none', 'important');
    }
    var fontButtons = state.toolbar.querySelectorAll('[data-bm-font-step], [data-bm-toc-open], [data-bm-resume]');
    for (var j = 0; j < fontButtons.length; j++) {
      fontButtons[j].style.setProperty('color', theme.text, 'important');
      fontButtons[j].style.setProperty('border-color', theme.text, 'important');
      fontButtons[j].style.setProperty('background-color',
        theme.id === 'night' ? 'rgba(255,255,255,.1)' : 'rgba(255,255,255,.22)', 'important');
    }
    var fontValue = state.toolbar.querySelector('[data-bm-font-value]');
    if (fontValue) fontValue.style.setProperty('color', theme.text, 'important');
    var collapse = state.toolbar.querySelector('[data-bm-toolbar-collapse]');
    if (collapse) collapse.style.setProperty('color', theme.text, 'important');
    if (state.toolbarHandle) {
      state.toolbarHandle.style.setProperty('background-color', theme.bar, 'important');
      state.toolbarHandle.style.setProperty('color', theme.text, 'important');
    }
    [state.tocPanel, state.progressPanel].forEach(function (panel) {
      if (panel) {
        panel.style.setProperty('background-color', theme.bg, 'important');
        panel.style.setProperty('background-image', themeBackground(theme), 'important');
        panel.style.setProperty('color', theme.text, 'important');
        var panelHeader = panel.querySelector('[data-bm-toc-header], [data-bm-progress-header]');
        if (panelHeader) panelHeader.style.setProperty('background-color', theme.bar, 'important');
        var panelButtons = panel.querySelectorAll('button');
        for (var k = 0; k < panelButtons.length; k++) {
          panelButtons[k].style.setProperty('color', theme.text, 'important');
        }
      }
    });
  }

  function installReaderStyle() {
    if (document.getElementById('bm-reader-theme-style')) return;
    var style = document.createElement('style');
    style.id = 'bm-reader-theme-style';
    style.textContent = '.via-reader-body[data-bm-auto-reader]{position:fixed;top:0;right:0;bottom:0;left:0;' +
      'overflow:auto;z-index:2147483647!important;overscroll-behavior:contain}' +
      '.via-reader-body[data-bm-auto-reader] .via-reader-header{margin:0 16px 24px;text-align:left}' +
      '.via-reader-body[data-bm-auto-reader] .via-reader-header h1{padding:24px 0 0;margin:0;font-size:1.4em;line-height:1.6}' +
      '.via-reader-body[data-bm-auto-reader] .via-reader-content{margin:10px 16px 0;overflow-wrap:break-word}' +
      '.via-reader-body[data-bm-reader-theme] .via-reader-content{' +
      'text-align:left!important;color:inherit!important}' +
      '.via-reader-body[data-bm-reader-theme] .via-reader-header,' +
      '.via-reader-body[data-bm-reader-theme] .via-reader-header h1,' +
      '.via-reader-body[data-bm-reader-theme] .via-reader-content h1,' +
      '.via-reader-body[data-bm-reader-theme] .via-reader-content h2,' +
      '.via-reader-body[data-bm-reader-theme] .via-reader-content p{' +
      'color:inherit!important}' +
      '.via-reader-body[data-bm-reader-theme] .via-reader-content p:not([style*="text-align"]){' +
      'font-size:inherit!important;line-height:1.7!important;padding:0!important;' +
      'margin:0 0 .45em!important;text-align:left!important;text-indent:2em!important;' +
      'overflow-wrap:break-word}' +
      '.via-reader-body[data-bm-reader-theme] .via-reader-content h1,' +
      '.via-reader-body[data-bm-reader-theme] .via-reader-content h2{' +
      'line-height:1.5!important;text-indent:0!important;margin:1em 0 .6em!important}' +
      '.via-reader-body[data-bm-reader-theme="night"] .via-reader-content a,' +
      '.via-reader-body[data-bm-reader-theme="night"] .via-reader-header a{' +
      'color:#9ec8ff!important}' +
      '.via-reader-body [data-bm-toolbar-expand]:active,' +
      '.via-reader-body [data-bm-toolbar-expand]:focus-visible{' +
      'opacity:.72!important}';
    (document.head || document.documentElement).appendChild(style);
  }

  function installThemeControls(reader) {
    var frame = reader.firstElementChild;
    if (!frame || !frame.querySelector('.via-reader-header')) return;
    // 始终覆盖整个 WebView,避免旧自定义 CSS 给阅读浮层留下侧边空白。
    reader.style.setProperty('position', 'fixed', 'important');
    ['top', 'right', 'bottom', 'left'].forEach(function (side) {
      reader.style.setProperty(side, '0', 'important');
    });
    reader.style.setProperty('width', '100%', 'important');
    // 释放前文和调整字号时由脚本保持可见段落,避免浏览器再次补偿滚动。
    reader.style.setProperty('overflow-anchor', 'none', 'important');
    var paper = document.createElement('div');
    paper.setAttribute('data-bm-theme-paper', '');
    paper.style.cssText = 'position:fixed;top:0;right:0;bottom:0;left:0;z-index:0;pointer-events:none;' +
      'background-position:center center;background-size:cover;background-repeat:no-repeat;';
    reader.insertBefore(paper, frame);
    frame.style.setProperty('position', 'relative');
    frame.style.setProperty('z-index', '1');
    frame.style.setProperty('width', '100%', 'important');
    var bar = document.createElement('div');
    bar.setAttribute('data-bm-theme-bar', '');
    bar.setAttribute('role', 'group');
    bar.setAttribute('aria-label', '阅读背景与字号');
    bar.style.cssText = 'position:sticky;top:0;z-index:2;display:flex;flex-wrap:nowrap;gap:3px;' +
      'align-items:center;box-sizing:border-box;width:100%;' +
      'padding:4px;min-height:40px;overflow:hidden;' +
      'border-bottom:1px solid rgba(90,80,70,.18);';
    var palette = document.createElement('div');
    palette.setAttribute('data-bm-theme-palette', '');
    palette.style.cssText = 'display:flex;flex:1 1 auto;min-width:113px;gap:3px;' +
      'align-items:center;overflow-x:auto;white-space:nowrap;';
    themes.forEach(function (theme) {
      var button = document.createElement('button');
      button.type = 'button';
      button.setAttribute('data-bm-theme-choice', theme.id);
      button.setAttribute('aria-label', theme.label);
      button.title = theme.label;
      button.style.cssText = 'flex:0 0 26px;width:26px;height:26px;box-sizing:border-box;' +
        'padding:0;border:2px solid #aaa;border-radius:5px;cursor:pointer;' +
        'background-position:center;background-size:cover;background-repeat:no-repeat;';
      button.style.setProperty('background-color', theme.bg, 'important');
      button.style.setProperty('background-image', themeBackground(theme), 'important');
      palette.appendChild(button);
    });
    bar.appendChild(palette);
    var tocButton = document.createElement('button');
    tocButton.type = 'button';
    tocButton.setAttribute('data-bm-toc-open', '');
    tocButton.setAttribute('aria-label', '打开章节目录');
    tocButton.textContent = '目录';
    tocButton.style.cssText = 'flex:0 0 34px;width:34px;height:32px;box-sizing:border-box;' +
      'padding:0;border:1px solid currentColor;border-radius:5px;' +
      'font-size:13px;font-weight:600;cursor:pointer;';
    bar.appendChild(tocButton);
    var resumeButton = document.createElement('button');
    resumeButton.type = 'button';
    resumeButton.setAttribute('data-bm-resume', '');
    resumeButton.setAttribute('aria-label', '查看阅读进度');
    resumeButton.title = '查看阅读进度';
    resumeButton.textContent = '进度';
    resumeButton.style.cssText = 'flex:0 0 34px;width:34px;height:32px;box-sizing:border-box;' +
      'padding:0;border:1px solid currentColor;border-radius:5px;' +
      'font-size:13px;font-weight:600;cursor:pointer;';
    bar.appendChild(resumeButton);
    var fontControls = document.createElement('div');
    fontControls.setAttribute('data-bm-font-controls', '');
    fontControls.style.cssText = 'display:flex;flex:0 0 auto;gap:3px;align-items:center;margin-left:auto;';
    [
      { step: -1, text: 'A−', label: '缩小字号' },
      { step: 1, text: 'A+', label: '放大字号' }
    ].forEach(function (item, index) {
      if (index) {
        var value = document.createElement('span');
        value.setAttribute('data-bm-font-value', '');
        value.setAttribute('role', 'status');
        value.setAttribute('aria-live', 'polite');
        value.style.cssText = 'flex:0 0 18px;width:18px;text-align:center;' +
          'font-size:11px;font-weight:600;line-height:1;';
        fontControls.appendChild(value);
      }
      var button = document.createElement('button');
      button.type = 'button';
      button.setAttribute('data-bm-font-step', String(item.step));
      button.setAttribute('aria-label', item.label);
      button.title = item.label;
      button.textContent = item.text;
      button.style.cssText = 'flex:0 0 30px;width:30px;height:32px;box-sizing:border-box;' +
        'padding:0;border:1px solid currentColor;border-radius:5px;' +
        'font-size:17px;font-weight:700;line-height:1;cursor:pointer;';
      fontControls.appendChild(button);
    });
    var collapse = document.createElement('button');
    collapse.type = 'button';
    collapse.setAttribute('data-bm-toolbar-collapse', '');
    collapse.setAttribute('aria-label', '收起阅读工具栏');
    collapse.textContent = '⌃';
    collapse.style.cssText = 'flex:0 0 24px;width:24px;height:32px;box-sizing:border-box;' +
      'padding:0;border:0;background:none;font-size:24px;line-height:1;cursor:pointer;';
    bar.appendChild(fontControls);
    bar.appendChild(collapse);
    frame.insertBefore(bar, frame.firstChild);
    var handle = document.createElement('button');
    handle.type = 'button';
    handle.setAttribute('data-bm-toolbar-expand', '');
    handle.setAttribute('aria-label', '展开阅读工具栏');
    handle.textContent = '☰';
    handle.style.cssText = 'position:fixed;top:6px;right:6px;z-index:5;opacity:.28;' +
      'width:34px;height:34px;padding:0;border:1px solid currentColor;' +
      'border-radius:7px;font-size:18px;line-height:1;cursor:pointer;';
    reader.appendChild(handle);
    state.paper = paper; state.toolbar = bar; state.toolbarHandle = handle;
    installCataloguePanel(reader);
    installProgressPanel(reader);
    applyTheme(currentTheme);
    applyFontSize(fontSize);
    updateResumeButton();
    setToolbarCollapsed(toolbarCollapsed);
  }

  function installCataloguePanel(reader) {
    var panel = document.createElement('div');
    panel.setAttribute('data-bm-toc-panel', '');
    panel.setAttribute('role', 'dialog');
    panel.setAttribute('aria-label', '章节目录');
    panel.hidden = true;
    panel.style.cssText = 'position:fixed;top:0;right:0;bottom:0;left:0;z-index:6;' +
      'box-sizing:border-box;width:100%;overflow-y:auto;overscroll-behavior:contain;' +
      'background-position:center;background-size:cover;background-repeat:no-repeat;';
    panel.style.setProperty('display', 'none', 'important');
    var header = document.createElement('div');
    header.setAttribute('data-bm-toc-header', '');
    header.style.cssText = 'position:sticky;top:0;z-index:1;display:flex;' +
      'align-items:center;justify-content:space-between;box-sizing:border-box;' +
      'min-height:52px;padding:8px 14px;border-bottom:1px solid rgba(80,70,60,.2);';
    var title = document.createElement('strong');
    title.textContent = '章节目录';
    title.style.cssText = 'font-size:18px;line-height:1.4;';
    var close = document.createElement('button');
    close.type = 'button';
    close.setAttribute('data-bm-toc-close', '');
    close.setAttribute('aria-label', '返回阅读');
    close.textContent = '返回阅读 ×';
    close.style.cssText = 'padding:6px 8px;border:1px solid currentColor;' +
      'border-radius:5px;background:none;font-size:14px;';
    header.appendChild(title); header.appendChild(close); panel.appendChild(header);
    var status = document.createElement('div');
    status.setAttribute('data-bm-toc-status', '');
    status.setAttribute('role', 'status');
    status.style.cssText = 'padding:12px 16px;font-size:14px;line-height:1.5;';
    status.hidden = true; panel.appendChild(status);
    var pages = document.createElement('div');
    pages.setAttribute('data-bm-toc-pages', '');
    pages.setAttribute('aria-label', '目录分页');
    pages.style.cssText = 'display:flex;gap:5px;overflow-x:auto;padding:10px 12px;' +
      'box-sizing:border-box;white-space:nowrap;';
    panel.appendChild(pages);
    var list = document.createElement('div');
    list.setAttribute('data-bm-toc-list', '');
    list.style.cssText = 'padding:0 8px 24px;box-sizing:border-box;';
    panel.appendChild(list); reader.appendChild(panel);
    state.tocPanel = panel; state.tocStatus = status; state.tocPages = pages; state.tocList = list;
  }

  function installProgressPanel(reader) {
    var panel = document.createElement('div');
    panel.setAttribute('data-bm-progress-panel', '');
    panel.setAttribute('role', 'dialog');
    panel.setAttribute('aria-label', '阅读进度');
    panel.hidden = true;
    panel.style.cssText = 'position:fixed;top:0;right:0;bottom:0;left:0;z-index:6;' +
      'box-sizing:border-box;width:100%;overflow-y:auto;overscroll-behavior:contain;' +
      'background-position:center;background-size:cover;background-repeat:no-repeat;';
    panel.style.setProperty('display', 'none', 'important');
    var header = document.createElement('div');
    header.setAttribute('data-bm-progress-header', '');
    header.style.cssText = 'position:sticky;top:0;z-index:1;display:flex;' +
      'align-items:center;justify-content:space-between;box-sizing:border-box;' +
      'min-height:52px;padding:8px 14px;border-bottom:1px solid rgba(80,70,60,.2);';
    var title = document.createElement('strong');
    title.textContent = '阅读进度';
    title.style.cssText = 'font-size:18px;line-height:1.4;';
    var close = document.createElement('button');
    close.type = 'button';
    close.setAttribute('data-bm-progress-close', '');
    close.setAttribute('aria-label', '返回阅读');
    close.textContent = '返回阅读 ×';
    close.style.cssText = 'padding:6px 8px;border:1px solid currentColor;' +
      'border-radius:5px;background:none;font-size:14px;';
    header.appendChild(title);
    if (reader.hasAttribute('data-bm-auto-reader')) {
      var exit = document.createElement('button');
      exit.type = 'button'; exit.textContent = '退出阅读';
      exit.setAttribute('data-bm-reader-exit', '');
      exit.style.cssText = 'padding:6px 8px;border:1px solid currentColor;border-radius:5px;background:none;font-size:14px;';
      header.appendChild(exit);
    }
    header.appendChild(close); panel.appendChild(header);
    var status = document.createElement('div');
    status.setAttribute('data-bm-progress-status', '');
    status.setAttribute('role', 'status');
    status.style.cssText = 'padding:12px 16px;font-size:14px;line-height:1.5;';
    status.hidden = true; panel.appendChild(status);
    installBackupControls(panel);
    var memoryNote = document.createElement('div');
    memoryNote.setAttribute('data-bm-memory-note', '');
    memoryNote.textContent = '较早的正文已释放。要回看,可从进度或目录重新打开。';
    memoryNote.style.cssText = 'padding:6px 16px;font-size:12px;line-height:1.5;opacity:.75;';
    memoryNote.hidden = !state.compactedPages; panel.appendChild(memoryNote);
    var list = document.createElement('div');
    list.setAttribute('data-bm-progress-list', '');
    list.style.cssText = 'padding:8px 12px 28px;box-sizing:border-box;';
    panel.appendChild(list); reader.appendChild(panel);
    state.progressPanel = panel; state.progressList = list; state.progressStatus = status;
  }

  // Backups contain owned reader settings and positions only, never chapter text or site credentials.
  var backupMaxBytes = 5 * 1024 * 1024;
  var backupFormat = 'boluomao-via-reader-backup';

  function backupObject(value) {
    return !!value && typeof value === 'object' && !Array.isArray(value);
  }

  function backupInteger(value, minimum, maximum) {
    return typeof value === 'number' && Number.isInteger(value) && value >= minimum && value <= maximum;
  }

  function backupError(message) { throw new Error(message || '备份内容格式不正确,未修改现有进度。'); }

  function backupReadUrl(value, id) {
    if (typeof value !== 'string' || value.length > 500) return null;
    try {
      var url = new URL(value);
      if (url.protocol !== 'https:' || url.origin !== origin || url.username || url.password || url.hash ||
          !new RegExp('^/read/' + id + '/\\d+\\.html$').test(url.pathname)) return null;
      var valid = true; var pages = 0;
      url.searchParams.forEach(function (item, key) {
        if (key !== 'p' || !/^[1-9]\d*$/.test(item) || Number(item) > 10000 || ++pages > 1) valid = false;
      });
      if (!valid) return null;
      if (url.searchParams.get('p') === '1') url.searchParams.delete('p');
      return url;
    } catch (_) { return null; }
  }

  function backupPosition(value, id, orders, titles) {
    if (value === null || typeof value === 'undefined') return null;
    if (!backupObject(value)) backupError();
    var url = backupReadUrl(value.url, id);
    if (!url || !backupInteger(value.index, 0, 100000) || typeof value.ratio !== 'number' ||
        !Number.isFinite(value.ratio) || value.ratio < 0 || value.ratio > 1 ||
        typeof value.time !== 'number' || !Number.isFinite(value.time) || value.time < 0 ||
        value.time > 8640000000000000 ||
        (typeof value.order !== 'undefined' && !backupInteger(value.order, 0, 100000)) ||
        (typeof value.title !== 'undefined' && (typeof value.title !== 'string' || value.title.length > 120))) backupError();
    return { url: url.href, index: value.index, ratio: value.ratio, time: value.time,
      order: orders.get(url.pathname) || value.order || 0,
      title: titles.get(url.pathname) || cleanChapterTitle(value.title || '').slice(0, 120) };
  }

  function backupMap(value, id, kind) {
    if (!Array.isArray(value) || value.length > 100000) backupError();
    var map = new Map();
    value.forEach(function (entry) {
      if (!Array.isArray(entry) || entry.length !== 2 || typeof entry[0] !== 'string' ||
          !new RegExp('^/read/' + id + '/\\d+\\.html$').test(entry[0]) || map.has(entry[0])) backupError();
      if (kind === 'orders') {
        if (!backupInteger(entry[1], 1, 100000)) backupError();
        map.set(entry[0], entry[1]);
      } else {
        if (typeof entry[1] !== 'string' || entry[1].length > 120) backupError();
        map.set(entry[0], cleanChapterTitle(entry[1]));
      }
    });
    return map;
  }

  function validateBackupBook(value) {
    if (!backupObject(value) || typeof value.id !== 'string' || !/^\d{1,18}$/.test(value.id) ||
        !backupObject(value.history) || !Array.isArray(value.history.recent) || value.history.recent.length > 1000 ||
        !backupInteger(value.catalogPage, 1, 100)) backupError();
    var orders = backupMap(value.chapterOrders, value.id, 'orders');
    var titles = backupMap(value.chapterTitles, value.id, 'titles');
    return { id: value.id, latest: backupPosition(value.latest, value.id, orders, titles),
      history: { furthest: backupPosition(value.history.furthest, value.id, orders, titles),
        recent: value.history.recent.map(function (entry) {
          var position = backupPosition(entry, value.id, orders, titles);
          if (!position) backupError();
          return position;
        }) },
      chapterOrders: Array.from(orders), chapterTitles: Array.from(titles), catalogPage: value.catalogPage };
  }

  function validateBackup(value) {
    if (!backupObject(value) || value.format !== backupFormat || value.schemaVersion !== 1 ||
        !backupObject(value.settings) || !Array.isArray(value.books) || value.books.length > 500 ||
        !themes.some(function (theme) { return theme.id === value.settings.theme; }) ||
        !backupInteger(value.settings.fontSize, 16, 34) || typeof value.settings.toolbarCollapsed !== 'boolean') {
      backupError('这不是支持的阅读备份,或备份版本不兼容;现有进度未修改。');
    }
    var ids = new Set();
    var books = value.books.map(function (book) {
      var checked = validateBackupBook(book);
      if (ids.has(checked.id)) backupError();
      ids.add(checked.id); return checked;
    });
    return { format: backupFormat, schemaVersion: 1, scriptVersion: '1.8.0',
      exportedAt: typeof value.exportedAt === 'string' && value.exportedAt.length <= 40 ? value.exportedAt : '',
      settings: { theme: value.settings.theme, fontSize: value.settings.fontSize,
        toolbarCollapsed: value.settings.toolbarCollapsed }, books: books };
  }

  function backupStoredJson(key, fallback) {
    var text = localStorage.getItem(key);
    if (text === null) return fallback;
    try { return JSON.parse(text); }
    catch (_) { backupError('已有阅读记录损坏,备份操作已停止;现有记录未修改。'); }
  }

  function collectBackupBook(id) {
    var prefix = 'bm-reader-';
    var latest = backupStoredJson(prefix + 'progress-' + id, null);
    var history = backupStoredJson(prefix + 'progress-history-' + id + '-v1', { furthest: null, recent: [] });
    var orders = backupStoredJson(prefix + 'chapter-order-' + id + '-v1', []);
    var titles = backupStoredJson(prefix + 'chapter-title-' + id + '-v1', []);
    var pageText = localStorage.getItem(prefix + 'catalog-page-' + id);
    var page = pageText === null ? 1 : Number(pageText);
    return validateBackupBook({ id: id, latest: latest, history: history,
      chapterOrders: orders, chapterTitles: titles, catalogPage: page });
  }

  function collectBackup() {
    var ids = new Set();
    for (var i = 0; i < localStorage.length; i++) {
      var key = localStorage.key(i); var found;
      if ((found = /^bm-reader-progress-(\d{1,18})$/.exec(key)) ||
          (found = /^bm-reader-progress-history-(\d{1,18})-v1$/.exec(key)) ||
          (found = /^bm-reader-chapter-(?:order|title)-(\d{1,18})-v1$/.exec(key)) ||
          (found = /^bm-reader-catalog-page-(\d{1,18})$/.exec(key))) ids.add(found[1]);
    }
    if (ids.size > 500) backupError('书籍记录超过备份上限,未生成文件。');
    return validateBackup({ format: backupFormat, schemaVersion: 1, scriptVersion: '1.8.0',
      exportedAt: new Date().toISOString(), settings: { theme: currentTheme, fontSize: fontSize,
        toolbarCollapsed: toolbarCollapsed }, books: Array.from(ids).sort().map(collectBackupBook) });
  }

  function backupWithin(first, second, id) {
    var a = backupReadUrl(first.url, id); var b = backupReadUrl(second.url, id);
    if (a.pathname !== b.pathname) return null;
    return progressPage(a) - progressPage(b) || first.index - second.index || first.ratio - second.ratio;
  }

  function mergeBackupBook(local, incoming) {
    var id = incoming.id; var orders = new Map(incoming.chapterOrders); var titles = new Map(incoming.chapterTitles);
    local.chapterOrders.forEach(function (entry) { orders.set(entry[0], entry[1]); });
    local.chapterTitles.forEach(function (entry) { if (entry[1]) titles.set(entry[0], entry[1]); });
    function normalize(entry) { return backupPosition(entry, id, orders, titles); }
    var latest = !local.latest ? incoming.latest : !incoming.latest || local.latest.time >= incoming.latest.time ? local.latest : incoming.latest;
    var recent = new Map();
    [local.history.furthest, incoming.history.furthest, local.latest, incoming.latest]
      .concat(local.history.recent, incoming.history.recent).forEach(function (entry) {
        if (!entry) return;
        var position = normalize(entry); var path = backupReadUrl(position.url, id).pathname; var old = recent.get(path);
        if (!old) { recent.set(path, position); return; }
        var winner = backupWithin(position, old, id) > 0 ? position : old;
        winner.time = Math.max(position.time, old.time); recent.set(path, winner);
      });
    var furthest = normalize(local.history.furthest || local.latest || incoming.history.furthest || incoming.latest);
    recent.forEach(function (entry) {
      if (!furthest) { furthest = entry; return; }
      var within = backupWithin(entry, furthest, id);
      if ((within !== null && within > 0) || (within === null && entry.order && furthest.order && entry.order > furthest.order)) {
        furthest = entry;
      }
    });
    return { id: id, latest: normalize(latest), history: { furthest: furthest,
      recent: Array.from(recent.values()).sort(function (a, b) { return b.time - a.time; }).slice(0, 1000) },
      chapterOrders: Array.from(orders), chapterTitles: Array.from(titles), catalogPage: local.catalogPage || incoming.catalogPage };
  }

  function backupWrites(book, writes) {
    var id = book.id;
    writes.set('bm-reader-progress-' + id, JSON.stringify(book.latest));
    writes.set('bm-reader-progress-history-' + id + '-v1', JSON.stringify(book.history));
    writes.set('bm-reader-chapter-order-' + id + '-v1', JSON.stringify(book.chapterOrders));
    writes.set('bm-reader-chapter-title-' + id + '-v1', JSON.stringify(book.chapterTitles));
    writes.set('bm-reader-catalog-page-' + id, String(book.catalogPage));
  }

  function applyBackupData(data) {
    var checked = validateBackup(data); var writes = new Map(); var merged = [];
    checked.books.forEach(function (incoming) {
      var local = collectBackupBook(incoming.id);
      var result = mergeBackupBook(local, incoming);
      if (localStorage.getItem('bm-reader-catalog-page-' + incoming.id) === null) result.catalogPage = incoming.catalogPage;
      backupWrites(result, writes); merged.push(result);
    });
    writes.set(themeKey, checked.settings.theme); writes.set(fontKey, String(checked.settings.fontSize));
    writes.set(toolbarKey, checked.settings.toolbarCollapsed ? '1' : '0');
    var before = new Map();
    writes.forEach(function (_, key) { before.set(key, localStorage.getItem(key)); });
    var applied = [];
    try {
      writes.forEach(function (value, key) { localStorage.setItem(key, value); applied.push(key); });
    } catch (_) {
      var rollbackFailed = false;
      applied.reverse().forEach(function (key) {
        try {
          var old = before.get(key);
          if (old === null) localStorage.removeItem(key); else localStorage.setItem(key, old);
        } catch (ignored) { rollbackFailed = true; }
      });
      backupError(rollbackFailed ? '存储空间不足,部分记录无法回滚;请保留备份文件并释放浏览器存储后重试。' :
        '存储空间不足,恢复已撤销;现有记录未修改。');
    }
    for (var i = 0; i < merged.length; i++) {
      if (merged[i].id !== bookId) continue;
      state.chapterOrders = new Map(merged[i].chapterOrders); state.chapterTitles = new Map(merged[i].chapterTitles);
      state.savedProgress = merged[i].latest; state.progressHistory = merged[i].history; state.tocPage = merged[i].catalogPage;
      state.progressTouched = false;
      if (state.progressTimer) { clearTimeout(state.progressTimer); state.progressTimer = null; }
      break;
    }
    applyTheme(checked.settings.theme); applyFontSize(checked.settings.fontSize);
    setToolbarCollapsed(checked.settings.toolbarCollapsed); updateResumeButton(); renderProgressHistory();
    setBackupStatus('已合并 ' + checked.books.length + ' 本书的进度,背景、字号和工具栏设置已恢复。');
    return checked;
  }

  function setBackupStatus(message) {
    if (state.backupStatus) state.backupStatus.textContent = message || '';
  }

  function toggleBackupText(force) {
    if (!state.backupTextPanel) return;
    var show = typeof force === 'boolean' ? force : state.backupTextPanel.hidden;
    state.backupTextPanel.hidden = !show;
    state.backupTextPanel.style.setProperty('display', show ? 'block' : 'none', 'important');
  }

  function exportBackup() {
    try {
      if (state.progressTouched) saveProgressNow(true);
      var data = collectBackup(); var text = JSON.stringify(data, null, 2);
      if (text.length > backupMaxBytes || new Blob([text]).size > backupMaxBytes) backupError('备份超过 5 MB 上限,未生成文件。');
      if (state.backupText) state.backupText.value = text;
      if (!window.URL || !URL.createObjectURL) {
        toggleBackupText(true); setBackupStatus('此浏览器不支持文件下载,请复制下面的备份文本保存。'); return;
      }
      if (state.backupDownloadUrl) URL.revokeObjectURL(state.backupDownloadUrl);
      if (state.backupDownloadAnchor) state.backupDownloadAnchor.remove();
      var url = URL.createObjectURL(new Blob([text], { type: 'application/json;charset=utf-8' }));
      var anchor = document.createElement('a'); anchor.href = url;
      anchor.download = '菠萝猫阅读备份-' + new Date().toISOString().slice(0, 10) + '.json';
      anchor.style.display = 'none';
      state.backupDownloadAnchor = anchor; state.backupDownloadUrl = url;
      document.body.appendChild(anchor); anchor.click();
      setBackupStatus('已生成 ' + data.books.length + ' 本书的备份。若手机未下载文件,点“备份文本”复制保存。');
      setTimeout(function () {
        if (state.backupDownloadAnchor === anchor) { state.backupDownloadAnchor = null; state.backupDownloadUrl = null; }
        anchor.remove(); URL.revokeObjectURL(url);
      }, 60000);
    } catch (error) { setBackupStatus(error.message || '备份生成失败。'); }
  }

  function restoreBackupText() {
    try {
      var text = state.backupText ? state.backupText.value.trim() : '';
      if (!text || text.length > backupMaxBytes || new Blob([text]).size > backupMaxBytes) backupError('请选择或粘贴不超过 5 MB 的阅读备份。');
      var data;
      try { data = JSON.parse(text); } catch (_) { backupError('备份不是有效 JSON;现有进度未修改。'); }
      applyBackupData(data);
    } catch (error) { setBackupStatus(error.message || '备份恢复失败,现有记录未修改。'); }
  }

  function importBackupFile(file) {
    if (!file) return;
    if (!backupInteger(file.size, 1, backupMaxBytes)) { setBackupStatus('请选择不超过 5 MB 的阅读备份文件。'); return; }
    var reader = new FileReader(); setBackupStatus('正在读取备份文件…');
    reader.onload = function () {
      if (state.backupText) state.backupText.value = String(reader.result || '');
      restoreBackupText();
    };
    reader.onerror = function () { setBackupStatus('文件读取失败,请用“备份文本”粘贴恢复。'); };
    try { reader.readAsText(file, 'UTF-8'); }
    catch (_) { setBackupStatus('无法打开此文件,请用“备份文本”粘贴恢复。'); }
  }

  function copyBackupText() {
    var text = state.backupText && state.backupText.value;
    if (!text) { setBackupStatus('先点“导出备份”生成文本,或粘贴已有备份。'); return; }
    function manualCopy() {
      toggleBackupText(true); state.backupText.focus(); state.backupText.select();
      var copied = false;
      try { copied = document.execCommand('copy'); } catch (_) {}
      setBackupStatus(copied ? '备份文本已复制,请保存到手机文件或笔记中。' : '请长按下面的文本,全选并复制保存。');
    }
    if (navigator.clipboard && navigator.clipboard.writeText) {
      navigator.clipboard.writeText(text).then(function () {
        setBackupStatus('备份文本已复制,请保存到手机文件或笔记中。');
      }, manualCopy);
    } else manualCopy();
  }

  function installBackupControls(panel) {
    var area = document.createElement('div'); area.setAttribute('data-bm-backup-area', '');
    area.style.cssText = 'padding:10px 12px 4px;box-sizing:border-box;font-size:14px;line-height:1.5;';
    var row = document.createElement('div'); row.style.cssText = 'display:flex;flex-wrap:wrap;gap:8px;';
    [['export', '导出备份'], ['import', '导入恢复'], ['toggle-text', '备份文本']].forEach(function (item) {
      var button = document.createElement('button'); button.type = 'button';
      button.setAttribute('data-bm-backup-' + item[0], ''); button.textContent = item[1];
      button.style.cssText = 'padding:6px 10px;border:1px solid currentColor;border-radius:5px;background:none;font-size:14px;';
      row.appendChild(button);
    });
    area.appendChild(row);
    var status = document.createElement('div'); status.setAttribute('data-bm-backup-status', '');
    status.setAttribute('role', 'status'); status.style.cssText = 'font-size:12px;line-height:1.5;padding-top:6px;';
    status.textContent = '备份全部书的阅读进度和外观设置。'; area.appendChild(status); state.backupStatus = status;
    var file = document.createElement('input'); file.type = 'file'; file.accept = '.json,application/json,text/plain';
    file.setAttribute('data-bm-backup-file', ''); file.style.display = 'none';
    file.addEventListener('change', function () { var selected = file.files && file.files[0]; file.value = ''; importBackupFile(selected); });
    area.appendChild(file); state.backupFile = file;
    var fallback = document.createElement('div'); fallback.setAttribute('data-bm-backup-text-panel', '');
    fallback.hidden = true; fallback.style.setProperty('display', 'none', 'important');
    var help = document.createElement('div'); help.textContent = '文件下载或选择失败时,可复制备份文本保存;以后粘贴到这里恢复。';
    help.style.cssText = 'padding:8px 0;font-size:12px;'; fallback.appendChild(help);
    var text = document.createElement('textarea'); text.setAttribute('data-bm-backup-text', '');
    text.setAttribute('aria-label', '阅读备份 JSON 文本'); text.placeholder = '粘贴阅读备份 JSON'; text.spellcheck = false;
    text.style.cssText = 'display:block;width:100%;height:120px;box-sizing:border-box;border:1px solid currentColor;border-radius:5px;' +
      'padding:8px;background:none;color:inherit;font-size:12px;font-family:monospace;line-height:1.5;';
    fallback.appendChild(text); state.backupText = text;
    var actions = document.createElement('div'); actions.style.cssText = 'display:flex;gap:8px;padding-top:8px;';
    [['copy', '复制文本'], ['restore-text', '从文本恢复']].forEach(function (item) {
      var button = document.createElement('button'); button.type = 'button';
      button.setAttribute('data-bm-backup-' + item[0], ''); button.textContent = item[1];
      button.style.cssText = 'padding:6px 10px;border:1px solid currentColor;border-radius:5px;background:none;font-size:14px;';
      actions.appendChild(button);
    });
    fallback.appendChild(actions); area.appendChild(fallback); state.backupTextPanel = fallback;
    panel.insertBefore(area, panel.children[1] || null);
  }

  function setProgressStatus(message) {
    if (!state.progressStatus) return;
    state.progressStatus.textContent = message || '';
    state.progressStatus.hidden = !message;
  }

  function closeProgressPanel() {
    if (!state.progressPanel) return;
    state.progressOpen = false;
    state.progressSeq++;
    stopCatalogueRequest();
    state.progressPanel.hidden = true;
    state.progressPanel.style.setProperty('display', 'none', 'important');
    setProgressStatus('');
    schedule();
  }

  function openProgressPanel() {
    if (!state.progressPanel || state.progressOpen) return;
    if (state.tocOpen) closeCatalogue();
    if (state.progressTimer) { clearTimeout(state.progressTimer); state.progressTimer = null; }
    if (state.progressTouched || !normalizeProgress(state.savedProgress)) saveProgressNow();
    state.progressOpen = true;
    if (state.timer) { clearTimeout(state.timer); state.timer = null; }
    state.progressPanel.hidden = false;
    state.progressPanel.style.setProperty('display', 'block', 'important');
    setProgressStatus('');
    renderProgressHistory();
  }

  function progressLabel(progress) {
    return progress.title || '章节名称待补全';
  }

  function addProgressChoice(label, progress) {
    var button = document.createElement('button');
    button.type = 'button';
    button.setAttribute('data-bm-progress-url', progress.url);
    button.setAttribute('data-bm-progress-index', String(progress.index));
    button.setAttribute('data-bm-progress-ratio', String(progress.ratio));
    button.style.cssText = 'display:block;width:100%;box-sizing:border-box;padding:12px 10px;' +
      'border:0;border-bottom:1px solid rgba(90,80,70,.18);' +
      'background:none;text-align:left;font-size:16px;line-height:1.5;';
    var caption = document.createElement('strong');
    caption.textContent = label;
    caption.style.cssText = 'display:block;font-size:12px;opacity:.75;font-weight:600;';
    var location = document.createElement('span');
    location.setAttribute('data-bm-progress-title', '');
    location.textContent = progressLabel(progress);
    location.style.cssText = 'display:block;font-weight:600;';
    var detail = document.createElement('span');
    detail.setAttribute('data-bm-progress-detail', '');
    var progressUrl = readUrl(progress.url);
    detail.textContent = '第' + progressPage(progressUrl) + '页 · 第' + (progress.index + 1) + '段';
    detail.style.cssText = 'display:block;font-size:13px;opacity:.75;';
    button.appendChild(caption); button.appendChild(location);
    button.appendChild(detail);
    state.progressList.appendChild(button);
  }

  function renderProgressHistory() {
    if (!state.progressList) return;
    state.progressList.textContent = '';
    var furthest = normalizeProgress(state.progressHistory.furthest);
    if (!furthest && !state.progressHistory.recent.length) {
      var empty = document.createElement('div');
      empty.textContent = '还没有保存的阅读进度。';
      empty.style.cssText = 'padding:16px 10px;font-size:14px;';
      state.progressList.appendChild(empty);
      return;
    }
    if (furthest) addProgressChoice('最远已读 · 固定在顶部', furthest);
    var recent = state.progressHistory.recent.slice().sort(function (a, b) { return b.time - a.time; });
    for (var i = 0; i < recent.length; i++) {
      var entry = normalizeProgress(recent[i]);
      if (!entry || (furthest && sameProgressPosition(entry, furthest))) continue;
      addProgressChoice(!furthest ? '最近打开' : entry.order ? '其他位置' : '其他位置 · 顺序待确认', entry);
    }
    applyTheme(currentTheme);
  }

  function setCatalogueStatus(message) {
    if (!state.tocStatus) return;
    state.tocStatus.textContent = message || '';
    state.tocStatus.hidden = !message;
  }

  function closeCatalogue() {
    if (!state.tocPanel) return;
    state.tocOpen = false;
    state.tocSeq++;
    stopCatalogueRequest();
    state.tocPanel.hidden = true;
    state.tocPanel.style.setProperty('display', 'none', 'important');
    setCatalogueStatus('');
    schedule();
  }

  function openCatalogue() {
    if (!state.tocPanel || state.tocOpen) return;
    if (state.progressTimer) { clearTimeout(state.progressTimer); state.progressTimer = null; }
    if (state.progressTouched || !normalizeProgress(state.savedProgress)) saveProgressNow();
    state.tocOpen = true;
    if (state.timer) { clearTimeout(state.timer); state.timer = null; }
    state.tocPanel.hidden = false;
    state.tocPanel.style.setProperty('display', 'block', 'important');
    loadCatalogue(state.tocPage);
  }

  function stopCatalogueRequest() {
    if (state.tocController) {
      state.tocController.abort();
      state.tocController = null;
    }
  }

  async function fetchInertPage(url, kind) {
    var controller = typeof AbortController === 'function' ? new AbortController() : null;
    state.tocController = controller;
    var timeout;
    try {
      return await Promise.race([(async function () {
        var response = await fetch(url.href, { credentials: 'same-origin', redirect: 'manual',
          signal: controller ? controller.signal : undefined });
        if (response.type === 'opaqueredirect' || (response.status >= 300 && response.status < 400)) {
          throw new Error(kind + '需要登录或验证,当前阅读已保留');
        }
        if (!response.ok) throw new Error(kind + '加载失败(' + response.status + '),当前阅读已保留');
        if (response.url) {
          var finalUrl = siteUrl(response.url);
          if (!finalUrl || finalUrl.pathname !== url.pathname || finalUrl.search !== url.search) {
            throw new Error(kind + '响应地址异常,当前阅读已保留');
          }
        }
        var template = document.createElement('template');
        template.innerHTML = await response.text();
        return template.content;
      })(), new Promise(function (_, reject) {
        timeout = setTimeout(function () {
          if (controller) controller.abort();
          reject(new Error(kind + '加载超时,当前阅读已保留'));
        }, 20000);
      })]);
    } finally {
      clearTimeout(timeout);
      if (state.tocController === controller) state.tocController = null;
    }
  }

  function parseCatalogue(doc, pageUrl, cp) {
    var title = doc.querySelector('title');
    if (doc.querySelector('input[name="GOEDGE_WAF_CAPTCHA_CODE"], #loginForm') ||
        (title && /^(?:身份验证|安全验证|访问验证|人机验证|登录\s*[-—]|Just a moment)/i.test(title.textContent.trim()))) {
      throw new Error('目录需要登录或验证,当前阅读已保留');
    }
    var chapterBox = doc.querySelector('#chapters .direList');
    if (!chapterBox) throw new Error('未找到原站章节目录,当前阅读已保留');
    var anchors = chapterBox.querySelectorAll('li .name > a[href]');
    var chapters = [];
    var seen = new Set();
    for (var i = 0; i < anchors.length; i++) {
      var url = readUrl(anchors[i].getAttribute('href'), pageUrl.href);
      if (!url || url.search || seen.has(url.href)) continue;
      var label = anchors[i].textContent.trim();
      if (!label) continue;
      var order = (cp - 1) * 100 + i + 1;
      chapters.push({ url: url, label: label, order: order }); seen.add(url.href);
      state.chapterOrders.set(url.pathname, order);
      state.chapterTitles.set(url.pathname, cleanChapterTitle(label));
    }
    try { localStorage.setItem(chapterOrderKey, JSON.stringify(Array.from(state.chapterOrders))); } catch (_) {}
    try { localStorage.setItem(chapterTitleKey, JSON.stringify(Array.from(state.chapterTitles))); } catch (_) {}
    reconcileProgressOrders();
    if (!chapters.length) throw new Error('这一页没有可用章节,当前阅读已保留');
    var ranges = {};
    ranges[cp] = String((cp - 1) * 100 + 1) + '-' + String((cp - 1) * 100 + chapters.length);
    var max = cp;
    var rangeLinks = doc.querySelectorAll('#chapters .page-range-list a[href]');
    for (var j = 0; j < rangeLinks.length; j++) {
      var rangeUrl = siteUrl(rangeLinks[j].getAttribute('href'), pageUrl.href);
      if (!rangeUrl || rangeUrl.pathname !== '/book/' + bookId + '.html') continue;
      var page = Number(rangeUrl.searchParams.get('cp'));
      if (!(page >= 1 && page <= 100 && page % 1 === 0)) continue;
      ranges[page] = rangeLinks[j].textContent.trim() || String(page);
      max = Math.max(max, page);
    }
    var currentRange = doc.querySelector('#chapters .page-range-list .cur');
    if (currentRange) ranges[cp] = currentRange.textContent.trim() || ranges[cp];
    return { chapters: chapters, ranges: ranges, max: max };
  }

  function renderCatalogue(data, cp) {
    if (!state.tocOpen || !state.tocPages || !state.tocList) return;
    state.tocMax = data.max;
    state.tocPages.textContent = '';
    for (var page = 1; page <= data.max; page++) {
      var button = document.createElement('button');
      button.type = 'button';
      button.setAttribute('data-bm-toc-page', String(page));
      button.setAttribute('aria-label', '目录 ' + (data.ranges[page] || page));
      button.textContent = data.ranges[page] || String(page);
      button.style.cssText = 'flex:0 0 auto;padding:6px 8px;border:1px solid currentColor;' +
        'border-radius:5px;background:none;font-size:12px;';
      if (page === cp) {
        button.setAttribute('aria-current', 'page');
        button.style.setProperty('font-weight', '700');
      }
      state.tocPages.appendChild(button);
    }
    state.tocList.textContent = '';
    data.chapters.forEach(function (chapter) {
      var button = document.createElement('button');
      button.type = 'button';
      button.setAttribute('data-bm-toc-url', chapter.url.href);
      button.textContent = chapter.label;
      button.style.cssText = 'display:block;width:100%;box-sizing:border-box;padding:11px 10px;' +
        'border:0;border-bottom:1px solid rgba(90,80,70,.18);' +
        'background:none;text-align:left;font-size:16px;line-height:1.5;';
      if (state.first && chapter.url.pathname === state.first.url.pathname) {
        button.setAttribute('aria-current', 'page');
        button.style.setProperty('font-weight', '700');
      }
      state.tocList.appendChild(button);
    });
    setCatalogueStatus('');
    applyTheme(currentTheme);
  }

  async function loadCatalogue(cp) {
    if (!state.tocOpen || !(cp >= 1 && cp <= 100 && cp % 1 === 0)) return;
    stopCatalogueRequest();
    state.tocPage = cp;
    try { localStorage.setItem(tocPageKey, String(cp)); } catch (_) {}
    var token = ++state.tocSeq;
    setCatalogueStatus('正在加载原站目录…');
    if (state.tocCache.has(cp)) {
      renderCatalogue(state.tocCache.get(cp), cp);
      return;
    }
    if (state.tocList) state.tocList.textContent = '';
    var url = new URL('/book/' + bookId + '.html?cp=' + cp, origin);
    try {
      var doc = await fetchInertPage(url, '目录');
      var data = parseCatalogue(doc, url, cp);
      if (!state.tocOpen || token !== state.tocSeq) return;
      state.tocCache.set(cp, data);
      renderCatalogue(data, cp);
    } catch (error) {
      if (state.tocOpen && token === state.tocSeq) setCatalogueStatus(error.message || '目录加载失败,当前阅读已保留');
    }
  }

  async function chooseCatalogueChapter(value) {
    var url = readUrl(value);
    if (!state.tocOpen || !url || url.search) return;
    stopCatalogueRequest();
    if (state.first && pageKey(state.first.url) === pageKey(url)) {
      state.reader.scrollTop = 0;
      closeCatalogue();
      saveChapterStart(url);
      return;
    }
    var token = ++state.tocSeq;
    setCatalogueStatus('正在读取章节…');
    try {
      var doc = await fetchInertPage(url, '本章');
      var page = extract(doc, url);
      if (!state.tocOpen || token !== state.tocSeq) return;
      showCatalogueChapter(page);
    } catch (error) {
      if (state.tocOpen && token === state.tocSeq) setCatalogueStatus(error.message || '本章暂不能打开,当前阅读已保留');
    }
  }

  function saveChapterStart(url) {
    state.progressTouched = false;
    recordProgress({ url: url.href, index: 0, ratio: 0, time: Date.now(),
      title: titleForProgress(url) });
  }

  function showCatalogueChapter(page, checkpoint) {
    if (!activeReader() || !state.source) throw new Error('阅读模式已关闭,当前章节未切换');
    var target = readUrl(page.url.href);
    if (!target) throw new Error('章节地址不正确,当前阅读已保留');
    try { history.replaceState(history.state, '', target.href); }
    catch (_) { throw new Error('浏览器无法原位切换地址,当前阅读已保留'); }
    rememberChapterTitle(page);

    // 只复制解码后的纯文本;下载页面中的脚本、图片和广告节点都不进入阅读层。
    state.readSeq++;
    if (state.timer) { clearTimeout(state.timer); state.timer = null; }
    if (state.progressTimer) { clearTimeout(state.progressTimer); state.progressTimer = null; }
    state.pendingResume = null;
    try { sessionStorage.removeItem(pendingKey); } catch (_) {}
    replaceReadingPages(page, []);
    delete page.content;
    state.first = page; state.next = page.next; state.pages = [];
    state.seen = new Set([pageKey(target)]);
    state.busy = false; state.blocked = false; state.error = '';
    markProgressParagraphs();
    state.reader.scrollTop = 0;
    if (state.tocOpen) closeCatalogue();
    if (state.progressOpen) closeProgressPanel();
    if (checkpoint) {
      var selected = normalizeProgress(checkpoint);
      selected.time = Date.now();
      selected.title = page.title;
      recordProgress(selected);
      state.pendingResume = selected;
      restorePendingProgress();
    } else saveChapterStart(target);
    updateStatus();
  }

  function replaceReadingPages(page, remaining) {
    state.source.textContent = '';
    state.content.textContent = '';
    for (var i = 0; i < page.paragraphs.length; i++) {
      var paragraph = document.createElement('p');
      paragraph.textContent = page.paragraphs[i];
      state.source.appendChild(paragraph);
      state.content.appendChild(paragraph.cloneNode(true));
    }
    state.source.setAttribute('data-bm-page', pageKey(page.url));
    state.content.setAttribute('data-bm-page', pageKey(page.url));
    remaining.forEach(function (item) { appendPage(state.source, item); appendPage(state.content, item); });
    var heading = document.querySelector('.conC h1.title');
    if (heading) heading.textContent = page.title;
    var readerHeading = state.reader.querySelector('.via-reader-header h1');
    if (readerHeading) readerHeading.textContent = page.title;
    document.title = page.docTitle || page.title;
    var breadcrumb = document.querySelector('.conC .position > span:last-child');
    if (breadcrumb) breadcrumb.textContent = page.title;
    var chapterInfo = document.querySelector('.conC .toolBox > .font14');
    if (chapterInfo) chapterInfo.textContent = page.chapterInfo || '';
    var staleChapterActions = document.querySelector('.conC .btnErrorW');
    if (staleChapterActions) staleChapterActions.remove();
    var navigation = document.querySelector('.readPage');
    if (navigation) {
      navigation.textContent = '';
      if (page.next) {
        var next = document.createElement('a');
        next.className = 'btnGreen';
        next.href = page.next.href;
        next.textContent = page.next.pathname === page.url.pathname ? '下一页 >' : '下一章 >';
        navigation.appendChild(next);
      }
      var catalogue = document.createElement('a');
      catalogue.className = 'btnBlue';
      catalogue.href = '/book/' + bookId + '.html';
      catalogue.textContent = '目录';
      navigation.appendChild(catalogue);
    }
  }

  function siteUrl(value, base) {
    try {
      var url = new URL(value, base || location.href);
      if (url.protocol === 'https:' && url.origin === origin && !url.username && !url.password) return url;
    } catch (_) {}
    return null;
  }

  function readUrl(value, base) {
    var url = siteUrl(value, base);
    if (!url || !bookId || !new RegExp('^/read/' + bookId + '/\\d+\\.html$').test(url.pathname)) return null;
    url.hash = '';
    return url;
  }

  function pageKey(url) {
    var copy = new URL(url.href);
    copy.hash = '';
    if (copy.searchParams.get('p') === '1') copy.searchParams.delete('p');
    if (copy.searchParams.sort) copy.searchParams.sort();
    return copy.href;
  }

  function normalizeProgress(value) {
    if (!value || typeof value !== 'object') return null;
    var url = readUrl(value.url);
    var index = Number(value.index);
    var ratio = Number(value.ratio);
    if (!url || !(index >= 0 && index % 1 === 0) || !(ratio >= 0 && ratio <= 1)) return null;
    var order = state.chapterOrders.get(url.pathname) || Number(value.order) || 0;
    return { url: url.href, index: index, ratio: ratio, time: Number(value.time) || 0,
      title: state.chapterTitles.get(url.pathname) ||
        (typeof value.title === 'string' ? cleanChapterTitle(value.title).slice(0, 120) : '') || titleForProgress(url),
      order: Number.isInteger(order) && order > 0 && order <= 100000 ? order : 0 };
  }

  function progressPage(url) {
    var page = Number(url.searchParams.get('p')) || 1;
    return Number.isInteger(page) && page >= 1 ? page : 1;
  }

  function compareWithinChapter(a, b) {
    var first = readUrl(a.url);
    var second = readUrl(b.url);
    if (!first || !second || first.pathname !== second.pathname) return null;
    var pageDifference = progressPage(first) - progressPage(second);
    return pageDifference || a.index - b.index || a.ratio - b.ratio;
  }

  function sameProgressPosition(a, b) {
    var first = readUrl(a.url);
    var second = readUrl(b.url);
    return !!first && !!second && pageKey(first) === pageKey(second) &&
      a.index === b.index && Math.abs(a.ratio - b.ratio) < .001;
  }

  function followsKnownNext(previous, current) {
    var from = readUrl(previous.url);
    var to = readUrl(current.url);
    if (!from || !to) return false;
    var key = pageKey(from);
    var wanted = pageKey(to);
    var visited = new Set();
    while (!visited.has(key)) {
      visited.add(key);
      key = state.forwardLinks.get(key);
      if (!key) return false;
      if (key === wanted) return true;
    }
    return false;
  }

  function isFurtherProgress(candidate, previous) {
    if (!previous) return true;
    var within = compareWithinChapter(candidate, previous);
    if (within !== null) return within > 0;
    if (candidate.order && previous.order) return candidate.order > previous.order;
    return followsKnownNext(previous, candidate);
  }

  function persistProgressHistory() {
    try { localStorage.setItem(historyKey, JSON.stringify(state.progressHistory)); } catch (_) {}
  }

  function recordProgress(value, writeLegacy, promote) {
    var progress = normalizeProgress(value);
    if (!progress) return;
    if (writeLegacy !== false) {
      state.savedProgress = progress;
      try { localStorage.setItem(progressKey, JSON.stringify(progress)); } catch (_) {}
    }
    var recent = state.progressHistory.recent;
    var path = readUrl(progress.url).pathname;
    for (var i = 0; i < recent.length; i++) {
      var old = normalizeProgress(recent[i]);
      if (!old || readUrl(old.url).pathname !== path) continue;
      if (compareWithinChapter(old, progress) > 0) {
        old.time = progress.time;
        if (!old.order) old.order = progress.order;
        progress = old;
      }
      recent.splice(i, 1);
      break;
    }
    recent.unshift(progress);
    if (recent.length > 1000) recent.length = 1000;
    var furthest = normalizeProgress(state.progressHistory.furthest);
    if (promote !== false && isFurtherProgress(progress, furthest)) state.progressHistory.furthest = progress;
    persistProgressHistory();
    updateResumeButton();
    if (state.progressOpen) renderProgressHistory();
  }

  function loadProgressHistory() {
    try {
      var stored = JSON.parse(localStorage.getItem(historyKey) || 'null');
      if (stored && typeof stored === 'object') {
        state.progressHistory.furthest = normalizeProgress(stored.furthest);
        if (Array.isArray(stored.recent)) {
          state.progressHistory.recent = stored.recent.map(normalizeProgress).filter(Boolean).slice(0, 1000);
        }
      }
    } catch (_) {}
    var legacy = normalizeProgress(state.savedProgress);
    if (legacy && !state.progressHistory.recent.some(function (entry) {
      return sameProgressPosition(entry, legacy) && entry.time >= legacy.time;
    })) recordProgress(legacy, false);
  }

  function reconcileProgressOrders() {
    var history = state.progressHistory;
    history.furthest = normalizeProgress(history.furthest);
    history.recent = history.recent.map(normalizeProgress).filter(Boolean);
    for (var i = 0; i < history.recent.length; i++) {
      if ((history.furthest || history.recent[i].order) &&
          isFurtherProgress(history.recent[i], history.furthest)) history.furthest = history.recent[i];
    }
    persistProgressHistory();
    if (state.progressOpen) renderProgressHistory();
  }

  function cleanChapterTitle(value) {
    return String(value || '').trim().replace(/\s*[((](?:第\s*\d+\s*页|\d+\s*\/\s*\d+(?:页)?)[))]\s*$/, '');
  }

  function rememberChapterTitle(page) {
    if (!page || !page.url || !page.title) return;
    var title = cleanChapterTitle(page.title);
    if (title && !state.chapterTitles.get(page.url.pathname)) state.chapterTitles.set(page.url.pathname, title);
    try { localStorage.setItem(chapterTitleKey, JSON.stringify(Array.from(state.chapterTitles))); } catch (_) {}
    reconcileProgressOrders();
  }

  function titleForProgress(url) {
    if (state.chapterTitles.has(url.pathname)) return state.chapterTitles.get(url.pathname);
    if (state.first && state.first.url.pathname === url.pathname) return cleanChapterTitle(state.first.title);
    for (var i = 0; i < state.pages.length; i++) {
      if (state.pages[i].url.pathname === url.pathname) return cleanChapterTitle(state.pages[i].title);
    }
    return '';
  }

  function updateResumeButton() {
    if (!state.toolbar) return;
    var button = state.toolbar.querySelector('[data-bm-resume]');
    if (!button) return;
    button.disabled = !normalizeProgress(state.progressHistory.furthest) &&
      !state.progressHistory.recent.length;
    button.style.setProperty('opacity', button.disabled ? '.45' : '1', 'important');
  }

  function markProgressParagraphs() {
    if (!state.content || !state.first) return;
    var counts = Object.create(null);
    var paragraphs = state.content.querySelectorAll('p');
    for (var i = 0; i < paragraphs.length; i++) {
      var paragraph = paragraphs[i];
      if (paragraph.hasAttribute('data-bm-native-nav') ||
          paragraph.closest('.readPage, .page2-chapter')) continue;
      var page = paragraph.closest('[data-bm-page]');
      var url = page ? readUrl(page.getAttribute('data-bm-page')) : state.first.url;
      if (!url) continue;
      var key = pageKey(url);
      var index = counts[key] || 0;
      counts[key] = index + 1;
      paragraph.setAttribute('data-bm-progress-url', url.href);
      paragraph.setAttribute('data-bm-progress-index', String(index));
    }
  }

  function saveProgressNow(allowProgressPanel) {
    if (!activeReader() || state.tocOpen || (state.progressOpen && allowProgressPanel !== true) || !state.first) return;
    var paragraphs = state.content.querySelectorAll('p[data-bm-progress-index]');
    var anchor = state.reader.getBoundingClientRect().top + Math.min(120, state.reader.clientHeight * .22);
    var selected = null;
    var rect = null;
    for (var i = 0; i < paragraphs.length; i++) {
      var candidate = paragraphs[i];
      if (candidate.hidden || candidate.closest('[hidden], .readPage, .page2-chapter')) continue;
      var bounds = candidate.getBoundingClientRect();
      if (!(bounds.height > 0)) continue;
      selected = candidate; rect = bounds;
      if (bounds.bottom > anchor) break;
    }
    if (!selected || !rect) return;
    var url = readUrl(selected.getAttribute('data-bm-progress-url'));
    var index = Number(selected.getAttribute('data-bm-progress-index'));
    if (!url || !(index >= 0 && index % 1 === 0)) return;
    var ratio = Math.max(0, Math.min(1, (anchor - rect.top) / rect.height));
    recordProgress({ url: url.href, index: index, ratio: Math.round(ratio * 1000) / 1000,
      time: Date.now(), title: titleForProgress(url) });
  }

  function scheduleProgress() {
    if (state.tocOpen || state.progressOpen) return;
    state.progressTouched = true;
    if (state.progressTimer) return;
    state.progressTimer = setTimeout(function () {
      state.progressTimer = null;
      saveProgressNow();
      compactReadPages();
    }, 800);
  }

  function restoreProgressHere(progress) {
    if (!activeReader()) return false;
    var targetUrl = readUrl(progress.url);
    if (!targetUrl) return false;
    var paragraphs = state.content.querySelectorAll('p[data-bm-progress-index]');
    for (var i = 0; i < paragraphs.length; i++) {
      var paragraph = paragraphs[i];
      var url = readUrl(paragraph.getAttribute('data-bm-progress-url'));
      if (!url || pageKey(url) !== pageKey(targetUrl) ||
          Number(paragraph.getAttribute('data-bm-progress-index')) !== progress.index) continue;
      var rect = paragraph.getBoundingClientRect();
      if (!(rect.height > 0)) return false;
      var anchor = state.reader.getBoundingClientRect().top + Math.min(120, state.reader.clientHeight * .22);
      state.reader.scrollTop += rect.top + progress.ratio * rect.height - anchor;
      return true;
    }
    return false;
  }

  function restorePendingProgress() {
    var pending = normalizeProgress(state.pendingResume);
    if (!pending || !state.first || pageKey(readUrl(pending.url)) !== pageKey(state.first.url)) return;
    var attempts = 0;
    function attempt() {
      if (!activeReader()) return;
      markProgressParagraphs();
      if (restoreProgressHere(pending)) {
        state.pendingResume = null;
        try { sessionStorage.removeItem(pendingKey); } catch (_) {}
        saveProgressNow();
      } else if (++attempts < 4) setTimeout(attempt, 250);
      else {
        state.pendingResume = null;
        try { sessionStorage.removeItem(pendingKey); } catch (_) {}
      }
    }
    attempt();
  }

  async function chooseHistoryPosition(button) {
    if (!state.progressOpen) return;
    var url = readUrl(button.getAttribute('data-bm-progress-url'));
    var index = Number(button.getAttribute('data-bm-progress-index'));
    var ratio = Number(button.getAttribute('data-bm-progress-ratio'));
    if (!url || !(index >= 0 && index % 1 === 0) || !(ratio >= 0 && ratio <= 1)) return;
    var choices = [state.progressHistory.furthest].concat(state.progressHistory.recent);
    var progress = null;
    for (var i = 0; i < choices.length; i++) {
      var entry = normalizeProgress(choices[i]);
      if (entry && pageKey(readUrl(entry.url)) === pageKey(url) && entry.index === index &&
          Math.abs(entry.ratio - ratio) < .001) { progress = entry; break; }
    }
    if (!progress) return;
    if (progress.index === 0 && progress.ratio === 0 && state.first &&
        pageKey(state.first.url) === pageKey(url)) {
      state.reader.scrollTop = 0;
      closeProgressPanel();
      progress.time = Date.now(); recordProgress(progress);
      return;
    }
    if (restoreProgressHere(progress)) {
      closeProgressPanel();
      progress.time = Date.now(); recordProgress(progress);
      return;
    }
    stopCatalogueRequest();
    var token = ++state.progressSeq;
    setProgressStatus('正在打开保存的位置…');
    try {
      var doc = await fetchInertPage(url, '进度');
      var page = extract(doc, url);
      if (!state.progressOpen || token !== state.progressSeq) return;
      showCatalogueChapter(page, progress);
    } catch (error) {
      if (state.progressOpen && token === state.progressSeq) {
        setProgressStatus(error.message || '暂时无法打开,当前阅读已保留');
      }
    }
  }

  // 这三个函数是当前章节“书签后、页码后、页脚”的广告插入入口。
  // 与单独的站外保护脚本共存:已有不可改写的保护不再覆盖。
  ['C061V4rne', 'ZJo6i4ZXG', 'r2lTyoQWN'].forEach(function (name) {
    try { Object.defineProperty(window, name, { value: function () {}, writable: false, configurable: false }); }
    catch (_) {}
  });
  try {
    Object.defineProperty(window, 'open', { value: function () { return null; }, writable: false, configurable: false });
  } catch (_) {
    try { window.open = function () { return null; }; } catch (ignored) {}
  }

  function guard(event) {
    var target = event.target;
    if (!target || !target.closest) return;
    var download = target.closest('a[href]');
    if (download && download === state.backupDownloadAnchor && state.backupDownloadUrl &&
        download.getAttribute('href') === state.backupDownloadUrl) {
      event.stopImmediatePropagation();
      return;
    }
    var backupField = target.closest('[data-bm-backup-file], [data-bm-backup-text]');
    if (backupField) { event.stopImmediatePropagation(); return; }
    var backupControl = target.closest('[data-bm-backup-export], [data-bm-backup-import], ' +
      '[data-bm-backup-toggle-text], [data-bm-backup-copy], [data-bm-backup-restore-text]');
    if (backupControl) {
      if (event.type === 'click') {
        event.preventDefault();
        if (backupControl.hasAttribute('data-bm-backup-export')) exportBackup();
        else if (backupControl.hasAttribute('data-bm-backup-import')) state.backupFile.click();
        else if (backupControl.hasAttribute('data-bm-backup-toggle-text')) toggleBackupText();
        else if (backupControl.hasAttribute('data-bm-backup-copy')) copyBackupText();
        else if (backupControl.hasAttribute('data-bm-backup-restore-text')) restoreBackupText();
      }
      event.stopImmediatePropagation(); return;
    }
    var searchControl = target.closest('.btnSearchM, .searchBox form, .searchBoxM input');
    if (searchControl) {
      if (event.type === 'click') {
        event.preventDefault();
        searchNavigationUntil = Date.now() + 5000;
        location.assign(searchEntry.href);
      }
      event.stopImmediatePropagation();
      return;
    }
    var readerControl = target.closest('[data-bm-toc-open], [data-bm-toc-close], ' +
      '[data-bm-toc-page], [data-bm-toc-url], [data-bm-toolbar-collapse], ' +
      '[data-bm-toolbar-expand], [data-bm-resume], [data-bm-progress-close], ' +
      '[data-bm-progress-url], [data-bm-reader-exit]');
    if (readerControl) {
      if (event.type === 'click') {
        event.preventDefault();
        if (readerControl.hasAttribute('data-bm-toc-open')) openCatalogue();
        else if (readerControl.hasAttribute('data-bm-toc-close')) closeCatalogue();
        else if (readerControl.hasAttribute('data-bm-toc-page')) {
          loadCatalogue(Number(readerControl.getAttribute('data-bm-toc-page')));
        } else if (readerControl.hasAttribute('data-bm-toc-url')) {
          chooseCatalogueChapter(readerControl.getAttribute('data-bm-toc-url'));
        } else if (readerControl.hasAttribute('data-bm-progress-close')) closeProgressPanel();
        else if (readerControl.hasAttribute('data-bm-reader-exit')) exitAssistedReader();
        else if (readerControl.hasAttribute('data-bm-progress-url')) chooseHistoryPosition(readerControl);
        else if (readerControl.hasAttribute('data-bm-toolbar-collapse')) setToolbarCollapsed(true);
        else if (readerControl.hasAttribute('data-bm-toolbar-expand')) setToolbarCollapsed(false);
        else if (readerControl.hasAttribute('data-bm-resume')) openProgressPanel();
      }
      event.stopImmediatePropagation();
      return;
    }
    var fontButton = target.closest('[data-bm-font-step]');
    if (fontButton) {
      if (event.type === 'touchstart') fontTouch.button = fontButton;
      if (event.type === 'touchend' && fontTouch.button === fontButton) {
        if (!fontButton.disabled) applyFontSize(fontSize + Number(fontButton.getAttribute('data-bm-font-step')));
        fontTouch.at = Date.now();
      }
      if (event.type === 'click') {
        event.preventDefault();
        if (!fontButton.disabled && !(fontTouch.button === fontButton && Date.now() - fontTouch.at < 700)) {
          applyFontSize(fontSize + Number(fontButton.getAttribute('data-bm-font-step')));
        }
        fontTouch.button = null;
      }
      event.stopImmediatePropagation();
      return;
    }
    var themeButton = target.closest('[data-bm-theme-choice]');
    if (themeButton) {
      if (event.type === 'click' || event.type === 'touchend') {
        if (event.type === 'click') event.preventDefault();
        applyTheme(themeButton.getAttribute('data-bm-theme-choice'));
      }
      event.stopImmediatePropagation();
      return;
    }
    var anchor = target.closest('a[href], a[_href]');
    if (anchor && state.reader && state.reader.contains(anchor) && /^\s*目录\s*$/.test(anchor.textContent)) {
      var indexUrl = siteUrl(anchor.getAttribute('href'));
      if (indexUrl && indexUrl.pathname === '/book/' + bookId + '.html') {
        if (event.type === 'click') { event.preventDefault(); openCatalogue(); }
        event.stopImmediatePropagation();
        return;
      }
    }
    // Via 原生阅读的上一页/下一页使用 href="#" 和 _href="实际地址"。
    var href = anchor && (anchor.getAttribute('href') || '#');
    var placeholder = href && /^javascript:\s*(?:void\s*\(\s*0\s*\)\s*;?|;)$/i.test(href.trim());
    if (anchor && ((!placeholder && !siteUrl(href)) ||
        (anchor.hasAttribute('_href') && !siteUrl(anchor.getAttribute('_href'))))) {
      event.preventDefault();
      event.stopImmediatePropagation();
      return;
    }
    if (target.closest('[data-bm-pager-status]')) event.stopImmediatePropagation();
  }
  ['click', 'auxclick', 'pointerdown', 'mousedown', 'touchstart', 'touchend'].forEach(function (type) {
    window.addEventListener(type, guard, { capture: true, passive: false });
  });
  window.addEventListener('submit', function (event) {
    if (event.target && event.target.matches && event.target.matches('.searchBox form')) {
      event.preventDefault(); event.stopImmediatePropagation();
      searchNavigationUntil = Date.now() + 5000;
      location.assign(searchEntry.href);
      return;
    }
    if (event.target && event.target.action && !siteUrl(event.target.action)) {
      event.preventDefault(); event.stopImmediatePropagation();
    }
  }, true);
  if (window.navigation && window.navigation.addEventListener) {
    window.navigation.addEventListener('navigate', function (event) {
      if (event.cancelable && !siteUrl(event.destination.url) &&
          !(state.backupDownloadUrl && event.destination.url === state.backupDownloadUrl) &&
          !intentionalSearchNavigation(event.destination.url)) event.preventDefault();
    });
  }
  if (!bookId) {
    try { localStorage.__via_reader_enabled__ = null; } catch (_) {}
    var catalogMatch = location.pathname.match(/^\/book\/(\d+)\.html$/);
    var visitedCp = Number(new URLSearchParams(location.search).get('cp'));
    if (catalogMatch && visitedCp >= 1 && visitedCp <= 100 && visitedCp % 1 === 0) {
      try { localStorage.setItem('bm-reader-catalog-page-' + catalogMatch[1], String(visitedCp)); } catch (_) {}
    }
    if (catalogMatch) {
      var rememberBookOrders = function () {
        var cp = visitedCp >= 1 && visitedCp <= 100 && visitedCp % 1 === 0 ? visitedCp : 1;
        var key = 'bm-reader-chapter-order-' + catalogMatch[1] + '-v1';
        var titleKey = 'bm-reader-chapter-title-' + catalogMatch[1] + '-v1';
        var orders = new Map();
        var titles = new Map();
        try {
          var stored = JSON.parse(localStorage.getItem(key) || '[]');
          if (Array.isArray(stored)) stored.forEach(function (item) {
            if (Array.isArray(item) && typeof item[0] === 'string' && Number.isInteger(item[1])) {
              orders.set(item[0], item[1]);
            }
          });
        } catch (_) {}
        try {
          var knownTitles = JSON.parse(localStorage.getItem(titleKey) || '[]');
          if (Array.isArray(knownTitles)) knownTitles.forEach(function (item) {
            if (Array.isArray(item) && typeof item[0] === 'string' && typeof item[1] === 'string') {
              titles.set(item[0], cleanChapterTitle(item[1]));
            }
          });
        } catch (_) {}
        var links = document.querySelectorAll('#chapters .direList li .name > a[href]');
        for (var i = 0; i < links.length; i++) {
          var chapter = siteUrl(links[i].getAttribute('href'));
          if (chapter && new RegExp('^/read/' + catalogMatch[1] + '/\\d+\\.html$').test(chapter.pathname) &&
              !chapter.search) {
            orders.set(chapter.pathname, (cp - 1) * 100 + i + 1);
            titles.set(chapter.pathname, cleanChapterTitle(links[i].textContent));
          }
        }
        if (links.length) try { localStorage.setItem(key, JSON.stringify(Array.from(orders))); } catch (_) {}
        if (links.length) try { localStorage.setItem(titleKey, JSON.stringify(Array.from(titles))); } catch (_) {}
      };
      if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', rememberBookOrders, { once: true });
      else rememberBookOrders();
    }
    return;
  }

  function decode(value) {
    var raw = atob(value);
    var bytes = new Uint8Array(raw.length);
    for (var i = 0; i < raw.length; i++) bytes[i] = raw.charCodeAt(i) ^ ((i % 127) + 1);
    if (typeof TextDecoder === 'function') return new TextDecoder('utf-8', { fatal: true }).decode(bytes);
    var percent = '';
    for (var j = 0; j < bytes.length; j++) percent += '%' + ('0' + bytes[j].toString(16)).slice(-2);
    return decodeURIComponent(percent);
  }

  function hidden(node, boundary) {
    for (var el = node; el && el !== boundary; el = el.parentElement) {
      var style = (el.getAttribute('style') || '').replace(/\s/g, '').toLowerCase();
      if (el.hidden || el.getAttribute('aria-hidden') === 'true' || el.classList.contains('honeypot') ||
          /(?:display:none|visibility:hidden|opacity:0(?:;|$)|font-size:0(?:px)?(?:;|$))/.test(style)) return true;
    }
    return false;
  }

  function isChapterArtifact(text) {
    // 只过滤整段残留的空调用;正常正文中的英文 chapter 或引号不会受影响。
    return /^\s*chapter_\s*\(\s*\)\s*;?\s*$/i.test(text);
  }

  function extract(doc, url) {
    var title = doc.querySelector('title');
    var docTitle = doc.title || (title ? title.textContent : '');
    if (doc.querySelector('input[name="GOEDGE_WAF_CAPTCHA_CODE"], #loginForm') ||
        /^(?:身份验证|安全验证|访问验证|人机验证|登录\s*[-—]|Just a moment)/i.test(docTitle.trim())) {
      throw new Error('下一页需要验证码或登录,自动接续已停止');
    }
    var content = doc.querySelector('.conC .content');
    if (!content) throw new Error('未找到下一页正文,自动接续已停止');
    var nodes = content.querySelectorAll('p');
    var paragraphs = [];
    for (var i = 0; i < nodes.length; i++) {
      if (hidden(nodes[i], content)) continue;
      var text = nodes[i].textContent;
      if (nodes[i].hasAttribute('data-obf')) {
        try { text = decode(nodes[i].getAttribute('data-obf')); }
        catch (_) { throw new Error('正文解码失败,自动接续已停止'); }
      }
      if (text && text.trim() && !isChapterArtifact(text)) paragraphs.push(text.trim());
    }
    if (!paragraphs.length) throw new Error('下一页没有可读取的正文,自动接续已停止');
    var heading = doc.querySelector('.conC h1.title');
    var links = doc.querySelectorAll('.readPage a[href]');
    var next = null;
    // 有章内分页时优先下一页,避免网站同时提供下一章而跳过本章后半页。
    for (var kind = 0; kind < 2 && !next; kind++) {
      var pattern = kind === 0 ? /^下一页/ : /^下一章/;
      for (var j = 0; j < links.length; j++) {
        if (!pattern.test(links[j].textContent.trim())) continue;
        next = readUrl(links[j].getAttribute('href'), url.href);
        if (!next) throw new Error('下一页地址不属于本站这本书,自动接续已停止');
        break;
      }
    }
    var chapterInfo = doc.querySelector('.conC .toolBox > .font14');
    return { url: url, title: heading ? heading.textContent.trim() : docTitle,
      docTitle: docTitle, chapterInfo: chapterInfo ? chapterInfo.textContent.trim() : '',
      paragraphs: paragraphs, next: next, content: content };
  }

  function hasPage(target, url) {
    var wanted = pageKey(url);
    if (target.getAttribute('data-bm-page') === wanted) return true;
    var nodes = target.querySelectorAll('[data-bm-page]');
    for (var i = 0; i < nodes.length; i++) if (nodes[i].getAttribute('data-bm-page') === wanted) return true;
    return false;
  }

  function appendPage(target, page) {
    if (!target || hasPage(target, page.url)) return;
    var section = document.createElement('section');
    section.setAttribute('data-bm-page', pageKey(page.url));
    if (page.chapterStart) {
      var title = document.createElement('h2'); title.textContent = page.title; section.appendChild(title);
    }
    page.paragraphs.forEach(function (text) {
      var paragraph = document.createElement('p'); paragraph.textContent = text; section.appendChild(paragraph);
    });
    target.appendChild(section);
  }

  // 只保留当前阅读附近的正文窗口;进度/目录仍能重新打开已经释放的章节。
  // 布局尚不可测量或读者正在回看前文时,宁可延后,也不删掉可见文字。
  function compactReadPages() {
    if (state.compacting || state.busy || state.tocOpen || state.progressOpen || document.hidden ||
        !activeReader() || !state.first || state.pages.length + 1 <= 12) return;
    var pages = [state.first].concat(state.pages);
    var paragraphs = state.content.querySelectorAll('p[data-bm-progress-index]');
    var viewport = state.reader.getBoundingClientRect();
    var height = state.reader.clientHeight;
    if (!(height > 0) || !Number.isFinite(viewport.top)) return;
    var anchorY = viewport.top + Math.min(120, height * .22);
    var visible = null;
    var bounds = null;
    var starts = new Map();
    for (var i = 0; i < paragraphs.length; i++) {
      var paragraph = paragraphs[i];
      var rect = paragraph.getBoundingClientRect();
      var url = readUrl(paragraph.getAttribute('data-bm-progress-url'));
      if (!url || !(rect.height > 0) || !Number.isFinite(rect.top) || !Number.isFinite(rect.bottom)) continue;
      var key = pageKey(url);
      if (!starts.has(key)) starts.set(key, rect.top);
      if (!visible && rect.bottom > anchorY && rect.top < viewport.top + height) {
        visible = paragraph; bounds = rect;
      }
    }
    if (!visible) return;
    var visibleKey = pageKey(readUrl(visible.getAttribute('data-bm-progress-url')));
    var activeIndex = pages.findIndex(function (page) { return pageKey(page.url) === visibleKey; });
    var cut = Math.min(pages.length - 8, activeIndex - 2);
    while (cut > 0 && !(starts.has(pageKey(pages[cut].url)) &&
        starts.get(pageKey(pages[cut].url)) <= viewport.top - 64)) cut--;
    if (!(cut > 0)) return;
    var index = visible.getAttribute('data-bm-progress-index');
    var retained = pages.slice(cut);
    // 关闭再开启原生阅读会重新抽取源正文,因此源页面也必须同步收窄。
    try { history.replaceState(history.state, '', retained[0].url.href); } catch (_) { return; }
    state.compacting = true;
    try {
      saveProgressNow();
      replaceReadingPages(retained[0], retained.slice(1));
      delete retained[0].content;
      state.first = retained[0]; state.pages = retained.slice(1);
      state.compactedPages += cut;
      markProgressParagraphs();
      var updated = state.content.querySelectorAll('p[data-bm-progress-index]');
      for (var j = 0; j < updated.length; j++) {
        if (updated[j].getAttribute('data-bm-progress-url') !== visible.getAttribute('data-bm-progress-url') ||
            updated[j].getAttribute('data-bm-progress-index') !== index) continue;
        var after = updated[j].getBoundingClientRect();
        if (after.height > 0 && Number.isFinite(after.top)) state.reader.scrollTop += after.top - bounds.top;
        break;
      }
      if (state.progressPanel) {
        var note = state.progressPanel.querySelector('[data-bm-memory-note]');
        if (note) note.hidden = false;
      }
    } finally { state.compacting = false; }
  }

  function hideReaderNavigation(reader, content) {
    var metadata = reader.querySelector('.via-reader-header > div');
    if (metadata) metadata.remove();
    var siteNav = content.querySelectorAll('.readPage, .page2-chapter');
    for (var i = 0; i < siteNav.length; i++) siteNav[i].remove();
    // Via 自己在正文末尾附上一组目录/上一页/下一页链接;自动接续和顶部目录
    // 已接管这些功能,因此直接从正文移除,避免朗读或正文识别再次读到它们。
    var paragraphs = content.querySelectorAll('p');
    for (var j = 0; j < paragraphs.length; j++) {
      var paragraph = paragraphs[j];
      if (!paragraph.querySelector('a[_href], a[href*="/book/"]')) continue;
      var text = paragraph.textContent.replace(/[\s||·•]/g, '');
      if (!/^(?:(?:上一|下一)(?:页|章)|目录)+$/.test(text)) continue;
      if (paragraph.nextElementSibling && paragraph.nextElementSibling.tagName === 'BR') {
        paragraph.nextElementSibling.remove();
      }
      paragraph.remove();
    }
  }

  function updateStatus() {
    if (!state.status) return;
    var message = state.blocked ? state.error : state.busy ? '正在接续下一页…' : '';
    if (state.status.getAttribute('data-message') === message) return;
    state.status.setAttribute('data-message', message);
    state.status.textContent = message;
    state.status.hidden = !message;
    if (state.blocked && state.next) {
      var manual = document.createElement('a');
      manual.href = state.next.href; manual.textContent = '打开该页手动处理';
      state.status.appendChild(document.createTextNode(' ')); state.status.appendChild(manual);
    }
  }

  function halt(message) {
    state.blocked = true; state.error = message;
    if (state.timer) { clearTimeout(state.timer); state.timer = null; }
    updateStatus();
  }

  function activeReader() {
    if (!state.reader || !state.reader.isConnected || !state.content || !state.content.isConnected || state.reader.hidden) return false;
    var style = window.getComputedStyle(state.reader);
    return style.display !== 'none' && style.visibility !== 'hidden' && style.visibility !== 'collapse';
  }

  function nearEnd() {
    if (!activeReader() || document.hidden || state.tocOpen || state.progressOpen) return false;
    var height = state.reader.clientHeight;
    if (!(height > 0 && state.reader.scrollHeight >= height)) return false;
    return state.reader.scrollHeight - state.reader.scrollTop - height <= Math.min(350, height * 0.6);
  }

  function schedule() {
    if (state.timer || state.busy || state.blocked || !state.next || !nearEnd()) return;
    state.timer = setTimeout(function () {
      state.timer = null;
      if (nearEnd()) loadNext();
    }, Math.max(250, 2000 - (Date.now() - state.lastRequest)));
  }

  async function loadNext() {
    if (state.busy || state.blocked || !state.next || !nearEnd()) return;
    var readSeq = state.readSeq;
    var url = readUrl(state.next.href);
    if (!url) { halt('下一页地址不属于本站这本书,自动接续已停止'); return; }
    if (state.seen.has(pageKey(url))) { halt('下一页链接重复,自动接续已停止'); return; }
    state.busy = true; state.lastRequest = Date.now(); updateStatus();
    var controller = typeof AbortController === 'function' ? new AbortController() : null;
    var timeout;
    try {
      var operation = (async function () {
        var response = await fetch(url.href, { credentials: 'same-origin', redirect: 'manual',
          signal: controller ? controller.signal : undefined });
        if (response.type === 'opaqueredirect' || (response.status >= 300 && response.status < 400)) {
          throw new Error('下一页要求跳转,可能需要验证码或登录,自动接续已停止');
        }
        if (!response.ok) throw new Error('下一页请求失败(' + response.status + '),自动接续已停止');
        if (response.url) {
          var finalUrl = readUrl(response.url);
          if (!finalUrl || pageKey(finalUrl) !== pageKey(url)) throw new Error('下一页响应地址异常,自动接续已停止');
        }
        var html = await response.text();
        // template 是惰性文档:后页的脚本、图片与 iframe 不执行、不请求。
        var template = document.createElement('template'); template.innerHTML = html;
        return extract(template.content, url);
      })();
      var page = await Promise.race([operation, new Promise(function (_, reject) {
        timeout = setTimeout(function () {
          if (controller) controller.abort();
          reject(new Error('下一页网络超时,自动接续已停止'));
        }, 20000);
      })]);
      if (readSeq !== state.readSeq) return;
      var previous = state.pages.length ? state.pages[state.pages.length - 1].url : state.first.url;
      state.forwardLinks.set(pageKey(previous), pageKey(page.url));
      if (previous.pathname !== page.url.pathname && state.chapterOrders.has(previous.pathname) &&
          !state.chapterOrders.has(page.url.pathname)) {
        state.chapterOrders.set(page.url.pathname, state.chapterOrders.get(previous.pathname) + 1);
        try { localStorage.setItem(chapterOrderKey, JSON.stringify(Array.from(state.chapterOrders))); } catch (_) {}
      }
      page.chapterStart = previous.pathname !== page.url.pathname;
      rememberChapterTitle(page);
      delete page.content;
      state.pages.push(page); state.seen.add(pageKey(page.url)); state.next = page.next;
      appendPage(state.source, page);
      if (activeReader()) { appendPage(state.content, page); markProgressParagraphs(); }
    } catch (error) {
      if (readSeq === state.readSeq) {
        halt(error.name === 'AbortError' ? '下一页网络超时,自动接续已停止' : error.message || '自动接续失败');
      }
    } finally {
      clearTimeout(timeout);
      if (readSeq === state.readSeq) { state.busy = false; updateStatus(); compactReadPages(); }
      // 等下一次读近底部的滚动,不在一次操作后递归预抓整本书。
    }
  }

  function bindReader() {
    var reader = document.querySelector('.via-reader-body');
    var content = reader && reader.querySelector('.via-reader-content');
    if (reader && content) {
      state.autoEntryDone = true;
      if (state.autoEntryTimer) { clearTimeout(state.autoEntryTimer); state.autoEntryTimer = null; }
    }
    if (!state.source || !reader || !content) {
      if (state.reader) {
        state.reader.removeEventListener('scroll', schedule);
        state.reader.removeEventListener('scroll', scheduleProgress);
      }
      state.reader = state.content = state.status = state.paper = state.toolbar = state.toolbarHandle = null;
      state.tocPanel = state.tocList = state.tocPages = state.tocStatus = null;
      state.tocOpen = false; state.tocSeq++;
      state.progressPanel = state.progressList = state.progressStatus = null;
      state.progressOpen = false; state.progressSeq++;
      stopCatalogueRequest();
      if (state.timer) { clearTimeout(state.timer); state.timer = null; }
      if (state.progressTimer) { clearTimeout(state.progressTimer); state.progressTimer = null; }
      return;
    }
    if (reader === state.reader && content === state.content) return;
    if (state.reader) {
      state.reader.removeEventListener('scroll', schedule);
      state.reader.removeEventListener('scroll', scheduleProgress);
    }
    state.reader = reader; state.content = content;
    state.progressTouched = false;
    installThemeControls(reader);
    hideReaderNavigation(reader, content);
    state.pages.forEach(function (page) { appendPage(state.source, page); appendPage(content, page); });
    markProgressParagraphs();
    recordProgress({ url: state.first.url.href, index: 0, ratio: 0,
      time: Date.now(), title: state.first.title }, false, false);
    // 状态行在正文外,不改变阅读界面,也不混进下一次 Readability 正文抽取。
    var status = document.createElement('div'); status.setAttribute('data-bm-pager-status', '');
    status.setAttribute('role', 'status');
    status.style.cssText = 'font-size:.85em;line-height:1.8;margin:12px 16px 24px;';
    status.hidden = true; content.parentElement.appendChild(status); state.status = status;
    reader.addEventListener('scroll', schedule, { passive: true });
    reader.addEventListener('scroll', scheduleProgress, { passive: true });
    restorePendingProgress();
    updateStatus(); schedule();
  }

  function start() {
    var initial = readUrl(location.href);
    var first;
    try { first = extract(document, initial); }
    catch (_) {
      try { localStorage.__via_reader_enabled__ = null; } catch (ignored) {}
      return;
    }
    state.source = first.content; state.first = first; state.next = first.next;
    rememberChapterTitle(first);
    installReaderStyle();
    state.source.setAttribute('data-bm-page', pageKey(initial)); state.seen.add(pageKey(initial));
    // 原节点保留,只把网站编码的文字还原,供 Via 自身 Readability 抽取。
    var nodes = state.source.querySelectorAll('p[data-obf]');
    for (var i = 0; i < nodes.length; i++) {
      if (!hidden(nodes[i], state.source)) nodes[i].textContent = decode(nodes[i].getAttribute('data-obf'));
    }
    var sourceParagraphs = state.source.querySelectorAll('p');
    for (var j = 0; j < sourceParagraphs.length; j++) {
      if (isChapterArtifact(sourceParagraphs[j].textContent)) sourceParagraphs[j].remove();
    }
    // 只有完整章节正文请求 Via 自动开启;原生阅读脚本打开后会清除标记。
    if (!document.querySelector('.via-reader-body') &&
        document.querySelector('.conC h1.title') && document.querySelector('.readPage')) {
      try { localStorage.__via_reader_enabled__ = '1'; } catch (_) {}
      requestAutoReader();
    }
    new MutationObserver(bindReader).observe(document.body, { childList: true, subtree: true });
    window.addEventListener('resize', schedule, { passive: true });
    document.addEventListener('visibilitychange', function () {
      if (document.hidden && (state.progressTouched || !normalizeProgress(state.savedProgress))) saveProgressNow();
      else schedule();
    });
    window.addEventListener('pagehide', function () {
      if (state.progressTouched || !normalizeProgress(state.savedProgress)) saveProgressNow();
    });
    bindReader();
  }

  function requestAutoReader() {
    if (state.autoEntryDone || state.autoEntryTimer) return;
    state.autoEntryTimer = setTimeout(function () {
      state.autoEntryTimer = null;
      if (state.autoEntryDone || !state.first || !document.body) return;
      state.autoEntryDone = true;
      if (document.querySelector('.via-reader-body')) { bindReader(); return; }
      var reader = document.createElement('div');
      reader.className = 'via-reader-body';
      reader.setAttribute('data-bm-auto-reader', '');
      var frame = document.createElement('div');
      frame.style.cssText = 'width:100%;box-sizing:border-box;font-size:' + fontSize + 'px;';
      var header = document.createElement('div'); header.className = 'via-reader-header';
      var title = document.createElement('h1'); title.textContent = state.first.title;
      header.appendChild(title); frame.appendChild(header);
      var content = document.createElement('div'); content.className = 'via-reader-content';
      state.first.paragraphs.forEach(function (text) {
        var paragraph = document.createElement('p'); paragraph.textContent = text; content.appendChild(paragraph);
      });
      frame.appendChild(content); reader.appendChild(frame);
      var key = 'via-reader-data';
      if (!document.body.hasAttribute(key)) document.body.setAttribute(key, document.body.style.overflow);
      document.body.style.overflow = 'hidden';
      var viewport = document.querySelector('meta[name="viewport"]');
      if (viewport && !viewport.hasAttribute(key)) {
        viewport.setAttribute(key, viewport.getAttribute('content') || '');
        viewport.setAttribute('content', 'width=device-width');
      }
      try { localStorage.__via_reader_enabled__ = null; } catch (_) {}
      document.body.appendChild(reader);
      bindReader();
    }, 500);
  }

  function exitAssistedReader() {
    var reader = state.reader;
    if (!reader || !reader.hasAttribute('data-bm-auto-reader')) return;
    if (state.progressOpen) closeProgressPanel();
    saveProgressNow();
    state.autoEntryDone = true;
    if (state.autoEntryTimer) { clearTimeout(state.autoEntryTimer); state.autoEntryTimer = null; }
    var key = 'via-reader-data';
    if (document.body.hasAttribute(key)) {
      document.body.style.overflow = document.body.getAttribute(key);
      document.body.removeAttribute(key);
    }
    var viewport = document.querySelector('meta[name="viewport"]');
    if (viewport && viewport.hasAttribute(key)) {
      viewport.setAttribute('content', viewport.getAttribute(key)); viewport.removeAttribute(key);
    }
    reader.remove(); bindReader();
  }
  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', start, { once: true });
  else start();
})();

$ tail -f comments.log

Comments [0]

// no comments yet