diff --git a/src/hamburger.js b/src/hamburger.js new file mode 100644 index 0000000..28c0595 --- /dev/null +++ b/src/hamburger.js @@ -0,0 +1,19 @@ +const btn = document.getElementById("hamburger-btn"); +const sidebar = document.querySelector(".sidebar"); + +btn.addEventListener("click", (e) => { + e.stopPropagation(); + sidebar.classList.toggle("active"); + btn.textContent = sidebar.classList.contains("active") ? "✕" : "☰"; +}); + +document.addEventListener("click", (e) => { + if (window.innerWidth <= 767) { + const outsideSidebar = !sidebar.contains(e.target); + const outsideBtn = !btn.contains(e.target); + if (outsideSidebar && outsideBtn) { + sidebar.classList.remove("active"); + btn.textContent = "☰"; + } + } +}); \ No newline at end of file diff --git a/src/renderer.js b/src/renderer.js index 71d7613..e0c89be 100644 --- a/src/renderer.js +++ b/src/renderer.js @@ -7,99 +7,100 @@ import { showMessage as uiShowMessage } from './modules/ui-utils.js'; import { applyLayoutToGallery } from './modules/layout-manager.js'; document.addEventListener('DOMContentLoaded', async () => { - const domRefs = getDomElements(); - - const currentLayout = 'grid'; - let currentSource = ''; - let currentPage = 1; - let isFetching = false; - const favoriteIds = new Set(); + const domRefs = getDomElements(); - try { - if (window.api && window.api.getFavorites) { - const favs = await window.api.getFavorites(); - favs.forEach(f => favoriteIds.add(String(f.id))); - } - } catch (e) { console.error(e); } + const currentLayout = 'grid'; + let currentSource = ''; + let currentPage = 1; + let isFetching = false; + const favoriteIds = new Set(); + const isBooksPage = window.location.pathname.includes('books.html'); - function showMessage(msg, type = 'success') { if (domRefs.messageBar) uiShowMessage(domRefs.messageBar, msg, type); } - function showTagModal(tags) { if (domRefs.tagInfoContent) { populateTagModal(domRefs.tagInfoContent, tags); domRefs.tagInfoModal.classList.remove('hidden'); } } - function localCreateImageCard(id, tags, img, thumb, type) { - return createImageCard(id, tags, img, thumb, type, { currentLayout, showMessage, showTagModal, applyLayoutToGallery, favoritesGallery: document.getElementById('favorites-gallery'), favoriteIds }); - } - function updateHeader() { if (domRefs.headerContext) domRefs.headerContext.classList.add('hidden'); } + try { + if (window.api && window.api.getFavorites) { + const favs = await window.api.getFavorites(); + favs.forEach(f => favoriteIds.add(String(f.id))); + } + } catch (e) { console.error(e); } - const callbacks = { showMessage, applyLayoutToGallery, updateHeader, createImageCard: localCreateImageCard }; + function showMessage(msg, type = 'success') { if (domRefs.messageBar) uiShowMessage(domRefs.messageBar, msg, type); } + function showTagModal(tags) { if (domRefs.tagInfoContent) { populateTagModal(domRefs.tagInfoContent, tags); domRefs.tagInfoModal.classList.remove('hidden'); } } + function localCreateImageCard(id, tags, img, thumb, type) { + return createImageCard(id, tags, img, thumb, type, { currentLayout, showMessage, showTagModal, applyLayoutToGallery, favoritesGallery: document.getElementById('favorites-gallery'), favoriteIds }); + } + function updateHeader() { if (domRefs.headerContext) domRefs.headerContext.classList.add('hidden'); } - let currentChapters = []; - let currentChapterPage = 1; - const CHAPTERS_PER_PAGE = 10; + const callbacks = { showMessage, applyLayoutToGallery, updateHeader, createImageCard: localCreateImageCard }; - function renderChapterPage() { - const listContainer = document.getElementById('chapter-list-container'); - if (!listContainer) return; - listContainer.innerHTML = ''; + let currentChapters = []; + let currentChapterPage = 1; + const CHAPTERS_PER_PAGE = 10; - const start = (currentChapterPage - 1) * CHAPTERS_PER_PAGE; - const end = start + CHAPTERS_PER_PAGE; - const slice = currentChapters.slice(start, end); + function renderChapterPage() { + const listContainer = document.getElementById('chapter-list-container'); + if (!listContainer) return; + listContainer.innerHTML = ''; - if (slice.length === 0) { - listContainer.innerHTML = '
No chapters available.
'; - return; - } + const start = (currentChapterPage - 1) * CHAPTERS_PER_PAGE; + const end = start + CHAPTERS_PER_PAGE; + const slice = currentChapters.slice(start, end); - slice.forEach(chapter => { - const row = document.createElement('div'); - row.className = 'chapter-row'; - - let mainText = chapter.chapter && chapter.chapter !== '0' ? `Chapter ${chapter.chapter}` : 'Read'; - if(chapter.title && !chapter.title.includes(chapter.chapter)) { - mainText = chapter.title; - } + if (slice.length === 0) { + listContainer.innerHTML = '
No chapters available.
'; + return; + } - row.innerHTML = `${mainText}`; - row.onclick = () => openReader(chapter.id); - listContainer.appendChild(row); - }); + slice.forEach(chapter => { + const row = document.createElement('div'); + row.className = 'chapter-row'; - const controls = document.getElementById('pagination-controls'); - if (controls) { - controls.innerHTML = ''; - if (currentChapters.length > CHAPTERS_PER_PAGE) { - const prev = document.createElement('button'); - prev.className = 'page-btn'; - prev.textContent = '← Prev'; - prev.disabled = currentChapterPage === 1; - prev.onclick = () => { currentChapterPage--; renderChapterPage(); }; + let mainText = chapter.chapter && chapter.chapter !== '0' ? `Chapter ${chapter.chapter}` : 'Read'; + if(chapter.title && !chapter.title.includes(chapter.chapter)) { + mainText = chapter.title; + } - const next = document.createElement('button'); - next.className = 'page-btn'; - next.textContent = 'Next →'; - next.disabled = end >= currentChapters.length; - next.onclick = () => { currentChapterPage++; renderChapterPage(); }; + row.innerHTML = `${mainText}`; + row.onclick = () => openReader(chapter.id); + listContainer.appendChild(row); + }); - const label = document.createElement('span'); - label.style.color = 'var(--text-secondary)'; - label.style.fontSize = '0.9rem'; - label.textContent = `Page ${currentChapterPage} of ${Math.ceil(currentChapters.length / CHAPTERS_PER_PAGE)}`; + const controls = document.getElementById('pagination-controls'); + if (controls) { + controls.innerHTML = ''; + if (currentChapters.length > CHAPTERS_PER_PAGE) { + const prev = document.createElement('button'); + prev.className = 'page-btn'; + prev.textContent = '← Prev'; + prev.disabled = currentChapterPage === 1; + prev.onclick = () => { currentChapterPage--; renderChapterPage(); }; - controls.appendChild(prev); - controls.appendChild(label); - controls.appendChild(next); - } - } - } + const next = document.createElement('button'); + next.className = 'page-btn'; + next.textContent = 'Next →'; + next.disabled = end >= currentChapters.length; + next.onclick = () => { currentChapterPage++; renderChapterPage(); }; - async function openBookDetails(id, imageUrl, title, tags) { - const detailsView = document.getElementById('book-details-view'); - const browseView = document.getElementById('browse-page'); - if (!detailsView || !browseView) return; + const label = document.createElement('span'); + label.style.color = 'var(--text-secondary)'; + label.style.fontSize = '0.9rem'; + label.textContent = `Page ${currentChapterPage} of ${Math.ceil(currentChapters.length / CHAPTERS_PER_PAGE)}`; - browseView.classList.add('hidden'); - detailsView.classList.remove('hidden'); - - detailsView.innerHTML = ` + controls.appendChild(prev); + controls.appendChild(label); + controls.appendChild(next); + } + } + } + + async function openBookDetails(id, imageUrl, title, tags) { + const detailsView = document.getElementById('book-details-view'); + const browseView = document.getElementById('browse-page'); + if (!detailsView || !browseView) return; + + browseView.classList.add('hidden'); + detailsView.classList.remove('hidden'); + + detailsView.innerHTML = `
@@ -122,177 +123,184 @@ document.addEventListener('DOMContentLoaded', async () => {
`; - document.getElementById('back-to-library').onclick = () => { - detailsView.classList.add('hidden'); - browseView.classList.remove('hidden'); - }; + document.getElementById('back-to-library').onclick = () => { + detailsView.classList.add('hidden'); + browseView.classList.remove('hidden'); + }; - let highResCover = null; - try { - const aniRes = await window.api.getMetadata(title); - if (aniRes.success && aniRes.data && aniRes.data.coverImage.extraLarge) { - highResCover = aniRes.data.coverImage.extraLarge; - } - } catch (e) {} - - try { - const response = await window.api.getChapters(currentSource, id); - currentChapters = response.success ? response.data.chapters : []; - currentChapterPage = 1; - - if (!highResCover && response.extra && response.extra.cover) { - highResCover = response.extra.cover; - } - - if (highResCover) { - const posterEl = document.getElementById('book-details-poster'); - if (posterEl) posterEl.src = highResCover; - } - - renderChapterPage(); - } catch (err) { - const chContainer = document.getElementById('chapter-list-container'); - if(chContainer) chContainer.innerHTML = '
Failed to load chapters.
'; - } - } - - async function openReader(chapterId) { - const detailsView = document.getElementById('book-details-view'); - const readerView = document.getElementById('reader-view'); - const readerContent = document.getElementById('reader-content'); - if (!detailsView || !readerView) return; - - detailsView.classList.add('hidden'); - readerView.classList.remove('hidden'); - readerContent.innerHTML = '

Loading content...

'; - - const existingBackBtn = readerView.querySelector('.reader-close-btn'); - if(existingBackBtn) existingBackBtn.remove(); - - const backBtn = document.createElement('div'); - backBtn.className = 'reader-close-btn'; - backBtn.innerHTML = ' Close Reader'; - backBtn.onclick = () => { - readerView.classList.add('hidden'); - detailsView.classList.remove('hidden'); - readerContent.innerHTML = ''; - }; - readerView.appendChild(backBtn); - - try { - const response = await window.api.getPages(currentSource, chapterId); - readerContent.innerHTML = ''; - - if (!response.success || response.data.length === 0) { - readerContent.innerHTML = '

No content found.

'; - return; - } - - const isTextMode = response.data[0].type === 'text'; - - if (isTextMode) { - const pageData = response.data[0]; - const textDiv = document.createElement('div'); - textDiv.className = 'reader-text-content'; - textDiv.innerHTML = pageData.content; - readerContent.appendChild(textDiv); - } else { - response.data.forEach(page => { - const img = document.createElement('img'); - img.className = 'reader-page-img'; - img.src = page.url; - img.loading = "lazy"; - readerContent.appendChild(img); - }); - } - - } catch (err) { - console.error(err); - showMessage('Failed to load content', 'error'); - } - } - - if (domRefs.searchModal) setupGlobalKeybinds(domRefs.searchModal); - if (domRefs.tagInfoCloseButton) domRefs.tagInfoCloseButton.onclick = () => domRefs.tagInfoModal.classList.add('hidden'); - if (domRefs.searchIconButton) { - domRefs.searchIconButton.onclick = () => { domRefs.searchModal.classList.remove('hidden'); domRefs.searchInput?.focus(); }; - domRefs.searchCloseButton.onclick = () => domRefs.searchModal.classList.add('hidden'); - } - - if (domRefs.sourceList) { - if (domRefs.contentGallery) applyLayoutToGallery(domRefs.contentGallery, currentLayout); - - const isBooksPage = window.location.pathname.includes('books.html'); - const contentType = isBooksPage ? 'book-board' : 'image-board'; - - let initialSource = await populateSources(domRefs.sourceList, contentType); - currentSource = initialSource; - updateHeader(); - - domRefs.sourceList.addEventListener('click', (e) => { - const button = e.target.closest('.source-button'); - if (button) { - domRefs.sourceList.querySelectorAll('.source-button').forEach(b => b.classList.remove('active')); - button.classList.add('active'); - currentSource = button.dataset.source; - updateHeader(); - currentPage = 1; - if (domRefs.searchInput?.value.trim()) performSearch(currentSource, domRefs.searchInput, currentLayout, domRefs, callbacks); - else if (domRefs.searchInput) performSearch(currentSource, { value: "" }, currentLayout, domRefs, callbacks); - } - }); - - if (domRefs.contentGallery) { - domRefs.contentGallery.addEventListener('click', (e) => { - const card = e.target.closest('.image-entry'); - if (card && isBooksPage) { - if (e.target.closest('button')) return; - e.preventDefault(); e.stopPropagation(); - - const bookId = card.dataset.id; - const img = card.querySelector('img'); - const title = card.dataset.title || "Unknown"; - - if (bookId) openBookDetails(bookId, img ? img.src : '', title, []); - } - }); - } - - const scrollContainer = document.querySelector('.content-view'); - if (scrollContainer) { - scrollContainer.addEventListener('scroll', async () => { - if (scrollContainer.scrollTop + scrollContainer.clientHeight >= scrollContainer.scrollHeight - 600) { - if (isFetching) return; - isFetching = true; - currentPage++; - if (domRefs.infiniteLoadingSpinner) domRefs.infiniteLoadingSpinner.classList.remove('hidden'); - try { await loadMoreResults(currentSource, currentPage, currentLayout, domRefs, callbacks); } - catch (error) { currentPage--; } - finally { isFetching = false; if (domRefs.infiniteLoadingSpinner) domRefs.infiniteLoadingSpinner.classList.add('hidden'); } + let highResCover = null; + try { + const aniRes = await window.api.getMetadata(title); + if (aniRes.success && aniRes.data && aniRes.data.coverImage.extraLarge) { + highResCover = aniRes.data.coverImage.extraLarge; } - }); - } + } catch (e) {} - if (domRefs.searchButton) { - domRefs.searchButton.onclick = () => { currentPage = 1; performSearch(currentSource, domRefs.searchInput, currentLayout, domRefs, callbacks); }; - } - } + try { + const response = await window.api.getChapters(currentSource, id); + currentChapters = response.success ? response.data.chapters : []; + currentChapterPage = 1; - if (document.getElementById('favorites-gallery')) { - const favGallery = document.getElementById('favorites-gallery'); - const rawFavorites = await window.api.getFavorites(); - favGallery.innerHTML = ''; - if (!rawFavorites || rawFavorites.length === 0) favGallery.innerHTML = '

No favorites found.

'; - else { - rawFavorites.forEach(row => { - let tags = []; - if (typeof row.tags === 'string') tags = row.tags.split(',').filter(t=>t); - else if (Array.isArray(row.tags)) tags = row.tags; - const card = localCreateImageCard(row.id, tags, row.image_url, row.thumbnail_url, 'image'); - card.dataset.title = row.title; - favGallery.appendChild(card); - }); - } - applyLayoutToGallery(favGallery, currentLayout); - } + if (!highResCover && response.extra && response.extra.cover) { + highResCover = response.extra.cover; + } + + if (highResCover) { + const posterEl = document.getElementById('book-details-poster'); + if (posterEl) posterEl.src = highResCover; + } + + renderChapterPage(); + } catch (err) { + const chContainer = document.getElementById('chapter-list-container'); + if(chContainer) chContainer.innerHTML = '
Failed to load chapters.
'; + } + } + + async function openReader(chapterId) { + const detailsView = document.getElementById('book-details-view'); + const readerView = document.getElementById('reader-view'); + const readerContent = document.getElementById('reader-content'); + if (!detailsView || !readerView) return; + + detailsView.classList.add('hidden'); + readerView.classList.remove('hidden'); + readerContent.innerHTML = '

Loading content...

'; + + const existingBackBtn = readerView.querySelector('.reader-close-btn'); + if(existingBackBtn) existingBackBtn.remove(); + + const backBtn = document.createElement('div'); + backBtn.className = 'reader-close-btn'; + backBtn.innerHTML = ' Close Reader'; + backBtn.onclick = () => { + readerView.classList.add('hidden'); + detailsView.classList.remove('hidden'); + readerContent.innerHTML = ''; + }; + readerView.appendChild(backBtn); + + try { + const response = await window.api.getPages(currentSource, chapterId); + readerContent.innerHTML = ''; + + if (!response.success || response.data.length === 0) { + readerContent.innerHTML = '

No content found.

'; + return; + } + + const isTextMode = response.data[0].type === 'text'; + + if (isTextMode) { + const pageData = response.data[0]; + const textDiv = document.createElement('div'); + textDiv.className = 'reader-text-content'; + textDiv.innerHTML = pageData.content; + readerContent.appendChild(textDiv); + } else { + response.data.forEach(page => { + const img = document.createElement('img'); + img.className = 'reader-page-img'; + img.src = page.url; + img.loading = "lazy"; + readerContent.appendChild(img); + }); + } + + } catch (err) { + console.error(err); + showMessage('Failed to load content', 'error'); + } + } + + if (domRefs.searchModal) setupGlobalKeybinds(domRefs.searchModal); + if (domRefs.tagInfoCloseButton) domRefs.tagInfoCloseButton.onclick = () => domRefs.tagInfoModal.classList.add('hidden'); + if (domRefs.searchIconButton) { + domRefs.searchIconButton.onclick = () => { domRefs.searchModal.classList.remove('hidden'); domRefs.searchInput?.focus(); }; + domRefs.searchCloseButton.onclick = () => domRefs.searchModal.classList.add('hidden'); + } + + if (domRefs.sourceList) { + if (domRefs.contentGallery) { + applyLayoutToGallery(domRefs.contentGallery, currentLayout); + } + + const contentType = isBooksPage ? 'book-board' : 'image-board'; + + let initialSource = await populateSources(domRefs.sourceList, contentType); + currentSource = initialSource; + updateHeader(); + + domRefs.sourceList.addEventListener('click', (e) => { + const button = e.target.closest('.source-button'); + if (button) { + domRefs.sourceList.querySelectorAll('.source-button').forEach(b => b.classList.remove('active')); + button.classList.add('active'); + currentSource = button.dataset.source; + updateHeader(); + currentPage = 1; + + // Apply books-only class when searching on books page + if (isBooksPage && domRefs.contentGallery) { + domRefs.contentGallery.classList.add('books-only'); + } + + if (domRefs.searchInput?.value.trim()) performSearch(currentSource, domRefs.searchInput, currentLayout, domRefs, callbacks); + else if (domRefs.searchInput) performSearch(currentSource, { value: "" }, currentLayout, domRefs, callbacks); + } + }); + + if (domRefs.contentGallery) { + domRefs.contentGallery.addEventListener('click', (e) => { + const card = e.target.closest('.image-entry'); + if (card && isBooksPage) { + if (e.target.closest('button')) return; + e.preventDefault(); e.stopPropagation(); + + const bookId = card.dataset.id; + const img = card.querySelector('img'); + const title = card.dataset.title || "Unknown"; + + if (bookId) openBookDetails(bookId, img ? img.src : '', title, []); + } + }); + } + + const scrollContainer = document.querySelector('.content-view'); + if (scrollContainer) { + scrollContainer.addEventListener('scroll', async () => { + if (scrollContainer.scrollTop + scrollContainer.clientHeight >= scrollContainer.scrollHeight - 600) { + if (isFetching) return; + isFetching = true; + currentPage++; + if (domRefs.infiniteLoadingSpinner) domRefs.infiniteLoadingSpinner.classList.remove('hidden'); + try { await loadMoreResults(currentSource, currentPage, currentLayout, domRefs, callbacks); } + catch (error) { currentPage--; } + finally { isFetching = false; if (domRefs.infiniteLoadingSpinner) domRefs.infiniteLoadingSpinner.classList.add('hidden'); } + } + }); + } + + if (domRefs.searchButton) { + domRefs.searchButton.onclick = () => { currentPage = 1; performSearch(currentSource, domRefs.searchInput, currentLayout, domRefs, callbacks); }; + } + } + + if (document.getElementById('favorites-gallery')) { + const favGallery = document.getElementById('favorites-gallery'); + const rawFavorites = await window.api.getFavorites(); + favGallery.innerHTML = ''; + if (!rawFavorites || rawFavorites.length === 0) favGallery.innerHTML = '

No favorites found.

'; + else { + rawFavorites.forEach(row => { + let tags = []; + if (typeof row.tags === 'string') tags = row.tags.split(',').filter(t=>t); + else if (Array.isArray(row.tags)) tags = row.tags; + const card = localCreateImageCard(row.id, tags, row.image_url, row.thumbnail_url, 'image'); + card.dataset.title = row.title; + favGallery.appendChild(card); + }); + } + applyLayoutToGallery(favGallery, currentLayout); + } }); \ No newline at end of file diff --git a/views/books.html b/views/books.html index aed313f..761b6d7 100644 --- a/views/books.html +++ b/views/books.html @@ -60,8 +60,9 @@
-
- + +
+ @@ -130,5 +131,6 @@ }); } + \ No newline at end of file diff --git a/views/emulator.html b/views/emulator.html index 8563ce1..68e33f5 100644 --- a/views/emulator.html +++ b/views/emulator.html @@ -34,6 +34,7 @@
+

Extension Emulator

@@ -97,6 +98,7 @@
+ \ No newline at end of file diff --git a/views/favorites.html b/views/favorites.html index 7903973..3a5a9e0 100644 --- a/views/favorites.html +++ b/views/favorites.html @@ -59,7 +59,8 @@
-
+ +
@@ -106,5 +107,6 @@ }); } + \ No newline at end of file diff --git a/views/index.html b/views/index.html index 6fac356..080310d 100644 --- a/views/index.html +++ b/views/index.html @@ -65,7 +65,8 @@
-
+ +
@@ -133,7 +134,6 @@
- + \ No newline at end of file diff --git a/views/marketplace.html b/views/marketplace.html index f409067..6d5ba2a 100644 --- a/views/marketplace.html +++ b/views/marketplace.html @@ -10,109 +10,115 @@ - + + + Settings + + + -
-
-
- -
-
-

WaifuBoard Store

-

Discover extensions for manga reading, image browsing, and more. Customize your experience.

-
-
- 0 - Extensions -
-
- 0 - Installed -
+
+
+ +

Marketplace

+
+ +
+
+ +
+
+

WaifuBoard Store

+

Discover extensions for manga reading, image browsing, and more. Customize your experience.

+
+
+ 0 + Extensions +
+
+ 0 + Installed
- -
- - -
- -
-
- - Trending Extensions -
-
-
- -

Connecting to repository...

-
-
-
- - -
+ +
+ + +
+ +
+
+ + Trending Extensions +
+
+
+ +

Connecting to repository...

+
+
+
+ + +
+
- + - + + \ No newline at end of file diff --git a/views/settings.html b/views/settings.html index 8dd54fc..58b1b87 100644 --- a/views/settings.html +++ b/views/settings.html @@ -59,7 +59,8 @@
-
+ +
@@ -103,5 +104,6 @@ }); } + \ No newline at end of file diff --git a/views/styles/books.css b/views/styles/books.css index 4462058..c65aca3 100644 --- a/views/styles/books.css +++ b/views/styles/books.css @@ -1,347 +1,3 @@ -#book-details-view { - display: flex; - flex-direction: column; - gap: 1.5rem; - padding-bottom: 4rem; - max-width: 1400px; - margin: 0 auto; - width: 100%; -} - -.book-top-nav { - display: flex; - align-items: center; - padding-bottom: 1rem; - border-bottom: 1px solid var(--border); -} - -.back-btn-large { - display: inline-flex; - align-items: center; - gap: 0.75rem; - font-size: 1.1rem; - font-weight: 600; - color: var(--text-secondary); - cursor: pointer; - transition: 0.2s; - padding: 0.5rem 1rem; - border-radius: var(--radius-md); -} - -.back-btn-large:hover { - color: var(--text-primary); - background: var(--bg-surface-hover); -} - -@media (max-width: 767px) { - .back-btn-large { - font-size: 0.95rem; - gap: 0.5rem; - padding: 0.4rem 0.8rem; - } -} - -.book-layout-grid { - display: grid; - grid-template-columns: 300px 1fr; - gap: 3rem; - align-items: start; -} - -@media (max-width: 1024px) { - .book-layout-grid { - grid-template-columns: 250px 1fr; - gap: 2rem; - } -} - -@media (max-width: 767px) { - .book-layout-grid { - grid-template-columns: 1fr; - gap: 1.5rem; - } -} - -.book-left-col { - display: flex; - flex-direction: column; - gap: 1.5rem; -} - -@media (min-width: 768px) { - .book-left-col { - position: sticky; - top: 20px; - } -} - -@media (max-width: 767px) { - .book-left-col { - flex-direction: row; - align-items: flex-start; - gap: 1rem; - } -} - -.book-poster-large { - width: 100%; - border-radius: var(--radius-lg); - box-shadow: 0 15px 40px rgba(0, 0, 0, 0.6); - aspect-ratio: 2 / 3; - object-fit: cover; - border: 1px solid var(--border); - background: #111; -} - -@media (max-width: 767px) { - .book-poster-large { - width: 120px; - flex-shrink: 0; - } -} - -.book-title-sidebar { - font-size: 1.5rem; - font-weight: 700; - line-height: 1.3; - margin: 0; - color: var(--text-primary); - text-align: center; - word-wrap: break-word; -} - -@media (max-width: 767px) { - .book-title-sidebar { - font-size: 1.2rem; - text-align: left; - } -} - -.book-chapters-column { - display: flex; - flex-direction: column; - gap: 1.5rem; - min-width: 0; -} - -.chapter-table-container { - background: var(--bg-surface); - border: 1px solid var(--border); - border-radius: var(--radius-md); - overflow: hidden; -} - -.chapter-row { - display: flex; - align-items: center; - justify-content: space-between; - padding: 1rem 1.5rem; - border-bottom: 1px solid var(--border); - cursor: pointer; - transition: background 0.2s; -} - -.chapter-row:last-child { - border-bottom: none; -} - -.chapter-row:hover { - background: var(--bg-surface-hover); -} - -@media (max-width: 767px) { - .chapter-row { - padding: 0.75rem 1rem; - flex-direction: column; - align-items: flex-start; - gap: 0.25rem; - } -} - -.chapter-main-text { - font-weight: 600; - font-size: 1rem; - color: var(--text-primary); -} - -.chapter-sub-text { - font-size: 0.9rem; - color: var(--text-tertiary); -} - -@media (max-width: 767px) { - .chapter-main-text { - font-size: 0.9rem; - } - .chapter-sub-text { - font-size: 0.8rem; - } -} - -.pagination-bar { - display: flex; - justify-content: center; - align-items: center; - gap: 1.5rem; - margin-top: 1rem; - padding-top: 1rem; - flex-wrap: wrap; -} - -.page-btn { - background: var(--bg-surface); - border: 1px solid var(--border); - color: var(--text-primary); - padding: 0.5rem 1.5rem; - border-radius: var(--radius-md); - cursor: pointer; - font-weight: 500; - transition: 0.2s; -} - -.page-btn:hover:not(:disabled) { - background: var(--bg-surface-hover); - border-color: var(--accent); -} - -.page-btn:disabled { - opacity: 0.4; - cursor: not-allowed; -} - -@media (max-width: 767px) { - .page-btn { - padding: 0.4rem 1rem; - font-size: 0.9rem; - } -} - -#reader-view { - position: fixed; - top: 0; - left: 0; - width: 100vw; - height: 100vh; - z-index: 200; - background: #0d0d0d; - overflow-y: auto; - display: flex; - flex-direction: column; - align-items: center; - padding-top: 60px; -} - -.reader-page-img { - max-width: 100%; - width: auto; - display: block; - margin-bottom: 0; - box-shadow: 0 0 20px rgba(0, 0, 0, 0.5); -} - -.reader-text-content { - max-width: 900px; - width: 95%; - color: #e4e4e7; - font-size: 1.1rem; - line-height: 1.8; - padding: 2rem; - background: #18181b; - margin-bottom: 4rem; - border-radius: 8px; - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5); -} - -.reader-text-content p { - margin-bottom: 1.5rem; -} - -@media (max-width: 767px) { - .reader-text-content { - font-size: 1rem; - line-height: 1.7; - padding: 1.5rem; - width: 100%; - border-radius: 0; - } -} - -.reader-close-btn { - position: fixed; - top: 20px; - left: 20px; - z-index: 210; - background: rgba(0, 0, 0, 0.8); - color: white; - border: 1px solid rgba(255, 255, 255, 0.2); - padding: 10px 20px; - border-radius: 8px; - cursor: pointer; - display: flex; - align-items: center; - gap: 8px; - font-weight: 600; - backdrop-filter: blur(4px); -} - -.reader-close-btn:hover { - background: var(--accent); - border-color: var(--accent); -} - -@media (max-width: 767px) { - .reader-close-btn { - top: 10px; - left: 10px; - padding: 8px 16px; - font-size: 0.9rem; - } -} - -.loading-state { - text-align: center; - padding: 4rem; - color: var(--text-tertiary); -} - -@media (max-width: 767px) { - .loading-state { - padding: 2rem 1rem; - } -} - -.book-read-overlay { - position: absolute; - inset: 0; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 0.5rem; - opacity: 0; - transition: opacity 0.3s ease; - pointer-events: none; - color: white; - z-index: 10; -} - -.image-entry[data-type="book"]:hover .book-read-overlay { - opacity: 1; -} - -.book-read-overlay span { - font-weight: 700; - font-size: 1.1rem; - text-transform: uppercase; - letter-spacing: 1px; - text-shadow: 0 2px 4px rgba(0, 0, 0, 0.8); -} - -.book-read-overlay svg { - filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8)); - color: var(--accent); -} - .image-entry[data-type="book"]::after { content: ""; position: absolute; @@ -419,4 +75,330 @@ .gallery-masonry .image-entry[data-type="book"]:hover .book-read-overlay { opacity: 1; +} + +.book-top-nav { + margin-bottom: 2rem; +} + +.back-btn-large { + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 0.75rem 1.25rem; + background: var(--bg-surface); + border: 1px solid var(--border); + border-radius: var(--radius-md); + color: var(--text-primary); + cursor: pointer; + transition: 0.2s; + font-weight: 500; +} + +.back-btn-large:hover { + background: var(--bg-surface-hover); + border-color: var(--accent); +} + +.back-btn-large svg { + flex-shrink: 0; +} + +.book-layout-grid { + display: grid; + grid-template-columns: 300px 1fr; + gap: 2rem; + align-items: start; +} + +.book-left-col { + position: sticky; + top: 2rem; +} + +.book-poster-large { + width: 100%; + border-radius: var(--radius-lg); + border: 1px solid var(--border); + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); + margin-bottom: 1.5rem; +} + +.book-title-sidebar { + font-size: 1.5rem; + font-weight: 700; + color: var(--text-primary); + margin: 0; + line-height: 1.3; +} + +.book-chapters-column { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.chapter-table-container { + background: var(--bg-surface); + border: 1px solid var(--border); + border-radius: var(--radius-lg); + overflow: hidden; +} + +.chapter-row { + padding: 1rem 1.5rem; + border-bottom: 1px solid var(--border); + cursor: pointer; + transition: 0.2s; + display: flex; + align-items: center; + justify-content: space-between; +} + +.chapter-row:last-child { + border-bottom: none; +} + +.chapter-row:hover { + background: var(--bg-surface-hover); +} + +.chapter-main-text { + font-weight: 500; + color: var(--text-primary); + font-size: 0.95rem; +} + +.pagination-bar { + display: flex; + justify-content: center; +} + +.page-btn { + padding: 0.5rem 1rem; + background: var(--bg-base); + border: 1px solid var(--border); + border-radius: var(--radius-md); + color: var(--text-primary); + cursor: pointer; + transition: 0.2s; + font-weight: 500; +} + +.page-btn:hover:not(:disabled) { + background: var(--accent); + border-color: var(--accent); +} + +.page-btn:disabled { + opacity: 0.4; + cursor: not-allowed; +} + +#reader-view { + position: fixed; + inset: 0; + background: #000; + z-index: 100; + overflow-y: auto; + padding: 4rem 0 2rem 0; +} + +.reader-close-btn { + position: fixed; + top: 1rem; + right: 1rem; + background: rgba(0, 0, 0, 0.8); + backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.1); + color: white; + padding: 0.75rem 1.25rem; + border-radius: var(--radius-md); + cursor: pointer; + display: flex; + align-items: center; + gap: 0.5rem; + font-weight: 500; + z-index: 101; + transition: 0.2s; +} + +.reader-close-btn:hover { + background: rgba(139, 92, 246, 0.9); + border-color: var(--accent); +} + +#reader-content { + max-width: 900px; + margin: 0 auto; + padding: 0 1rem; +} + +.reader-page-img { + width: 100%; + height: auto; + display: block; + margin-bottom: 0; + border-radius: 4px; +} + +.reader-text-content { + background: #1a1a1a; + color: #e5e5e5; + padding: 3rem; + border-radius: var(--radius-lg); + line-height: 1.8; + font-size: 1.05rem; + max-width: 800px; + margin: 0 auto; +} + +.reader-text-content p { + margin-bottom: 1.5rem; +} + +.reader-text-content h1, +.reader-text-content h2, +.reader-text-content h3 { + color: var(--accent); + margin-top: 2rem; + margin-bottom: 1rem; +} + +@media (max-width: 767px) { + /* Book Cards */ + .gallery-masonry.books-only { + grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); + gap: 1rem; + } + + .image-entry[data-type="book"] img { + height: 200px; + } + + .image-entry[data-type="book"]:hover { + transform: none; + } + + .image-entry[data-type="book"] .image-buttons { + padding: 0.5rem; + gap: 0.4rem; + opacity: 0.9; + } + + .image-entry[data-type="book"] .image-buttons button { + width: 32px; + height: 32px; + } + + /* Book Details */ + .book-layout-grid { + grid-template-columns: 1fr; + gap: 1.5rem; + } + + .book-left-col { + position: relative; + top: 0; + display: grid; + grid-template-columns: 140px 1fr; + gap: 1rem; + align-items: start; + } + + .book-poster-large { + width: 100%; + margin-bottom: 0; + } + + .book-title-sidebar { + font-size: 1.2rem; + align-self: center; + } + + .back-btn-large { + padding: 0.6rem 1rem; + font-size: 0.9rem; + margin-bottom: 1rem; + } + + /* Chapter List */ + .chapter-row { + padding: 0.85rem 1rem; + } + + .chapter-main-text { + font-size: 0.9rem; + } + + .pagination-bar { + flex-wrap: wrap; + gap: 0.75rem; + padding: 0.75rem; + } + + .page-btn { + padding: 0.5rem 0.85rem; + font-size: 0.85rem; + } + + #reader-view { + padding: 3.5rem 0 1rem 0; + } + + .reader-close-btn { + top: 0.75rem; + right: 0.75rem; + padding: 0.6rem 1rem; + font-size: 0.9rem; + } + + #reader-content { + padding: 0 0.75rem; + } + + .reader-text-content { + padding: 1.5rem; + font-size: 1rem; + line-height: 1.7; + } + + .reader-page-img { + border-radius: 2px; + } +} + +@media (min-width: 768px) and (max-width: 1023px) { + .gallery-masonry.books-only { + grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); + } + + .book-layout-grid { + grid-template-columns: 240px 1fr; + gap: 1.5rem; + } + + .image-entry[data-type="book"] img { + height: 280px; + } + + .book-left-col { + position: sticky; + top: 1rem; + } +} + +@media (min-width: 1400px) { + .gallery-masonry.books-only { + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + } + + .image-entry[data-type="book"] img { + height: 340px; + } + + .book-layout-grid { + grid-template-columns: 320px 1fr; + gap: 2.5rem; + } } \ No newline at end of file diff --git a/views/styles/emulator.css b/views/styles/emulator.css index cf506e9..52c1b89 100644 --- a/views/styles/emulator.css +++ b/views/styles/emulator.css @@ -4,7 +4,7 @@ gap: 1.5rem; height: calc(100vh - var(--header-height)); padding: 1rem 2rem 2rem 2rem; - overflow: hidden; + overflow: auto; } .editor-pane, @@ -51,6 +51,7 @@ flex-direction: column; gap: 0.25rem; flex: 1; + min-width: 120px; } .control-group label { @@ -94,6 +95,12 @@ gap: 0.5rem; border-bottom: 1px solid var(--border); margin-bottom: 0.5rem; + overflow-x: auto; + scrollbar-width: none; +} + +.tabs::-webkit-scrollbar { + display: none; } .tab-btn { @@ -104,6 +111,8 @@ cursor: pointer; border-bottom: 2px solid transparent; font-weight: 500; + white-space: nowrap; + transition: 0.2s; } .tab-btn.active { @@ -193,4 +202,169 @@ pre { .loading-state.hidden { display: none; +} + +@media (max-width: 767px) { + .emulator-container { + grid-template-columns: 1fr; + grid-template-rows: minmax(250px, 40vh) minmax(400px, 1fr); + gap: 1rem; + padding: 1rem; + height: auto; + overflow-y: auto; + } + + .editor-pane, + .preview-pane { + gap: 0.75rem; + height: auto; + min-height: 0; + overflow: visible; + } + + .editor-pane { + display: flex; + flex-direction: column; + } + + .preview-pane { + display: flex; + flex-direction: column; + overflow: visible; + } + + .code-editor { + font-size: 13px; + padding: 0.75rem; + min-height: 200px; + max-height: 35vh; + } + + .control-bar { + padding: 0.75rem; + gap: 0.5rem; + flex-direction: column; + align-items: stretch; + } + + .control-bar[style*="background: transparent"] { + flex-direction: row !important; + padding: 0 !important; + } + + .control-group { + flex: unset; + width: 100%; + min-width: 0; + } + + .control-group:has(label:contains("Page")) { + max-width: none; + } + + .control-input { + font-size: 0.85rem; + padding: 0.6rem; + } + + .btn-run { + width: 100%; + height: auto; + padding: 0.75rem; + align-self: stretch; + margin-top: 0.25rem; + } + + .tabs { + gap: 0.25rem; + margin-bottom: 0.5rem; + } + + .tab-btn { + padding: 0.6rem 0.75rem; + font-size: 0.85rem; + flex: 1; + text-align: center; + } + + .output-area { + padding: 0.75rem; + min-height: 300px; + overflow: auto; + } + + .visual-card { + width: 130px; + margin: 0.35rem; + } + + .visual-card img { + height: 170px; + } + + .visual-card .title { + font-size: 0.75rem; + padding: 0.4rem; + } + + .visual-chapter { + padding: 0.6rem 0.5rem; + font-size: 0.9rem; + } + + pre { + font-size: 0.8rem; + } + + .log-entry { + font-size: 0.8rem; + } +} + +@media (min-width: 768px) and (max-width: 1023px) { + .emulator-container { + grid-template-columns: 1fr; + grid-template-rows: auto 1fr; + gap: 1.25rem; + padding: 1rem 1.5rem; + } + + .editor-pane { + max-height: 35vh; + } + + .preview-pane { + min-height: 45vh; + } + + .code-editor { + font-size: 13px; + } + + .control-bar { + flex-wrap: wrap; + } + + .control-group { + min-width: 140px; + } + + .btn-run { + width: auto; + min-width: 100px; + } +} + +@media (min-width: 1024px) and (max-width: 1279px) { + .emulator-container { + gap: 1.25rem; + } + + .visual-card { + width: 140px; + } + + .visual-card img { + height: 180px; + } } \ No newline at end of file diff --git a/views/styles/home.css b/views/styles/home.css index 8187a78..d9e092e 100644 --- a/views/styles/home.css +++ b/views/styles/home.css @@ -54,13 +54,6 @@ body { width: var(--sidebar-width-expanded); } -@media (max-width: 767px) { - .sidebar { - width: 60px; - padding: 1rem 0.5rem; - } -} - .main-wrapper { flex: 1; display: flex; @@ -131,18 +124,6 @@ body { margin-right: 1rem; } -@media (max-width: 767px) { - .nav-button { - padding: 0.7rem; - } - .nav-button svg { - min-width: 20px; - width: 20px; - height: 20px; - margin-right: 0; - } -} - a, a:visited, a:hover, @@ -172,13 +153,6 @@ a:active { z-index: 40; } -@media (max-width: 767px) { - .top-header { - height: 60px; - padding: 0 1rem; - } -} - .search-box { display: contents; } @@ -199,33 +173,12 @@ a:active { box-shadow: 0 0 0 2px var(--accent-glow); } -@media (max-width: 767px) { - #search-input { - width: 100%; - max-width: 350px; - font-size: 0.85rem; - } -} - -@media (max-width: 480px) { - #search-input { - width: calc(100vw - 80px); - max-width: 300px; - } -} - .content-view { flex: 1; overflow-y: auto; padding: 0 2rem 2rem 2rem; } -@media (max-width: 767px) { - .content-view { - padding: 0 1rem 2rem 1rem; - } -} - .page { max-width: 1600px; margin: 0 auto; @@ -272,12 +225,6 @@ a:active { background: var(--border-hover); } -@media (max-width: 767px) { - #source-list { - gap: 0.75rem; - } -} - .source-button { background: var(--bg-surface); border: 1px solid var(--border); @@ -310,14 +257,6 @@ a:active { color: var(--text-primary); } -@media (max-width: 767px) { - .source-button { - min-width: 160px; - padding: 0.6rem 0.8rem; - gap: 0.75rem; - } -} - .source-button img, .source-button .brand-icon { width: 32px; @@ -327,14 +266,6 @@ a:active { flex-shrink: 0; } -@media (max-width: 767px) { - .source-button img, - .source-button .brand-icon { - width: 28px; - height: 28px; - } -} - .source-text-wrapper { display: flex; flex-direction: column; @@ -360,15 +291,6 @@ a:active { text-overflow: ellipsis; } -@media (max-width: 767px) { - .source-name { - font-size: 0.85rem; - } - .source-url { - font-size: 0.7rem; - } -} - .gallery-masonry { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); @@ -379,30 +301,6 @@ a:active { grid-auto-rows: 8px; } -@media (min-width: 768px) { - .gallery-masonry { - grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); - } -} - -@media (min-width: 1024px) { - .gallery-masonry { - grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); - } -} - -@media (min-width: 1400px) { - .gallery-masonry { - grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); - } -} - -@media (max-width: 480px) { - .gallery-masonry { - grid-template-columns: 1fr; - } -} - .image-entry:not([data-type="book"]) { margin-bottom: 0; border-radius: var(--radius-md); @@ -412,7 +310,7 @@ a:active { break-inside: avoid; transition: transform 0.2s; cursor: zoom-in; - display: inline-block; + display: block; width: 100%; } @@ -422,20 +320,17 @@ a:active { box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3); } -@media (max-width: 767px) { - .image-entry:hover { - transform: none; - } -} - .image-entry img { width: 100%; height: auto; + display: block; aspect-ratio: auto; } .image-entry img.loaded { opacity: 1; + transition: opacity 0.3s ease-in; + min-height: unset; } .image-buttons { @@ -459,13 +354,6 @@ a:active { opacity: 1; } -@media (max-width: 767px) { - .image-buttons { - opacity: 0.6; - padding: 1.5rem 0.75rem 0.75rem 0.75rem; - } -} - .image-buttons button { width: 32px; height: 32px; @@ -492,30 +380,12 @@ a:active { height: 16px; } -@media (max-width: 767px) { - .image-buttons button { - width: 36px; - height: 36px; - } - .image-buttons button svg { - width: 18px; - height: 18px; - } -} - .settings-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 1.5rem; } -@media (max-width: 640px) { - .settings-grid { - grid-template-columns: 1fr; - gap: 1rem; - } -} - .settings-card { background: var(--bg-surface); border: 1px solid var(--border); @@ -523,12 +393,6 @@ a:active { padding: 1.5rem; } -@media (max-width: 767px) { - .settings-card { - padding: 1rem; - } -} - .settings-card h3 { margin-top: 0; font-size: 1.1rem; @@ -579,12 +443,6 @@ input[type="radio"] { gap: 1rem; } -@media (max-width: 767px) { - .loading-state { - padding: 2rem 1rem; - } -} - #tag-info-modal { position: fixed; inset: 0; @@ -601,7 +459,7 @@ input[type="radio"] { display: none; } -#tag-info-modal > div { +#tag-info-modal>div { background: var(--bg-surface); border: 1px solid var(--border); padding: 2rem; @@ -614,13 +472,6 @@ input[type="radio"] { overflow-y: auto; } -@media (max-width: 767px) { - #tag-info-modal > div { - padding: 1.5rem; - width: 95%; - } -} - #tag-info-close-button { position: absolute; top: 1rem; @@ -672,17 +523,6 @@ input[type="radio"] { max-width: calc(100vw - 4rem); } -@media (max-width: 767px) { - .toast { - bottom: 1rem; - right: 1rem; - left: 1rem; - max-width: none; - padding: 0.75rem 1rem; - font-size: 0.9rem; - } -} - .toast:not(.hidden) { transform: translateY(0); opacity: 1; @@ -704,6 +544,7 @@ input[type="radio"] { padding: 4rem 1rem; break-inside: avoid; column-span: all; + grid-column: 1 / -1; } #gallery-placeholder p { @@ -713,12 +554,6 @@ input[type="radio"] { margin: 0; } -.image-entry img.loaded { - opacity: 1; - transition: opacity 0.3s ease-in; - min-height: unset; -} - @keyframes fadeInUp { from { opacity: 0; @@ -732,4 +567,254 @@ input[type="radio"] { .image-entry.newly-added { animation: fadeInUp 0.4s ease-out; +} + +.hamburger { + display: none; + width: 42px; + height: 42px; + border-radius: 12px; + border: 1px solid var(--border); + background: var(--bg-surface); + color: var(--text-primary); + font-size: 1.8rem; + font-weight: bold; + cursor: pointer; + position: absolute; + left: 15px; + top: 50%; + transform: translateY(-50%); + transition: background 0.2s, border-color 0.2s; + align-items: center; + justify-content: center; + z-index: 999; +} + +.hamburger:hover { + background: var(--bg-surface-hover); + border-color: var(--accent); +} + +@media (min-width: 1400px) { + .gallery-masonry { + grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); + } +} + +@media (min-width: 1024px) and (max-width: 1399px) { + .gallery-masonry { + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + } +} + +@media (min-width: 768px) and (max-width: 1023px) { + .content-view { + padding: 0 1.5rem 2rem 1.5rem; + } + + .top-header { + padding: 0 1.5rem; + } + + .gallery-masonry { + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + } + + #search-input { + width: 280px; + } + + .source-button { + min-width: 180px; + } + + .settings-grid { + grid-template-columns: 1fr; + } +} + +@media (max-width: 767px) { + html { + font-size: 16px; + } + + body { + zoom: 1; + } + + .content-view { + overflow-x: hidden !important; + padding: 0 1rem 2rem 1rem; + } + + .top-header { + height: 70px; + padding: 0 1rem; + justify-content: flex-start; + } + + .hamburger { + display: flex; + position: static; + transform: none; + margin-right: auto; + } + + #search-input { + width: 100%; + max-width: none; + font-size: 1rem; + padding: 0.6rem 1rem; + } + + .sidebar { + position: fixed; + left: -100%; + top: 0; + width: 280px; + height: 100%; + background: var(--bg-sidebar); + transition: left 0.3s ease; + z-index: 300; + padding: 1.5rem 1rem; + box-shadow: 4px 0 20px rgba(0, 0, 0, 0.5); + } + + .sidebar.active { + left: 0; + } + + .sidebar:hover { + width: 280px; + } + + .main-wrapper { + margin-left: 0 !important; + width: 100%; + } + + .sidebar .nav-button span { + opacity: 1 !important; + transform: translateX(0) !important; + } + + .sidebar nav { + gap: 0.75rem !important; + } + + .nav-button { + padding: 1rem 1.25rem !important; + font-size: 1rem !important; + } + + .nav-button span { + font-size: 1rem !important; + } + + .nav-button svg { + width: 24px !important; + height: 24px !important; + stroke-width: 2 !important; + margin-right: 0.75rem !important; + } + + .gallery-masonry { + grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); + gap: 0.75rem; + } + + .image-entry:not([data-type="book"]):hover { + transform: none; + } + + .image-buttons { + opacity: 0.8; + padding: 1.5rem 0.75rem 0.75rem 0.75rem; + } + + .image-buttons button { + width: 36px; + height: 36px; + } + + .image-buttons button svg { + width: 18px; + height: 18px; + } + + #source-list { + gap: 0.75rem; + padding-bottom: 0.75rem; + } + + .source-button { + min-width: 160px; + padding: 0.6rem 0.85rem; + gap: 0.75rem; + } + + .source-button img, + .source-button .brand-icon { + width: 28px; + height: 28px; + } + + .source-name { + font-size: 0.9rem; + } + + .source-url { + font-size: 0.7rem; + } + + .source-button:hover { + transform: none; + } + + .toast { + bottom: 1rem; + right: 1rem; + left: 1rem; + max-width: none; + padding: 0.85rem 1rem; + font-size: 0.9rem; + } + + .loading-state { + padding: 2rem 1rem; + } + + #tag-info-modal>div { + padding: 1.5rem; + width: 95%; + } + + .settings-grid { + grid-template-columns: 1fr; + gap: 1rem; + } + + .settings-card { + padding: 1.25rem; + } + + h1, h2, h3 { + font-size: 1.25rem; + } +} + +@media (max-width: 480px) { + .gallery-masonry { + grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); + gap: 0.6rem; + } + + .source-button { + min-width: 140px; + padding: 0.5rem 0.75rem; + } + + .source-name { + font-size: 0.85rem; + } } \ No newline at end of file diff --git a/views/styles/marketplace.css b/views/styles/marketplace.css index 42aa065..5547598 100644 --- a/views/styles/marketplace.css +++ b/views/styles/marketplace.css @@ -32,7 +32,7 @@ .hero-content { z-index: 1; - max-width: 60%; + max-width: 100%; } .hero-title { @@ -42,6 +42,7 @@ background: linear-gradient(to right, #fff, #a5b4fc); -webkit-background-clip: text; -webkit-text-fill-color: transparent; + background-clip: text; } .hero-subtitle { @@ -53,7 +54,8 @@ .hero-stats { display: flex; - gap: 2rem; + gap: 1.5rem; + flex-wrap: wrap; } .stat-box { @@ -65,7 +67,7 @@ } .stat-value { - font-size: 1.2rem; + font-size: 1.5rem; font-weight: 700; color: #fff; display: block; @@ -120,6 +122,7 @@ .section-icon { color: var(--accent); + flex-shrink: 0; } .section-title { @@ -156,6 +159,7 @@ display: flex; justify-content: space-between; align-items: flex-start; + gap: 0.75rem; } .ext-icon-box { @@ -168,6 +172,7 @@ display: flex; align-items: center; justify-content: center; + flex-shrink: 0; } .ext-icon { @@ -231,7 +236,7 @@ } .install-btn:hover { - background: #7c3aed; + background: #7c3aed; box-shadow: 0 0 15px var(--accent-glow); } @@ -254,4 +259,148 @@ @keyframes rotate { 100% { transform: rotate(360deg); } } .hidden { display: none !important; } -.loading-state { text-align: center; padding: 4rem; color: var(--text-tertiary); } \ No newline at end of file +.loading-state { text-align: center; padding: 4rem; color: var(--text-tertiary); } + +.main-wrapper .top-header { + display: none; +} + +@media (max-width: 767px) { + .main-wrapper .top-header { + display: flex; + } + #marketplace-page { + gap: 1.5rem; + padding-bottom: 2rem; + } + + .marketplace-hero { + padding: 1.5rem; + border-radius: 12px; + } + + .marketplace-hero::before { + width: 250px; + height: 250px; + right: -20%; + top: -30%; + } + + .hero-title { + font-size: 1.8rem; + margin-bottom: 0.5rem; + } + + .hero-subtitle { + font-size: 0.9rem; + margin-bottom: 1.25rem; + line-height: 1.4; + } + + .hero-stats { + gap: 1rem; + } + + .stat-box { + padding: 0.6rem 1rem; + flex: 1; + min-width: 0; + } + + .stat-value { + font-size: 1.3rem; + } + + .stat-label { + font-size: 0.7rem; + } + + .marketplace-tabs { + width: 100%; + justify-content: stretch; + gap: 0.5rem; + padding: 0.4rem; + } + + .tab-btn { + flex: 1; + padding: 0.7rem 1rem; + font-size: 0.9rem; + } + + .section-header { + margin-bottom: 1rem; + } + + .section-title { + font-size: 1rem; + } + + .section-icon { + width: 18px; + height: 18px; + } + + .marketplace-grid { + grid-template-columns: 1fr; + gap: 1rem; + } + + .extension-card { + padding: 1.25rem; + gap: 0.75rem; + } + + .extension-card:hover { + transform: none; + } + + .ext-icon-box { + width: 48px; + height: 48px; + } + + .ext-name { + font-size: 1rem; + } + + .ext-meta { + font-size: 0.75rem; + } + + .type-badge { + font-size: 0.6rem; + padding: 3px 7px; + } + + .card-footer { + padding-top: 0.75rem; + } + + .ext-size { + font-size: 0.7rem; + } + + .install-btn { + padding: 0.5rem 0.85rem; + font-size: 0.8rem; + } + + .loading-state { + padding: 2rem 1rem; + } +} + +@media (min-width: 768px) and (max-width: 1023px) { + .marketplace-grid { + grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); + } + + .hero-title { + font-size: 2rem; + } + + .marketplace-tabs { + width: auto; + } +} \ No newline at end of file