From 33b73087cf3599cdc27ee63a4a64371bd4cd7e7a Mon Sep 17 00:00:00 2001 From: fs Date: Fri, 16 Oct 2026 22:50:26 +0200 Subject: [PATCH] Stadionzeitung Untersteinach vorbereiten und Instagram aktualisieren --- CLAUDE.md | 15 +- app/components/stadionzeitung-rueckblick.php | 41 ++ app/components/stadionzeitung-seite.php | 3 + bin/preflight.php | 15 + bin/stadionzeitung-add.php | 13 + data/instagram.json | 38 +- data/stadionzeitung.json | 613 +++++++++++++++++- public/assets/css/components.css | 38 ++ public/assets/img/instagram/DeG8wTzjAVR.jpg | Bin 0 -> 195272 bytes public/assets/img/instagram/DePJUbkjKPc.jpg | Bin 0 -> 66264 bytes public/assets/img/instagram/DeeldfjMZEm.jpg | Bin 0 -> 117756 bytes public/assets/img/instagram/DehQgDrDB0Z.jpg | Bin 0 -> 66733 bytes .../galerie-01-1200.jpg | Bin 0 -> 291980 bytes .../galerie-01-640.jpg | Bin 0 -> 83278 bytes .../galerie-02-1200.jpg | Bin 0 -> 200234 bytes .../galerie-02-640.jpg | Bin 0 -> 70839 bytes .../galerie-03-1200.jpg | Bin 0 -> 198575 bytes .../galerie-03-640.jpg | Bin 0 -> 65857 bytes .../galerie-04-1200.jpg | Bin 0 -> 194091 bytes .../galerie-04-640.jpg | Bin 0 -> 63340 bytes .../galerie-05-1200.jpg | Bin 0 -> 225446 bytes .../galerie-05-640.jpg | Bin 0 -> 76686 bytes .../qr.png | Bin 0 -> 588 bytes .../rueckblick-480.jpg | Bin 0 -> 26278 bytes .../rueckblick-560.jpg | Bin 0 -> 38228 bytes .../rueckseite-1410.jpg | Bin 0 -> 407164 bytes .../rueckseite-480.jpg | Bin 0 -> 80454 bytes .../rueckseite-960.jpg | Bin 0 -> 227425 bytes .../spieler-1000.png | Bin 0 -> 1971598 bytes .../spieler-320.png | Bin 0 -> 229284 bytes .../spieler-640.png | Bin 0 -> 823095 bytes .../verfasser-120.jpg | Bin 0 -> 3111 bytes .../verfasser-222.jpg | Bin 0 -> 6896 bytes 33 files changed, 773 insertions(+), 3 deletions(-) create mode 100644 app/components/stadionzeitung-rueckblick.php create mode 100644 public/assets/img/instagram/DeG8wTzjAVR.jpg create mode 100644 public/assets/img/instagram/DePJUbkjKPc.jpg create mode 100644 public/assets/img/instagram/DeeldfjMZEm.jpg create mode 100644 public/assets/img/instagram/DehQgDrDB0Z.jpg create mode 100644 public/assets/img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/galerie-01-1200.jpg create mode 100644 public/assets/img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/galerie-01-640.jpg create mode 100644 public/assets/img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/galerie-02-1200.jpg create mode 100644 public/assets/img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/galerie-02-640.jpg create mode 100644 public/assets/img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/galerie-03-1200.jpg create mode 100644 public/assets/img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/galerie-03-640.jpg create mode 100644 public/assets/img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/galerie-04-1200.jpg create mode 100644 public/assets/img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/galerie-04-640.jpg create mode 100644 public/assets/img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/galerie-05-1200.jpg create mode 100644 public/assets/img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/galerie-05-640.jpg create mode 100644 public/assets/img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/qr.png create mode 100644 public/assets/img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/rueckblick-480.jpg create mode 100644 public/assets/img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/rueckblick-560.jpg create mode 100644 public/assets/img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/rueckseite-1410.jpg create mode 100644 public/assets/img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/rueckseite-480.jpg create mode 100644 public/assets/img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/rueckseite-960.jpg create mode 100644 public/assets/img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/spieler-1000.png create mode 100644 public/assets/img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/spieler-320.png create mode 100644 public/assets/img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/spieler-640.png create mode 100644 public/assets/img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/verfasser-120.jpg create mode 100644 public/assets/img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/verfasser-222.jpg diff --git a/CLAUDE.md b/CLAUDE.md index 215b814..1141e1f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -54,7 +54,7 @@ selbst gehosteter Stack ohne Abhängigkeiten von Drittanbietern. | Partner/Sponsoren | `data/partners.json` | — | | Instagram-Beiträge | `data/instagram.json` + `public/assets/img/instagram/` | Aufgenommen ausschließlich mit **`php bin/instagram-add.php `** (holt Bild, Text und Datum) — Einträge nie von Hand tippen, Bilder nie von Hand skalieren. **Kein Cron**, chat-gepflegt wie `events.json`. Eintrag und Bild müssen immer zusammen existieren, `bin/preflight.php` prüft beide Richtungen | | Matchcenter (Spiele/Ergebnisse/Tabellen) | `data/matchcenter.json` + `public/assets/img/crests/` | **maschinenverwaltet von `bin/matchcenter-sync.php` — nie von Hand editieren**. Team-/Wettbewerbs-IDs in `config.php` (`matchcenter.teams`) | -| Stadionzeitung (Ausgaben-Archiv) | `data/stadionzeitung.json` + `public/assets/img/stadionzeitung/` | **maschinenverwaltet von `bin/stadionzeitung-add.php` + `bin/stadionzeitung-publish.php` (Status/Snapshot) — nie von Hand editieren; einzige Chat-Pflege-Ausnahmen sind `vorwort`, `interview`, `aufruf`, `veranstaltung` (Slug-Verweis auf `veranstaltungen.json`), `cover` (`teaser` einer Sonderausgabe), `opponent_short` (gedruckter Anzeigename des Gegners) und `gegner_teams` (weitere Mannschaften mit Gegnerseite).** Der Ausgaben-Ordner wird bei jedem Lauf komplett geleert und neu gefüllt | +| Stadionzeitung (Ausgaben-Archiv) | `data/stadionzeitung.json` + `public/assets/img/stadionzeitung/` | **maschinenverwaltet von `bin/stadionzeitung-add.php` + `bin/stadionzeitung-publish.php` (Status/Snapshot) — nie von Hand editieren; einzige Chat-Pflege-Ausnahmen sind `vorwort`, `interview`, `aufruf`, `rueckblick` (Text/Bildnachweis; `image` bleibt script-verwaltet), `veranstaltung` (Slug-Verweis auf `veranstaltungen.json`), `cover` (`teaser` einer Sonderausgabe), `opponent_short` (gedruckter Anzeigename des Gegners) und `gegner_teams` (weitere Mannschaften mit Gegnerseite).** Der Ausgaben-Ordner wird bei jedem Lauf komplett geleert und neu gefüllt | | Sponsoren-Anzeigen (Stadionzeitung) | `data/anzeigen.json` + `public/assets/img/anzeigen/` | Dauerhafter Bestand, **nicht** pro Ausgabe: Motive ändern sich selten, das Heft erscheint oft. `sponsor`, `alt` (optional), `aktiv`, `bis` (optional, Enddatum gegen das Ausgabedatum), `platzierung` (optional, fester Platz auf einer Live-Seite statt im Streu-Pool) und die **Reihenfolge** (= Reihenfolge im Heft) im Chat gepflegt; `base`/`widths` schreibt ausschließlich `bin/anzeige-add.php`. Anzeigen nie in den Ausgaben-Ordner legen | | Termine/Events (`/termine`) | `data/events.json` (Vereins-Termine **ohne** eigene Detailseite) — Spieltermine kommen weiterhin nur aus `data/matchcenter.json`, Feste mit eigener Seite nur aus `data/veranstaltungen.json`; die Termine-Seite mergt alle drei | Von Claude im Chat gepflegt wie `teams.json`/`partners.json` — **keine** Automatisierung, kein Bin-Skript. Spieltermine nie hier duplizieren. Ein Fest, das eine Detailseite hat, steht **nur** in `veranstaltungen.json` (`bin/preflight.php` prüft das) | | Veranstaltungen (`/veranstaltungen` + Detailseiten) | `data/veranstaltungen.json` + `public/assets/img/veranstaltungen/` | Termin, Texte, Programm, Turnierpläne (`turniere[]`, nur fürs Heft), Abschnitte von Claude im Chat gepflegt — **außer `plakate` und `galerie`: die schreibt ausschließlich `bin/veranstaltung-bilder.php`**. Adresse nie in die Texte schreiben (steht in `club.json`) | @@ -834,6 +834,19 @@ Raster: 6×4-Gitter, das erste Foto 4×2, die Anordnung je Anzahl (1 bis 7) als `__bento--nN` mit `grid-template-areas`. Entstanden als Füllseite, die eine 43-seitige Ausgabe auf 44 brachte. +**Redaktioneller Spielrückblick (16.10.2026).** Optionales Feld `rueckblick` einer Ausgabe: +`kicker`, `heading`, `meta`, `result`, `paragraphs[]`, `credit`, `source_url` +sind Chat-Pflege; `image` (inklusive chat-gepflegtem Alt-Text) verwaltet das Add-Skript aus +`/rueckblick.*`. Die Live-Seite steht nach den Ergebnissen, vor der Galerie. Das Foto +liegt dauerhaft im Ausgaben-Ordner. Bei erneutem Erzeugen muss die Quelle wieder mitgeliefert +werden; fehlt sie, bricht das Skript vor dem Leeren des Zielordners ab. Preflight prüft Foto +und Bildnachweis. Der gemeinsame Bild-/Textnachweis steht einmal direkt unter dem Foto +(im Web zur Quelle verlinkt, auch im Druck lesbar). Kein Bild hochskalieren oder fremd einbinden. +Für die Untersteinach-Ausgabe: öffentliches Derby-Vorschaubild +`https://www.anpfiff.info/upload/images/Teaser8/843447.jpg` (560 × 270), Bildquelle anpfiff.info. +Felix hat die Nutzungsgenehmigung im Chat am 16.10.2026 bestätigt. Ein individueller Fotograf +ist am frei sichtbaren Bild nicht ausgewiesen; deshalb keinen Namen vermuten. + **Gegner- und Ergebnisseite neu gestaltet (19.09.2026).** Beide Seiten waren inhaltlich richtig und gestalterisch leer, der Umbau lief über mehrere verworfene Entwürfe. Was davon bleibt: - **Ergebnisse als Anzeigetafel** (Vorbild kicker/Sofascore): Wappen und Name je Seite, das Ergebnis diff --git a/app/components/stadionzeitung-rueckblick.php b/app/components/stadionzeitung-rueckblick.php new file mode 100644 index 0000000..7b1b2d7 --- /dev/null +++ b/app/components/stadionzeitung-rueckblick.php @@ -0,0 +1,41 @@ + +
+
+

+

+
+ +
+

+

+
+
+ $rueckblick['image'], + 'sizes' => '(min-width: 520px) 430px, 90vw', + 'class' => 'stadionzeitung-rueckblick__foto', + 'eager' => $eager ?? false, +]); ?> +
+ + + + + +
+
+
+ +

+ +
+
diff --git a/app/components/stadionzeitung-seite.php b/app/components/stadionzeitung-seite.php index 176cfdb..b2452f9 100644 --- a/app/components/stadionzeitung-seite.php +++ b/app/components/stadionzeitung-seite.php @@ -100,6 +100,9 @@ $type = $entry['type'] ?? 'image'; $issue]); ?> + + $issue, 'eager' => $eager]); ?> + $data['momente'] ?? []]); ?> diff --git a/bin/preflight.php b/bin/preflight.php index 6bb5ac3..00e2b47 100644 --- a/bin/preflight.php +++ b/bin/preflight.php @@ -393,6 +393,21 @@ if (is_file($szFile)) { if (is_file($szFile)) { $szData = $szData ?? (json_decode((string) file_get_contents($szFile), true) ?: []); foreach ($szData['issues'] ?? [] as $ausgabe) { + if (is_array($ausgabe['rueckblick'] ?? null)) { + $rueckblick = $ausgabe['rueckblick']; + $foto = $rueckblick['image'] ?? []; + if (empty($foto['base']) || empty($foto['widths'])) { + $errors[] = "Stadionzeitung '{$ausgabe['slug']}': Foto zum Spielrückblick fehlt."; + } + foreach ($foto['widths'] ?? [] as $w) { + if (!is_file(PUBLIC_PATH . '/assets/' . ($foto['base'] ?? '') . "-{$w}.jpg")) { + $errors[] = "Stadionzeitung '{$ausgabe['slug']}': Rückblick-Foto fehlt ({$w}px)."; + } + } + if (trim((string) ($rueckblick['credit'] ?? '')) === '') { + $errors[] = "Stadionzeitung '{$ausgabe['slug']}': Bildnachweis zum Spielrückblick fehlt."; + } + } foreach ($ausgabe['galerie']['bilder'] ?? [] as $bild) { foreach ($bild['widths'] ?? [] as $w) { $datei = PUBLIC_PATH . '/assets/' . ($bild['base'] ?? '') . "-{$w}.jpg"; diff --git a/bin/stadionzeitung-add.php b/bin/stadionzeitung-add.php index b6835ab..5cf8b18 100644 --- a/bin/stadionzeitung-add.php +++ b/bin/stadionzeitung-add.php @@ -160,6 +160,7 @@ $vorwort = $findOne('vorwort'); $rueckseite = $findOne('rueckseite'); $spieler = $findOne('spieler'); $verfasser = $findOne('verfasser'); +$rueckblickFoto = $findOne('rueckblick'); $galerieQuellen = $findAll('galerie'); // Anzeigen kommen NICHT mehr aus dem Ablieferordner, sondern aus dem dauerhaften // Bestand (data/anzeigen.json, gepflegt über bin/anzeige-add.php). Ein noch @@ -213,6 +214,10 @@ $oldOpponentShort = $oldIssue['opponent_short'] ?? null; // Galerie-Seite: Kopf (kicker/heading/text) und Alt-Texte sind Chat-Pflege, // die Bilder schreibt dieser Lauf aus /galerie/ (siehe unten). $oldGalerie = is_array($oldIssue['galerie'] ?? null) ? $oldIssue['galerie'] : null; +$rueckblick = is_array($oldIssue['rueckblick'] ?? null) ? $oldIssue['rueckblick'] : null; +if ($rueckblick !== null && $rueckblickFoto === null) { + $fail('Spielrückblick vorhanden, aber rueckblick.* fehlt im Ablieferordner.'); +} $oldGegnerTeams = is_array($oldIssue['gegner_teams'] ?? null) ? array_values($oldIssue['gegner_teams']) : null; $veranstaltung = null; if (is_string($oldVeranstaltung) && $oldVeranstaltung !== '') { @@ -437,6 +442,13 @@ try { $bloecke[] = ['name' => 'ergebnisse', 'seiten' => [$live('ergebnisse')], 'anzeigen_danach' => true]; + // Redaktioneller Spielrückblick: Text und Bildnachweis sind Chat-Pflege, + // das Foto kommt aus dem Ablieferordner und bleibt in dieser Ausgabe. + if ($rueckblick !== null) { + $rueckblick['image'] = $bild($rueckblickFoto, 'rueckblick', (string) ($rueckblick['image']['alt'] ?? $rueckblick['heading'] ?? 'Spielrückblick')); + $bloecke[] = ['name' => 'rueckblick', 'seiten' => [$live('rueckblick')], 'anzeigen_danach' => true]; + } + // Galerie direkt hinter dem Ergebnis-Rückblick: erst das Ergebnis, dann die // Bilder dazu. Eigener Block, eine Anzeige dazwischen ist unbedenklich. if (!empty($galerie['bilder'])) { @@ -830,6 +842,7 @@ $issues[] = [ 'veranstaltung' => $oldVeranstaltung, 'cover' => $oldCover, 'galerie' => $galerie, + 'rueckblick' => $rueckblick, 'verfasser_photo' => $verfasserPhoto, 'termine_snapshot' => $termineSnapshot, 'images' => $images, diff --git a/data/instagram.json b/data/instagram.json index 9f88469..252a308 100644 --- a/data/instagram.json +++ b/data/instagram.json @@ -1,7 +1,43 @@ { - "fetched_at": 1791023677, + "fetched_at": 1792183583, "username": "tsv08kulmbach", "posts": [ + { + "shortcode": "DehQgDrDB0Z", + "caption": "🔴⚫️ Vorschau", + "alt": "🔴⚫️ Vorschau", + "taken_at": 1792077339, + "is_video": false, + "image": "img/instagram/DehQgDrDB0Z.jpg", + "url": "https://www.instagram.com/p/DehQgDrDB0Z/" + }, + { + "shortcode": "DeeldfjMZEm", + "caption": "Neue Trikots für unsere E-Jugend! ⚽️😍\n„Euer Ort, euer Verein, euer Trikot“ – unter diesem Motto sorgt die bundesweite TUI-Aktion auch beim TSV 08 Kulmbach für strahlende Gesichter! 👕😊\nDas ReiseCenter Schaffranek sicherte sich unter mehr als 500 Bewerbern einen von 200 Trikotsätzen. Wer sich darüber freuen durfte, entschieden anschließend die Verantwortlichen im ReiseCenter per Los: Sie befüllten die Lostrommel mit den Namen aller Vereine im Kulmbacher Stadtgebiet, die Jugendarbeit bis zur E-Jugend anbieten, und führten die Ziehung durch. Das gezogene Los: TSV 08 Kulmbach! 🍀🙌\nMelanie Schaffranek überreichte die neuen Trikots bei unserem E-Jugendfestival und konnte unsere Nachwuchskicker direkt darin in Aktion erleben. ⚽\nEin herzliches Dankeschön an TUI sowie an Melanie Schaffranek und das gesamte Team des ReiseCenter Schaffranek für diese tolle Unterstützung unserer Jugendarbeit! ❤️🖤\nUnsere E-Jugend trägt das TUI-Lächeln ab sofort auf dem Trikot – und die Freude darüber im Gesicht! 😃\n\n#tsv08kulmbach #jugendfussball #reisetui \nDanke @reisebuero_schaffranek", + "alt": "Neue Trikots für unsere E-Jugend! ⚽️😍", + "taken_at": 1791987664, + "is_video": false, + "image": "img/instagram/DeeldfjMZEm.jpg", + "url": "https://www.instagram.com/p/DeeldfjMZEm/" + }, + { + "shortcode": "DePJUbkjKPc", + "caption": "🔴⚫️ Vorschau", + "alt": "🔴⚫️ Vorschau", + "taken_at": 1791469594, + "is_video": false, + "image": "img/instagram/DePJUbkjKPc.jpg", + "url": "https://www.instagram.com/p/DePJUbkjKPc/" + }, + { + "shortcode": "DeG8wTzjAVR", + "caption": "Ergebnisse vom Wochenende 🔴⚫️\n\nDerbysieg für unsere Erste 🤹🏻‍♂️ und unsere Frauen bleiben weiterhin ungeschlagen! 💪🏻", + "alt": "Ergebnisse vom Wochenende 🔴⚫️", + "taken_at": 1791194571, + "is_video": false, + "image": "img/instagram/DeG8wTzjAVR.jpg", + "url": "https://www.instagram.com/p/DeG8wTzjAVR/" + }, { "shortcode": "Dd9tmXplrZx", "caption": "🔴⚫️ Vorschau inkl. Stadtderby 🔥", diff --git a/data/stadionzeitung.json b/data/stadionzeitung.json index 9cf17e9..5134455 100644 --- a/data/stadionzeitung.json +++ b/data/stadionzeitung.json @@ -1,5 +1,616 @@ { "issues": [ + { + "slug": "2026-10-17-sv-fortuna-untersteinach", + "opponent": "SV Fortuna Untersteinach", + "opponent_short": null, + "gegner_teams": [ + "zweite-mannschaft", + "damen" + ], + "date": "2026-10-17", + "team_key": "erste-mannschaft", + "status": "entwurf", + "pages": 44, + "player_image": { + "base": "img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/spieler", + "widths": [ + 320, + 640, + 1000 + ], + "ext": "png", + "alt": "" + }, + "qr_image": "img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/qr.png", + "vorwort": { + "heading": "Willkommen zum Heimspiel", + "paragraphs": [ + "Liebe Fußballfreunde,", + "herzlich willkommen im Katzbachtal! Wir begrüßen unsere Gäste aus Untersteinach, ihre mitgereisten Fans und den Schiedsrichter.", + "Nach dem tragischen Todesfall in der Mannschaft aus Bischofsgrün war die Absage unseres letzten Spiels selbstverständlich. Unsere Gedanken sind bei den Angehörigen und der Mannschaft.", + "Heute empfangen wir mit Untersteinach einen Gegner, der bislang eine starke Saison spielt. Unsere Jungs haben im Training konzentriert gearbeitet und wollen nun vor heimischem Publikum daran anknüpfen. Unterstützt sie lautstark und bleibt fair. Auf geht’s!" + ], + "closing": "Rot-schwarze Grüße", + "signee_name": "Benedikt Höfner", + "signee_role": "Sportlicher Leiter" + }, + "interview": { + "teaser": "Unser Trainer Ali Kilic über die Trainingswoche und das Heimspiel gegen Untersteinach", + "heading": "Zwei Fragen an Ali Kilic", + "person_name": "Ali Kilic", + "person_role": "Trainer 1. Mannschaft", + "intro": null, + "fragen": [ + { + "frage": "Wie hat die Mannschaft diese Trainingswoche gearbeitet?", + "antwort": "Wir hatten eine gute Trainingswoche und haben konzentriert gearbeitet. Die Jungs haben gut mitgezogen. Jetzt kommt es darauf an, das auch im Spiel umzusetzen. Wir wollen von Anfang an wach sein, uns gegenseitig unterstützen und gemeinsam in die Partie finden. Es wird sicher auch Phasen geben, in denen nicht alles klappt. Dann müssen wir dranbleiben und als Mannschaft zusammenhalten. Wir wollen unseren Zuschauern ein gutes Heimspiel zeigen und die Arbeit aus dem Training auf den Platz bringen." + }, + { + "frage": "Was erwartest du von Untersteinach?", + "antwort": "Untersteinach spielt bisher eine sehr gute Saison. Wir haben Respekt vor ihnen und wissen, dass wir als Mannschaft eine gute Leistung brauchen. Wir müssen aufmerksam sein, die Zweikämpfe annehmen und dürfen ihnen keine einfachen Möglichkeiten geben. Gleichzeitig wollen wir unser eigenes Spiel aufziehen und unsere Chancen nutzen. Dafür brauchen wir auch mit dem Ball Ruhe und den Mut, nach vorne zu spielen. Wir spielen zu Hause und wollen hier etwas holen. Entscheidend wird sein, dass wir über die gesamte Partie zusammenarbeiten und jeder für den anderen da ist." + } + ], + "photo": "img/persons/ali-kilic.jpg" + }, + "aufruf": null, + "veranstaltung": null, + "cover": null, + "galerie": { + "kicker": "Rückblick", + "heading": "Unterwegs in Kirchleus", + "bilder": [ + { + "source": "01-IMG_0586_01.jpg", + "base": "img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/galerie-01", + "widths": [ + 640, + 1200 + ], + "alt": "Einer unserer Spieler holt in Kirchleus zum Schuss aus, ein Gegenspieler kommt einen Schritt zu spät." + }, + { + "source": "02-IMG_0692_01.jpg", + "base": "img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/galerie-02", + "widths": [ + 640, + 1200 + ], + "alt": "Zweikampf um den Ball: Einer unserer Spieler setzt sich gegen einen Kirchleuser durch." + }, + { + "source": "03-IMG_0565_01.jpg", + "base": "img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/galerie-03", + "widths": [ + 640, + 1200 + ], + "alt": "Einer unserer Spieler treibt den Ball nach vorne, ein Kirchleuser läuft heran." + }, + { + "source": "04-IMG_0612_01.jpg", + "base": "img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/galerie-04", + "widths": [ + 640, + 1200 + ], + "alt": "An der Eckfahne nimmt einer unserer Spieler den Ball an." + }, + { + "source": "05-IMG_0571_01.jpg", + "base": "img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/galerie-05", + "widths": [ + 640, + 1200 + ], + "alt": "Einer unserer Spieler läuft in der Herbstsonne über den Platz." + } + ], + "text": "Ein Rückblick auf unser Auswärtsspiel am 27. September beim 1. FC Kirchleus, das wir knapp mit 2:3 verloren haben." + }, + "rueckblick": { + "kicker": "Derby-Rückblick", + "heading": "Derbysieg im Katzbachtal", + "meta": "TSV 08 Kulmbach – VfB Kulmbach · 3. Oktober 2026", + "result": "2:0", + "paragraphs": [ + "Das Stadtderby blieb lange offen. Der VfB hatte vor allem in der ersten Halbzeit mehr vom Spiel. Auch nach der Pause mussten unsere Jungs zunächst dagegenhalten.", + "Mit zunehmender Spielzeit fand unsere Mannschaft besser in die Partie und entschied das Derby mit zwei späten Treffern für sich. Am Ende standen ein Heimsieg, drei Punkte und eine weiße Weste." + ], + "credit": "Quelle: anpfiff.info", + "source_url": "https://www.anpfiff.info/sites/fb/spielbericht.aspx?SK=6&Lg=118&Sp=1153653&Ver=784&TmHm=1265&TmGt=1225&Top=2&Ticker=1&Men=0", + "image": { + "type": "image", + "base": "img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/rueckblick", + "widths": [ + 480, + 560 + ], + "alt": "Zweikampf zwischen einem Spieler des TSV 08 Kulmbach in Rot und einem Spieler des VfB Kulmbach in Blau beim Stadtderby am 3. Oktober 2026." + } + }, + "verfasser_photo": { + "base": "img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/verfasser", + "widths": [ + 120, + 222 + ], + "alt": "" + }, + "termine_snapshot": [ + { + "date": "2026-10-24", + "date_end": null, + "title": "TSV 08 Kulmbach – TDC Lindau 2", + "department": "fussball", + "type": "spiel", + "meta": "Heimspiel · Kreisklasse", + "href": "/matchcenter", + "kickoff": "2026-10-24T14:00", + "team_name": "1. Mannschaft", + "league": "Kreisklasse", + "raw": { + "kickoff": "2026-10-24T14:00", + "date_display": "Sa, 24.10.", + "time_display": "14:00 Uhr", + "competition": "Liga", + "home": "TSV 08 Kulmbach", + "away": "TDC Lindau 2", + "home_crest": "img/crests/00ES8GNK3G000012VV0AG08LVUPGND5I.png", + "away_crest": "img/crests/00ES8GNK3G000019VV0AG08LVUPGND5I.png", + "is_home": true, + "team_key": "erste-mannschaft", + "team_name": "1. Mannschaft" + } + }, + { + "date": "2026-10-24", + "date_end": null, + "title": "1. FC Trogen (flex) – TSV 08 Kulmbach", + "department": "fussball", + "type": "spiel", + "meta": "Auswärtsspiel · Frauen KL Ost", + "href": "/matchcenter", + "kickoff": "2026-10-24T17:00", + "team_name": "Frauenmannschaft", + "league": "Frauen KL Ost", + "raw": { + "kickoff": "2026-10-24T17:00", + "date_display": "Sa, 24.10.", + "time_display": "17:00 Uhr", + "competition": "Liga", + "home": "1. FC Trogen (flex)", + "away": "TSV 08 Kulmbach", + "home_crest": "img/crests/00ES8GNK9O00001CVV0AG08LVUPGND5I.png", + "away_crest": "img/crests/00ES8GNK3G000012VV0AG08LVUPGND5I.png", + "is_home": false, + "team_key": "damen", + "team_name": "Frauenmannschaft" + } + }, + { + "date": "2026-11-01", + "date_end": null, + "title": "TSV 08 Kulmbach – SSV Schwarzenbach a.Wald", + "department": "fussball", + "type": "spiel", + "meta": "Heimspiel · Frauen KL Ost", + "href": "/matchcenter", + "kickoff": "2026-11-01T10:30", + "team_name": "Frauenmannschaft", + "league": "Frauen KL Ost", + "raw": { + "kickoff": "2026-11-01T10:30", + "date_display": "So, 01.11.", + "time_display": "10:30 Uhr", + "competition": "Liga", + "home": "TSV 08 Kulmbach", + "away": "SSV Schwarzenbach a.Wald", + "home_crest": "img/crests/00ES8GNK3G000012VV0AG08LVUPGND5I.png", + "away_crest": "img/crests/00ES8GNK9O00000PVV0AG08LVUPGND5I.png", + "is_home": true, + "team_key": "damen", + "team_name": "Frauenmannschaft" + } + }, + { + "date": "2026-11-01", + "date_end": null, + "title": "SV Hutschdorf – TSV 08 Kulmbach", + "department": "fussball", + "type": "spiel", + "meta": "Auswärtsspiel · Kreisklasse", + "href": "/matchcenter", + "kickoff": "2026-11-01T14:00", + "team_name": "1. Mannschaft", + "league": "Kreisklasse", + "raw": { + "kickoff": "2026-11-01T14:00", + "date_display": "So, 01.11.", + "time_display": "14:00 Uhr", + "competition": "Liga", + "home": "SV Hutschdorf", + "away": "TSV 08 Kulmbach", + "home_crest": "img/crests/00ES8GNK3G00000LVV0AG08LVUPGND5I.png", + "away_crest": "img/crests/00ES8GNK3G000012VV0AG08LVUPGND5I.png", + "is_home": false, + "team_key": "erste-mannschaft", + "team_name": "1. Mannschaft" + } + }, + { + "date": "2027-02-20", + "date_end": null, + "title": "Tagesskifahrt 2027", + "department": "verein", + "type": "event", + "meta": "Skigebiet Hochzillertal", + "href": "/veranstaltungen/tagesskifahrt-2027", + "time": "", + "location": "Skigebiet Hochzillertal", + "raw": { + "slug": "tagesskifahrt-2027", + "title": "Tagesskifahrt 2027", + "date_start": "2027-02-20", + "date_end": null, + "time": "", + "location": "Skigebiet Hochzillertal", + "department": "verein", + "status": "veroeffentlicht", + "text": "Wir fahren für einen Tag zum Skifahren ins Skigebiet Hochzillertal. Die Plätze sind auf 40 Personen begrenzt, angemeldet wird bei Fabian Früh.", + "ankuendigung": [ + "Einmal im Winter machen wir uns gemeinsam auf und fahren für einen Tag ins Skigebiet Hochzillertal bei Kaltenbach. Ob Erwachsene, Jugendliche oder Kinder: Auf den Pisten ist für alle etwas dabei. Die Fahrt ist auf 40 Personen begrenzt, wer dabei sein möchte, meldet sich am besten früh.", + "Erwachsene zahlen 115 Euro, Jugendliche 95 Euro und Kinder 70 Euro. Anmelden könnt ihr euch bei Fabian Früh unter 0160 97516797." + ], + "rueckblick": null, + "karte": "", + "anfahrt": [], + "plakate": [ + { + "base": "img/veranstaltungen/tagesskifahrt-2027/plakat-01", + "widths": [ + 640, + 1000, + 1024 + ], + "alt": "Plakat zu unserer Tagesskifahrt am Samstag, 20. Februar 2027 ins Skigebiet Hochzillertal, mit den Preisen für Erwachsene, Jugendliche und Kinder und der Anmeldung bei Fabian Früh.", + "source": "1-ankuendigung.jpeg" + } + ], + "galerie": [] + } + } + ], + "images": [ + { + "type": "live", + "page": "cover" + }, + { + "type": "live", + "page": "vorwort" + }, + { + "type": "live", + "page": "interview" + }, + { + "type": "image", + "base": "img/anzeigen/eldorado", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: eldorado Radsporttechnik Kulmbach" + }, + { + "type": "image", + "base": "img/anzeigen/egu", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Erfrischungsgetränke-Union Kulmbacher Gruppe GmbH" + }, + { + "type": "live", + "page": "ergebnisse" + }, + { + "type": "image", + "base": "img/anzeigen/hofmann-graef", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Buchhandlung Hofmann, Kulmbach, und Automobilwerkstatt Gräf, Thurnau" + }, + { + "type": "live", + "page": "rueckblick" + }, + { + "type": "image", + "base": "img/anzeigen/muench-richterstegner", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Planungsbüro Münch und Richter & Stegner Steuerungstechnik" + }, + { + "type": "image", + "base": "img/anzeigen/malteser-herrmann", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Malteser-Hilfsdienst und Schlosserei Herrmann, Kulmbach" + }, + { + "type": "live", + "page": "galerie" + }, + { + "type": "image", + "base": "img/anzeigen/apotheken-wenkel", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Apotheke im Fritz, Stadtpark Apotheke und Schlüsseldienst Wenkel, Kulmbach" + }, + { + "type": "live", + "page": "gegner", + "team": "erste-mannschaft" + }, + { + "type": "image", + "base": "img/anzeigen/karl-geyer", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Geyer Farbe + Raum, Kulmbach, Starthilfe Boden" + }, + { + "type": "image", + "base": "img/anzeigen/gsb", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: GSB Security und GSB Gebäude Service, Bindlach" + }, + { + "type": "live", + "page": "tabelle", + "team": "erste-mannschaft" + }, + { + "type": "live", + "page": "tabelle", + "team": "zweite-mannschaft" + }, + { + "type": "live", + "page": "tabelle", + "team": "damen" + }, + { + "type": "image", + "base": "img/anzeigen/physiofit-wohlfart", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Physio Fit Neudrossenfeld und Textilpflege Wohlfart, Kulmbach" + }, + { + "type": "live", + "page": "vorschau" + }, + { + "type": "image", + "base": "img/anzeigen/sport2000-pizza", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Sport 2000 Downstairs und Kulmbacher Pizza-Service" + }, + { + "type": "image", + "base": "img/anzeigen/schulz-csu", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Schreinerei Schulz, Mainleus, und CSU Stadtverband Kulmbach" + }, + { + "type": "live", + "page": "termine" + }, + { + "type": "image", + "base": "img/anzeigen/mattis-ka2", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Karl Mattis Flaschnerei und KA2 Fitness, Kulmbach" + }, + { + "type": "live", + "page": "news" + }, + { + "type": "image", + "base": "img/anzeigen/motor-nuetzel", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Motor-Nützel Vertriebs-GmbH, Bayreuth" + }, + { + "type": "image", + "base": "img/anzeigen/vereinskarte-edeka", + "widths": [ + 480, + 960, + 1410 + ], + "alt": "Eigenanzeige: So funktioniert die Vereinskarte beim E center Seidl Kulmbach" + }, + { + "type": "live", + "page": "kontakt" + }, + { + "type": "image", + "base": "img/anzeigen/trapper-verkehrsakademie", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Trapper GmbH Entsorgungsfachbetrieb und Verkehrsakademie, Kulmbach" + }, + { + "type": "live", + "page": "mitglied" + }, + { + "type": "image", + "base": "img/anzeigen/ohnemueller-dippold", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Gaststätte und Metzgerei Ohne-Müller, Kulmbach-Weiher, und Bäckerei Dippold, Melkendorf" + }, + { + "type": "image", + "base": "img/anzeigen/hanft", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Hanft Bürotechnik GmbH, Kulmbach" + }, + { + "type": "live", + "page": "historie" + }, + { + "type": "image", + "base": "img/anzeigen/elma-kleinheinz", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: elma GmbH Bayreuth und Metzgerei Kleinheinz, Kulmbach" + }, + { + "type": "live", + "page": "sportheim" + }, + { + "type": "image", + "base": "img/anzeigen/stadionzeitung-digital", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Eigenanzeige: Unsere Stadionzeitung gibt es jetzt auch online, mit QR-Code zum Scannen" + }, + { + "type": "image", + "base": "img/anzeigen/gagel-pickelmann", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Gagel Bäder und Mineralölhandel Pickelmann" + }, + { + "type": "live", + "page": "partner" + }, + { + "type": "live", + "page": "danke", + "anzeige": { + "base": "img/anzeigen/emons", + "widths": [ + 480, + 960, + 1141 + ], + "alt": "Anzeige: Emons Spedition Himmelkron, Ihr Partner für nationale und internationale Transporte" + } + }, + { + "type": "image", + "base": "img/anzeigen/schramm", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Landgasthof und Metzgerei Schramm, Forstlahm" + }, + { + "type": "live", + "page": "momente" + }, + { + "type": "image", + "base": "img/anzeigen/tagesskifahrt-2027", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Eigenanzeige: Unsere Tagesskifahrt ins Hochzillertal am 20. Februar 2027" + }, + { + "type": "live", + "page": "impressum" + }, + { + "type": "image", + "base": "img/stadionzeitung/2026-10-17-sv-fortuna-untersteinach/rueckseite", + "widths": [ + 480, + 960, + 1410 + ], + "alt": "Rückseite der Stadionzeitung gegen SV Fortuna Untersteinach" + } + ] + }, { "slug": "2026-10-03-vfb-kulmbach", "opponent": "VfB Kulmbach", @@ -8085,4 +8696,4 @@ } } ] -} \ No newline at end of file +} diff --git a/public/assets/css/components.css b/public/assets/css/components.css index 1020b00..d0a0be8 100644 --- a/public/assets/css/components.css +++ b/public/assets/css/components.css @@ -8628,6 +8628,44 @@ p.stadionzeitung-turnier__label:first-of-type { object-fit: cover; } +/* === stadionzeitung-rueckblick (redaktionelle Seite mit Bildnachweis) === */ +.stadionzeitung-rueckblick { + display: flex; + flex-direction: column; + min-height: 100%; +} + +/* Kopf/Trennlinie, Ergebnis und Fließtext verwenden die vorhandenen + Heft-Klassen. Hier nur die Anordnung von Bild und Ergebnis definieren. */ +.stadionzeitung-rueckblick__scoreline { + display: flex; + align-items: center; + gap: 4cqi; + margin-bottom: 4cqi; +} + +.stadionzeitung-rueckblick__scoreline .stadionzeitung-ergebnisse__result { + flex: 0 0 auto; + margin: 0; +} + +.stadionzeitung-rueckblick__figure { + margin: 0 0 3cqi; +} + +.stadionzeitung-rueckblick__foto { + display: block; + width: 100%; + height: auto; +} + +.stadionzeitung-rueckblick__credit { + font-size: 2.5cqi; + line-height: 1.4; + color: var(--clr-text-muted); + margin-top: 1cqi; +} + /* === stadionzeitung-galerie (Live-Seite, optional: Fotos vom letzten Spiel) === */ /* Bento-Raster auf einem 6×4-Gitter: das erste Foto ist der Aufmacher (4×2), die übrigen legen sich je nach Anzahl darum. Die Fläche unter dem Kopf gehört diff --git a/public/assets/img/instagram/DeG8wTzjAVR.jpg b/public/assets/img/instagram/DeG8wTzjAVR.jpg new file mode 100644 index 0000000000000000000000000000000000000000..20ac57f0a816cda106aff4cd25cc2201e049fbc0 GIT binary patch literal 195272 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