diff --git a/frontend/src/components/TopicDetail.vue b/frontend/src/components/TopicDetail.vue index 8e6e555..44db5b4 100644 --- a/frontend/src/components/TopicDetail.vue +++ b/frontend/src/components/TopicDetail.vue @@ -34,6 +34,14 @@ function onFrameMouseDown() { } function injectStyles(doc) { + // Ohne viewport-meta rendert das iframe-Dokument mit Desktop-Breite und greift unsere max-width-Query nicht. + if (!doc.querySelector('meta[name="viewport"]')) { + const meta = doc.createElement('meta') + meta.name = 'viewport' + meta.content = 'width=device-width, initial-scale=1' + doc.head?.appendChild(meta) + } + const style = doc.createElement('style') const portrait = !isLandscape.value ? `html { background: #f0f1f4; } @@ -70,6 +78,50 @@ function injectStyles(doc) { color: #065f46; } section.chapter.ch-complete > :not(.ch-toggle) { opacity: 0.4; } + } + + @media screen and (max-width: 700px) { + html { background: #fff; } + body { + zoom: 1 !important; + max-width: 100% !important; + padding: 1.25rem 1rem !important; + box-shadow: none !important; + } + + /* Cover/Part-Divider: feste mm-Höhen + flex-center fürs Print-A4. Auf Mobile läuft + zentrierter Inhalt über die Box hinaus und überlappt das nächste Element. + → als normale Blöcke von oben fließen lassen. */ + .cover, .part-divider { + height: auto !important; + min-height: 0 !important; + justify-content: flex-start !important; + padding: 2.5rem 1.25rem !important; + overflow: hidden; + } + .cover h1 { font-size: 30pt !important; } + .cover h1 .light { font-size: 22pt !important; } + .cover .sub { font-size: 12pt !important; max-width: 100% !important; margin-bottom: 1.5rem !important; } + .cover .meta-row { flex-wrap: wrap; gap: 0.75rem 1.5rem !important; } + .cover-deco { font-size: 60pt !important; right: 1rem !important; } + + .part-divider h1 { font-size: 26pt !important; } + .part-divider .part-desc { max-width: 100% !important; } + + .chapter-head h1 { font-size: 22pt !important; } + + /* Print schneidet Code hart ab (overflow: hidden) → auf Mobile umbrechen + scrollbar */ + pre { + white-space: pre-wrap !important; + word-break: break-word; + overflow-x: auto !important; + } + + /* Blocksatz erzeugt riesige Wortlücken in schmalen Spalten */ + p { text-align: left !important; } + + /* Breite Tabellen horizontal scrollbar statt überlaufend */ + table { display: block; width: 100%; overflow-x: auto; } }` doc.head?.appendChild(style) } @@ -110,6 +162,13 @@ async function setupProgress(doc) { }) section.appendChild(toggle) }) + + // Zum ersten noch offenen Kapitel springen — aber nur, wenn davor schon was erledigt ist. + // Frischer Guide (nichts erledigt) bleibt oben beim Cover. + const firstOpen = chapters.find((s) => !s.classList.contains('ch-complete')) + if (firstOpen && firstOpen !== chapters[0]) { + firstOpen.scrollIntoView({ block: 'start' }) + } } // --- Chat --- diff --git a/frontend/src/components/TopicSidebar.vue b/frontend/src/components/TopicSidebar.vue index f7db6fd..8cab096 100644 --- a/frontend/src/components/TopicSidebar.vue +++ b/frontend/src/components/TopicSidebar.vue @@ -247,6 +247,7 @@ function confirmDeleteTopic(topic) { .new-topic input { flex: 1; + min-width: 0; padding: 6px 8px; border: 1px solid #d8dde3; border-radius: 6px;