diff --git a/app/web/src/main.js b/app/web/src/main.js
index 853114b..aeaa779 100644
--- a/app/web/src/main.js
+++ b/app/web/src/main.js
@@ -754,7 +754,7 @@ async function openRecording(id) {
`;
const mods = {
analyse: `
- ${r.summary ? `
${escapeHtml(r.summary)}
` : 'Noch keine Zusammenfassung.
'}
+ ${r.summary ? `${renderSummary(r.summary)}
` : 'Noch keine Zusammenfassung.
'}
${(r.participants && r.participants.length) ? `Teilnehmer
${r.participants.map(p => `- 👤 ${escapeHtml(p)}
`).join('')}
` : ''}
${markersHtml}`,
todos: (r.todos && r.todos.length) ? `${r.todos.map(t => `- ${escapeHtml(t)}
`).join('')}
` : 'Keine ToDos erkannt.
',
@@ -1143,6 +1143,22 @@ async function openRecording(id) {
function escapeHtml(s) { return (s || '').replace(/[&<>"]/g, c => ({ '&': '&', '<': '<', '>': '>', '"': '"' }[c])); }
+// The section summary comes back as "Abschnittstitel:\nFließtext…" blocks (see
+// llm.js analyzeLong). Flat, that reads as one wall of text, so the title lines
+// get set in bold. Done at RENDER time on purpose, not stored in the database:
+// it applies to every summary that already exists, without re-running a
+// 20-minute analysis on 22 recordings.
+function renderSummary(text) {
+ return escapeHtml(text || '').split('\n').map(line => {
+ const t = line.trim();
+ // A heading is a SHORT, STANDALONE line ending in a colon. Both conditions
+ // matter: prose like "…die Struktur der Projektberichterstattung: kurze
+ // Einordnung, aktueller Stand…" has the colon mid-line and keeps running,
+ // and excluding . ! ? stops a full sentence that happens to end in a colon.
+ return /^[^.!?]{3,90}:$/.test(t) ? `${t}` : line;
+ }).join('\n');
+}
+
// ---- Konferenztisch-Ansicht ----
// Seat positions (person center, % of scene) per participant count, arranged
// around the rectangular table; each seat knows which bubble-arrow side points
diff --git a/app/web/src/style.css b/app/web/src/style.css
index 4709051..bae6e52 100644
--- a/app/web/src/style.css
+++ b/app/web/src/style.css
@@ -492,4 +492,12 @@ body.resizing { cursor: col-resize; user-select: none; }
@media (max-width: 640px) {
.search-page.landing { padding-top: 6vh; }
.search-go { padding: .55rem .8rem; }
+}
+/* Abschnittstitel in der Zusammenfassung ("Neuer Projektleiter vorgestellt:").
+ Etwas Luft darüber, damit die Blöcke optisch trennen — der Text steht in
+ white-space: pre-line, die ZeilenumbrĂĽche kommen also aus dem Text selbst. */
+.summary .sum-head {
+ font-weight: 700;
+ color: var(--fg);
+ line-height: 2.2;
}
\ No newline at end of file
diff --git a/docs/08-changelog.md b/docs/08-changelog.md
index d845812..2ac68a3 100644
--- a/docs/08-changelog.md
+++ b/docs/08-changelog.md
@@ -3,6 +3,25 @@
Chronik der Entwicklungsschritte. **Regel: jede zukünftige Änderung bekommt hier einen Eintrag** (Datum,
Was, Warum, betroffene Dateien/Backups).
+## 2026-07-31 (nachmittags) — Abschnittstitel in der Zusammenfassung fett
+
+Die Section-Zusammenfassung kommt als `Abschnittstitel:\nFließtext…`-Blöcke zurück (llm.js/analyzeLong),
+wurde aber als eine flache Textwand gerendert. Titelzeilen erscheinen jetzt fett.
+
+**Bewusst im Renderer, nicht in der Datenbank:** so gilt es sofort fĂĽr alle bereits vorhandenen
+Zusammenfassungen, ohne auf 22 Aufnahmen je eine 20-Minuten-Analyse neu zu fahren.
+
+Erkennungsregel in `renderSummary()` (`main.js`): eine **kurze, alleinstehende** Zeile, die auf einen
+Doppelpunkt endet und kein `.` `!` `?` enthält — `/^[^.!?]{3,90}:$/`. Beide Bedingungen sind nötig: Fließtext
+wie „…die Struktur der Projektberichterstattung: kurze Einordnung, aktueller Stand…" hat den Doppelpunkt
+mitten in der Zeile und läuft weiter.
+
+**Gegen echte Daten geprĂĽft** (Zusammenfassungen #85, #79, #74): 37 Titel erkannt, keine FlieĂźtextzeile
+fälschlich fett, keine Doppelpunkt-Zeile übersehen.
+
+Dateien: `app/web/src/main.js`, `app/web/src/style.css` (`.summary .sum-head`).
+Board-Backups: `.bak-sumhead`.
+
## 2026-07-31 — Inhaltssuche, Papierkorb, Titel umbenennen (+ WLAN-Ausfall behoben)
Drei Funktionen auf Wunsch des Nutzers, dazu die Störung vom Vormittag. Details: