<?php
declare(strict_types=1);

require_once dirname(__DIR__) . '/_article_catalog.php';
require_once dirname(__DIR__) . '/_dossier_catalog.php';
require_once dirname(__DIR__) . '/_story_priority.php';

$catalog = sg_catalog_load(['start', 'archiv', 'dev']);
$dossier = sg_dossier_load();
$incomingMap = sg_catalog_incoming_map($catalog);
$items = sg_catalog_flatten($catalog);

usort($items, static function (array $left, array $right): int {
    $leftOrder = (int) ($left['date_timestamp'] ?: $left['file_mtime'] ?: $left['index_number']);
    $rightOrder = (int) ($right['date_timestamp'] ?: $right['file_mtime'] ?: $right['index_number']);
    if ($rightOrder !== $leftOrder) {
        return $rightOrder <=> $leftOrder;
    }
    return (int) ($right['index_number'] ?? 0) <=> (int) ($left['index_number'] ?? 0);
});

$scopeCounts = [
    'start' => count(sg_catalog_items($catalog, 'start')),
    'archiv' => count(sg_catalog_items($catalog, 'archiv')),
    'dev' => count(sg_catalog_items($catalog, 'dev')),
];

$issueCounts = [];
foreach ($items as $item) {
    foreach (($item['issues'] ?? []) as $issue) {
        $issueCounts[$issue] = ($issueCounts[$issue] ?? 0) + 1;
    }
}
arsort($issueCounts);

$articleDateIndex = [];
foreach ($items as $item) {
    $normalized = (string) ($item['date_normalized'] ?? '');
    if ($normalized === '') {
        continue;
    }
    $articleDateIndex[substr($normalized, 0, 10)][] = $item;
}

$dossier = sg_priority_enrich_dossier($items, $dossier, 4);
$timelineSource = $dossier['timeline'] ?? [];
$overviewSource = $dossier['overview'] ?? [];
$assetSource = $dossier['assets'] ?? [];
$investigationQuestions = $timelineSource['questions'] ?? [];
$logicClusters = $timelineSource['clusters'] ?? [];
$offenseRows = $overviewSource['offenses'] ?? [];

function h(string $value): string
{
    return htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}

function scope_label(string $scope): string
{
    return match ($scope) {
        'start' => 'Startseite',
        'archiv' => 'Archiv',
        'dev' => 'devseiten',
        default => $scope,
    };
}

function lower_text(string $value): string
{
    return function_exists('mb_strtolower') ? mb_strtolower($value, 'UTF-8') : strtolower($value);
}

function article_public_href(array $item): string
{
    $slug = trim((string) ($item['slug'] ?? ''));
    if ($slug === '') {
        return '#';
    }
    return ((string) ($item['scope'] ?? '') === 'archiv' ? '/archiv/' : '/') . $slug;
}

function path_href(string $path): string
{
    if ($path === '' || $path === '#') {
        return '#';
    }

    $fragment = '';
    $fragmentPos = strpos($path, '#');
    if ($fragmentPos !== false) {
        $fragment = substr($path, $fragmentPos);
        $path = substr($path, 0, $fragmentPos);
    }

    $prefix = str_starts_with($path, '/') ? '/' : '';
    $parts = array_values(array_filter(explode('/', trim($path, '/')), static fn (string $part): bool => $part !== ''));
    return $prefix . implode('/', array_map('rawurlencode', $parts)) . $fragment;
}

function wall_link_label(array $link): string
{
    $label = trim((string) ($link['label'] ?? ''));
    if ($label !== '' && !preg_match('~^(oeffnen|öffnen|datei öffnen|pdf öffnen|beleg öffnen)$~iu', $label)) {
        return $label;
    }

    $href = (string) ($link['href'] ?? '');
    if ($href === '') {
        return $label !== '' ? $label : 'Beleg';
    }

    $path = parse_url($href, PHP_URL_PATH);
    if (!is_string($path) || $path === '') {
        $path = $href;
    }

    $base = basename(str_replace('\\', '/', $path));
    $base = trim(urldecode($base));
    return $base !== '' ? $base : ($label !== '' ? $label : 'Beleg');
}

function wall_group_offenses(array $offenses): array
{
    return sg_priority_group_offenses($offenses);
}

$offenseGroups = wall_group_offenses($offenseRows);

function wall_match_stopwords(): array
{
    static $words = null;
    if (is_array($words)) {
        return $words;
    }

    $words = array_fill_keys([
        'aber', 'akte', 'aktenzeichen', 'aktuelle', 'alles', 'allgemein', 'als', 'am', 'amtsgericht', 'an', 'antwort',
        'antrag', 'antraege', 'antragstellung', 'auch', 'auf', 'aus', 'beim', 'bereits', 'berlin', 'beweis', 'beweise',
        'beleg', 'belege', 'beitrag', 'beitraege', 'beschluss', 'beschwerde', 'beschwerden', 'bezug', 'bundesverfassungsbeschwerde',
        'christian', 'datei', 'dateiname', 'dem', 'den', 'der', 'des', 'diese', 'diesem', 'dieser', 'dieses', 'dokument', 'dokumente',
        'durch', 'eine', 'einem', 'einen', 'einer', 'eines', 'enthalt', 'enthaelt', 'enthaelt', 'enthält', 'enthielten', 'ergaenzende',
        'fuer', 'gegen', 'gericht', 'gerichte', 'gesamte', 'hat', 'hier', 'html', 'ihre', 'ihren', 'ihrer', 'index', 'kapitel', 'klage',
        'kreuzberg', 'lothar', 'kiessler', 'gabi', 'reimer', 'christian', 'landgericht', 'mueller', 'nicole', 'neuhauss', 'neuhaus',
        'ohne', 'oder', 'ordner', 'pdf', 'persoenliche', 'persoenlicher', 'richter', 'richterin', 'schluesselbeweise', 'schreiben',
        'seite', 'seiten', 'sicherheitsgigant', 'staatsanwaltschaft', 'system', 'tempelhof', 'timeline', 'titel', 'und', 'unterlagen',
        'verfahren', 'vorgangsnummer', 'vom', 'von', 'vorwurf', 'weitere', 'weiteren', 'welche', 'wird', 'wurden', 'zum', 'zur', 'zentrale'
    ], true);

    return $words;
}

function wall_normalize_match_text(string $value): string
{
    $value = lower_text(html_entity_decode($value, ENT_QUOTES | ENT_HTML5, 'UTF-8'));
    $value = strtr($value, [
        'ä' => 'ae',
        'ö' => 'oe',
        'ü' => 'ue',
        'ß' => 'ss',
    ]);
    $value = preg_replace('~[^a-z0-9]+~u', ' ', $value) ?? $value;
    return trim($value);
}

function wall_tokenize(string $value): array
{
    $normalized = wall_normalize_match_text($value);
    if ($normalized === '') {
        return [];
    }

    $specialShort = ['vkh' => true, 'zpo' => true, 'dhl' => true, 'fax' => true, 'olg' => true, 'kg' => true];
    $stopwords = wall_match_stopwords();
    $tokens = [];

    foreach (preg_split('~\s+~', $normalized) ?: [] as $token) {
        if ($token === '') {
            continue;
        }
        if (isset($stopwords[$token])) {
            continue;
        }
        if (preg_match('~^\d+$~', $token)) {
            if (strlen($token) < 4 || preg_match('~^(19|20)\d{2}$~', $token)) {
                continue;
            }
            $tokens[$token] = true;
            continue;
        }
        if (strlen($token) < 4 && !isset($specialShort[$token])) {
            continue;
        }
        $tokens[$token] = true;
    }

    return array_keys($tokens);
}

function wall_prepare_matchable_articles(array $items): array
{
    $prepared = [];
    foreach ($items as $item) {
        $prepared[] = $item + [
            '_date_key' => substr((string) ($item['date_normalized'] ?? ''), 0, 10),
            '_core_tokens' => wall_tokenize(implode(' ', [
                (string) ($item['title'] ?? ''),
                (string) ($item['headline2'] ?? ''),
                str_replace(['_', '-'], ' ', (string) ($item['slug'] ?? '')),
            ])),
            '_body_tokens' => wall_tokenize(implode(' ', [
                (string) ($item['excerpt'] ?? ''),
                (string) ($item['content_text'] ?? ''),
                (string) ($item['date_line'] ?? ''),
            ])),
        ];
    }
    return $prepared;
}

function wall_rank_related_articles(array $preparedItems, string $coreText, string $bodyText, string $dateKey = '', int $limit = 4): array
{
    $coreTokens = wall_tokenize($coreText);
    $bodyTokens = wall_tokenize($bodyText);
    $allTokens = array_values(array_unique(array_merge($coreTokens, $bodyTokens)));
    if (!$allTokens) {
        return [];
    }

    $coreSet = array_fill_keys($coreTokens, true);
    $allSet = array_fill_keys($allTokens, true);
    $ranked = [];

    foreach ($preparedItems as $article) {
        $score = 0;
        $matched = [];

        foreach (($article['_core_tokens'] ?? []) as $token) {
            if (!isset($allSet[$token])) {
                continue;
            }
            $score += isset($coreSet[$token]) ? 3 : 2;
            $matched[$token] = true;
        }

        foreach (($article['_body_tokens'] ?? []) as $token) {
            if (!isset($allSet[$token])) {
                continue;
            }
            $score += isset($coreSet[$token]) ? 2 : 1;
            $matched[$token] = true;
        }

        if ($dateKey !== '' && (string) ($article['_date_key'] ?? '') === $dateKey) {
            $score += 2;
        }

        if (!$matched || $score < 3) {
            continue;
        }

        $candidate = $article;
        $candidate['_match_score'] = $score;
        $candidate['_match_terms'] = array_slice(array_keys($matched), 0, 4);
        $ranked[] = $candidate;
    }

    usort($ranked, static function (array $left, array $right): int {
        $scoreDiff = (int) ($right['_match_score'] ?? 0) <=> (int) ($left['_match_score'] ?? 0);
        if ($scoreDiff !== 0) {
            return $scoreDiff;
        }
        $rightTime = (int) ($right['date_timestamp'] ?: $right['file_mtime'] ?: $right['index_number']);
        $leftTime = (int) ($left['date_timestamp'] ?: $left['file_mtime'] ?: $left['index_number']);
        return $rightTime <=> $leftTime;
    });

    return array_slice($ranked, 0, $limit);
}

function wall_chapter_core_text(array $chapter): string
{
    $parts = [(string) ($chapter['title'] ?? '')];
    foreach (($chapter['items'] ?? []) as $item) {
        $parts[] = (string) ($item['title'] ?? '');
    }
    return implode(' ', $parts);
}

function wall_chapter_body_text(array $chapter): string
{
    $parts = [(string) ($chapter['summary'] ?? '')];
    foreach (($chapter['items'] ?? []) as $item) {
        $parts[] = (string) ($item['summary'] ?? '');
        $parts[] = implode(' ', $item['badges'] ?? []);
        $parts[] = implode(' ', $item['files'] ?? []);
    }
    return implode(' ', $parts);
}

function wall_event_core_text(array $event): string
{
    return implode(' ', [
        (string) ($event['title'] ?? ''),
        implode(' ', $event['tags'] ?? []),
    ]);
}

function wall_event_body_text(array $event): string
{
    return implode(' ', [
        (string) ($event['summary'] ?? ''),
        (string) ($event['date_label'] ?? ''),
    ]);
}

function wall_evidence_core_text(array $evidence): string
{
    return implode(' ', [
        (string) ($evidence['title'] ?? ''),
        implode(' ', $evidence['tags'] ?? []),
    ]);
}

function wall_evidence_body_text(array $evidence): string
{
    return implode(' ', [
        (string) ($evidence['summary'] ?? ''),
        implode(' ', $evidence['files'] ?? []),
    ]);
}

function wall_collect_priority(array &$priorityArticles, array $article, string $reason, int $weight): void
{
    $key = (string) ($article['scope'] ?? '') . ':' . (string) (($article['slug'] ?? '') ?: ($article['index_number'] ?? '0'));
    if (!isset($priorityArticles[$key])) {
        $priorityArticles[$key] = $article + [
            '_priority_score' => 0,
            '_priority_reasons' => [],
        ];
    }

    $priorityArticles[$key]['_priority_score'] += $weight;
    if (!in_array($reason, $priorityArticles[$key]['_priority_reasons'], true)) {
        $priorityArticles[$key]['_priority_reasons'][] = $reason;
    }
}

$priorityCandidates = sg_priority_build_candidates($items, $dossier, 6, ['start', 'archiv'], [83, 90, 154, 155]);
?>
<!doctype html>
<html lang="de">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Ermittlerwand</title>
    <style>
        :root {
            color-scheme: dark;
            --bg: #0d1016;
            --panel: #151a23;
            --panel-2: #0f141d;
            --line: rgba(255,255,255,.08);
            --text: #eef3f8;
            --muted: #9aa7b8;
            --accent: #6ed0ff;
            --accent-2: #ffd166;
            --danger: #ff7272;
            --ok: #7bd88f;
        }
        * { box-sizing: border-box; }
        body {
            margin: 0;
            font-family: "Segoe UI Variable", "Segoe UI", sans-serif;
            background:
                radial-gradient(circle at top left, rgba(110,208,255,.12), transparent 30%),
                radial-gradient(circle at top right, rgba(255,209,102,.10), transparent 28%),
                linear-gradient(180deg, #121824, var(--bg));
            color: var(--text);
        }
        .shell { max-width: 1600px; margin: 0 auto; padding: 24px; display: grid; gap: 18px; }
        .hero, .card { border: 1px solid var(--line); border-radius: 22px; background: rgba(21,26,35,.92); box-shadow: 0 18px 60px rgba(0,0,0,.25); }
        .hero { padding: 24px; display: grid; gap: 14px; }
        .hero h1 { margin: 0; font-size: 34px; line-height: 1.05; }
        .hero p { margin: 0; color: var(--muted); max-width: 980px; line-height: 1.5; }
        .summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; }
        .stat { padding: 16px; border-radius: 18px; background: var(--panel-2); border: 1px solid var(--line); }
        .stat strong { display: block; font-size: 28px; margin-bottom: 6px; }
        .stat span { color: var(--muted); font-size: 13px; }
        .toolbar { display: flex; gap: 10px; flex-wrap: wrap; }
        .toolbar input, .toolbar select { background: var(--panel-2); border: 1px solid var(--line); color: var(--text); border-radius: 14px; padding: 10px 12px; }
        .grid { display: grid; grid-template-columns: 340px minmax(0, 1fr); gap: 18px; }
        .card { padding: 18px; }
        .card h2 { margin: 0 0 12px; font-size: 18px; }
        .issue-list, .meta-list, .link-list { display: grid; gap: 8px; }
        .issue-item, .meta-item, .link-item { padding: 10px 12px; border-radius: 14px; background: var(--panel-2); border: 1px solid var(--line); }
        .wall { display: grid; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); gap: 14px; }
        .article { display: grid; gap: 12px; padding: 16px; border-radius: 20px; background: var(--panel-2); border: 1px solid var(--line); }
        .article[hidden] { display: none !important; }
        .head { display: flex; justify-content: space-between; gap: 12px; align-items: flex-start; }
        .head h3 { margin: 0; font-size: 18px; line-height: 1.2; }
        .head p { margin: 6px 0 0; color: var(--muted); font-size: 13px; }
        .badges { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
        .badge { padding: 6px 10px; border-radius: 999px; font-size: 12px; border: 1px solid var(--line); }
        .badge.scope-start { background: rgba(110,208,255,.14); color: var(--accent); }
        .badge.scope-archiv { background: rgba(255,209,102,.14); color: var(--accent-2); }
        .badge.scope-dev { background: rgba(123,216,143,.14); color: var(--ok); }
        .badge.issue { background: rgba(255,114,114,.14); color: var(--danger); }
        .article dl { margin: 0; display: grid; grid-template-columns: minmax(110px, 140px) 1fr; gap: 8px 10px; font-size: 13px; }
        .article dt { color: var(--muted); }
        .article dd { margin: 0; }
        .article .excerpt { color: #d8e1ec; line-height: 1.5; font-size: 14px; }
        .chip-row { display: flex; flex-wrap: wrap; gap: 8px; }
        .chip { display: inline-flex; align-items: center; gap: 6px; padding: 6px 10px; border-radius: 999px; border: 1px solid var(--line); background: rgba(255,255,255,.03); color: var(--text); text-decoration: none; font-size: 12px; }
        .chip.missing { border-color: rgba(255,114,114,.4); color: var(--danger); }
        .muted { color: var(--muted); }
        .image-state { font-size: 12px; color: var(--muted); }
        .section-copy { color: var(--muted); line-height: 1.6; max-width: 1040px; margin: 0 0 16px; }
        .band-grid { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(320px, .85fr); gap: 18px; }
        .band-column, .band-list { display: grid; gap: 14px; }
        .band-card { display: grid; gap: 10px; padding: 16px; border-radius: 18px; background: var(--panel-2); border: 1px solid var(--line); }
        .band-kicker { font-size: 12px; letter-spacing: .08em; text-transform: uppercase; color: var(--accent); }
        .band-date { color: var(--accent-2); font-weight: 700; font-size: 13px; }
        .band-card h3, .band-card h4 { margin: 0; font-size: 17px; line-height: 1.25; }
        .band-actions { display: flex; flex-wrap: wrap; gap: 8px; }
        .band-actions a { text-decoration: none; }
        .source-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; margin-bottom: 16px; }
        .source-box { padding: 16px; border-radius: 18px; background: var(--panel-2); border: 1px solid var(--line); display: grid; gap: 8px; }
        .source-box strong { font-size: 18px; }
        .pin-section { display: grid; gap: 12px; }
        .pin-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 14px; }
        .pin-card { display: grid; gap: 10px; padding: 16px; border-radius: 18px; background: var(--panel-2); border: 1px solid var(--line); }
        .pin-preview, .pin-placeholder, .pin-card video { width: 100%; aspect-ratio: 16 / 10; border-radius: 14px; border: 1px solid var(--line); background: rgba(255,255,255,.03); }
        .pin-preview { object-fit: cover; display: block; }
        .pin-placeholder { display: grid; place-items: center; color: var(--accent-2); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; }
        .pin-card video { object-fit: cover; }
        .pin-card h3 { margin: 0; font-size: 16px; line-height: 1.3; }
        .pin-card p { margin: 0; color: var(--muted); line-height: 1.5; font-size: 13px; }
        @media (max-width: 1100px) { .grid { grid-template-columns: 1fr; } }
        @media (max-width: 1100px) { .band-grid { grid-template-columns: 1fr; } }
    </style>
</head>
<body>
<div class="shell">
    <section class="hero">
        <div>
            <h1>Ermittlerwand</h1>
            <p>Diese erste Backend-Ansicht zieht Startseite, Archiv und devseiten in eine gemeinsame Fallübersicht. Sie zeigt bestehende Verknüpfungen, eingehende Referenzen, erkennbare Metadaten und die Stellen, an denen Beiträge heute noch händisch nachgearbeitet werden müssen.</p>
        </div>
        <div class="summary">
            <div class="stat"><strong><?= count($items) ?></strong><span>Beiträge gesamt</span></div>
            <div class="stat"><strong><?= $scopeCounts['start'] ?></strong><span>Startseite</span></div>
            <div class="stat"><strong><?= $scopeCounts['archiv'] ?></strong><span>Archiv</span></div>
            <div class="stat"><strong><?= $scopeCounts['dev'] ?></strong><span>devseiten</span></div>
            <div class="stat"><strong><?= (int) ($timelineSource['question_count'] ?? 0) ?></strong><span>Ermittlungsfragen</span></div>
            <div class="stat"><strong><?= count($offenseGroups) ?></strong><span>Tatkomplexe / Verstöße</span></div>
        </div>
        <div class="toolbar">
            <input id="wallSearch" type="search" placeholder="Titel, Slug oder Index filtern">
            <select id="scopeFilter">
                <option value="all">Alle Bereiche</option>
                <option value="start">Nur Startseite</option>
                <option value="archiv">Nur Archiv</option>
                <option value="dev">Nur devseiten</option>
            </select>
            <select id="issueFilter">
                <option value="all">Alle Qualitätsstände</option>
                <option value="clean">Nur ohne offene Hinweise</option>
                <option value="issues">Nur mit offenen Hinweisen</option>
            </select>
        </div>
    </section>

    <section class="card">
        <h2>Außenbänder Aus Dem Dossier</h2>
        <p class="section-copy">Die zwei HTML-Dateien unter LotharAnklageschrift werden jetzt nicht mehr nur als Nebenwelt betrachtet, sondern als zweite strukturierte Quelle neben den Beiträgen. Die Timeline liefert harte chronologische Marker, Ermittlungsfragen und Schnelllogik. Das Hauptdossier liefert Kapitelstränge, Dokumente und die tabellarisch benannten Gesetzesverstöße.</p>
        <div class="source-grid">
            <div class="source-box">
                <strong><?= (int) ($timelineSource['event_count'] ?? 0) ?></strong>
                <span>Timeline-Ereignisse aus Neuhauß / Müller</span>
                <a class="chip" href="<?= h((string) ($timelineSource['web_path'] ?? '#')) ?>" target="_blank" rel="noopener noreferrer">Quelle öffnen</a>
            </div>
            <div class="source-box">
                <strong><?= (int) ($timelineSource['evidence_count'] ?? 0) ?></strong>
                <span>Schlüsselbeweise aus der Fokus-Timeline</span>
                <a class="chip" href="<?= h((string) ($timelineSource['web_path'] ?? '#')) ?>#schluesselbeweise" target="_blank" rel="noopener noreferrer">Beweise öffnen</a>
            </div>
            <div class="source-box">
                <strong><?= (int) ($overviewSource['chapter_count'] ?? 0) ?></strong>
                <span>Kapitel im Lothar-Kießler-Dossier</span>
                <a class="chip" href="<?= h((string) ($overviewSource['web_path'] ?? '#')) ?>" target="_blank" rel="noopener noreferrer">Dossier öffnen</a>
            </div>
            <div class="source-box">
                <strong><?= (int) ($overviewSource['item_count'] ?? 0) ?></strong>
                <span>Dokumentkarten aus dem Hauptdossier</span>
                <a class="chip" href="<?= h((string) ($overviewSource['web_path'] ?? '#')) ?>#kap0" target="_blank" rel="noopener noreferrer">Kapitelbeginn</a>
            </div>
            <div class="source-box">
                <strong><?= (int) ($timelineSource['question_count'] ?? 0) ?></strong>
                <span>Ermittlungsfragen aus Neuhauß / Müller</span>
                <a class="chip" href="<?= h((string) ($timelineSource['web_path'] ?? '#')) ?>#ermittlungsfragen" target="_blank" rel="noopener noreferrer">Fragen öffnen</a>
            </div>
            <div class="source-box">
                <strong><?= count($offenseGroups) ?></strong>
                <span>Benannte Tatkomplexe / Verstöße</span>
                <a class="chip" href="<?= h((string) ($overviewSource['web_path'] ?? '#')) ?>#nolegal1" target="_blank" rel="noopener noreferrer">Verstoßliste öffnen</a>
            </div>
        </div>

        <div class="band-grid">
            <div class="band-column">
                <div>
                    <h2>Chronologisches Band</h2>
                    <p class="section-copy">Jedes Timeline-Ereignis bekommt hier einen echten Datumsanker. Wo die Startseite oder das Archiv am selben Tag bereits einen Beitrag tragen, wird die Verbindung direkt angezeigt.</p>
                </div>
                <div class="band-list">
                    <?php foreach (($timelineSource['events'] ?? []) as $event): ?>
                        <?php
                        $dateKey = substr((string) ($event['date_normalized'] ?? ''), 0, 10);
                        $matchingArticles = $dateKey !== '' ? array_slice($articleDateIndex[$dateKey] ?? [], 0, 4) : [];
                        ?>
                        <article class="band-card">
                            <div class="band-date"><?= h((string) ($event['date_label'] ?? 'ohne Datum')) ?></div>
                            <h3><?= h((string) ($event['title'] ?? 'Ohne Titel')) ?></h3>
                            <div class="excerpt"><?= h((string) ($event['summary'] ?? '')) ?></div>
                            <?php if (!empty($event['tags'])): ?>
                                <div class="chip-row">
                                    <?php foreach (($event['tags'] ?? []) as $tag): ?>
                                        <span class="chip"><?= h((string) $tag) ?></span>
                                    <?php endforeach; ?>
                                </div>
                            <?php endif; ?>
                            <?php if ($matchingArticles): ?>
                                <div>
                                    <strong>Beiträge Am Selben Tag</strong>
                                    <div class="chip-row" style="margin-top:8px;">
                                        <?php foreach ($matchingArticles as $article): ?>
                                            <a class="chip" href="<?= h(article_public_href($article)) ?>" target="_blank" rel="noopener noreferrer">#<?= (int) ($article['index_number'] ?? 0) ?> · <?= h((string) ($article['title'] ?? '')) ?></a>
                                        <?php endforeach; ?>
                                    </div>
                                </div>
                            <?php endif; ?>
                            <?php if (!empty($event['related_articles'])): ?>
                                <div>
                                    <strong>Passende Beiträge Im Thema</strong>
                                    <div class="chip-row" style="margin-top:8px;">
                                        <?php foreach (($event['related_articles'] ?? []) as $article): ?>
                                            <a class="chip" href="<?= h(article_public_href($article)) ?>" target="_blank" rel="noopener noreferrer">#<?= (int) ($article['index_number'] ?? 0) ?> · <?= h((string) ($article['title'] ?? '')) ?></a>
                                        <?php endforeach; ?>
                                    </div>
                                </div>
                            <?php endif; ?>
                            <?php if (!empty($event['links'])): ?>
                                <div class="band-actions">
                                    <?php foreach (array_slice($event['links'], 0, 2) as $link): ?>
                                        <a class="chip" href="<?= h((string) ($link['href'] ?? '#')) ?>" target="_blank" rel="noopener noreferrer"><?= h((string) ($link['label'] ?? 'Beleg öffnen')) ?></a>
                                    <?php endforeach; ?>
                                </div>
                            <?php endif; ?>
                        </article>
                    <?php endforeach; ?>
                </div>
            </div>

            <div class="band-column">
                <div>
                    <h2>Kapitelstränge</h2>
                    <p class="section-copy">Das Hauptdossier beschreibt nicht nur einzelne Dateien, sondern bereits die großen Stränge: Ursprung, Urkundenfälschung, Sucht, Paket-Gate, Landgericht, Vertuschung. Diese Kapitel sind die Außenbänder, die später sauber mit Artikeln, Belegen und Ermittlungsfragen vernäht werden können.</p>
                </div>
                <div class="band-list">
                    <?php foreach (($overviewSource['chapters'] ?? []) as $chapter): ?>
                        <article class="band-card">
                            <div class="band-kicker">Kapitelband</div>
                            <h4><?= h((string) ($chapter['title'] ?? 'Ohne Kapitelname')) ?></h4>
                            <div class="excerpt"><?= h((string) ($chapter['summary'] ?? '')) ?></div>
                            <div class="chip-row">
                                <span class="chip"><?= (int) ($chapter['item_count'] ?? 0) ?> Dokumentkarten</span>
                                <?php foreach (array_slice(($chapter['items'] ?? []), 0, 2) as $chapterItem): ?>
                                    <span class="chip"><?= h((string) ($chapterItem['title'] ?? '')) ?></span>
                                <?php endforeach; ?>
                            </div>
                            <?php if (!empty($chapter['related_articles'])): ?>
                                <div>
                                    <strong>Passende Beiträge</strong>
                                    <div class="chip-row" style="margin-top:8px;">
                                        <?php foreach (($chapter['related_articles'] ?? []) as $article): ?>
                                            <a class="chip" href="<?= h(article_public_href($article)) ?>" target="_blank" rel="noopener noreferrer">#<?= (int) ($article['index_number'] ?? 0) ?> · <?= h((string) ($article['title'] ?? '')) ?></a>
                                        <?php endforeach; ?>
                                    </div>
                                </div>
                            <?php endif; ?>
                            <div class="band-actions">
                                <a class="chip" href="<?= h((string) ($chapter['href'] ?? '#')) ?>" target="_blank" rel="noopener noreferrer">Kapitel öffnen</a>
                                <?php foreach (array_slice(($chapter['items'] ?? []), 0, 2) as $chapterItem): ?>
                                    <?php foreach (array_slice(($chapterItem['links'] ?? []), 0, 1) as $link): ?>
                                        <a class="chip" href="<?= h((string) ($link['href'] ?? '#')) ?>" target="_blank" rel="noopener noreferrer"><?= h((string) ($link['label'] ?? 'Beleg öffnen')) ?></a>
                                    <?php endforeach; ?>
                                <?php endforeach; ?>
                            </div>
                        </article>
                    <?php endforeach; ?>
                </div>

                <div>
                    <h2>Schlüsselbeweise</h2>
                    <p class="section-copy">Diese Karten sind die harte Kurzfassung fuer spätere Ermittler-Pfade: schnell lesbar, direkt belegbar, ohne dass man erst das gesamte Tagebuch durchsuchen muss.</p>
                </div>
                <div class="band-list">
                    <?php foreach (array_slice(($timelineSource['evidence'] ?? []), 0, 8) as $evidence): ?>
                        <article class="band-card">
                            <div class="band-kicker">Belegkarte</div>
                            <h4><?= h((string) ($evidence['title'] ?? 'Ohne Titel')) ?></h4>
                            <div class="excerpt"><?= h((string) ($evidence['summary'] ?? '')) ?></div>
                            <?php if (!empty($evidence['tags'])): ?>
                                <div class="chip-row">
                                    <?php foreach (($evidence['tags'] ?? []) as $tag): ?>
                                        <span class="chip"><?= h((string) $tag) ?></span>
                                    <?php endforeach; ?>
                                </div>
                            <?php endif; ?>
                            <?php if (!empty($evidence['links'])): ?>
                                <div class="band-actions">
                                    <?php foreach (array_slice($evidence['links'], 0, 3) as $link): ?>
                                        <a class="chip" href="<?= h((string) ($link['href'] ?? '#')) ?>" target="_blank" rel="noopener noreferrer"><?= h((string) ($link['label'] ?? 'Beleg öffnen')) ?></a>
                                    <?php endforeach; ?>
                                </div>
                            <?php endif; ?>
                            <?php if (!empty($evidence['related_articles'])): ?>
                                <div>
                                    <strong>Passende Beiträge</strong>
                                    <div class="chip-row" style="margin-top:8px;">
                                        <?php foreach (($evidence['related_articles'] ?? []) as $article): ?>
                                            <a class="chip" href="<?= h(article_public_href($article)) ?>" target="_blank" rel="noopener noreferrer">#<?= (int) ($article['index_number'] ?? 0) ?> · <?= h((string) ($article['title'] ?? '')) ?></a>
                                        <?php endforeach; ?>
                                    </div>
                                </div>
                            <?php endif; ?>
                        </article>
                    <?php endforeach; ?>
                </div>
            </div>
        </div>
    </section>

    <section class="card">
        <h2>Ermittlungsfragen Und Tatkomplexe</h2>
        <p class="section-copy">Hier wird die argumentative Schärfe aus beiden HTML-Quellen sichtbar: Die Neuhauß/Müller-Seite liefert die Ermittlungsfragen und Schnelllogik, das Hauptdossier liefert die benannten Gesetzesverstöße. Beides wird direkt mit passenden Beiträgen vernäht, damit aus emotionalem Tagebuchstoff nachvollziehbare Ermittlungsachsen werden.</p>
        <div class="band-grid">
            <div class="band-column">
                <div>
                    <h2>Ermittlungsfragen</h2>
                    <p class="section-copy">Diese Fragen kommen direkt aus dem A-Z-Beweisdossier. Sie zwingen die Sache auf den Kern zurück: Was musste ein Ermittler nach kurzer Zeit verstanden haben?</p>
                </div>
                <div class="band-list">
                    <?php foreach ($investigationQuestions as $question): ?>
                        <article class="band-card" id="<?= h(sg_priority_question_anchor($question)) ?>">
                            <div class="band-kicker">Ermittlungsfrage</div>
                            <h4><?= h((string) ($question['title'] ?? 'Ohne Frage')) ?></h4>
                            <div class="excerpt"><?= h((string) ($question['summary'] ?? '')) ?></div>
                            <?php if (!empty($question['related_articles'])): ?>
                                <div>
                                    <strong>Passende Beiträge</strong>
                                    <div class="chip-row" style="margin-top:8px;">
                                        <?php foreach (($question['related_articles'] ?? []) as $article): ?>
                                            <a class="chip" href="<?= h(article_public_href($article)) ?>" target="_blank" rel="noopener noreferrer">#<?= (int) ($article['index_number'] ?? 0) ?> · <?= h((string) ($article['title'] ?? '')) ?></a>
                                        <?php endforeach; ?>
                                    </div>
                                </div>
                            <?php endif; ?>
                            <div class="band-actions">
                                <a class="chip" href="<?= h(path_href((string) ($question['href'] ?? '#'))) ?>" target="_blank" rel="noopener noreferrer">Fragenquelle öffnen</a>
                            </div>
                        </article>
                    <?php endforeach; ?>
                </div>

                <?php if ($logicClusters): ?>
                    <div>
                        <h2>Schnelllogik</h2>
                        <p class="section-copy">Die Alphabet-Wand zerlegt das Material in wenige Cluster, damit sofort sichtbar wird, welche Verdachtsachsen zusammengehören.</p>
                    </div>
                    <div class="band-list">
                        <?php foreach ($logicClusters as $cluster): ?>
                            <article class="band-card">
                                <div class="band-kicker">Cluster</div>
                                <h4><?= h((string) ($cluster['title'] ?? 'Ohne Cluster')) ?></h4>
                                <div class="excerpt"><?= h((string) ($cluster['summary'] ?? '')) ?></div>
                                <?php if (!empty($cluster['related_articles'])): ?>
                                    <div>
                                        <strong>Passende Beiträge</strong>
                                        <div class="chip-row" style="margin-top:8px;">
                                            <?php foreach (($cluster['related_articles'] ?? []) as $article): ?>
                                                <a class="chip" href="<?= h(article_public_href($article)) ?>" target="_blank" rel="noopener noreferrer">#<?= (int) ($article['index_number'] ?? 0) ?> · <?= h((string) ($article['title'] ?? '')) ?></a>
                                            <?php endforeach; ?>
                                        </div>
                                    </div>
                                <?php endif; ?>
                                <div class="band-actions">
                                    <a class="chip" href="<?= h(path_href((string) ($cluster['href'] ?? '#'))) ?>" target="_blank" rel="noopener noreferrer">Clusterquelle öffnen</a>
                                </div>
                            </article>
                        <?php endforeach; ?>
                    </div>
                <?php endif; ?>
            </div>

            <div class="band-column">
                <div>
                    <h2>Tatkomplexe / Gesetzesverstöße</h2>
                    <p class="section-copy">Dieser Block kommt aus der tabellarischen Verstoßliste des Hauptdossiers. Gleiche Vorwurfslinien werden hier gebündelt und direkt mit Aktenbelegen sowie passenden Beiträgen verbunden.</p>
                </div>
                <div class="band-list">
                    <?php foreach ($offenseGroups as $offense): ?>
                        <article class="band-card" id="<?= h(sg_priority_offense_anchor($offense)) ?>">
                            <div class="band-kicker">Tatkomplex</div>
                            <h4><?= h((string) ($offense['title'] ?? 'Ohne Vorwurf')) ?></h4>
                            <div class="chip-row">
                                <span class="chip"><?= count($offense['rows'] ?? []) ?> Belegspur<?= count($offense['rows'] ?? []) === 1 ? '' : 'en' ?></span>
                                <?php if (!empty($offense['links'])): ?>
                                    <span class="chip"><?= count($offense['links'] ?? []) ?> Aktenlink<?= count($offense['links'] ?? []) === 1 ? '' : 's' ?></span>
                                <?php endif; ?>
                            </div>
                            <?php if (!empty($offense['related_articles'])): ?>
                                <div>
                                    <strong>Passende Beiträge</strong>
                                    <div class="chip-row" style="margin-top:8px;">
                                        <?php foreach (array_slice(($offense['related_articles'] ?? []), 0, 4) as $article): ?>
                                            <a class="chip" href="<?= h(article_public_href($article)) ?>" target="_blank" rel="noopener noreferrer">#<?= (int) ($article['index_number'] ?? 0) ?> · <?= h((string) ($article['title'] ?? '')) ?></a>
                                        <?php endforeach; ?>
                                    </div>
                                </div>
                            <?php endif; ?>
                            <?php if (!empty($offense['links'])): ?>
                                <div>
                                    <strong>Aktenbelege</strong>
                                    <div class="chip-row" style="margin-top:8px;">
                                        <?php foreach (array_slice(($offense['links'] ?? []), 0, 4) as $link): ?>
                                            <a class="chip" href="<?= h(path_href(sg_priority_preferred_href((string) ($link['href'] ?? '#')))) ?>" target="_blank" rel="noopener noreferrer"><?= h(wall_link_label($link)) ?></a>
                                        <?php endforeach; ?>
                                    </div>
                                </div>
                            <?php endif; ?>
                            <div class="band-actions">
                                <a class="chip" href="<?= h(path_href((string) ($offense['href'] ?? '#'))) ?>" target="_blank" rel="noopener noreferrer">Verstoßliste öffnen</a>
                            </div>
                        </article>
                    <?php endforeach; ?>
                </div>
            </div>
        </div>
    </section>

    <section class="card">
        <h2>Belegpins</h2>
        <p class="section-copy">Die Dossier-Ordner sind jetzt als eigene Belegoberfläche sichtbar. Bildspuren bekommen echte Vorschaubilder, PDF-Stränge werden als Dokumentanker gebündelt und die Vorlese-Datei hängt direkt mit in der Wand.</p>
        <div class="source-grid">
            <div class="source-box">
                <strong><?= (int) (($assetSource['images']['count'] ?? 0)) ?></strong>
                <span>Bildbelege im Dossier</span>
                <div class="chip-row">
                    <?php foreach (array_slice(($assetSource['images']['groups'] ?? []), 0, 3) as $group): ?>
                        <span class="chip"><?= h((string) ($group['label'] ?? '')) ?> · <?= (int) ($group['count'] ?? 0) ?></span>
                    <?php endforeach; ?>
                </div>
            </div>
            <div class="source-box">
                <strong><?= (int) (($assetSource['pdfs']['count'] ?? 0)) ?></strong>
                <span>PDF-Belege im Dossier</span>
                <div class="chip-row">
                    <?php foreach (array_slice(($assetSource['pdfs']['groups'] ?? []), 0, 3) as $group): ?>
                        <span class="chip"><?= h((string) ($group['label'] ?? '')) ?> · <?= (int) ($group['count'] ?? 0) ?></span>
                    <?php endforeach; ?>
                </div>
            </div>
            <div class="source-box">
                <strong><?= (int) (($assetSource['videos']['count'] ?? 0)) ?></strong>
                <span>Vorlese- und Videobelege</span>
                <div class="chip-row">
                    <?php foreach (array_slice(($assetSource['videos']['groups'] ?? []), 0, 3) as $group): ?>
                        <span class="chip"><?= h((string) ($group['label'] ?? '')) ?> · <?= (int) ($group['count'] ?? 0) ?></span>
                    <?php endforeach; ?>
                </div>
            </div>
        </div>

        <div class="band-grid">
            <div class="pin-section">
                <div>
                    <h2>Bildspuren</h2>
                    <p class="section-copy">Hier landen zuerst die visuell stärksten Belege aus dem Bilddossier, nicht bloß die ersten Dateinamen.</p>
                </div>
                <div class="pin-grid">
                    <?php foreach (($assetSource['images']['samples'] ?? []) as $asset): ?>
                        <article class="pin-card">
                            <a href="<?= h(path_href((string) ($asset['href'] ?? '#'))) ?>" target="_blank" rel="noopener noreferrer">
                                <img class="pin-preview" src="<?= h(path_href((string) ($asset['href'] ?? ''))) ?>" alt="<?= h((string) ($asset['label'] ?? 'Bildbeleg')) ?>">
                            </a>
                            <h3><?= h((string) ($asset['label'] ?? 'Bildbeleg')) ?></h3>
                            <p><?= h((string) ($asset['group'] ?? 'Bilddateien')) ?></p>
                            <div class="band-actions">
                                <a class="chip" href="<?= h(path_href((string) ($asset['href'] ?? '#'))) ?>" target="_blank" rel="noopener noreferrer">Bild öffnen</a>
                            </div>
                        </article>
                    <?php endforeach; ?>
                </div>
            </div>

            <div class="pin-section">
                <div>
                    <h2>Dokumentanker</h2>
                    <p class="section-copy">Die wichtigsten PDF-Stränge werden als direkte Belegkarten sichtbar, damit man schneller vom Kapitel in die Unterlagen springen kann.</p>
                </div>
                <div class="pin-grid">
                    <?php foreach (($assetSource['pdfs']['samples'] ?? []) as $asset): ?>
                        <article class="pin-card">
                            <div class="pin-placeholder">PDF</div>
                            <h3><?= h((string) ($asset['label'] ?? 'Dokument')) ?></h3>
                            <p><?= h((string) ($asset['group'] ?? 'pdf')) ?></p>
                            <div class="band-actions">
                                <a class="chip" href="<?= h(path_href((string) ($asset['href'] ?? '#'))) ?>" target="_blank" rel="noopener noreferrer">PDF öffnen</a>
                            </div>
                        </article>
                    <?php endforeach; ?>
                </div>

                <div>
                    <h2>Video-Beweise</h2>
                    <p class="section-copy">Vorlese- und Video-Dateien bleiben direkt an der Wand, damit das Material nicht wieder in einer Nebenstruktur verschwindet.</p>
                </div>
                <div class="pin-grid">
                    <?php foreach (($assetSource['videos']['samples'] ?? []) as $asset): ?>
                        <article class="pin-card">
                            <video controls preload="metadata" src="<?= h(path_href((string) ($asset['href'] ?? ''))) ?>"></video>
                            <h3><?= h((string) ($asset['label'] ?? 'Videobeleg')) ?></h3>
                            <p><?= h((string) ($asset['group'] ?? 'videoBeweisschrift')) ?></p>
                            <div class="band-actions">
                                <a class="chip" href="<?= h(path_href((string) ($asset['href'] ?? '#'))) ?>" target="_blank" rel="noopener noreferrer">Video öffnen</a>
                            </div>
                        </article>
                    <?php endforeach; ?>
                </div>
            </div>
        </div>
    </section>

    <section class="card">
        <h2>Leitbeitrags-Kandidaten</h2>
        <p class="section-copy">Hier stehen jetzt exakt dieselben öffentlichen Leitkarten wie auf der Startseite. Oben kommt der emotionale Einstieg, hier darunter derselbe Stoff als sauberer Faktenpfad mit Begründungen und Rücksprung zur öffentlichen Karte.</p>
        <div class="wall">
            <?php foreach ($priorityCandidates as $candidate): ?>
                <article class="article" id="<?= h(sg_priority_wall_anchor($candidate)) ?>">
                    <div class="head">
                        <div>
                            <h3><?= h((string) ($candidate['title'] ?: 'Ohne Titel')) ?></h3>
                            <p>#<?= (int) ($candidate['index_number'] ?? 0) ?> · <?= h((string) ($candidate['date_normalized'] ?: $candidate['date_line'] ?: 'ohne sicheres Datum')) ?></p>
                        </div>
                        <div class="badges">
                            <span class="badge scope-<?= h((string) ($candidate['scope'] ?? '')) ?>"><?= h(scope_label((string) ($candidate['scope'] ?? ''))) ?></span>
                            <span class="badge"><?= (int) ($candidate['_priority_score'] ?? 0) ?> Punkte</span>
                        </div>
                    </div>
                    <div class="excerpt"><?= h((string) ($candidate['excerpt'] ?: $candidate['headline2'] ?: 'Kein kurzer Teaser vorhanden.')) ?></div>
                    <div>
                        <strong>Warum Vorne?</strong>
                        <div class="chip-row" style="margin-top:8px;">
                            <?php foreach (array_slice(($candidate['_priority_reasons'] ?? []), 0, 4) as $reason): ?>
                                <span class="chip"><?= h((string) $reason) ?></span>
                            <?php endforeach; ?>
                        </div>
                    </div>
                    <div class="band-actions">
                        <a class="chip" href="<?= h(article_public_href($candidate)) ?>" target="_blank" rel="noopener noreferrer">Beitrag öffnen</a>
                        <?php if (in_array((string) ($candidate['scope'] ?? ''), ['start', 'archiv'], true)): ?>
                            <a class="chip" href="<?= h(sg_priority_public_focus_href($candidate)) ?>" target="_blank" rel="noopener noreferrer">Öffentliche Leitkarte</a>
                        <?php endif; ?>
                    </div>
                </article>
            <?php endforeach; ?>
        </div>
    </section>

    <div class="grid">
        <aside class="card">
            <h2>Offene Hinweise</h2>
            <div class="issue-list">
                <?php foreach ($issueCounts as $label => $count): ?>
                    <div class="issue-item"><strong><?= h((string) $count) ?></strong> <span class="muted"><?= h((string) $label) ?></span></div>
                <?php endforeach; ?>
            </div>
            <h2 style="margin-top:18px;">Lesart der Zeitachse</h2>
            <div class="meta-list">
                <div class="meta-item">Zuerst wird versucht, das im Beitrag geschriebene Datum aus der datespan zu lesen.</div>
                <div class="meta-item">Wenn dort nichts Brauchbares steht, fällt die Wand auf die Dateizeit zurück.</div>
                <div class="meta-item">Die Linux-Datei selbst liefert in der Regel keine echte Erstellungszeit. Deshalb bleibt die Index-Nummer zusätzlich als chronologischer Notanker wichtig.</div>
            </div>
        </aside>

        <section class="card">
            <h2>Verknüpfte Beiträge</h2>
            <div class="wall" id="wall">
                <?php foreach ($items as $item): ?>
                    <?php
                    $incoming = $incomingMap[(int) ($item['index_number'] ?? 0)] ?? [];
                    $related = sg_catalog_related($catalog, $item, 24);
                    $issues = $item['issues'] ?? [];
                    $scope = (string) ($item['scope'] ?? '');
                    $searchBlob = implode(' ', [
                        (string) ($item['title'] ?? ''),
                        (string) ($item['slug'] ?? ''),
                        (string) ($item['headline2'] ?? ''),
                        (string) ($item['index_number'] ?? ''),
                    ]);
                    ?>
                    <article
                        class="article"
                        data-scope="<?= h($scope) ?>"
                        data-issues="<?= $issues ? '1' : '0' ?>"
                        data-search="<?= h(lower_text($searchBlob)) ?>"
                    >
                        <div class="head">
                            <div>
                                <h3><?= h((string) ($item['title'] ?: 'Ohne Titel')) ?></h3>
                                <p>#<?= (int) ($item['index_number'] ?? 0) ?> · <?= h((string) ($item['slug'] ?? '')) ?></p>
                            </div>
                            <div class="badges">
                                <span class="badge scope-<?= h($scope) ?>"><?= h(scope_label($scope)) ?></span>
                                <?php if ($issues): ?><span class="badge issue"><?= count($issues) ?> Hinweise</span><?php endif; ?>
                            </div>
                        </div>

                        <div class="excerpt"><?= h((string) ($item['excerpt'] ?: 'Kein zusammenhängender Teaser auslesbar.')) ?></div>

                        <dl>
                            <dt>Datum im Beitrag</dt>
                            <dd><?= h((string) ($item['date_line'] ?: 'nicht im Text gefunden')) ?></dd>
                            <dt>Normalisiert</dt>
                            <dd><?= h((string) ($item['date_normalized'] ?: 'keine sichere Datumsableitung')) ?></dd>
                            <dt>Datei geändert</dt>
                            <dd><?= !empty($item['file_mtime']) ? h(date('Y-m-d H:i:s', (int) $item['file_mtime'])) : 'unbekannt' ?></dd>
                            <dt>Zweite Überschrift</dt>
                            <dd><?= h((string) ($item['headline2'] ?: 'fehlt')) ?></dd>
                            <dt>Bild / Medien</dt>
                            <dd class="image-state">
                                <?= $item['image_src'] ? 'Bild vorhanden' : 'kein Bild' ?> ·
                                <?= $item['video_url'] ? 'Vorlese-Video' : 'kein Vorlese-Video' ?> ·
                                <?= $item['video_beitrag_url'] ? 'Beitragsvideo' : 'kein Beitragsvideo' ?>
                            </dd>
                        </dl>

                        <div>
                            <strong>Ausgehende Verknüpfungen</strong>
                            <div class="chip-row" style="margin-top:8px;">
                                <?php if (!$related): ?>
                                    <span class="muted">Noch keine verknüpften Beiträge.</span>
                                <?php else: ?>
                                    <?php foreach ($related as $target): ?>
                                        <?php if (!empty($target['missing'])): ?>
                                            <span class="chip missing">#<?= (int) ($target['index_number'] ?? 0) ?> fehlt</span>
                                        <?php else: ?>
                                            <span class="chip">#<?= (int) ($target['index_number'] ?? 0) ?> · <?= h((string) ($target['title'] ?? '')) ?> <small class="muted">(<?= h(scope_label((string) ($target['scope'] ?? ''))) ?>)</small></span>
                                        <?php endif; ?>
                                    <?php endforeach; ?>
                                <?php endif; ?>
                            </div>
                        </div>

                        <div>
                            <strong>Eingehende Verknüpfungen</strong>
                            <div class="chip-row" style="margin-top:8px;">
                                <?php if (!$incoming): ?>
                                    <span class="muted">Noch keine anderen Beiträge verweisen hierhin.</span>
                                <?php else: ?>
                                    <?php foreach ($incoming as $source): ?>
                                        <span class="chip">#<?= (int) ($source['index_number'] ?? 0) ?> · <?= h((string) ($source['title'] ?? '')) ?> <small class="muted">(<?= h(scope_label((string) ($source['scope'] ?? ''))) ?>)</small></span>
                                    <?php endforeach; ?>
                                <?php endif; ?>
                            </div>
                        </div>

                        <?php if ($issues): ?>
                            <div>
                                <strong>Offene Baustellen</strong>
                                <div class="chip-row" style="margin-top:8px;">
                                    <?php foreach ($issues as $issue): ?>
                                        <span class="chip missing"><?= h((string) $issue) ?></span>
                                    <?php endforeach; ?>
                                </div>
                            </div>
                        <?php endif; ?>

                        <div class="muted">Datei: <?= h((string) ($item['file_name'] ?? '')) ?></div>
                    </article>
                <?php endforeach; ?>
            </div>
        </section>
    </div>
</div>

<script>
const wallSearch = document.getElementById('wallSearch');
const scopeFilter = document.getElementById('scopeFilter');
const issueFilter = document.getElementById('issueFilter');
const cards = Array.from(document.querySelectorAll('.article'));

function applyFilters() {
    const query = String(wallSearch.value || '').trim().toLowerCase();
    const scope = String(scopeFilter.value || 'all');
    const issueMode = String(issueFilter.value || 'all');

    cards.forEach((card) => {
        const matchesQuery = !query || String(card.dataset.search || '').includes(query);
        const matchesScope = scope === 'all' || String(card.dataset.scope || '') === scope;
        const hasIssues = String(card.dataset.issues || '0') === '1';
        const matchesIssueMode = issueMode === 'all' || (issueMode === 'issues' ? hasIssues : !hasIssues);
        card.hidden = !(matchesQuery && matchesScope && matchesIssueMode);
    });
}

wallSearch.addEventListener('input', applyFilters);
scopeFilter.addEventListener('change', applyFilters);
issueFilter.addEventListener('change', applyFilters);
</script>
</body>
</html>