禁漫天堂
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
}