From 6b4e5e9ce8569163ef4512024c0feb08f9bfeb3e Mon Sep 17 00:00:00 2001 From: Baivab Sarkar Date: Thu, 11 Jun 2026 11:13:27 +0530 Subject: [PATCH 1/4] fix: resolve blank page and timeout errors on large PDF exports --- desktop-app/resources/js/script.js | 92 ++++++++++++++++++------------ script.js | 92 ++++++++++++++++++------------ 2 files changed, 110 insertions(+), 74 deletions(-) diff --git a/desktop-app/resources/js/script.js b/desktop-app/resources/js/script.js index 9f457d2a..4ddda0b6 100644 --- a/desktop-app/resources/js/script.js +++ b/desktop-app/resources/js/script.js @@ -8158,50 +8158,68 @@ document.addEventListener("DOMContentLoaded", function () { const contentWidth = pageWidth - (margin * 2); const captureScale = choosePdfCanvasScale(tempElement); - updatePdfProgress(progressState, 65, "Capturing document"); - const canvas = await runPdfAbortable(progressState, html2canvas(tempElement, { - scale: captureScale, - useCORS: true, - allowTaint: false, - logging: false, - windowWidth: Math.max(PAGE_CONFIG.windowWidth, Math.ceil(tempElement.getBoundingClientRect().width)), - windowHeight: Math.ceil(tempElement.getBoundingClientRect().height) - })); - await waitForPdfFrame(progressState); - throwIfPdfExportAborted(progressState.signal); + const pageCount = pageBreakAnalysis.pageCount; + const pageHeightPx = pageBreakAnalysis.pageHeightPx; + const totalHeight = Math.ceil(tempElement.getBoundingClientRect().height); + + const PAGES_PER_CHUNK = 8; + const chunkCount = Math.ceil(pageCount / PAGES_PER_CHUNK); - console.log(`[PDF DEBUG] canvas.width = ${canvas.width}, canvas.height = ${canvas.height}`); - console.log(`[PDF DEBUG] tempElement.offsetWidth = ${tempElement.offsetWidth}, rect.width = ${tempElement.getBoundingClientRect().width}`); - const scaleFactor = canvas.width / contentWidth; - console.log(`[PDF DEBUG] scaleFactor = ${scaleFactor}, PAGE_CONFIG.scale = ${PAGE_CONFIG.scale}, captureScale = ${captureScale}`); - const imgHeight = canvas.height / scaleFactor; - console.log(`[PDF DEBUG] imgHeight = ${imgHeight}, contentHeight = ${pageHeight - margin * 2}`); - // Introduce a 0.5mm tolerance to prevent rounding errors from creating a trailing blank page - const pagesCount = Math.ceil((imgHeight - 0.5) / (pageHeight - margin * 2)); - console.log(`[PDF DEBUG] pagesCount = ${pagesCount}`); - - updatePdfProgress(progressState, 76, "Rendering pages"); - for (let page = 0; page < pagesCount; page++) { + logPdfExportDebug("Starting hybrid chunked capture loop. Total pages:", pageCount, "Chunks:", chunkCount); + updatePdfProgress(progressState, 65, "Rendering pages"); + + for (let c = 0; c < chunkCount; c++) { throwIfPdfExportAborted(progressState.signal); - const pageProgress = 76 + ((page + 1) / pagesCount) * 18; - updatePdfProgress(progressState, pageProgress, `Rendering page ${page + 1} of ${pagesCount}`); + + const startPage = c * PAGES_PER_CHUNK; + const endPage = Math.min((c + 1) * PAGES_PER_CHUNK, pageCount); + + const yStart = startPage * pageHeightPx; + const chunkHeight = Math.min(totalHeight - yStart, (endPage - startPage) * pageHeightPx); + + const progressPercent = 65 + ((c + 1) / chunkCount) * 33; + updatePdfProgress(progressState, progressPercent, `Rendering page ${startPage + 1} to ${endPage} of ${pageCount}`); - if (page > 0) pdf.addPage(); + console.log(`[PDF DEBUG] Rendering chunk ${c + 1}/${chunkCount}: yStart=${yStart}, chunkHeight=${chunkHeight}`); + + const chunkCanvas = await runPdfAbortable(progressState, html2canvas(tempElement, { + scale: captureScale, + useCORS: true, + allowTaint: false, + logging: false, + x: 0, + y: yStart, + width: tempElement.offsetWidth, + height: chunkHeight, + windowWidth: Math.max(PAGE_CONFIG.windowWidth, Math.ceil(tempElement.getBoundingClientRect().width)), + windowHeight: totalHeight, + scrollX: 0, + scrollY: 0 + })); + + const chunkPagesCount = endPage - startPage; + for (let p = 0; p < chunkPagesCount; p++) { + throwIfPdfExportAborted(progressState.signal); + const pageIndex = startPage + p; + + if (pageIndex > 0) pdf.addPage(); - const sourceY = page * (pageHeight - margin * 2) * scaleFactor; - const sourceHeight = Math.min(canvas.height - sourceY, (pageHeight - margin * 2) * scaleFactor); - const destHeight = sourceHeight / scaleFactor; + const pageYInChunkCanvas = p * pageHeightPx * captureScale; + const pageHeightInChunkCanvas = Math.min(chunkCanvas.height - pageYInChunkCanvas, pageHeightPx * captureScale); - const pageCanvas = document.createElement('canvas'); - pageCanvas.width = canvas.width; - pageCanvas.height = sourceHeight; + const pageCanvas = document.createElement('canvas'); + pageCanvas.width = chunkCanvas.width; + pageCanvas.height = pageHeightInChunkCanvas; - const ctx = pageCanvas.getContext('2d'); - ctx.drawImage(canvas, 0, sourceY, canvas.width, sourceHeight, 0, 0, canvas.width, sourceHeight); + const ctx = pageCanvas.getContext('2d'); + ctx.drawImage(chunkCanvas, 0, pageYInChunkCanvas, chunkCanvas.width, pageHeightInChunkCanvas, 0, 0, chunkCanvas.width, pageHeightInChunkCanvas); - const imgData = pageCanvas.toDataURL('image/png'); - pdf.addImage(imgData, 'PNG', margin, margin, contentWidth, destHeight); - await waitForPdfFrame(progressState); + const imgData = pageCanvas.toDataURL('image/jpeg', 0.95); + const destHeight = (pageHeightInChunkCanvas / captureScale) / (pageCanvas.width / contentWidth); + pdf.addImage(imgData, 'JPEG', margin, margin, contentWidth, destHeight); + + await waitForPdfFrame(progressState); + } } throwIfPdfExportAborted(progressState.signal); diff --git a/script.js b/script.js index 9f457d2a..4ddda0b6 100644 --- a/script.js +++ b/script.js @@ -8158,50 +8158,68 @@ document.addEventListener("DOMContentLoaded", function () { const contentWidth = pageWidth - (margin * 2); const captureScale = choosePdfCanvasScale(tempElement); - updatePdfProgress(progressState, 65, "Capturing document"); - const canvas = await runPdfAbortable(progressState, html2canvas(tempElement, { - scale: captureScale, - useCORS: true, - allowTaint: false, - logging: false, - windowWidth: Math.max(PAGE_CONFIG.windowWidth, Math.ceil(tempElement.getBoundingClientRect().width)), - windowHeight: Math.ceil(tempElement.getBoundingClientRect().height) - })); - await waitForPdfFrame(progressState); - throwIfPdfExportAborted(progressState.signal); + const pageCount = pageBreakAnalysis.pageCount; + const pageHeightPx = pageBreakAnalysis.pageHeightPx; + const totalHeight = Math.ceil(tempElement.getBoundingClientRect().height); + + const PAGES_PER_CHUNK = 8; + const chunkCount = Math.ceil(pageCount / PAGES_PER_CHUNK); - console.log(`[PDF DEBUG] canvas.width = ${canvas.width}, canvas.height = ${canvas.height}`); - console.log(`[PDF DEBUG] tempElement.offsetWidth = ${tempElement.offsetWidth}, rect.width = ${tempElement.getBoundingClientRect().width}`); - const scaleFactor = canvas.width / contentWidth; - console.log(`[PDF DEBUG] scaleFactor = ${scaleFactor}, PAGE_CONFIG.scale = ${PAGE_CONFIG.scale}, captureScale = ${captureScale}`); - const imgHeight = canvas.height / scaleFactor; - console.log(`[PDF DEBUG] imgHeight = ${imgHeight}, contentHeight = ${pageHeight - margin * 2}`); - // Introduce a 0.5mm tolerance to prevent rounding errors from creating a trailing blank page - const pagesCount = Math.ceil((imgHeight - 0.5) / (pageHeight - margin * 2)); - console.log(`[PDF DEBUG] pagesCount = ${pagesCount}`); - - updatePdfProgress(progressState, 76, "Rendering pages"); - for (let page = 0; page < pagesCount; page++) { + logPdfExportDebug("Starting hybrid chunked capture loop. Total pages:", pageCount, "Chunks:", chunkCount); + updatePdfProgress(progressState, 65, "Rendering pages"); + + for (let c = 0; c < chunkCount; c++) { throwIfPdfExportAborted(progressState.signal); - const pageProgress = 76 + ((page + 1) / pagesCount) * 18; - updatePdfProgress(progressState, pageProgress, `Rendering page ${page + 1} of ${pagesCount}`); + + const startPage = c * PAGES_PER_CHUNK; + const endPage = Math.min((c + 1) * PAGES_PER_CHUNK, pageCount); + + const yStart = startPage * pageHeightPx; + const chunkHeight = Math.min(totalHeight - yStart, (endPage - startPage) * pageHeightPx); + + const progressPercent = 65 + ((c + 1) / chunkCount) * 33; + updatePdfProgress(progressState, progressPercent, `Rendering page ${startPage + 1} to ${endPage} of ${pageCount}`); - if (page > 0) pdf.addPage(); + console.log(`[PDF DEBUG] Rendering chunk ${c + 1}/${chunkCount}: yStart=${yStart}, chunkHeight=${chunkHeight}`); + + const chunkCanvas = await runPdfAbortable(progressState, html2canvas(tempElement, { + scale: captureScale, + useCORS: true, + allowTaint: false, + logging: false, + x: 0, + y: yStart, + width: tempElement.offsetWidth, + height: chunkHeight, + windowWidth: Math.max(PAGE_CONFIG.windowWidth, Math.ceil(tempElement.getBoundingClientRect().width)), + windowHeight: totalHeight, + scrollX: 0, + scrollY: 0 + })); + + const chunkPagesCount = endPage - startPage; + for (let p = 0; p < chunkPagesCount; p++) { + throwIfPdfExportAborted(progressState.signal); + const pageIndex = startPage + p; + + if (pageIndex > 0) pdf.addPage(); - const sourceY = page * (pageHeight - margin * 2) * scaleFactor; - const sourceHeight = Math.min(canvas.height - sourceY, (pageHeight - margin * 2) * scaleFactor); - const destHeight = sourceHeight / scaleFactor; + const pageYInChunkCanvas = p * pageHeightPx * captureScale; + const pageHeightInChunkCanvas = Math.min(chunkCanvas.height - pageYInChunkCanvas, pageHeightPx * captureScale); - const pageCanvas = document.createElement('canvas'); - pageCanvas.width = canvas.width; - pageCanvas.height = sourceHeight; + const pageCanvas = document.createElement('canvas'); + pageCanvas.width = chunkCanvas.width; + pageCanvas.height = pageHeightInChunkCanvas; - const ctx = pageCanvas.getContext('2d'); - ctx.drawImage(canvas, 0, sourceY, canvas.width, sourceHeight, 0, 0, canvas.width, sourceHeight); + const ctx = pageCanvas.getContext('2d'); + ctx.drawImage(chunkCanvas, 0, pageYInChunkCanvas, chunkCanvas.width, pageHeightInChunkCanvas, 0, 0, chunkCanvas.width, pageHeightInChunkCanvas); - const imgData = pageCanvas.toDataURL('image/png'); - pdf.addImage(imgData, 'PNG', margin, margin, contentWidth, destHeight); - await waitForPdfFrame(progressState); + const imgData = pageCanvas.toDataURL('image/jpeg', 0.95); + const destHeight = (pageHeightInChunkCanvas / captureScale) / (pageCanvas.width / contentWidth); + pdf.addImage(imgData, 'JPEG', margin, margin, contentWidth, destHeight); + + await waitForPdfFrame(progressState); + } } throwIfPdfExportAborted(progressState.signal); From 8ca2cfc2e6d74872070840c673c1a36b09e9442e Mon Sep 17 00:00:00 2001 From: Baivab Sarkar Date: Thu, 11 Jun 2026 11:54:01 +0530 Subject: [PATCH 2/4] fix: resolve squished PDF layout and add native print dialog fallback for large documents --- desktop-app/resources/js/script.js | 79 +- desktop-app/resources/styles.css | 7703 ++++++++++++++-------------- script.js | 79 +- styles.css | 7703 ++++++++++++++-------------- 4 files changed, 7886 insertions(+), 7678 deletions(-) diff --git a/desktop-app/resources/js/script.js b/desktop-app/resources/js/script.js index 4ddda0b6..7cbfd9bd 100644 --- a/desktop-app/resources/js/script.js +++ b/desktop-app/resources/js/script.js @@ -7964,18 +7964,51 @@ document.addEventListener("DOMContentLoaded", function () { return Promise.all(promises); } - // ============================================ - // End Oversized Graphics Scaling Functions - // ============================================ + function showLargePdfExportDialog(onChoosePrint, onChooseCanvas) { + const dialogOverlay = document.createElement("div"); + dialogOverlay.className = "reset-modal-overlay"; + dialogOverlay.style.display = "flex"; + dialogOverlay.setAttribute("role", "dialog"); + dialogOverlay.setAttribute("aria-modal", "true"); + + dialogOverlay.innerHTML = ` +
+

Large Document Detected

+

+ This document is very large. Generating a canvas-based PDF can take a long time and might cause browser lagging. +

+ We recommend using the Browser Print Dialog (select 'Save as PDF' as the destination). It is instant, uses vector graphics for perfectly sharp text, and has zero document size limits. +

+
+ + + +
+
+ `; - exportPdf.addEventListener("click", async function (event) { - event.preventDefault(); - logPdfExportDebug("PDF export button clicked!"); - if (activePdfExport) { - logPdfExportDebug("PDF export already active, ignoring click"); - return; - } + document.body.appendChild(dialogOverlay); + const cleanup = () => { + dialogOverlay.remove(); + }; + + dialogOverlay.querySelector("#large-pdf-cancel").addEventListener("click", () => { + cleanup(); + }); + + dialogOverlay.querySelector("#large-pdf-canvas").addEventListener("click", () => { + cleanup(); + onChooseCanvas(); + }); + + dialogOverlay.querySelector("#large-pdf-print").addEventListener("click", () => { + cleanup(); + onChoosePrint(); + }); + } + + async function startCanvasPdfExport() { const progressState = createPdfProgressState(); activePdfExport = progressState; setPdfExportTriggersBusy(progressState, true); @@ -8237,6 +8270,32 @@ document.addEventListener("DOMContentLoaded", function () { } finally { cleanupPdfExport(progressState); } + } + + exportPdf.addEventListener("click", async function (event) { + event.preventDefault(); + logPdfExportDebug("PDF export button clicked!"); + if (activePdfExport) { + logPdfExportDebug("PDF export already active, ignoring click"); + return; + } + + const markdown = markdownEditor.value; + // Set a threshold of 30,000 characters for large documents + if (markdown.length > 30000) { + showLargePdfExportDialog( + () => { + // Choice: Browser Print + window.print(); + }, + () => { + // Choice: Canvas rendering + startCanvasPdfExport(); + } + ); + } else { + startCanvasPdfExport(); + } }); copyMarkdownButton.addEventListener("click", function () { diff --git a/desktop-app/resources/styles.css b/desktop-app/resources/styles.css index aafd5a8a..c0c8401f 100644 --- a/desktop-app/resources/styles.css +++ b/desktop-app/resources/styles.css @@ -1,3873 +1,3918 @@ -:root { - --bg-color: #ffffff; - --editor-bg: #f6f8fa; - --preview-bg: #ffffff; /* Preview background for light mode */ - --text-color: #24292e; - --text-secondary: #57606a; - --font-mono: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace; - --color-danger-fg: #d73a49; - --preview-text-color: #24292e; /* Text color for preview in light mode */ - --border-color: #e1e4e8; - --header-bg: #f6f8fa; - --button-bg: #f6f8fa; - --button-hover: #e1e4e8; - --button-active: #d1d5da; - --scrollbar-thumb: #c1c1c1; - --scrollbar-track: #f1f1f1; - --accent-color: #0366d6; - --table-bg: #ffffff; /* Table background for light mode */ - --code-bg: #f6f8fa; /* Code block background for light mode */ - --skeleton-bg: #e2e8f0; - --skeleton-glow: rgba(255, 255, 255, 0.65); - - /* Find & Replace Panel custom properties (PERF-010 consolidated) */ - --fr-bg: rgba(255, 255, 255, 0.95); - --fr-border: #d0d7de; - --fr-shadow: 0 8px 24px rgba(140, 149, 159, 0.2); - --fr-btn-active: #0969da; - --fr-btn-active-bg: #ddf4ff; - --fr-match-highlight: #ffdf5d; - --fr-match-active: #ff9b30; - --fr-match-text-color: #24292e; - --fr-match-active-text-color: #24292e; - --fr-error-bg: #ffebe9; - --fr-error-border: #ff8577; - --fr-text-danger: #cf222e; -} - -[data-theme="dark"] { - --bg-color: #0d1117; - --editor-bg: #161b22; - --preview-bg: #0d1117; /* Preview background for dark mode */ - --text-color: #c9d1d9; - --text-secondary: #8b949e; - --color-danger-fg: #f85149; - --preview-text-color: #c9d1d9; /* Text color for preview in dark mode */ - --border-color: #30363d; - --header-bg: #161b22; - --button-bg: #21262d; - --button-hover: #30363d; - --button-active: #3b434b; - --scrollbar-thumb: #484f58; - --scrollbar-track: #21262d; - --accent-color: #58a6ff; - --table-bg: #161b22; /* Table background for dark mode */ - --code-bg: #161b22; /* Code block background for dark mode */ - --skeleton-bg: #2d3139; - --skeleton-glow: rgba(255, 255, 255, 0.08); - - /* Find & Replace Panel custom properties for dark mode */ - --fr-bg: rgba(28, 33, 40, 0.98); - --fr-border: #444c56; - --fr-shadow: 0 8px 24px rgba(0, 0, 0, 0.5); - --fr-btn-active: #2f81f7; - --fr-btn-active-bg: rgba(56, 139, 253, 0.15); - --fr-match-highlight: rgba(187, 128, 9, 0.4); - --fr-match-active: #ad6200; - --fr-match-text-color: #c9d1d9; - --fr-match-active-text-color: #ffffff; - --fr-error-bg: rgba(248, 81, 73, 0.1); - --fr-error-border: rgba(248, 81, 73, 0.4); - --fr-text-danger: #ff7b72; -} - -* { - box-sizing: border-box; - margin: 0; - padding: 0; -} - -@media (min-width: 768px) { - html, - body { - height: 100%; - overflow: hidden; - } -} - -body { - background-color: var(--bg-color); - color: var(--text-color); - /* PERF-021: Removed background-color transition to avoid full-viewport repaint on theme toggle */ - transition: color 0.15s ease; - min-height: 100vh; - font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Hiragino Kaku Gothic ProN", Meiryo, "Malgun Gothic", "Apple SD Gothic Neo", "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; -} - -.app-header { - background-color: var(--header-bg); - border-bottom: 1px solid var(--border-color); - padding: 0.35rem 0.75rem; - transition: background-color 0.3s ease; - position: relative; - z-index: 100; - flex-shrink: 0; -} - -.app-container { - height: 100vh; - display: flex; - flex-direction: column; - overflow: hidden; -} - -.content-container { - display: flex; - flex: 1; - overflow: hidden; -} - -.editor-pane, .preview-pane { - flex: 1; - padding: 20px; - overflow-y: auto; - position: relative; - /* PERF-025: Shortened transition and scoped to background-color only */ - transition: background-color 0.15s ease; -} - -.editor-pane { - background-color: var(--editor-bg); - border-right: 1px solid var(--border-color); - padding-right: 0px; - --line-number-gutter: 0px; -} - -.preview-pane { - background-color: var(--preview-bg); /* Using the new variable for preview background */ -} - -/* Custom scrollbar */ -.editor-pane::-webkit-scrollbar, -.preview-pane::-webkit-scrollbar, -#markdown-editor::-webkit-scrollbar { - width: 8px; - height: 8px; -} - -.editor-pane::-webkit-scrollbar-track, -.preview-pane::-webkit-scrollbar-track, -#markdown-editor::-webkit-scrollbar-track { - background: var(--scrollbar-track); -} - -.editor-pane::-webkit-scrollbar-thumb, -.preview-pane::-webkit-scrollbar-thumb, -#markdown-editor::-webkit-scrollbar-thumb { - background: var(--scrollbar-thumb); - border-radius: 4px; -} - -.editor-pane::-webkit-scrollbar-thumb:hover, -.preview-pane::-webkit-scrollbar-thumb:hover, -#markdown-editor::-webkit-scrollbar-thumb:hover { - background: var(--button-active); -} - -#markdown-editor { - width: 100%; - height: 100%; - border: none; - background-color: transparent; - color: var(--text-color); - resize: none; - font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; - font-size: 14px; - line-height: 1.5; - padding: 10px; - padding-left: calc(10px + var(--line-number-gutter)); - transition: background-color 0.3s ease, color 0.3s ease; - overflow-y: auto; - position: relative; - z-index: 3; -} - -#markdown-editor:focus { - outline: none; -} - -.preview-pane { - padding: 20px; -} - -.markdown-body { - padding: 20px; - width: 100%; - background-color: var(--preview-bg); /* Ensuring the markdown content matches preview background */ - color: var(--preview-text-color); /* Using specific text color for preview content */ -} - -.markdown-body a.reference-link { - font-size: 0.75em; - letter-spacing: -0.02em; - line-height: 1; - vertical-align: super; - position: relative; - top: 0.08em; -} - -/* Style tables in light mode */ -.markdown-body table { - background-color: var(--table-bg); - border-color: var(--border-color); -} - -.markdown-body table tr { - background-color: var(--table-bg); - border-top: 1px solid var(--border-color); -} - -.markdown-body table tr:nth-child(2n) { - background-color: var(--bg-color); -} - -/* Style code blocks in light mode */ -.markdown-body pre { - background-color: var(--code-bg); - border-radius: 6px; -} - -.markdown-body code { - background-color: var(--code-bg); - border-radius: 3px; - padding: 0.2em 0.4em; -} - -.markdown-body img.emoji-inline { - width: 1em; - height: 1em; - vertical-align: -0.1em; -} - -.markdown-body ul, -.markdown-body ol { - padding-left: 2em; - margin: 0.4em 0; -} - -.markdown-body ul ul, -.markdown-body ul ol, -.markdown-body ol ul, -.markdown-body ol ol { - margin-top: 0.2em; - margin-bottom: 0.2em; -} - -.markdown-body ul.contains-task-list, -.markdown-body li.task-list-item { - list-style: none; -} - -.markdown-body ul.contains-task-list { - padding-left: 2em; -} - -.markdown-body li.task-list-item input[type="checkbox"] { - margin: 0 0.5em 0.2em 0; - vertical-align: middle; - pointer-events: none; -} - -.markdown-body li.task-list-item::marker { - content: ""; -} - -.markdown-body li:has(> input[type="checkbox"]) { - list-style: none; -} - -.markdown-body li:has(> input[type="checkbox"])::marker { - content: ""; -} - -.markdown-body ul:has(> li > input[type="checkbox"]) { - list-style: none; - padding-left: 2em; -} - -.markdown-body .footnotes { - margin-top: 1.5rem; - font-size: 0.9em; -} - -.markdown-body .footnotes ol { - padding-left: 1.5em; -} - -.markdown-body .footnotes ol > li::marker { - content: "[" counter(list-item) "] "; - font-weight: 600; -} - -.markdown-body .footnotes li > p { - margin: 0.2em 0; -} - -.markdown-body .footnote-ref a, -.markdown-body .footnote-backref { - text-decoration: none; -} - -.markdown-body .footnote-backref { - margin-left: 0.4em; -} - -.markdown-body .markdown-alert { - padding: 0.5rem 1rem; - margin-bottom: 16px; - border-left: 0.25em solid; - border-radius: 0.375rem; -} - -.markdown-body .markdown-alert > :last-child { - margin-bottom: 0; -} - -.markdown-body .markdown-alert-title { - margin: 0 0 8px; - font-weight: 600; - line-height: 1.25; - display: flex; - align-items: center; - gap: 8px; -} - -.markdown-body .markdown-alert-icon { - display: inline-flex; - width: 16px; - height: 16px; -} - -.markdown-body .markdown-alert-icon svg { - width: 16px; - height: 16px; - fill: currentColor; -} - -.markdown-body .markdown-alert-note { - color: #0969da; - border-left-color: #0969da; - background-color: #ddf4ff; -} - -.markdown-body .markdown-alert-tip { - color: #1a7f37; - border-left-color: #1a7f37; - background-color: #dafbe1; -} - -.markdown-body .markdown-alert-important { - color: #8250df; - border-left-color: #8250df; - background-color: #fbefff; -} - -.markdown-body .markdown-alert-warning { - color: #9a6700; - border-left-color: #9a6700; - background-color: #fff8c5; -} - -.markdown-body .markdown-alert-caution { - color: #cf222e; - border-left-color: #cf222e; - background-color: #ffebe9; -} - -.markdown-body .markdown-alert > *:not(.markdown-alert-title) { - color: var(--preview-text-color); -} - -[data-theme="dark"] .markdown-body .markdown-alert-note { - color: #4493f8; - background-color: rgba(31, 111, 235, 0.15); - border-left-color: #4493f8; -} - -[data-theme="dark"] .markdown-body .markdown-alert-tip { - color: #3fb950; - background-color: rgba(35, 134, 54, 0.15); - border-left-color: #3fb950; -} - -[data-theme="dark"] .markdown-body .markdown-alert-important { - color: #ab7df8; - background-color: rgba(137, 87, 229, 0.15); - border-left-color: #ab7df8; -} - -[data-theme="dark"] .markdown-body .markdown-alert-warning { - color: #d29922; - background-color: rgba(210, 153, 34, 0.18); - border-left-color: #d29922; -} - -[data-theme="dark"] .markdown-body .markdown-alert-caution { - color: #f85149; - background-color: rgba(248, 81, 73, 0.18); - border-left-color: #f85149; -} - -.toolbar { - display: flex; - gap: 8px; - align-items: center; -} - -.toolbar-group { - display: inline-flex; - align-items: center; - gap: 6px; -} - -.toolbar-divider { - width: 1px; - height: 20px; - background-color: var(--border-color); - opacity: 0.7; -} - -.tool-button { - background-color: var(--button-bg); - border: 1px solid var(--border-color); - color: var(--text-color); - border-radius: 5px; - padding: 4px 8px; - font-size: 13px; - cursor: pointer; - display: inline-flex; - align-items: center; - justify-content: center; - gap: 4px; - /* PERF-016: Specific transition properties instead of 'all' to avoid animating layout-triggering properties */ - transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease; -} - -.tool-button:hover { - background-color: var(--button-hover); -} - -.tool-button:active { - background-color: var(--button-active); -} - -.tool-button:disabled, -.tool-button[aria-disabled="true"] { - cursor: not-allowed; - opacity: 0.5; -} - -.tool-button i { - font-size: 15px; -} - -.tool-button.is-active, -.tool-button.is-active:hover { - border-color: var(--accent-color); - color: var(--accent-color); - background-color: rgba(3, 102, 214, 0.08); -} - -.btn-text { - display: none; -} - -.toolbar .tool-button { - height: 28px; - min-width: 28px; -} - -.toolbar .tool-button.sync-active { - border-color: var(--accent-color); - color: var(--accent-color); -} - -.file-input { - display: none; -} - -/* Drag overlay: full-screen drop target shown when user drags a file over the window */ -.drag-overlay { - display: none; - position: fixed; - inset: 0; - z-index: 9999; - background-color: rgba(0, 0, 0, 0.45); - pointer-events: none; - align-items: center; - justify-content: center; -} - -.drag-overlay.active { - display: flex; - pointer-events: auto; -} - -.drag-overlay-inner { - border: 3px dashed var(--accent-color); - border-radius: 12px; - padding: 48px 64px; - text-align: center; - color: #ffffff; - background-color: rgba(3, 102, 214, 0.15); - animation: overlayPulse 1.4s ease-in-out infinite; -} - -.drag-overlay-icon { - display: block; - font-size: 3rem; - margin-bottom: 12px; - color: var(--accent-color); -} - -.drag-overlay-text { - font-size: 1.4rem; - font-weight: 600; - margin-bottom: 4px; -} - -.drag-overlay-sub { - font-size: 0.85rem; - opacity: 0.75; - margin-bottom: 0; -} - -@keyframes overlayPulse { - 0%, 100% { transform: scale(1); } - 50% { transform: scale(1.015); } -} - -/* Editor drop hint: subtle text at bottom of editor pane, shown only when empty */ -.drop-hint { - position: absolute; - bottom: 14px; - left: 0; - right: 0; - text-align: center; - font-size: 0.75rem; - color: var(--text-color); - opacity: 0.35; - pointer-events: none; - user-select: none; - z-index: 3; -} - -.editor-pane:has(#markdown-editor:not(:placeholder-shown)) .drop-hint { - display: none; -} - -.line-numbers { - position: absolute; - top: 20px; - bottom: 20px; - left: 20px; - width: var(--line-number-gutter); - padding: 10px 8px 10px 0; - font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; - font-size: 14px; - line-height: 1.5; - text-align: right; - color: var(--text-secondary); - background-color: var(--editor-bg); - border-right: 1px solid var(--border-color); - box-sizing: border-box; - overflow: hidden; - pointer-events: none; - user-select: none; - z-index: 2; - font-variant-numeric: tabular-nums; -} - -.line-numbers .line-number { - display: block; - height: auto; -} - -.editor-highlight-layer { - position: absolute; - inset: 20px 0 20px calc(20px + var(--line-number-gutter)); - padding: 10px; - font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; - font-size: 14px; - line-height: 1.5; - white-space: pre-wrap; - word-wrap: break-word; - color: transparent; - pointer-events: none; - overflow: auto; - background-color: var(--editor-bg); - border-radius: 4px; - z-index: 1; -} - -.editor-highlight-layer::-webkit-scrollbar { - width: 8px; - height: 8px; -} - -.editor-highlight-layer::-webkit-scrollbar-thumb { - background: transparent; -} - -.editor-highlight-layer::-webkit-scrollbar-track { - background: transparent; -} - -.find-highlight { - background-color: var(--fr-match-highlight, rgba(255, 223, 93, 0.4)) !important; - border-radius: 2px; - color: transparent !important; - padding: 0 !important; - margin: 0 !important; -} - -.find-highlight.active { - background-color: var(--fr-match-active, #ff9b30) !important; - color: transparent !important; - padding: 0 !important; - margin: 0 !important; - outline: 1px solid var(--accent-color, #0366d6) !important; - outline-offset: -1px; -} - -.preview-find-highlight { - background-color: var(--fr-match-highlight, rgba(255, 223, 93, 0.4)) !important; - color: var(--fr-match-text-color, inherit) !important; - border-radius: 2px; - padding: 0 1px !important; - margin: 0 !important; -} - -.preview-find-highlight.active { - background-color: var(--fr-match-active, #ff9b30) !important; - color: var(--fr-match-active-text-color, inherit) !important; - outline: 1px solid var(--accent-color, #0366d6) !important; - outline-offset: -1px; -} - -/* Dropdown improvements */ -.dropdown-menu { - background-color: var(--bg-color); - border-color: var(--border-color); -} - -.dropdown-item { - color: var(--text-color); -} - -.dropdown-item:hover, .dropdown-item:focus { - background-color: var(--button-hover); - color: var(--text-color); -} - -/* Markdown formatting toolbar */ -.markdown-format-toolbar { - display: flex; - align-items: center; - height: 34px; - padding: 0 6px; - background-color: var(--header-bg); - border-bottom: 1px solid var(--border-color); - overflow-x: auto; - overflow-y: hidden; - flex-shrink: 0; - scrollbar-width: none; - -ms-overflow-style: none; -} - -.markdown-format-toolbar::-webkit-scrollbar { - display: none; -} - -.markdown-toolbar-group { - display: flex; - align-items: center; - gap: 2px; - height: 100%; - padding: 0 6px; - border-right: 1px solid var(--border-color); - flex-shrink: 0; -} - -.markdown-toolbar-group:first-child { - padding-left: 0; -} - -.markdown-toolbar-group:last-child { - border-right: none; - padding-right: 0; -} - -.markdown-tool-btn { - display: inline-flex; - align-items: center; - justify-content: center; - width: 26px; - height: 26px; - border: 1px solid transparent; - border-radius: 4px; - background: transparent; - color: var(--text-color); - cursor: pointer; - font-size: 14px; - line-height: 1; - padding: 0; - transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease; -} - -.markdown-tool-btn:hover, -.markdown-tool-btn:focus-visible { - background-color: var(--button-hover); - border-color: var(--border-color); - color: var(--accent-color); -} - -.markdown-tool-btn:active { - background-color: var(--button-active); -} - -.markdown-tool-btn:disabled, -.markdown-tool-btn.disabled { - opacity: 0.4; - cursor: not-allowed; - pointer-events: none; -} - -.markdown-tool-btn i { - font-size: 15px; -} - -.markdown-tool-btn[data-md-action="reference"] i::before { - content: "[ ]"; - font-style: normal; - font-size: 12px; - letter-spacing: -0.12em; -} - -.markdown-tool-btn.text-tool { - width: auto; - min-width: 26px; - padding: 0 5px; - font-weight: 600; - font-family: Georgia, "Times New Roman", serif; -} - -.heading-group .markdown-tool-btn { - min-width: 30px; -} - - - -/* Loading indicators */ -.loading { - opacity: 0.6; - pointer-events: none; -} - -/* Focus outline for accessibility */ -button:focus, -a:focus { - outline: 2px solid var(--accent-color); - outline-offset: 2px; -} - -/* Animation for copied message */ -@keyframes fadeIn { - from { opacity: 0; } - to { opacity: 1; } -} - -/* Tooltip styles */ -.tooltip { - position: absolute; - background: var(--button-bg); - border: 1px solid var(--border-color); - padding: 5px 8px; - border-radius: 4px; - font-size: 12px; - z-index: 1000; - animation: fadeIn 0.2s ease; -} - -/* Styles for GitHub markdown preview light mode */ -.markdown-body { - color-scheme: light; - --color-prettylights-syntax-comment: #6a737d; - --color-prettylights-syntax-constant: #005cc5; - --color-prettylights-syntax-entity: #6f42c1; - --color-prettylights-syntax-storage-modifier-import: #24292e; - --color-prettylights-syntax-entity-tag: #22863a; - --color-prettylights-syntax-keyword: #cf222e; - --color-prettylights-syntax-string: #032f62; - --color-prettylights-syntax-variable: #e36209; - --color-prettylights-syntax-brackethighlighter-unmatched: #b31d28; - --color-prettylights-syntax-invalid-illegal-text: #fafbfc; - --color-prettylights-syntax-invalid-illegal-bg: #b31d28; - --color-prettylights-syntax-carriage-return-text: #fafbfc; - --color-prettylights-syntax-carriage-return-bg: #d73a49; - --color-prettylights-syntax-string-regexp: #22863a; - --color-prettylights-syntax-markup-list: #735c0f; - --color-prettylights-syntax-markup-heading: #005cc5; - --color-prettylights-syntax-markup-italic: #24292e; - --color-prettylights-syntax-markup-bold: #24292e; - --color-prettylights-syntax-markup-deleted-text: #b31d28; - --color-prettylights-syntax-markup-deleted-bg: #ffeef0; - --color-prettylights-syntax-markup-inserted-text: #22863a; - --color-prettylights-syntax-markup-inserted-bg: #f0fff4; - --color-prettylights-syntax-markup-changed-text: #e36209; - --color-prettylights-syntax-markup-changed-bg: #ffebda; - --color-prettylights-syntax-markup-ignored-text: #f6f8fa; - --color-prettylights-syntax-markup-ignored-bg: #005cc5; - --color-prettylights-syntax-meta-diff-range: #6f42c1; - --color-prettylights-syntax-brackethighlighter-angle: #586069; - --color-prettylights-syntax-sublimelinter-gutter-mark: #e1e4e8; - --color-prettylights-syntax-constant-other-reference-link: #032f62; - --color-fg-default: #24292e; - --color-fg-muted: #586069; - --color-fg-subtle: #6a737d; - --color-canvas-default: #ffffff; - --color-canvas-subtle: #f6f8fa; - --color-border-default: #e1e4e8; - --color-border-muted: #eaecef; - --color-neutral-muted: rgba(175,184,193,0.2); - --color-accent-fg: #0366d6; - --color-accent-emphasis: #0366d6; - --color-attention-subtle: #fff5b1; - --color-danger-fg: #d73a49; -} - -/* Styles for GitHub markdown preview dark mode */ -[data-theme="dark"] .markdown-body { - color-scheme: dark; - --color-prettylights-syntax-comment: #8b949e; - --color-prettylights-syntax-constant: #79c0ff; - --color-prettylights-syntax-entity: #d2a8ff; - --color-prettylights-syntax-storage-modifier-import: #c9d1d9; - --color-prettylights-syntax-entity-tag: #7ee787; - --color-prettylights-syntax-keyword: #ff7b72; - --color-prettylights-syntax-string: #a5d6ff; - --color-prettylights-syntax-variable: #ffa657; - --color-prettylights-syntax-brackethighlighter-unmatched: #f85149; - --color-prettylights-syntax-invalid-illegal-text: #f0f6fc; - --color-prettylights-syntax-invalid-illegal-bg: #8e1519; - --color-prettylights-syntax-carriage-return-text: #f0f6fc; - --color-prettylights-syntax-carriage-return-bg: #b62324; - --color-prettylights-syntax-string-regexp: #7ee787; - --color-prettylights-syntax-markup-list: #f2cc60; - --color-prettylights-syntax-markup-heading: #1f6feb; - --color-prettylights-syntax-markup-italic: #c9d1d9; - --color-prettylights-syntax-markup-bold: #c9d1d9; - --color-prettylights-syntax-markup-deleted-text: #ffdcd7; - --color-prettylights-syntax-markup-deleted-bg: #67060c; - --color-prettylights-syntax-markup-inserted-text: #aff5b4; - --color-prettylights-syntax-markup-inserted-bg: #033a16; - --color-prettylights-syntax-markup-changed-text: #ffdfb6; - --color-prettylights-syntax-markup-changed-bg: #5a1e02; - --color-prettylights-syntax-markup-ignored-text: #c9d1d9; - --color-prettylights-syntax-markup-ignored-bg: #1158c7; - --color-prettylights-syntax-meta-diff-range: #d2a8ff; - --color-prettylights-syntax-brackethighlighter-angle: #8b949e; - --color-prettylights-syntax-sublimelinter-gutter-mark: #484f58; - --color-prettylights-syntax-constant-other-reference-link: #a5d6ff; - --color-fg-default: #c9d1d9; - --color-fg-muted: #8b949e; - --color-fg-subtle: #484f58; - --color-canvas-default: #0d1117; - --color-canvas-subtle: #161b22; - --color-border-default: #30363d; - --color-border-muted: #21262d; - --color-neutral-muted: rgba(110,118,129,0.4); - --color-accent-fg: #58a6ff; - --color-accent-emphasis: #1f6feb; - --color-attention-subtle: rgba(187,128,9,0.15); - --color-danger-fg: #f85149; -} - -/* Override specific styles for dark mode tables and code */ -[data-theme="dark"] .markdown-body table tr { - background-color: var(--table-bg); -} - -[data-theme="dark"] .markdown-body table tr:nth-child(2n) { - background-color: #1c2128; /* Slightly lighter than base dark background */ -} - -[data-theme="dark"] .markdown-body pre { - background-color: var(--code-bg); -} - -[data-theme="dark"] .markdown-body code { - background-color: var(--code-bg); -} - -/* Syntax Highlighting Mapping to GitHub Variables */ -.hljs { - color: var(--color-fg-default); -} -.hljs-doctag, -.hljs-keyword, -.hljs-meta .hljs-keyword, -.hljs-template-tag, -.hljs-template-variable, -.hljs-type, -.hljs-variable.language_ { - color: var(--color-prettylights-syntax-keyword); -} -.hljs-title, -.hljs-title.class_, -.hljs-title.class_.inherited__, -.hljs-title.function_ { - color: var(--color-prettylights-syntax-entity); -} -.hljs-attr, -.hljs-attribute, -.hljs-literal, -.hljs-meta, -.hljs-number, -.hljs-operator, -.hljs-variable, -.hljs-selector-attr, -.hljs-selector-class, -.hljs-selector-id { - color: var(--color-prettylights-syntax-constant); -} -.hljs-regexp, -.hljs-string, -.hljs-meta .hljs-string { - color: var(--color-prettylights-syntax-string); -} -.hljs-built_in, -.hljs-symbol { - color: var(--color-prettylights-syntax-variable); -} -.hljs-comment, -.hljs-code, -.hljs-formula { - color: var(--color-prettylights-syntax-comment); -} -.hljs-name, -.hljs-quote, -.hljs-selector-tag, -.hljs-selector-pseudo { - color: var(--color-prettylights-syntax-entity-tag); -} -.hljs-subst { - color: var(--color-fg-default); -} -.hljs-section { - color: var(--color-prettylights-syntax-markup-heading); - font-weight: bold; -} -.hljs-bullet { - color: var(--color-prettylights-syntax-constant); -} -.hljs-emphasis { - color: var(--color-fg-default); - font-style: italic; -} -.hljs-strong { - color: var(--color-fg-default); - font-weight: bold; -} -.hljs-addition { - color: var(--color-prettylights-syntax-markup-inserted-text); - background-color: var(--color-prettylights-syntax-markup-inserted-bg); -} -.hljs-deletion { - color: var(--color-prettylights-syntax-markup-deleted-text); - background-color: var(--color-prettylights-syntax-markup-deleted-bg); -} - -.stats-container { - font-size: 0.8rem; - color: var(--text-color); -} - -.stat-item { - align-items: center; -} - -.stat-item i { - font-size: 0.9rem; - opacity: 0.8; -} - -#importDropdown, -#exportDropdown, -#languageDropdown { - font-size: 0.8rem; -} - -#importDropdown i, -#exportDropdown i, -#languageDropdown i { - font-size: 0.9rem; -} - -/* Ensure desktop dropdown menu options match the stats-container font size */ -[aria-labelledby="importDropdown"] .dropdown-item, -[aria-labelledby="exportDropdown"] .dropdown-item, -[aria-labelledby="languageDropdown"] .dropdown-item { - font-size: 0.8rem; -} - -/* Ensure mobile menu import, export, and language dropdown triggers/options match the mobile stats-container font size */ -#mobile-import-button, -#mobile-import-github-button, -#mobile-export-md, -#mobile-export-html, -#mobile-export-pdf, -#mobileLanguageDropdown { - font-size: 0.9rem !important; -} - -[aria-labelledby="mobileLanguageDropdown"] .dropdown-item { - font-size: 0.9rem; -} - -.editor-pane { - overflow: hidden; -} - -/* Mobile Menu Styles */ -.mobile-menu { - display: none; - position: relative; - z-index: 1001; -} - - - -/* slide‑in panel */ -.mobile-menu-panel { - position: fixed; - top: 0; - right: -300px; - width: 280px; - height: 100vh; - background-color: var(--bg-color); - box-shadow: -2px 0 10px rgba(0, 0, 0, 0.2); - transition: right 0.3s ease; - overflow-y: auto; - padding: 1rem; - display: flex; - flex-direction: column; - z-index: 1002; -} - -.mobile-menu-panel.active { - right: 0; -} - -/* translucent overlay behind panel */ -.mobile-menu-overlay { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100vh; - background-color: rgba(0, 0, 0, 0.5); - opacity: 0; - visibility: hidden; - pointer-events: none; - transition: opacity 0.3s ease, visibility 0.3s ease; - z-index: 1000; -} - -.mobile-menu-overlay.active { - opacity: 1; - visibility: visible; - pointer-events: auto; -} - -/* header inside mobile menu */ -.mobile-menu-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 1rem; -} - -.mobile-menu-header h5 { - margin: 0; - font-size: 1.25rem; - color: var(--text-color); -} - -/* stats section in mobile menu */ -.mobile-stats-container { - border-bottom: 1px solid var(--border-color); - padding-bottom: 0.75rem; - margin-bottom: 1rem; -} - -.mobile-stats-container .stat-item { - font-size: 0.9rem; - color: var(--text-color); - display: flex; - align-items: center; -} - -.mobile-stats-container .stat-item i { - margin-right: 0.5em; - opacity: 0.8; -} - -/* menu buttons list */ -.mobile-menu-items { - display: flex; - flex-direction: column; - gap: 0.5rem; - flex-grow: 1; -} - -/* each menu item */ -.mobile-menu-item { - background-color: var(--button-bg); - border: 1px solid var(--border-color); - color: var(--text-color); - border-radius: 6px; - padding: 0.6rem 1rem; - font-size: 1rem; - text-align: left; - display: flex; - align-items: center; - gap: 0.5rem; - transition: background-color 0.2s ease; - cursor: pointer; -} - -.mobile-menu-item:hover { - background-color: var(--button-hover); -} - -.mobile-menu-item:active { - background-color: var(--button-active); -} - -/* close button override */ -#close-mobile-menu.tool-button { - padding: 0.25rem 0.5rem; - font-size: 1rem; -} - -/* Mobile document tabs section */ -.mobile-tabs-section { - border-bottom: 1px solid var(--border-color); - padding-bottom: 0.75rem; -} - -.mobile-tabs-header { - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: 0.5rem; -} - -.mobile-tabs-label { - font-size: 0.85rem; - font-weight: 600; - color: var(--text-color); - opacity: 0.8; - text-transform: uppercase; - letter-spacing: 0.04em; -} - -.mobile-new-tab-btn { - background: none; - border: 1px solid var(--border-color); - border-radius: 4px; - color: var(--text-color); - padding: 2px 7px; - font-size: 0.9rem; - cursor: pointer; - display: flex; - align-items: center; - transition: background-color 0.15s ease; -} - -.mobile-new-tab-btn:hover { - background-color: var(--button-hover); -} - -.mobile-tab-list { - display: flex; - flex-direction: column; - gap: 4px; - max-height: 180px; - overflow-y: auto; -} - -.mobile-tab-item { - display: flex; - align-items: center; - justify-content: space-between; - background-color: var(--button-bg); - border: 1px solid var(--border-color); - border-radius: 6px; - padding: 0.45rem 0.75rem; - font-size: 0.9rem; - color: var(--text-color); - cursor: pointer; - transition: background-color 0.15s ease; - gap: 0.5rem; -} - -.mobile-tab-item:hover { - background-color: var(--button-hover); -} - -.mobile-tab-item.active { - border-color: var(--accent-color); - color: var(--accent-color); - background-color: var(--bg-color); -} - -.mobile-tab-title { - flex: 1; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - min-width: 0; -} - -.mobile-tab-item .tab-menu-btn { - opacity: 0.6; -} - -.mobile-tab-item:hover .tab-menu-btn, -.mobile-tab-item.active .tab-menu-btn { - opacity: 0.8; -} - -#mobile-tab-reset-btn { - margin-left: 0; - height: auto; - padding: 0.45rem 0.75rem; - justify-content: center; - font-size: 0.9rem; -} - -/* ========================================== - NAVBAR RESPONSIVE BREAKPOINTS - >= 1080px : full desktop navbar - < 1080px : mobile hamburger + stacked panes - ========================================== */ - -/* Mobile / tablet (< 1080px): switch to hamburger, stack panes */ -@media (max-width: 1079px) { - /* Override Bootstrap d-md-flex / d-md-none so the breakpoint is 1080px */ - .stats-container, - .toolbar { - display: none !important; - } - - /* Expand touch target sizes to meet WCAG mobile guidelines */ - .markdown-tool-btn { - width: 36px !important; - height: 36px !important; - font-size: 16px !important; - } - .markdown-format-toolbar { - height: 44px !important; - } - .tab-close-btn { - width: 28px !important; - height: 28px !important; - font-size: 14px !important; - } - .tab-menu-btn { - width: 28px !important; - height: 28px !important; - font-size: 14px !important; - } - - .mobile-menu { - display: block !important; - } - - /* Stack editor and preview vertically */ - .content-container { - flex-direction: column; - } - - .editor-pane, - .preview-pane { - flex: none; - height: 50%; - border-right: none; - } - - .editor-pane { - border-bottom: 1px solid var(--border-color); - } - - /* Hide drag-resize divider (touch devices don't use it) */ - .resize-divider { - display: none; - } - - /* Single-pane view modes: occupy full height */ - .content-container.view-editor-only .editor-pane, - .content-container.view-preview-only .preview-pane { - height: 100%; - } - - .content-container.view-split .editor-pane, - .content-container.view-split .preview-pane { - height: 50%; - } -} - -.github-link { - color: var(--text-color); - text-decoration: none; - display: flex; - align-items: center; - justify-content: center; - transition: transform 0.2s ease, color 0.2s ease; - margin-right: 2rem; -} - -.github-link:hover { - color: var(--accent-color); - transform: scale(1.1); -} - -.github-link i { - font-size: 1.25rem; -} - -/* ======================================== - HEADER LAYOUT - ======================================== */ -.header-container { - position: relative; - min-height: 30px; -} - -.app-header h1 { - font-size: 1.05rem; - line-height: 1.1; -} - -.header-left { - flex: 1 0 auto; - justify-content: flex-start; - white-space: nowrap; -} - -.header-right { - flex: 1 0 auto; - justify-content: flex-end; - white-space: nowrap; -} - -/* Pane View States */ -.content-container.view-editor-only .preview-pane { - display: none; -} - -.content-container.view-editor-only .editor-pane { - flex: 1; - border-right: none; -} - -.content-container.view-preview-only .editor-pane { - display: none; -} - -.content-container.view-preview-only .preview-pane { - flex: 1; -} - -.content-container.view-split .editor-pane, -.content-container.view-split .preview-pane { - flex: 1; -} - -/* Compact desktop (< 1280px): compact toolbar */ -@media (max-width: 1280px) { - /* Compact toolbar at medium widths */ - .toolbar { - gap: 4px; - } -} - - - -/* ======================================== - RESIZE DIVIDER - Story 1.3 - ======================================== */ - -.resize-divider { - width: 8px; - background-color: transparent; - cursor: col-resize; - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - position: relative; - z-index: 10; - transition: background-color 0.2s ease; -} - -.resize-divider:hover { - background-color: var(--button-hover); -} - -.resize-divider.dragging { - background-color: var(--accent-color); -} - -.resize-divider-handle { - width: 2px; - height: 40px; - background-color: var(--border-color); - border-radius: 2px; - transition: background-color 0.2s ease, width 0.2s ease; -} - -.resize-divider:hover .resize-divider-handle, -.resize-divider.dragging .resize-divider-handle { - background-color: var(--accent-color); - width: 3px; -} - -/* Hide divider in single-pane modes */ -.content-container.view-editor-only .resize-divider, -.content-container.view-preview-only .resize-divider { - display: none; -} - - - -/* Prevent text selection during drag */ -.resizing { - user-select: none; - cursor: col-resize !important; -} - -.resizing * { - cursor: col-resize !important; -} - -.resizing #markdown-preview, -.resizing #markdown-editor, -.resizing .line-numbers { - pointer-events: none !important; -} - -/* ======================================== - MOBILE VIEW MODE CONTROLS - Story 1.4 - ======================================== */ - -.mobile-view-mode-group { - display: flex; - gap: 0; - border-bottom: 1px solid var(--border-color); - padding-bottom: 0.75rem; -} - -.mobile-view-mode-btn { - flex: 1; - background-color: var(--button-bg); - border: 1px solid var(--border-color); - color: var(--text-color); - padding: 8px 12px; - font-size: 14px; - cursor: pointer; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 4px; - transition: all 0.2s ease; -} - -.mobile-view-mode-btn:first-child { - border-radius: 6px 0 0 6px; -} - -.mobile-view-mode-btn:last-child { - border-radius: 0 6px 6px 0; -} - -.mobile-view-mode-btn:not(:last-child) { - border-right: none; -} - -.mobile-view-mode-btn:hover, -.mobile-view-mode-btn:active { - background-color: var(--button-hover); -} - -.mobile-view-mode-btn.active { - background-color: var(--button-bg); - border-color: var(--accent-color); - color: var(--accent-color); - border-width: 2px; - padding: 7px 11px; -} - -.mobile-view-mode-btn.active:not(:last-child) { - border-right: 2px solid var(--accent-color); -} - -.mobile-view-mode-btn i { - font-size: 18px; -} - -.mobile-view-mode-btn span { - font-size: 12px; -} - -/* ======================================== - RESPONSIVE VIEW MODE FIXES - Story 1.5 - ======================================== */ - - - -/* ======================================== - PDF EXPORT TABLE FIX - Rowspan/Colspan - ======================================== */ - -/* Fix for html2canvas not properly rendering rowspan/colspan cells. - Apply backgrounds to cells instead of rows to prevent row backgrounds - from painting over rowspan cells during canvas capture. */ -.pdf-export table tr { - background-color: transparent !important; -} - -.pdf-export table th, -.pdf-export table td { - background-color: var(--table-bg, #ffffff); - position: relative; -} - -.pdf-export table tr:nth-child(2n) th, -.pdf-export table tr:nth-child(2n) td { - background-color: var(--bg-color, #f6f8fa); -} - -/* Ensure rowspan cells render correctly */ -.pdf-export table th[rowspan], -.pdf-export table td[rowspan] { - vertical-align: middle; - background-color: var(--table-bg, #ffffff) !important; -} - -/* Ensure colspan cells render correctly */ -.pdf-export table th[colspan], -.pdf-export table td[colspan] { - text-align: center; -} - -/* Dark mode PDF export table fix */ -[data-theme="dark"] .pdf-export table th, -[data-theme="dark"] .pdf-export table td { - background-color: var(--table-bg, #161b22); -} - -[data-theme="dark"] .pdf-export table tr:nth-child(2n) th, -[data-theme="dark"] .pdf-export table tr:nth-child(2n) td { - background-color: #1c2128; -} - -[data-theme="dark"] .pdf-export table th[rowspan], -[data-theme="dark"] .pdf-export table td[rowspan] { - background-color: var(--table-bg, #161b22) !important; -} - -/* ======================================== - MERMAID DIAGRAM TOOLBAR - ======================================== */ - -.mermaid-container { - position: relative; -} - -.mermaid-toolbar { - position: absolute; - top: 8px; - right: 8px; - display: flex; - gap: 4px; - opacity: 0; - transition: opacity 0.2s ease; - z-index: 10; -} - -.mermaid-container:hover .mermaid-toolbar { - opacity: 1; -} - -.mermaid-toolbar-btn { - background-color: var(--button-bg); - border: 1px solid var(--border-color); - color: var(--text-color); - border-radius: 4px; - padding: 4px 7px; - font-size: 13px; - cursor: pointer; - display: flex; - align-items: center; - gap: 3px; - transition: background-color 0.2s ease, color 0.2s ease; - white-space: nowrap; -} - -.mermaid-toolbar-btn:hover { - background-color: var(--button-hover); - color: var(--accent-color); -} - -.mermaid-toolbar-btn:active { - background-color: var(--button-active); -} - -.mermaid-toolbar-btn i { - font-size: 14px; -} - -/* ======================================== - MERMAID ZOOM MODAL - ======================================== */ - -#mermaid-zoom-modal { - display: none; - position: fixed; - inset: 0; - z-index: 2000; - background-color: rgba(0, 0, 0, 0.75); - align-items: center; - justify-content: center; -} - -#mermaid-zoom-modal.active { - display: flex; -} - -.mermaid-modal-content { - background-color: var(--bg-color); - border: 1px solid var(--border-color); - border-radius: 8px; - padding: 16px; - width: 85vw; - height: 85vh; - max-width: 85vw; - max-height: 85vh; - display: flex; - flex-direction: column; - gap: 12px; -} - -@media (max-width: 576px) { - .mermaid-modal-content { - width: 95vw; - height: 90vh; - max-width: 95vw; - max-height: 90vh; - padding: 10px; - } -} - -.mermaid-modal-header { - display: flex; - justify-content: space-between; - align-items: center; -} - -.mermaid-modal-header span { - font-weight: 600; - font-size: 15px; - color: var(--text-color); -} - -.mermaid-modal-close { - background: none; - border: none; - color: var(--text-color); - font-size: 1.2rem; - cursor: pointer; - padding: 2px 6px; - border-radius: 4px; - display: flex; - align-items: center; - transition: background-color 0.2s ease; -} - -.mermaid-modal-close:hover { - background-color: var(--button-hover); -} - -.mermaid-modal-diagram { - overflow: auto; - flex: 1; - display: flex; - align-items: center; - justify-content: center; - min-height: 200px; - cursor: grab; -} - -.mermaid-modal-diagram.dragging { - cursor: grabbing; -} - -.mermaid-modal-diagram svg { - transform-origin: center; - transition: transform 0.1s ease; - max-width: none; -} - -.mermaid-modal-controls { - display: flex; - justify-content: center; - gap: 8px; - flex-wrap: wrap; -} - -.mermaid-modal-controls .mermaid-toolbar-btn { - opacity: 1; -} - -/* ======================================== - DOCUMENT TABS & SESSION MANAGEMENT - ======================================== */ - -.tab-bar { - display: flex; - align-items: center; - background-color: var(--header-bg); - border-bottom: 1px solid var(--border-color); - height: 32px; - overflow: visible; /* ← was: overflow: hidden */ - flex-shrink: 0; - padding: 0 4px; - gap: 0; - user-select: none; - position: relative; - z-index: 10; -} - -.tab-list { - display: flex; - align-items: flex-end; - overflow-x: auto; - overflow-y: visible; /* ← was: overflow-y: hidden */ - flex: 1; - height: 100%; - scrollbar-width: none; - -ms-overflow-style: none; -} - -.tab-list::-webkit-scrollbar { - display: none; -} - -.tab-item { - display: flex; - align-items: center; - gap: 6px; - height: 32px; - padding: 0 8px 0 10px; - min-width: 100px; - max-width: 180px; - background-color: var(--button-bg); - border: 1px solid var(--border-color); - border-bottom: 1px solid transparent; - border-radius: 6px 6px 0 0; - cursor: pointer; - font-size: 13px; - color: var(--text-color); - white-space: nowrap; - /* overflow: hidden; <-- REMOVE THIS */ - position: relative; - transition: background-color 0.15s ease, color 0.15s ease; - flex-shrink: 0; - margin-right: 2px; - opacity: 0.7; -} - -.tab-item:hover { - background-color: var(--button-hover); - opacity: 0.9; -} - -.tab-item.active { - background-color: var(--bg-color); - border-color: var(--border-color); - color: var(--accent-color); - border-bottom: 1px solid var(--bg-color); - opacity: 1; - z-index: 2; -} - -.tab-item.unsaved::after { - content: ''; - display: inline-block; - width: 6px; - height: 6px; - background-color: var(--accent-color); - border-radius: 50%; - flex-shrink: 0; - margin-left: 2px; -} - -.tab-title { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - flex: 1; - min-width: 0; -} - -.tab-close-btn { - display: flex; - align-items: center; - justify-content: center; - width: 16px; - height: 16px; - border-radius: 3px; - background: none; - border: none; - color: var(--text-color); - cursor: pointer; - padding: 0; - font-size: 11px; - opacity: 0; - flex-shrink: 0; - transition: background-color 0.15s ease, opacity 0.15s ease; -} - -.tab-item:hover .tab-close-btn, -.tab-item.active .tab-close-btn { - opacity: 0.6; -} - -.tab-close-btn:hover { - background-color: var(--button-active); - opacity: 1 !important; - color: var(--color-danger-fg, #d73a49); -} - -.tab-new-btn { - display: flex; - align-items: center; - gap: 4px; - height: 24px; - padding: 0 8px; - border-radius: 5px; - background: none; - border: 1px solid var(--border-color); - color: var(--text-color); - cursor: pointer; - font-size: 12px; - flex-shrink: 0; - margin-left: 6px; - align-self: center; - transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease; -} - -.tab-new-btn:hover { - background-color: rgba(46, 160, 67, 0.1); - border-color: var(--accent-color, #2ea043); - color: var(--accent-color, #2ea043); -} - -.tab-new-btn:active { - background-color: rgba(46, 160, 67, 0.2); -} - -/* Drag-and-drop visual feedback */ -.tab-item.dragging { - opacity: 0.4; -} - -.tab-item.drag-over { - border-left: 2px solid var(--accent-color); -} - -/* Tab enter animation */ -@keyframes tabSlideIn { - from { opacity: 0; transform: translateY(4px); } - to { opacity: 0.7; transform: translateY(0); } -} - -.tab-item { - animation: tabSlideIn 0.12s ease forwards; -} - -.tab-item.active { - animation: none; -} - -/* Hide tab bar on very small screens — single-file use */ -@media (max-width: 480px) { - .tab-bar { - display: none; - } -} - -/* ======================================== - TAB OVERFLOW — Scroll Buttons & Fade Indicators - ======================================== */ - -.tab-scroll-btn { - display: none; - align-items: center; - justify-content: center; - width: 24px; - height: 24px; - border-radius: 4px; - background: none; - border: 1px solid transparent; - color: var(--text-color); - cursor: pointer; - font-size: 14px; - flex-shrink: 0; - padding: 0; - transition: background-color 0.15s ease, border-color 0.15s ease, opacity 0.15s ease; - z-index: 2; - opacity: 0.6; -} - -.tab-scroll-btn:hover { - background-color: var(--button-hover); - border-color: var(--border-color); - opacity: 1; -} - -.tab-scroll-btn:active { - background-color: var(--button-active); -} - -/* Show scroll buttons only when overflow exists */ -.tab-bar.has-overflow-left .tab-scroll-left, -.tab-bar.has-overflow-right .tab-scroll-right { - display: flex; -} - -/* Overflow fade indicators — subtle gradient at clipped edges */ -.tab-list::before, -.tab-list::after { - content: ''; - position: sticky; - top: 0; - bottom: 0; - width: 0; - flex-shrink: 0; - pointer-events: none; - z-index: 3; - transition: box-shadow 0.2s ease; -} - -.tab-list::before { - left: 0; -} - -.tab-list::after { - right: 0; -} - -.tab-bar.has-overflow-left .tab-list::before { - box-shadow: 8px 0 12px -4px rgba(0, 0, 0, 0.12); -} - -.tab-bar.has-overflow-right .tab-list::after { - box-shadow: -8px 0 12px -4px rgba(0, 0, 0, 0.12); -} - -[data-theme="dark"] .tab-bar.has-overflow-left .tab-list::before { - box-shadow: 8px 0 12px -4px rgba(0, 0, 0, 0.35); -} - -[data-theme="dark"] .tab-bar.has-overflow-right .tab-list::after { - box-shadow: -8px 0 12px -4px rgba(0, 0, 0, 0.35); -} - -/* ======================================== - THREE-DOT TAB MENU - ======================================== */ - -.tab-menu-btn { - display: flex; - align-items: center; - justify-content: center; - width: 22px; - height: 22px; - border-radius: 3px; - background: none; - border: none; - color: var(--text-color); - cursor: pointer; - padding: 0; - font-size: 14px; - font-weight: bold; - letter-spacing: 1px; - opacity: 0.65; - flex-shrink: 0; - transition: background-color 0.15s ease, opacity 0.15s ease; - position: relative; -} - -/* Touch Hitbox Expansion for Tab Menu Button */ -.tab-menu-btn::before { - content: ''; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - width: 48px; - height: 48px; -} - -/* Touch-optimized styling for coarser pointers (e.g., smartphones & tablets) */ -@media (pointer: coarse) { - .tab-bar { - height: 40px !important; - } - .tab-item { - height: 40px !important; - font-size: 14px !important; - padding: 0 10px 0 12px !important; - gap: 8px !important; - } - .tab-new-btn, - .tab-reset-btn { - height: 32px !important; - font-size: 14px !important; - padding: 0 12px !important; - } - .tab-scroll-btn { - width: 32px !important; - height: 32px !important; - font-size: 18px !important; - } - .tab-menu-btn { - width: 30px !important; - height: 30px !important; - font-size: 18px !important; - } - .tab-close-btn { - width: 20px !important; - height: 20px !important; - font-size: 13px !important; - opacity: 0.8 !important; - } -} - -.tab-item:hover .tab-menu-btn, -.tab-item.active .tab-menu-btn { - opacity: 0.65; -} - -.tab-menu-btn:hover { - background-color: var(--button-active); - opacity: 1 !important; -} - -.tab-menu-dropdown { - display: none; - position: fixed; - min-width: 130px; - background-color: var(--header-bg); - border: 1px solid var(--border-color); - border-radius: 6px; - box-shadow: 0 4px 12px rgba(0,0,0,0.15); - z-index: 99999; - overflow: hidden; - flex-direction: column; -} - -.tab-menu-dropdown.open { - display: flex; -} - -.tab-menu-item { - display: flex; - align-items: center; - gap: 7px; - padding: 7px 12px; - background: none; - border: none; - color: var(--text-color); - font-size: 12px; - cursor: pointer; - text-align: left; - transition: background-color 0.12s ease; - white-space: nowrap; -} - -.tab-menu-item:hover { - background-color: var(--button-hover); -} - -.tab-menu-item-danger { - color: var(--color-danger-fg, #d73a49); -} - -.tab-menu-item-danger:hover { - background-color: rgba(215, 58, 73, 0.1); -} - -/* ======================================== - RESET BUTTON - ======================================== */ - -.tab-reset-btn { - display: flex; - align-items: center; - gap: 4px; - height: 24px; - padding: 0 8px; - border-radius: 5px; - background: none; - border: 1px solid var(--border-color); - color: var(--text-color); - cursor: pointer; - font-size: 12px; - flex-shrink: 0; - margin-left: 6px; - transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease; -} - -.tab-reset-btn:hover { - background-color: rgba(215, 58, 73, 0.1); - border-color: var(--color-danger-fg, #d73a49); - color: var(--color-danger-fg, #d73a49); -} - -/* ======================================== - RESET & RENAME CONFIRMATION MODALS - ======================================== */ - -.reset-modal-overlay { - position: fixed; - inset: 0; - background: rgba(0, 0, 0, 0.45); - z-index: 2000; - display: flex; - align-items: center; - justify-content: center; -} - -.reset-modal-overlay.modal-overlay { - opacity: 0; - visibility: hidden; - transition: opacity 0.2s ease, visibility 0.2s ease; -} - -.reset-modal-overlay.modal-overlay.is-visible { - opacity: 1; - visibility: visible; -} - -.reset-modal-box { - background: var(--header-bg); - border: 1px solid var(--border-color); - border-radius: 10px; - padding: 24px 28px; - min-width: 280px; - max-width: 360px; - box-shadow: 0 8px 32px rgba(0,0,0,0.25); - display: flex; - flex-direction: column; - gap: 16px; -} - -.modal-box { - max-height: min(85vh, 760px); - opacity: 0; - transform: translateY(8px); - transition: transform 0.2s ease, opacity 0.2s ease; -} - -.reset-modal-overlay.modal-overlay.is-visible .modal-box { - opacity: 1; - transform: translateY(0); -} - -.modal-header { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; -} - -.modal-header .reset-modal-message { - text-align: left; - flex: 1; -} - -.modal-close-btn { - border: 1px solid var(--border-color); - background: var(--button-bg); - color: var(--text-color); - border-radius: 6px; - width: 28px; - height: 28px; - display: inline-flex; - align-items: center; - justify-content: center; - cursor: pointer; - transition: background-color 0.15s ease; -} - -.modal-close-btn:hover { - background-color: var(--button-hover); -} - -.modal-body { - display: flex; - flex-direction: column; - gap: 16px; - max-height: min(60vh, 520px); - overflow: auto; - padding-right: 4px; -} - -.modal-section { - display: flex; - flex-direction: column; - gap: 8px; -} - -.modal-section-title { - margin: 0; - font-size: 0.95rem; - font-weight: 600; -} - -.modal-list { - margin: 0; - padding-left: 1.1rem; - display: flex; - flex-direction: column; - gap: 6px; - font-size: 0.85rem; -} - -.modal-list a { - color: var(--accent-color); - text-decoration: none; -} - -.modal-list a:hover { - text-decoration: underline; -} - -.modal-subtext { - margin: 0; - font-size: 12px; - color: var(--text-secondary, #57606a); - line-height: 1.4; -} - -.find-replace-meta { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; -} - -.find-match-count { - font-size: 12px; - color: var(--text-secondary, #57606a); -} - -.find-replace-nav { - display: inline-flex; - gap: 6px; -} - -.find-nav-btn { - width: 28px; - height: 28px; - padding: 0; -} - -.about-header { - display: flex; - align-items: center; - gap: 16px; - flex-wrap: wrap; -} - -.about-logo { - width: 64px; - height: 64px; - border-radius: 12px; - border: 1px solid var(--border-color); - object-fit: cover; -} - -.about-details { - display: flex; - flex-direction: column; - gap: 6px; -} - -.about-title { - margin: 0; - font-size: 1.05rem; - font-weight: 600; -} - -.about-description { - margin: 0; - font-size: 0.85rem; - color: var(--text-secondary, #57606a); -} - -.about-meta { - margin: 0; - font-size: 0.78rem; - color: var(--text-secondary, #57606a); -} - -.modal-body kbd { - padding: 2px 6px; - border-radius: 4px; - background-color: var(--button-bg); - border: 1px solid var(--border-color); - font-size: 0.75rem; - font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; -} - -.reset-modal-box--wide { - width: min(92vw, 640px); - max-width: 640px; -} - -.reset-modal-message { - margin: 0; - font-size: 14px; - color: var(--text-color); - font-weight: 500; - text-align: center; -} - -.reset-modal-actions { - display: flex; - gap: 10px; - justify-content: flex-end; -} - -.reset-modal-btn { - padding: 6px 16px; - border-radius: 6px; - border: 1px solid var(--border-color); - background: var(--button-bg); - color: var(--text-color); - font-size: 13px; - cursor: pointer; - transition: background-color 0.15s ease; -} - -.reset-modal-btn:hover { - background-color: var(--button-hover); -} - -.reset-modal-confirm { - background-color: var(--color-danger-fg, #d73a49); - border-color: var(--color-danger-fg, #d73a49); - color: #fff; -} - -.reset-modal-confirm:hover { - background-color: #b02a37; - border-color: #b02a37; -} - +:root { + --bg-color: #ffffff; + --editor-bg: #f6f8fa; + --preview-bg: #ffffff; /* Preview background for light mode */ + --text-color: #24292e; + --text-secondary: #57606a; + --font-mono: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace; + --color-danger-fg: #d73a49; + --preview-text-color: #24292e; /* Text color for preview in light mode */ + --border-color: #e1e4e8; + --header-bg: #f6f8fa; + --button-bg: #f6f8fa; + --button-hover: #e1e4e8; + --button-active: #d1d5da; + --scrollbar-thumb: #c1c1c1; + --scrollbar-track: #f1f1f1; + --accent-color: #0366d6; + --table-bg: #ffffff; /* Table background for light mode */ + --code-bg: #f6f8fa; /* Code block background for light mode */ + --skeleton-bg: #e2e8f0; + --skeleton-glow: rgba(255, 255, 255, 0.65); + + /* Find & Replace Panel custom properties (PERF-010 consolidated) */ + --fr-bg: rgba(255, 255, 255, 0.95); + --fr-border: #d0d7de; + --fr-shadow: 0 8px 24px rgba(140, 149, 159, 0.2); + --fr-btn-active: #0969da; + --fr-btn-active-bg: #ddf4ff; + --fr-match-highlight: #ffdf5d; + --fr-match-active: #ff9b30; + --fr-match-text-color: #24292e; + --fr-match-active-text-color: #24292e; + --fr-error-bg: #ffebe9; + --fr-error-border: #ff8577; + --fr-text-danger: #cf222e; +} + +[data-theme="dark"] { + --bg-color: #0d1117; + --editor-bg: #161b22; + --preview-bg: #0d1117; /* Preview background for dark mode */ + --text-color: #c9d1d9; + --text-secondary: #8b949e; + --color-danger-fg: #f85149; + --preview-text-color: #c9d1d9; /* Text color for preview in dark mode */ + --border-color: #30363d; + --header-bg: #161b22; + --button-bg: #21262d; + --button-hover: #30363d; + --button-active: #3b434b; + --scrollbar-thumb: #484f58; + --scrollbar-track: #21262d; + --accent-color: #58a6ff; + --table-bg: #161b22; /* Table background for dark mode */ + --code-bg: #161b22; /* Code block background for dark mode */ + --skeleton-bg: #2d3139; + --skeleton-glow: rgba(255, 255, 255, 0.08); + + /* Find & Replace Panel custom properties for dark mode */ + --fr-bg: rgba(28, 33, 40, 0.98); + --fr-border: #444c56; + --fr-shadow: 0 8px 24px rgba(0, 0, 0, 0.5); + --fr-btn-active: #2f81f7; + --fr-btn-active-bg: rgba(56, 139, 253, 0.15); + --fr-match-highlight: rgba(187, 128, 9, 0.4); + --fr-match-active: #ad6200; + --fr-match-text-color: #c9d1d9; + --fr-match-active-text-color: #ffffff; + --fr-error-bg: rgba(248, 81, 73, 0.1); + --fr-error-border: rgba(248, 81, 73, 0.4); + --fr-text-danger: #ff7b72; +} + +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +@media (min-width: 768px) { + html, + body { + height: 100%; + overflow: hidden; + } +} + +body { + background-color: var(--bg-color); + color: var(--text-color); + /* PERF-021: Removed background-color transition to avoid full-viewport repaint on theme toggle */ + transition: color 0.15s ease; + min-height: 100vh; + font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Hiragino Kaku Gothic ProN", Meiryo, "Malgun Gothic", "Apple SD Gothic Neo", "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; +} + +.app-header { + background-color: var(--header-bg); + border-bottom: 1px solid var(--border-color); + padding: 0.35rem 0.75rem; + transition: background-color 0.3s ease; + position: relative; + z-index: 100; + flex-shrink: 0; +} + +.app-container { + height: 100vh; + display: flex; + flex-direction: column; + overflow: hidden; +} + +.content-container { + display: flex; + flex: 1; + overflow: hidden; +} + +.editor-pane, .preview-pane { + flex: 1; + padding: 20px; + overflow-y: auto; + position: relative; + /* PERF-025: Shortened transition and scoped to background-color only */ + transition: background-color 0.15s ease; +} + +.editor-pane { + background-color: var(--editor-bg); + border-right: 1px solid var(--border-color); + padding-right: 0px; + --line-number-gutter: 0px; +} + +.preview-pane { + background-color: var(--preview-bg); /* Using the new variable for preview background */ +} + +/* Custom scrollbar */ +.editor-pane::-webkit-scrollbar, +.preview-pane::-webkit-scrollbar, +#markdown-editor::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +.editor-pane::-webkit-scrollbar-track, +.preview-pane::-webkit-scrollbar-track, +#markdown-editor::-webkit-scrollbar-track { + background: var(--scrollbar-track); +} + +.editor-pane::-webkit-scrollbar-thumb, +.preview-pane::-webkit-scrollbar-thumb, +#markdown-editor::-webkit-scrollbar-thumb { + background: var(--scrollbar-thumb); + border-radius: 4px; +} + +.editor-pane::-webkit-scrollbar-thumb:hover, +.preview-pane::-webkit-scrollbar-thumb:hover, +#markdown-editor::-webkit-scrollbar-thumb:hover { + background: var(--button-active); +} + +#markdown-editor { + width: 100%; + height: 100%; + border: none; + background-color: transparent; + color: var(--text-color); + resize: none; + font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; + font-size: 14px; + line-height: 1.5; + padding: 10px; + padding-left: calc(10px + var(--line-number-gutter)); + transition: background-color 0.3s ease, color 0.3s ease; + overflow-y: auto; + position: relative; + z-index: 3; +} + +#markdown-editor:focus { + outline: none; +} + +.preview-pane { + padding: 20px; +} + +.markdown-body { + padding: 20px; + width: 100%; + background-color: var(--preview-bg); /* Ensuring the markdown content matches preview background */ + color: var(--preview-text-color); /* Using specific text color for preview content */ +} + +.markdown-body a.reference-link { + font-size: 0.75em; + letter-spacing: -0.02em; + line-height: 1; + vertical-align: super; + position: relative; + top: 0.08em; +} + +/* Style tables in light mode */ +.markdown-body table { + background-color: var(--table-bg); + border-color: var(--border-color); +} + +.markdown-body table tr { + background-color: var(--table-bg); + border-top: 1px solid var(--border-color); +} + +.markdown-body table tr:nth-child(2n) { + background-color: var(--bg-color); +} + +/* Style code blocks in light mode */ +.markdown-body pre { + background-color: var(--code-bg); + border-radius: 6px; +} + +.markdown-body code { + background-color: var(--code-bg); + border-radius: 3px; + padding: 0.2em 0.4em; +} + +.markdown-body img.emoji-inline { + width: 1em; + height: 1em; + vertical-align: -0.1em; +} + +.markdown-body ul, +.markdown-body ol { + padding-left: 2em; + margin: 0.4em 0; +} + +.markdown-body ul ul, +.markdown-body ul ol, +.markdown-body ol ul, +.markdown-body ol ol { + margin-top: 0.2em; + margin-bottom: 0.2em; +} + +.markdown-body ul.contains-task-list, +.markdown-body li.task-list-item { + list-style: none; +} + +.markdown-body ul.contains-task-list { + padding-left: 2em; +} + +.markdown-body li.task-list-item input[type="checkbox"] { + margin: 0 0.5em 0.2em 0; + vertical-align: middle; + pointer-events: none; +} + +.markdown-body li.task-list-item::marker { + content: ""; +} + +.markdown-body li:has(> input[type="checkbox"]) { + list-style: none; +} + +.markdown-body li:has(> input[type="checkbox"])::marker { + content: ""; +} + +.markdown-body ul:has(> li > input[type="checkbox"]) { + list-style: none; + padding-left: 2em; +} + +.markdown-body .footnotes { + margin-top: 1.5rem; + font-size: 0.9em; +} + +.markdown-body .footnotes ol { + padding-left: 1.5em; +} + +.markdown-body .footnotes ol > li::marker { + content: "[" counter(list-item) "] "; + font-weight: 600; +} + +.markdown-body .footnotes li > p { + margin: 0.2em 0; +} + +.markdown-body .footnote-ref a, +.markdown-body .footnote-backref { + text-decoration: none; +} + +.markdown-body .footnote-backref { + margin-left: 0.4em; +} + +.markdown-body .markdown-alert { + padding: 0.5rem 1rem; + margin-bottom: 16px; + border-left: 0.25em solid; + border-radius: 0.375rem; +} + +.markdown-body .markdown-alert > :last-child { + margin-bottom: 0; +} + +.markdown-body .markdown-alert-title { + margin: 0 0 8px; + font-weight: 600; + line-height: 1.25; + display: flex; + align-items: center; + gap: 8px; +} + +.markdown-body .markdown-alert-icon { + display: inline-flex; + width: 16px; + height: 16px; +} + +.markdown-body .markdown-alert-icon svg { + width: 16px; + height: 16px; + fill: currentColor; +} + +.markdown-body .markdown-alert-note { + color: #0969da; + border-left-color: #0969da; + background-color: #ddf4ff; +} + +.markdown-body .markdown-alert-tip { + color: #1a7f37; + border-left-color: #1a7f37; + background-color: #dafbe1; +} + +.markdown-body .markdown-alert-important { + color: #8250df; + border-left-color: #8250df; + background-color: #fbefff; +} + +.markdown-body .markdown-alert-warning { + color: #9a6700; + border-left-color: #9a6700; + background-color: #fff8c5; +} + +.markdown-body .markdown-alert-caution { + color: #cf222e; + border-left-color: #cf222e; + background-color: #ffebe9; +} + +.markdown-body .markdown-alert > *:not(.markdown-alert-title) { + color: var(--preview-text-color); +} + +[data-theme="dark"] .markdown-body .markdown-alert-note { + color: #4493f8; + background-color: rgba(31, 111, 235, 0.15); + border-left-color: #4493f8; +} + +[data-theme="dark"] .markdown-body .markdown-alert-tip { + color: #3fb950; + background-color: rgba(35, 134, 54, 0.15); + border-left-color: #3fb950; +} + +[data-theme="dark"] .markdown-body .markdown-alert-important { + color: #ab7df8; + background-color: rgba(137, 87, 229, 0.15); + border-left-color: #ab7df8; +} + +[data-theme="dark"] .markdown-body .markdown-alert-warning { + color: #d29922; + background-color: rgba(210, 153, 34, 0.18); + border-left-color: #d29922; +} + +[data-theme="dark"] .markdown-body .markdown-alert-caution { + color: #f85149; + background-color: rgba(248, 81, 73, 0.18); + border-left-color: #f85149; +} + +.toolbar { + display: flex; + gap: 8px; + align-items: center; +} + +.toolbar-group { + display: inline-flex; + align-items: center; + gap: 6px; +} + +.toolbar-divider { + width: 1px; + height: 20px; + background-color: var(--border-color); + opacity: 0.7; +} + +.tool-button { + background-color: var(--button-bg); + border: 1px solid var(--border-color); + color: var(--text-color); + border-radius: 5px; + padding: 4px 8px; + font-size: 13px; + cursor: pointer; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 4px; + /* PERF-016: Specific transition properties instead of 'all' to avoid animating layout-triggering properties */ + transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease; +} + +.tool-button:hover { + background-color: var(--button-hover); +} + +.tool-button:active { + background-color: var(--button-active); +} + +.tool-button:disabled, +.tool-button[aria-disabled="true"] { + cursor: not-allowed; + opacity: 0.5; +} + +.tool-button i { + font-size: 15px; +} + +.tool-button.is-active, +.tool-button.is-active:hover { + border-color: var(--accent-color); + color: var(--accent-color); + background-color: rgba(3, 102, 214, 0.08); +} + +.btn-text { + display: none; +} + +.toolbar .tool-button { + height: 28px; + min-width: 28px; +} + +.toolbar .tool-button.sync-active { + border-color: var(--accent-color); + color: var(--accent-color); +} + +.file-input { + display: none; +} + +/* Drag overlay: full-screen drop target shown when user drags a file over the window */ +.drag-overlay { + display: none; + position: fixed; + inset: 0; + z-index: 9999; + background-color: rgba(0, 0, 0, 0.45); + pointer-events: none; + align-items: center; + justify-content: center; +} + +.drag-overlay.active { + display: flex; + pointer-events: auto; +} + +.drag-overlay-inner { + border: 3px dashed var(--accent-color); + border-radius: 12px; + padding: 48px 64px; + text-align: center; + color: #ffffff; + background-color: rgba(3, 102, 214, 0.15); + animation: overlayPulse 1.4s ease-in-out infinite; +} + +.drag-overlay-icon { + display: block; + font-size: 3rem; + margin-bottom: 12px; + color: var(--accent-color); +} + +.drag-overlay-text { + font-size: 1.4rem; + font-weight: 600; + margin-bottom: 4px; +} + +.drag-overlay-sub { + font-size: 0.85rem; + opacity: 0.75; + margin-bottom: 0; +} + +@keyframes overlayPulse { + 0%, 100% { transform: scale(1); } + 50% { transform: scale(1.015); } +} + +/* Editor drop hint: subtle text at bottom of editor pane, shown only when empty */ +.drop-hint { + position: absolute; + bottom: 14px; + left: 0; + right: 0; + text-align: center; + font-size: 0.75rem; + color: var(--text-color); + opacity: 0.35; + pointer-events: none; + user-select: none; + z-index: 3; +} + +.editor-pane:has(#markdown-editor:not(:placeholder-shown)) .drop-hint { + display: none; +} + +.line-numbers { + position: absolute; + top: 20px; + bottom: 20px; + left: 20px; + width: var(--line-number-gutter); + padding: 10px 8px 10px 0; + font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; + font-size: 14px; + line-height: 1.5; + text-align: right; + color: var(--text-secondary); + background-color: var(--editor-bg); + border-right: 1px solid var(--border-color); + box-sizing: border-box; + overflow: hidden; + pointer-events: none; + user-select: none; + z-index: 2; + font-variant-numeric: tabular-nums; +} + +.line-numbers .line-number { + display: block; + height: auto; +} + +.editor-highlight-layer { + position: absolute; + inset: 20px 0 20px calc(20px + var(--line-number-gutter)); + padding: 10px; + font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; + font-size: 14px; + line-height: 1.5; + white-space: pre-wrap; + word-wrap: break-word; + color: transparent; + pointer-events: none; + overflow: auto; + background-color: var(--editor-bg); + border-radius: 4px; + z-index: 1; +} + +.editor-highlight-layer::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +.editor-highlight-layer::-webkit-scrollbar-thumb { + background: transparent; +} + +.editor-highlight-layer::-webkit-scrollbar-track { + background: transparent; +} + +.find-highlight { + background-color: var(--fr-match-highlight, rgba(255, 223, 93, 0.4)) !important; + border-radius: 2px; + color: transparent !important; + padding: 0 !important; + margin: 0 !important; +} + +.find-highlight.active { + background-color: var(--fr-match-active, #ff9b30) !important; + color: transparent !important; + padding: 0 !important; + margin: 0 !important; + outline: 1px solid var(--accent-color, #0366d6) !important; + outline-offset: -1px; +} + +.preview-find-highlight { + background-color: var(--fr-match-highlight, rgba(255, 223, 93, 0.4)) !important; + color: var(--fr-match-text-color, inherit) !important; + border-radius: 2px; + padding: 0 1px !important; + margin: 0 !important; +} + +.preview-find-highlight.active { + background-color: var(--fr-match-active, #ff9b30) !important; + color: var(--fr-match-active-text-color, inherit) !important; + outline: 1px solid var(--accent-color, #0366d6) !important; + outline-offset: -1px; +} + +/* Dropdown improvements */ +.dropdown-menu { + background-color: var(--bg-color); + border-color: var(--border-color); +} + +.dropdown-item { + color: var(--text-color); +} + +.dropdown-item:hover, .dropdown-item:focus { + background-color: var(--button-hover); + color: var(--text-color); +} + +/* Markdown formatting toolbar */ +.markdown-format-toolbar { + display: flex; + align-items: center; + height: 34px; + padding: 0 6px; + background-color: var(--header-bg); + border-bottom: 1px solid var(--border-color); + overflow-x: auto; + overflow-y: hidden; + flex-shrink: 0; + scrollbar-width: none; + -ms-overflow-style: none; +} + +.markdown-format-toolbar::-webkit-scrollbar { + display: none; +} + +.markdown-toolbar-group { + display: flex; + align-items: center; + gap: 2px; + height: 100%; + padding: 0 6px; + border-right: 1px solid var(--border-color); + flex-shrink: 0; +} + +.markdown-toolbar-group:first-child { + padding-left: 0; +} + +.markdown-toolbar-group:last-child { + border-right: none; + padding-right: 0; +} + +.markdown-tool-btn { + display: inline-flex; + align-items: center; + justify-content: center; + width: 26px; + height: 26px; + border: 1px solid transparent; + border-radius: 4px; + background: transparent; + color: var(--text-color); + cursor: pointer; + font-size: 14px; + line-height: 1; + padding: 0; + transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease; +} + +.markdown-tool-btn:hover, +.markdown-tool-btn:focus-visible { + background-color: var(--button-hover); + border-color: var(--border-color); + color: var(--accent-color); +} + +.markdown-tool-btn:active { + background-color: var(--button-active); +} + +.markdown-tool-btn:disabled, +.markdown-tool-btn.disabled { + opacity: 0.4; + cursor: not-allowed; + pointer-events: none; +} + +.markdown-tool-btn i { + font-size: 15px; +} + +.markdown-tool-btn[data-md-action="reference"] i::before { + content: "[ ]"; + font-style: normal; + font-size: 12px; + letter-spacing: -0.12em; +} + +.markdown-tool-btn.text-tool { + width: auto; + min-width: 26px; + padding: 0 5px; + font-weight: 600; + font-family: Georgia, "Times New Roman", serif; +} + +.heading-group .markdown-tool-btn { + min-width: 30px; +} + + + +/* Loading indicators */ +.loading { + opacity: 0.6; + pointer-events: none; +} + +/* Focus outline for accessibility */ +button:focus, +a:focus { + outline: 2px solid var(--accent-color); + outline-offset: 2px; +} + +/* Animation for copied message */ +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +/* Tooltip styles */ +.tooltip { + position: absolute; + background: var(--button-bg); + border: 1px solid var(--border-color); + padding: 5px 8px; + border-radius: 4px; + font-size: 12px; + z-index: 1000; + animation: fadeIn 0.2s ease; +} + +/* Styles for GitHub markdown preview light mode */ +.markdown-body { + color-scheme: light; + --color-prettylights-syntax-comment: #6a737d; + --color-prettylights-syntax-constant: #005cc5; + --color-prettylights-syntax-entity: #6f42c1; + --color-prettylights-syntax-storage-modifier-import: #24292e; + --color-prettylights-syntax-entity-tag: #22863a; + --color-prettylights-syntax-keyword: #cf222e; + --color-prettylights-syntax-string: #032f62; + --color-prettylights-syntax-variable: #e36209; + --color-prettylights-syntax-brackethighlighter-unmatched: #b31d28; + --color-prettylights-syntax-invalid-illegal-text: #fafbfc; + --color-prettylights-syntax-invalid-illegal-bg: #b31d28; + --color-prettylights-syntax-carriage-return-text: #fafbfc; + --color-prettylights-syntax-carriage-return-bg: #d73a49; + --color-prettylights-syntax-string-regexp: #22863a; + --color-prettylights-syntax-markup-list: #735c0f; + --color-prettylights-syntax-markup-heading: #005cc5; + --color-prettylights-syntax-markup-italic: #24292e; + --color-prettylights-syntax-markup-bold: #24292e; + --color-prettylights-syntax-markup-deleted-text: #b31d28; + --color-prettylights-syntax-markup-deleted-bg: #ffeef0; + --color-prettylights-syntax-markup-inserted-text: #22863a; + --color-prettylights-syntax-markup-inserted-bg: #f0fff4; + --color-prettylights-syntax-markup-changed-text: #e36209; + --color-prettylights-syntax-markup-changed-bg: #ffebda; + --color-prettylights-syntax-markup-ignored-text: #f6f8fa; + --color-prettylights-syntax-markup-ignored-bg: #005cc5; + --color-prettylights-syntax-meta-diff-range: #6f42c1; + --color-prettylights-syntax-brackethighlighter-angle: #586069; + --color-prettylights-syntax-sublimelinter-gutter-mark: #e1e4e8; + --color-prettylights-syntax-constant-other-reference-link: #032f62; + --color-fg-default: #24292e; + --color-fg-muted: #586069; + --color-fg-subtle: #6a737d; + --color-canvas-default: #ffffff; + --color-canvas-subtle: #f6f8fa; + --color-border-default: #e1e4e8; + --color-border-muted: #eaecef; + --color-neutral-muted: rgba(175,184,193,0.2); + --color-accent-fg: #0366d6; + --color-accent-emphasis: #0366d6; + --color-attention-subtle: #fff5b1; + --color-danger-fg: #d73a49; +} + +/* Styles for GitHub markdown preview dark mode */ +[data-theme="dark"] .markdown-body { + color-scheme: dark; + --color-prettylights-syntax-comment: #8b949e; + --color-prettylights-syntax-constant: #79c0ff; + --color-prettylights-syntax-entity: #d2a8ff; + --color-prettylights-syntax-storage-modifier-import: #c9d1d9; + --color-prettylights-syntax-entity-tag: #7ee787; + --color-prettylights-syntax-keyword: #ff7b72; + --color-prettylights-syntax-string: #a5d6ff; + --color-prettylights-syntax-variable: #ffa657; + --color-prettylights-syntax-brackethighlighter-unmatched: #f85149; + --color-prettylights-syntax-invalid-illegal-text: #f0f6fc; + --color-prettylights-syntax-invalid-illegal-bg: #8e1519; + --color-prettylights-syntax-carriage-return-text: #f0f6fc; + --color-prettylights-syntax-carriage-return-bg: #b62324; + --color-prettylights-syntax-string-regexp: #7ee787; + --color-prettylights-syntax-markup-list: #f2cc60; + --color-prettylights-syntax-markup-heading: #1f6feb; + --color-prettylights-syntax-markup-italic: #c9d1d9; + --color-prettylights-syntax-markup-bold: #c9d1d9; + --color-prettylights-syntax-markup-deleted-text: #ffdcd7; + --color-prettylights-syntax-markup-deleted-bg: #67060c; + --color-prettylights-syntax-markup-inserted-text: #aff5b4; + --color-prettylights-syntax-markup-inserted-bg: #033a16; + --color-prettylights-syntax-markup-changed-text: #ffdfb6; + --color-prettylights-syntax-markup-changed-bg: #5a1e02; + --color-prettylights-syntax-markup-ignored-text: #c9d1d9; + --color-prettylights-syntax-markup-ignored-bg: #1158c7; + --color-prettylights-syntax-meta-diff-range: #d2a8ff; + --color-prettylights-syntax-brackethighlighter-angle: #8b949e; + --color-prettylights-syntax-sublimelinter-gutter-mark: #484f58; + --color-prettylights-syntax-constant-other-reference-link: #a5d6ff; + --color-fg-default: #c9d1d9; + --color-fg-muted: #8b949e; + --color-fg-subtle: #484f58; + --color-canvas-default: #0d1117; + --color-canvas-subtle: #161b22; + --color-border-default: #30363d; + --color-border-muted: #21262d; + --color-neutral-muted: rgba(110,118,129,0.4); + --color-accent-fg: #58a6ff; + --color-accent-emphasis: #1f6feb; + --color-attention-subtle: rgba(187,128,9,0.15); + --color-danger-fg: #f85149; +} + +/* Override specific styles for dark mode tables and code */ +[data-theme="dark"] .markdown-body table tr { + background-color: var(--table-bg); +} + +[data-theme="dark"] .markdown-body table tr:nth-child(2n) { + background-color: #1c2128; /* Slightly lighter than base dark background */ +} + +[data-theme="dark"] .markdown-body pre { + background-color: var(--code-bg); +} + +[data-theme="dark"] .markdown-body code { + background-color: var(--code-bg); +} + +/* Syntax Highlighting Mapping to GitHub Variables */ +.hljs { + color: var(--color-fg-default); +} +.hljs-doctag, +.hljs-keyword, +.hljs-meta .hljs-keyword, +.hljs-template-tag, +.hljs-template-variable, +.hljs-type, +.hljs-variable.language_ { + color: var(--color-prettylights-syntax-keyword); +} +.hljs-title, +.hljs-title.class_, +.hljs-title.class_.inherited__, +.hljs-title.function_ { + color: var(--color-prettylights-syntax-entity); +} +.hljs-attr, +.hljs-attribute, +.hljs-literal, +.hljs-meta, +.hljs-number, +.hljs-operator, +.hljs-variable, +.hljs-selector-attr, +.hljs-selector-class, +.hljs-selector-id { + color: var(--color-prettylights-syntax-constant); +} +.hljs-regexp, +.hljs-string, +.hljs-meta .hljs-string { + color: var(--color-prettylights-syntax-string); +} +.hljs-built_in, +.hljs-symbol { + color: var(--color-prettylights-syntax-variable); +} +.hljs-comment, +.hljs-code, +.hljs-formula { + color: var(--color-prettylights-syntax-comment); +} +.hljs-name, +.hljs-quote, +.hljs-selector-tag, +.hljs-selector-pseudo { + color: var(--color-prettylights-syntax-entity-tag); +} +.hljs-subst { + color: var(--color-fg-default); +} +.hljs-section { + color: var(--color-prettylights-syntax-markup-heading); + font-weight: bold; +} +.hljs-bullet { + color: var(--color-prettylights-syntax-constant); +} +.hljs-emphasis { + color: var(--color-fg-default); + font-style: italic; +} +.hljs-strong { + color: var(--color-fg-default); + font-weight: bold; +} +.hljs-addition { + color: var(--color-prettylights-syntax-markup-inserted-text); + background-color: var(--color-prettylights-syntax-markup-inserted-bg); +} +.hljs-deletion { + color: var(--color-prettylights-syntax-markup-deleted-text); + background-color: var(--color-prettylights-syntax-markup-deleted-bg); +} + +.stats-container { + font-size: 0.8rem; + color: var(--text-color); +} + +.stat-item { + align-items: center; +} + +.stat-item i { + font-size: 0.9rem; + opacity: 0.8; +} + +#importDropdown, +#exportDropdown, +#languageDropdown { + font-size: 0.8rem; +} + +#importDropdown i, +#exportDropdown i, +#languageDropdown i { + font-size: 0.9rem; +} + +/* Ensure desktop dropdown menu options match the stats-container font size */ +[aria-labelledby="importDropdown"] .dropdown-item, +[aria-labelledby="exportDropdown"] .dropdown-item, +[aria-labelledby="languageDropdown"] .dropdown-item { + font-size: 0.8rem; +} + +/* Ensure mobile menu import, export, and language dropdown triggers/options match the mobile stats-container font size */ +#mobile-import-button, +#mobile-import-github-button, +#mobile-export-md, +#mobile-export-html, +#mobile-export-pdf, +#mobileLanguageDropdown { + font-size: 0.9rem !important; +} + +[aria-labelledby="mobileLanguageDropdown"] .dropdown-item { + font-size: 0.9rem; +} + +.editor-pane { + overflow: hidden; +} + +/* Mobile Menu Styles */ +.mobile-menu { + display: none; + position: relative; + z-index: 1001; +} + + + +/* slide‑in panel */ +.mobile-menu-panel { + position: fixed; + top: 0; + right: -300px; + width: 280px; + height: 100vh; + background-color: var(--bg-color); + box-shadow: -2px 0 10px rgba(0, 0, 0, 0.2); + transition: right 0.3s ease; + overflow-y: auto; + padding: 1rem; + display: flex; + flex-direction: column; + z-index: 1002; +} + +.mobile-menu-panel.active { + right: 0; +} + +/* translucent overlay behind panel */ +.mobile-menu-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100vh; + background-color: rgba(0, 0, 0, 0.5); + opacity: 0; + visibility: hidden; + pointer-events: none; + transition: opacity 0.3s ease, visibility 0.3s ease; + z-index: 1000; +} + +.mobile-menu-overlay.active { + opacity: 1; + visibility: visible; + pointer-events: auto; +} + +/* header inside mobile menu */ +.mobile-menu-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1rem; +} + +.mobile-menu-header h5 { + margin: 0; + font-size: 1.25rem; + color: var(--text-color); +} + +/* stats section in mobile menu */ +.mobile-stats-container { + border-bottom: 1px solid var(--border-color); + padding-bottom: 0.75rem; + margin-bottom: 1rem; +} + +.mobile-stats-container .stat-item { + font-size: 0.9rem; + color: var(--text-color); + display: flex; + align-items: center; +} + +.mobile-stats-container .stat-item i { + margin-right: 0.5em; + opacity: 0.8; +} + +/* menu buttons list */ +.mobile-menu-items { + display: flex; + flex-direction: column; + gap: 0.5rem; + flex-grow: 1; +} + +/* each menu item */ +.mobile-menu-item { + background-color: var(--button-bg); + border: 1px solid var(--border-color); + color: var(--text-color); + border-radius: 6px; + padding: 0.6rem 1rem; + font-size: 1rem; + text-align: left; + display: flex; + align-items: center; + gap: 0.5rem; + transition: background-color 0.2s ease; + cursor: pointer; +} + +.mobile-menu-item:hover { + background-color: var(--button-hover); +} + +.mobile-menu-item:active { + background-color: var(--button-active); +} + +/* close button override */ +#close-mobile-menu.tool-button { + padding: 0.25rem 0.5rem; + font-size: 1rem; +} + +/* Mobile document tabs section */ +.mobile-tabs-section { + border-bottom: 1px solid var(--border-color); + padding-bottom: 0.75rem; +} + +.mobile-tabs-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 0.5rem; +} + +.mobile-tabs-label { + font-size: 0.85rem; + font-weight: 600; + color: var(--text-color); + opacity: 0.8; + text-transform: uppercase; + letter-spacing: 0.04em; +} + +.mobile-new-tab-btn { + background: none; + border: 1px solid var(--border-color); + border-radius: 4px; + color: var(--text-color); + padding: 2px 7px; + font-size: 0.9rem; + cursor: pointer; + display: flex; + align-items: center; + transition: background-color 0.15s ease; +} + +.mobile-new-tab-btn:hover { + background-color: var(--button-hover); +} + +.mobile-tab-list { + display: flex; + flex-direction: column; + gap: 4px; + max-height: 180px; + overflow-y: auto; +} + +.mobile-tab-item { + display: flex; + align-items: center; + justify-content: space-between; + background-color: var(--button-bg); + border: 1px solid var(--border-color); + border-radius: 6px; + padding: 0.45rem 0.75rem; + font-size: 0.9rem; + color: var(--text-color); + cursor: pointer; + transition: background-color 0.15s ease; + gap: 0.5rem; +} + +.mobile-tab-item:hover { + background-color: var(--button-hover); +} + +.mobile-tab-item.active { + border-color: var(--accent-color); + color: var(--accent-color); + background-color: var(--bg-color); +} + +.mobile-tab-title { + flex: 1; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + min-width: 0; +} + +.mobile-tab-item .tab-menu-btn { + opacity: 0.6; +} + +.mobile-tab-item:hover .tab-menu-btn, +.mobile-tab-item.active .tab-menu-btn { + opacity: 0.8; +} + +#mobile-tab-reset-btn { + margin-left: 0; + height: auto; + padding: 0.45rem 0.75rem; + justify-content: center; + font-size: 0.9rem; +} + +/* ========================================== + NAVBAR RESPONSIVE BREAKPOINTS + >= 1080px : full desktop navbar + < 1080px : mobile hamburger + stacked panes + ========================================== */ + +/* Mobile / tablet (< 1080px): switch to hamburger, stack panes */ +@media (max-width: 1079px) { + /* Override Bootstrap d-md-flex / d-md-none so the breakpoint is 1080px */ + .stats-container, + .toolbar { + display: none !important; + } + + /* Expand touch target sizes to meet WCAG mobile guidelines */ + .markdown-tool-btn { + width: 36px !important; + height: 36px !important; + font-size: 16px !important; + } + .markdown-format-toolbar { + height: 44px !important; + } + .tab-close-btn { + width: 28px !important; + height: 28px !important; + font-size: 14px !important; + } + .tab-menu-btn { + width: 28px !important; + height: 28px !important; + font-size: 14px !important; + } + + .mobile-menu { + display: block !important; + } + + /* Stack editor and preview vertically */ + .content-container { + flex-direction: column; + } + + .editor-pane, + .preview-pane { + flex: none; + height: 50%; + border-right: none; + } + + .editor-pane { + border-bottom: 1px solid var(--border-color); + } + + /* Hide drag-resize divider (touch devices don't use it) */ + .resize-divider { + display: none; + } + + /* Single-pane view modes: occupy full height */ + .content-container.view-editor-only .editor-pane, + .content-container.view-preview-only .preview-pane { + height: 100%; + } + + .content-container.view-split .editor-pane, + .content-container.view-split .preview-pane { + height: 50%; + } +} + +.github-link { + color: var(--text-color); + text-decoration: none; + display: flex; + align-items: center; + justify-content: center; + transition: transform 0.2s ease, color 0.2s ease; + margin-right: 2rem; +} + +.github-link:hover { + color: var(--accent-color); + transform: scale(1.1); +} + +.github-link i { + font-size: 1.25rem; +} + +/* ======================================== + HEADER LAYOUT + ======================================== */ +.header-container { + position: relative; + min-height: 30px; +} + +.app-header h1 { + font-size: 1.05rem; + line-height: 1.1; +} + +.header-left { + flex: 1 0 auto; + justify-content: flex-start; + white-space: nowrap; +} + +.header-right { + flex: 1 0 auto; + justify-content: flex-end; + white-space: nowrap; +} + +/* Pane View States */ +.content-container.view-editor-only .preview-pane { + display: none; +} + +.content-container.view-editor-only .editor-pane { + flex: 1; + border-right: none; +} + +.content-container.view-preview-only .editor-pane { + display: none; +} + +.content-container.view-preview-only .preview-pane { + flex: 1; +} + +.content-container.view-split .editor-pane, +.content-container.view-split .preview-pane { + flex: 1; +} + +/* Compact desktop (< 1280px): compact toolbar */ +@media (max-width: 1280px) { + /* Compact toolbar at medium widths */ + .toolbar { + gap: 4px; + } +} + + + +/* ======================================== + RESIZE DIVIDER - Story 1.3 + ======================================== */ + +.resize-divider { + width: 8px; + background-color: transparent; + cursor: col-resize; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + position: relative; + z-index: 10; + transition: background-color 0.2s ease; +} + +.resize-divider:hover { + background-color: var(--button-hover); +} + +.resize-divider.dragging { + background-color: var(--accent-color); +} + +.resize-divider-handle { + width: 2px; + height: 40px; + background-color: var(--border-color); + border-radius: 2px; + transition: background-color 0.2s ease, width 0.2s ease; +} + +.resize-divider:hover .resize-divider-handle, +.resize-divider.dragging .resize-divider-handle { + background-color: var(--accent-color); + width: 3px; +} + +/* Hide divider in single-pane modes */ +.content-container.view-editor-only .resize-divider, +.content-container.view-preview-only .resize-divider { + display: none; +} + + + +/* Prevent text selection during drag */ +.resizing { + user-select: none; + cursor: col-resize !important; +} + +.resizing * { + cursor: col-resize !important; +} + +.resizing #markdown-preview, +.resizing #markdown-editor, +.resizing .line-numbers { + pointer-events: none !important; +} + +/* ======================================== + MOBILE VIEW MODE CONTROLS - Story 1.4 + ======================================== */ + +.mobile-view-mode-group { + display: flex; + gap: 0; + border-bottom: 1px solid var(--border-color); + padding-bottom: 0.75rem; +} + +.mobile-view-mode-btn { + flex: 1; + background-color: var(--button-bg); + border: 1px solid var(--border-color); + color: var(--text-color); + padding: 8px 12px; + font-size: 14px; + cursor: pointer; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 4px; + transition: all 0.2s ease; +} + +.mobile-view-mode-btn:first-child { + border-radius: 6px 0 0 6px; +} + +.mobile-view-mode-btn:last-child { + border-radius: 0 6px 6px 0; +} + +.mobile-view-mode-btn:not(:last-child) { + border-right: none; +} + +.mobile-view-mode-btn:hover, +.mobile-view-mode-btn:active { + background-color: var(--button-hover); +} + +.mobile-view-mode-btn.active { + background-color: var(--button-bg); + border-color: var(--accent-color); + color: var(--accent-color); + border-width: 2px; + padding: 7px 11px; +} + +.mobile-view-mode-btn.active:not(:last-child) { + border-right: 2px solid var(--accent-color); +} + +.mobile-view-mode-btn i { + font-size: 18px; +} + +.mobile-view-mode-btn span { + font-size: 12px; +} + +/* ======================================== + RESPONSIVE VIEW MODE FIXES - Story 1.5 + ======================================== */ + + + +/* ======================================== + PDF EXPORT TABLE FIX - Rowspan/Colspan + ======================================== */ + +/* Fix for html2canvas not properly rendering rowspan/colspan cells. + Apply backgrounds to cells instead of rows to prevent row backgrounds + from painting over rowspan cells during canvas capture. */ +.pdf-export table tr { + background-color: transparent !important; +} + +.pdf-export table th, +.pdf-export table td { + background-color: var(--table-bg, #ffffff); + position: relative; +} + +.pdf-export table tr:nth-child(2n) th, +.pdf-export table tr:nth-child(2n) td { + background-color: var(--bg-color, #f6f8fa); +} + +/* Ensure rowspan cells render correctly */ +.pdf-export table th[rowspan], +.pdf-export table td[rowspan] { + vertical-align: middle; + background-color: var(--table-bg, #ffffff) !important; +} + +/* Ensure colspan cells render correctly */ +.pdf-export table th[colspan], +.pdf-export table td[colspan] { + text-align: center; +} + +/* Dark mode PDF export table fix */ +[data-theme="dark"] .pdf-export table th, +[data-theme="dark"] .pdf-export table td { + background-color: var(--table-bg, #161b22); +} + +[data-theme="dark"] .pdf-export table tr:nth-child(2n) th, +[data-theme="dark"] .pdf-export table tr:nth-child(2n) td { + background-color: #1c2128; +} + +[data-theme="dark"] .pdf-export table th[rowspan], +[data-theme="dark"] .pdf-export table td[rowspan] { + background-color: var(--table-bg, #161b22) !important; +} + +/* ======================================== + MERMAID DIAGRAM TOOLBAR + ======================================== */ + +.mermaid-container { + position: relative; +} + +.mermaid-toolbar { + position: absolute; + top: 8px; + right: 8px; + display: flex; + gap: 4px; + opacity: 0; + transition: opacity 0.2s ease; + z-index: 10; +} + +.mermaid-container:hover .mermaid-toolbar { + opacity: 1; +} + +.mermaid-toolbar-btn { + background-color: var(--button-bg); + border: 1px solid var(--border-color); + color: var(--text-color); + border-radius: 4px; + padding: 4px 7px; + font-size: 13px; + cursor: pointer; + display: flex; + align-items: center; + gap: 3px; + transition: background-color 0.2s ease, color 0.2s ease; + white-space: nowrap; +} + +.mermaid-toolbar-btn:hover { + background-color: var(--button-hover); + color: var(--accent-color); +} + +.mermaid-toolbar-btn:active { + background-color: var(--button-active); +} + +.mermaid-toolbar-btn i { + font-size: 14px; +} + +/* ======================================== + MERMAID ZOOM MODAL + ======================================== */ + +#mermaid-zoom-modal { + display: none; + position: fixed; + inset: 0; + z-index: 2000; + background-color: rgba(0, 0, 0, 0.75); + align-items: center; + justify-content: center; +} + +#mermaid-zoom-modal.active { + display: flex; +} + +.mermaid-modal-content { + background-color: var(--bg-color); + border: 1px solid var(--border-color); + border-radius: 8px; + padding: 16px; + width: 85vw; + height: 85vh; + max-width: 85vw; + max-height: 85vh; + display: flex; + flex-direction: column; + gap: 12px; +} + +@media (max-width: 576px) { + .mermaid-modal-content { + width: 95vw; + height: 90vh; + max-width: 95vw; + max-height: 90vh; + padding: 10px; + } +} + +.mermaid-modal-header { + display: flex; + justify-content: space-between; + align-items: center; +} + +.mermaid-modal-header span { + font-weight: 600; + font-size: 15px; + color: var(--text-color); +} + +.mermaid-modal-close { + background: none; + border: none; + color: var(--text-color); + font-size: 1.2rem; + cursor: pointer; + padding: 2px 6px; + border-radius: 4px; + display: flex; + align-items: center; + transition: background-color 0.2s ease; +} + +.mermaid-modal-close:hover { + background-color: var(--button-hover); +} + +.mermaid-modal-diagram { + overflow: auto; + flex: 1; + display: flex; + align-items: center; + justify-content: center; + min-height: 200px; + cursor: grab; +} + +.mermaid-modal-diagram.dragging { + cursor: grabbing; +} + +.mermaid-modal-diagram svg { + transform-origin: center; + transition: transform 0.1s ease; + max-width: none; +} + +.mermaid-modal-controls { + display: flex; + justify-content: center; + gap: 8px; + flex-wrap: wrap; +} + +.mermaid-modal-controls .mermaid-toolbar-btn { + opacity: 1; +} + +/* ======================================== + DOCUMENT TABS & SESSION MANAGEMENT + ======================================== */ + +.tab-bar { + display: flex; + align-items: center; + background-color: var(--header-bg); + border-bottom: 1px solid var(--border-color); + height: 32px; + overflow: visible; /* ← was: overflow: hidden */ + flex-shrink: 0; + padding: 0 4px; + gap: 0; + user-select: none; + position: relative; + z-index: 10; +} + +.tab-list { + display: flex; + align-items: flex-end; + overflow-x: auto; + overflow-y: visible; /* ← was: overflow-y: hidden */ + flex: 1; + height: 100%; + scrollbar-width: none; + -ms-overflow-style: none; +} + +.tab-list::-webkit-scrollbar { + display: none; +} + +.tab-item { + display: flex; + align-items: center; + gap: 6px; + height: 32px; + padding: 0 8px 0 10px; + min-width: 100px; + max-width: 180px; + background-color: var(--button-bg); + border: 1px solid var(--border-color); + border-bottom: 1px solid transparent; + border-radius: 6px 6px 0 0; + cursor: pointer; + font-size: 13px; + color: var(--text-color); + white-space: nowrap; + /* overflow: hidden; <-- REMOVE THIS */ + position: relative; + transition: background-color 0.15s ease, color 0.15s ease; + flex-shrink: 0; + margin-right: 2px; + opacity: 0.7; +} + +.tab-item:hover { + background-color: var(--button-hover); + opacity: 0.9; +} + +.tab-item.active { + background-color: var(--bg-color); + border-color: var(--border-color); + color: var(--accent-color); + border-bottom: 1px solid var(--bg-color); + opacity: 1; + z-index: 2; +} + +.tab-item.unsaved::after { + content: ''; + display: inline-block; + width: 6px; + height: 6px; + background-color: var(--accent-color); + border-radius: 50%; + flex-shrink: 0; + margin-left: 2px; +} + +.tab-title { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + flex: 1; + min-width: 0; +} + +.tab-close-btn { + display: flex; + align-items: center; + justify-content: center; + width: 16px; + height: 16px; + border-radius: 3px; + background: none; + border: none; + color: var(--text-color); + cursor: pointer; + padding: 0; + font-size: 11px; + opacity: 0; + flex-shrink: 0; + transition: background-color 0.15s ease, opacity 0.15s ease; +} + +.tab-item:hover .tab-close-btn, +.tab-item.active .tab-close-btn { + opacity: 0.6; +} + +.tab-close-btn:hover { + background-color: var(--button-active); + opacity: 1 !important; + color: var(--color-danger-fg, #d73a49); +} + +.tab-new-btn { + display: flex; + align-items: center; + gap: 4px; + height: 24px; + padding: 0 8px; + border-radius: 5px; + background: none; + border: 1px solid var(--border-color); + color: var(--text-color); + cursor: pointer; + font-size: 12px; + flex-shrink: 0; + margin-left: 6px; + align-self: center; + transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease; +} + +.tab-new-btn:hover { + background-color: rgba(46, 160, 67, 0.1); + border-color: var(--accent-color, #2ea043); + color: var(--accent-color, #2ea043); +} + +.tab-new-btn:active { + background-color: rgba(46, 160, 67, 0.2); +} + +/* Drag-and-drop visual feedback */ +.tab-item.dragging { + opacity: 0.4; +} + +.tab-item.drag-over { + border-left: 2px solid var(--accent-color); +} + +/* Tab enter animation */ +@keyframes tabSlideIn { + from { opacity: 0; transform: translateY(4px); } + to { opacity: 0.7; transform: translateY(0); } +} + +.tab-item { + animation: tabSlideIn 0.12s ease forwards; +} + +.tab-item.active { + animation: none; +} + +/* Hide tab bar on very small screens — single-file use */ +@media (max-width: 480px) { + .tab-bar { + display: none; + } +} + +/* ======================================== + TAB OVERFLOW — Scroll Buttons & Fade Indicators + ======================================== */ + +.tab-scroll-btn { + display: none; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + border-radius: 4px; + background: none; + border: 1px solid transparent; + color: var(--text-color); + cursor: pointer; + font-size: 14px; + flex-shrink: 0; + padding: 0; + transition: background-color 0.15s ease, border-color 0.15s ease, opacity 0.15s ease; + z-index: 2; + opacity: 0.6; +} + +.tab-scroll-btn:hover { + background-color: var(--button-hover); + border-color: var(--border-color); + opacity: 1; +} + +.tab-scroll-btn:active { + background-color: var(--button-active); +} + +/* Show scroll buttons only when overflow exists */ +.tab-bar.has-overflow-left .tab-scroll-left, +.tab-bar.has-overflow-right .tab-scroll-right { + display: flex; +} + +/* Overflow fade indicators — subtle gradient at clipped edges */ +.tab-list::before, +.tab-list::after { + content: ''; + position: sticky; + top: 0; + bottom: 0; + width: 0; + flex-shrink: 0; + pointer-events: none; + z-index: 3; + transition: box-shadow 0.2s ease; +} + +.tab-list::before { + left: 0; +} + +.tab-list::after { + right: 0; +} + +.tab-bar.has-overflow-left .tab-list::before { + box-shadow: 8px 0 12px -4px rgba(0, 0, 0, 0.12); +} + +.tab-bar.has-overflow-right .tab-list::after { + box-shadow: -8px 0 12px -4px rgba(0, 0, 0, 0.12); +} + +[data-theme="dark"] .tab-bar.has-overflow-left .tab-list::before { + box-shadow: 8px 0 12px -4px rgba(0, 0, 0, 0.35); +} + +[data-theme="dark"] .tab-bar.has-overflow-right .tab-list::after { + box-shadow: -8px 0 12px -4px rgba(0, 0, 0, 0.35); +} + +/* ======================================== + THREE-DOT TAB MENU + ======================================== */ + +.tab-menu-btn { + display: flex; + align-items: center; + justify-content: center; + width: 22px; + height: 22px; + border-radius: 3px; + background: none; + border: none; + color: var(--text-color); + cursor: pointer; + padding: 0; + font-size: 14px; + font-weight: bold; + letter-spacing: 1px; + opacity: 0.65; + flex-shrink: 0; + transition: background-color 0.15s ease, opacity 0.15s ease; + position: relative; +} + +/* Touch Hitbox Expansion for Tab Menu Button */ +.tab-menu-btn::before { + content: ''; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 48px; + height: 48px; +} + +/* Touch-optimized styling for coarser pointers (e.g., smartphones & tablets) */ +@media (pointer: coarse) { + .tab-bar { + height: 40px !important; + } + .tab-item { + height: 40px !important; + font-size: 14px !important; + padding: 0 10px 0 12px !important; + gap: 8px !important; + } + .tab-new-btn, + .tab-reset-btn { + height: 32px !important; + font-size: 14px !important; + padding: 0 12px !important; + } + .tab-scroll-btn { + width: 32px !important; + height: 32px !important; + font-size: 18px !important; + } + .tab-menu-btn { + width: 30px !important; + height: 30px !important; + font-size: 18px !important; + } + .tab-close-btn { + width: 20px !important; + height: 20px !important; + font-size: 13px !important; + opacity: 0.8 !important; + } +} + +.tab-item:hover .tab-menu-btn, +.tab-item.active .tab-menu-btn { + opacity: 0.65; +} + +.tab-menu-btn:hover { + background-color: var(--button-active); + opacity: 1 !important; +} + +.tab-menu-dropdown { + display: none; + position: fixed; + min-width: 130px; + background-color: var(--header-bg); + border: 1px solid var(--border-color); + border-radius: 6px; + box-shadow: 0 4px 12px rgba(0,0,0,0.15); + z-index: 99999; + overflow: hidden; + flex-direction: column; +} + +.tab-menu-dropdown.open { + display: flex; +} + +.tab-menu-item { + display: flex; + align-items: center; + gap: 7px; + padding: 7px 12px; + background: none; + border: none; + color: var(--text-color); + font-size: 12px; + cursor: pointer; + text-align: left; + transition: background-color 0.12s ease; + white-space: nowrap; +} + +.tab-menu-item:hover { + background-color: var(--button-hover); +} + +.tab-menu-item-danger { + color: var(--color-danger-fg, #d73a49); +} + +.tab-menu-item-danger:hover { + background-color: rgba(215, 58, 73, 0.1); +} + +/* ======================================== + RESET BUTTON + ======================================== */ + +.tab-reset-btn { + display: flex; + align-items: center; + gap: 4px; + height: 24px; + padding: 0 8px; + border-radius: 5px; + background: none; + border: 1px solid var(--border-color); + color: var(--text-color); + cursor: pointer; + font-size: 12px; + flex-shrink: 0; + margin-left: 6px; + transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease; +} + +.tab-reset-btn:hover { + background-color: rgba(215, 58, 73, 0.1); + border-color: var(--color-danger-fg, #d73a49); + color: var(--color-danger-fg, #d73a49); +} + +/* ======================================== + RESET & RENAME CONFIRMATION MODALS + ======================================== */ + +.reset-modal-overlay { + position: fixed; + inset: 0; + background: rgba(0, 0, 0, 0.45); + z-index: 2000; + display: flex; + align-items: center; + justify-content: center; +} + +.reset-modal-overlay.modal-overlay { + opacity: 0; + visibility: hidden; + transition: opacity 0.2s ease, visibility 0.2s ease; +} + +.reset-modal-overlay.modal-overlay.is-visible { + opacity: 1; + visibility: visible; +} + +.reset-modal-box { + background: var(--header-bg); + border: 1px solid var(--border-color); + border-radius: 10px; + padding: 24px 28px; + min-width: 280px; + max-width: 360px; + box-shadow: 0 8px 32px rgba(0,0,0,0.25); + display: flex; + flex-direction: column; + gap: 16px; +} + +.modal-box { + max-height: min(85vh, 760px); + opacity: 0; + transform: translateY(8px); + transition: transform 0.2s ease, opacity 0.2s ease; +} + +.reset-modal-overlay.modal-overlay.is-visible .modal-box { + opacity: 1; + transform: translateY(0); +} + +.modal-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; +} + +.modal-header .reset-modal-message { + text-align: left; + flex: 1; +} + +.modal-close-btn { + border: 1px solid var(--border-color); + background: var(--button-bg); + color: var(--text-color); + border-radius: 6px; + width: 28px; + height: 28px; + display: inline-flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: background-color 0.15s ease; +} + +.modal-close-btn:hover { + background-color: var(--button-hover); +} + +.modal-body { + display: flex; + flex-direction: column; + gap: 16px; + max-height: min(60vh, 520px); + overflow: auto; + padding-right: 4px; +} + +.modal-section { + display: flex; + flex-direction: column; + gap: 8px; +} + +.modal-section-title { + margin: 0; + font-size: 0.95rem; + font-weight: 600; +} + +.modal-list { + margin: 0; + padding-left: 1.1rem; + display: flex; + flex-direction: column; + gap: 6px; + font-size: 0.85rem; +} + +.modal-list a { + color: var(--accent-color); + text-decoration: none; +} + +.modal-list a:hover { + text-decoration: underline; +} + +.modal-subtext { + margin: 0; + font-size: 12px; + color: var(--text-secondary, #57606a); + line-height: 1.4; +} + +.find-replace-meta { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; +} + +.find-match-count { + font-size: 12px; + color: var(--text-secondary, #57606a); +} + +.find-replace-nav { + display: inline-flex; + gap: 6px; +} + +.find-nav-btn { + width: 28px; + height: 28px; + padding: 0; +} + +.about-header { + display: flex; + align-items: center; + gap: 16px; + flex-wrap: wrap; +} + +.about-logo { + width: 64px; + height: 64px; + border-radius: 12px; + border: 1px solid var(--border-color); + object-fit: cover; +} + +.about-details { + display: flex; + flex-direction: column; + gap: 6px; +} + +.about-title { + margin: 0; + font-size: 1.05rem; + font-weight: 600; +} + +.about-description { + margin: 0; + font-size: 0.85rem; + color: var(--text-secondary, #57606a); +} + +.about-meta { + margin: 0; + font-size: 0.78rem; + color: var(--text-secondary, #57606a); +} + +.modal-body kbd { + padding: 2px 6px; + border-radius: 4px; + background-color: var(--button-bg); + border: 1px solid var(--border-color); + font-size: 0.75rem; + font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; +} + +.reset-modal-box--wide { + width: min(92vw, 640px); + max-width: 640px; +} + +.reset-modal-message { + margin: 0; + font-size: 14px; + color: var(--text-color); + font-weight: 500; + text-align: center; +} + +.reset-modal-actions { + display: flex; + gap: 10px; + justify-content: flex-end; +} + +.reset-modal-btn { + padding: 6px 16px; + border-radius: 6px; + border: 1px solid var(--border-color); + background: var(--button-bg); + color: var(--text-color); + font-size: 13px; + cursor: pointer; + transition: background-color 0.15s ease; +} + +.reset-modal-btn:hover { + background-color: var(--button-hover); +} + +.reset-modal-confirm { + background-color: var(--color-danger-fg, #d73a49); + border-color: var(--color-danger-fg, #d73a49); + color: #fff; +} + +.reset-modal-confirm:hover { + background-color: #b02a37; + border-color: #b02a37; +} + +/* ======================================== + PDF EXPORT PROGRESS MODAL + ======================================== */ + +.pdf-progress-overlay { + position: fixed; + inset: 0; + z-index: 2600; + display: flex; + align-items: center; + justify-content: center; + background: rgba(0, 0, 0, 0.45); + padding: 20px; +} + +.pdf-progress-modal { + width: min(92vw, 420px); + background: var(--header-bg); + border: 1px solid var(--border-color); + border-radius: 8px; + box-shadow: 0 16px 48px rgba(0, 0, 0, 0.28); + color: var(--text-color); + display: flex; + flex-direction: column; + gap: 16px; + padding: 20px; +} + +.pdf-progress-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; +} + +.pdf-progress-title { + margin: 0; + font-size: 15px; + font-weight: 600; +} + +.pdf-progress-percent { + font-size: 28px; + font-weight: 600; + line-height: 1; +} + +.pdf-progress-track { + width: 100%; + height: 10px; + background: var(--button-bg); + border: 1px solid var(--border-color); + border-radius: 999px; + overflow: hidden; +} + +.pdf-progress-fill { + width: 0%; + height: 100%; + background: var(--accent-color); + border-radius: inherit; + transition: width 0.18s ease; +} + +.pdf-progress-details { + display: flex; + flex-direction: column; + gap: 6px; + font-size: 12px; + color: var(--text-secondary); +} + +.pdf-progress-detail { + display: flex; + justify-content: space-between; + gap: 12px; +} + +.pdf-progress-detail strong { + color: var(--text-color); + font-weight: 600; +} + +.pdf-progress-actions { + display: flex; + justify-content: flex-end; +} + +.tool-button.pdf-export-loading, +.mobile-menu-item.pdf-export-loading { + pointer-events: none; +} +/* ======================================== + RESET MODAL FORM FIELDS + ======================================== */ + +.reset-modal-field { + display: flex; + flex-direction: column; + gap: 6px; + text-align: left; +} + +.reset-modal-field-group { + display: flex; + flex-direction: column; + gap: 12px; +} + +.reset-modal-label { + font-size: 12px; + color: var(--text-secondary, #57606a); + font-weight: 600; +} + +.reset-modal-toggle-group { + display: flex; + flex-direction: column; + gap: 8px; +} + +.reset-modal-option { + display: flex; + align-items: center; + gap: 8px; + font-size: 13px; + color: var(--text-color); +} + +.reset-modal-option input { + margin: 0; +} + +/* ======================================== + RENAME MODAL INPUT + ======================================== */ + +.rename-modal-input { + width: 100%; + padding: 7px 10px; + border-radius: 6px; + border: 1px solid var(--border-color); + background: var(--bg-color); + color: var(--text-color); + font-size: 13px; + outline: none; + box-sizing: border-box; +} + +.rename-modal-input:focus { + border-color: var(--accent-color); +} + +/* ======================================== + TOOLBAR POPUP PANELS + ======================================== */ + +.reset-modal-box--xl { + width: min(94vw, 980px); + max-width: 980px; +} + +.modal-empty { + margin: 0; + font-size: 12px; + color: var(--text-secondary, #57606a); + text-align: center; +} + +.emoji-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); + gap: 12px; + max-height: min(52vh, 440px); + overflow: auto; + padding: 4px; +} + +.symbol-grid { + display: flex; + flex-direction: column; + gap: 16px; + max-height: min(52vh, 440px); + overflow: auto; + padding: 4px 2px; +} + +.symbol-section-title { + margin: 0; + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--text-secondary, #57606a); +} + +.symbol-section-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); + gap: 12px; +} + +.alert-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); + gap: 12px; + max-height: min(45vh, 360px); + overflow: auto; + padding: 2px; +} + +.emoji-item, +.symbol-item, +.alert-option { + display: flex; + flex-direction: column; + gap: 8px; + align-items: center; + border: 1px solid var(--border-color); + border-radius: 10px; + padding: 10px; + background: var(--bg-color); + color: var(--text-color); + cursor: pointer; + transition: border-color 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease; +} + +.emoji-item:focus-visible, +.symbol-item:focus-visible, +.alert-option:focus-visible { + outline: 2px solid var(--accent-color); + outline-offset: 2px; +} + +.emoji-item.is-selected, +.symbol-item.is-selected, +.alert-option.is-selected { + border-color: var(--accent-color); + box-shadow: 0 0 0 2px rgba(88, 166, 255, 0.2); + background-color: rgba(88, 166, 255, 0.08); +} + +.emoji-preview { + width: 36px; + height: 36px; + display: flex; + align-items: center; + justify-content: center; +} + +.emoji-preview img { + width: 32px; + height: 32px; +} + +.emoji-shortcode { + display: flex; + align-items: center; + gap: 6px; + font-size: 12px; + color: var(--text-secondary, #57606a); + text-align: center; +} + +.emoji-copy-btn, +.symbol-copy-btn { + border: none; + background: transparent; + color: var(--text-secondary, #57606a); + cursor: pointer; + padding: 2px; + border-radius: 4px; +} + +.emoji-copy-btn:hover, +.symbol-copy-btn:hover { + color: var(--text-color); + background: var(--button-hover); +} + +.emoji-copy-btn.is-copied, +.symbol-copy-btn.is-copied { + color: var(--accent-color); +} + +.symbol-preview { + font-size: 28px; + line-height: 1; +} + +.symbol-code { + display: flex; + align-items: center; + gap: 6px; + font-size: 12px; + color: var(--text-secondary, #57606a); +} + +.alert-option { + align-items: stretch; + text-align: left; + padding: 12px; +} + +.alert-preview { + margin: 0; +} + +.alert-preview .markdown-alert { + padding: 0.5rem 0.9rem; + border-left: 0.25em solid; + border-radius: 0.375rem; +} + +.alert-preview .markdown-alert-title { + margin: 0 0 6px; + font-weight: 600; + line-height: 1.25; + display: flex; + align-items: center; + gap: 8px; +} + +.alert-preview .markdown-alert-icon { + display: inline-flex; + width: 16px; + height: 16px; +} + +.alert-preview .markdown-alert-icon svg { + width: 16px; + height: 16px; + fill: currentColor; +} + +.alert-preview .markdown-alert > *:not(.markdown-alert-title) { + color: var(--text-color); +} + +.alert-preview .markdown-alert-note { + color: #0969da; + border-left-color: #0969da; + background-color: #ddf4ff; +} + +.alert-preview .markdown-alert-tip { + color: #1a7f37; + border-left-color: #1a7f37; + background-color: #dafbe1; +} + +.alert-preview .markdown-alert-important { + color: #8250df; + border-left-color: #8250df; + background-color: #fbefff; +} + +.alert-preview .markdown-alert-warning { + color: #9a6700; + border-left-color: #9a6700; + background-color: #fff8c5; +} + +.alert-preview .markdown-alert-caution { + color: #cf222e; + border-left-color: #cf222e; + background-color: #ffebe9; +} + +[data-theme="dark"] .alert-preview .markdown-alert-note { + color: #4493f8; + border-left-color: #4493f8; + background-color: rgba(31, 111, 235, 0.15); +} + +[data-theme="dark"] .alert-preview .markdown-alert-tip { + color: #3fb950; + border-left-color: #3fb950; + background-color: rgba(35, 134, 54, 0.15); +} + +[data-theme="dark"] .alert-preview .markdown-alert-important { + color: #ab7df8; + border-left-color: #ab7df8; + background-color: rgba(137, 87, 229, 0.15); +} + +[data-theme="dark"] .alert-preview .markdown-alert-warning { + color: #d29922; + border-left-color: #d29922; + background-color: rgba(210, 153, 34, 0.18); +} + +[data-theme="dark"] .alert-preview .markdown-alert-caution { + color: #f85149; + border-left-color: #f85149; + background-color: rgba(248, 81, 73, 0.18); +} + +.github-import-error { + margin: 0; + font-size: 12px; + color: var(--color-danger-fg, #d73a49); + text-align: left; + line-height: 1.5; +} + +.github-import-error.is-info { + color: var(--text-secondary, #57606a); +} + +#github-import-modal .reset-modal-box { + width: 60vw; + max-width: 60vw; + min-width: 340px; + padding: 30px 34px; + gap: 16px; + box-shadow: 0 20px 48px rgba(0, 0, 0, 0.22); +} + +#github-import-modal .reset-modal-message { + font-size: 18px; + line-height: 1.35; + text-align: left; +} + +#github-import-url, +#github-import-file-select { + min-height: 46px; + padding: 10px 12px; + font-size: 15px; +} + +#github-import-file-select { + min-height: 180px; +} + +.github-import-tree { + max-height: 420px; + overflow: auto; + border: 1px solid var(--border-color); + border-radius: 10px; + padding: 12px; + background: var(--bg-color); +} + +.github-import-selection-toolbar { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + padding: 10px 12px; + border: 1px solid var(--border-color); + border-radius: 8px; + background: var(--button-bg); +} + +.github-import-selected-count { + font-size: 14px; + font-weight: 600; + color: var(--text-color); +} + +.github-import-tree ul { + list-style: none; + margin: 0; + padding-left: 18px; +} + +.github-import-tree > ul { + padding-left: 4px; +} + +.github-import-tree li { + margin: 2px 0; +} + +.github-tree-folder-label { + display: inline-block; + font-size: 14px; + color: var(--text-secondary, #57606a); + margin-bottom: 4px; +} + +.github-tree-file-btn { + border: 0; + background: transparent; + color: var(--text-color); + cursor: pointer; + padding: 6px 8px; + border-radius: 6px; + text-align: left; + width: 100%; + font-size: 14px; +} + +.github-tree-file-btn:hover, +.github-tree-file-btn:focus-visible { + background: var(--button-hover); + outline: none; +} + +.github-tree-file-btn.is-selected { + background: rgba(56, 139, 253, 0.14); + color: var(--accent-color); +} + +#github-import-modal .reset-modal-actions { + gap: 12px; +} + +#github-import-modal .reset-modal-btn { + min-height: 42px; + padding: 9px 18px; + font-size: 14px; +} + +@media (max-width: 576px) { + #github-import-modal .reset-modal-box { + width: 95vw; + max-width: 95vw; + min-width: 0; + padding: 20px; + gap: 14px; + } + + .github-import-selection-toolbar { + flex-direction: column; + align-items: stretch; + } + + #github-import-modal .reset-modal-message { + font-size: 16px; + } + + #github-import-modal .reset-modal-actions { + flex-direction: column-reverse; + } + + #github-import-modal .reset-modal-btn { + width: 100%; + } +} + +.frontmatter-table { + border-collapse: collapse; + margin-bottom: 1.5em; + font-size: 0.9em; + width: auto; + max-width: 100%; +} + +.frontmatter-table th, +.frontmatter-table td { + border: 1px solid var(--border-color); + padding: 6px 13px; + vertical-align: top; + color: var(--text-color); +} + +.frontmatter-table tr:nth-child(odd) th, +.frontmatter-table tr:nth-child(odd) td { + background-color: var(--table-bg); +} + +.frontmatter-table tr:nth-child(even) th, +.frontmatter-table tr:nth-child(even) td { + background-color: var(--editor-bg); +} + +.frontmatter-table th { + font-weight: 600; + text-align: right; + white-space: nowrap; + vertical-align: middle; +} + +.frontmatter-table td { + text-align: left; +} + +.fm-complex { + margin: 0; + padding: 4px 6px; + font-size: 0.8em; + font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; + white-space: pre-wrap; + word-break: break-word; + background: transparent; + border: none; + color: var(--text-color); +} + +.fm-tag { + display: inline-block; + padding: 2px 8px; + margin: 2px 3px 2px 0; + border: 1px solid var(--border-color); + border-radius: 2em; + font-size: 0.8em; + font-weight: 500; + color: var(--accent-color); + background-color: var(--button-bg); + white-space: nowrap; +} + +/* ======================================== + RTL SUPPORT + ======================================== */ + +[dir="rtl"] body { + direction: rtl; +} + +[dir="rtl"] .editor-pane { + padding-left: 0px; + padding-right: 20px; + border-right: none; + border-left: 1px solid var(--border-color); +} + +[dir="rtl"] #markdown-editor, +[dir="rtl"] .markdown-body { + direction: rtl; + text-align: right; +} + +[dir="rtl"] .markdown-body pre, +[dir="rtl"] .markdown-body code, +[dir="rtl"] .fm-complex { + direction: ltr; + text-align: left; +} + +[dir="rtl"] .line-numbers { + left: auto; + right: 20px; + padding: 10px 0 10px 8px; + text-align: left; + border-right: none; + border-left: 1px solid var(--border-color); +} + +[dir="rtl"] #markdown-editor { + padding-left: 10px; + padding-right: calc(10px + var(--line-number-gutter)); +} + +[dir="rtl"] .editor-highlight-layer { + inset: 20px calc(20px + var(--line-number-gutter)) 20px 0; +} + +[dir="rtl"] .mobile-menu-item, +[dir="rtl"] .tab-menu-item, +[dir="rtl"] .modal-header .reset-modal-message, +[dir="rtl"] .reset-modal-field, +[dir="rtl"] .alert-option, +[dir="rtl"] .github-import-error, +[dir="rtl"] #github-import-modal .reset-modal-message, +[dir="rtl"] .github-tree-file-btn, +[dir="rtl"] .frontmatter-table td { + text-align: right; +} + +[dir="rtl"] .github-import-tree ul { + padding-left: 0; + padding-right: 18px; +} + +[dir="rtl"] .github-import-tree > ul { + padding-right: 4px; +} + +[dir="rtl"] .markdown-body .markdown-alert, +[dir="rtl"] .alert-preview .markdown-alert { + border-left: 0; + border-right: 0.25em solid currentColor; +} + +/* ============================================ + SHARE MODAL + ============================================ */ + +.share-modal-description { + font-size: 13px; + color: var(--text-secondary, #57606a); + margin: 0; +} + +.share-mode-cards { + display: flex; + flex-direction: column; + gap: 8px; +} + +.share-mode-card { + display: flex; + align-items: center; + gap: 12px; + padding: 12px 14px; + border-radius: 8px; + border: 1px solid var(--border-color); + background: var(--bg-color); + cursor: pointer; + transition: border-color 0.15s ease, background-color 0.15s ease; + user-select: none; +} + +.share-mode-card:hover { + border-color: var(--accent-color); + background: var(--button-hover); +} + +.share-mode-card.is-selected { + border-color: var(--accent-color); + background: color-mix(in srgb, var(--accent-color) 8%, transparent); +} + +.share-mode-card input[type="radio"] { + display: none; +} + +.share-card-icon { + font-size: 18px; + width: 28px; + text-align: center; + color: var(--text-secondary, #57606a); + flex-shrink: 0; +} + +.share-mode-card.is-selected .share-card-icon { + color: var(--accent-color); +} + +.share-card-body { + display: flex; + flex-direction: column; + gap: 2px; + flex: 1; + min-width: 0; +} + +.share-card-title { + font-size: 13px; + font-weight: 600; + color: var(--text-color); +} + +.share-card-desc { + font-size: 12px; + color: var(--text-secondary, #57606a); +} + +.share-card-check { + width: 18px; + text-align: center; + color: var(--accent-color); + opacity: 0; + transition: opacity 0.15s ease; + flex-shrink: 0; +} + +.share-mode-card.is-selected .share-card-check { + opacity: 1; +} + +.share-url-row { + display: flex; + gap: 8px; + align-items: center; +} + +.share-url-input { + flex: 1; + font-size: 12px; + font-family: var(--font-mono, monospace); + color: var(--text-secondary, #57606a); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.share-copy-btn { + flex-shrink: 0; + padding: 6px 10px; +} + +.share-copy-btn:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.share-modal-notice { + font-size: 11px; + color: var(--text-secondary, #57606a); + margin: 0; + display: flex; + align-items: center; + gap: 5px; +} + +/* ========================================================================== + Multilingual & CJK Optimization styles added by Aegis SEO agency + ========================================================================== */ +.lang-select-item { + display: flex !important; + align-items: center; + gap: 8px; + cursor: pointer; + transition: background-color 0.2s ease, padding-left 0.2s ease; +} + +.lang-select-item:hover { + padding-left: 12px; +} + +.lang-select-item.active { + background-color: var(--accent-color) !important; + color: #ffffff !important; + font-weight: 600; +} + +/* Adjust CJK text layout for maximum readability inside the preview pane */ +html[lang="zh"] .markdown-body, +html[lang="ja"] .markdown-body, +html[lang="ko"] .markdown-body { + line-height: 1.75 !important; + letter-spacing: 0.03em; + word-break: keep-all; + overflow-wrap: break-word; + text-align: justify; +} + +/* Specific heading spacing improvements for CJK characters */ +html[lang="zh"] .markdown-body h1, html[lang="zh"] .markdown-body h2, html[lang="zh"] .markdown-body h3, +html[lang="ja"] .markdown-body h1, html[lang="ja"] .markdown-body h2, html[lang="ja"] .markdown-body h3, +html[lang="ko"] .markdown-body h1, html[lang="ko"] .markdown-body h2, html[lang="ko"] .markdown-body h3 { + font-weight: 700; + letter-spacing: 0.02em; + margin-top: 1.4em; + margin-bottom: 0.6em; +} + +/* Smooth fade and scale transition for dropdown active states */ +.dropdown-menu { + opacity: 0; + transform: translateY(8px) scale(0.98); + display: block; + visibility: hidden; + transition: opacity 0.2s cubic-bezier(0.16, 1, 0.3, 1), transform 0.2s cubic-bezier(0.16, 1, 0.3, 1), visibility 0.2s; +} + +.dropdown-menu.show { + opacity: 1; + transform: translateY(0) scale(1); + visibility: visible; +} + /* ======================================== - PDF EXPORT PROGRESS MODAL + FIND & REPLACE FLOATING PANEL DESIGN ======================================== */ -.pdf-progress-overlay { +.find-replace-panel { position: fixed; - inset: 0; - z-index: 2600; + top: 100px; + right: 20px; + width: 340px; + background-color: var(--fr-bg); + border: 1px solid var(--fr-border); + border-radius: 12px; + box-shadow: var(--fr-shadow); + z-index: 1050; + display: flex; + flex-direction: column; + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + transition: opacity 0.2s ease, transform 0.2s ease; + user-select: none; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; +} + +.find-replace-panel.docked { + position: relative; + top: 0 !important; + right: 0 !important; + height: 100%; + border-radius: 0; + border-top: none; + border-bottom: none; + border-right: none; + border-left: 1px solid var(--fr-border); + box-shadow: none; + backdrop-filter: none; + z-index: 10; + flex-shrink: 0; +} + +.find-replace-panel.docked #find-replace-reset, +.find-replace-panel.docked #find-replace-reset-footer { + display: none !important; +} + +.find-replace-header { display: flex; align-items: center; - justify-content: center; - background: rgba(0, 0, 0, 0.45); - padding: 20px; + justify-content: space-between; + padding: 8px 12px; + border-bottom: 1px solid var(--fr-border); + cursor: move; + background-color: var(--header-bg); + border-top-left-radius: 11px; + border-top-right-radius: 11px; } -.pdf-progress-modal { - width: min(92vw, 420px); - background: var(--header-bg); - border: 1px solid var(--border-color); - border-radius: 8px; - box-shadow: 0 16px 48px rgba(0, 0, 0, 0.28); +.find-replace-panel.docked .find-replace-header { + cursor: default; + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.find-replace-title { + font-size: 13px; + font-weight: 600; + color: var(--text-color); +} + +.find-replace-header-actions { + display: flex; + gap: 4px; +} + +.panel-icon-btn { + background: none; + border: none; color: var(--text-color); + font-size: 12px; + cursor: pointer; + padding: 2px 6px; + border-radius: 4px; + display: flex; + align-items: center; + justify-content: center; + transition: background-color 0.15s ease; +} + +.panel-icon-btn:hover { + background-color: var(--button-hover); +} + +.find-replace-body { + padding: 12px; display: flex; flex-direction: column; - gap: 16px; - padding: 20px; + gap: 8px; } -.pdf-progress-header { +.find-replace-field-row { + display: flex; + flex-direction: column; + position: relative; +} + +.find-input-container, .replace-input-container { display: flex; align-items: center; - justify-content: space-between; - gap: 12px; + border: 1px solid var(--fr-border); + border-radius: 6px; + background-color: var(--bg-color); + padding: 2px 4px; + width: 100%; } -.pdf-progress-title { - margin: 0; - font-size: 15px; +.find-input-container:focus-within, .replace-input-container:focus-within { + border-color: var(--accent-color); + box-shadow: 0 0 0 3px rgba(9, 105, 218, 0.15); +} + +.find-input-field { + flex: 1; + border: none; + background: transparent; + color: var(--text-color); + font-size: 13px; + padding: 4px 6px; + outline: none; + width: 50%; +} + +.find-options-group { + display: flex; + gap: 2px; +} + +.find-option-btn { + background: none; + border: none; + color: var(--text-secondary); + font-size: 11px; font-weight: 600; + cursor: pointer; + padding: 2px 5px; + border-radius: 4px; + transition: background-color 0.12s ease, color 0.12s ease; + min-width: 22px; + height: 22px; + display: inline-flex; + align-items: center; + justify-content: center; } -.pdf-progress-percent { - font-size: 28px; +.find-option-btn:hover { + background-color: var(--button-hover); + color: var(--text-color); +} + +.find-option-btn.active { + background-color: var(--fr-btn-active-bg); + color: var(--fr-btn-active); +} + +.find-error-drawer { + background-color: var(--fr-error-bg); + border: 1px solid var(--fr-error-border); + border-radius: 6px; + padding: 6px 10px; + font-size: 11px; + color: var(--fr-text-danger); + line-height: 1.3; +} + +.find-replace-meta-row { + display: flex; + align-items: center; + justify-content: space-between; + padding: 2px 4px; +} + +.find-match-count { + font-size: 12px; + color: var(--text-secondary); +} + +.find-nav-group { + display: flex; + gap: 4px; +} + +.find-nav-arrow-btn { + background: none; + border: 1px solid var(--fr-border); + color: var(--text-color); + font-size: 12px; + cursor: pointer; + padding: 2px 8px; + border-radius: 4px; + transition: background-color 0.15s ease; + display: flex; + align-items: center; + justify-content: center; +} + +.find-nav-arrow-btn:hover:not(:disabled) { + background-color: var(--button-hover); +} + +.find-nav-arrow-btn:disabled { + opacity: 0.4; + cursor: not-allowed; +} + +.find-drawer-toggle-row { + border-top: 1px solid var(--fr-border); + margin-top: 4px; + padding-top: 6px; +} + +.drawer-toggle-btn { + background: none; + border: none; + color: var(--text-secondary); + font-size: 12px; + cursor: pointer; + display: flex; + align-items: center; + padding: 2px 4px; + border-radius: 4px; + transition: color 0.15s ease; +} + +.drawer-toggle-btn:hover { + color: var(--text-color); +} + +.find-replace-drawer-content { + display: flex; + flex-direction: column; + gap: 8px; + padding: 4px 6px; + border-top: 1px dashed var(--fr-border); + margin-top: 2px; + padding-top: 8px; +} + +.drawer-field { + display: flex; + flex-direction: column; + gap: 4px; +} + +.drawer-field.check-field { + flex-direction: row; + align-items: center; + gap: 6px; + padding: 2px 0; +} + +.drawer-label { + font-size: 11px; font-weight: 600; - line-height: 1; + color: var(--text-secondary); } -.pdf-progress-track { +.drawer-select { width: 100%; - height: 10px; - background: var(--button-bg); - border: 1px solid var(--border-color); - border-radius: 999px; - overflow: hidden; + padding: 4px 6px; + border-radius: 4px; + border: 1px solid var(--fr-border); + background-color: var(--bg-color); + color: var(--text-color); + font-size: 12px; + outline: none; } -.pdf-progress-fill { - width: 0%; - height: 100%; - background: var(--accent-color); - border-radius: inherit; - transition: width 0.18s ease; +.drawer-checkbox { + margin: 0; + cursor: pointer; } -.pdf-progress-details { +.drawer-label-checkbox { + font-size: 12px; + color: var(--text-color); + cursor: pointer; +} + +.find-replace-actions-footer { display: flex; - flex-direction: column; gap: 6px; + padding: 8px 12px 12px 12px; + border-top: 1px solid var(--fr-border); + background-color: var(--header-bg); + border-bottom-left-radius: 11px; + border-bottom-right-radius: 11px; +} + +.find-replace-panel.docked .find-replace-actions-footer { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + +.fr-action-btn { + flex: 1; + padding: 6px 8px; font-size: 12px; - color: var(--text-secondary); + font-weight: 500; + border-radius: 6px; + border: 1px solid var(--fr-border); + background-color: var(--button-bg); + color: var(--text-color); + cursor: pointer; + transition: background-color 0.15s ease, border-color 0.15s ease; + text-align: center; } -.pdf-progress-detail { +.fr-action-btn:hover:not(:disabled) { + background-color: var(--button-hover); +} + +.fr-action-btn:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.fr-action-btn.secondary { + max-width: 60px; +} + +/* ======================================== + DIFF PREVIEW CONTAINER + ======================================== */ +.diff-preview-body { + padding: 16px; display: flex; - justify-content: space-between; + flex-direction: column; gap: 12px; } -.pdf-progress-detail strong { - color: var(--text-color); - font-weight: 600; +.diff-container { + border: 1px solid var(--fr-border); + border-radius: 8px; + background-color: var(--bg-color); + max-height: 400px; + overflow: auto; + font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; + font-size: 12px; + line-height: 1.5; } -.pdf-progress-actions { +.diff-line { display: flex; - justify-content: flex-end; + padding: 1px 8px; } -.tool-button.pdf-export-loading, -.mobile-menu-item.pdf-export-loading { +.diff-line.addition { + background-color: rgba(46, 160, 67, 0.15); + color: #3fb950; +} + +.diff-line.deletion { + background-color: rgba(248, 81, 73, 0.15); + color: #f85149; +} + +.diff-line.context { + color: var(--text-secondary); +} + +.diff-line-num { + width: 40px; + flex-shrink: 0; + text-align: right; + padding-right: 12px; + border-right: 1px solid var(--fr-border); + user-select: none; + opacity: 0.5; +} + +.diff-line-content { + padding-left: 12px; + white-space: pre-wrap; + word-break: break-all; +} + +/* ======================================== + DOCK LAYOUT CODES + ======================================== */ +.content-container { + display: flex; + flex: 1; + overflow: hidden; + position: relative; +} + +.editor-dock-wrapper { + display: flex; + flex: 1; + overflow: hidden; + position: relative; +} + +.editor-pane-inner { + display: flex; + flex-direction: column; + flex: 1; + position: relative; + overflow: hidden; +} + +/* ======================================== + MOBILE & TABLET FIND PANEL RESPONSIVE FIXES + ======================================== */ +@media (max-width: 1079px) { + #find-replace-dock { + display: none !important; + } +} + +@media (max-width: 768px) { + /* Prevent full screen expansion of floating panel on small mobile viewports */ + .find-replace-panel { + width: calc(100% - 24px) !important; + right: 12px !important; + left: 12px !important; + top: 80px !important; + } +} + +/* ======================================== + SKELETON LOADING SHIMMER SYSTEM + ======================================== */ +.skeleton-placeholder { + display: block; + background-color: var(--skeleton-bg); + border-radius: 6px; + position: relative; + overflow: hidden; + /* PERF-017: Removed skeleton-pulse; shimmer-only is sufficient and halves GPU compositing layers */ + /* animation: skeleton-pulse 2.2s cubic-bezier(0.4, 0, 0.2, 1) infinite alternate; */ +} + +.skeleton-placeholder::after { + content: ""; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + transform: translateX(-100%); + background-image: linear-gradient( + 90deg, + rgba(255, 255, 255, 0) 0%, + var(--skeleton-glow) 50%, + rgba(255, 255, 255, 0) 100% + ); + animation: skeleton-shimmer 1.6s cubic-bezier(0.4, 0, 0.2, 1) infinite; +} + +@keyframes skeleton-shimmer { + 100% { + transform: translateX(100%); + } +} + +@keyframes skeleton-pulse { + 0%, 100% { + opacity: 1; + } + 50% { + opacity: 0.82; + } +} + +.skeleton-circle { + width: 32px; + height: 32px; + border-radius: 50%; + margin: 0 auto; +} + +.skeleton-text { + height: 12px; + width: 80%; + margin: 4px auto; + border-radius: 3px; +} + +.skeleton-tree-folder { + height: 16px; + width: 140px; + margin: 6px 0; + display: inline-block; +} + +.skeleton-tree-file { + height: 14px; + width: 180px; + margin: 4px 0 4px 12px; + display: inline-block; +} + +/* Screen reader accessibility utility */ +.visually-hidden { + position: absolute !important; + width: 1px !important; + height: 1px !important; + padding: 0 !important; + margin: -1px !important; + overflow: hidden !important; + clip: rect(0, 0, 0, 0) !important; + clip-path: inset(50%) !important; + white-space: nowrap !important; + border: 0 !important; +} + +/* Article skeleton layout structures */ +.skeleton-title { + height: 28px; + width: 35%; + margin-bottom: 24px; + border-radius: 8px; +} + +.skeleton-subtitle { + height: 20px; + width: 20%; + margin-bottom: 18px; + margin-top: 32px; + border-radius: 6px; +} + +.skeleton-line { + height: 14px; + margin-bottom: 12px; + border-radius: 6px; +} + +/* Symmetrical dynamic widths */ +.skeleton-w90 { width: 90%; } +.skeleton-w92 { width: 92%; } +.skeleton-w88 { width: 88%; } +.skeleton-w85 { width: 85%; } +.skeleton-w60 { width: 60%; } +.skeleton-w45 { width: 45%; } + +/* Editor pane skeleton overlay */ +.editor-skeleton { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + padding: 30px 24px 24px calc(24px + var(--line-number-gutter)); + z-index: 10; pointer-events: none; + background: var(--editor-bg); + box-sizing: border-box; + overflow: hidden; + transition: opacity 0.3s ease; +} + +.editor-pane:not(.is-loading) .editor-skeleton { + display: none; +} + +.editor-pane.is-loading textarea { + opacity: 0; /* Completely hide editor content while initial bootstrap skeleton runs */ +} + +/* Preview pane skeleton container */ +.skeleton-preview-container { + display: block; + width: 100%; + box-sizing: border-box; + padding: 10px 4px; + background: transparent; + transition: opacity 0.3s ease; +} + +/* Mermaid compilation loading states */ +.mermaid-container.is-loading { + min-height: 180px; + background-color: var(--skeleton-bg); + border-radius: 8px; + border: 1px solid var(--border-color); + position: relative; + overflow: hidden; + animation: skeleton-pulse 2.2s cubic-bezier(0.4, 0, 0.2, 1) infinite alternate; +} + +.mermaid-container.is-loading .mermaid { + opacity: 0; /* Hide raw chart source code during compile */ } -/* ======================================== - RESET MODAL FORM FIELDS - ======================================== */ - -.reset-modal-field { - display: flex; - flex-direction: column; - gap: 6px; - text-align: left; -} - -.reset-modal-field-group { - display: flex; - flex-direction: column; - gap: 12px; -} - -.reset-modal-label { - font-size: 12px; - color: var(--text-secondary, #57606a); - font-weight: 600; -} - -.reset-modal-toggle-group { - display: flex; - flex-direction: column; - gap: 8px; -} - -.reset-modal-option { - display: flex; - align-items: center; - gap: 8px; - font-size: 13px; - color: var(--text-color); -} - -.reset-modal-option input { - margin: 0; -} - -/* ======================================== - RENAME MODAL INPUT - ======================================== */ - -.rename-modal-input { - width: 100%; - padding: 7px 10px; - border-radius: 6px; - border: 1px solid var(--border-color); - background: var(--bg-color); - color: var(--text-color); - font-size: 13px; - outline: none; - box-sizing: border-box; -} - -.rename-modal-input:focus { - border-color: var(--accent-color); -} - -/* ======================================== - TOOLBAR POPUP PANELS - ======================================== */ - -.reset-modal-box--xl { - width: min(94vw, 980px); - max-width: 980px; -} - -.modal-empty { - margin: 0; - font-size: 12px; - color: var(--text-secondary, #57606a); - text-align: center; -} - -.emoji-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); - gap: 12px; - max-height: min(52vh, 440px); - overflow: auto; - padding: 4px; -} - -.symbol-grid { - display: flex; - flex-direction: column; - gap: 16px; - max-height: min(52vh, 440px); - overflow: auto; - padding: 4px 2px; -} - -.symbol-section-title { - margin: 0; - font-size: 11px; - text-transform: uppercase; - letter-spacing: 0.08em; - color: var(--text-secondary, #57606a); -} - -.symbol-section-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); - gap: 12px; -} - -.alert-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); - gap: 12px; - max-height: min(45vh, 360px); - overflow: auto; - padding: 2px; -} - -.emoji-item, -.symbol-item, -.alert-option { - display: flex; - flex-direction: column; - gap: 8px; - align-items: center; - border: 1px solid var(--border-color); - border-radius: 10px; - padding: 10px; - background: var(--bg-color); - color: var(--text-color); - cursor: pointer; - transition: border-color 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease; -} - -.emoji-item:focus-visible, -.symbol-item:focus-visible, -.alert-option:focus-visible { - outline: 2px solid var(--accent-color); - outline-offset: 2px; -} - -.emoji-item.is-selected, -.symbol-item.is-selected, -.alert-option.is-selected { - border-color: var(--accent-color); - box-shadow: 0 0 0 2px rgba(88, 166, 255, 0.2); - background-color: rgba(88, 166, 255, 0.08); -} - -.emoji-preview { - width: 36px; - height: 36px; - display: flex; - align-items: center; - justify-content: center; -} - -.emoji-preview img { - width: 32px; - height: 32px; -} - -.emoji-shortcode { - display: flex; - align-items: center; - gap: 6px; - font-size: 12px; - color: var(--text-secondary, #57606a); - text-align: center; -} - -.emoji-copy-btn, -.symbol-copy-btn { - border: none; - background: transparent; - color: var(--text-secondary, #57606a); - cursor: pointer; - padding: 2px; - border-radius: 4px; -} - -.emoji-copy-btn:hover, -.symbol-copy-btn:hover { - color: var(--text-color); - background: var(--button-hover); -} - -.emoji-copy-btn.is-copied, -.symbol-copy-btn.is-copied { - color: var(--accent-color); -} - -.symbol-preview { - font-size: 28px; - line-height: 1; -} - -.symbol-code { - display: flex; - align-items: center; - gap: 6px; - font-size: 12px; - color: var(--text-secondary, #57606a); -} - -.alert-option { - align-items: stretch; - text-align: left; - padding: 12px; -} - -.alert-preview { - margin: 0; -} - -.alert-preview .markdown-alert { - padding: 0.5rem 0.9rem; - border-left: 0.25em solid; - border-radius: 0.375rem; -} - -.alert-preview .markdown-alert-title { - margin: 0 0 6px; - font-weight: 600; - line-height: 1.25; - display: flex; - align-items: center; - gap: 8px; -} - -.alert-preview .markdown-alert-icon { - display: inline-flex; - width: 16px; - height: 16px; -} - -.alert-preview .markdown-alert-icon svg { - width: 16px; - height: 16px; - fill: currentColor; -} - -.alert-preview .markdown-alert > *:not(.markdown-alert-title) { - color: var(--text-color); -} - -.alert-preview .markdown-alert-note { - color: #0969da; - border-left-color: #0969da; - background-color: #ddf4ff; -} - -.alert-preview .markdown-alert-tip { - color: #1a7f37; - border-left-color: #1a7f37; - background-color: #dafbe1; -} - -.alert-preview .markdown-alert-important { - color: #8250df; - border-left-color: #8250df; - background-color: #fbefff; -} - -.alert-preview .markdown-alert-warning { - color: #9a6700; - border-left-color: #9a6700; - background-color: #fff8c5; -} - -.alert-preview .markdown-alert-caution { - color: #cf222e; - border-left-color: #cf222e; - background-color: #ffebe9; -} - -[data-theme="dark"] .alert-preview .markdown-alert-note { - color: #4493f8; - border-left-color: #4493f8; - background-color: rgba(31, 111, 235, 0.15); -} - -[data-theme="dark"] .alert-preview .markdown-alert-tip { - color: #3fb950; - border-left-color: #3fb950; - background-color: rgba(35, 134, 54, 0.15); -} - -[data-theme="dark"] .alert-preview .markdown-alert-important { - color: #ab7df8; - border-left-color: #ab7df8; - background-color: rgba(137, 87, 229, 0.15); -} - -[data-theme="dark"] .alert-preview .markdown-alert-warning { - color: #d29922; - border-left-color: #d29922; - background-color: rgba(210, 153, 34, 0.18); -} - -[data-theme="dark"] .alert-preview .markdown-alert-caution { - color: #f85149; - border-left-color: #f85149; - background-color: rgba(248, 81, 73, 0.18); -} - -.github-import-error { - margin: 0; - font-size: 12px; - color: var(--color-danger-fg, #d73a49); - text-align: left; - line-height: 1.5; -} - -.github-import-error.is-info { - color: var(--text-secondary, #57606a); -} - -#github-import-modal .reset-modal-box { - width: 60vw; - max-width: 60vw; - min-width: 340px; - padding: 30px 34px; - gap: 16px; - box-shadow: 0 20px 48px rgba(0, 0, 0, 0.22); -} - -#github-import-modal .reset-modal-message { - font-size: 18px; - line-height: 1.35; - text-align: left; -} - -#github-import-url, -#github-import-file-select { - min-height: 46px; - padding: 10px 12px; - font-size: 15px; -} - -#github-import-file-select { - min-height: 180px; -} - -.github-import-tree { - max-height: 420px; - overflow: auto; - border: 1px solid var(--border-color); - border-radius: 10px; - padding: 12px; - background: var(--bg-color); -} - -.github-import-selection-toolbar { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; - padding: 10px 12px; - border: 1px solid var(--border-color); - border-radius: 8px; - background: var(--button-bg); -} - -.github-import-selected-count { - font-size: 14px; - font-weight: 600; - color: var(--text-color); -} - -.github-import-tree ul { - list-style: none; - margin: 0; - padding-left: 18px; -} - -.github-import-tree > ul { - padding-left: 4px; -} - -.github-import-tree li { - margin: 2px 0; -} - -.github-tree-folder-label { - display: inline-block; - font-size: 14px; - color: var(--text-secondary, #57606a); - margin-bottom: 4px; -} - -.github-tree-file-btn { - border: 0; - background: transparent; - color: var(--text-color); - cursor: pointer; - padding: 6px 8px; - border-radius: 6px; - text-align: left; - width: 100%; - font-size: 14px; -} - -.github-tree-file-btn:hover, -.github-tree-file-btn:focus-visible { - background: var(--button-hover); - outline: none; -} - -.github-tree-file-btn.is-selected { - background: rgba(56, 139, 253, 0.14); - color: var(--accent-color); -} - -#github-import-modal .reset-modal-actions { - gap: 12px; -} - -#github-import-modal .reset-modal-btn { - min-height: 42px; - padding: 9px 18px; - font-size: 14px; -} - -@media (max-width: 576px) { - #github-import-modal .reset-modal-box { - width: 95vw; - max-width: 95vw; - min-width: 0; - padding: 20px; - gap: 14px; - } - - .github-import-selection-toolbar { - flex-direction: column; - align-items: stretch; - } - - #github-import-modal .reset-modal-message { - font-size: 16px; - } - - #github-import-modal .reset-modal-actions { - flex-direction: column-reverse; - } - - #github-import-modal .reset-modal-btn { - width: 100%; - } -} - -.frontmatter-table { - border-collapse: collapse; - margin-bottom: 1.5em; - font-size: 0.9em; - width: auto; - max-width: 100%; -} - -.frontmatter-table th, -.frontmatter-table td { - border: 1px solid var(--border-color); - padding: 6px 13px; - vertical-align: top; - color: var(--text-color); -} - -.frontmatter-table tr:nth-child(odd) th, -.frontmatter-table tr:nth-child(odd) td { - background-color: var(--table-bg); -} - -.frontmatter-table tr:nth-child(even) th, -.frontmatter-table tr:nth-child(even) td { - background-color: var(--editor-bg); -} - -.frontmatter-table th { - font-weight: 600; - text-align: right; - white-space: nowrap; - vertical-align: middle; -} - -.frontmatter-table td { - text-align: left; -} - -.fm-complex { - margin: 0; - padding: 4px 6px; - font-size: 0.8em; - font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; - white-space: pre-wrap; - word-break: break-word; - background: transparent; - border: none; - color: var(--text-color); -} - -.fm-tag { - display: inline-block; - padding: 2px 8px; - margin: 2px 3px 2px 0; - border: 1px solid var(--border-color); - border-radius: 2em; - font-size: 0.8em; - font-weight: 500; - color: var(--accent-color); - background-color: var(--button-bg); - white-space: nowrap; -} - -/* ======================================== - RTL SUPPORT - ======================================== */ - -[dir="rtl"] body { - direction: rtl; -} - -[dir="rtl"] .editor-pane { - padding-left: 0px; - padding-right: 20px; - border-right: none; - border-left: 1px solid var(--border-color); -} - -[dir="rtl"] #markdown-editor, -[dir="rtl"] .markdown-body { - direction: rtl; - text-align: right; -} - -[dir="rtl"] .markdown-body pre, -[dir="rtl"] .markdown-body code, -[dir="rtl"] .fm-complex { - direction: ltr; - text-align: left; -} - -[dir="rtl"] .line-numbers { - left: auto; - right: 20px; - padding: 10px 0 10px 8px; - text-align: left; - border-right: none; - border-left: 1px solid var(--border-color); -} - -[dir="rtl"] #markdown-editor { - padding-left: 10px; - padding-right: calc(10px + var(--line-number-gutter)); -} - -[dir="rtl"] .editor-highlight-layer { - inset: 20px calc(20px + var(--line-number-gutter)) 20px 0; -} - -[dir="rtl"] .mobile-menu-item, -[dir="rtl"] .tab-menu-item, -[dir="rtl"] .modal-header .reset-modal-message, -[dir="rtl"] .reset-modal-field, -[dir="rtl"] .alert-option, -[dir="rtl"] .github-import-error, -[dir="rtl"] #github-import-modal .reset-modal-message, -[dir="rtl"] .github-tree-file-btn, -[dir="rtl"] .frontmatter-table td { - text-align: right; -} - -[dir="rtl"] .github-import-tree ul { - padding-left: 0; - padding-right: 18px; -} - -[dir="rtl"] .github-import-tree > ul { - padding-right: 4px; -} - -[dir="rtl"] .markdown-body .markdown-alert, -[dir="rtl"] .alert-preview .markdown-alert { - border-left: 0; - border-right: 0.25em solid currentColor; -} - -/* ============================================ - SHARE MODAL - ============================================ */ - -.share-modal-description { - font-size: 13px; - color: var(--text-secondary, #57606a); - margin: 0; -} - -.share-mode-cards { - display: flex; - flex-direction: column; - gap: 8px; -} - -.share-mode-card { - display: flex; - align-items: center; - gap: 12px; - padding: 12px 14px; - border-radius: 8px; - border: 1px solid var(--border-color); - background: var(--bg-color); - cursor: pointer; - transition: border-color 0.15s ease, background-color 0.15s ease; - user-select: none; -} - -.share-mode-card:hover { - border-color: var(--accent-color); - background: var(--button-hover); -} - -.share-mode-card.is-selected { - border-color: var(--accent-color); - background: color-mix(in srgb, var(--accent-color) 8%, transparent); -} - -.share-mode-card input[type="radio"] { - display: none; -} - -.share-card-icon { - font-size: 18px; - width: 28px; - text-align: center; - color: var(--text-secondary, #57606a); - flex-shrink: 0; -} - -.share-mode-card.is-selected .share-card-icon { - color: var(--accent-color); -} - -.share-card-body { - display: flex; - flex-direction: column; - gap: 2px; - flex: 1; - min-width: 0; -} - -.share-card-title { - font-size: 13px; - font-weight: 600; - color: var(--text-color); -} - -.share-card-desc { - font-size: 12px; - color: var(--text-secondary, #57606a); -} - -.share-card-check { - width: 18px; - text-align: center; - color: var(--accent-color); - opacity: 0; - transition: opacity 0.15s ease; - flex-shrink: 0; -} - -.share-mode-card.is-selected .share-card-check { - opacity: 1; -} - -.share-url-row { - display: flex; - gap: 8px; - align-items: center; -} - -.share-url-input { - flex: 1; - font-size: 12px; - font-family: var(--font-mono, monospace); - color: var(--text-secondary, #57606a); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.share-copy-btn { - flex-shrink: 0; - padding: 6px 10px; -} - -.share-copy-btn:disabled { - opacity: 0.5; - cursor: not-allowed; -} - -.share-modal-notice { - font-size: 11px; - color: var(--text-secondary, #57606a); - margin: 0; - display: flex; - align-items: center; - gap: 5px; -} - -/* ========================================================================== - Multilingual & CJK Optimization styles added by Aegis SEO agency - ========================================================================== */ -.lang-select-item { - display: flex !important; - align-items: center; - gap: 8px; - cursor: pointer; - transition: background-color 0.2s ease, padding-left 0.2s ease; -} - -.lang-select-item:hover { - padding-left: 12px; -} - -.lang-select-item.active { - background-color: var(--accent-color) !important; - color: #ffffff !important; - font-weight: 600; -} - -/* Adjust CJK text layout for maximum readability inside the preview pane */ -html[lang="zh"] .markdown-body, -html[lang="ja"] .markdown-body, -html[lang="ko"] .markdown-body { - line-height: 1.75 !important; - letter-spacing: 0.03em; - word-break: keep-all; - overflow-wrap: break-word; - text-align: justify; -} - -/* Specific heading spacing improvements for CJK characters */ -html[lang="zh"] .markdown-body h1, html[lang="zh"] .markdown-body h2, html[lang="zh"] .markdown-body h3, -html[lang="ja"] .markdown-body h1, html[lang="ja"] .markdown-body h2, html[lang="ja"] .markdown-body h3, -html[lang="ko"] .markdown-body h1, html[lang="ko"] .markdown-body h2, html[lang="ko"] .markdown-body h3 { - font-weight: 700; - letter-spacing: 0.02em; - margin-top: 1.4em; - margin-bottom: 0.6em; -} - -/* Smooth fade and scale transition for dropdown active states */ -.dropdown-menu { - opacity: 0; - transform: translateY(8px) scale(0.98); - display: block; - visibility: hidden; - transition: opacity 0.2s cubic-bezier(0.16, 1, 0.3, 1), transform 0.2s cubic-bezier(0.16, 1, 0.3, 1), visibility 0.2s; -} - -.dropdown-menu.show { - opacity: 1; - transform: translateY(0) scale(1); - visibility: visible; -} - -/* ======================================== - FIND & REPLACE FLOATING PANEL DESIGN - ======================================== */ - -.find-replace-panel { - position: fixed; - top: 100px; - right: 20px; - width: 340px; - background-color: var(--fr-bg); - border: 1px solid var(--fr-border); - border-radius: 12px; - box-shadow: var(--fr-shadow); - z-index: 1050; - display: flex; - flex-direction: column; - backdrop-filter: blur(10px); - -webkit-backdrop-filter: blur(10px); - transition: opacity 0.2s ease, transform 0.2s ease; - user-select: none; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; -} - -.find-replace-panel.docked { - position: relative; - top: 0 !important; - right: 0 !important; - height: 100%; - border-radius: 0; - border-top: none; - border-bottom: none; - border-right: none; - border-left: 1px solid var(--fr-border); - box-shadow: none; - backdrop-filter: none; - z-index: 10; - flex-shrink: 0; -} - -.find-replace-panel.docked #find-replace-reset, -.find-replace-panel.docked #find-replace-reset-footer { - display: none !important; -} - -.find-replace-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 8px 12px; - border-bottom: 1px solid var(--fr-border); - cursor: move; - background-color: var(--header-bg); - border-top-left-radius: 11px; - border-top-right-radius: 11px; -} - -.find-replace-panel.docked .find-replace-header { - cursor: default; - border-top-left-radius: 0; - border-top-right-radius: 0; -} - -.find-replace-title { - font-size: 13px; - font-weight: 600; - color: var(--text-color); -} - -.find-replace-header-actions { - display: flex; - gap: 4px; -} - -.panel-icon-btn { - background: none; - border: none; - color: var(--text-color); - font-size: 12px; - cursor: pointer; - padding: 2px 6px; - border-radius: 4px; - display: flex; - align-items: center; - justify-content: center; - transition: background-color 0.15s ease; -} - -.panel-icon-btn:hover { - background-color: var(--button-hover); -} - -.find-replace-body { - padding: 12px; - display: flex; - flex-direction: column; - gap: 8px; -} - -.find-replace-field-row { - display: flex; - flex-direction: column; - position: relative; -} - -.find-input-container, .replace-input-container { - display: flex; - align-items: center; - border: 1px solid var(--fr-border); - border-radius: 6px; - background-color: var(--bg-color); - padding: 2px 4px; - width: 100%; -} - -.find-input-container:focus-within, .replace-input-container:focus-within { - border-color: var(--accent-color); - box-shadow: 0 0 0 3px rgba(9, 105, 218, 0.15); -} - -.find-input-field { - flex: 1; - border: none; - background: transparent; - color: var(--text-color); - font-size: 13px; - padding: 4px 6px; - outline: none; - width: 50%; -} - -.find-options-group { - display: flex; - gap: 2px; -} - -.find-option-btn { - background: none; - border: none; - color: var(--text-secondary); - font-size: 11px; - font-weight: 600; - cursor: pointer; - padding: 2px 5px; - border-radius: 4px; - transition: background-color 0.12s ease, color 0.12s ease; - min-width: 22px; - height: 22px; - display: inline-flex; - align-items: center; - justify-content: center; -} - -.find-option-btn:hover { - background-color: var(--button-hover); - color: var(--text-color); -} - -.find-option-btn.active { - background-color: var(--fr-btn-active-bg); - color: var(--fr-btn-active); -} - -.find-error-drawer { - background-color: var(--fr-error-bg); - border: 1px solid var(--fr-error-border); - border-radius: 6px; - padding: 6px 10px; - font-size: 11px; - color: var(--fr-text-danger); - line-height: 1.3; -} - -.find-replace-meta-row { - display: flex; - align-items: center; - justify-content: space-between; - padding: 2px 4px; -} - -.find-match-count { - font-size: 12px; - color: var(--text-secondary); -} - -.find-nav-group { - display: flex; - gap: 4px; -} - -.find-nav-arrow-btn { - background: none; - border: 1px solid var(--fr-border); - color: var(--text-color); - font-size: 12px; - cursor: pointer; - padding: 2px 8px; - border-radius: 4px; - transition: background-color 0.15s ease; - display: flex; - align-items: center; - justify-content: center; -} - -.find-nav-arrow-btn:hover:not(:disabled) { - background-color: var(--button-hover); -} - -.find-nav-arrow-btn:disabled { - opacity: 0.4; - cursor: not-allowed; -} - -.find-drawer-toggle-row { - border-top: 1px solid var(--fr-border); - margin-top: 4px; - padding-top: 6px; -} - -.drawer-toggle-btn { - background: none; - border: none; - color: var(--text-secondary); - font-size: 12px; - cursor: pointer; - display: flex; - align-items: center; - padding: 2px 4px; - border-radius: 4px; - transition: color 0.15s ease; -} - -.drawer-toggle-btn:hover { - color: var(--text-color); -} - -.find-replace-drawer-content { - display: flex; - flex-direction: column; - gap: 8px; - padding: 4px 6px; - border-top: 1px dashed var(--fr-border); - margin-top: 2px; - padding-top: 8px; -} - -.drawer-field { - display: flex; - flex-direction: column; - gap: 4px; -} - -.drawer-field.check-field { - flex-direction: row; - align-items: center; - gap: 6px; - padding: 2px 0; -} - -.drawer-label { - font-size: 11px; - font-weight: 600; - color: var(--text-secondary); -} - -.drawer-select { - width: 100%; - padding: 4px 6px; - border-radius: 4px; - border: 1px solid var(--fr-border); - background-color: var(--bg-color); - color: var(--text-color); - font-size: 12px; - outline: none; -} - -.drawer-checkbox { - margin: 0; - cursor: pointer; -} - -.drawer-label-checkbox { - font-size: 12px; - color: var(--text-color); - cursor: pointer; -} - -.find-replace-actions-footer { - display: flex; - gap: 6px; - padding: 8px 12px 12px 12px; - border-top: 1px solid var(--fr-border); - background-color: var(--header-bg); - border-bottom-left-radius: 11px; - border-bottom-right-radius: 11px; -} - -.find-replace-panel.docked .find-replace-actions-footer { - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; -} - -.fr-action-btn { - flex: 1; - padding: 6px 8px; - font-size: 12px; - font-weight: 500; - border-radius: 6px; - border: 1px solid var(--fr-border); - background-color: var(--button-bg); - color: var(--text-color); - cursor: pointer; - transition: background-color 0.15s ease, border-color 0.15s ease; - text-align: center; -} - -.fr-action-btn:hover:not(:disabled) { - background-color: var(--button-hover); -} - -.fr-action-btn:disabled { - opacity: 0.5; - cursor: not-allowed; -} - -.fr-action-btn.secondary { - max-width: 60px; -} - -/* ======================================== - DIFF PREVIEW CONTAINER - ======================================== */ -.diff-preview-body { - padding: 16px; - display: flex; - flex-direction: column; - gap: 12px; -} - -.diff-container { - border: 1px solid var(--fr-border); - border-radius: 8px; - background-color: var(--bg-color); - max-height: 400px; - overflow: auto; - font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; - font-size: 12px; - line-height: 1.5; -} - -.diff-line { - display: flex; - padding: 1px 8px; -} - -.diff-line.addition { - background-color: rgba(46, 160, 67, 0.15); - color: #3fb950; -} - -.diff-line.deletion { - background-color: rgba(248, 81, 73, 0.15); - color: #f85149; -} - -.diff-line.context { - color: var(--text-secondary); -} - -.diff-line-num { - width: 40px; - flex-shrink: 0; - text-align: right; - padding-right: 12px; - border-right: 1px solid var(--fr-border); - user-select: none; - opacity: 0.5; -} - -.diff-line-content { - padding-left: 12px; - white-space: pre-wrap; - word-break: break-all; -} - -/* ======================================== - DOCK LAYOUT CODES - ======================================== */ -.content-container { - display: flex; - flex: 1; - overflow: hidden; - position: relative; -} - -.editor-dock-wrapper { - display: flex; - flex: 1; - overflow: hidden; - position: relative; -} - -.editor-pane-inner { - display: flex; - flex-direction: column; - flex: 1; - position: relative; - overflow: hidden; -} - -/* ======================================== - MOBILE & TABLET FIND PANEL RESPONSIVE FIXES - ======================================== */ -@media (max-width: 1079px) { - #find-replace-dock { - display: none !important; - } -} - -@media (max-width: 768px) { - /* Prevent full screen expansion of floating panel on small mobile viewports */ - .find-replace-panel { - width: calc(100% - 24px) !important; - right: 12px !important; - left: 12px !important; - top: 80px !important; - } -} - -/* ======================================== - SKELETON LOADING SHIMMER SYSTEM - ======================================== */ -.skeleton-placeholder { - display: block; - background-color: var(--skeleton-bg); - border-radius: 6px; - position: relative; - overflow: hidden; - /* PERF-017: Removed skeleton-pulse; shimmer-only is sufficient and halves GPU compositing layers */ - /* animation: skeleton-pulse 2.2s cubic-bezier(0.4, 0, 0.2, 1) infinite alternate; */ -} - -.skeleton-placeholder::after { - content: ""; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - transform: translateX(-100%); - background-image: linear-gradient( - 90deg, - rgba(255, 255, 255, 0) 0%, - var(--skeleton-glow) 50%, - rgba(255, 255, 255, 0) 100% - ); - animation: skeleton-shimmer 1.6s cubic-bezier(0.4, 0, 0.2, 1) infinite; -} - -@keyframes skeleton-shimmer { - 100% { - transform: translateX(100%); - } -} - -@keyframes skeleton-pulse { - 0%, 100% { - opacity: 1; - } - 50% { - opacity: 0.82; - } -} - -.skeleton-circle { - width: 32px; - height: 32px; - border-radius: 50%; - margin: 0 auto; -} - -.skeleton-text { - height: 12px; - width: 80%; - margin: 4px auto; - border-radius: 3px; -} - -.skeleton-tree-folder { - height: 16px; - width: 140px; - margin: 6px 0; - display: inline-block; -} - -.skeleton-tree-file { - height: 14px; - width: 180px; - margin: 4px 0 4px 12px; - display: inline-block; -} - -/* Screen reader accessibility utility */ -.visually-hidden { - position: absolute !important; - width: 1px !important; - height: 1px !important; - padding: 0 !important; - margin: -1px !important; - overflow: hidden !important; - clip: rect(0, 0, 0, 0) !important; - clip-path: inset(50%) !important; - white-space: nowrap !important; - border: 0 !important; -} - -/* Article skeleton layout structures */ -.skeleton-title { - height: 28px; - width: 35%; - margin-bottom: 24px; - border-radius: 8px; -} - -.skeleton-subtitle { - height: 20px; - width: 20%; - margin-bottom: 18px; - margin-top: 32px; - border-radius: 6px; -} - -.skeleton-line { - height: 14px; - margin-bottom: 12px; - border-radius: 6px; -} - -/* Symmetrical dynamic widths */ -.skeleton-w90 { width: 90%; } -.skeleton-w92 { width: 92%; } -.skeleton-w88 { width: 88%; } -.skeleton-w85 { width: 85%; } -.skeleton-w60 { width: 60%; } -.skeleton-w45 { width: 45%; } - -/* Editor pane skeleton overlay */ -.editor-skeleton { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - padding: 30px 24px 24px calc(24px + var(--line-number-gutter)); - z-index: 10; - pointer-events: none; - background: var(--editor-bg); - box-sizing: border-box; - overflow: hidden; - transition: opacity 0.3s ease; -} - -.editor-pane:not(.is-loading) .editor-skeleton { - display: none; -} - -.editor-pane.is-loading textarea { - opacity: 0; /* Completely hide editor content while initial bootstrap skeleton runs */ -} - -/* Preview pane skeleton container */ -.skeleton-preview-container { - display: block; - width: 100%; - box-sizing: border-box; - padding: 10px 4px; - background: transparent; - transition: opacity 0.3s ease; -} - -/* Mermaid compilation loading states */ -.mermaid-container.is-loading { - min-height: 180px; - background-color: var(--skeleton-bg); - border-radius: 8px; - border: 1px solid var(--border-color); - position: relative; - overflow: hidden; - animation: skeleton-pulse 2.2s cubic-bezier(0.4, 0, 0.2, 1) infinite alternate; -} - -.mermaid-container.is-loading .mermaid { - opacity: 0; /* Hide raw chart source code during compile */ -} - -.mermaid-container.is-loading::after { - content: ""; - position: absolute; - inset: 0; - transform: translateX(-100%); - background-image: linear-gradient( - 90deg, - rgba(255, 255, 255, 0) 0%, - var(--skeleton-glow) 50%, - rgba(255, 255, 255, 0) 100% - ); - animation: skeleton-shimmer 1.6s cubic-bezier(0.4, 0, 0.2, 1) infinite; -} - -/* Accessibility: respect user's motion preferences */ -@media (prefers-reduced-motion: reduce) { - .skeleton-placeholder, - .skeleton-placeholder::after, - .mermaid-container.is-loading, - .mermaid-container.is-loading::after { - animation: none; - } - .drag-overlay-inner { - animation: none; - } - .tab-item-new { - animation: none; - } - body, - .app-header, - .editor-pane, - .preview-pane, - .tool-button, - .markdown-tool-btn { - transition: none; - } -} - \ No newline at end of file + +.mermaid-container.is-loading::after { + content: ""; + position: absolute; + inset: 0; + transform: translateX(-100%); + background-image: linear-gradient( + 90deg, + rgba(255, 255, 255, 0) 0%, + var(--skeleton-glow) 50%, + rgba(255, 255, 255, 0) 100% + ); + animation: skeleton-shimmer 1.6s cubic-bezier(0.4, 0, 0.2, 1) infinite; +} + +/* Accessibility: respect user's motion preferences */ +@media (prefers-reduced-motion: reduce) { + .skeleton-placeholder, + .skeleton-placeholder::after, + .mermaid-container.is-loading, + .mermaid-container.is-loading::after { + animation: none; + } + .drag-overlay-inner { + animation: none; + } + .tab-item-new { + animation: none; + } + body, + .app-header, + .editor-pane, + .preview-pane, + .tool-button, + .markdown-tool-btn { + transition: none; + } +} + +/* ======================================== + BROWSER PRINT STYLES + ======================================== */ +@media print { + body * { + visibility: hidden; + } + #markdown-preview, #markdown-preview * { + visibility: visible; + } + #markdown-preview { + position: absolute; + left: 0; + top: 0; + width: 100% !important; + height: auto !important; + margin: 0 !important; + padding: 0 !important; + overflow: visible !important; + box-shadow: none !important; + border: none !important; + background: transparent !important; + } + .preview-pane { + position: static !important; + width: 100% !important; + height: auto !important; + overflow: visible !important; + margin: 0 !important; + padding: 0 !important; + box-shadow: none !important; + border: none !important; + background: transparent !important; + } + .content-container { + display: block !important; + position: static !important; + width: 100% !important; + height: auto !important; + overflow: visible !important; + } + header, .tab-bar, .markdown-format-toolbar, .editor-pane, .resize-divider, #line-numbers, .pdf-progress-overlay { + display: none !important; + } +} \ No newline at end of file diff --git a/script.js b/script.js index 4ddda0b6..7cbfd9bd 100644 --- a/script.js +++ b/script.js @@ -7964,18 +7964,51 @@ document.addEventListener("DOMContentLoaded", function () { return Promise.all(promises); } - // ============================================ - // End Oversized Graphics Scaling Functions - // ============================================ + function showLargePdfExportDialog(onChoosePrint, onChooseCanvas) { + const dialogOverlay = document.createElement("div"); + dialogOverlay.className = "reset-modal-overlay"; + dialogOverlay.style.display = "flex"; + dialogOverlay.setAttribute("role", "dialog"); + dialogOverlay.setAttribute("aria-modal", "true"); + + dialogOverlay.innerHTML = ` +
+

Large Document Detected

+

+ This document is very large. Generating a canvas-based PDF can take a long time and might cause browser lagging. +

+ We recommend using the Browser Print Dialog (select 'Save as PDF' as the destination). It is instant, uses vector graphics for perfectly sharp text, and has zero document size limits. +

+
+ + + +
+
+ `; - exportPdf.addEventListener("click", async function (event) { - event.preventDefault(); - logPdfExportDebug("PDF export button clicked!"); - if (activePdfExport) { - logPdfExportDebug("PDF export already active, ignoring click"); - return; - } + document.body.appendChild(dialogOverlay); + const cleanup = () => { + dialogOverlay.remove(); + }; + + dialogOverlay.querySelector("#large-pdf-cancel").addEventListener("click", () => { + cleanup(); + }); + + dialogOverlay.querySelector("#large-pdf-canvas").addEventListener("click", () => { + cleanup(); + onChooseCanvas(); + }); + + dialogOverlay.querySelector("#large-pdf-print").addEventListener("click", () => { + cleanup(); + onChoosePrint(); + }); + } + + async function startCanvasPdfExport() { const progressState = createPdfProgressState(); activePdfExport = progressState; setPdfExportTriggersBusy(progressState, true); @@ -8237,6 +8270,32 @@ document.addEventListener("DOMContentLoaded", function () { } finally { cleanupPdfExport(progressState); } + } + + exportPdf.addEventListener("click", async function (event) { + event.preventDefault(); + logPdfExportDebug("PDF export button clicked!"); + if (activePdfExport) { + logPdfExportDebug("PDF export already active, ignoring click"); + return; + } + + const markdown = markdownEditor.value; + // Set a threshold of 30,000 characters for large documents + if (markdown.length > 30000) { + showLargePdfExportDialog( + () => { + // Choice: Browser Print + window.print(); + }, + () => { + // Choice: Canvas rendering + startCanvasPdfExport(); + } + ); + } else { + startCanvasPdfExport(); + } }); copyMarkdownButton.addEventListener("click", function () { diff --git a/styles.css b/styles.css index aafd5a8a..c0c8401f 100644 --- a/styles.css +++ b/styles.css @@ -1,3873 +1,3918 @@ -:root { - --bg-color: #ffffff; - --editor-bg: #f6f8fa; - --preview-bg: #ffffff; /* Preview background for light mode */ - --text-color: #24292e; - --text-secondary: #57606a; - --font-mono: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace; - --color-danger-fg: #d73a49; - --preview-text-color: #24292e; /* Text color for preview in light mode */ - --border-color: #e1e4e8; - --header-bg: #f6f8fa; - --button-bg: #f6f8fa; - --button-hover: #e1e4e8; - --button-active: #d1d5da; - --scrollbar-thumb: #c1c1c1; - --scrollbar-track: #f1f1f1; - --accent-color: #0366d6; - --table-bg: #ffffff; /* Table background for light mode */ - --code-bg: #f6f8fa; /* Code block background for light mode */ - --skeleton-bg: #e2e8f0; - --skeleton-glow: rgba(255, 255, 255, 0.65); - - /* Find & Replace Panel custom properties (PERF-010 consolidated) */ - --fr-bg: rgba(255, 255, 255, 0.95); - --fr-border: #d0d7de; - --fr-shadow: 0 8px 24px rgba(140, 149, 159, 0.2); - --fr-btn-active: #0969da; - --fr-btn-active-bg: #ddf4ff; - --fr-match-highlight: #ffdf5d; - --fr-match-active: #ff9b30; - --fr-match-text-color: #24292e; - --fr-match-active-text-color: #24292e; - --fr-error-bg: #ffebe9; - --fr-error-border: #ff8577; - --fr-text-danger: #cf222e; -} - -[data-theme="dark"] { - --bg-color: #0d1117; - --editor-bg: #161b22; - --preview-bg: #0d1117; /* Preview background for dark mode */ - --text-color: #c9d1d9; - --text-secondary: #8b949e; - --color-danger-fg: #f85149; - --preview-text-color: #c9d1d9; /* Text color for preview in dark mode */ - --border-color: #30363d; - --header-bg: #161b22; - --button-bg: #21262d; - --button-hover: #30363d; - --button-active: #3b434b; - --scrollbar-thumb: #484f58; - --scrollbar-track: #21262d; - --accent-color: #58a6ff; - --table-bg: #161b22; /* Table background for dark mode */ - --code-bg: #161b22; /* Code block background for dark mode */ - --skeleton-bg: #2d3139; - --skeleton-glow: rgba(255, 255, 255, 0.08); - - /* Find & Replace Panel custom properties for dark mode */ - --fr-bg: rgba(28, 33, 40, 0.98); - --fr-border: #444c56; - --fr-shadow: 0 8px 24px rgba(0, 0, 0, 0.5); - --fr-btn-active: #2f81f7; - --fr-btn-active-bg: rgba(56, 139, 253, 0.15); - --fr-match-highlight: rgba(187, 128, 9, 0.4); - --fr-match-active: #ad6200; - --fr-match-text-color: #c9d1d9; - --fr-match-active-text-color: #ffffff; - --fr-error-bg: rgba(248, 81, 73, 0.1); - --fr-error-border: rgba(248, 81, 73, 0.4); - --fr-text-danger: #ff7b72; -} - -* { - box-sizing: border-box; - margin: 0; - padding: 0; -} - -@media (min-width: 768px) { - html, - body { - height: 100%; - overflow: hidden; - } -} - -body { - background-color: var(--bg-color); - color: var(--text-color); - /* PERF-021: Removed background-color transition to avoid full-viewport repaint on theme toggle */ - transition: color 0.15s ease; - min-height: 100vh; - font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Hiragino Kaku Gothic ProN", Meiryo, "Malgun Gothic", "Apple SD Gothic Neo", "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; -} - -.app-header { - background-color: var(--header-bg); - border-bottom: 1px solid var(--border-color); - padding: 0.35rem 0.75rem; - transition: background-color 0.3s ease; - position: relative; - z-index: 100; - flex-shrink: 0; -} - -.app-container { - height: 100vh; - display: flex; - flex-direction: column; - overflow: hidden; -} - -.content-container { - display: flex; - flex: 1; - overflow: hidden; -} - -.editor-pane, .preview-pane { - flex: 1; - padding: 20px; - overflow-y: auto; - position: relative; - /* PERF-025: Shortened transition and scoped to background-color only */ - transition: background-color 0.15s ease; -} - -.editor-pane { - background-color: var(--editor-bg); - border-right: 1px solid var(--border-color); - padding-right: 0px; - --line-number-gutter: 0px; -} - -.preview-pane { - background-color: var(--preview-bg); /* Using the new variable for preview background */ -} - -/* Custom scrollbar */ -.editor-pane::-webkit-scrollbar, -.preview-pane::-webkit-scrollbar, -#markdown-editor::-webkit-scrollbar { - width: 8px; - height: 8px; -} - -.editor-pane::-webkit-scrollbar-track, -.preview-pane::-webkit-scrollbar-track, -#markdown-editor::-webkit-scrollbar-track { - background: var(--scrollbar-track); -} - -.editor-pane::-webkit-scrollbar-thumb, -.preview-pane::-webkit-scrollbar-thumb, -#markdown-editor::-webkit-scrollbar-thumb { - background: var(--scrollbar-thumb); - border-radius: 4px; -} - -.editor-pane::-webkit-scrollbar-thumb:hover, -.preview-pane::-webkit-scrollbar-thumb:hover, -#markdown-editor::-webkit-scrollbar-thumb:hover { - background: var(--button-active); -} - -#markdown-editor { - width: 100%; - height: 100%; - border: none; - background-color: transparent; - color: var(--text-color); - resize: none; - font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; - font-size: 14px; - line-height: 1.5; - padding: 10px; - padding-left: calc(10px + var(--line-number-gutter)); - transition: background-color 0.3s ease, color 0.3s ease; - overflow-y: auto; - position: relative; - z-index: 3; -} - -#markdown-editor:focus { - outline: none; -} - -.preview-pane { - padding: 20px; -} - -.markdown-body { - padding: 20px; - width: 100%; - background-color: var(--preview-bg); /* Ensuring the markdown content matches preview background */ - color: var(--preview-text-color); /* Using specific text color for preview content */ -} - -.markdown-body a.reference-link { - font-size: 0.75em; - letter-spacing: -0.02em; - line-height: 1; - vertical-align: super; - position: relative; - top: 0.08em; -} - -/* Style tables in light mode */ -.markdown-body table { - background-color: var(--table-bg); - border-color: var(--border-color); -} - -.markdown-body table tr { - background-color: var(--table-bg); - border-top: 1px solid var(--border-color); -} - -.markdown-body table tr:nth-child(2n) { - background-color: var(--bg-color); -} - -/* Style code blocks in light mode */ -.markdown-body pre { - background-color: var(--code-bg); - border-radius: 6px; -} - -.markdown-body code { - background-color: var(--code-bg); - border-radius: 3px; - padding: 0.2em 0.4em; -} - -.markdown-body img.emoji-inline { - width: 1em; - height: 1em; - vertical-align: -0.1em; -} - -.markdown-body ul, -.markdown-body ol { - padding-left: 2em; - margin: 0.4em 0; -} - -.markdown-body ul ul, -.markdown-body ul ol, -.markdown-body ol ul, -.markdown-body ol ol { - margin-top: 0.2em; - margin-bottom: 0.2em; -} - -.markdown-body ul.contains-task-list, -.markdown-body li.task-list-item { - list-style: none; -} - -.markdown-body ul.contains-task-list { - padding-left: 2em; -} - -.markdown-body li.task-list-item input[type="checkbox"] { - margin: 0 0.5em 0.2em 0; - vertical-align: middle; - pointer-events: none; -} - -.markdown-body li.task-list-item::marker { - content: ""; -} - -.markdown-body li:has(> input[type="checkbox"]) { - list-style: none; -} - -.markdown-body li:has(> input[type="checkbox"])::marker { - content: ""; -} - -.markdown-body ul:has(> li > input[type="checkbox"]) { - list-style: none; - padding-left: 2em; -} - -.markdown-body .footnotes { - margin-top: 1.5rem; - font-size: 0.9em; -} - -.markdown-body .footnotes ol { - padding-left: 1.5em; -} - -.markdown-body .footnotes ol > li::marker { - content: "[" counter(list-item) "] "; - font-weight: 600; -} - -.markdown-body .footnotes li > p { - margin: 0.2em 0; -} - -.markdown-body .footnote-ref a, -.markdown-body .footnote-backref { - text-decoration: none; -} - -.markdown-body .footnote-backref { - margin-left: 0.4em; -} - -.markdown-body .markdown-alert { - padding: 0.5rem 1rem; - margin-bottom: 16px; - border-left: 0.25em solid; - border-radius: 0.375rem; -} - -.markdown-body .markdown-alert > :last-child { - margin-bottom: 0; -} - -.markdown-body .markdown-alert-title { - margin: 0 0 8px; - font-weight: 600; - line-height: 1.25; - display: flex; - align-items: center; - gap: 8px; -} - -.markdown-body .markdown-alert-icon { - display: inline-flex; - width: 16px; - height: 16px; -} - -.markdown-body .markdown-alert-icon svg { - width: 16px; - height: 16px; - fill: currentColor; -} - -.markdown-body .markdown-alert-note { - color: #0969da; - border-left-color: #0969da; - background-color: #ddf4ff; -} - -.markdown-body .markdown-alert-tip { - color: #1a7f37; - border-left-color: #1a7f37; - background-color: #dafbe1; -} - -.markdown-body .markdown-alert-important { - color: #8250df; - border-left-color: #8250df; - background-color: #fbefff; -} - -.markdown-body .markdown-alert-warning { - color: #9a6700; - border-left-color: #9a6700; - background-color: #fff8c5; -} - -.markdown-body .markdown-alert-caution { - color: #cf222e; - border-left-color: #cf222e; - background-color: #ffebe9; -} - -.markdown-body .markdown-alert > *:not(.markdown-alert-title) { - color: var(--preview-text-color); -} - -[data-theme="dark"] .markdown-body .markdown-alert-note { - color: #4493f8; - background-color: rgba(31, 111, 235, 0.15); - border-left-color: #4493f8; -} - -[data-theme="dark"] .markdown-body .markdown-alert-tip { - color: #3fb950; - background-color: rgba(35, 134, 54, 0.15); - border-left-color: #3fb950; -} - -[data-theme="dark"] .markdown-body .markdown-alert-important { - color: #ab7df8; - background-color: rgba(137, 87, 229, 0.15); - border-left-color: #ab7df8; -} - -[data-theme="dark"] .markdown-body .markdown-alert-warning { - color: #d29922; - background-color: rgba(210, 153, 34, 0.18); - border-left-color: #d29922; -} - -[data-theme="dark"] .markdown-body .markdown-alert-caution { - color: #f85149; - background-color: rgba(248, 81, 73, 0.18); - border-left-color: #f85149; -} - -.toolbar { - display: flex; - gap: 8px; - align-items: center; -} - -.toolbar-group { - display: inline-flex; - align-items: center; - gap: 6px; -} - -.toolbar-divider { - width: 1px; - height: 20px; - background-color: var(--border-color); - opacity: 0.7; -} - -.tool-button { - background-color: var(--button-bg); - border: 1px solid var(--border-color); - color: var(--text-color); - border-radius: 5px; - padding: 4px 8px; - font-size: 13px; - cursor: pointer; - display: inline-flex; - align-items: center; - justify-content: center; - gap: 4px; - /* PERF-016: Specific transition properties instead of 'all' to avoid animating layout-triggering properties */ - transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease; -} - -.tool-button:hover { - background-color: var(--button-hover); -} - -.tool-button:active { - background-color: var(--button-active); -} - -.tool-button:disabled, -.tool-button[aria-disabled="true"] { - cursor: not-allowed; - opacity: 0.5; -} - -.tool-button i { - font-size: 15px; -} - -.tool-button.is-active, -.tool-button.is-active:hover { - border-color: var(--accent-color); - color: var(--accent-color); - background-color: rgba(3, 102, 214, 0.08); -} - -.btn-text { - display: none; -} - -.toolbar .tool-button { - height: 28px; - min-width: 28px; -} - -.toolbar .tool-button.sync-active { - border-color: var(--accent-color); - color: var(--accent-color); -} - -.file-input { - display: none; -} - -/* Drag overlay: full-screen drop target shown when user drags a file over the window */ -.drag-overlay { - display: none; - position: fixed; - inset: 0; - z-index: 9999; - background-color: rgba(0, 0, 0, 0.45); - pointer-events: none; - align-items: center; - justify-content: center; -} - -.drag-overlay.active { - display: flex; - pointer-events: auto; -} - -.drag-overlay-inner { - border: 3px dashed var(--accent-color); - border-radius: 12px; - padding: 48px 64px; - text-align: center; - color: #ffffff; - background-color: rgba(3, 102, 214, 0.15); - animation: overlayPulse 1.4s ease-in-out infinite; -} - -.drag-overlay-icon { - display: block; - font-size: 3rem; - margin-bottom: 12px; - color: var(--accent-color); -} - -.drag-overlay-text { - font-size: 1.4rem; - font-weight: 600; - margin-bottom: 4px; -} - -.drag-overlay-sub { - font-size: 0.85rem; - opacity: 0.75; - margin-bottom: 0; -} - -@keyframes overlayPulse { - 0%, 100% { transform: scale(1); } - 50% { transform: scale(1.015); } -} - -/* Editor drop hint: subtle text at bottom of editor pane, shown only when empty */ -.drop-hint { - position: absolute; - bottom: 14px; - left: 0; - right: 0; - text-align: center; - font-size: 0.75rem; - color: var(--text-color); - opacity: 0.35; - pointer-events: none; - user-select: none; - z-index: 3; -} - -.editor-pane:has(#markdown-editor:not(:placeholder-shown)) .drop-hint { - display: none; -} - -.line-numbers { - position: absolute; - top: 20px; - bottom: 20px; - left: 20px; - width: var(--line-number-gutter); - padding: 10px 8px 10px 0; - font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; - font-size: 14px; - line-height: 1.5; - text-align: right; - color: var(--text-secondary); - background-color: var(--editor-bg); - border-right: 1px solid var(--border-color); - box-sizing: border-box; - overflow: hidden; - pointer-events: none; - user-select: none; - z-index: 2; - font-variant-numeric: tabular-nums; -} - -.line-numbers .line-number { - display: block; - height: auto; -} - -.editor-highlight-layer { - position: absolute; - inset: 20px 0 20px calc(20px + var(--line-number-gutter)); - padding: 10px; - font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; - font-size: 14px; - line-height: 1.5; - white-space: pre-wrap; - word-wrap: break-word; - color: transparent; - pointer-events: none; - overflow: auto; - background-color: var(--editor-bg); - border-radius: 4px; - z-index: 1; -} - -.editor-highlight-layer::-webkit-scrollbar { - width: 8px; - height: 8px; -} - -.editor-highlight-layer::-webkit-scrollbar-thumb { - background: transparent; -} - -.editor-highlight-layer::-webkit-scrollbar-track { - background: transparent; -} - -.find-highlight { - background-color: var(--fr-match-highlight, rgba(255, 223, 93, 0.4)) !important; - border-radius: 2px; - color: transparent !important; - padding: 0 !important; - margin: 0 !important; -} - -.find-highlight.active { - background-color: var(--fr-match-active, #ff9b30) !important; - color: transparent !important; - padding: 0 !important; - margin: 0 !important; - outline: 1px solid var(--accent-color, #0366d6) !important; - outline-offset: -1px; -} - -.preview-find-highlight { - background-color: var(--fr-match-highlight, rgba(255, 223, 93, 0.4)) !important; - color: var(--fr-match-text-color, inherit) !important; - border-radius: 2px; - padding: 0 1px !important; - margin: 0 !important; -} - -.preview-find-highlight.active { - background-color: var(--fr-match-active, #ff9b30) !important; - color: var(--fr-match-active-text-color, inherit) !important; - outline: 1px solid var(--accent-color, #0366d6) !important; - outline-offset: -1px; -} - -/* Dropdown improvements */ -.dropdown-menu { - background-color: var(--bg-color); - border-color: var(--border-color); -} - -.dropdown-item { - color: var(--text-color); -} - -.dropdown-item:hover, .dropdown-item:focus { - background-color: var(--button-hover); - color: var(--text-color); -} - -/* Markdown formatting toolbar */ -.markdown-format-toolbar { - display: flex; - align-items: center; - height: 34px; - padding: 0 6px; - background-color: var(--header-bg); - border-bottom: 1px solid var(--border-color); - overflow-x: auto; - overflow-y: hidden; - flex-shrink: 0; - scrollbar-width: none; - -ms-overflow-style: none; -} - -.markdown-format-toolbar::-webkit-scrollbar { - display: none; -} - -.markdown-toolbar-group { - display: flex; - align-items: center; - gap: 2px; - height: 100%; - padding: 0 6px; - border-right: 1px solid var(--border-color); - flex-shrink: 0; -} - -.markdown-toolbar-group:first-child { - padding-left: 0; -} - -.markdown-toolbar-group:last-child { - border-right: none; - padding-right: 0; -} - -.markdown-tool-btn { - display: inline-flex; - align-items: center; - justify-content: center; - width: 26px; - height: 26px; - border: 1px solid transparent; - border-radius: 4px; - background: transparent; - color: var(--text-color); - cursor: pointer; - font-size: 14px; - line-height: 1; - padding: 0; - transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease; -} - -.markdown-tool-btn:hover, -.markdown-tool-btn:focus-visible { - background-color: var(--button-hover); - border-color: var(--border-color); - color: var(--accent-color); -} - -.markdown-tool-btn:active { - background-color: var(--button-active); -} - -.markdown-tool-btn:disabled, -.markdown-tool-btn.disabled { - opacity: 0.4; - cursor: not-allowed; - pointer-events: none; -} - -.markdown-tool-btn i { - font-size: 15px; -} - -.markdown-tool-btn[data-md-action="reference"] i::before { - content: "[ ]"; - font-style: normal; - font-size: 12px; - letter-spacing: -0.12em; -} - -.markdown-tool-btn.text-tool { - width: auto; - min-width: 26px; - padding: 0 5px; - font-weight: 600; - font-family: Georgia, "Times New Roman", serif; -} - -.heading-group .markdown-tool-btn { - min-width: 30px; -} - - - -/* Loading indicators */ -.loading { - opacity: 0.6; - pointer-events: none; -} - -/* Focus outline for accessibility */ -button:focus, -a:focus { - outline: 2px solid var(--accent-color); - outline-offset: 2px; -} - -/* Animation for copied message */ -@keyframes fadeIn { - from { opacity: 0; } - to { opacity: 1; } -} - -/* Tooltip styles */ -.tooltip { - position: absolute; - background: var(--button-bg); - border: 1px solid var(--border-color); - padding: 5px 8px; - border-radius: 4px; - font-size: 12px; - z-index: 1000; - animation: fadeIn 0.2s ease; -} - -/* Styles for GitHub markdown preview light mode */ -.markdown-body { - color-scheme: light; - --color-prettylights-syntax-comment: #6a737d; - --color-prettylights-syntax-constant: #005cc5; - --color-prettylights-syntax-entity: #6f42c1; - --color-prettylights-syntax-storage-modifier-import: #24292e; - --color-prettylights-syntax-entity-tag: #22863a; - --color-prettylights-syntax-keyword: #cf222e; - --color-prettylights-syntax-string: #032f62; - --color-prettylights-syntax-variable: #e36209; - --color-prettylights-syntax-brackethighlighter-unmatched: #b31d28; - --color-prettylights-syntax-invalid-illegal-text: #fafbfc; - --color-prettylights-syntax-invalid-illegal-bg: #b31d28; - --color-prettylights-syntax-carriage-return-text: #fafbfc; - --color-prettylights-syntax-carriage-return-bg: #d73a49; - --color-prettylights-syntax-string-regexp: #22863a; - --color-prettylights-syntax-markup-list: #735c0f; - --color-prettylights-syntax-markup-heading: #005cc5; - --color-prettylights-syntax-markup-italic: #24292e; - --color-prettylights-syntax-markup-bold: #24292e; - --color-prettylights-syntax-markup-deleted-text: #b31d28; - --color-prettylights-syntax-markup-deleted-bg: #ffeef0; - --color-prettylights-syntax-markup-inserted-text: #22863a; - --color-prettylights-syntax-markup-inserted-bg: #f0fff4; - --color-prettylights-syntax-markup-changed-text: #e36209; - --color-prettylights-syntax-markup-changed-bg: #ffebda; - --color-prettylights-syntax-markup-ignored-text: #f6f8fa; - --color-prettylights-syntax-markup-ignored-bg: #005cc5; - --color-prettylights-syntax-meta-diff-range: #6f42c1; - --color-prettylights-syntax-brackethighlighter-angle: #586069; - --color-prettylights-syntax-sublimelinter-gutter-mark: #e1e4e8; - --color-prettylights-syntax-constant-other-reference-link: #032f62; - --color-fg-default: #24292e; - --color-fg-muted: #586069; - --color-fg-subtle: #6a737d; - --color-canvas-default: #ffffff; - --color-canvas-subtle: #f6f8fa; - --color-border-default: #e1e4e8; - --color-border-muted: #eaecef; - --color-neutral-muted: rgba(175,184,193,0.2); - --color-accent-fg: #0366d6; - --color-accent-emphasis: #0366d6; - --color-attention-subtle: #fff5b1; - --color-danger-fg: #d73a49; -} - -/* Styles for GitHub markdown preview dark mode */ -[data-theme="dark"] .markdown-body { - color-scheme: dark; - --color-prettylights-syntax-comment: #8b949e; - --color-prettylights-syntax-constant: #79c0ff; - --color-prettylights-syntax-entity: #d2a8ff; - --color-prettylights-syntax-storage-modifier-import: #c9d1d9; - --color-prettylights-syntax-entity-tag: #7ee787; - --color-prettylights-syntax-keyword: #ff7b72; - --color-prettylights-syntax-string: #a5d6ff; - --color-prettylights-syntax-variable: #ffa657; - --color-prettylights-syntax-brackethighlighter-unmatched: #f85149; - --color-prettylights-syntax-invalid-illegal-text: #f0f6fc; - --color-prettylights-syntax-invalid-illegal-bg: #8e1519; - --color-prettylights-syntax-carriage-return-text: #f0f6fc; - --color-prettylights-syntax-carriage-return-bg: #b62324; - --color-prettylights-syntax-string-regexp: #7ee787; - --color-prettylights-syntax-markup-list: #f2cc60; - --color-prettylights-syntax-markup-heading: #1f6feb; - --color-prettylights-syntax-markup-italic: #c9d1d9; - --color-prettylights-syntax-markup-bold: #c9d1d9; - --color-prettylights-syntax-markup-deleted-text: #ffdcd7; - --color-prettylights-syntax-markup-deleted-bg: #67060c; - --color-prettylights-syntax-markup-inserted-text: #aff5b4; - --color-prettylights-syntax-markup-inserted-bg: #033a16; - --color-prettylights-syntax-markup-changed-text: #ffdfb6; - --color-prettylights-syntax-markup-changed-bg: #5a1e02; - --color-prettylights-syntax-markup-ignored-text: #c9d1d9; - --color-prettylights-syntax-markup-ignored-bg: #1158c7; - --color-prettylights-syntax-meta-diff-range: #d2a8ff; - --color-prettylights-syntax-brackethighlighter-angle: #8b949e; - --color-prettylights-syntax-sublimelinter-gutter-mark: #484f58; - --color-prettylights-syntax-constant-other-reference-link: #a5d6ff; - --color-fg-default: #c9d1d9; - --color-fg-muted: #8b949e; - --color-fg-subtle: #484f58; - --color-canvas-default: #0d1117; - --color-canvas-subtle: #161b22; - --color-border-default: #30363d; - --color-border-muted: #21262d; - --color-neutral-muted: rgba(110,118,129,0.4); - --color-accent-fg: #58a6ff; - --color-accent-emphasis: #1f6feb; - --color-attention-subtle: rgba(187,128,9,0.15); - --color-danger-fg: #f85149; -} - -/* Override specific styles for dark mode tables and code */ -[data-theme="dark"] .markdown-body table tr { - background-color: var(--table-bg); -} - -[data-theme="dark"] .markdown-body table tr:nth-child(2n) { - background-color: #1c2128; /* Slightly lighter than base dark background */ -} - -[data-theme="dark"] .markdown-body pre { - background-color: var(--code-bg); -} - -[data-theme="dark"] .markdown-body code { - background-color: var(--code-bg); -} - -/* Syntax Highlighting Mapping to GitHub Variables */ -.hljs { - color: var(--color-fg-default); -} -.hljs-doctag, -.hljs-keyword, -.hljs-meta .hljs-keyword, -.hljs-template-tag, -.hljs-template-variable, -.hljs-type, -.hljs-variable.language_ { - color: var(--color-prettylights-syntax-keyword); -} -.hljs-title, -.hljs-title.class_, -.hljs-title.class_.inherited__, -.hljs-title.function_ { - color: var(--color-prettylights-syntax-entity); -} -.hljs-attr, -.hljs-attribute, -.hljs-literal, -.hljs-meta, -.hljs-number, -.hljs-operator, -.hljs-variable, -.hljs-selector-attr, -.hljs-selector-class, -.hljs-selector-id { - color: var(--color-prettylights-syntax-constant); -} -.hljs-regexp, -.hljs-string, -.hljs-meta .hljs-string { - color: var(--color-prettylights-syntax-string); -} -.hljs-built_in, -.hljs-symbol { - color: var(--color-prettylights-syntax-variable); -} -.hljs-comment, -.hljs-code, -.hljs-formula { - color: var(--color-prettylights-syntax-comment); -} -.hljs-name, -.hljs-quote, -.hljs-selector-tag, -.hljs-selector-pseudo { - color: var(--color-prettylights-syntax-entity-tag); -} -.hljs-subst { - color: var(--color-fg-default); -} -.hljs-section { - color: var(--color-prettylights-syntax-markup-heading); - font-weight: bold; -} -.hljs-bullet { - color: var(--color-prettylights-syntax-constant); -} -.hljs-emphasis { - color: var(--color-fg-default); - font-style: italic; -} -.hljs-strong { - color: var(--color-fg-default); - font-weight: bold; -} -.hljs-addition { - color: var(--color-prettylights-syntax-markup-inserted-text); - background-color: var(--color-prettylights-syntax-markup-inserted-bg); -} -.hljs-deletion { - color: var(--color-prettylights-syntax-markup-deleted-text); - background-color: var(--color-prettylights-syntax-markup-deleted-bg); -} - -.stats-container { - font-size: 0.8rem; - color: var(--text-color); -} - -.stat-item { - align-items: center; -} - -.stat-item i { - font-size: 0.9rem; - opacity: 0.8; -} - -#importDropdown, -#exportDropdown, -#languageDropdown { - font-size: 0.8rem; -} - -#importDropdown i, -#exportDropdown i, -#languageDropdown i { - font-size: 0.9rem; -} - -/* Ensure desktop dropdown menu options match the stats-container font size */ -[aria-labelledby="importDropdown"] .dropdown-item, -[aria-labelledby="exportDropdown"] .dropdown-item, -[aria-labelledby="languageDropdown"] .dropdown-item { - font-size: 0.8rem; -} - -/* Ensure mobile menu import, export, and language dropdown triggers/options match the mobile stats-container font size */ -#mobile-import-button, -#mobile-import-github-button, -#mobile-export-md, -#mobile-export-html, -#mobile-export-pdf, -#mobileLanguageDropdown { - font-size: 0.9rem !important; -} - -[aria-labelledby="mobileLanguageDropdown"] .dropdown-item { - font-size: 0.9rem; -} - -.editor-pane { - overflow: hidden; -} - -/* Mobile Menu Styles */ -.mobile-menu { - display: none; - position: relative; - z-index: 1001; -} - - - -/* slide‑in panel */ -.mobile-menu-panel { - position: fixed; - top: 0; - right: -300px; - width: 280px; - height: 100vh; - background-color: var(--bg-color); - box-shadow: -2px 0 10px rgba(0, 0, 0, 0.2); - transition: right 0.3s ease; - overflow-y: auto; - padding: 1rem; - display: flex; - flex-direction: column; - z-index: 1002; -} - -.mobile-menu-panel.active { - right: 0; -} - -/* translucent overlay behind panel */ -.mobile-menu-overlay { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100vh; - background-color: rgba(0, 0, 0, 0.5); - opacity: 0; - visibility: hidden; - pointer-events: none; - transition: opacity 0.3s ease, visibility 0.3s ease; - z-index: 1000; -} - -.mobile-menu-overlay.active { - opacity: 1; - visibility: visible; - pointer-events: auto; -} - -/* header inside mobile menu */ -.mobile-menu-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 1rem; -} - -.mobile-menu-header h5 { - margin: 0; - font-size: 1.25rem; - color: var(--text-color); -} - -/* stats section in mobile menu */ -.mobile-stats-container { - border-bottom: 1px solid var(--border-color); - padding-bottom: 0.75rem; - margin-bottom: 1rem; -} - -.mobile-stats-container .stat-item { - font-size: 0.9rem; - color: var(--text-color); - display: flex; - align-items: center; -} - -.mobile-stats-container .stat-item i { - margin-right: 0.5em; - opacity: 0.8; -} - -/* menu buttons list */ -.mobile-menu-items { - display: flex; - flex-direction: column; - gap: 0.5rem; - flex-grow: 1; -} - -/* each menu item */ -.mobile-menu-item { - background-color: var(--button-bg); - border: 1px solid var(--border-color); - color: var(--text-color); - border-radius: 6px; - padding: 0.6rem 1rem; - font-size: 1rem; - text-align: left; - display: flex; - align-items: center; - gap: 0.5rem; - transition: background-color 0.2s ease; - cursor: pointer; -} - -.mobile-menu-item:hover { - background-color: var(--button-hover); -} - -.mobile-menu-item:active { - background-color: var(--button-active); -} - -/* close button override */ -#close-mobile-menu.tool-button { - padding: 0.25rem 0.5rem; - font-size: 1rem; -} - -/* Mobile document tabs section */ -.mobile-tabs-section { - border-bottom: 1px solid var(--border-color); - padding-bottom: 0.75rem; -} - -.mobile-tabs-header { - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: 0.5rem; -} - -.mobile-tabs-label { - font-size: 0.85rem; - font-weight: 600; - color: var(--text-color); - opacity: 0.8; - text-transform: uppercase; - letter-spacing: 0.04em; -} - -.mobile-new-tab-btn { - background: none; - border: 1px solid var(--border-color); - border-radius: 4px; - color: var(--text-color); - padding: 2px 7px; - font-size: 0.9rem; - cursor: pointer; - display: flex; - align-items: center; - transition: background-color 0.15s ease; -} - -.mobile-new-tab-btn:hover { - background-color: var(--button-hover); -} - -.mobile-tab-list { - display: flex; - flex-direction: column; - gap: 4px; - max-height: 180px; - overflow-y: auto; -} - -.mobile-tab-item { - display: flex; - align-items: center; - justify-content: space-between; - background-color: var(--button-bg); - border: 1px solid var(--border-color); - border-radius: 6px; - padding: 0.45rem 0.75rem; - font-size: 0.9rem; - color: var(--text-color); - cursor: pointer; - transition: background-color 0.15s ease; - gap: 0.5rem; -} - -.mobile-tab-item:hover { - background-color: var(--button-hover); -} - -.mobile-tab-item.active { - border-color: var(--accent-color); - color: var(--accent-color); - background-color: var(--bg-color); -} - -.mobile-tab-title { - flex: 1; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - min-width: 0; -} - -.mobile-tab-item .tab-menu-btn { - opacity: 0.6; -} - -.mobile-tab-item:hover .tab-menu-btn, -.mobile-tab-item.active .tab-menu-btn { - opacity: 0.8; -} - -#mobile-tab-reset-btn { - margin-left: 0; - height: auto; - padding: 0.45rem 0.75rem; - justify-content: center; - font-size: 0.9rem; -} - -/* ========================================== - NAVBAR RESPONSIVE BREAKPOINTS - >= 1080px : full desktop navbar - < 1080px : mobile hamburger + stacked panes - ========================================== */ - -/* Mobile / tablet (< 1080px): switch to hamburger, stack panes */ -@media (max-width: 1079px) { - /* Override Bootstrap d-md-flex / d-md-none so the breakpoint is 1080px */ - .stats-container, - .toolbar { - display: none !important; - } - - /* Expand touch target sizes to meet WCAG mobile guidelines */ - .markdown-tool-btn { - width: 36px !important; - height: 36px !important; - font-size: 16px !important; - } - .markdown-format-toolbar { - height: 44px !important; - } - .tab-close-btn { - width: 28px !important; - height: 28px !important; - font-size: 14px !important; - } - .tab-menu-btn { - width: 28px !important; - height: 28px !important; - font-size: 14px !important; - } - - .mobile-menu { - display: block !important; - } - - /* Stack editor and preview vertically */ - .content-container { - flex-direction: column; - } - - .editor-pane, - .preview-pane { - flex: none; - height: 50%; - border-right: none; - } - - .editor-pane { - border-bottom: 1px solid var(--border-color); - } - - /* Hide drag-resize divider (touch devices don't use it) */ - .resize-divider { - display: none; - } - - /* Single-pane view modes: occupy full height */ - .content-container.view-editor-only .editor-pane, - .content-container.view-preview-only .preview-pane { - height: 100%; - } - - .content-container.view-split .editor-pane, - .content-container.view-split .preview-pane { - height: 50%; - } -} - -.github-link { - color: var(--text-color); - text-decoration: none; - display: flex; - align-items: center; - justify-content: center; - transition: transform 0.2s ease, color 0.2s ease; - margin-right: 2rem; -} - -.github-link:hover { - color: var(--accent-color); - transform: scale(1.1); -} - -.github-link i { - font-size: 1.25rem; -} - -/* ======================================== - HEADER LAYOUT - ======================================== */ -.header-container { - position: relative; - min-height: 30px; -} - -.app-header h1 { - font-size: 1.05rem; - line-height: 1.1; -} - -.header-left { - flex: 1 0 auto; - justify-content: flex-start; - white-space: nowrap; -} - -.header-right { - flex: 1 0 auto; - justify-content: flex-end; - white-space: nowrap; -} - -/* Pane View States */ -.content-container.view-editor-only .preview-pane { - display: none; -} - -.content-container.view-editor-only .editor-pane { - flex: 1; - border-right: none; -} - -.content-container.view-preview-only .editor-pane { - display: none; -} - -.content-container.view-preview-only .preview-pane { - flex: 1; -} - -.content-container.view-split .editor-pane, -.content-container.view-split .preview-pane { - flex: 1; -} - -/* Compact desktop (< 1280px): compact toolbar */ -@media (max-width: 1280px) { - /* Compact toolbar at medium widths */ - .toolbar { - gap: 4px; - } -} - - - -/* ======================================== - RESIZE DIVIDER - Story 1.3 - ======================================== */ - -.resize-divider { - width: 8px; - background-color: transparent; - cursor: col-resize; - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - position: relative; - z-index: 10; - transition: background-color 0.2s ease; -} - -.resize-divider:hover { - background-color: var(--button-hover); -} - -.resize-divider.dragging { - background-color: var(--accent-color); -} - -.resize-divider-handle { - width: 2px; - height: 40px; - background-color: var(--border-color); - border-radius: 2px; - transition: background-color 0.2s ease, width 0.2s ease; -} - -.resize-divider:hover .resize-divider-handle, -.resize-divider.dragging .resize-divider-handle { - background-color: var(--accent-color); - width: 3px; -} - -/* Hide divider in single-pane modes */ -.content-container.view-editor-only .resize-divider, -.content-container.view-preview-only .resize-divider { - display: none; -} - - - -/* Prevent text selection during drag */ -.resizing { - user-select: none; - cursor: col-resize !important; -} - -.resizing * { - cursor: col-resize !important; -} - -.resizing #markdown-preview, -.resizing #markdown-editor, -.resizing .line-numbers { - pointer-events: none !important; -} - -/* ======================================== - MOBILE VIEW MODE CONTROLS - Story 1.4 - ======================================== */ - -.mobile-view-mode-group { - display: flex; - gap: 0; - border-bottom: 1px solid var(--border-color); - padding-bottom: 0.75rem; -} - -.mobile-view-mode-btn { - flex: 1; - background-color: var(--button-bg); - border: 1px solid var(--border-color); - color: var(--text-color); - padding: 8px 12px; - font-size: 14px; - cursor: pointer; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 4px; - transition: all 0.2s ease; -} - -.mobile-view-mode-btn:first-child { - border-radius: 6px 0 0 6px; -} - -.mobile-view-mode-btn:last-child { - border-radius: 0 6px 6px 0; -} - -.mobile-view-mode-btn:not(:last-child) { - border-right: none; -} - -.mobile-view-mode-btn:hover, -.mobile-view-mode-btn:active { - background-color: var(--button-hover); -} - -.mobile-view-mode-btn.active { - background-color: var(--button-bg); - border-color: var(--accent-color); - color: var(--accent-color); - border-width: 2px; - padding: 7px 11px; -} - -.mobile-view-mode-btn.active:not(:last-child) { - border-right: 2px solid var(--accent-color); -} - -.mobile-view-mode-btn i { - font-size: 18px; -} - -.mobile-view-mode-btn span { - font-size: 12px; -} - -/* ======================================== - RESPONSIVE VIEW MODE FIXES - Story 1.5 - ======================================== */ - - - -/* ======================================== - PDF EXPORT TABLE FIX - Rowspan/Colspan - ======================================== */ - -/* Fix for html2canvas not properly rendering rowspan/colspan cells. - Apply backgrounds to cells instead of rows to prevent row backgrounds - from painting over rowspan cells during canvas capture. */ -.pdf-export table tr { - background-color: transparent !important; -} - -.pdf-export table th, -.pdf-export table td { - background-color: var(--table-bg, #ffffff); - position: relative; -} - -.pdf-export table tr:nth-child(2n) th, -.pdf-export table tr:nth-child(2n) td { - background-color: var(--bg-color, #f6f8fa); -} - -/* Ensure rowspan cells render correctly */ -.pdf-export table th[rowspan], -.pdf-export table td[rowspan] { - vertical-align: middle; - background-color: var(--table-bg, #ffffff) !important; -} - -/* Ensure colspan cells render correctly */ -.pdf-export table th[colspan], -.pdf-export table td[colspan] { - text-align: center; -} - -/* Dark mode PDF export table fix */ -[data-theme="dark"] .pdf-export table th, -[data-theme="dark"] .pdf-export table td { - background-color: var(--table-bg, #161b22); -} - -[data-theme="dark"] .pdf-export table tr:nth-child(2n) th, -[data-theme="dark"] .pdf-export table tr:nth-child(2n) td { - background-color: #1c2128; -} - -[data-theme="dark"] .pdf-export table th[rowspan], -[data-theme="dark"] .pdf-export table td[rowspan] { - background-color: var(--table-bg, #161b22) !important; -} - -/* ======================================== - MERMAID DIAGRAM TOOLBAR - ======================================== */ - -.mermaid-container { - position: relative; -} - -.mermaid-toolbar { - position: absolute; - top: 8px; - right: 8px; - display: flex; - gap: 4px; - opacity: 0; - transition: opacity 0.2s ease; - z-index: 10; -} - -.mermaid-container:hover .mermaid-toolbar { - opacity: 1; -} - -.mermaid-toolbar-btn { - background-color: var(--button-bg); - border: 1px solid var(--border-color); - color: var(--text-color); - border-radius: 4px; - padding: 4px 7px; - font-size: 13px; - cursor: pointer; - display: flex; - align-items: center; - gap: 3px; - transition: background-color 0.2s ease, color 0.2s ease; - white-space: nowrap; -} - -.mermaid-toolbar-btn:hover { - background-color: var(--button-hover); - color: var(--accent-color); -} - -.mermaid-toolbar-btn:active { - background-color: var(--button-active); -} - -.mermaid-toolbar-btn i { - font-size: 14px; -} - -/* ======================================== - MERMAID ZOOM MODAL - ======================================== */ - -#mermaid-zoom-modal { - display: none; - position: fixed; - inset: 0; - z-index: 2000; - background-color: rgba(0, 0, 0, 0.75); - align-items: center; - justify-content: center; -} - -#mermaid-zoom-modal.active { - display: flex; -} - -.mermaid-modal-content { - background-color: var(--bg-color); - border: 1px solid var(--border-color); - border-radius: 8px; - padding: 16px; - width: 85vw; - height: 85vh; - max-width: 85vw; - max-height: 85vh; - display: flex; - flex-direction: column; - gap: 12px; -} - -@media (max-width: 576px) { - .mermaid-modal-content { - width: 95vw; - height: 90vh; - max-width: 95vw; - max-height: 90vh; - padding: 10px; - } -} - -.mermaid-modal-header { - display: flex; - justify-content: space-between; - align-items: center; -} - -.mermaid-modal-header span { - font-weight: 600; - font-size: 15px; - color: var(--text-color); -} - -.mermaid-modal-close { - background: none; - border: none; - color: var(--text-color); - font-size: 1.2rem; - cursor: pointer; - padding: 2px 6px; - border-radius: 4px; - display: flex; - align-items: center; - transition: background-color 0.2s ease; -} - -.mermaid-modal-close:hover { - background-color: var(--button-hover); -} - -.mermaid-modal-diagram { - overflow: auto; - flex: 1; - display: flex; - align-items: center; - justify-content: center; - min-height: 200px; - cursor: grab; -} - -.mermaid-modal-diagram.dragging { - cursor: grabbing; -} - -.mermaid-modal-diagram svg { - transform-origin: center; - transition: transform 0.1s ease; - max-width: none; -} - -.mermaid-modal-controls { - display: flex; - justify-content: center; - gap: 8px; - flex-wrap: wrap; -} - -.mermaid-modal-controls .mermaid-toolbar-btn { - opacity: 1; -} - -/* ======================================== - DOCUMENT TABS & SESSION MANAGEMENT - ======================================== */ - -.tab-bar { - display: flex; - align-items: center; - background-color: var(--header-bg); - border-bottom: 1px solid var(--border-color); - height: 32px; - overflow: visible; /* ← was: overflow: hidden */ - flex-shrink: 0; - padding: 0 4px; - gap: 0; - user-select: none; - position: relative; - z-index: 10; -} - -.tab-list { - display: flex; - align-items: flex-end; - overflow-x: auto; - overflow-y: visible; /* ← was: overflow-y: hidden */ - flex: 1; - height: 100%; - scrollbar-width: none; - -ms-overflow-style: none; -} - -.tab-list::-webkit-scrollbar { - display: none; -} - -.tab-item { - display: flex; - align-items: center; - gap: 6px; - height: 32px; - padding: 0 8px 0 10px; - min-width: 100px; - max-width: 180px; - background-color: var(--button-bg); - border: 1px solid var(--border-color); - border-bottom: 1px solid transparent; - border-radius: 6px 6px 0 0; - cursor: pointer; - font-size: 13px; - color: var(--text-color); - white-space: nowrap; - /* overflow: hidden; <-- REMOVE THIS */ - position: relative; - transition: background-color 0.15s ease, color 0.15s ease; - flex-shrink: 0; - margin-right: 2px; - opacity: 0.7; -} - -.tab-item:hover { - background-color: var(--button-hover); - opacity: 0.9; -} - -.tab-item.active { - background-color: var(--bg-color); - border-color: var(--border-color); - color: var(--accent-color); - border-bottom: 1px solid var(--bg-color); - opacity: 1; - z-index: 2; -} - -.tab-item.unsaved::after { - content: ''; - display: inline-block; - width: 6px; - height: 6px; - background-color: var(--accent-color); - border-radius: 50%; - flex-shrink: 0; - margin-left: 2px; -} - -.tab-title { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - flex: 1; - min-width: 0; -} - -.tab-close-btn { - display: flex; - align-items: center; - justify-content: center; - width: 16px; - height: 16px; - border-radius: 3px; - background: none; - border: none; - color: var(--text-color); - cursor: pointer; - padding: 0; - font-size: 11px; - opacity: 0; - flex-shrink: 0; - transition: background-color 0.15s ease, opacity 0.15s ease; -} - -.tab-item:hover .tab-close-btn, -.tab-item.active .tab-close-btn { - opacity: 0.6; -} - -.tab-close-btn:hover { - background-color: var(--button-active); - opacity: 1 !important; - color: var(--color-danger-fg, #d73a49); -} - -.tab-new-btn { - display: flex; - align-items: center; - gap: 4px; - height: 24px; - padding: 0 8px; - border-radius: 5px; - background: none; - border: 1px solid var(--border-color); - color: var(--text-color); - cursor: pointer; - font-size: 12px; - flex-shrink: 0; - margin-left: 6px; - align-self: center; - transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease; -} - -.tab-new-btn:hover { - background-color: rgba(46, 160, 67, 0.1); - border-color: var(--accent-color, #2ea043); - color: var(--accent-color, #2ea043); -} - -.tab-new-btn:active { - background-color: rgba(46, 160, 67, 0.2); -} - -/* Drag-and-drop visual feedback */ -.tab-item.dragging { - opacity: 0.4; -} - -.tab-item.drag-over { - border-left: 2px solid var(--accent-color); -} - -/* Tab enter animation */ -@keyframes tabSlideIn { - from { opacity: 0; transform: translateY(4px); } - to { opacity: 0.7; transform: translateY(0); } -} - -.tab-item { - animation: tabSlideIn 0.12s ease forwards; -} - -.tab-item.active { - animation: none; -} - -/* Hide tab bar on very small screens — single-file use */ -@media (max-width: 480px) { - .tab-bar { - display: none; - } -} - -/* ======================================== - TAB OVERFLOW — Scroll Buttons & Fade Indicators - ======================================== */ - -.tab-scroll-btn { - display: none; - align-items: center; - justify-content: center; - width: 24px; - height: 24px; - border-radius: 4px; - background: none; - border: 1px solid transparent; - color: var(--text-color); - cursor: pointer; - font-size: 14px; - flex-shrink: 0; - padding: 0; - transition: background-color 0.15s ease, border-color 0.15s ease, opacity 0.15s ease; - z-index: 2; - opacity: 0.6; -} - -.tab-scroll-btn:hover { - background-color: var(--button-hover); - border-color: var(--border-color); - opacity: 1; -} - -.tab-scroll-btn:active { - background-color: var(--button-active); -} - -/* Show scroll buttons only when overflow exists */ -.tab-bar.has-overflow-left .tab-scroll-left, -.tab-bar.has-overflow-right .tab-scroll-right { - display: flex; -} - -/* Overflow fade indicators — subtle gradient at clipped edges */ -.tab-list::before, -.tab-list::after { - content: ''; - position: sticky; - top: 0; - bottom: 0; - width: 0; - flex-shrink: 0; - pointer-events: none; - z-index: 3; - transition: box-shadow 0.2s ease; -} - -.tab-list::before { - left: 0; -} - -.tab-list::after { - right: 0; -} - -.tab-bar.has-overflow-left .tab-list::before { - box-shadow: 8px 0 12px -4px rgba(0, 0, 0, 0.12); -} - -.tab-bar.has-overflow-right .tab-list::after { - box-shadow: -8px 0 12px -4px rgba(0, 0, 0, 0.12); -} - -[data-theme="dark"] .tab-bar.has-overflow-left .tab-list::before { - box-shadow: 8px 0 12px -4px rgba(0, 0, 0, 0.35); -} - -[data-theme="dark"] .tab-bar.has-overflow-right .tab-list::after { - box-shadow: -8px 0 12px -4px rgba(0, 0, 0, 0.35); -} - -/* ======================================== - THREE-DOT TAB MENU - ======================================== */ - -.tab-menu-btn { - display: flex; - align-items: center; - justify-content: center; - width: 22px; - height: 22px; - border-radius: 3px; - background: none; - border: none; - color: var(--text-color); - cursor: pointer; - padding: 0; - font-size: 14px; - font-weight: bold; - letter-spacing: 1px; - opacity: 0.65; - flex-shrink: 0; - transition: background-color 0.15s ease, opacity 0.15s ease; - position: relative; -} - -/* Touch Hitbox Expansion for Tab Menu Button */ -.tab-menu-btn::before { - content: ''; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - width: 48px; - height: 48px; -} - -/* Touch-optimized styling for coarser pointers (e.g., smartphones & tablets) */ -@media (pointer: coarse) { - .tab-bar { - height: 40px !important; - } - .tab-item { - height: 40px !important; - font-size: 14px !important; - padding: 0 10px 0 12px !important; - gap: 8px !important; - } - .tab-new-btn, - .tab-reset-btn { - height: 32px !important; - font-size: 14px !important; - padding: 0 12px !important; - } - .tab-scroll-btn { - width: 32px !important; - height: 32px !important; - font-size: 18px !important; - } - .tab-menu-btn { - width: 30px !important; - height: 30px !important; - font-size: 18px !important; - } - .tab-close-btn { - width: 20px !important; - height: 20px !important; - font-size: 13px !important; - opacity: 0.8 !important; - } -} - -.tab-item:hover .tab-menu-btn, -.tab-item.active .tab-menu-btn { - opacity: 0.65; -} - -.tab-menu-btn:hover { - background-color: var(--button-active); - opacity: 1 !important; -} - -.tab-menu-dropdown { - display: none; - position: fixed; - min-width: 130px; - background-color: var(--header-bg); - border: 1px solid var(--border-color); - border-radius: 6px; - box-shadow: 0 4px 12px rgba(0,0,0,0.15); - z-index: 99999; - overflow: hidden; - flex-direction: column; -} - -.tab-menu-dropdown.open { - display: flex; -} - -.tab-menu-item { - display: flex; - align-items: center; - gap: 7px; - padding: 7px 12px; - background: none; - border: none; - color: var(--text-color); - font-size: 12px; - cursor: pointer; - text-align: left; - transition: background-color 0.12s ease; - white-space: nowrap; -} - -.tab-menu-item:hover { - background-color: var(--button-hover); -} - -.tab-menu-item-danger { - color: var(--color-danger-fg, #d73a49); -} - -.tab-menu-item-danger:hover { - background-color: rgba(215, 58, 73, 0.1); -} - -/* ======================================== - RESET BUTTON - ======================================== */ - -.tab-reset-btn { - display: flex; - align-items: center; - gap: 4px; - height: 24px; - padding: 0 8px; - border-radius: 5px; - background: none; - border: 1px solid var(--border-color); - color: var(--text-color); - cursor: pointer; - font-size: 12px; - flex-shrink: 0; - margin-left: 6px; - transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease; -} - -.tab-reset-btn:hover { - background-color: rgba(215, 58, 73, 0.1); - border-color: var(--color-danger-fg, #d73a49); - color: var(--color-danger-fg, #d73a49); -} - -/* ======================================== - RESET & RENAME CONFIRMATION MODALS - ======================================== */ - -.reset-modal-overlay { - position: fixed; - inset: 0; - background: rgba(0, 0, 0, 0.45); - z-index: 2000; - display: flex; - align-items: center; - justify-content: center; -} - -.reset-modal-overlay.modal-overlay { - opacity: 0; - visibility: hidden; - transition: opacity 0.2s ease, visibility 0.2s ease; -} - -.reset-modal-overlay.modal-overlay.is-visible { - opacity: 1; - visibility: visible; -} - -.reset-modal-box { - background: var(--header-bg); - border: 1px solid var(--border-color); - border-radius: 10px; - padding: 24px 28px; - min-width: 280px; - max-width: 360px; - box-shadow: 0 8px 32px rgba(0,0,0,0.25); - display: flex; - flex-direction: column; - gap: 16px; -} - -.modal-box { - max-height: min(85vh, 760px); - opacity: 0; - transform: translateY(8px); - transition: transform 0.2s ease, opacity 0.2s ease; -} - -.reset-modal-overlay.modal-overlay.is-visible .modal-box { - opacity: 1; - transform: translateY(0); -} - -.modal-header { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; -} - -.modal-header .reset-modal-message { - text-align: left; - flex: 1; -} - -.modal-close-btn { - border: 1px solid var(--border-color); - background: var(--button-bg); - color: var(--text-color); - border-radius: 6px; - width: 28px; - height: 28px; - display: inline-flex; - align-items: center; - justify-content: center; - cursor: pointer; - transition: background-color 0.15s ease; -} - -.modal-close-btn:hover { - background-color: var(--button-hover); -} - -.modal-body { - display: flex; - flex-direction: column; - gap: 16px; - max-height: min(60vh, 520px); - overflow: auto; - padding-right: 4px; -} - -.modal-section { - display: flex; - flex-direction: column; - gap: 8px; -} - -.modal-section-title { - margin: 0; - font-size: 0.95rem; - font-weight: 600; -} - -.modal-list { - margin: 0; - padding-left: 1.1rem; - display: flex; - flex-direction: column; - gap: 6px; - font-size: 0.85rem; -} - -.modal-list a { - color: var(--accent-color); - text-decoration: none; -} - -.modal-list a:hover { - text-decoration: underline; -} - -.modal-subtext { - margin: 0; - font-size: 12px; - color: var(--text-secondary, #57606a); - line-height: 1.4; -} - -.find-replace-meta { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; -} - -.find-match-count { - font-size: 12px; - color: var(--text-secondary, #57606a); -} - -.find-replace-nav { - display: inline-flex; - gap: 6px; -} - -.find-nav-btn { - width: 28px; - height: 28px; - padding: 0; -} - -.about-header { - display: flex; - align-items: center; - gap: 16px; - flex-wrap: wrap; -} - -.about-logo { - width: 64px; - height: 64px; - border-radius: 12px; - border: 1px solid var(--border-color); - object-fit: cover; -} - -.about-details { - display: flex; - flex-direction: column; - gap: 6px; -} - -.about-title { - margin: 0; - font-size: 1.05rem; - font-weight: 600; -} - -.about-description { - margin: 0; - font-size: 0.85rem; - color: var(--text-secondary, #57606a); -} - -.about-meta { - margin: 0; - font-size: 0.78rem; - color: var(--text-secondary, #57606a); -} - -.modal-body kbd { - padding: 2px 6px; - border-radius: 4px; - background-color: var(--button-bg); - border: 1px solid var(--border-color); - font-size: 0.75rem; - font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; -} - -.reset-modal-box--wide { - width: min(92vw, 640px); - max-width: 640px; -} - -.reset-modal-message { - margin: 0; - font-size: 14px; - color: var(--text-color); - font-weight: 500; - text-align: center; -} - -.reset-modal-actions { - display: flex; - gap: 10px; - justify-content: flex-end; -} - -.reset-modal-btn { - padding: 6px 16px; - border-radius: 6px; - border: 1px solid var(--border-color); - background: var(--button-bg); - color: var(--text-color); - font-size: 13px; - cursor: pointer; - transition: background-color 0.15s ease; -} - -.reset-modal-btn:hover { - background-color: var(--button-hover); -} - -.reset-modal-confirm { - background-color: var(--color-danger-fg, #d73a49); - border-color: var(--color-danger-fg, #d73a49); - color: #fff; -} - -.reset-modal-confirm:hover { - background-color: #b02a37; - border-color: #b02a37; -} - +:root { + --bg-color: #ffffff; + --editor-bg: #f6f8fa; + --preview-bg: #ffffff; /* Preview background for light mode */ + --text-color: #24292e; + --text-secondary: #57606a; + --font-mono: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace; + --color-danger-fg: #d73a49; + --preview-text-color: #24292e; /* Text color for preview in light mode */ + --border-color: #e1e4e8; + --header-bg: #f6f8fa; + --button-bg: #f6f8fa; + --button-hover: #e1e4e8; + --button-active: #d1d5da; + --scrollbar-thumb: #c1c1c1; + --scrollbar-track: #f1f1f1; + --accent-color: #0366d6; + --table-bg: #ffffff; /* Table background for light mode */ + --code-bg: #f6f8fa; /* Code block background for light mode */ + --skeleton-bg: #e2e8f0; + --skeleton-glow: rgba(255, 255, 255, 0.65); + + /* Find & Replace Panel custom properties (PERF-010 consolidated) */ + --fr-bg: rgba(255, 255, 255, 0.95); + --fr-border: #d0d7de; + --fr-shadow: 0 8px 24px rgba(140, 149, 159, 0.2); + --fr-btn-active: #0969da; + --fr-btn-active-bg: #ddf4ff; + --fr-match-highlight: #ffdf5d; + --fr-match-active: #ff9b30; + --fr-match-text-color: #24292e; + --fr-match-active-text-color: #24292e; + --fr-error-bg: #ffebe9; + --fr-error-border: #ff8577; + --fr-text-danger: #cf222e; +} + +[data-theme="dark"] { + --bg-color: #0d1117; + --editor-bg: #161b22; + --preview-bg: #0d1117; /* Preview background for dark mode */ + --text-color: #c9d1d9; + --text-secondary: #8b949e; + --color-danger-fg: #f85149; + --preview-text-color: #c9d1d9; /* Text color for preview in dark mode */ + --border-color: #30363d; + --header-bg: #161b22; + --button-bg: #21262d; + --button-hover: #30363d; + --button-active: #3b434b; + --scrollbar-thumb: #484f58; + --scrollbar-track: #21262d; + --accent-color: #58a6ff; + --table-bg: #161b22; /* Table background for dark mode */ + --code-bg: #161b22; /* Code block background for dark mode */ + --skeleton-bg: #2d3139; + --skeleton-glow: rgba(255, 255, 255, 0.08); + + /* Find & Replace Panel custom properties for dark mode */ + --fr-bg: rgba(28, 33, 40, 0.98); + --fr-border: #444c56; + --fr-shadow: 0 8px 24px rgba(0, 0, 0, 0.5); + --fr-btn-active: #2f81f7; + --fr-btn-active-bg: rgba(56, 139, 253, 0.15); + --fr-match-highlight: rgba(187, 128, 9, 0.4); + --fr-match-active: #ad6200; + --fr-match-text-color: #c9d1d9; + --fr-match-active-text-color: #ffffff; + --fr-error-bg: rgba(248, 81, 73, 0.1); + --fr-error-border: rgba(248, 81, 73, 0.4); + --fr-text-danger: #ff7b72; +} + +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +@media (min-width: 768px) { + html, + body { + height: 100%; + overflow: hidden; + } +} + +body { + background-color: var(--bg-color); + color: var(--text-color); + /* PERF-021: Removed background-color transition to avoid full-viewport repaint on theme toggle */ + transition: color 0.15s ease; + min-height: 100vh; + font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Hiragino Kaku Gothic ProN", Meiryo, "Malgun Gothic", "Apple SD Gothic Neo", "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; +} + +.app-header { + background-color: var(--header-bg); + border-bottom: 1px solid var(--border-color); + padding: 0.35rem 0.75rem; + transition: background-color 0.3s ease; + position: relative; + z-index: 100; + flex-shrink: 0; +} + +.app-container { + height: 100vh; + display: flex; + flex-direction: column; + overflow: hidden; +} + +.content-container { + display: flex; + flex: 1; + overflow: hidden; +} + +.editor-pane, .preview-pane { + flex: 1; + padding: 20px; + overflow-y: auto; + position: relative; + /* PERF-025: Shortened transition and scoped to background-color only */ + transition: background-color 0.15s ease; +} + +.editor-pane { + background-color: var(--editor-bg); + border-right: 1px solid var(--border-color); + padding-right: 0px; + --line-number-gutter: 0px; +} + +.preview-pane { + background-color: var(--preview-bg); /* Using the new variable for preview background */ +} + +/* Custom scrollbar */ +.editor-pane::-webkit-scrollbar, +.preview-pane::-webkit-scrollbar, +#markdown-editor::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +.editor-pane::-webkit-scrollbar-track, +.preview-pane::-webkit-scrollbar-track, +#markdown-editor::-webkit-scrollbar-track { + background: var(--scrollbar-track); +} + +.editor-pane::-webkit-scrollbar-thumb, +.preview-pane::-webkit-scrollbar-thumb, +#markdown-editor::-webkit-scrollbar-thumb { + background: var(--scrollbar-thumb); + border-radius: 4px; +} + +.editor-pane::-webkit-scrollbar-thumb:hover, +.preview-pane::-webkit-scrollbar-thumb:hover, +#markdown-editor::-webkit-scrollbar-thumb:hover { + background: var(--button-active); +} + +#markdown-editor { + width: 100%; + height: 100%; + border: none; + background-color: transparent; + color: var(--text-color); + resize: none; + font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; + font-size: 14px; + line-height: 1.5; + padding: 10px; + padding-left: calc(10px + var(--line-number-gutter)); + transition: background-color 0.3s ease, color 0.3s ease; + overflow-y: auto; + position: relative; + z-index: 3; +} + +#markdown-editor:focus { + outline: none; +} + +.preview-pane { + padding: 20px; +} + +.markdown-body { + padding: 20px; + width: 100%; + background-color: var(--preview-bg); /* Ensuring the markdown content matches preview background */ + color: var(--preview-text-color); /* Using specific text color for preview content */ +} + +.markdown-body a.reference-link { + font-size: 0.75em; + letter-spacing: -0.02em; + line-height: 1; + vertical-align: super; + position: relative; + top: 0.08em; +} + +/* Style tables in light mode */ +.markdown-body table { + background-color: var(--table-bg); + border-color: var(--border-color); +} + +.markdown-body table tr { + background-color: var(--table-bg); + border-top: 1px solid var(--border-color); +} + +.markdown-body table tr:nth-child(2n) { + background-color: var(--bg-color); +} + +/* Style code blocks in light mode */ +.markdown-body pre { + background-color: var(--code-bg); + border-radius: 6px; +} + +.markdown-body code { + background-color: var(--code-bg); + border-radius: 3px; + padding: 0.2em 0.4em; +} + +.markdown-body img.emoji-inline { + width: 1em; + height: 1em; + vertical-align: -0.1em; +} + +.markdown-body ul, +.markdown-body ol { + padding-left: 2em; + margin: 0.4em 0; +} + +.markdown-body ul ul, +.markdown-body ul ol, +.markdown-body ol ul, +.markdown-body ol ol { + margin-top: 0.2em; + margin-bottom: 0.2em; +} + +.markdown-body ul.contains-task-list, +.markdown-body li.task-list-item { + list-style: none; +} + +.markdown-body ul.contains-task-list { + padding-left: 2em; +} + +.markdown-body li.task-list-item input[type="checkbox"] { + margin: 0 0.5em 0.2em 0; + vertical-align: middle; + pointer-events: none; +} + +.markdown-body li.task-list-item::marker { + content: ""; +} + +.markdown-body li:has(> input[type="checkbox"]) { + list-style: none; +} + +.markdown-body li:has(> input[type="checkbox"])::marker { + content: ""; +} + +.markdown-body ul:has(> li > input[type="checkbox"]) { + list-style: none; + padding-left: 2em; +} + +.markdown-body .footnotes { + margin-top: 1.5rem; + font-size: 0.9em; +} + +.markdown-body .footnotes ol { + padding-left: 1.5em; +} + +.markdown-body .footnotes ol > li::marker { + content: "[" counter(list-item) "] "; + font-weight: 600; +} + +.markdown-body .footnotes li > p { + margin: 0.2em 0; +} + +.markdown-body .footnote-ref a, +.markdown-body .footnote-backref { + text-decoration: none; +} + +.markdown-body .footnote-backref { + margin-left: 0.4em; +} + +.markdown-body .markdown-alert { + padding: 0.5rem 1rem; + margin-bottom: 16px; + border-left: 0.25em solid; + border-radius: 0.375rem; +} + +.markdown-body .markdown-alert > :last-child { + margin-bottom: 0; +} + +.markdown-body .markdown-alert-title { + margin: 0 0 8px; + font-weight: 600; + line-height: 1.25; + display: flex; + align-items: center; + gap: 8px; +} + +.markdown-body .markdown-alert-icon { + display: inline-flex; + width: 16px; + height: 16px; +} + +.markdown-body .markdown-alert-icon svg { + width: 16px; + height: 16px; + fill: currentColor; +} + +.markdown-body .markdown-alert-note { + color: #0969da; + border-left-color: #0969da; + background-color: #ddf4ff; +} + +.markdown-body .markdown-alert-tip { + color: #1a7f37; + border-left-color: #1a7f37; + background-color: #dafbe1; +} + +.markdown-body .markdown-alert-important { + color: #8250df; + border-left-color: #8250df; + background-color: #fbefff; +} + +.markdown-body .markdown-alert-warning { + color: #9a6700; + border-left-color: #9a6700; + background-color: #fff8c5; +} + +.markdown-body .markdown-alert-caution { + color: #cf222e; + border-left-color: #cf222e; + background-color: #ffebe9; +} + +.markdown-body .markdown-alert > *:not(.markdown-alert-title) { + color: var(--preview-text-color); +} + +[data-theme="dark"] .markdown-body .markdown-alert-note { + color: #4493f8; + background-color: rgba(31, 111, 235, 0.15); + border-left-color: #4493f8; +} + +[data-theme="dark"] .markdown-body .markdown-alert-tip { + color: #3fb950; + background-color: rgba(35, 134, 54, 0.15); + border-left-color: #3fb950; +} + +[data-theme="dark"] .markdown-body .markdown-alert-important { + color: #ab7df8; + background-color: rgba(137, 87, 229, 0.15); + border-left-color: #ab7df8; +} + +[data-theme="dark"] .markdown-body .markdown-alert-warning { + color: #d29922; + background-color: rgba(210, 153, 34, 0.18); + border-left-color: #d29922; +} + +[data-theme="dark"] .markdown-body .markdown-alert-caution { + color: #f85149; + background-color: rgba(248, 81, 73, 0.18); + border-left-color: #f85149; +} + +.toolbar { + display: flex; + gap: 8px; + align-items: center; +} + +.toolbar-group { + display: inline-flex; + align-items: center; + gap: 6px; +} + +.toolbar-divider { + width: 1px; + height: 20px; + background-color: var(--border-color); + opacity: 0.7; +} + +.tool-button { + background-color: var(--button-bg); + border: 1px solid var(--border-color); + color: var(--text-color); + border-radius: 5px; + padding: 4px 8px; + font-size: 13px; + cursor: pointer; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 4px; + /* PERF-016: Specific transition properties instead of 'all' to avoid animating layout-triggering properties */ + transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease; +} + +.tool-button:hover { + background-color: var(--button-hover); +} + +.tool-button:active { + background-color: var(--button-active); +} + +.tool-button:disabled, +.tool-button[aria-disabled="true"] { + cursor: not-allowed; + opacity: 0.5; +} + +.tool-button i { + font-size: 15px; +} + +.tool-button.is-active, +.tool-button.is-active:hover { + border-color: var(--accent-color); + color: var(--accent-color); + background-color: rgba(3, 102, 214, 0.08); +} + +.btn-text { + display: none; +} + +.toolbar .tool-button { + height: 28px; + min-width: 28px; +} + +.toolbar .tool-button.sync-active { + border-color: var(--accent-color); + color: var(--accent-color); +} + +.file-input { + display: none; +} + +/* Drag overlay: full-screen drop target shown when user drags a file over the window */ +.drag-overlay { + display: none; + position: fixed; + inset: 0; + z-index: 9999; + background-color: rgba(0, 0, 0, 0.45); + pointer-events: none; + align-items: center; + justify-content: center; +} + +.drag-overlay.active { + display: flex; + pointer-events: auto; +} + +.drag-overlay-inner { + border: 3px dashed var(--accent-color); + border-radius: 12px; + padding: 48px 64px; + text-align: center; + color: #ffffff; + background-color: rgba(3, 102, 214, 0.15); + animation: overlayPulse 1.4s ease-in-out infinite; +} + +.drag-overlay-icon { + display: block; + font-size: 3rem; + margin-bottom: 12px; + color: var(--accent-color); +} + +.drag-overlay-text { + font-size: 1.4rem; + font-weight: 600; + margin-bottom: 4px; +} + +.drag-overlay-sub { + font-size: 0.85rem; + opacity: 0.75; + margin-bottom: 0; +} + +@keyframes overlayPulse { + 0%, 100% { transform: scale(1); } + 50% { transform: scale(1.015); } +} + +/* Editor drop hint: subtle text at bottom of editor pane, shown only when empty */ +.drop-hint { + position: absolute; + bottom: 14px; + left: 0; + right: 0; + text-align: center; + font-size: 0.75rem; + color: var(--text-color); + opacity: 0.35; + pointer-events: none; + user-select: none; + z-index: 3; +} + +.editor-pane:has(#markdown-editor:not(:placeholder-shown)) .drop-hint { + display: none; +} + +.line-numbers { + position: absolute; + top: 20px; + bottom: 20px; + left: 20px; + width: var(--line-number-gutter); + padding: 10px 8px 10px 0; + font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; + font-size: 14px; + line-height: 1.5; + text-align: right; + color: var(--text-secondary); + background-color: var(--editor-bg); + border-right: 1px solid var(--border-color); + box-sizing: border-box; + overflow: hidden; + pointer-events: none; + user-select: none; + z-index: 2; + font-variant-numeric: tabular-nums; +} + +.line-numbers .line-number { + display: block; + height: auto; +} + +.editor-highlight-layer { + position: absolute; + inset: 20px 0 20px calc(20px + var(--line-number-gutter)); + padding: 10px; + font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; + font-size: 14px; + line-height: 1.5; + white-space: pre-wrap; + word-wrap: break-word; + color: transparent; + pointer-events: none; + overflow: auto; + background-color: var(--editor-bg); + border-radius: 4px; + z-index: 1; +} + +.editor-highlight-layer::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +.editor-highlight-layer::-webkit-scrollbar-thumb { + background: transparent; +} + +.editor-highlight-layer::-webkit-scrollbar-track { + background: transparent; +} + +.find-highlight { + background-color: var(--fr-match-highlight, rgba(255, 223, 93, 0.4)) !important; + border-radius: 2px; + color: transparent !important; + padding: 0 !important; + margin: 0 !important; +} + +.find-highlight.active { + background-color: var(--fr-match-active, #ff9b30) !important; + color: transparent !important; + padding: 0 !important; + margin: 0 !important; + outline: 1px solid var(--accent-color, #0366d6) !important; + outline-offset: -1px; +} + +.preview-find-highlight { + background-color: var(--fr-match-highlight, rgba(255, 223, 93, 0.4)) !important; + color: var(--fr-match-text-color, inherit) !important; + border-radius: 2px; + padding: 0 1px !important; + margin: 0 !important; +} + +.preview-find-highlight.active { + background-color: var(--fr-match-active, #ff9b30) !important; + color: var(--fr-match-active-text-color, inherit) !important; + outline: 1px solid var(--accent-color, #0366d6) !important; + outline-offset: -1px; +} + +/* Dropdown improvements */ +.dropdown-menu { + background-color: var(--bg-color); + border-color: var(--border-color); +} + +.dropdown-item { + color: var(--text-color); +} + +.dropdown-item:hover, .dropdown-item:focus { + background-color: var(--button-hover); + color: var(--text-color); +} + +/* Markdown formatting toolbar */ +.markdown-format-toolbar { + display: flex; + align-items: center; + height: 34px; + padding: 0 6px; + background-color: var(--header-bg); + border-bottom: 1px solid var(--border-color); + overflow-x: auto; + overflow-y: hidden; + flex-shrink: 0; + scrollbar-width: none; + -ms-overflow-style: none; +} + +.markdown-format-toolbar::-webkit-scrollbar { + display: none; +} + +.markdown-toolbar-group { + display: flex; + align-items: center; + gap: 2px; + height: 100%; + padding: 0 6px; + border-right: 1px solid var(--border-color); + flex-shrink: 0; +} + +.markdown-toolbar-group:first-child { + padding-left: 0; +} + +.markdown-toolbar-group:last-child { + border-right: none; + padding-right: 0; +} + +.markdown-tool-btn { + display: inline-flex; + align-items: center; + justify-content: center; + width: 26px; + height: 26px; + border: 1px solid transparent; + border-radius: 4px; + background: transparent; + color: var(--text-color); + cursor: pointer; + font-size: 14px; + line-height: 1; + padding: 0; + transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease; +} + +.markdown-tool-btn:hover, +.markdown-tool-btn:focus-visible { + background-color: var(--button-hover); + border-color: var(--border-color); + color: var(--accent-color); +} + +.markdown-tool-btn:active { + background-color: var(--button-active); +} + +.markdown-tool-btn:disabled, +.markdown-tool-btn.disabled { + opacity: 0.4; + cursor: not-allowed; + pointer-events: none; +} + +.markdown-tool-btn i { + font-size: 15px; +} + +.markdown-tool-btn[data-md-action="reference"] i::before { + content: "[ ]"; + font-style: normal; + font-size: 12px; + letter-spacing: -0.12em; +} + +.markdown-tool-btn.text-tool { + width: auto; + min-width: 26px; + padding: 0 5px; + font-weight: 600; + font-family: Georgia, "Times New Roman", serif; +} + +.heading-group .markdown-tool-btn { + min-width: 30px; +} + + + +/* Loading indicators */ +.loading { + opacity: 0.6; + pointer-events: none; +} + +/* Focus outline for accessibility */ +button:focus, +a:focus { + outline: 2px solid var(--accent-color); + outline-offset: 2px; +} + +/* Animation for copied message */ +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +/* Tooltip styles */ +.tooltip { + position: absolute; + background: var(--button-bg); + border: 1px solid var(--border-color); + padding: 5px 8px; + border-radius: 4px; + font-size: 12px; + z-index: 1000; + animation: fadeIn 0.2s ease; +} + +/* Styles for GitHub markdown preview light mode */ +.markdown-body { + color-scheme: light; + --color-prettylights-syntax-comment: #6a737d; + --color-prettylights-syntax-constant: #005cc5; + --color-prettylights-syntax-entity: #6f42c1; + --color-prettylights-syntax-storage-modifier-import: #24292e; + --color-prettylights-syntax-entity-tag: #22863a; + --color-prettylights-syntax-keyword: #cf222e; + --color-prettylights-syntax-string: #032f62; + --color-prettylights-syntax-variable: #e36209; + --color-prettylights-syntax-brackethighlighter-unmatched: #b31d28; + --color-prettylights-syntax-invalid-illegal-text: #fafbfc; + --color-prettylights-syntax-invalid-illegal-bg: #b31d28; + --color-prettylights-syntax-carriage-return-text: #fafbfc; + --color-prettylights-syntax-carriage-return-bg: #d73a49; + --color-prettylights-syntax-string-regexp: #22863a; + --color-prettylights-syntax-markup-list: #735c0f; + --color-prettylights-syntax-markup-heading: #005cc5; + --color-prettylights-syntax-markup-italic: #24292e; + --color-prettylights-syntax-markup-bold: #24292e; + --color-prettylights-syntax-markup-deleted-text: #b31d28; + --color-prettylights-syntax-markup-deleted-bg: #ffeef0; + --color-prettylights-syntax-markup-inserted-text: #22863a; + --color-prettylights-syntax-markup-inserted-bg: #f0fff4; + --color-prettylights-syntax-markup-changed-text: #e36209; + --color-prettylights-syntax-markup-changed-bg: #ffebda; + --color-prettylights-syntax-markup-ignored-text: #f6f8fa; + --color-prettylights-syntax-markup-ignored-bg: #005cc5; + --color-prettylights-syntax-meta-diff-range: #6f42c1; + --color-prettylights-syntax-brackethighlighter-angle: #586069; + --color-prettylights-syntax-sublimelinter-gutter-mark: #e1e4e8; + --color-prettylights-syntax-constant-other-reference-link: #032f62; + --color-fg-default: #24292e; + --color-fg-muted: #586069; + --color-fg-subtle: #6a737d; + --color-canvas-default: #ffffff; + --color-canvas-subtle: #f6f8fa; + --color-border-default: #e1e4e8; + --color-border-muted: #eaecef; + --color-neutral-muted: rgba(175,184,193,0.2); + --color-accent-fg: #0366d6; + --color-accent-emphasis: #0366d6; + --color-attention-subtle: #fff5b1; + --color-danger-fg: #d73a49; +} + +/* Styles for GitHub markdown preview dark mode */ +[data-theme="dark"] .markdown-body { + color-scheme: dark; + --color-prettylights-syntax-comment: #8b949e; + --color-prettylights-syntax-constant: #79c0ff; + --color-prettylights-syntax-entity: #d2a8ff; + --color-prettylights-syntax-storage-modifier-import: #c9d1d9; + --color-prettylights-syntax-entity-tag: #7ee787; + --color-prettylights-syntax-keyword: #ff7b72; + --color-prettylights-syntax-string: #a5d6ff; + --color-prettylights-syntax-variable: #ffa657; + --color-prettylights-syntax-brackethighlighter-unmatched: #f85149; + --color-prettylights-syntax-invalid-illegal-text: #f0f6fc; + --color-prettylights-syntax-invalid-illegal-bg: #8e1519; + --color-prettylights-syntax-carriage-return-text: #f0f6fc; + --color-prettylights-syntax-carriage-return-bg: #b62324; + --color-prettylights-syntax-string-regexp: #7ee787; + --color-prettylights-syntax-markup-list: #f2cc60; + --color-prettylights-syntax-markup-heading: #1f6feb; + --color-prettylights-syntax-markup-italic: #c9d1d9; + --color-prettylights-syntax-markup-bold: #c9d1d9; + --color-prettylights-syntax-markup-deleted-text: #ffdcd7; + --color-prettylights-syntax-markup-deleted-bg: #67060c; + --color-prettylights-syntax-markup-inserted-text: #aff5b4; + --color-prettylights-syntax-markup-inserted-bg: #033a16; + --color-prettylights-syntax-markup-changed-text: #ffdfb6; + --color-prettylights-syntax-markup-changed-bg: #5a1e02; + --color-prettylights-syntax-markup-ignored-text: #c9d1d9; + --color-prettylights-syntax-markup-ignored-bg: #1158c7; + --color-prettylights-syntax-meta-diff-range: #d2a8ff; + --color-prettylights-syntax-brackethighlighter-angle: #8b949e; + --color-prettylights-syntax-sublimelinter-gutter-mark: #484f58; + --color-prettylights-syntax-constant-other-reference-link: #a5d6ff; + --color-fg-default: #c9d1d9; + --color-fg-muted: #8b949e; + --color-fg-subtle: #484f58; + --color-canvas-default: #0d1117; + --color-canvas-subtle: #161b22; + --color-border-default: #30363d; + --color-border-muted: #21262d; + --color-neutral-muted: rgba(110,118,129,0.4); + --color-accent-fg: #58a6ff; + --color-accent-emphasis: #1f6feb; + --color-attention-subtle: rgba(187,128,9,0.15); + --color-danger-fg: #f85149; +} + +/* Override specific styles for dark mode tables and code */ +[data-theme="dark"] .markdown-body table tr { + background-color: var(--table-bg); +} + +[data-theme="dark"] .markdown-body table tr:nth-child(2n) { + background-color: #1c2128; /* Slightly lighter than base dark background */ +} + +[data-theme="dark"] .markdown-body pre { + background-color: var(--code-bg); +} + +[data-theme="dark"] .markdown-body code { + background-color: var(--code-bg); +} + +/* Syntax Highlighting Mapping to GitHub Variables */ +.hljs { + color: var(--color-fg-default); +} +.hljs-doctag, +.hljs-keyword, +.hljs-meta .hljs-keyword, +.hljs-template-tag, +.hljs-template-variable, +.hljs-type, +.hljs-variable.language_ { + color: var(--color-prettylights-syntax-keyword); +} +.hljs-title, +.hljs-title.class_, +.hljs-title.class_.inherited__, +.hljs-title.function_ { + color: var(--color-prettylights-syntax-entity); +} +.hljs-attr, +.hljs-attribute, +.hljs-literal, +.hljs-meta, +.hljs-number, +.hljs-operator, +.hljs-variable, +.hljs-selector-attr, +.hljs-selector-class, +.hljs-selector-id { + color: var(--color-prettylights-syntax-constant); +} +.hljs-regexp, +.hljs-string, +.hljs-meta .hljs-string { + color: var(--color-prettylights-syntax-string); +} +.hljs-built_in, +.hljs-symbol { + color: var(--color-prettylights-syntax-variable); +} +.hljs-comment, +.hljs-code, +.hljs-formula { + color: var(--color-prettylights-syntax-comment); +} +.hljs-name, +.hljs-quote, +.hljs-selector-tag, +.hljs-selector-pseudo { + color: var(--color-prettylights-syntax-entity-tag); +} +.hljs-subst { + color: var(--color-fg-default); +} +.hljs-section { + color: var(--color-prettylights-syntax-markup-heading); + font-weight: bold; +} +.hljs-bullet { + color: var(--color-prettylights-syntax-constant); +} +.hljs-emphasis { + color: var(--color-fg-default); + font-style: italic; +} +.hljs-strong { + color: var(--color-fg-default); + font-weight: bold; +} +.hljs-addition { + color: var(--color-prettylights-syntax-markup-inserted-text); + background-color: var(--color-prettylights-syntax-markup-inserted-bg); +} +.hljs-deletion { + color: var(--color-prettylights-syntax-markup-deleted-text); + background-color: var(--color-prettylights-syntax-markup-deleted-bg); +} + +.stats-container { + font-size: 0.8rem; + color: var(--text-color); +} + +.stat-item { + align-items: center; +} + +.stat-item i { + font-size: 0.9rem; + opacity: 0.8; +} + +#importDropdown, +#exportDropdown, +#languageDropdown { + font-size: 0.8rem; +} + +#importDropdown i, +#exportDropdown i, +#languageDropdown i { + font-size: 0.9rem; +} + +/* Ensure desktop dropdown menu options match the stats-container font size */ +[aria-labelledby="importDropdown"] .dropdown-item, +[aria-labelledby="exportDropdown"] .dropdown-item, +[aria-labelledby="languageDropdown"] .dropdown-item { + font-size: 0.8rem; +} + +/* Ensure mobile menu import, export, and language dropdown triggers/options match the mobile stats-container font size */ +#mobile-import-button, +#mobile-import-github-button, +#mobile-export-md, +#mobile-export-html, +#mobile-export-pdf, +#mobileLanguageDropdown { + font-size: 0.9rem !important; +} + +[aria-labelledby="mobileLanguageDropdown"] .dropdown-item { + font-size: 0.9rem; +} + +.editor-pane { + overflow: hidden; +} + +/* Mobile Menu Styles */ +.mobile-menu { + display: none; + position: relative; + z-index: 1001; +} + + + +/* slide‑in panel */ +.mobile-menu-panel { + position: fixed; + top: 0; + right: -300px; + width: 280px; + height: 100vh; + background-color: var(--bg-color); + box-shadow: -2px 0 10px rgba(0, 0, 0, 0.2); + transition: right 0.3s ease; + overflow-y: auto; + padding: 1rem; + display: flex; + flex-direction: column; + z-index: 1002; +} + +.mobile-menu-panel.active { + right: 0; +} + +/* translucent overlay behind panel */ +.mobile-menu-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100vh; + background-color: rgba(0, 0, 0, 0.5); + opacity: 0; + visibility: hidden; + pointer-events: none; + transition: opacity 0.3s ease, visibility 0.3s ease; + z-index: 1000; +} + +.mobile-menu-overlay.active { + opacity: 1; + visibility: visible; + pointer-events: auto; +} + +/* header inside mobile menu */ +.mobile-menu-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1rem; +} + +.mobile-menu-header h5 { + margin: 0; + font-size: 1.25rem; + color: var(--text-color); +} + +/* stats section in mobile menu */ +.mobile-stats-container { + border-bottom: 1px solid var(--border-color); + padding-bottom: 0.75rem; + margin-bottom: 1rem; +} + +.mobile-stats-container .stat-item { + font-size: 0.9rem; + color: var(--text-color); + display: flex; + align-items: center; +} + +.mobile-stats-container .stat-item i { + margin-right: 0.5em; + opacity: 0.8; +} + +/* menu buttons list */ +.mobile-menu-items { + display: flex; + flex-direction: column; + gap: 0.5rem; + flex-grow: 1; +} + +/* each menu item */ +.mobile-menu-item { + background-color: var(--button-bg); + border: 1px solid var(--border-color); + color: var(--text-color); + border-radius: 6px; + padding: 0.6rem 1rem; + font-size: 1rem; + text-align: left; + display: flex; + align-items: center; + gap: 0.5rem; + transition: background-color 0.2s ease; + cursor: pointer; +} + +.mobile-menu-item:hover { + background-color: var(--button-hover); +} + +.mobile-menu-item:active { + background-color: var(--button-active); +} + +/* close button override */ +#close-mobile-menu.tool-button { + padding: 0.25rem 0.5rem; + font-size: 1rem; +} + +/* Mobile document tabs section */ +.mobile-tabs-section { + border-bottom: 1px solid var(--border-color); + padding-bottom: 0.75rem; +} + +.mobile-tabs-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 0.5rem; +} + +.mobile-tabs-label { + font-size: 0.85rem; + font-weight: 600; + color: var(--text-color); + opacity: 0.8; + text-transform: uppercase; + letter-spacing: 0.04em; +} + +.mobile-new-tab-btn { + background: none; + border: 1px solid var(--border-color); + border-radius: 4px; + color: var(--text-color); + padding: 2px 7px; + font-size: 0.9rem; + cursor: pointer; + display: flex; + align-items: center; + transition: background-color 0.15s ease; +} + +.mobile-new-tab-btn:hover { + background-color: var(--button-hover); +} + +.mobile-tab-list { + display: flex; + flex-direction: column; + gap: 4px; + max-height: 180px; + overflow-y: auto; +} + +.mobile-tab-item { + display: flex; + align-items: center; + justify-content: space-between; + background-color: var(--button-bg); + border: 1px solid var(--border-color); + border-radius: 6px; + padding: 0.45rem 0.75rem; + font-size: 0.9rem; + color: var(--text-color); + cursor: pointer; + transition: background-color 0.15s ease; + gap: 0.5rem; +} + +.mobile-tab-item:hover { + background-color: var(--button-hover); +} + +.mobile-tab-item.active { + border-color: var(--accent-color); + color: var(--accent-color); + background-color: var(--bg-color); +} + +.mobile-tab-title { + flex: 1; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + min-width: 0; +} + +.mobile-tab-item .tab-menu-btn { + opacity: 0.6; +} + +.mobile-tab-item:hover .tab-menu-btn, +.mobile-tab-item.active .tab-menu-btn { + opacity: 0.8; +} + +#mobile-tab-reset-btn { + margin-left: 0; + height: auto; + padding: 0.45rem 0.75rem; + justify-content: center; + font-size: 0.9rem; +} + +/* ========================================== + NAVBAR RESPONSIVE BREAKPOINTS + >= 1080px : full desktop navbar + < 1080px : mobile hamburger + stacked panes + ========================================== */ + +/* Mobile / tablet (< 1080px): switch to hamburger, stack panes */ +@media (max-width: 1079px) { + /* Override Bootstrap d-md-flex / d-md-none so the breakpoint is 1080px */ + .stats-container, + .toolbar { + display: none !important; + } + + /* Expand touch target sizes to meet WCAG mobile guidelines */ + .markdown-tool-btn { + width: 36px !important; + height: 36px !important; + font-size: 16px !important; + } + .markdown-format-toolbar { + height: 44px !important; + } + .tab-close-btn { + width: 28px !important; + height: 28px !important; + font-size: 14px !important; + } + .tab-menu-btn { + width: 28px !important; + height: 28px !important; + font-size: 14px !important; + } + + .mobile-menu { + display: block !important; + } + + /* Stack editor and preview vertically */ + .content-container { + flex-direction: column; + } + + .editor-pane, + .preview-pane { + flex: none; + height: 50%; + border-right: none; + } + + .editor-pane { + border-bottom: 1px solid var(--border-color); + } + + /* Hide drag-resize divider (touch devices don't use it) */ + .resize-divider { + display: none; + } + + /* Single-pane view modes: occupy full height */ + .content-container.view-editor-only .editor-pane, + .content-container.view-preview-only .preview-pane { + height: 100%; + } + + .content-container.view-split .editor-pane, + .content-container.view-split .preview-pane { + height: 50%; + } +} + +.github-link { + color: var(--text-color); + text-decoration: none; + display: flex; + align-items: center; + justify-content: center; + transition: transform 0.2s ease, color 0.2s ease; + margin-right: 2rem; +} + +.github-link:hover { + color: var(--accent-color); + transform: scale(1.1); +} + +.github-link i { + font-size: 1.25rem; +} + +/* ======================================== + HEADER LAYOUT + ======================================== */ +.header-container { + position: relative; + min-height: 30px; +} + +.app-header h1 { + font-size: 1.05rem; + line-height: 1.1; +} + +.header-left { + flex: 1 0 auto; + justify-content: flex-start; + white-space: nowrap; +} + +.header-right { + flex: 1 0 auto; + justify-content: flex-end; + white-space: nowrap; +} + +/* Pane View States */ +.content-container.view-editor-only .preview-pane { + display: none; +} + +.content-container.view-editor-only .editor-pane { + flex: 1; + border-right: none; +} + +.content-container.view-preview-only .editor-pane { + display: none; +} + +.content-container.view-preview-only .preview-pane { + flex: 1; +} + +.content-container.view-split .editor-pane, +.content-container.view-split .preview-pane { + flex: 1; +} + +/* Compact desktop (< 1280px): compact toolbar */ +@media (max-width: 1280px) { + /* Compact toolbar at medium widths */ + .toolbar { + gap: 4px; + } +} + + + +/* ======================================== + RESIZE DIVIDER - Story 1.3 + ======================================== */ + +.resize-divider { + width: 8px; + background-color: transparent; + cursor: col-resize; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + position: relative; + z-index: 10; + transition: background-color 0.2s ease; +} + +.resize-divider:hover { + background-color: var(--button-hover); +} + +.resize-divider.dragging { + background-color: var(--accent-color); +} + +.resize-divider-handle { + width: 2px; + height: 40px; + background-color: var(--border-color); + border-radius: 2px; + transition: background-color 0.2s ease, width 0.2s ease; +} + +.resize-divider:hover .resize-divider-handle, +.resize-divider.dragging .resize-divider-handle { + background-color: var(--accent-color); + width: 3px; +} + +/* Hide divider in single-pane modes */ +.content-container.view-editor-only .resize-divider, +.content-container.view-preview-only .resize-divider { + display: none; +} + + + +/* Prevent text selection during drag */ +.resizing { + user-select: none; + cursor: col-resize !important; +} + +.resizing * { + cursor: col-resize !important; +} + +.resizing #markdown-preview, +.resizing #markdown-editor, +.resizing .line-numbers { + pointer-events: none !important; +} + +/* ======================================== + MOBILE VIEW MODE CONTROLS - Story 1.4 + ======================================== */ + +.mobile-view-mode-group { + display: flex; + gap: 0; + border-bottom: 1px solid var(--border-color); + padding-bottom: 0.75rem; +} + +.mobile-view-mode-btn { + flex: 1; + background-color: var(--button-bg); + border: 1px solid var(--border-color); + color: var(--text-color); + padding: 8px 12px; + font-size: 14px; + cursor: pointer; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 4px; + transition: all 0.2s ease; +} + +.mobile-view-mode-btn:first-child { + border-radius: 6px 0 0 6px; +} + +.mobile-view-mode-btn:last-child { + border-radius: 0 6px 6px 0; +} + +.mobile-view-mode-btn:not(:last-child) { + border-right: none; +} + +.mobile-view-mode-btn:hover, +.mobile-view-mode-btn:active { + background-color: var(--button-hover); +} + +.mobile-view-mode-btn.active { + background-color: var(--button-bg); + border-color: var(--accent-color); + color: var(--accent-color); + border-width: 2px; + padding: 7px 11px; +} + +.mobile-view-mode-btn.active:not(:last-child) { + border-right: 2px solid var(--accent-color); +} + +.mobile-view-mode-btn i { + font-size: 18px; +} + +.mobile-view-mode-btn span { + font-size: 12px; +} + +/* ======================================== + RESPONSIVE VIEW MODE FIXES - Story 1.5 + ======================================== */ + + + +/* ======================================== + PDF EXPORT TABLE FIX - Rowspan/Colspan + ======================================== */ + +/* Fix for html2canvas not properly rendering rowspan/colspan cells. + Apply backgrounds to cells instead of rows to prevent row backgrounds + from painting over rowspan cells during canvas capture. */ +.pdf-export table tr { + background-color: transparent !important; +} + +.pdf-export table th, +.pdf-export table td { + background-color: var(--table-bg, #ffffff); + position: relative; +} + +.pdf-export table tr:nth-child(2n) th, +.pdf-export table tr:nth-child(2n) td { + background-color: var(--bg-color, #f6f8fa); +} + +/* Ensure rowspan cells render correctly */ +.pdf-export table th[rowspan], +.pdf-export table td[rowspan] { + vertical-align: middle; + background-color: var(--table-bg, #ffffff) !important; +} + +/* Ensure colspan cells render correctly */ +.pdf-export table th[colspan], +.pdf-export table td[colspan] { + text-align: center; +} + +/* Dark mode PDF export table fix */ +[data-theme="dark"] .pdf-export table th, +[data-theme="dark"] .pdf-export table td { + background-color: var(--table-bg, #161b22); +} + +[data-theme="dark"] .pdf-export table tr:nth-child(2n) th, +[data-theme="dark"] .pdf-export table tr:nth-child(2n) td { + background-color: #1c2128; +} + +[data-theme="dark"] .pdf-export table th[rowspan], +[data-theme="dark"] .pdf-export table td[rowspan] { + background-color: var(--table-bg, #161b22) !important; +} + +/* ======================================== + MERMAID DIAGRAM TOOLBAR + ======================================== */ + +.mermaid-container { + position: relative; +} + +.mermaid-toolbar { + position: absolute; + top: 8px; + right: 8px; + display: flex; + gap: 4px; + opacity: 0; + transition: opacity 0.2s ease; + z-index: 10; +} + +.mermaid-container:hover .mermaid-toolbar { + opacity: 1; +} + +.mermaid-toolbar-btn { + background-color: var(--button-bg); + border: 1px solid var(--border-color); + color: var(--text-color); + border-radius: 4px; + padding: 4px 7px; + font-size: 13px; + cursor: pointer; + display: flex; + align-items: center; + gap: 3px; + transition: background-color 0.2s ease, color 0.2s ease; + white-space: nowrap; +} + +.mermaid-toolbar-btn:hover { + background-color: var(--button-hover); + color: var(--accent-color); +} + +.mermaid-toolbar-btn:active { + background-color: var(--button-active); +} + +.mermaid-toolbar-btn i { + font-size: 14px; +} + +/* ======================================== + MERMAID ZOOM MODAL + ======================================== */ + +#mermaid-zoom-modal { + display: none; + position: fixed; + inset: 0; + z-index: 2000; + background-color: rgba(0, 0, 0, 0.75); + align-items: center; + justify-content: center; +} + +#mermaid-zoom-modal.active { + display: flex; +} + +.mermaid-modal-content { + background-color: var(--bg-color); + border: 1px solid var(--border-color); + border-radius: 8px; + padding: 16px; + width: 85vw; + height: 85vh; + max-width: 85vw; + max-height: 85vh; + display: flex; + flex-direction: column; + gap: 12px; +} + +@media (max-width: 576px) { + .mermaid-modal-content { + width: 95vw; + height: 90vh; + max-width: 95vw; + max-height: 90vh; + padding: 10px; + } +} + +.mermaid-modal-header { + display: flex; + justify-content: space-between; + align-items: center; +} + +.mermaid-modal-header span { + font-weight: 600; + font-size: 15px; + color: var(--text-color); +} + +.mermaid-modal-close { + background: none; + border: none; + color: var(--text-color); + font-size: 1.2rem; + cursor: pointer; + padding: 2px 6px; + border-radius: 4px; + display: flex; + align-items: center; + transition: background-color 0.2s ease; +} + +.mermaid-modal-close:hover { + background-color: var(--button-hover); +} + +.mermaid-modal-diagram { + overflow: auto; + flex: 1; + display: flex; + align-items: center; + justify-content: center; + min-height: 200px; + cursor: grab; +} + +.mermaid-modal-diagram.dragging { + cursor: grabbing; +} + +.mermaid-modal-diagram svg { + transform-origin: center; + transition: transform 0.1s ease; + max-width: none; +} + +.mermaid-modal-controls { + display: flex; + justify-content: center; + gap: 8px; + flex-wrap: wrap; +} + +.mermaid-modal-controls .mermaid-toolbar-btn { + opacity: 1; +} + +/* ======================================== + DOCUMENT TABS & SESSION MANAGEMENT + ======================================== */ + +.tab-bar { + display: flex; + align-items: center; + background-color: var(--header-bg); + border-bottom: 1px solid var(--border-color); + height: 32px; + overflow: visible; /* ← was: overflow: hidden */ + flex-shrink: 0; + padding: 0 4px; + gap: 0; + user-select: none; + position: relative; + z-index: 10; +} + +.tab-list { + display: flex; + align-items: flex-end; + overflow-x: auto; + overflow-y: visible; /* ← was: overflow-y: hidden */ + flex: 1; + height: 100%; + scrollbar-width: none; + -ms-overflow-style: none; +} + +.tab-list::-webkit-scrollbar { + display: none; +} + +.tab-item { + display: flex; + align-items: center; + gap: 6px; + height: 32px; + padding: 0 8px 0 10px; + min-width: 100px; + max-width: 180px; + background-color: var(--button-bg); + border: 1px solid var(--border-color); + border-bottom: 1px solid transparent; + border-radius: 6px 6px 0 0; + cursor: pointer; + font-size: 13px; + color: var(--text-color); + white-space: nowrap; + /* overflow: hidden; <-- REMOVE THIS */ + position: relative; + transition: background-color 0.15s ease, color 0.15s ease; + flex-shrink: 0; + margin-right: 2px; + opacity: 0.7; +} + +.tab-item:hover { + background-color: var(--button-hover); + opacity: 0.9; +} + +.tab-item.active { + background-color: var(--bg-color); + border-color: var(--border-color); + color: var(--accent-color); + border-bottom: 1px solid var(--bg-color); + opacity: 1; + z-index: 2; +} + +.tab-item.unsaved::after { + content: ''; + display: inline-block; + width: 6px; + height: 6px; + background-color: var(--accent-color); + border-radius: 50%; + flex-shrink: 0; + margin-left: 2px; +} + +.tab-title { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + flex: 1; + min-width: 0; +} + +.tab-close-btn { + display: flex; + align-items: center; + justify-content: center; + width: 16px; + height: 16px; + border-radius: 3px; + background: none; + border: none; + color: var(--text-color); + cursor: pointer; + padding: 0; + font-size: 11px; + opacity: 0; + flex-shrink: 0; + transition: background-color 0.15s ease, opacity 0.15s ease; +} + +.tab-item:hover .tab-close-btn, +.tab-item.active .tab-close-btn { + opacity: 0.6; +} + +.tab-close-btn:hover { + background-color: var(--button-active); + opacity: 1 !important; + color: var(--color-danger-fg, #d73a49); +} + +.tab-new-btn { + display: flex; + align-items: center; + gap: 4px; + height: 24px; + padding: 0 8px; + border-radius: 5px; + background: none; + border: 1px solid var(--border-color); + color: var(--text-color); + cursor: pointer; + font-size: 12px; + flex-shrink: 0; + margin-left: 6px; + align-self: center; + transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease; +} + +.tab-new-btn:hover { + background-color: rgba(46, 160, 67, 0.1); + border-color: var(--accent-color, #2ea043); + color: var(--accent-color, #2ea043); +} + +.tab-new-btn:active { + background-color: rgba(46, 160, 67, 0.2); +} + +/* Drag-and-drop visual feedback */ +.tab-item.dragging { + opacity: 0.4; +} + +.tab-item.drag-over { + border-left: 2px solid var(--accent-color); +} + +/* Tab enter animation */ +@keyframes tabSlideIn { + from { opacity: 0; transform: translateY(4px); } + to { opacity: 0.7; transform: translateY(0); } +} + +.tab-item { + animation: tabSlideIn 0.12s ease forwards; +} + +.tab-item.active { + animation: none; +} + +/* Hide tab bar on very small screens — single-file use */ +@media (max-width: 480px) { + .tab-bar { + display: none; + } +} + +/* ======================================== + TAB OVERFLOW — Scroll Buttons & Fade Indicators + ======================================== */ + +.tab-scroll-btn { + display: none; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + border-radius: 4px; + background: none; + border: 1px solid transparent; + color: var(--text-color); + cursor: pointer; + font-size: 14px; + flex-shrink: 0; + padding: 0; + transition: background-color 0.15s ease, border-color 0.15s ease, opacity 0.15s ease; + z-index: 2; + opacity: 0.6; +} + +.tab-scroll-btn:hover { + background-color: var(--button-hover); + border-color: var(--border-color); + opacity: 1; +} + +.tab-scroll-btn:active { + background-color: var(--button-active); +} + +/* Show scroll buttons only when overflow exists */ +.tab-bar.has-overflow-left .tab-scroll-left, +.tab-bar.has-overflow-right .tab-scroll-right { + display: flex; +} + +/* Overflow fade indicators — subtle gradient at clipped edges */ +.tab-list::before, +.tab-list::after { + content: ''; + position: sticky; + top: 0; + bottom: 0; + width: 0; + flex-shrink: 0; + pointer-events: none; + z-index: 3; + transition: box-shadow 0.2s ease; +} + +.tab-list::before { + left: 0; +} + +.tab-list::after { + right: 0; +} + +.tab-bar.has-overflow-left .tab-list::before { + box-shadow: 8px 0 12px -4px rgba(0, 0, 0, 0.12); +} + +.tab-bar.has-overflow-right .tab-list::after { + box-shadow: -8px 0 12px -4px rgba(0, 0, 0, 0.12); +} + +[data-theme="dark"] .tab-bar.has-overflow-left .tab-list::before { + box-shadow: 8px 0 12px -4px rgba(0, 0, 0, 0.35); +} + +[data-theme="dark"] .tab-bar.has-overflow-right .tab-list::after { + box-shadow: -8px 0 12px -4px rgba(0, 0, 0, 0.35); +} + +/* ======================================== + THREE-DOT TAB MENU + ======================================== */ + +.tab-menu-btn { + display: flex; + align-items: center; + justify-content: center; + width: 22px; + height: 22px; + border-radius: 3px; + background: none; + border: none; + color: var(--text-color); + cursor: pointer; + padding: 0; + font-size: 14px; + font-weight: bold; + letter-spacing: 1px; + opacity: 0.65; + flex-shrink: 0; + transition: background-color 0.15s ease, opacity 0.15s ease; + position: relative; +} + +/* Touch Hitbox Expansion for Tab Menu Button */ +.tab-menu-btn::before { + content: ''; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 48px; + height: 48px; +} + +/* Touch-optimized styling for coarser pointers (e.g., smartphones & tablets) */ +@media (pointer: coarse) { + .tab-bar { + height: 40px !important; + } + .tab-item { + height: 40px !important; + font-size: 14px !important; + padding: 0 10px 0 12px !important; + gap: 8px !important; + } + .tab-new-btn, + .tab-reset-btn { + height: 32px !important; + font-size: 14px !important; + padding: 0 12px !important; + } + .tab-scroll-btn { + width: 32px !important; + height: 32px !important; + font-size: 18px !important; + } + .tab-menu-btn { + width: 30px !important; + height: 30px !important; + font-size: 18px !important; + } + .tab-close-btn { + width: 20px !important; + height: 20px !important; + font-size: 13px !important; + opacity: 0.8 !important; + } +} + +.tab-item:hover .tab-menu-btn, +.tab-item.active .tab-menu-btn { + opacity: 0.65; +} + +.tab-menu-btn:hover { + background-color: var(--button-active); + opacity: 1 !important; +} + +.tab-menu-dropdown { + display: none; + position: fixed; + min-width: 130px; + background-color: var(--header-bg); + border: 1px solid var(--border-color); + border-radius: 6px; + box-shadow: 0 4px 12px rgba(0,0,0,0.15); + z-index: 99999; + overflow: hidden; + flex-direction: column; +} + +.tab-menu-dropdown.open { + display: flex; +} + +.tab-menu-item { + display: flex; + align-items: center; + gap: 7px; + padding: 7px 12px; + background: none; + border: none; + color: var(--text-color); + font-size: 12px; + cursor: pointer; + text-align: left; + transition: background-color 0.12s ease; + white-space: nowrap; +} + +.tab-menu-item:hover { + background-color: var(--button-hover); +} + +.tab-menu-item-danger { + color: var(--color-danger-fg, #d73a49); +} + +.tab-menu-item-danger:hover { + background-color: rgba(215, 58, 73, 0.1); +} + +/* ======================================== + RESET BUTTON + ======================================== */ + +.tab-reset-btn { + display: flex; + align-items: center; + gap: 4px; + height: 24px; + padding: 0 8px; + border-radius: 5px; + background: none; + border: 1px solid var(--border-color); + color: var(--text-color); + cursor: pointer; + font-size: 12px; + flex-shrink: 0; + margin-left: 6px; + transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease; +} + +.tab-reset-btn:hover { + background-color: rgba(215, 58, 73, 0.1); + border-color: var(--color-danger-fg, #d73a49); + color: var(--color-danger-fg, #d73a49); +} + +/* ======================================== + RESET & RENAME CONFIRMATION MODALS + ======================================== */ + +.reset-modal-overlay { + position: fixed; + inset: 0; + background: rgba(0, 0, 0, 0.45); + z-index: 2000; + display: flex; + align-items: center; + justify-content: center; +} + +.reset-modal-overlay.modal-overlay { + opacity: 0; + visibility: hidden; + transition: opacity 0.2s ease, visibility 0.2s ease; +} + +.reset-modal-overlay.modal-overlay.is-visible { + opacity: 1; + visibility: visible; +} + +.reset-modal-box { + background: var(--header-bg); + border: 1px solid var(--border-color); + border-radius: 10px; + padding: 24px 28px; + min-width: 280px; + max-width: 360px; + box-shadow: 0 8px 32px rgba(0,0,0,0.25); + display: flex; + flex-direction: column; + gap: 16px; +} + +.modal-box { + max-height: min(85vh, 760px); + opacity: 0; + transform: translateY(8px); + transition: transform 0.2s ease, opacity 0.2s ease; +} + +.reset-modal-overlay.modal-overlay.is-visible .modal-box { + opacity: 1; + transform: translateY(0); +} + +.modal-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; +} + +.modal-header .reset-modal-message { + text-align: left; + flex: 1; +} + +.modal-close-btn { + border: 1px solid var(--border-color); + background: var(--button-bg); + color: var(--text-color); + border-radius: 6px; + width: 28px; + height: 28px; + display: inline-flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: background-color 0.15s ease; +} + +.modal-close-btn:hover { + background-color: var(--button-hover); +} + +.modal-body { + display: flex; + flex-direction: column; + gap: 16px; + max-height: min(60vh, 520px); + overflow: auto; + padding-right: 4px; +} + +.modal-section { + display: flex; + flex-direction: column; + gap: 8px; +} + +.modal-section-title { + margin: 0; + font-size: 0.95rem; + font-weight: 600; +} + +.modal-list { + margin: 0; + padding-left: 1.1rem; + display: flex; + flex-direction: column; + gap: 6px; + font-size: 0.85rem; +} + +.modal-list a { + color: var(--accent-color); + text-decoration: none; +} + +.modal-list a:hover { + text-decoration: underline; +} + +.modal-subtext { + margin: 0; + font-size: 12px; + color: var(--text-secondary, #57606a); + line-height: 1.4; +} + +.find-replace-meta { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; +} + +.find-match-count { + font-size: 12px; + color: var(--text-secondary, #57606a); +} + +.find-replace-nav { + display: inline-flex; + gap: 6px; +} + +.find-nav-btn { + width: 28px; + height: 28px; + padding: 0; +} + +.about-header { + display: flex; + align-items: center; + gap: 16px; + flex-wrap: wrap; +} + +.about-logo { + width: 64px; + height: 64px; + border-radius: 12px; + border: 1px solid var(--border-color); + object-fit: cover; +} + +.about-details { + display: flex; + flex-direction: column; + gap: 6px; +} + +.about-title { + margin: 0; + font-size: 1.05rem; + font-weight: 600; +} + +.about-description { + margin: 0; + font-size: 0.85rem; + color: var(--text-secondary, #57606a); +} + +.about-meta { + margin: 0; + font-size: 0.78rem; + color: var(--text-secondary, #57606a); +} + +.modal-body kbd { + padding: 2px 6px; + border-radius: 4px; + background-color: var(--button-bg); + border: 1px solid var(--border-color); + font-size: 0.75rem; + font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; +} + +.reset-modal-box--wide { + width: min(92vw, 640px); + max-width: 640px; +} + +.reset-modal-message { + margin: 0; + font-size: 14px; + color: var(--text-color); + font-weight: 500; + text-align: center; +} + +.reset-modal-actions { + display: flex; + gap: 10px; + justify-content: flex-end; +} + +.reset-modal-btn { + padding: 6px 16px; + border-radius: 6px; + border: 1px solid var(--border-color); + background: var(--button-bg); + color: var(--text-color); + font-size: 13px; + cursor: pointer; + transition: background-color 0.15s ease; +} + +.reset-modal-btn:hover { + background-color: var(--button-hover); +} + +.reset-modal-confirm { + background-color: var(--color-danger-fg, #d73a49); + border-color: var(--color-danger-fg, #d73a49); + color: #fff; +} + +.reset-modal-confirm:hover { + background-color: #b02a37; + border-color: #b02a37; +} + +/* ======================================== + PDF EXPORT PROGRESS MODAL + ======================================== */ + +.pdf-progress-overlay { + position: fixed; + inset: 0; + z-index: 2600; + display: flex; + align-items: center; + justify-content: center; + background: rgba(0, 0, 0, 0.45); + padding: 20px; +} + +.pdf-progress-modal { + width: min(92vw, 420px); + background: var(--header-bg); + border: 1px solid var(--border-color); + border-radius: 8px; + box-shadow: 0 16px 48px rgba(0, 0, 0, 0.28); + color: var(--text-color); + display: flex; + flex-direction: column; + gap: 16px; + padding: 20px; +} + +.pdf-progress-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; +} + +.pdf-progress-title { + margin: 0; + font-size: 15px; + font-weight: 600; +} + +.pdf-progress-percent { + font-size: 28px; + font-weight: 600; + line-height: 1; +} + +.pdf-progress-track { + width: 100%; + height: 10px; + background: var(--button-bg); + border: 1px solid var(--border-color); + border-radius: 999px; + overflow: hidden; +} + +.pdf-progress-fill { + width: 0%; + height: 100%; + background: var(--accent-color); + border-radius: inherit; + transition: width 0.18s ease; +} + +.pdf-progress-details { + display: flex; + flex-direction: column; + gap: 6px; + font-size: 12px; + color: var(--text-secondary); +} + +.pdf-progress-detail { + display: flex; + justify-content: space-between; + gap: 12px; +} + +.pdf-progress-detail strong { + color: var(--text-color); + font-weight: 600; +} + +.pdf-progress-actions { + display: flex; + justify-content: flex-end; +} + +.tool-button.pdf-export-loading, +.mobile-menu-item.pdf-export-loading { + pointer-events: none; +} +/* ======================================== + RESET MODAL FORM FIELDS + ======================================== */ + +.reset-modal-field { + display: flex; + flex-direction: column; + gap: 6px; + text-align: left; +} + +.reset-modal-field-group { + display: flex; + flex-direction: column; + gap: 12px; +} + +.reset-modal-label { + font-size: 12px; + color: var(--text-secondary, #57606a); + font-weight: 600; +} + +.reset-modal-toggle-group { + display: flex; + flex-direction: column; + gap: 8px; +} + +.reset-modal-option { + display: flex; + align-items: center; + gap: 8px; + font-size: 13px; + color: var(--text-color); +} + +.reset-modal-option input { + margin: 0; +} + +/* ======================================== + RENAME MODAL INPUT + ======================================== */ + +.rename-modal-input { + width: 100%; + padding: 7px 10px; + border-radius: 6px; + border: 1px solid var(--border-color); + background: var(--bg-color); + color: var(--text-color); + font-size: 13px; + outline: none; + box-sizing: border-box; +} + +.rename-modal-input:focus { + border-color: var(--accent-color); +} + +/* ======================================== + TOOLBAR POPUP PANELS + ======================================== */ + +.reset-modal-box--xl { + width: min(94vw, 980px); + max-width: 980px; +} + +.modal-empty { + margin: 0; + font-size: 12px; + color: var(--text-secondary, #57606a); + text-align: center; +} + +.emoji-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); + gap: 12px; + max-height: min(52vh, 440px); + overflow: auto; + padding: 4px; +} + +.symbol-grid { + display: flex; + flex-direction: column; + gap: 16px; + max-height: min(52vh, 440px); + overflow: auto; + padding: 4px 2px; +} + +.symbol-section-title { + margin: 0; + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--text-secondary, #57606a); +} + +.symbol-section-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); + gap: 12px; +} + +.alert-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); + gap: 12px; + max-height: min(45vh, 360px); + overflow: auto; + padding: 2px; +} + +.emoji-item, +.symbol-item, +.alert-option { + display: flex; + flex-direction: column; + gap: 8px; + align-items: center; + border: 1px solid var(--border-color); + border-radius: 10px; + padding: 10px; + background: var(--bg-color); + color: var(--text-color); + cursor: pointer; + transition: border-color 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease; +} + +.emoji-item:focus-visible, +.symbol-item:focus-visible, +.alert-option:focus-visible { + outline: 2px solid var(--accent-color); + outline-offset: 2px; +} + +.emoji-item.is-selected, +.symbol-item.is-selected, +.alert-option.is-selected { + border-color: var(--accent-color); + box-shadow: 0 0 0 2px rgba(88, 166, 255, 0.2); + background-color: rgba(88, 166, 255, 0.08); +} + +.emoji-preview { + width: 36px; + height: 36px; + display: flex; + align-items: center; + justify-content: center; +} + +.emoji-preview img { + width: 32px; + height: 32px; +} + +.emoji-shortcode { + display: flex; + align-items: center; + gap: 6px; + font-size: 12px; + color: var(--text-secondary, #57606a); + text-align: center; +} + +.emoji-copy-btn, +.symbol-copy-btn { + border: none; + background: transparent; + color: var(--text-secondary, #57606a); + cursor: pointer; + padding: 2px; + border-radius: 4px; +} + +.emoji-copy-btn:hover, +.symbol-copy-btn:hover { + color: var(--text-color); + background: var(--button-hover); +} + +.emoji-copy-btn.is-copied, +.symbol-copy-btn.is-copied { + color: var(--accent-color); +} + +.symbol-preview { + font-size: 28px; + line-height: 1; +} + +.symbol-code { + display: flex; + align-items: center; + gap: 6px; + font-size: 12px; + color: var(--text-secondary, #57606a); +} + +.alert-option { + align-items: stretch; + text-align: left; + padding: 12px; +} + +.alert-preview { + margin: 0; +} + +.alert-preview .markdown-alert { + padding: 0.5rem 0.9rem; + border-left: 0.25em solid; + border-radius: 0.375rem; +} + +.alert-preview .markdown-alert-title { + margin: 0 0 6px; + font-weight: 600; + line-height: 1.25; + display: flex; + align-items: center; + gap: 8px; +} + +.alert-preview .markdown-alert-icon { + display: inline-flex; + width: 16px; + height: 16px; +} + +.alert-preview .markdown-alert-icon svg { + width: 16px; + height: 16px; + fill: currentColor; +} + +.alert-preview .markdown-alert > *:not(.markdown-alert-title) { + color: var(--text-color); +} + +.alert-preview .markdown-alert-note { + color: #0969da; + border-left-color: #0969da; + background-color: #ddf4ff; +} + +.alert-preview .markdown-alert-tip { + color: #1a7f37; + border-left-color: #1a7f37; + background-color: #dafbe1; +} + +.alert-preview .markdown-alert-important { + color: #8250df; + border-left-color: #8250df; + background-color: #fbefff; +} + +.alert-preview .markdown-alert-warning { + color: #9a6700; + border-left-color: #9a6700; + background-color: #fff8c5; +} + +.alert-preview .markdown-alert-caution { + color: #cf222e; + border-left-color: #cf222e; + background-color: #ffebe9; +} + +[data-theme="dark"] .alert-preview .markdown-alert-note { + color: #4493f8; + border-left-color: #4493f8; + background-color: rgba(31, 111, 235, 0.15); +} + +[data-theme="dark"] .alert-preview .markdown-alert-tip { + color: #3fb950; + border-left-color: #3fb950; + background-color: rgba(35, 134, 54, 0.15); +} + +[data-theme="dark"] .alert-preview .markdown-alert-important { + color: #ab7df8; + border-left-color: #ab7df8; + background-color: rgba(137, 87, 229, 0.15); +} + +[data-theme="dark"] .alert-preview .markdown-alert-warning { + color: #d29922; + border-left-color: #d29922; + background-color: rgba(210, 153, 34, 0.18); +} + +[data-theme="dark"] .alert-preview .markdown-alert-caution { + color: #f85149; + border-left-color: #f85149; + background-color: rgba(248, 81, 73, 0.18); +} + +.github-import-error { + margin: 0; + font-size: 12px; + color: var(--color-danger-fg, #d73a49); + text-align: left; + line-height: 1.5; +} + +.github-import-error.is-info { + color: var(--text-secondary, #57606a); +} + +#github-import-modal .reset-modal-box { + width: 60vw; + max-width: 60vw; + min-width: 340px; + padding: 30px 34px; + gap: 16px; + box-shadow: 0 20px 48px rgba(0, 0, 0, 0.22); +} + +#github-import-modal .reset-modal-message { + font-size: 18px; + line-height: 1.35; + text-align: left; +} + +#github-import-url, +#github-import-file-select { + min-height: 46px; + padding: 10px 12px; + font-size: 15px; +} + +#github-import-file-select { + min-height: 180px; +} + +.github-import-tree { + max-height: 420px; + overflow: auto; + border: 1px solid var(--border-color); + border-radius: 10px; + padding: 12px; + background: var(--bg-color); +} + +.github-import-selection-toolbar { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + padding: 10px 12px; + border: 1px solid var(--border-color); + border-radius: 8px; + background: var(--button-bg); +} + +.github-import-selected-count { + font-size: 14px; + font-weight: 600; + color: var(--text-color); +} + +.github-import-tree ul { + list-style: none; + margin: 0; + padding-left: 18px; +} + +.github-import-tree > ul { + padding-left: 4px; +} + +.github-import-tree li { + margin: 2px 0; +} + +.github-tree-folder-label { + display: inline-block; + font-size: 14px; + color: var(--text-secondary, #57606a); + margin-bottom: 4px; +} + +.github-tree-file-btn { + border: 0; + background: transparent; + color: var(--text-color); + cursor: pointer; + padding: 6px 8px; + border-radius: 6px; + text-align: left; + width: 100%; + font-size: 14px; +} + +.github-tree-file-btn:hover, +.github-tree-file-btn:focus-visible { + background: var(--button-hover); + outline: none; +} + +.github-tree-file-btn.is-selected { + background: rgba(56, 139, 253, 0.14); + color: var(--accent-color); +} + +#github-import-modal .reset-modal-actions { + gap: 12px; +} + +#github-import-modal .reset-modal-btn { + min-height: 42px; + padding: 9px 18px; + font-size: 14px; +} + +@media (max-width: 576px) { + #github-import-modal .reset-modal-box { + width: 95vw; + max-width: 95vw; + min-width: 0; + padding: 20px; + gap: 14px; + } + + .github-import-selection-toolbar { + flex-direction: column; + align-items: stretch; + } + + #github-import-modal .reset-modal-message { + font-size: 16px; + } + + #github-import-modal .reset-modal-actions { + flex-direction: column-reverse; + } + + #github-import-modal .reset-modal-btn { + width: 100%; + } +} + +.frontmatter-table { + border-collapse: collapse; + margin-bottom: 1.5em; + font-size: 0.9em; + width: auto; + max-width: 100%; +} + +.frontmatter-table th, +.frontmatter-table td { + border: 1px solid var(--border-color); + padding: 6px 13px; + vertical-align: top; + color: var(--text-color); +} + +.frontmatter-table tr:nth-child(odd) th, +.frontmatter-table tr:nth-child(odd) td { + background-color: var(--table-bg); +} + +.frontmatter-table tr:nth-child(even) th, +.frontmatter-table tr:nth-child(even) td { + background-color: var(--editor-bg); +} + +.frontmatter-table th { + font-weight: 600; + text-align: right; + white-space: nowrap; + vertical-align: middle; +} + +.frontmatter-table td { + text-align: left; +} + +.fm-complex { + margin: 0; + padding: 4px 6px; + font-size: 0.8em; + font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; + white-space: pre-wrap; + word-break: break-word; + background: transparent; + border: none; + color: var(--text-color); +} + +.fm-tag { + display: inline-block; + padding: 2px 8px; + margin: 2px 3px 2px 0; + border: 1px solid var(--border-color); + border-radius: 2em; + font-size: 0.8em; + font-weight: 500; + color: var(--accent-color); + background-color: var(--button-bg); + white-space: nowrap; +} + +/* ======================================== + RTL SUPPORT + ======================================== */ + +[dir="rtl"] body { + direction: rtl; +} + +[dir="rtl"] .editor-pane { + padding-left: 0px; + padding-right: 20px; + border-right: none; + border-left: 1px solid var(--border-color); +} + +[dir="rtl"] #markdown-editor, +[dir="rtl"] .markdown-body { + direction: rtl; + text-align: right; +} + +[dir="rtl"] .markdown-body pre, +[dir="rtl"] .markdown-body code, +[dir="rtl"] .fm-complex { + direction: ltr; + text-align: left; +} + +[dir="rtl"] .line-numbers { + left: auto; + right: 20px; + padding: 10px 0 10px 8px; + text-align: left; + border-right: none; + border-left: 1px solid var(--border-color); +} + +[dir="rtl"] #markdown-editor { + padding-left: 10px; + padding-right: calc(10px + var(--line-number-gutter)); +} + +[dir="rtl"] .editor-highlight-layer { + inset: 20px calc(20px + var(--line-number-gutter)) 20px 0; +} + +[dir="rtl"] .mobile-menu-item, +[dir="rtl"] .tab-menu-item, +[dir="rtl"] .modal-header .reset-modal-message, +[dir="rtl"] .reset-modal-field, +[dir="rtl"] .alert-option, +[dir="rtl"] .github-import-error, +[dir="rtl"] #github-import-modal .reset-modal-message, +[dir="rtl"] .github-tree-file-btn, +[dir="rtl"] .frontmatter-table td { + text-align: right; +} + +[dir="rtl"] .github-import-tree ul { + padding-left: 0; + padding-right: 18px; +} + +[dir="rtl"] .github-import-tree > ul { + padding-right: 4px; +} + +[dir="rtl"] .markdown-body .markdown-alert, +[dir="rtl"] .alert-preview .markdown-alert { + border-left: 0; + border-right: 0.25em solid currentColor; +} + +/* ============================================ + SHARE MODAL + ============================================ */ + +.share-modal-description { + font-size: 13px; + color: var(--text-secondary, #57606a); + margin: 0; +} + +.share-mode-cards { + display: flex; + flex-direction: column; + gap: 8px; +} + +.share-mode-card { + display: flex; + align-items: center; + gap: 12px; + padding: 12px 14px; + border-radius: 8px; + border: 1px solid var(--border-color); + background: var(--bg-color); + cursor: pointer; + transition: border-color 0.15s ease, background-color 0.15s ease; + user-select: none; +} + +.share-mode-card:hover { + border-color: var(--accent-color); + background: var(--button-hover); +} + +.share-mode-card.is-selected { + border-color: var(--accent-color); + background: color-mix(in srgb, var(--accent-color) 8%, transparent); +} + +.share-mode-card input[type="radio"] { + display: none; +} + +.share-card-icon { + font-size: 18px; + width: 28px; + text-align: center; + color: var(--text-secondary, #57606a); + flex-shrink: 0; +} + +.share-mode-card.is-selected .share-card-icon { + color: var(--accent-color); +} + +.share-card-body { + display: flex; + flex-direction: column; + gap: 2px; + flex: 1; + min-width: 0; +} + +.share-card-title { + font-size: 13px; + font-weight: 600; + color: var(--text-color); +} + +.share-card-desc { + font-size: 12px; + color: var(--text-secondary, #57606a); +} + +.share-card-check { + width: 18px; + text-align: center; + color: var(--accent-color); + opacity: 0; + transition: opacity 0.15s ease; + flex-shrink: 0; +} + +.share-mode-card.is-selected .share-card-check { + opacity: 1; +} + +.share-url-row { + display: flex; + gap: 8px; + align-items: center; +} + +.share-url-input { + flex: 1; + font-size: 12px; + font-family: var(--font-mono, monospace); + color: var(--text-secondary, #57606a); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.share-copy-btn { + flex-shrink: 0; + padding: 6px 10px; +} + +.share-copy-btn:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.share-modal-notice { + font-size: 11px; + color: var(--text-secondary, #57606a); + margin: 0; + display: flex; + align-items: center; + gap: 5px; +} + +/* ========================================================================== + Multilingual & CJK Optimization styles added by Aegis SEO agency + ========================================================================== */ +.lang-select-item { + display: flex !important; + align-items: center; + gap: 8px; + cursor: pointer; + transition: background-color 0.2s ease, padding-left 0.2s ease; +} + +.lang-select-item:hover { + padding-left: 12px; +} + +.lang-select-item.active { + background-color: var(--accent-color) !important; + color: #ffffff !important; + font-weight: 600; +} + +/* Adjust CJK text layout for maximum readability inside the preview pane */ +html[lang="zh"] .markdown-body, +html[lang="ja"] .markdown-body, +html[lang="ko"] .markdown-body { + line-height: 1.75 !important; + letter-spacing: 0.03em; + word-break: keep-all; + overflow-wrap: break-word; + text-align: justify; +} + +/* Specific heading spacing improvements for CJK characters */ +html[lang="zh"] .markdown-body h1, html[lang="zh"] .markdown-body h2, html[lang="zh"] .markdown-body h3, +html[lang="ja"] .markdown-body h1, html[lang="ja"] .markdown-body h2, html[lang="ja"] .markdown-body h3, +html[lang="ko"] .markdown-body h1, html[lang="ko"] .markdown-body h2, html[lang="ko"] .markdown-body h3 { + font-weight: 700; + letter-spacing: 0.02em; + margin-top: 1.4em; + margin-bottom: 0.6em; +} + +/* Smooth fade and scale transition for dropdown active states */ +.dropdown-menu { + opacity: 0; + transform: translateY(8px) scale(0.98); + display: block; + visibility: hidden; + transition: opacity 0.2s cubic-bezier(0.16, 1, 0.3, 1), transform 0.2s cubic-bezier(0.16, 1, 0.3, 1), visibility 0.2s; +} + +.dropdown-menu.show { + opacity: 1; + transform: translateY(0) scale(1); + visibility: visible; +} + /* ======================================== - PDF EXPORT PROGRESS MODAL + FIND & REPLACE FLOATING PANEL DESIGN ======================================== */ -.pdf-progress-overlay { +.find-replace-panel { position: fixed; - inset: 0; - z-index: 2600; + top: 100px; + right: 20px; + width: 340px; + background-color: var(--fr-bg); + border: 1px solid var(--fr-border); + border-radius: 12px; + box-shadow: var(--fr-shadow); + z-index: 1050; + display: flex; + flex-direction: column; + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + transition: opacity 0.2s ease, transform 0.2s ease; + user-select: none; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; +} + +.find-replace-panel.docked { + position: relative; + top: 0 !important; + right: 0 !important; + height: 100%; + border-radius: 0; + border-top: none; + border-bottom: none; + border-right: none; + border-left: 1px solid var(--fr-border); + box-shadow: none; + backdrop-filter: none; + z-index: 10; + flex-shrink: 0; +} + +.find-replace-panel.docked #find-replace-reset, +.find-replace-panel.docked #find-replace-reset-footer { + display: none !important; +} + +.find-replace-header { display: flex; align-items: center; - justify-content: center; - background: rgba(0, 0, 0, 0.45); - padding: 20px; + justify-content: space-between; + padding: 8px 12px; + border-bottom: 1px solid var(--fr-border); + cursor: move; + background-color: var(--header-bg); + border-top-left-radius: 11px; + border-top-right-radius: 11px; } -.pdf-progress-modal { - width: min(92vw, 420px); - background: var(--header-bg); - border: 1px solid var(--border-color); - border-radius: 8px; - box-shadow: 0 16px 48px rgba(0, 0, 0, 0.28); +.find-replace-panel.docked .find-replace-header { + cursor: default; + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.find-replace-title { + font-size: 13px; + font-weight: 600; + color: var(--text-color); +} + +.find-replace-header-actions { + display: flex; + gap: 4px; +} + +.panel-icon-btn { + background: none; + border: none; color: var(--text-color); + font-size: 12px; + cursor: pointer; + padding: 2px 6px; + border-radius: 4px; + display: flex; + align-items: center; + justify-content: center; + transition: background-color 0.15s ease; +} + +.panel-icon-btn:hover { + background-color: var(--button-hover); +} + +.find-replace-body { + padding: 12px; display: flex; flex-direction: column; - gap: 16px; - padding: 20px; + gap: 8px; } -.pdf-progress-header { +.find-replace-field-row { + display: flex; + flex-direction: column; + position: relative; +} + +.find-input-container, .replace-input-container { display: flex; align-items: center; - justify-content: space-between; - gap: 12px; + border: 1px solid var(--fr-border); + border-radius: 6px; + background-color: var(--bg-color); + padding: 2px 4px; + width: 100%; } -.pdf-progress-title { - margin: 0; - font-size: 15px; +.find-input-container:focus-within, .replace-input-container:focus-within { + border-color: var(--accent-color); + box-shadow: 0 0 0 3px rgba(9, 105, 218, 0.15); +} + +.find-input-field { + flex: 1; + border: none; + background: transparent; + color: var(--text-color); + font-size: 13px; + padding: 4px 6px; + outline: none; + width: 50%; +} + +.find-options-group { + display: flex; + gap: 2px; +} + +.find-option-btn { + background: none; + border: none; + color: var(--text-secondary); + font-size: 11px; font-weight: 600; + cursor: pointer; + padding: 2px 5px; + border-radius: 4px; + transition: background-color 0.12s ease, color 0.12s ease; + min-width: 22px; + height: 22px; + display: inline-flex; + align-items: center; + justify-content: center; } -.pdf-progress-percent { - font-size: 28px; +.find-option-btn:hover { + background-color: var(--button-hover); + color: var(--text-color); +} + +.find-option-btn.active { + background-color: var(--fr-btn-active-bg); + color: var(--fr-btn-active); +} + +.find-error-drawer { + background-color: var(--fr-error-bg); + border: 1px solid var(--fr-error-border); + border-radius: 6px; + padding: 6px 10px; + font-size: 11px; + color: var(--fr-text-danger); + line-height: 1.3; +} + +.find-replace-meta-row { + display: flex; + align-items: center; + justify-content: space-between; + padding: 2px 4px; +} + +.find-match-count { + font-size: 12px; + color: var(--text-secondary); +} + +.find-nav-group { + display: flex; + gap: 4px; +} + +.find-nav-arrow-btn { + background: none; + border: 1px solid var(--fr-border); + color: var(--text-color); + font-size: 12px; + cursor: pointer; + padding: 2px 8px; + border-radius: 4px; + transition: background-color 0.15s ease; + display: flex; + align-items: center; + justify-content: center; +} + +.find-nav-arrow-btn:hover:not(:disabled) { + background-color: var(--button-hover); +} + +.find-nav-arrow-btn:disabled { + opacity: 0.4; + cursor: not-allowed; +} + +.find-drawer-toggle-row { + border-top: 1px solid var(--fr-border); + margin-top: 4px; + padding-top: 6px; +} + +.drawer-toggle-btn { + background: none; + border: none; + color: var(--text-secondary); + font-size: 12px; + cursor: pointer; + display: flex; + align-items: center; + padding: 2px 4px; + border-radius: 4px; + transition: color 0.15s ease; +} + +.drawer-toggle-btn:hover { + color: var(--text-color); +} + +.find-replace-drawer-content { + display: flex; + flex-direction: column; + gap: 8px; + padding: 4px 6px; + border-top: 1px dashed var(--fr-border); + margin-top: 2px; + padding-top: 8px; +} + +.drawer-field { + display: flex; + flex-direction: column; + gap: 4px; +} + +.drawer-field.check-field { + flex-direction: row; + align-items: center; + gap: 6px; + padding: 2px 0; +} + +.drawer-label { + font-size: 11px; font-weight: 600; - line-height: 1; + color: var(--text-secondary); } -.pdf-progress-track { +.drawer-select { width: 100%; - height: 10px; - background: var(--button-bg); - border: 1px solid var(--border-color); - border-radius: 999px; - overflow: hidden; + padding: 4px 6px; + border-radius: 4px; + border: 1px solid var(--fr-border); + background-color: var(--bg-color); + color: var(--text-color); + font-size: 12px; + outline: none; } -.pdf-progress-fill { - width: 0%; - height: 100%; - background: var(--accent-color); - border-radius: inherit; - transition: width 0.18s ease; +.drawer-checkbox { + margin: 0; + cursor: pointer; } -.pdf-progress-details { +.drawer-label-checkbox { + font-size: 12px; + color: var(--text-color); + cursor: pointer; +} + +.find-replace-actions-footer { display: flex; - flex-direction: column; gap: 6px; + padding: 8px 12px 12px 12px; + border-top: 1px solid var(--fr-border); + background-color: var(--header-bg); + border-bottom-left-radius: 11px; + border-bottom-right-radius: 11px; +} + +.find-replace-panel.docked .find-replace-actions-footer { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + +.fr-action-btn { + flex: 1; + padding: 6px 8px; font-size: 12px; - color: var(--text-secondary); + font-weight: 500; + border-radius: 6px; + border: 1px solid var(--fr-border); + background-color: var(--button-bg); + color: var(--text-color); + cursor: pointer; + transition: background-color 0.15s ease, border-color 0.15s ease; + text-align: center; } -.pdf-progress-detail { +.fr-action-btn:hover:not(:disabled) { + background-color: var(--button-hover); +} + +.fr-action-btn:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.fr-action-btn.secondary { + max-width: 60px; +} + +/* ======================================== + DIFF PREVIEW CONTAINER + ======================================== */ +.diff-preview-body { + padding: 16px; display: flex; - justify-content: space-between; + flex-direction: column; gap: 12px; } -.pdf-progress-detail strong { - color: var(--text-color); - font-weight: 600; +.diff-container { + border: 1px solid var(--fr-border); + border-radius: 8px; + background-color: var(--bg-color); + max-height: 400px; + overflow: auto; + font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; + font-size: 12px; + line-height: 1.5; } -.pdf-progress-actions { +.diff-line { display: flex; - justify-content: flex-end; + padding: 1px 8px; } -.tool-button.pdf-export-loading, -.mobile-menu-item.pdf-export-loading { +.diff-line.addition { + background-color: rgba(46, 160, 67, 0.15); + color: #3fb950; +} + +.diff-line.deletion { + background-color: rgba(248, 81, 73, 0.15); + color: #f85149; +} + +.diff-line.context { + color: var(--text-secondary); +} + +.diff-line-num { + width: 40px; + flex-shrink: 0; + text-align: right; + padding-right: 12px; + border-right: 1px solid var(--fr-border); + user-select: none; + opacity: 0.5; +} + +.diff-line-content { + padding-left: 12px; + white-space: pre-wrap; + word-break: break-all; +} + +/* ======================================== + DOCK LAYOUT CODES + ======================================== */ +.content-container { + display: flex; + flex: 1; + overflow: hidden; + position: relative; +} + +.editor-dock-wrapper { + display: flex; + flex: 1; + overflow: hidden; + position: relative; +} + +.editor-pane-inner { + display: flex; + flex-direction: column; + flex: 1; + position: relative; + overflow: hidden; +} + +/* ======================================== + MOBILE & TABLET FIND PANEL RESPONSIVE FIXES + ======================================== */ +@media (max-width: 1079px) { + #find-replace-dock { + display: none !important; + } +} + +@media (max-width: 768px) { + /* Prevent full screen expansion of floating panel on small mobile viewports */ + .find-replace-panel { + width: calc(100% - 24px) !important; + right: 12px !important; + left: 12px !important; + top: 80px !important; + } +} + +/* ======================================== + SKELETON LOADING SHIMMER SYSTEM + ======================================== */ +.skeleton-placeholder { + display: block; + background-color: var(--skeleton-bg); + border-radius: 6px; + position: relative; + overflow: hidden; + /* PERF-017: Removed skeleton-pulse; shimmer-only is sufficient and halves GPU compositing layers */ + /* animation: skeleton-pulse 2.2s cubic-bezier(0.4, 0, 0.2, 1) infinite alternate; */ +} + +.skeleton-placeholder::after { + content: ""; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + transform: translateX(-100%); + background-image: linear-gradient( + 90deg, + rgba(255, 255, 255, 0) 0%, + var(--skeleton-glow) 50%, + rgba(255, 255, 255, 0) 100% + ); + animation: skeleton-shimmer 1.6s cubic-bezier(0.4, 0, 0.2, 1) infinite; +} + +@keyframes skeleton-shimmer { + 100% { + transform: translateX(100%); + } +} + +@keyframes skeleton-pulse { + 0%, 100% { + opacity: 1; + } + 50% { + opacity: 0.82; + } +} + +.skeleton-circle { + width: 32px; + height: 32px; + border-radius: 50%; + margin: 0 auto; +} + +.skeleton-text { + height: 12px; + width: 80%; + margin: 4px auto; + border-radius: 3px; +} + +.skeleton-tree-folder { + height: 16px; + width: 140px; + margin: 6px 0; + display: inline-block; +} + +.skeleton-tree-file { + height: 14px; + width: 180px; + margin: 4px 0 4px 12px; + display: inline-block; +} + +/* Screen reader accessibility utility */ +.visually-hidden { + position: absolute !important; + width: 1px !important; + height: 1px !important; + padding: 0 !important; + margin: -1px !important; + overflow: hidden !important; + clip: rect(0, 0, 0, 0) !important; + clip-path: inset(50%) !important; + white-space: nowrap !important; + border: 0 !important; +} + +/* Article skeleton layout structures */ +.skeleton-title { + height: 28px; + width: 35%; + margin-bottom: 24px; + border-radius: 8px; +} + +.skeleton-subtitle { + height: 20px; + width: 20%; + margin-bottom: 18px; + margin-top: 32px; + border-radius: 6px; +} + +.skeleton-line { + height: 14px; + margin-bottom: 12px; + border-radius: 6px; +} + +/* Symmetrical dynamic widths */ +.skeleton-w90 { width: 90%; } +.skeleton-w92 { width: 92%; } +.skeleton-w88 { width: 88%; } +.skeleton-w85 { width: 85%; } +.skeleton-w60 { width: 60%; } +.skeleton-w45 { width: 45%; } + +/* Editor pane skeleton overlay */ +.editor-skeleton { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + padding: 30px 24px 24px calc(24px + var(--line-number-gutter)); + z-index: 10; pointer-events: none; + background: var(--editor-bg); + box-sizing: border-box; + overflow: hidden; + transition: opacity 0.3s ease; +} + +.editor-pane:not(.is-loading) .editor-skeleton { + display: none; +} + +.editor-pane.is-loading textarea { + opacity: 0; /* Completely hide editor content while initial bootstrap skeleton runs */ +} + +/* Preview pane skeleton container */ +.skeleton-preview-container { + display: block; + width: 100%; + box-sizing: border-box; + padding: 10px 4px; + background: transparent; + transition: opacity 0.3s ease; +} + +/* Mermaid compilation loading states */ +.mermaid-container.is-loading { + min-height: 180px; + background-color: var(--skeleton-bg); + border-radius: 8px; + border: 1px solid var(--border-color); + position: relative; + overflow: hidden; + animation: skeleton-pulse 2.2s cubic-bezier(0.4, 0, 0.2, 1) infinite alternate; +} + +.mermaid-container.is-loading .mermaid { + opacity: 0; /* Hide raw chart source code during compile */ } -/* ======================================== - RESET MODAL FORM FIELDS - ======================================== */ - -.reset-modal-field { - display: flex; - flex-direction: column; - gap: 6px; - text-align: left; -} - -.reset-modal-field-group { - display: flex; - flex-direction: column; - gap: 12px; -} - -.reset-modal-label { - font-size: 12px; - color: var(--text-secondary, #57606a); - font-weight: 600; -} - -.reset-modal-toggle-group { - display: flex; - flex-direction: column; - gap: 8px; -} - -.reset-modal-option { - display: flex; - align-items: center; - gap: 8px; - font-size: 13px; - color: var(--text-color); -} - -.reset-modal-option input { - margin: 0; -} - -/* ======================================== - RENAME MODAL INPUT - ======================================== */ - -.rename-modal-input { - width: 100%; - padding: 7px 10px; - border-radius: 6px; - border: 1px solid var(--border-color); - background: var(--bg-color); - color: var(--text-color); - font-size: 13px; - outline: none; - box-sizing: border-box; -} - -.rename-modal-input:focus { - border-color: var(--accent-color); -} - -/* ======================================== - TOOLBAR POPUP PANELS - ======================================== */ - -.reset-modal-box--xl { - width: min(94vw, 980px); - max-width: 980px; -} - -.modal-empty { - margin: 0; - font-size: 12px; - color: var(--text-secondary, #57606a); - text-align: center; -} - -.emoji-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); - gap: 12px; - max-height: min(52vh, 440px); - overflow: auto; - padding: 4px; -} - -.symbol-grid { - display: flex; - flex-direction: column; - gap: 16px; - max-height: min(52vh, 440px); - overflow: auto; - padding: 4px 2px; -} - -.symbol-section-title { - margin: 0; - font-size: 11px; - text-transform: uppercase; - letter-spacing: 0.08em; - color: var(--text-secondary, #57606a); -} - -.symbol-section-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); - gap: 12px; -} - -.alert-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); - gap: 12px; - max-height: min(45vh, 360px); - overflow: auto; - padding: 2px; -} - -.emoji-item, -.symbol-item, -.alert-option { - display: flex; - flex-direction: column; - gap: 8px; - align-items: center; - border: 1px solid var(--border-color); - border-radius: 10px; - padding: 10px; - background: var(--bg-color); - color: var(--text-color); - cursor: pointer; - transition: border-color 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease; -} - -.emoji-item:focus-visible, -.symbol-item:focus-visible, -.alert-option:focus-visible { - outline: 2px solid var(--accent-color); - outline-offset: 2px; -} - -.emoji-item.is-selected, -.symbol-item.is-selected, -.alert-option.is-selected { - border-color: var(--accent-color); - box-shadow: 0 0 0 2px rgba(88, 166, 255, 0.2); - background-color: rgba(88, 166, 255, 0.08); -} - -.emoji-preview { - width: 36px; - height: 36px; - display: flex; - align-items: center; - justify-content: center; -} - -.emoji-preview img { - width: 32px; - height: 32px; -} - -.emoji-shortcode { - display: flex; - align-items: center; - gap: 6px; - font-size: 12px; - color: var(--text-secondary, #57606a); - text-align: center; -} - -.emoji-copy-btn, -.symbol-copy-btn { - border: none; - background: transparent; - color: var(--text-secondary, #57606a); - cursor: pointer; - padding: 2px; - border-radius: 4px; -} - -.emoji-copy-btn:hover, -.symbol-copy-btn:hover { - color: var(--text-color); - background: var(--button-hover); -} - -.emoji-copy-btn.is-copied, -.symbol-copy-btn.is-copied { - color: var(--accent-color); -} - -.symbol-preview { - font-size: 28px; - line-height: 1; -} - -.symbol-code { - display: flex; - align-items: center; - gap: 6px; - font-size: 12px; - color: var(--text-secondary, #57606a); -} - -.alert-option { - align-items: stretch; - text-align: left; - padding: 12px; -} - -.alert-preview { - margin: 0; -} - -.alert-preview .markdown-alert { - padding: 0.5rem 0.9rem; - border-left: 0.25em solid; - border-radius: 0.375rem; -} - -.alert-preview .markdown-alert-title { - margin: 0 0 6px; - font-weight: 600; - line-height: 1.25; - display: flex; - align-items: center; - gap: 8px; -} - -.alert-preview .markdown-alert-icon { - display: inline-flex; - width: 16px; - height: 16px; -} - -.alert-preview .markdown-alert-icon svg { - width: 16px; - height: 16px; - fill: currentColor; -} - -.alert-preview .markdown-alert > *:not(.markdown-alert-title) { - color: var(--text-color); -} - -.alert-preview .markdown-alert-note { - color: #0969da; - border-left-color: #0969da; - background-color: #ddf4ff; -} - -.alert-preview .markdown-alert-tip { - color: #1a7f37; - border-left-color: #1a7f37; - background-color: #dafbe1; -} - -.alert-preview .markdown-alert-important { - color: #8250df; - border-left-color: #8250df; - background-color: #fbefff; -} - -.alert-preview .markdown-alert-warning { - color: #9a6700; - border-left-color: #9a6700; - background-color: #fff8c5; -} - -.alert-preview .markdown-alert-caution { - color: #cf222e; - border-left-color: #cf222e; - background-color: #ffebe9; -} - -[data-theme="dark"] .alert-preview .markdown-alert-note { - color: #4493f8; - border-left-color: #4493f8; - background-color: rgba(31, 111, 235, 0.15); -} - -[data-theme="dark"] .alert-preview .markdown-alert-tip { - color: #3fb950; - border-left-color: #3fb950; - background-color: rgba(35, 134, 54, 0.15); -} - -[data-theme="dark"] .alert-preview .markdown-alert-important { - color: #ab7df8; - border-left-color: #ab7df8; - background-color: rgba(137, 87, 229, 0.15); -} - -[data-theme="dark"] .alert-preview .markdown-alert-warning { - color: #d29922; - border-left-color: #d29922; - background-color: rgba(210, 153, 34, 0.18); -} - -[data-theme="dark"] .alert-preview .markdown-alert-caution { - color: #f85149; - border-left-color: #f85149; - background-color: rgba(248, 81, 73, 0.18); -} - -.github-import-error { - margin: 0; - font-size: 12px; - color: var(--color-danger-fg, #d73a49); - text-align: left; - line-height: 1.5; -} - -.github-import-error.is-info { - color: var(--text-secondary, #57606a); -} - -#github-import-modal .reset-modal-box { - width: 60vw; - max-width: 60vw; - min-width: 340px; - padding: 30px 34px; - gap: 16px; - box-shadow: 0 20px 48px rgba(0, 0, 0, 0.22); -} - -#github-import-modal .reset-modal-message { - font-size: 18px; - line-height: 1.35; - text-align: left; -} - -#github-import-url, -#github-import-file-select { - min-height: 46px; - padding: 10px 12px; - font-size: 15px; -} - -#github-import-file-select { - min-height: 180px; -} - -.github-import-tree { - max-height: 420px; - overflow: auto; - border: 1px solid var(--border-color); - border-radius: 10px; - padding: 12px; - background: var(--bg-color); -} - -.github-import-selection-toolbar { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; - padding: 10px 12px; - border: 1px solid var(--border-color); - border-radius: 8px; - background: var(--button-bg); -} - -.github-import-selected-count { - font-size: 14px; - font-weight: 600; - color: var(--text-color); -} - -.github-import-tree ul { - list-style: none; - margin: 0; - padding-left: 18px; -} - -.github-import-tree > ul { - padding-left: 4px; -} - -.github-import-tree li { - margin: 2px 0; -} - -.github-tree-folder-label { - display: inline-block; - font-size: 14px; - color: var(--text-secondary, #57606a); - margin-bottom: 4px; -} - -.github-tree-file-btn { - border: 0; - background: transparent; - color: var(--text-color); - cursor: pointer; - padding: 6px 8px; - border-radius: 6px; - text-align: left; - width: 100%; - font-size: 14px; -} - -.github-tree-file-btn:hover, -.github-tree-file-btn:focus-visible { - background: var(--button-hover); - outline: none; -} - -.github-tree-file-btn.is-selected { - background: rgba(56, 139, 253, 0.14); - color: var(--accent-color); -} - -#github-import-modal .reset-modal-actions { - gap: 12px; -} - -#github-import-modal .reset-modal-btn { - min-height: 42px; - padding: 9px 18px; - font-size: 14px; -} - -@media (max-width: 576px) { - #github-import-modal .reset-modal-box { - width: 95vw; - max-width: 95vw; - min-width: 0; - padding: 20px; - gap: 14px; - } - - .github-import-selection-toolbar { - flex-direction: column; - align-items: stretch; - } - - #github-import-modal .reset-modal-message { - font-size: 16px; - } - - #github-import-modal .reset-modal-actions { - flex-direction: column-reverse; - } - - #github-import-modal .reset-modal-btn { - width: 100%; - } -} - -.frontmatter-table { - border-collapse: collapse; - margin-bottom: 1.5em; - font-size: 0.9em; - width: auto; - max-width: 100%; -} - -.frontmatter-table th, -.frontmatter-table td { - border: 1px solid var(--border-color); - padding: 6px 13px; - vertical-align: top; - color: var(--text-color); -} - -.frontmatter-table tr:nth-child(odd) th, -.frontmatter-table tr:nth-child(odd) td { - background-color: var(--table-bg); -} - -.frontmatter-table tr:nth-child(even) th, -.frontmatter-table tr:nth-child(even) td { - background-color: var(--editor-bg); -} - -.frontmatter-table th { - font-weight: 600; - text-align: right; - white-space: nowrap; - vertical-align: middle; -} - -.frontmatter-table td { - text-align: left; -} - -.fm-complex { - margin: 0; - padding: 4px 6px; - font-size: 0.8em; - font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; - white-space: pre-wrap; - word-break: break-word; - background: transparent; - border: none; - color: var(--text-color); -} - -.fm-tag { - display: inline-block; - padding: 2px 8px; - margin: 2px 3px 2px 0; - border: 1px solid var(--border-color); - border-radius: 2em; - font-size: 0.8em; - font-weight: 500; - color: var(--accent-color); - background-color: var(--button-bg); - white-space: nowrap; -} - -/* ======================================== - RTL SUPPORT - ======================================== */ - -[dir="rtl"] body { - direction: rtl; -} - -[dir="rtl"] .editor-pane { - padding-left: 0px; - padding-right: 20px; - border-right: none; - border-left: 1px solid var(--border-color); -} - -[dir="rtl"] #markdown-editor, -[dir="rtl"] .markdown-body { - direction: rtl; - text-align: right; -} - -[dir="rtl"] .markdown-body pre, -[dir="rtl"] .markdown-body code, -[dir="rtl"] .fm-complex { - direction: ltr; - text-align: left; -} - -[dir="rtl"] .line-numbers { - left: auto; - right: 20px; - padding: 10px 0 10px 8px; - text-align: left; - border-right: none; - border-left: 1px solid var(--border-color); -} - -[dir="rtl"] #markdown-editor { - padding-left: 10px; - padding-right: calc(10px + var(--line-number-gutter)); -} - -[dir="rtl"] .editor-highlight-layer { - inset: 20px calc(20px + var(--line-number-gutter)) 20px 0; -} - -[dir="rtl"] .mobile-menu-item, -[dir="rtl"] .tab-menu-item, -[dir="rtl"] .modal-header .reset-modal-message, -[dir="rtl"] .reset-modal-field, -[dir="rtl"] .alert-option, -[dir="rtl"] .github-import-error, -[dir="rtl"] #github-import-modal .reset-modal-message, -[dir="rtl"] .github-tree-file-btn, -[dir="rtl"] .frontmatter-table td { - text-align: right; -} - -[dir="rtl"] .github-import-tree ul { - padding-left: 0; - padding-right: 18px; -} - -[dir="rtl"] .github-import-tree > ul { - padding-right: 4px; -} - -[dir="rtl"] .markdown-body .markdown-alert, -[dir="rtl"] .alert-preview .markdown-alert { - border-left: 0; - border-right: 0.25em solid currentColor; -} - -/* ============================================ - SHARE MODAL - ============================================ */ - -.share-modal-description { - font-size: 13px; - color: var(--text-secondary, #57606a); - margin: 0; -} - -.share-mode-cards { - display: flex; - flex-direction: column; - gap: 8px; -} - -.share-mode-card { - display: flex; - align-items: center; - gap: 12px; - padding: 12px 14px; - border-radius: 8px; - border: 1px solid var(--border-color); - background: var(--bg-color); - cursor: pointer; - transition: border-color 0.15s ease, background-color 0.15s ease; - user-select: none; -} - -.share-mode-card:hover { - border-color: var(--accent-color); - background: var(--button-hover); -} - -.share-mode-card.is-selected { - border-color: var(--accent-color); - background: color-mix(in srgb, var(--accent-color) 8%, transparent); -} - -.share-mode-card input[type="radio"] { - display: none; -} - -.share-card-icon { - font-size: 18px; - width: 28px; - text-align: center; - color: var(--text-secondary, #57606a); - flex-shrink: 0; -} - -.share-mode-card.is-selected .share-card-icon { - color: var(--accent-color); -} - -.share-card-body { - display: flex; - flex-direction: column; - gap: 2px; - flex: 1; - min-width: 0; -} - -.share-card-title { - font-size: 13px; - font-weight: 600; - color: var(--text-color); -} - -.share-card-desc { - font-size: 12px; - color: var(--text-secondary, #57606a); -} - -.share-card-check { - width: 18px; - text-align: center; - color: var(--accent-color); - opacity: 0; - transition: opacity 0.15s ease; - flex-shrink: 0; -} - -.share-mode-card.is-selected .share-card-check { - opacity: 1; -} - -.share-url-row { - display: flex; - gap: 8px; - align-items: center; -} - -.share-url-input { - flex: 1; - font-size: 12px; - font-family: var(--font-mono, monospace); - color: var(--text-secondary, #57606a); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.share-copy-btn { - flex-shrink: 0; - padding: 6px 10px; -} - -.share-copy-btn:disabled { - opacity: 0.5; - cursor: not-allowed; -} - -.share-modal-notice { - font-size: 11px; - color: var(--text-secondary, #57606a); - margin: 0; - display: flex; - align-items: center; - gap: 5px; -} - -/* ========================================================================== - Multilingual & CJK Optimization styles added by Aegis SEO agency - ========================================================================== */ -.lang-select-item { - display: flex !important; - align-items: center; - gap: 8px; - cursor: pointer; - transition: background-color 0.2s ease, padding-left 0.2s ease; -} - -.lang-select-item:hover { - padding-left: 12px; -} - -.lang-select-item.active { - background-color: var(--accent-color) !important; - color: #ffffff !important; - font-weight: 600; -} - -/* Adjust CJK text layout for maximum readability inside the preview pane */ -html[lang="zh"] .markdown-body, -html[lang="ja"] .markdown-body, -html[lang="ko"] .markdown-body { - line-height: 1.75 !important; - letter-spacing: 0.03em; - word-break: keep-all; - overflow-wrap: break-word; - text-align: justify; -} - -/* Specific heading spacing improvements for CJK characters */ -html[lang="zh"] .markdown-body h1, html[lang="zh"] .markdown-body h2, html[lang="zh"] .markdown-body h3, -html[lang="ja"] .markdown-body h1, html[lang="ja"] .markdown-body h2, html[lang="ja"] .markdown-body h3, -html[lang="ko"] .markdown-body h1, html[lang="ko"] .markdown-body h2, html[lang="ko"] .markdown-body h3 { - font-weight: 700; - letter-spacing: 0.02em; - margin-top: 1.4em; - margin-bottom: 0.6em; -} - -/* Smooth fade and scale transition for dropdown active states */ -.dropdown-menu { - opacity: 0; - transform: translateY(8px) scale(0.98); - display: block; - visibility: hidden; - transition: opacity 0.2s cubic-bezier(0.16, 1, 0.3, 1), transform 0.2s cubic-bezier(0.16, 1, 0.3, 1), visibility 0.2s; -} - -.dropdown-menu.show { - opacity: 1; - transform: translateY(0) scale(1); - visibility: visible; -} - -/* ======================================== - FIND & REPLACE FLOATING PANEL DESIGN - ======================================== */ - -.find-replace-panel { - position: fixed; - top: 100px; - right: 20px; - width: 340px; - background-color: var(--fr-bg); - border: 1px solid var(--fr-border); - border-radius: 12px; - box-shadow: var(--fr-shadow); - z-index: 1050; - display: flex; - flex-direction: column; - backdrop-filter: blur(10px); - -webkit-backdrop-filter: blur(10px); - transition: opacity 0.2s ease, transform 0.2s ease; - user-select: none; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; -} - -.find-replace-panel.docked { - position: relative; - top: 0 !important; - right: 0 !important; - height: 100%; - border-radius: 0; - border-top: none; - border-bottom: none; - border-right: none; - border-left: 1px solid var(--fr-border); - box-shadow: none; - backdrop-filter: none; - z-index: 10; - flex-shrink: 0; -} - -.find-replace-panel.docked #find-replace-reset, -.find-replace-panel.docked #find-replace-reset-footer { - display: none !important; -} - -.find-replace-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 8px 12px; - border-bottom: 1px solid var(--fr-border); - cursor: move; - background-color: var(--header-bg); - border-top-left-radius: 11px; - border-top-right-radius: 11px; -} - -.find-replace-panel.docked .find-replace-header { - cursor: default; - border-top-left-radius: 0; - border-top-right-radius: 0; -} - -.find-replace-title { - font-size: 13px; - font-weight: 600; - color: var(--text-color); -} - -.find-replace-header-actions { - display: flex; - gap: 4px; -} - -.panel-icon-btn { - background: none; - border: none; - color: var(--text-color); - font-size: 12px; - cursor: pointer; - padding: 2px 6px; - border-radius: 4px; - display: flex; - align-items: center; - justify-content: center; - transition: background-color 0.15s ease; -} - -.panel-icon-btn:hover { - background-color: var(--button-hover); -} - -.find-replace-body { - padding: 12px; - display: flex; - flex-direction: column; - gap: 8px; -} - -.find-replace-field-row { - display: flex; - flex-direction: column; - position: relative; -} - -.find-input-container, .replace-input-container { - display: flex; - align-items: center; - border: 1px solid var(--fr-border); - border-radius: 6px; - background-color: var(--bg-color); - padding: 2px 4px; - width: 100%; -} - -.find-input-container:focus-within, .replace-input-container:focus-within { - border-color: var(--accent-color); - box-shadow: 0 0 0 3px rgba(9, 105, 218, 0.15); -} - -.find-input-field { - flex: 1; - border: none; - background: transparent; - color: var(--text-color); - font-size: 13px; - padding: 4px 6px; - outline: none; - width: 50%; -} - -.find-options-group { - display: flex; - gap: 2px; -} - -.find-option-btn { - background: none; - border: none; - color: var(--text-secondary); - font-size: 11px; - font-weight: 600; - cursor: pointer; - padding: 2px 5px; - border-radius: 4px; - transition: background-color 0.12s ease, color 0.12s ease; - min-width: 22px; - height: 22px; - display: inline-flex; - align-items: center; - justify-content: center; -} - -.find-option-btn:hover { - background-color: var(--button-hover); - color: var(--text-color); -} - -.find-option-btn.active { - background-color: var(--fr-btn-active-bg); - color: var(--fr-btn-active); -} - -.find-error-drawer { - background-color: var(--fr-error-bg); - border: 1px solid var(--fr-error-border); - border-radius: 6px; - padding: 6px 10px; - font-size: 11px; - color: var(--fr-text-danger); - line-height: 1.3; -} - -.find-replace-meta-row { - display: flex; - align-items: center; - justify-content: space-between; - padding: 2px 4px; -} - -.find-match-count { - font-size: 12px; - color: var(--text-secondary); -} - -.find-nav-group { - display: flex; - gap: 4px; -} - -.find-nav-arrow-btn { - background: none; - border: 1px solid var(--fr-border); - color: var(--text-color); - font-size: 12px; - cursor: pointer; - padding: 2px 8px; - border-radius: 4px; - transition: background-color 0.15s ease; - display: flex; - align-items: center; - justify-content: center; -} - -.find-nav-arrow-btn:hover:not(:disabled) { - background-color: var(--button-hover); -} - -.find-nav-arrow-btn:disabled { - opacity: 0.4; - cursor: not-allowed; -} - -.find-drawer-toggle-row { - border-top: 1px solid var(--fr-border); - margin-top: 4px; - padding-top: 6px; -} - -.drawer-toggle-btn { - background: none; - border: none; - color: var(--text-secondary); - font-size: 12px; - cursor: pointer; - display: flex; - align-items: center; - padding: 2px 4px; - border-radius: 4px; - transition: color 0.15s ease; -} - -.drawer-toggle-btn:hover { - color: var(--text-color); -} - -.find-replace-drawer-content { - display: flex; - flex-direction: column; - gap: 8px; - padding: 4px 6px; - border-top: 1px dashed var(--fr-border); - margin-top: 2px; - padding-top: 8px; -} - -.drawer-field { - display: flex; - flex-direction: column; - gap: 4px; -} - -.drawer-field.check-field { - flex-direction: row; - align-items: center; - gap: 6px; - padding: 2px 0; -} - -.drawer-label { - font-size: 11px; - font-weight: 600; - color: var(--text-secondary); -} - -.drawer-select { - width: 100%; - padding: 4px 6px; - border-radius: 4px; - border: 1px solid var(--fr-border); - background-color: var(--bg-color); - color: var(--text-color); - font-size: 12px; - outline: none; -} - -.drawer-checkbox { - margin: 0; - cursor: pointer; -} - -.drawer-label-checkbox { - font-size: 12px; - color: var(--text-color); - cursor: pointer; -} - -.find-replace-actions-footer { - display: flex; - gap: 6px; - padding: 8px 12px 12px 12px; - border-top: 1px solid var(--fr-border); - background-color: var(--header-bg); - border-bottom-left-radius: 11px; - border-bottom-right-radius: 11px; -} - -.find-replace-panel.docked .find-replace-actions-footer { - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; -} - -.fr-action-btn { - flex: 1; - padding: 6px 8px; - font-size: 12px; - font-weight: 500; - border-radius: 6px; - border: 1px solid var(--fr-border); - background-color: var(--button-bg); - color: var(--text-color); - cursor: pointer; - transition: background-color 0.15s ease, border-color 0.15s ease; - text-align: center; -} - -.fr-action-btn:hover:not(:disabled) { - background-color: var(--button-hover); -} - -.fr-action-btn:disabled { - opacity: 0.5; - cursor: not-allowed; -} - -.fr-action-btn.secondary { - max-width: 60px; -} - -/* ======================================== - DIFF PREVIEW CONTAINER - ======================================== */ -.diff-preview-body { - padding: 16px; - display: flex; - flex-direction: column; - gap: 12px; -} - -.diff-container { - border: 1px solid var(--fr-border); - border-radius: 8px; - background-color: var(--bg-color); - max-height: 400px; - overflow: auto; - font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; - font-size: 12px; - line-height: 1.5; -} - -.diff-line { - display: flex; - padding: 1px 8px; -} - -.diff-line.addition { - background-color: rgba(46, 160, 67, 0.15); - color: #3fb950; -} - -.diff-line.deletion { - background-color: rgba(248, 81, 73, 0.15); - color: #f85149; -} - -.diff-line.context { - color: var(--text-secondary); -} - -.diff-line-num { - width: 40px; - flex-shrink: 0; - text-align: right; - padding-right: 12px; - border-right: 1px solid var(--fr-border); - user-select: none; - opacity: 0.5; -} - -.diff-line-content { - padding-left: 12px; - white-space: pre-wrap; - word-break: break-all; -} - -/* ======================================== - DOCK LAYOUT CODES - ======================================== */ -.content-container { - display: flex; - flex: 1; - overflow: hidden; - position: relative; -} - -.editor-dock-wrapper { - display: flex; - flex: 1; - overflow: hidden; - position: relative; -} - -.editor-pane-inner { - display: flex; - flex-direction: column; - flex: 1; - position: relative; - overflow: hidden; -} - -/* ======================================== - MOBILE & TABLET FIND PANEL RESPONSIVE FIXES - ======================================== */ -@media (max-width: 1079px) { - #find-replace-dock { - display: none !important; - } -} - -@media (max-width: 768px) { - /* Prevent full screen expansion of floating panel on small mobile viewports */ - .find-replace-panel { - width: calc(100% - 24px) !important; - right: 12px !important; - left: 12px !important; - top: 80px !important; - } -} - -/* ======================================== - SKELETON LOADING SHIMMER SYSTEM - ======================================== */ -.skeleton-placeholder { - display: block; - background-color: var(--skeleton-bg); - border-radius: 6px; - position: relative; - overflow: hidden; - /* PERF-017: Removed skeleton-pulse; shimmer-only is sufficient and halves GPU compositing layers */ - /* animation: skeleton-pulse 2.2s cubic-bezier(0.4, 0, 0.2, 1) infinite alternate; */ -} - -.skeleton-placeholder::after { - content: ""; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - transform: translateX(-100%); - background-image: linear-gradient( - 90deg, - rgba(255, 255, 255, 0) 0%, - var(--skeleton-glow) 50%, - rgba(255, 255, 255, 0) 100% - ); - animation: skeleton-shimmer 1.6s cubic-bezier(0.4, 0, 0.2, 1) infinite; -} - -@keyframes skeleton-shimmer { - 100% { - transform: translateX(100%); - } -} - -@keyframes skeleton-pulse { - 0%, 100% { - opacity: 1; - } - 50% { - opacity: 0.82; - } -} - -.skeleton-circle { - width: 32px; - height: 32px; - border-radius: 50%; - margin: 0 auto; -} - -.skeleton-text { - height: 12px; - width: 80%; - margin: 4px auto; - border-radius: 3px; -} - -.skeleton-tree-folder { - height: 16px; - width: 140px; - margin: 6px 0; - display: inline-block; -} - -.skeleton-tree-file { - height: 14px; - width: 180px; - margin: 4px 0 4px 12px; - display: inline-block; -} - -/* Screen reader accessibility utility */ -.visually-hidden { - position: absolute !important; - width: 1px !important; - height: 1px !important; - padding: 0 !important; - margin: -1px !important; - overflow: hidden !important; - clip: rect(0, 0, 0, 0) !important; - clip-path: inset(50%) !important; - white-space: nowrap !important; - border: 0 !important; -} - -/* Article skeleton layout structures */ -.skeleton-title { - height: 28px; - width: 35%; - margin-bottom: 24px; - border-radius: 8px; -} - -.skeleton-subtitle { - height: 20px; - width: 20%; - margin-bottom: 18px; - margin-top: 32px; - border-radius: 6px; -} - -.skeleton-line { - height: 14px; - margin-bottom: 12px; - border-radius: 6px; -} - -/* Symmetrical dynamic widths */ -.skeleton-w90 { width: 90%; } -.skeleton-w92 { width: 92%; } -.skeleton-w88 { width: 88%; } -.skeleton-w85 { width: 85%; } -.skeleton-w60 { width: 60%; } -.skeleton-w45 { width: 45%; } - -/* Editor pane skeleton overlay */ -.editor-skeleton { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - padding: 30px 24px 24px calc(24px + var(--line-number-gutter)); - z-index: 10; - pointer-events: none; - background: var(--editor-bg); - box-sizing: border-box; - overflow: hidden; - transition: opacity 0.3s ease; -} - -.editor-pane:not(.is-loading) .editor-skeleton { - display: none; -} - -.editor-pane.is-loading textarea { - opacity: 0; /* Completely hide editor content while initial bootstrap skeleton runs */ -} - -/* Preview pane skeleton container */ -.skeleton-preview-container { - display: block; - width: 100%; - box-sizing: border-box; - padding: 10px 4px; - background: transparent; - transition: opacity 0.3s ease; -} - -/* Mermaid compilation loading states */ -.mermaid-container.is-loading { - min-height: 180px; - background-color: var(--skeleton-bg); - border-radius: 8px; - border: 1px solid var(--border-color); - position: relative; - overflow: hidden; - animation: skeleton-pulse 2.2s cubic-bezier(0.4, 0, 0.2, 1) infinite alternate; -} - -.mermaid-container.is-loading .mermaid { - opacity: 0; /* Hide raw chart source code during compile */ -} - -.mermaid-container.is-loading::after { - content: ""; - position: absolute; - inset: 0; - transform: translateX(-100%); - background-image: linear-gradient( - 90deg, - rgba(255, 255, 255, 0) 0%, - var(--skeleton-glow) 50%, - rgba(255, 255, 255, 0) 100% - ); - animation: skeleton-shimmer 1.6s cubic-bezier(0.4, 0, 0.2, 1) infinite; -} - -/* Accessibility: respect user's motion preferences */ -@media (prefers-reduced-motion: reduce) { - .skeleton-placeholder, - .skeleton-placeholder::after, - .mermaid-container.is-loading, - .mermaid-container.is-loading::after { - animation: none; - } - .drag-overlay-inner { - animation: none; - } - .tab-item-new { - animation: none; - } - body, - .app-header, - .editor-pane, - .preview-pane, - .tool-button, - .markdown-tool-btn { - transition: none; - } -} - \ No newline at end of file + +.mermaid-container.is-loading::after { + content: ""; + position: absolute; + inset: 0; + transform: translateX(-100%); + background-image: linear-gradient( + 90deg, + rgba(255, 255, 255, 0) 0%, + var(--skeleton-glow) 50%, + rgba(255, 255, 255, 0) 100% + ); + animation: skeleton-shimmer 1.6s cubic-bezier(0.4, 0, 0.2, 1) infinite; +} + +/* Accessibility: respect user's motion preferences */ +@media (prefers-reduced-motion: reduce) { + .skeleton-placeholder, + .skeleton-placeholder::after, + .mermaid-container.is-loading, + .mermaid-container.is-loading::after { + animation: none; + } + .drag-overlay-inner { + animation: none; + } + .tab-item-new { + animation: none; + } + body, + .app-header, + .editor-pane, + .preview-pane, + .tool-button, + .markdown-tool-btn { + transition: none; + } +} + +/* ======================================== + BROWSER PRINT STYLES + ======================================== */ +@media print { + body * { + visibility: hidden; + } + #markdown-preview, #markdown-preview * { + visibility: visible; + } + #markdown-preview { + position: absolute; + left: 0; + top: 0; + width: 100% !important; + height: auto !important; + margin: 0 !important; + padding: 0 !important; + overflow: visible !important; + box-shadow: none !important; + border: none !important; + background: transparent !important; + } + .preview-pane { + position: static !important; + width: 100% !important; + height: auto !important; + overflow: visible !important; + margin: 0 !important; + padding: 0 !important; + box-shadow: none !important; + border: none !important; + background: transparent !important; + } + .content-container { + display: block !important; + position: static !important; + width: 100% !important; + height: auto !important; + overflow: visible !important; + } + header, .tab-bar, .markdown-format-toolbar, .editor-pane, .resize-divider, #line-numbers, .pdf-progress-overlay { + display: none !important; + } +} \ No newline at end of file From 769583236fce9adcda2055911e9d88c8ff17702e Mon Sep 17 00:00:00 2001 From: Baivab Sarkar Date: Thu, 11 Jun 2026 11:59:02 +0530 Subject: [PATCH 3/4] fix: add @page margin configuration to browser print stylesheet --- desktop-app/resources/styles.css | 3 +++ styles.css | 3 +++ 2 files changed, 6 insertions(+) diff --git a/desktop-app/resources/styles.css b/desktop-app/resources/styles.css index c0c8401f..00c3f70b 100644 --- a/desktop-app/resources/styles.css +++ b/desktop-app/resources/styles.css @@ -3875,6 +3875,9 @@ html[lang="ko"] .markdown-body h1, html[lang="ko"] .markdown-body h2, html[lang= BROWSER PRINT STYLES ======================================== */ @media print { + @page { + margin: 20mm 15mm !important; + } body * { visibility: hidden; } diff --git a/styles.css b/styles.css index c0c8401f..00c3f70b 100644 --- a/styles.css +++ b/styles.css @@ -3875,6 +3875,9 @@ html[lang="ko"] .markdown-body h1, html[lang="ko"] .markdown-body h2, html[lang= BROWSER PRINT STYLES ======================================== */ @media print { + @page { + margin: 20mm 15mm !important; + } body * { visibility: hidden; } From 0f8192fd05cea906227dd0a91c48d848581571e8 Mon Sep 17 00:00:00 2001 From: Baivab Sarkar Date: Thu, 11 Jun 2026 12:04:32 +0530 Subject: [PATCH 4/4] style: add margins and format layout for browser print --- desktop-app/resources/styles.css | 49 ++++++++++++++------------------ styles.css | 49 ++++++++++++++------------------ 2 files changed, 42 insertions(+), 56 deletions(-) diff --git a/desktop-app/resources/styles.css b/desktop-app/resources/styles.css index 00c3f70b..90facaaf 100644 --- a/desktop-app/resources/styles.css +++ b/desktop-app/resources/styles.css @@ -3876,46 +3876,39 @@ html[lang="ko"] .markdown-body h1, html[lang="ko"] .markdown-body h2, html[lang= ======================================== */ @media print { @page { - margin: 20mm 15mm !important; + margin: 15mm 15mm 15mm 15mm; } - body * { - visibility: hidden; + body { + background: #ffffff !important; + color: #000000 !important; } - #markdown-preview, #markdown-preview * { - visibility: visible; + /* Hide all UI layout components */ + header, + .tab-bar, + .markdown-format-toolbar, + .editor-pane, + .resize-divider, + .pdf-progress-overlay, + .reset-modal-overlay, + .drag-overlay, + #mobile-menu-overlay, + .mermaid-toolbar, + #line-numbers { + display: none !important; } + /* Ensure preview container fills the page with correct margins */ + .content-container, + .preview-pane, #markdown-preview { - position: absolute; - left: 0; - top: 0; + display: block !important; width: 100% !important; height: auto !important; margin: 0 !important; padding: 0 !important; overflow: visible !important; - box-shadow: none !important; - border: none !important; - background: transparent !important; - } - .preview-pane { position: static !important; - width: 100% !important; - height: auto !important; - overflow: visible !important; - margin: 0 !important; - padding: 0 !important; box-shadow: none !important; border: none !important; background: transparent !important; } - .content-container { - display: block !important; - position: static !important; - width: 100% !important; - height: auto !important; - overflow: visible !important; - } - header, .tab-bar, .markdown-format-toolbar, .editor-pane, .resize-divider, #line-numbers, .pdf-progress-overlay { - display: none !important; - } } \ No newline at end of file diff --git a/styles.css b/styles.css index 00c3f70b..90facaaf 100644 --- a/styles.css +++ b/styles.css @@ -3876,46 +3876,39 @@ html[lang="ko"] .markdown-body h1, html[lang="ko"] .markdown-body h2, html[lang= ======================================== */ @media print { @page { - margin: 20mm 15mm !important; + margin: 15mm 15mm 15mm 15mm; } - body * { - visibility: hidden; + body { + background: #ffffff !important; + color: #000000 !important; } - #markdown-preview, #markdown-preview * { - visibility: visible; + /* Hide all UI layout components */ + header, + .tab-bar, + .markdown-format-toolbar, + .editor-pane, + .resize-divider, + .pdf-progress-overlay, + .reset-modal-overlay, + .drag-overlay, + #mobile-menu-overlay, + .mermaid-toolbar, + #line-numbers { + display: none !important; } + /* Ensure preview container fills the page with correct margins */ + .content-container, + .preview-pane, #markdown-preview { - position: absolute; - left: 0; - top: 0; + display: block !important; width: 100% !important; height: auto !important; margin: 0 !important; padding: 0 !important; overflow: visible !important; - box-shadow: none !important; - border: none !important; - background: transparent !important; - } - .preview-pane { position: static !important; - width: 100% !important; - height: auto !important; - overflow: visible !important; - margin: 0 !important; - padding: 0 !important; box-shadow: none !important; border: none !important; background: transparent !important; } - .content-container { - display: block !important; - position: static !important; - width: 100% !important; - height: auto !important; - overflow: visible !important; - } - header, .tab-bar, .markdown-format-toolbar, .editor-pane, .resize-divider, #line-numbers, .pdf-progress-overlay { - display: none !important; - } } \ No newline at end of file