禁漫天堂

https://jm18c-uoi.net

分享者: haobai1 (12083)发布时间: 6天前

发布页:
https://jmcomicgo.me
https://jmcmomic.github.io
二维码导入
{
    "articleStyle": 3,
    "cacheFirst": false,
    "customOrder": 2,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": false,
    "lastUpdateTime": 1772213501009,
    "loadWithBaseUrl": true,
    "preload": false,
    "ruleArticles": "class.list-col",
    "ruleContent": "<html>\n<head>\n<title>{{@.dropdown-menu.series_drop@p@text}}{{@@title@text}}<\/title>\n{{@meta@html}}\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/blueimp-md5\/2.19.0\/js\/md5.min.js\"><\/script>\n<link rel=\"stylesheet\" href=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/font-awesome\/6.0.0\/css\/all.min.css\">\n<\/head>\n<body>\n<button id=\"detail-button\" class=\"is-detail\">\n    <div class=\"hamburger\">\n        <span><\/span>\n        <span><\/span>\n        <span><\/span>\n    <\/div>\n<\/button>\n\n<button id=\"auto-scroll-button\" class=\"floating-btn\">\n    <i class=\"fas fa-play\"><\/i>\n<\/button>\n\n<button id=\"comment-button\" class=\"floating-comment-btn\">\n    <i class=\"fas fa-comments\"><\/i>\n<\/button>\n\n<div style=\"display:none\">{{@.dropdown-menu.series_drop@html}}<\/div>\n<div id=\"comic-content\" class=\"comic-content\" style=\"display:none;\">\n    <div class=\"loading\" id=\"initial-loading\">正在加载漫画...<\/div>\n<\/div>\n<div id=\"detail-page\" class=\"detail-container\"><\/div>\n<div id=\"bottom-loader\" class=\"loading\" style=\"display:none\"><\/div>\n<div id=\"end-message\" class=\"end-message\">已经到底了<\/div>\n\n<script>\nlet isDetailView = true,\n    currentChapters = [],\n    activeChapterIndex = -1,\n    config = {\n        currentChapter: 1,\n        totalChapters: 0,\n        isLoading: false,\n        hasMore: true,\n        nextChapterUrl: null\n    },\n    comicScrollPosition = 0,\n    commentsCurrentPage = 1,\n    commentsIsLoading = false,\n    commentsHasMore = true,\n    currentTab = 'chapters',\n    currentChapterId = null;\n\nlet currentChapterImages = [];\nlet displayedImagesCount = 0;\nlet imagesPerBatch = 300;\nlet batchLoading = false;\nlet allImagesLoaded = false;\n\nlet autoScrollEnabled = false;\nlet autoScrollAnimationId = null;\nlet autoScrollSpeed = 180;\n\nlet chapterReadStatus = {};\nlet lastActiveChapter = null;\n\nconst getMetaContent = p => {\n        const el = document.querySelector(`meta[property=\"${p}\"], meta[name=\"${p}\"]`);\n        return el ? el.getAttribute('content') || '' : '';\n    },\n    getSeriesId = () => {\n        const url = getMetaContent('og:url') || window.location.href;\n        const m = url.match(\/\\\/photo\\\/(\\d+)\/);\n        return m ? m[1] : '';\n    },\n    getCoverUrl = () => {\n        const o = getMetaContent('og:image'),\n              s = getSeriesId();\n        if (!o || !s) return '';\n        try {\n            return `https:\/\/${new URL(o.replace(\/\\\\\\\/\/g, '\/')).hostname}\/media\/albums\/${s}.jpg`;\n        } catch {\n            return '';\n        }\n    },\n    getChaptersData = (html = null) => {\n        const c = [];\n        const container = html ? \n            (() => {\n                const d = document.createElement('div');\n                d.innerHTML = html;\n                return d;\n            })() : \n            document;\n        \n        container.querySelectorAll('.series_drop_item').forEach(e => {\n            const h = e.getAttribute('href'),\n                  t = e.textContent.trim();\n            if (h && t) c.push({ \n                url: h.split('?')[0], \n                number: t, \n                title: t,\n                id: h.split('?')[0].match(\/\\\/photo\\\/(\\d+)\/)?.[1]\n            });\n        });\n        return c;\n    },\n    getTagsData = () => {\n        const k = getMetaContent('keywords');\n        return k ? k.split(',').map(t => t.trim()).filter(t => t) : [];\n    },\n    extractChapterIdFromUrl = u => {\n        const m = u ? u.match(\/\\\/photo\\\/(\\d+)\/) : null;\n        return m ? m[1] : null;\n    };\n\nconst highlightCurrentChapter = () => {\n    const chapterLinks = document.querySelectorAll('.chapter-link');\n    chapterLinks.forEach(link => {\n        link.classList.remove('active');\n        const index = parseInt(link.getAttribute('data-index'));\n        if (chapterReadStatus[index]) {\n            link.classList.add('read');\n        } else {\n            link.classList.remove('read');\n        }\n        if (index === activeChapterIndex) {\n            link.classList.add('active');\n            const chaptersList = document.querySelector('.chapters-list');\n            if (chaptersList && link.offsetTop > chaptersList.scrollTop + chaptersList.clientHeight - 50) {\n                chaptersList.scrollTop = link.offsetTop - chaptersList.offsetTop - 100;\n            } else if (link.offsetTop < chaptersList.scrollTop) {\n                chaptersList.scrollTop = link.offsetTop - chaptersList.offsetTop;\n            }\n        }\n    });\n};\n\nconst markChapterAsRead = (chapterIndex) => {\n    if (chapterIndex >= 0) {\n        chapterReadStatus[chapterIndex] = true;\n        const seriesId = getSeriesId();\n        if (seriesId) {\n            const key = `jm_${seriesId}_read`;\n            localStorage.setItem(key, JSON.stringify(chapterReadStatus));\n        }\n        highlightCurrentChapter();\n    }\n};\n\nconst loadReadStatus = () => {\n    const seriesId = getSeriesId();\n    if (seriesId) {\n        const key = `jm_${seriesId}_read`;\n        const saved = localStorage.getItem(key);\n        if (saved) {\n            try {\n                chapterReadStatus = JSON.parse(saved);\n            } catch (e) {\n                chapterReadStatus = {};\n            }\n        }\n    }\n};\n\nconst updateCurrentChapterInDirectory = (chapterIndex) => {\n    if (chapterIndex !== activeChapterIndex) {\n        lastActiveChapter = activeChapterIndex;\n        activeChapterIndex = chapterIndex;\n        if (lastActiveChapter !== null && lastActiveChapter >= 0) {\n            markChapterAsRead(lastActiveChapter);\n        }\n        if (isDetailView && currentTab === 'chapters') {\n            highlightCurrentChapter();\n        }\n    }\n};\n\nconst detectCurrentChapter = () => {\n    if (isDetailView || currentChapters.length === 0) return;\n    \n    const scrollPosition = window.scrollY + window.innerHeight \/ 3;\n    const chapters = document.querySelectorAll('.chapter-title');\n    \n    let currentFound = false;\n    \n    for (let i = 0; i < chapters.length; i++) {\n        const chapter = chapters[i];\n        const rect = chapter.getBoundingClientRect();\n        const top = rect.top + window.scrollY;\n        const bottom = rect.bottom + window.scrollY;\n        \n        if (scrollPosition >= top && scrollPosition <= bottom) {\n            const chapterNum = parseInt(chapter.textContent.match(\/第(\\d+)话\/)?.[1]);\n            if (chapterNum && chapterNum - 1 !== activeChapterIndex) {\n                updateCurrentChapterInDirectory(chapterNum - 1);\n                currentFound = true;\n                break;\n            }\n        }\n    }\n    if (!currentFound && chapters.length > 0) {\n        const lastChapter = chapters[chapters.length - 1];\n        const rect = lastChapter.getBoundingClientRect();\n        if (scrollPosition > rect.bottom + window.scrollY) {\n            const chapterNum = parseInt(lastChapter.textContent.match(\/第(\\d+)话\/)?.[1]);\n            if (chapterNum && chapterNum - 1 !== activeChapterIndex) {\n                updateCurrentChapterInDirectory(chapterNum - 1);\n            }\n        }\n    }\n};\n\nconst findLastReadChapterIndex = () => {\n    let lastReadIndex = -1;\n    for (let i = 0; i < currentChapters.length; i++) {\n        if (chapterReadStatus[i]) {\n            lastReadIndex = i;\n        }\n    }\n    return lastReadIndex;\n};\n\nconst toggleElementDisplay = (id, display) => {\n    const el = document.getElementById(id);\n    if (el) el.style.display = display;\n};\n\nconst toggleButtonClass = () => {\n    const detailButton = document.getElementById('detail-button');\n    if (detailButton) {\n        if (isDetailView) {\n            detailButton.classList.replace('is-reader', 'is-detail');\n        } else {\n            detailButton.classList.replace('is-detail', 'is-reader');\n        }\n    }\n};\n\nconst getSeriesTitle = () => {\n    const ogTitle = getMetaContent('og:title');\n    if (ogTitle && ogTitle.trim()) {\n        return ogTitle.trim()\n            .replace(\/^\\d+\\s*-\\s*\/, '')\n            .replace(\/\\|H漫內頁瀏覽 Comics - 禁漫天堂\/, '')\n            .trim();\n    }\n    \n    const pageTitle = document.title || '';\n    if (pageTitle) {\n        return pageTitle.trim();\n    }\n    \n    return '未知标题';\n};\n\nconst updateCommentHeaderText = (status = 'loading', commentCount = 0) => {\n    const tc = document.querySelector('.total-comments');\n    if (!tc) return;\n    \n    const chapterNum = Math.max(config.currentChapter, 1);\n    let text = '';\n    \n    switch(status) {\n        case 'loading':\n            text = `<i class=\"fas fa-comments\"><\/i> 正在加载第${chapterNum}话评论...`;\n            break;\n        case 'loaded':\n            if (commentCount === 0) {\n                text = `<i class=\"fas fa-comments\"><\/i> 第${chapterNum}话评论 (0)`;\n            } else {\n                text = `<i class=\"fas fa-comments\"><\/i> 第${chapterNum}话评论 (${commentCount})`;\n            }\n            break;\n        case 'empty':\n            text = `<i class=\"fas fa-comments\"><\/i> 第${chapterNum}话评论 (0)`;\n            break;\n        case 'error':\n            text = `<i class=\"fas fa-comments\"><\/i> 第${chapterNum}话评论加载失败`;\n            break;\n        default:\n            text = `<i class=\"fas fa-comments\"><\/i> 第${chapterNum}话评论`;\n    }\n    \n    tc.innerHTML = text;\n};\n\nconst toggleAutoScroll = () => {\n    autoScrollEnabled = !autoScrollEnabled;\n    const autoScrollBtn = document.getElementById('auto-scroll-button');\n    \n    if (autoScrollBtn) {\n        if (autoScrollEnabled) {\n            autoScrollBtn.classList.add('active');\n            autoScrollBtn.innerHTML = '<i class=\"fas fa-pause\"><\/i>';\n            startAutoScroll();\n        } else {\n            autoScrollBtn.classList.remove('active');\n            autoScrollBtn.innerHTML = '<i class=\"fas fa-play\"><\/i>';\n            stopAutoScroll();\n        }\n    }\n};\n\nconst startAutoScroll = () => {\n    let lastScrollTime = 0;\n    const scrollPerFrame = autoScrollSpeed \/ 60;\n    \n    function smoothScroll(currentTime) {\n        if (!autoScrollEnabled || isDetailView) return;\n        \n        const elapsed = currentTime - lastScrollTime;\n        \n        if (elapsed >= 16) {\n            detectCurrentChapter();\n            \n            const scrollPosition = window.innerHeight + window.scrollY;\n            const documentHeight = document.documentElement.scrollHeight;\n            \n            if (scrollPosition >= documentHeight - 100) {\n                stopAutoScroll();\n                return;\n            }\n            \n            window.scrollBy({\n                top: scrollPerFrame,\n                behavior: 'instant'\n            });\n            \n            lastScrollTime = currentTime;\n        }\n        \n        if (autoScrollEnabled) {\n            autoScrollAnimationId = requestAnimationFrame(smoothScroll);\n        }\n    }\n    \n    autoScrollAnimationId = requestAnimationFrame(smoothScroll);\n};\n\nconst stopAutoScroll = () => {\n    if (autoScrollAnimationId) {\n        cancelAnimationFrame(autoScrollAnimationId);\n        autoScrollAnimationId = null;\n    }\n    autoScrollEnabled = false;\n};\n\nconst startReading = () => {\n    const lastReadIndex = findLastReadChapterIndex();\n    let startChapterIndex;\n    \n    if (lastReadIndex >= 0) {\n        if (lastReadIndex + 1 < currentChapters.length) {\n            startChapterIndex = lastReadIndex + 1;\n        } else {\n            startChapterIndex = lastReadIndex;\n        }\n    } else {\n        startChapterIndex = 0;\n    }\n    \n    if (currentChapters[startChapterIndex]) {\n        updateCurrentChapterInDirectory(startChapterIndex);\n        config.currentChapter = startChapterIndex + 1;\n        loadChapterByUrl(currentChapters[startChapterIndex].url, startChapterIndex);\n        showReaderView();\n    }\n};\n\nconst showDetailPage = () => {\n    stopAutoScroll();\n    \n    comicScrollPosition = window.scrollY || document.documentElement.scrollTop;\n    isDetailView = true;\n    window.scrollTo(0, 0);\n    \n    toggleElementDisplay('comic-content', 'none');\n    toggleElementDisplay('bottom-loader', 'none');\n    toggleElementDisplay('end-message', 'none');\n    \n    toggleButtonClass();\n    \n    const dc = document.getElementById('detail-page');\n    if (!dc) return;\n    \n    dc.style.display = 'block';\n    \n    const title = getSeriesTitle();\n    let desc = (getMetaContent('og:description') || getMetaContent('description') || '');\n    const cover = getCoverUrl();\n    const tags = getTagsData();\n    const seriesId = getSeriesId();\n    \n    const lastReadIndex = findLastReadChapterIndex();\n    const hasReadChapters = lastReadIndex >= 0;\n    const continueReadingText = hasReadChapters ? '继续阅读' : '立即阅读';\n    \n    if (desc) {\n        desc = desc.replace(\/-免費成人H漫線上看\/, '').trim();\n    }\n    \n    let html = `<div class=\"detail-header\"><div class=\"info-container\">\n        <h2 class=\"detail-title\">${title}<\/h2>\n        <div class=\"cover-container\">${cover ? `<img src=\"${cover}\" alt=\"${title}\" class=\"cover-image\" onerror=\"this.style.display='none'\">` : ''}<\/div>\n        <div class=\"detail-meta\">${seriesId ? `<span>作品ID: ${seriesId}<\/span>` : ''}${currentChapters.length > 0 ? `<span>目录数: ${currentChapters.length}<\/span>` : ''}<\/div>\n        <button class=\"start-reading-btn\" onclick=\"startReading()\">${continueReadingText}<\/button>\n        ${desc ? `<div class=\"detail-description\">${desc}<\/div>` : ''}\n        ${tags.length > 0 ? `<div class=\"detail-tags\">${tags.map(t => `<span class=\"tag\">${t}<\/span>`).join('')}<\/div>` : ''}\n    <\/div><\/div>`;\n    \n    html += `<div class=\"chapters-section\"><h2 class=\"section-title\">作品详情<\/h2>`;\n    \n    if (currentChapters.length <= 1) {\n        currentTab = 'comments';\n        html += `<div class=\"tab-container\">\n            <div class=\"tab-header\">\n                <button class=\"tab-btn active\" onclick=\"switchTab('comments')\">评论<\/button>\n            <\/div>\n            <div class=\"tab-content\">\n                <div id=\"commentsTabContent\">\n                    <div class=\"comments-container\">\n                        <div class=\"comments-header\"><div class=\"total-comments\"><i class=\"fas fa-comments\"><\/i> 评论区<\/div><\/div>\n                        <section class=\"comment-list\" id=\"commentContainer\"><\/section>\n                        <button class=\"load-more-btn\" id=\"loadMoreBtn\"><i class=\"fas fa-spinner fa-spin\" style=\"display:none;\"><\/i><span>查看更多评论<\/span><\/button>\n                    <\/div>\n                <\/div>\n            <\/div>\n        <\/div>`;\n    } else {\n        html += `<div class=\"tab-container\">\n            <div class=\"tab-header\">\n                <button class=\"tab-btn ${currentTab === 'chapters' ? 'active' : ''}\" onclick=\"switchTab('chapters')\">目录<\/button>\n                <button class=\"tab-btn ${currentTab === 'comments' ? 'active' : ''}\" onclick=\"switchTab('comments')\">评论<\/button>\n            <\/div>\n            <div class=\"tab-content\">\n                ${currentTab === 'chapters' ? `\n                <div class=\"chapters-list\" id=\"chapters-list\">\n                    ${currentChapters.map((c, i) => `\n                        <a href=\"javascript:void(0);\" data-index=\"${i}\" data-url=\"${c.url}\" class=\"chapter-item chapter-link ${i === activeChapterIndex ? 'active' : ''} ${chapterReadStatus[i] ? 'read' : ''}\">\n                            <div class=\"chapter-number\">${c.number}<\/div>\n                            ${i === activeChapterIndex ? '<div class=\"chapter-progress\">当前阅读<\/div>' : ''}\n                        <\/a>`).join('')}\n                <\/div>` : `\n                <div id=\"commentsTabContent\">\n                    <div class=\"comments-container\">\n                        <div class=\"comments-header\"><div class=\"total-comments\"><\/div><\/div>\n                        <section class=\"comment-list\" id=\"commentContainer\"><\/section>\n                        <button class=\"load-more-btn\" id=\"loadMoreBtn\"><i class=\"fas fa-spinner fa-spin\" style=\"display:none;\"><\/i><span>查看更多评论<\/span><\/button>\n                    <\/div>\n                <\/div>`}\n            <\/div>\n        <\/div>`;\n    }\n    \n    html += `<\/div>`;\n    \n    dc.innerHTML = html;\n    \n    initCommentsSystem();\n    \n    let chapterId;\n    if (activeChapterIndex >= 0 && currentChapters[activeChapterIndex]) {\n        chapterId = extractChapterIdFromUrl(currentChapters[activeChapterIndex].url);\n    } else {\n        chapterId = extractChapterIdFromUrl(window.location.href);\n    }\n    \n    if (chapterId) {\n        currentChapterId = chapterId;\n        loadComments(currentChapterId, 1);\n    }\n    \n    if (currentChapters.length > 1) {\n        const chapterLinks = document.querySelectorAll('.chapter-link');\n        chapterLinks.forEach(l => {\n            l.addEventListener('click', function(e) {\n                e.preventDefault();\n                const i = parseInt(this.getAttribute('data-index'));\n                updateCurrentChapterInDirectory(i);\n                config.currentChapter = i + 1;\n                loadChapterByUrl(this.getAttribute('data-url'), i);\n                showReaderView();\n            });\n        });\n    }\n    \n    highlightCurrentChapter();\n};\n\nconst showReaderView = () => {\n    isDetailView = false;\n    \n    toggleElementDisplay('detail-page', 'none');\n    toggleElementDisplay('comic-content', 'block');\n    \n    toggleButtonClass();\n    \n    setTimeout(() => {\n        window.scrollTo(0, comicScrollPosition);\n    }, 0);\n};\n\nconst switchToComments = () => {\n    if (!isDetailView) {\n        showDetailPage();\n        setTimeout(() => {\n            switchTab('comments');\n            document.querySelector('#commentsTabContent')?.scrollIntoView({\n                behavior: 'smooth',\n                block: 'start'\n            });\n        }, 250);\n    } else {\n        switchTab('comments');\n        setTimeout(() => {\n            document.querySelector('#commentsTabContent')?.scrollIntoView({\n                behavior: 'smooth',\n                block: 'start'\n            });\n        }, 50);\n    }\n};\n\nfunction switchTab(t) {\n    currentTab = t;\n    \n    const tabButtons = document.querySelectorAll('.tab-btn');\n    tabButtons.forEach(b => {\n        b.classList.remove('active');\n        if (b.textContent.includes(t === 'chapters' ? '目录' : '评论')) {\n            b.classList.add('active');\n        }\n    });\n    \n    const tc = document.querySelector('.tab-content');\n    if (!tc) return;\n    \n    if (t === 'chapters') {\n        if (currentChapters.length > 1) {\n            tc.innerHTML = `<div class=\"chapters-list\" id=\"chapters-list\">\n                ${currentChapters.map((c, i) => `\n                    <a href=\"javascript:void(0);\" data-index=\"${i}\" data-url=\"${c.url}\" class=\"chapter-item chapter-link ${i === activeChapterIndex ? 'active' : ''} ${chapterReadStatus[i] ? 'read' : ''}\">\n                        <div class=\"chapter-number\">${c.number}<\/div>\n                        ${i === activeChapterIndex ? '<div class=\"chapter-progress\">当前阅读<\/div>' : ''}\n                    <\/a>`).join('')}\n            <\/div>`;\n            \n            const chapterLinks = document.querySelectorAll('.chapter-link');\n            chapterLinks.forEach(l => {\n                l.addEventListener('click', function(e) {\n                    e.preventDefault();\n                    const i = parseInt(this.getAttribute('data-index'));\n                    updateCurrentChapterInDirectory(i);\n                    config.currentChapter = i + 1;\n                    loadChapterByUrl(this.getAttribute('data-url'), i);\n                    showReaderView();\n                });\n            });\n            highlightCurrentChapter();\n        } else {\n            switchTab('comments');\n            return;\n        }\n    } else {\n        tc.innerHTML = `<div id=\"commentsTabContent\">\n            <div class=\"comments-container\">\n                <div class=\"comments-header\"><div class=\"total-comments\"><\/div><\/div>\n                <section class=\"comment-list\" id=\"commentContainer\"><\/section>\n                <button class=\"load-more-btn\" id=\"loadMoreBtn\"><i class=\"fas fa-spinner fa-spin\" style=\"display:none;\"><\/i><span>查看更多评论<\/span><\/button>\n            <\/div>\n        <\/div>`;\n        \n        initCommentsSystem();\n        \n        if (currentChapterId) {\n            commentsCurrentPage = 1;\n            commentsHasMore = true;\n            const cc = document.getElementById('commentContainer');\n            if (cc) cc.innerHTML = '<div class=\"loading\" style=\"text-align:center;padding:20px;\">正在加载评论...<\/div>';\n            \n            updateCommentHeaderText('loading');\n            \n            loadComments(currentChapterId, commentsCurrentPage);\n        }\n    }\n}\n\nfunction initCommentsSystem() {\n    const b = document.getElementById('loadMoreBtn');\n    if (b) {\n        b.addEventListener('click', () => {\n            if (!commentsIsLoading && commentsHasMore) {\n                commentsCurrentPage++;\n                loadComments(currentChapterId, commentsCurrentPage);\n            }\n        });\n    }\n}\n\nfunction loadComments(cid, page) {\n    if (!cid) return;\n    \n    commentsIsLoading = true;\n    const b = document.getElementById('loadMoreBtn');\n    if (!b) return;\n    \n    const s = b.querySelector('.fa-spinner'),\n          t = b.querySelector('span');\n    s.style.display = 'inline-block';\n    t.textContent = '加载中...';\n    b.disabled = true;\n    \n    updateCommentHeaderText('loading');\n    \n    fetch(`${window.location.origin}\/ajax\/album_pagination`, {\n        method: \"POST\",\n        headers: {\"Content-Type\": \"application\/x-www-form-urlencoded\"},\n        body: `video_id=${cid}&page=${page}`\n    })\n    .then(r => r.text())\n    .then(d => {\n        if (d.trim() === '' || d.includes('没有评论')) {\n            commentsHasMore = false;\n            b.style.display = 'none';\n            const cc = document.getElementById('commentContainer');\n            if (cc && page === 1) {\n                cc.innerHTML = `<div style=\"text-align:center;padding:30px;color:#999;\">第${Math.max(config.currentChapter, 1)}话暂无评论<\/div>`;\n                updateCommentHeaderText('empty');\n            }\n        } else {\n            const hasNextPage = d.includes('btn-primary');\n            \n            if (!hasNextPage) {\n                commentsHasMore = false;\n            }\n            \n            const td = document.createElement('div');\n            td.innerHTML = d;\n            td.querySelectorAll('.disclose').forEach(sc => {\n                const tl = sc.closest('.timeline');\n                if (tl) {\n                    const hc = tl.querySelector('.timeline-content[style*=\"display: none\"]');\n                    sc.remove();\n                    if (hc) hc.style.display = 'block';\n                }\n            });\n            \n            const cc = document.getElementById('commentContainer');\n            if (cc) {\n                if (page === 1) {\n                    cc.innerHTML = td.innerHTML;\n                } else {\n                    cc.insertAdjacentHTML('beforeend', td.innerHTML);\n                }\n                const cs = cc.querySelectorAll('.timeline-panel');\n                updateCommentHeaderText('loaded', cs.length);\n            }\n            \n            if (!hasNextPage) {\n                b.style.display = 'none';\n                const cc = document.getElementById('commentContainer');\n                if (cc && page >= 1) {\n                    const endDiv = document.createElement('div');\n                    endDiv.style.textAlign = 'center';\n                    endDiv.style.padding = '15px';\n                    endDiv.style.color = '#999';\n                    endDiv.innerHTML = '已加载所有评论';\n                    cc.appendChild(endDiv);\n                }\n            }\n        }\n    })\n    .catch((error) => {\n        console.error('Error loading comments:', error);\n        commentsCurrentPage--;\n        commentsHasMore = false;\n        b.style.display = 'none';\n        const cc = document.getElementById('commentContainer');\n        if (cc && page === 1) {\n            cc.innerHTML = `<div style=\"text-align:center;padding:30px;color:#ff6b6b;\">第${Math.max(config.currentChapter, 1)}话评论加载失败<\/div>`;\n            updateCommentHeaderText('error');\n        }\n    })\n    .finally(() => {\n        commentsIsLoading = false;\n        if (b && b.style.display !== 'none') {\n            s.style.display = 'none';\n            t.textContent = '查看更多评论';\n            b.disabled = false;\n        }\n    });\n}\n\nconst loadChapterByUrl = (u, i) => {\n    stopAutoScroll();\n    \n    comicScrollPosition = 0;\n    window.scrollTo(0, 0);\n    \n    const comicContent = document.getElementById('comic-content');\n    if (comicContent) {\n        comicContent.innerHTML = '<div class=\"loading\" id=\"initial-loading\">正在加载漫画...<\/div>';\n    }\n    \n    const initialLoading = document.getElementById('initial-loading');\n    if (initialLoading) initialLoading.style.display = 'block';\n    \n    updateCurrentChapterInDirectory(i);\n    config.currentChapter = i + 1;\n    config.isLoading = true;\n    config.hasMore = true;\n    \n    currentChapterImages = [];\n    displayedImagesCount = 0;\n    allImagesLoaded = false;\n    batchLoading = false;\n    \n    const nid = extractChapterIdFromUrl(u);\n    if (nid) {\n        currentChapterId = nid;\n        if (isDetailView && currentTab === 'comments') {\n            commentsCurrentPage = 1;\n            commentsHasMore = true;\n            const cc = document.getElementById('commentContainer');\n            if (cc) cc.innerHTML = '<div class=\"loading\" style=\"text-align:center;padding:20px;\">正在加载评论...<\/div>';\n            \n            updateCommentHeaderText('loading');\n            \n            loadComments(currentChapterId, 1);\n        }\n    }\n    \n    const x = new XMLHttpRequest();\n    x.open('GET', u, true);\n    x.timeout = 10000;\n    x.onload = async () => {\n        if (x.status === 200) {\n            currentChapters = getChaptersData(x.responseText);\n            await processChapterContent(x.responseText, config.currentChapter, true);\n            config.isLoading = false;\n            if (isDetailView && currentTab === 'chapters') {\n                highlightCurrentChapter();\n            }\n        }\n    };\n    x.onerror = x.ontimeout = () => config.isLoading = false;\n    x.send();\n};\n\nconst extractAllImageUrls = h => {\n    const d = document.createElement('div');\n    d.innerHTML = h;\n    const imgs = d.querySelectorAll('.spnotice_chk img[data-original]');\n    const urls = [];\n    \n    imgs.forEach(img => {\n        const u = img.getAttribute('data-original');\n        if (u && !u.includes('blank.jpg')) {\n            urls.push(u);\n        }\n    });\n    \n    return urls;\n};\n\nconst decryptImage = (src, imgElement) => {\n    const m = src.match(\/photos\\\/(\\d+)\\\/(\\d+)\/);\n    if (!m) return Promise.resolve();\n    \n    const b = m[1], i = m[2].split('.')[0], bn = parseInt(b);\n    \n    let n;\n    if (bn > 421925) n = (md5(b + i).charCodeAt(md5(b + i).length - 1) % 8 + 1) * 2;\n    else if (bn >= 268850) n = (md5(b + i).charCodeAt(md5(b + i).length - 1) % 10 + 1) * 2;\n    else n = 10;\n    \n    return new Promise(resolve => {\n        const tempImg = new Image();\n        tempImg.crossOrigin = 'anonymous';\n        \n        tempImg.onload = () => {\n            const canvas = document.createElement('canvas');\n            const ctx = canvas.getContext('2d');\n            canvas.width = tempImg.width;\n            canvas.height = tempImg.height;\n            \n            const w = tempImg.width, h = tempImg.height;\n            const y = Math.floor(h \/ n), r = h % n;\n            \n            for (let j = 1; j <= n; j++) {\n                let sy = y * (j - 1), sh = y, dy = h - (y * j);\n                if (j === n) { sh += r; dy -= r; }\n                if (dy < 0) dy = 0;\n                ctx.drawImage(tempImg, 0, sy, w, sh, 0, dy, w, sh);\n            }\n            \n            imgElement.src = canvas.toDataURL();\n            resolve();\n        };\n        \n        tempImg.onerror = () => {\n            imgElement.src = src;\n            resolve();\n        };\n        \n        tempImg.src = src;\n    });\n};\n\nconst loadImageWithPlaceholder = async (src, placeholderImg) => {\n    const m = src.match(\/photos\\\/(\\d+)\\\/(\\d+)\/);\n    \n    if (m && !src.includes('.gif') && parseInt(m[1]) >= 220980) {\n        await decryptImage(src, placeholderImg);\n    } else {\n        placeholderImg.src = src;\n    }\n};\n\nconst displayImageBatch = async (startIndex) => {\n    if (batchLoading || startIndex >= currentChapterImages.length) return;\n    \n    batchLoading = true;\n    \n    const endIndex = Math.min(startIndex + imagesPerBatch, currentChapterImages.length);\n    const comicContent = document.getElementById('comic-content');\n    if (!comicContent) return;\n    \n    const chapterContainer = comicContent.querySelector(`#chapter-${config.currentChapter}`);\n    if (!chapterContainer) return;\n    \n    for (let i = startIndex; i < endIndex; i++) {\n        const placeholder = document.createElement('img');\n        placeholder.className = 'comic-page';\n        placeholder.style.width = '100%';\n        placeholder.style.height = 'auto';\n        placeholder.style.minHeight = '200px';\n        placeholder.style.backgroundColor = '#f5f5f5';\n        placeholder.src = 'data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';\n        chapterContainer.appendChild(placeholder);\n        \n        loadImageWithPlaceholder(currentChapterImages[i], placeholder);\n    }\n    \n    displayedImagesCount = endIndex;\n    batchLoading = false;\n    \n    if (endIndex >= currentChapterImages.length) {\n        allImagesLoaded = true;\n    }\n};\n\nconst processChapterContent = async (h, cn, first) => {\n    const comicContent = document.getElementById('comic-content');\n    if (!comicContent) return;\n    \n    const oldChapter = comicContent.querySelector(`#chapter-${cn}`);\n    if (oldChapter) oldChapter.remove();\n    \n    const cc = document.createElement('div');\n    cc.id = `chapter-${cn}`;\n    comicContent.appendChild(cc);\n    \n    const t = document.createElement('div');\n    t.className = 'chapter-title';\n    if (first) {\n        config.totalChapters = currentChapters.length;\n        t.textContent = `第${cn}话,共${config.totalChapters}话`;\n    } else {\n        t.textContent = `第${cn}话,共${config.totalChapters}话`;\n    }\n    if (config.totalChapters <= 1) t.style.display = 'none';\n    cc.appendChild(t);\n    \n    if (first) {\n        toggleElementDisplay('initial-loading', 'none');\n    }\n    \n    currentChapterImages = extractAllImageUrls(h);\n    displayedImagesCount = 0;\n    allImagesLoaded = false;\n    \n    await displayImageBatch(0);\n    \n    if (activeChapterIndex + 1 < currentChapters.length) {\n        const nextBtn = document.createElement('button');\n        nextBtn.className = 'next-chapter-btn';\n        nextBtn.innerHTML = '下一话';\n        nextBtn.onclick = () => {\n            const nextChapterIndex = activeChapterIndex + 1;\n            const nextChapter = currentChapters[nextChapterIndex];\n            if (nextChapter) {\n                updateCurrentChapterInDirectory(nextChapterIndex);\n                config.currentChapter = nextChapterIndex + 1;\n                loadChapterByUrl(nextChapter.url, nextChapterIndex);\n            }\n        };\n        cc.appendChild(nextBtn);\n    }\n};\n\nwindow.addEventListener('DOMContentLoaded', () => {\n    const i = extractChapterIdFromUrl(window.location.href);\n    if (i) currentChapterId = i;\n    \n    loadReadStatus();\n    \n    config.isLoading = true;\n    const x = new XMLHttpRequest();\n    x.open('GET', window.location.pathname, true);\n    x.timeout = 30000;\n    x.onload = async () => {\n        if (x.status === 200) {\n            currentChapters = getChaptersData(x.responseText);\n            \n            const currentUrl = window.location.pathname;\n            activeChapterIndex = currentChapters.findIndex(chapter => \n                chapter.url === currentUrl.split('?')[0]\n            );\n            \n            if (activeChapterIndex === -1 && currentChapters.length > 0) {\n                activeChapterIndex = 0;\n            }\n            \n            config.currentChapter = activeChapterIndex + 1;\n            \n            if (currentChapters.length <= 1) {\n                isDetailView = false;\n                toggleButtonClass();\n                toggleElementDisplay('comic-content', 'block');\n                await processChapterContent(x.responseText, config.currentChapter, true);\n                markChapterAsRead(activeChapterIndex);\n            } else {\n                showDetailPage();\n            }\n            \n            config.isLoading = false;\n        }\n    };\n    x.onerror = x.ontimeout = () => config.isLoading = false;\n    x.send();\n    \n    const detailButton = document.getElementById('detail-button');\n    if (detailButton) {\n        detailButton.addEventListener('click', () => {\n            isDetailView ? showReaderView() : showDetailPage();\n        });\n    }\n    \n    const autoScrollButton = document.getElementById('auto-scroll-button');\n    if (autoScrollButton) {\n        autoScrollButton.addEventListener('click', toggleAutoScroll);\n    }\n    \n    const commentButton = document.getElementById('comment-button');\n    if (commentButton) {\n        commentButton.addEventListener('click', switchToComments);\n    }\n});\nlet scrollTimeout;\nwindow.addEventListener('scroll', () => {\n    clearTimeout(scrollTimeout);\n    scrollTimeout = setTimeout(() => {\n        detectCurrentChapter();\n    }, 100);\n    \n    if (config.isLoading || batchLoading || isDetailView) return;\n    \n    if (!allImagesLoaded && currentChapterImages.length > 0) {\n        const imageElements = document.querySelectorAll('.comic-page');\n        if (imageElements.length > 0) {\n            const loadedCount = Array.from(imageElements).filter(img => \n                img.src && !img.src.includes('data:image\/gif') && img.complete\n            ).length;\n            \n            if (loadedCount < currentChapterImages.length) {\n                const nextBatchStart = Math.floor(loadedCount \/ imagesPerBatch) * imagesPerBatch;\n                if (nextBatchStart < currentChapterImages.length) {\n                    const lastImage = imageElements[imageElements.length - 1];\n                    const lastImageRect = lastImage.getBoundingClientRect();\n                    \n                    if (lastImageRect.top <= window.innerHeight + 500) {\n                        displayImageBatch(nextBatchStart);\n                    }\n                }\n            } else {\n                allImagesLoaded = true;\n            }\n        }\n    }\n});\n<\/script>\n<\/body>\n<\/html>",
    "ruleImage": "tag.img@data-original&&tag.img@src",
    "ruleLink": "tag.a.0@href@js:result.replace(\/.*?album\\\/(\\d+).*\/g,\"\/photo\/$1\")",
    "ruleNextPage": "class.prevnext.0@href",
    "rulePubDate": "class.tags@text||class.video-views pull-left@text&&class.video-added@text##分类标签:",
    "ruleTitle": "tag.img@title##\\[.*?\\]|【.*?】",
    "searchUrl": "\/search\/photos?search_query={{key}}",
    "showWebLog": false,
    "singleUrl": false,
    "sortUrl": "全部::albums?o=mr\n全彩::\/search\/photos?search_query=全彩\n韩漫::\/albums\/hanman?o=mr\n美漫::\/albums\/meiman?o=mr&page={{page}}\n同人::\/albums\/doujin?o=mr\n短篇::\/albums\/short?o=mr\n其他::\/albums\/another?o=mr\n单行本::\/albums\/single?o=mr\n日排行榜::\/albums?o=mv&t=t\n月排行榜::\/albums?t=m&o=mv\n总排行榜::\/albums?o=mv",
    "sourceComment": "发布页:\nhttps:\/\/jmcomicgo.me\nhttps:\/\/jmcmomic.github.io",
    "sourceIcon": "https:\/\/img2.baidu.com\/it\/u=3335455477,220573182&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=501",
    "sourceName": "禁漫天堂",
    "sourceUrl": "https:\/\/jm18c-uoi.net",
    "style": "#jm-page-body {\n    margin: 0;\n    padding: 0;\n    overflow-x: hidden;\n}\n#detail-page {\n    max-width: 1200px;\n    margin: 0 auto;\n    padding: 15px;\n    box-shadow: 0 0 8px rgba(0,0,0,0.08);\n    display: block;\n}\n#comic-content {\n    padding: 0 !important;\n    margin: -12px !important;\n    width: calc(100% + 24px) !important;\n    box-sizing: border-box;\n}\n.comic-page {\n    max-width: 100% !important;\n    height: auto;\n    display: block;\n    margin: 0 auto !important;\n    box-sizing: border-box;\n}\n.chapter-title {\n    text-align: center;\n    font-size: 16px;\n    font-weight: 600;\n    color: #333;\n    background-color: #f8f9fa;\n    padding: 12px 20px;\n    margin: 15px 0;\n    border-radius: 8px;\n    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\n    letter-spacing: 0.5px;\n    box-sizing: border-box;\n}\n.page-title {\n    text-align: center;\n    font-size: 14px;\n    color: #666;\n    padding: 8px 0;\n    margin: 10px 0;\n    box-sizing: border-box;\n}\n.next-chapter-btn {\n    display: block;\n    width: 90%;\n    max-width: 300px;\n    margin: 25px auto;\n    padding: 14px 28px;\n    background: #ff6b6b;\n    color: white;\n    border: none;\n    border-radius: 8px;\n    font-size: 16px;\n    font-weight: 600;\n    cursor: pointer;\n    text-align: center;\n    transition: all 0.3s;\n    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n}\n.next-chapter-btn:hover {\n    background: #ff5252;\n    transform: translateY(-2px);\n    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);\n}\n.next-chapter-btn:active {\n    transform: translateY(0);\n}\n#detail-page .detail-header {\n    display: flex;\n    flex-wrap: wrap;\n    margin-bottom: 25px;\n    border-bottom: 1px solid #eee;\n    padding-bottom: 15px;\n}\n#detail-page .cover-container {\n    flex: 0 0 250px;\n    margin-right: 25px;\n}\n#detail-page .cover-image {\n    width: 100%;\n    height: auto;\n    border-radius: 6px;\n    box-shadow: 0 3px 10px rgba(0,0,0,0.12);\n}\n#detail-page .info-container {\n    flex: 1;\n    min-width: 280px;\n}\n#detail-page .detail-title {\n    font-size: 24px;\n    font-weight: bold;\n    margin: 0 0 8px;\n    color: #222;\n}\n#detail-page .detail-meta {\n    color: #666;\n    font-size: 13px;\n    margin-bottom: 8px;\n}\n#detail-page .detail-meta span {\n    margin-right: 15px;\n}\n#detail-page .start-reading-btn {\n    background-color: #ff6b6b;\n    color: white;\n    border: none;\n    padding: 12px 24px;\n    border-radius: 6px;\n    font-size: 16px;\n    font-weight: 600;\n    cursor: pointer;\n    margin: 12px 0 18px;\n    transition: all 0.2s;\n}\n#detail-page .start-reading-btn:hover {\n    background-color: #ff5252;\n    transform: translateY(-1px);\n    box-shadow: 0 4px 12px rgba(255,107,107,0.25);\n}\n#detail-page .start-reading-btn:active {\n    transform: translateY(0);\n}\n#detail-page .detail-description {\n    line-height: 1.5;\n    margin-bottom: 15px;\n    font-size: 14px;\n    color: #444;\n}\n#detail-page .detail-tags {\n    display: flex;\n    flex-wrap: wrap;\n    gap: 8px;\n    margin-bottom: 15px;\n}\n#detail-page .tag {\n    background-color: #f0f0f0;\n    padding: 4px 10px;\n    border-radius: 16px;\n    font-size: 13px;\n    color: #555;\n}\n#detail-page .chapters-section {\n    margin-top: 25px;\n}\n#detail-page .section-title {\n    font-size: 20px;\n    font-weight: bold;\n    margin-bottom: 15px;\n    padding-bottom: 8px;\n    border-bottom: 2px solid #ff6b6b;\n}\n#detail-page .tab-container {\n    margin-bottom: 20px;\n}\n#detail-page .tab-header {\n    display: flex;\n    border-bottom: 2px solid #e0e0e0;\n    margin-bottom: 20px;\n}\n#detail-page .tab-btn {\n    padding: 12px 24px;\n    background: none;\n    border: none;\n    font-size: 16px;\n    font-weight: 600;\n    color: #666;\n    cursor: pointer;\n    position: relative;\n    transition: all 0.2s;\n}\n#detail-page .tab-btn:hover,\n#detail-page .tab-btn.active {\n    color: #ff6b6b;\n}\n#detail-page .tab-btn.active::after {\n    content: '';\n    position: absolute;\n    bottom: -2px;\n    left: 0;\n    right: 0;\n    height: 2px;\n    background-color: #ff6b6b;\n}\n#detail-page .chapters-list {\n    display: grid;\n    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));\n    gap: 12px;\n    max-height: 500px;\n    overflow-y: auto;\n    padding: 10px;\n}\n#detail-page .chapter-item {\n    background-color: #f9f9f9;\n    border-radius: 6px;\n    padding: 12px;\n    text-align: center;\n    transition: all 0.2s ease;\n    cursor: pointer;\n    text-decoration: none;\n    color: #333;\n    display: flex;\n    flex-direction: column;\n    justify-content: center;\n    min-height: 60px;\n    position: relative;\n}\n#detail-page .chapter-item:hover {\n    background-color: #e9e9e9;\n    transform: translateY(-2px);\n    box-shadow: 0 4px 12px rgba(0,0,0,0.1);\n}\n#detail-page .chapter-item.active {\n    background-color: #ff6b6b;\n    transform: translateY(-2px);\n    box-shadow: 0 4px 12px rgba(255,107,107,0.25);\n}\n#detail-page .chapter-item.read {\n    background-color: #e8f5e8;\n    border-left: 3px solid #4caf50;\n}\n#detail-page .chapter-number {\n    font-size: 14px;\n    font-weight: bold;\n    margin-bottom: 4px;\n}\n#detail-page .chapter-progress {\n    font-size: 12px;\n    color: #666;\n    margin-top: 4px;\n}\n#detail-page .chapter-item.active .chapter-progress {\n    color: #333;\n    font-weight: 600;\n}\n#detail-page .comments-container {\n    background: white;\n    border-radius: 12px;\n    padding: 20px;\n    box-shadow: 0 2px 8px rgba(0,0,0,0.08);\n    border: 1px solid #e0e0e0;\n}\n#detail-page .comments-header {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    margin-bottom: 20px;\n    padding-bottom: 12px;\n    border-bottom: 2px solid #f0f0f0;\n}\n#detail-page .total-comments {\n    font-size: 16px;\n    font-weight: 600;\n    color: #333;\n}\n#detail-page .load-more-btn {\n    display: block;\n    width: 100%;\n    padding: 12px;\n    background: white;\n    border: 1px solid #e0e0e0;\n    border-radius: 12px;\n    color: #666;\n    font-size: 14px;\n    font-weight: 500;\n    text-align: center;\n    cursor: pointer;\n    margin-top: 12px;\n    transition: all 0.2s;\n}\n#detail-page .load-more-btn:hover {\n    background: #f8f9fa;\n    border-color: #d0d0d0;\n}\n#detail-page .load-more-btn:active {\n    background: #f0f2f5;\n}\n#detail-page .comment-header {\n    display: flex;\n    align-items: center;\n    margin-bottom: 12px;\n}\n#detail-page .user-avatar,\n#detail-page .timeline-avatar {\n    width: 40px;\n    height: 40px;\n    border-radius: 50%;\n    margin-right: 12px;\n    overflow: hidden;\n    flex-shrink: 0;\n}\n#detail-page .user-avatar img,\n#detail-page .timeline-avatar img {\n    width: 100%;\n    height: 100%;\n    object-fit: cover;\n}\n#detail-page .user-info {\n    flex: 1;\n}\n#detail-page .username-row {\n    display: flex;\n    align-items: center;\n    margin-bottom: 4px;\n}\n#detail-page .username,\n#detail-page .timeline-username {\n    font-weight: 600;\n    color: #1a1a1a;\n    font-size: 15px;\n    margin-right: 8px;\n}\n#detail-page .user-level,\n#detail-page .timeline-user-level {\n    background: linear-gradient(45deg, #FFD700, #FFA500);\n    color: #333;\n    padding: 2px 8px;\n    border-radius: 10px;\n    font-size: 11px;\n    font-weight: 600;\n    text-align: center;\n}\n#detail-page .user-title,\n#detail-page .timeline-user-title {\n    color: #666;\n    font-size: 13px;\n    line-height: 1.3;\n}\n#detail-page .comment-content {\n    font-size: 15px;\n    line-height: 1.5;\n    color: #1a1a1a;\n    margin-bottom: 16px;\n    padding-left: 52px;\n    word-wrap: break-word;\n}\n#detail-page .date-info,\n#detail-page .timeline-date {\n    color: #999;\n    font-size: 12px;\n    margin-top: 4px;\n}\n#detail-page .timeline-panel {\n    border: none;\n    background: transparent;\n    box-shadow: none;\n    margin-bottom: 12px;\n}\n#detail-page .timeline-panel-body {\n    padding: 16px;\n    background: white;\n    border-radius: 12px;\n    box-shadow: 0 2px 8px rgba(0,0,0,0.08);\n    border: 1px solid #e0e0e0;\n}\n#detail-page .timeline-left {\n    float: left;\n    width: 40px;\n    margin-right: 12px;\n}\n#detail-page .timeline-right {\n    margin-left: 52px;\n}\n#detail-page .timeline-header {\n    display: flex;\n    align-items: center;\n    margin-bottom: 4px;\n}\n#detail-page .timeline-second-header {\n    margin-bottom: 8px;\n}\n#detail-page .timeline-content {\n    font-size: 15px;\n    line-height: 1.5;\n    color: #1a1a1a;\n    margin-bottom: 8px;\n}\n#detail-page .comment-vote,\n#detail-page .timeline-info-reply,\n#detail-page .timeline-ft,\n#detail-page .timeline-info,\n#detail-page .reply-line,\n#detail-page .other-timelines,\n#detail-page .timeline-badge,\n#detail-page .notice_more,\n#detail-page .btn,\n#detail-page .navbar-btn,\n#detail-page .m-l-15,\n#detail-page .m-r-15 {\n    display: none;\n}\n#detail-button {\n    position: fixed;\n    top: 15px;\n    right: 15px;\n    width: 46px;\n    height: 46px;\n    background-color: rgba(255, 107, 107, 0.95);\n    border-radius: 50%;\n    border: none;\n    color: white;\n    font-weight: 600;\n    cursor: pointer;\n    box-shadow: 0 3px 10px rgba(0,0,0,0.2);\n    transition: all 0.2s ease;\n    z-index: 1001;\n    padding: 0;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    overflow: hidden;\n}\n#detail-button:hover {\n    background-color: rgba(255, 82, 82, 0.95);\n    transform: translateY(-1px) scale(1.05);\n    box-shadow: 0 5px 15px rgba(0,0,0,0.25);\n}\n#detail-button:active {\n    transform: translateY(0) scale(0.98);\n    box-shadow: 0 2px 8px rgba(0,0,0,0.15);\n}\n#comment-button {\n    position: fixed;\n    top: 71px;\n    right: 15px;\n    width: 46px;\n    height: 46px;\n    background-color: rgba(74, 144, 226, 0.95);\n    border-radius: 50%;\n    border: none;\n    color: white;\n    font-weight: 600;\n    cursor: pointer;\n    box-shadow: 0 3px 10px rgba(0,0,0,0.2);\n    transition: all 0.2s ease;\n    z-index: 1000;\n    padding: 0;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    overflow: hidden;\n    font-size: 20px;\n}\n#comment-button:hover {\n    background-color: rgba(58, 126, 204, 0.95);\n    transform: translateY(-1px) scale(1.05);\n    box-shadow: 0 5px 15px rgba(0,0,0,0.25);\n}\n#comment-button:active {\n    transform: translateY(0) scale(0.98);\n    box-shadow: 0 2px 8px rgba(0,0,0,0.15);\n}\n#auto-scroll-button {\n    position: fixed;\n    bottom: 100px;\n    right: 20px;\n    width: 56px;\n    height: 56px;\n    border-radius: 50%;\n    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n    color: white;\n    border: none;\n    box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);\n    cursor: pointer;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    font-size: 22px;\n    z-index: 9999;\n    transition: all 0.3s ease;\n    opacity: 0.9;\n}\n#auto-scroll-button:hover {\n    opacity: 1;\n    transform: scale(1.05);\n    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);\n}\n#auto-scroll-button.active {\n    background: linear-gradient(135deg, #f56565 0%, #ed64a6 100%);\n    animation: auto-scroll-pulse 2s infinite;\n}\n@keyframes auto-scroll-pulse {\n    0% {\n        box-shadow: 0 0 0 0 rgba(245, 101, 101, 0.4);\n    }\n    70% {\n        box-shadow: 0 0 0 10px rgba(245, 101, 101, 0);\n    }\n    100% {\n        box-shadow: 0 0 0 0 rgba(245, 101, 101, 0);\n    }\n}\n#detail-button .hamburger {\n    width: 22px;\n    height: 18px;\n    position: relative;\n    display: flex;\n    flex-direction: column;\n    justify-content: space-between;\n    align-items: center;\n}\n#detail-button .hamburger span {\n    display: block;\n    width: 22px;\n    height: 2.8px;\n    background-color: white;\n    border-radius: 2px;\n    transition: all 0.3s ease;\n}\n#detail-button.is-reader .hamburger span:nth-child(1),\n#detail-button.is-reader .hamburger span:nth-child(3) {\n    transform: none;\n    width: 22px;\n}\n#detail-button.is-reader .hamburger span:nth-child(2) {\n    opacity: 1;\n    width: 18px;\n}\n#detail-button.is-detail .hamburger span:nth-child(1) {\n    transform: translateY(7.5px) rotate(45deg);\n}\n#detail-button.is-detail .hamburger span:nth-child(2) {\n    opacity: 0;\n    width: 0;\n}\n#detail-button.is-detail .hamburger span:nth-child(3) {\n    transform: translateY(-7.5px) rotate(-45deg);\n}\n#initial-loading,\n#bottom-loader,\n.end-message {\n    text-align: center;\n    padding: 30px;\n    font-size: 16px;\n    box-sizing: border-box;\n}\n#initial-loading,\n#bottom-loader {\n    color: #666;\n}\n#end-message {\n    color: #888;\n    display: none;\n}\n@media (max-width: 768px) {\n    #jm-page-body {\n        padding: 12px;\n    }\n    #detail-page .detail-header {\n        flex-direction: column;\n    }\n    #detail-page .cover-container {\n        margin-right: 0;\n        margin-bottom: 15px;\n    }\n    #detail-page .chapters-list {\n        grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));\n        max-height: 400px;\n    }\n    #detail-page .detail-title {\n        font-size: 22px;\n    }\n    .chapter-title {\n        font-size: 15px;\n        padding: 10px 18px;\n        margin: 12px 0 8px;\n    }\n    .next-chapter-btn {\n        width: 85%;\n        padding: 12px 20px;\n        font-size: 15px;\n        margin: 20px auto;\n    }\n    #detail-page .tab-btn {\n        padding: 10px 20px;\n        font-size: 15px;\n    }\n    #detail-page .comments-container {\n        padding: 15px;\n    }\n    #detail-page .start-reading-btn {\n        padding: 10px 20px;\n        font-size: 15px;\n        margin: 10px 0 15px;\n    }\n    #detail-button {\n        width: 42px;\n        height: 42px;\n        top: 12px;\n        right: 12px;\n    }\n    #detail-button .hamburger {\n        width: 20px;\n        height: 16px;\n    }\n    #detail-button .hamburger span {\n        width: 20px;\n        height: 2.5px;\n    }\n    #detail-button.is-detail .hamburger span:nth-child(1) {\n        transform: translateY(6.5px) rotate(45deg);\n    }\n    #detail-button.is-detail .hamburger span:nth-child(3) {\n        transform: translateY(-6.5px) rotate(-45deg);\n    }\n    #comment-button {\n        width: 42px;\n        height: 42px;\n        top: 64px;\n        right: 12px;\n        font-size: 18px;\n    }\n    #auto-scroll-button {\n        width: 50px;\n        height: 50px;\n        bottom: 90px;\n        right: 15px;\n        font-size: 20px;\n    }\n}\n@media (max-width: 480px) {\n    #detail-page {\n        padding: 10px;\n    }\n    #detail-page .cover-container {\n        flex: 0 0 200px;\n    }\n    #detail-page .chapters-list {\n        grid-template-columns: repeat(auto-fill, minmax(85px, 1fr));\n        max-height: 350px;\n    }\n    #detail-page .chapter-item {\n        padding: 8px;\n        min-height: 55px;\n    }\n    #detail-page .chapter-number {\n        font-size: 13px;\n    }\n    .chapter-title {\n        font-size: 14px;\n        padding: 8px 16px;\n        margin: 10px 0 6px;\n    }\n    .next-chapter-btn {\n        width: 80%;\n        padding: 10px 16px;\n        font-size: 14px;\n        margin: 15px auto;\n    }\n    .page-title {\n        font-size: 13px;\n    }\n    #detail-page .tab-btn {\n        padding: 8px 16px;\n        font-size: 14px;\n    }\n    #detail-page .start-reading-btn {\n        padding: 8px 16px;\n        font-size: 14px;\n        margin: 8px 0 12px;\n    }\n    #detail-button {\n        width: 40px;\n        height: 40px;\n        top: 10px;\n        right: 10px;\n    }\n    #detail-button .hamburger {\n        width: 18px;\n        height: 14px;\n    }\n    #detail-button .hamburger span {\n        width: 18px;\n        height: 2.2px;\n    }\n    #detail-button.is-detail .hamburger span:nth-child(1) {\n        transform: translateY(6px) rotate(45deg);\n    }\n    #detail-button.is-detail .hamburger span:nth-child(3) {\n        transform: translateY(-6px) rotate(-45deg);\n    }\n    #comment-button {\n        width: 40px;\n        height: 40px;\n        top: 60px;\n        right: 10px;\n        font-size: 16px;\n    }\n    #auto-scroll-button {\n        width: 48px;\n        height: 48px;\n        bottom: 85px;\n        right: 12px;\n        font-size: 18px;\n    }\n}",
    "type": 0
}
广告