diff --git a/CLAUDE.md b/CLAUDE.md index 17948fe..b866950 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -517,6 +517,7 @@ kein Download-Link — nur die Web-Ansicht. Der Ablauf pro Heimspiel ist damit: Inhalt ist eine Liste von **Blöcken**, die Anzeigen füllen die Lücken dazwischen (⌷ = Lücke): ``` Cover → [Vorwort → Interview (nur wenn die Ausgabe eins trägt)] ⌷ Ergebnis-Rückblick ⌷ + Gegnerstatistik der tragenden Mannschaft (automatisch aus deren Tabelle) ⌷ [je Mannschaft eine Tabelle, Reihenfolge = matchcenter.json — EIN Block, dazwischen nie eine Anzeige; Erste + Zweite bilden im gefalteten Heft eine Doppelseite] ⌷ Vorschau ⌷ Termine ⌷ News ⌷ Ansprechpartner ⌷ Mitglied-werden-Poster ⌷ Historie-Teaser (Website-Verweis + @@ -547,7 +548,7 @@ Lücken bekommen 7 Lücken zwei. Zwei hintereinander ist das Optimum, nicht eins Zweier-Paar auf einer Doppelseite landen kann, schlägt man das Heft gelegentlich auf zwei Anzeigen auf. Ein `images[]`-Eintrag hat `"type": "image"` (wie gehabt, `base`/`widths`/`alt`) oder `"type": "live"` (`page`: `cover` | -`vorwort` | `interview` | `aufruf` | `tabelle` | `termine` | `news` | `ergebnisse` | `vorschau` | `kontakt` | `mitglied` | `historie` | `sportheim` | `partner` | `momente` | `impressum`, kein Bild; +`vorwort` | `interview` | `aufruf` | `tabelle` | `termine` | `news` | `ergebnisse` | `gegner` | `vorschau` | `kontakt` | `mitglied` | `historie` | `sportheim` | `partner` | `momente` | `impressum`, kein Bild; `tabelle` zusätzlich mit `team`: Team-Key aus `matchcenter.json`, ohne `team` greift der Team-Key der Ausgabe). Fehlt `type` (alte Phase-1-Ausgaben) → Fallback `image`, bricht nicht. **Gerendert wird jede Seite (Bild wie Live) über `app/components/stadionzeitung-seite.php`** — die eine diff --git a/app/components/stadionzeitung-gegner.php b/app/components/stadionzeitung-gegner.php new file mode 100644 index 0000000..9a206d3 --- /dev/null +++ b/app/components/stadionzeitung-gegner.php @@ -0,0 +1,88 @@ + 'Tabellenplatz', 'key' => 'rank'], + ['label' => 'Spiele', 'key' => 'played'], + ['label' => 'Siege', 'key' => 'won'], + ['label' => 'Unentschieden', 'key' => 'drawn'], + ['label' => 'Niederlagen', 'key' => 'lost'], + ['label' => 'Tordifferenz', 'key' => 'goal_diff', 'signed' => true], + ['label' => 'Punkte', 'key' => 'points'], +]; + +$format = static function (?array $row, string $key, bool $signed = false): string { + if ($row === null || !array_key_exists($key, $row)) { + return '–'; + } + $value = (int) $row[$key]; + return $signed && $value > 0 ? '+' . $value : (string) $value; +}; +?> +
+
+

Unser Gegner

+

+ +

+ +
+ + +
+
+ $fixture['home_crest'] ?? $own['crest'] ?? null, 'name' => $fixture['home'] ?? 'TSV 08 Kulmbach']); ?> + +
+
+ gegen + + + + + Uhr + +
+
+ $fixture['away_crest'] ?? $opponent['crest'] ?? null, 'name' => $fixture['away'] ?? $opponentName]); ?> + +
+
+ + +
+
+ TSV 08 + Vergleich + ASV +
+ +
+ + + +
+ +
+ +

Die aktuellen Vergleichsdaten waren beim letzten Abruf nicht verfügbar.

+ +
diff --git a/app/components/stadionzeitung-seite.php b/app/components/stadionzeitung-seite.php index 51d4280..6638955 100644 --- a/app/components/stadionzeitung-seite.php +++ b/app/components/stadionzeitung-seite.php @@ -10,7 +10,7 @@ declare(strict_types=1); * $entry Eintrag aus issue.images[]: * type 'image' (base/widths/alt), * type 'live' (page: cover|vorwort|interview|aufruf|tabelle|termine| - * news|ergebnisse|vorschau|kontakt; tabelle optional + * news|ergebnisse|gegner|vorschau|kontakt; tabelle optional * mit team: Team-Key aus matchcenter.json), * type 'leer' (weiße Füllseite, nur Druckfassung — hält die * Seitenzahl auf einem Vielfachen von 4) @@ -55,6 +55,9 @@ $type = $entry['type'] ?? 'image'; $data['ergebnisse'] ?? []]); ?> + + $data['gegner'] ?? null]); ?> + $data['vorschau'] ?? []]); ?> diff --git a/app/components/stadionzeitung-termine.php b/app/components/stadionzeitung-termine.php index 84a7997..6246c88 100644 --- a/app/components/stadionzeitung-termine.php +++ b/app/components/stadionzeitung-termine.php @@ -8,7 +8,7 @@ declare(strict_types=1); * (Kicker + Überschrift über einblendendem Vereinsfoto), aber mit einer * Icon-Liste statt Fließtext. * - * Die drei Termine sind KEIN Live-Abruf: bin/stadionzeitung-add.php friert + * Die Termine sind KEIN Live-Abruf: bin/stadionzeitung-add.php friert * sie beim Anlegen der Ausgabe einmalig ein (`termine_snapshot`, siehe dort * und termine_build_lists()) — eine gedruckte Ausgabe zeigt dauerhaft, was * am Spieltag anstand, nicht was von "heute" aus gesehen ansteht. @@ -60,6 +60,8 @@ $termineLink = club_domain('termine'); } elseif (!$isMatch && !empty($item['location'])) { $parts[] = (string) $item['location']; } + $title = (string) ($item['title'] ?? ''); + $meta = implode(' · ', $parts); ?>
  • -

    -

    +

    +

  • diff --git a/app/helpers.php b/app/helpers.php index 31a6bf9..169ed88 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -988,10 +988,12 @@ function stadionzeitung_build_snapshot(array $issue): array { $date = (string) ($issue['date'] ?? ''); $issueTeam = (string) ($issue['team_key'] ?? ''); + $issueOpponent = trim((string) ($issue['opponent'] ?? '')); $tabellen = []; $ergebnisse = []; $vorschau = []; + $gegner = null; foreach (json_load('matchcenter')['teams'] ?? [] as $team) { $key = (string) ($team['key'] ?? ''); if ($key === '') { @@ -1004,6 +1006,44 @@ function stadionzeitung_build_snapshot(array $issue): array 'table' => $team['table'] ?? [], ]; + // Gegnerseite der tragenden Mannschaft: ausschließlich aus demselben + // Matchcenter-Datensatz wie die Tabelle ableiten. So gibt es keinen + // zweiten BFV-Abruf und der Stand wird beim Veröffentlichen zusammen + // mit den übrigen Live-Daten eingefroren. + if ($key === $issueTeam && $issueOpponent !== '') { + $table = is_array($team['table'] ?? null) ? $team['table'] : []; + $ownRow = null; + $opponentRow = null; + foreach ($table as $row) { + if (!empty($row['is_own_club'])) { + $ownRow = $row; + } + if (strcasecmp(trim((string) ($row['club'] ?? '')), $issueOpponent) === 0) { + $opponentRow = $row; + } + } + + $fixture = null; + foreach ($team['next_matches'] ?? [] as $match) { + $matchDate = substr((string) ($match['kickoff'] ?? ''), 0, 10); + $clubs = [(string) ($match['home'] ?? ''), (string) ($match['away'] ?? '')]; + if ($matchDate === $date && in_array($issueOpponent, $clubs, true)) { + $fixture = $match; + break; + } + } + + $gegner = [ + 'team_name' => (string) ($team['name'] ?? ''), + 'opponent' => $issueOpponent, + 'league' => (string) ($team['league'] ?? ''), + 'season' => (string) ($team['season'] ?? ''), + 'fixture' => $fixture, + 'own' => $ownRow, + 'opponent_stats' => $opponentRow, + ]; + } + // Nur Spiele mit erfasstem Ergebnis — ein Testspiel ohne Tore ist // kein Rückblick (dieselbe Regel wie im News-Feed). $withScore = array_values(array_filter( @@ -1058,6 +1098,7 @@ function stadionzeitung_build_snapshot(array $issue): array return [ 'tabellen' => $tabellen, + 'gegner' => $gegner, 'ergebnisse' => $ergebnisse, 'vorschau' => $vorschau, // Fünf statt sechs: mit den größeren Überschriften + CTA-Fuß braucht diff --git a/bin/stadionzeitung-add.php b/bin/stadionzeitung-add.php index dc855a2..f966d30 100644 --- a/bin/stadionzeitung-add.php +++ b/bin/stadionzeitung-add.php @@ -309,6 +309,7 @@ try { } $bloecke[] = ['name' => 'ergebnisse', 'seiten' => [$live('ergebnisse')], 'anzeigen_danach' => true]; + $bloecke[] = ['name' => 'gegner', 'seiten' => [$live('gegner')], 'anzeigen_danach' => true]; // Eine Tabellen-Seite je Mannschaft, Reihenfolge wie in matchcenter.json // (= config 'matchcenter.teams'). Kommt eine Mannschaft dazu (z. B. die diff --git a/data/anzeigen.json b/data/anzeigen.json index 32b60fb..bc3f70e 100644 --- a/data/anzeigen.json +++ b/data/anzeigen.json @@ -124,7 +124,7 @@ { "slug": "emons-stuebinger", "sponsor": "Emons Spedition und AST Stübinger Hoch-, Tief- und Straßenbau, Kulmbach", - "aktiv": true, + "aktiv": false, "base": "img/anzeigen/emons-stuebinger", "widths": [ 480, @@ -247,6 +247,53 @@ 960, 1440 ] + }, + { + "slug": "emons-partnerdank", + "sponsor": "Emons Spedition und Dank an unsere Partner", + "aktiv": true, + "alt": "Anzeige: Emons Spedition, darunter unser Dank an alle Partner", + "base": "img/anzeigen/emons-partnerdank", + "widths": [ + 480, + 960, + 1440 + ] + }, + { + "slug": "gagel-pickelmann", + "sponsor": "Gagel Bäder und Mineralölhandel Pickelmann", + "aktiv": true, + "base": "img/anzeigen/gagel-pickelmann", + "widths": [ + 480, + 960, + 1440 + ] + }, + { + "slug": "schramm", + "sponsor": "Landgasthof und Metzgerei Schramm, Forstlahm", + "aktiv": true, + "base": "img/anzeigen/schramm", + "widths": [ + 480, + 960, + 1440 + ] + }, + { + "slug": "tagesskifahrt-2027", + "sponsor": "Unsere Tagesskifahrt ins Hochzillertal 2027", + "aktiv": true, + "bis": "2027-02-20", + "alt": "Eigenanzeige: Unsere Tagesskifahrt ins Hochzillertal am 20. Februar 2027", + "base": "img/anzeigen/tagesskifahrt-2027", + "widths": [ + 480, + 960, + 1440 + ] } ] } diff --git a/data/stadionzeitung.json b/data/stadionzeitung.json index f011ad6..7690dee 100644 --- a/data/stadionzeitung.json +++ b/data/stadionzeitung.json @@ -1,5 +1,582 @@ { "issues": [ + { + "slug": "2026-08-29-asv-marktschorgast", + "opponent": "ASV Marktschorgast", + "date": "2026-08-29", + "team_key": "erste-mannschaft", + "status": "entwurf", + "pages": 44, + "player_image": { + "base": "img/stadionzeitung/2026-08-29-asv-marktschorgast/spieler", + "widths": [ + 320, + 640, + 1000 + ], + "ext": "png", + "alt": "" + }, + "qr_image": "img/stadionzeitung/2026-08-29-asv-marktschorgast/qr.png", + "vorwort": { + "heading": "Jetzt soll der erste Heimsieg her!", + "paragraphs": [ + "Liebe Fußballfreunde,", + "herzlich willkommen im Katzbachtal. Ein besonderer Gruß gilt dem Schiedsrichtergespann und unseren Gästen vom ASV Marktschorgast.", + "Der starke 7:1-Auswärtssieg in Rugendorf gibt uns Rückenwind. Trotzdem zählt heute nur die neue Aufgabe: Gegen den direkten Tabellennachbarn aus Marktschorgast wollen wir endlich unseren ersten Heimsieg feiern.", + "Leidenschaft, Wille, Heimsieg. Los geht's!" + ], + "closing": "Rot-schwarze Grüße", + "signee_name": "Benedikt Höfner", + "signee_role": "Sportlicher Leiter" + }, + "interview": { + "teaser": "Unser Trainer Ali Kilic über den starken Auftritt in Rugendorf, den ASV Marktschorgast und den ersehnten ersten Heimsieg", + "heading": "Drei Fragen an Ali Kilic", + "person_name": "Ali Kilic", + "person_role": "Trainer 1. Mannschaft", + "intro": null, + "fragen": [ + { + "frage": "Ali, wie blickst du auf das letzte Auswärtsspiel in Rugendorf zurück?", + "antwort": "Das war ein sehr guter Auftritt von uns. Trotz der teilweise hitzigen Stimmung haben wir uns nicht beirren lassen, sind bei unserem Spiel geblieben und haben über 90 Minuten eine konzentrierte Auswärtsleistung gezeigt. Das 7:1 wollen wir trotzdem nicht zu hoch hängen. Entscheidend ist, dass wir diesen Schwung mitnehmen und gegen Marktschorgast endlich unseren ersten Heimsieg holen." + }, + { + "frage": "Marktschorgast steht aktuell einen Punkt vor uns. Was für einen Gegner erwartest du?", + "antwort": "Die Tabelle zeigt, wie eng es aktuell zugeht. Marktschorgast wird uns alles abverlangen. Für uns geht es darum, unabhängig vom Gegner unsere eigenen Prinzipien auf den Platz zu bringen, aufmerksam zu verteidigen und mutig nach vorne zu spielen." + }, + { + "frage": "In den ersten beiden Heimspielen hat es noch nicht mit einem Sieg geklappt. Was müssen wir diesmal besser machen?", + "antwort": "Wir müssen von der ersten Minute an wach und konsequent sein. Gerade zuhause wollen wir das Spiel aktiv gestalten, unsere Fehler kleinhalten und unsere Chancen besser nutzen. Wenn wir als Mannschaft dieselbe Geschlossenheit wie in Rugendorf zeigen, haben wir sehr gute Möglichkeiten, den ersten Heimsieg zu holen." + } + ], + "photo": "img/persons/ali-kilic.jpg" + }, + "aufruf": { + "kicker": "Sportfest 2026", + "heading": "Helfende Hände gesucht", + "intro": [ + "Sportfest vom 4. bis 6. September.", + "Drei Tage Fußball, Essen und Feiern.", + "Dafür brauchen wir dich." + ], + "tasks_title": "Wobei wir Hilfe brauchen", + "tasks": [ + "Grillen", + "Kaffee, Kuchen und Getränke verkaufen", + "Pizza backen und verkaufen", + "Kuchen backen und mitbringen" + ], + "contacts_intro": "Du willst mit anpacken? Melde dich bei einem von uns:", + "contacts": [ + "Sam Kern", + "Kerstin Tauber", + "Fabian Früh" + ], + "link": "veranstaltungen/sportfest-2026", + "cta_label": "Alle Infos", + "cta_title": "Alles zum Sportfest", + "poster": { + "base": "img/veranstaltungen/sportfest-2026/plakat-01", + "widths": [ + 640, + 1000, + 1587 + ], + "alt": "Plakat zum Sportfest 2026 mit Luftbild unserer Sportanlage und den Terminen vom 4. bis 6. September" + } + }, + "verfasser_photo": { + "base": "img/stadionzeitung/2026-08-29-asv-marktschorgast/verfasser", + "widths": [ + 120, + 222 + ], + "alt": "" + }, + "termine_snapshot": [ + { + "date": "2026-09-02", + "date_end": null, + "title": "(SG1) TSV Melkendorf III/ TSV 08 Kulmbach II – TSV 1902 Thurnau II", + "department": "fussball", + "type": "spiel", + "meta": "Heimspiel · Reserve BK 5 BT-KU", + "href": "/matchcenter", + "kickoff": "2026-09-02T18:00", + "team_name": "2. Mannschaft", + "league": "Reserve BK 5 BT-KU", + "raw": { + "kickoff": "2026-09-02T18:00", + "date_display": "Mi, 02.09.", + "time_display": "18:00 Uhr", + "competition": "Liga", + "home": "(SG1) TSV Melkendorf III/ TSV 08 Kulmbach II", + "away": "TSV 1902 Thurnau II", + "home_crest": "img/crests/00ES8GNK4O000002VV0AG08LVUPGND5I.png", + "away_crest": "img/crests/00ES8GNK4O00000SVV0AG08LVUPGND5I.png", + "is_home": true, + "team_key": "zweite-mannschaft", + "team_name": "2. Mannschaft" + } + }, + { + "date": "2026-09-04", + "date_end": null, + "title": "TSV 08 Kulmbach – ATS Wartenfels", + "department": "fussball", + "type": "spiel", + "meta": "Heimspiel · Kreisklasse", + "href": "/matchcenter", + "kickoff": "2026-09-04T18:00", + "team_name": "1. Mannschaft", + "league": "Kreisklasse", + "raw": { + "kickoff": "2026-09-04T18:00", + "date_display": "Fr, 04.09.", + "time_display": "18:00 Uhr", + "competition": "Liga", + "home": "TSV 08 Kulmbach", + "away": "ATS Wartenfels", + "home_crest": "img/crests/00ES8GNK3G000012VV0AG08LVUPGND5I.png", + "away_crest": "img/crests/00ES8GNK4O000012VV0AG08LVUPGND5I.png", + "is_home": true, + "team_key": "erste-mannschaft", + "team_name": "1. Mannschaft" + } + }, + { + "date": "2026-09-04", + "date_end": "2026-09-06", + "title": "Sportfest 2026", + "department": "verein", + "type": "event", + "meta": "16:30 Uhr · Hans-Rausch-Sportanlage", + "href": "/veranstaltungen/sportfest-2026", + "time": "16:30", + "location": "Hans-Rausch-Sportanlage", + "raw": { + "slug": "sportfest-2026", + "title": "Sportfest 2026", + "date_start": "2026-09-04", + "date_end": "2026-09-06", + "time": "16:30", + "location": "Hans-Rausch-Sportanlage", + "department": "verein", + "status": "veroeffentlicht", + "text": "Drei Tage Fußball, Essen, Trinken, Kaffee und Kuchen: bei uns ist für groß und klein alles dabei, für die Kinder steht eine Hüpfburg.", + "ankuendigung": null, + "rueckblick": null, + "karte": "club", + "anfahrt": [], + "plakate": [ + { + "base": "img/veranstaltungen/sportfest-2026/plakat-01", + "widths": [ + 640, + 1000, + 1587 + ], + "alt": "Plakat zum Sportfest 2026 mit Luftbild unserer Sportanlage und den Terminen vom 4. bis 6. September", + "source": "1-ankuendigung.png" + }, + { + "base": "img/veranstaltungen/sportfest-2026/plakat-02", + "widths": [ + 640, + 1000, + 1587 + ], + "alt": "Programmplakat zum Sportfest 2026 mit allen Spielen, Turnieren und der Kinderolympiade am Samstag", + "source": "2-programm.png" + } + ], + "galerie": [] + } + }, + { + "date": "2026-09-05", + "date_end": null, + "title": "(SG1) TSV Melkendorf III/ TSV 08 Kulmbach II – (SG 2) SV Weidenberg III/SSV Warmensteinach II (flex)", + "department": "fussball", + "type": "spiel", + "meta": "Heimspiel · Reserve BK 5 BT-KU", + "href": "/matchcenter", + "kickoff": "2026-09-05T18:00", + "team_name": "2. Mannschaft", + "league": "Reserve BK 5 BT-KU", + "raw": { + "kickoff": "2026-09-05T18:00", + "date_display": "Sa, 05.09.", + "time_display": "18:00 Uhr", + "competition": "Liga", + "home": "(SG1) TSV Melkendorf III/ TSV 08 Kulmbach II", + "away": "(SG 2) SV Weidenberg III/SSV Warmensteinach II (flex)", + "home_crest": "img/crests/00ES8GNK4O000002VV0AG08LVUPGND5I.png", + "away_crest": "img/crests/00ES8GNK4O000013VV0AG08LVUPGND5I.png", + "is_home": true, + "team_key": "zweite-mannschaft", + "team_name": "2. Mannschaft" + } + }, + { + "date": "2026-09-06", + "date_end": null, + "title": "TSV 08 Kulmbach – 1. FC 1928 Schwarzenbach/Saale", + "department": "fussball", + "type": "spiel", + "meta": "Heimspiel · Frauen KL Ost", + "href": "/matchcenter", + "kickoff": "2026-09-06T11:00", + "team_name": "Frauenmannschaft", + "league": "Frauen KL Ost", + "raw": { + "kickoff": "2026-09-06T11:00", + "date_display": "So, 06.09.", + "time_display": "11:00 Uhr", + "competition": "Liga", + "home": "TSV 08 Kulmbach", + "away": "1. FC 1928 Schwarzenbach/Saale", + "home_crest": "img/crests/00ES8GNK3G000012VV0AG08LVUPGND5I.png", + "away_crest": "img/crests/00ES8GNK9O00000QVV0AG08LVUPGND5I.png", + "is_home": true, + "team_key": "damen", + "team_name": "Frauenmannschaft" + } + } + ], + "images": [ + { + "type": "live", + "page": "cover" + }, + { + "type": "live", + "page": "vorwort" + }, + { + "type": "live", + "page": "interview" + }, + { + "type": "live", + "page": "aufruf" + }, + { + "type": "image", + "base": "img/anzeigen/eldorado", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: eldorado Radsporttechnik Kulmbach" + }, + { + "type": "live", + "page": "ergebnisse" + }, + { + "type": "image", + "base": "img/anzeigen/egu", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Erfrischungsgetränke-Union Kulmbacher Gruppe GmbH" + }, + { + "type": "image", + "base": "img/anzeigen/hofmann-graef", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Buchhandlung Hofmann, Kulmbach, und Automobilwerkstatt Gräf, Thurnau" + }, + { + "type": "live", + "page": "gegner" + }, + { + "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": "tabelle", + "team": "erste-mannschaft" + }, + { + "type": "live", + "page": "tabelle", + "team": "zweite-mannschaft" + }, + { + "type": "live", + "page": "tabelle", + "team": "damen" + }, + { + "type": "image", + "base": "img/anzeigen/apotheken-wenkel", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Apotheke im Fritz, Stadtpark Apotheke und Schlüsseldienst Wenkel, Kulmbach" + }, + { + "type": "image", + "base": "img/anzeigen/karl-geyer", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Geyer Farbe + Raum, Kulmbach, Starthilfe Boden" + }, + { + "type": "live", + "page": "vorschau" + }, + { + "type": "image", + "base": "img/anzeigen/gsb", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: GSB Security und GSB Gebäude Service, Bindlach" + }, + { + "type": "image", + "base": "img/anzeigen/physiofit-wohlfart", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Physio Fit Neudrossenfeld und Textilpflege Wohlfart, Kulmbach" + }, + { + "type": "live", + "page": "termine" + }, + { + "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": "news" + }, + { + "type": "image", + "base": "img/anzeigen/mattis-ka2", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Karl Mattis Flaschnerei und KA2 Fitness, Kulmbach" + }, + { + "type": "live", + "page": "kontakt" + }, + { + "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": "mitglied" + }, + { + "type": "image", + "base": "img/anzeigen/trapper-verkehrsakademie", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Trapper GmbH Entsorgungsfachbetrieb und Verkehrsakademie, Kulmbach" + }, + { + "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": "live", + "page": "historie" + }, + { + "type": "image", + "base": "img/anzeigen/hanft", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Hanft Bürotechnik GmbH, Kulmbach" + }, + { + "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/sportfest-2026-programm", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Eigenanzeige: Programm des Sportfests 2026 mit allen Spielen, Turnieren und der Kinderolympiade" + }, + { + "type": "live", + "page": "partner" + }, + { + "type": "image", + "base": "img/anzeigen/emons-partnerdank", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Emons Spedition, darunter unser Dank an alle Partner" + }, + { + "type": "image", + "base": "img/anzeigen/gagel-pickelmann", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Gagel Bäder und Mineralölhandel Pickelmann" + }, + { + "type": "live", + "page": "momente" + }, + { + "type": "image", + "base": "img/anzeigen/schramm", + "widths": [ + 480, + 960, + 1440 + ], + "alt": "Anzeige: Landgasthof und Metzgerei Schramm, Forstlahm" + }, + { + "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-08-29-asv-marktschorgast/rueckseite", + "widths": [ + 480, + 960, + 1410 + ], + "alt": "Rückseite der Stadionzeitung gegen ASV Marktschorgast" + } + ] + }, { "slug": "2026-08-15-tsv-koednitz", "opponent": "TSV Ködnitz", @@ -1591,4 +2168,4 @@ } } ] -} +} \ No newline at end of file diff --git a/public/assets/css/components.css b/public/assets/css/components.css index 9ba7d1c..4adc914 100644 --- a/public/assets/css/components.css +++ b/public/assets/css/components.css @@ -6605,11 +6605,17 @@ body.is-sz-full .back-to-top { font-weight: var(--fw-bold); font-size: 4.4cqi; line-height: 1.25; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } .stadionzeitung-termine__meta { font-size: 3.1cqi; color: var(--clr-text-muted); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } /* === termine-list (Termine/Events-Seite) === */ @@ -7033,6 +7039,106 @@ a.news-feature__link:hover .news-feature__more { line-height: 1; } +/* === stadionzeitung-gegner (Live-Seite) === */ +.stadionzeitung-gegner { + min-height: 100%; +} + +.stadionzeitung-gegner__duell { + display: grid; + grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); + align-items: center; + gap: 2.5cqi; + margin-bottom: 5cqi; + padding: 3.3cqi; + border: 1px solid var(--clr-glass-border); + border-radius: var(--radius-btn); + background: color-mix(in srgb, var(--clr-accent) 5%, #fff); +} + +.stadionzeitung-gegner__club { + --crest-size: 12cqi; + display: flex; + flex-direction: column; + align-items: center; + gap: 1.7cqi; + min-width: 0; + text-align: center; +} + +.stadionzeitung-gegner__club strong { + font-size: 3.2cqi; + line-height: 1.15; +} + +.stadionzeitung-gegner__club--own strong { + color: var(--clr-accent); +} + +.stadionzeitung-gegner__match { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.5cqi; + font-size: 2.5cqi; + color: var(--clr-text-muted); + white-space: nowrap; +} + +.stadionzeitung-gegner__match strong { + font-size: 2.9cqi; + color: var(--clr-text); +} + +.stadionzeitung-gegner__vergleich { + border-block: 1px solid var(--clr-glass-border); +} + +.stadionzeitung-gegner__vergleich-head, +.stadionzeitung-gegner__vergleich-row { + display: grid; + grid-template-columns: 1fr 2fr 1fr; + align-items: center; + text-align: center; +} + +.stadionzeitung-gegner__vergleich-head { + padding-block: 1.7cqi; + font-size: 2.5cqi; + font-weight: var(--fw-bold); + text-transform: uppercase; + letter-spacing: var(--ls-caps); + color: var(--clr-text-muted); +} + +.stadionzeitung-gegner__vergleich-row { + min-height: 6.5cqi; + border-top: 1px solid var(--clr-glass-border); +} + +.stadionzeitung-gegner__vergleich-row span { + font-size: 2.8cqi; + color: var(--clr-text-muted); +} + +.stadionzeitung-gegner__vergleich-row strong { + font-family: var(--ff-heading); + font-size: 4.8cqi; + line-height: 1; +} + +.stadionzeitung-gegner__vergleich-row strong:first-child { + color: var(--clr-accent); +} + +.stadionzeitung-gegner__empty { + padding: 4.2cqi; + border: 1px solid var(--clr-glass-border); + font-size: 3.3cqi; + color: var(--clr-text-muted); + text-align: center; +} + /* === stadionzeitung-vorschau (Live-Seite) === */ /* Nächstes Spiel je Mannschaft nach dem Spieltag — Meta-Zeile + Begegnung in zwei Wappen-Zeilen (dasselbe Zeilen-Muster wie der Ergebnis-Rückblick), @@ -8585,4 +8691,3 @@ body.lightbox-open { overflow: hidden; } } - diff --git a/public/assets/img/anzeigen/emons-partnerdank-1440.jpg b/public/assets/img/anzeigen/emons-partnerdank-1440.jpg new file mode 100644 index 0000000..e03c069 Binary files /dev/null and b/public/assets/img/anzeigen/emons-partnerdank-1440.jpg differ diff --git a/public/assets/img/anzeigen/emons-partnerdank-480.jpg b/public/assets/img/anzeigen/emons-partnerdank-480.jpg new file mode 100644 index 0000000..770c24e Binary files /dev/null and b/public/assets/img/anzeigen/emons-partnerdank-480.jpg differ diff --git a/public/assets/img/anzeigen/emons-partnerdank-960.jpg b/public/assets/img/anzeigen/emons-partnerdank-960.jpg new file mode 100644 index 0000000..7d0a418 Binary files /dev/null and b/public/assets/img/anzeigen/emons-partnerdank-960.jpg differ diff --git a/public/assets/img/anzeigen/gagel-pickelmann-1440.jpg b/public/assets/img/anzeigen/gagel-pickelmann-1440.jpg new file mode 100644 index 0000000..8749036 Binary files /dev/null and b/public/assets/img/anzeigen/gagel-pickelmann-1440.jpg differ diff --git a/public/assets/img/anzeigen/gagel-pickelmann-480.jpg b/public/assets/img/anzeigen/gagel-pickelmann-480.jpg new file mode 100644 index 0000000..4f10435 Binary files /dev/null and b/public/assets/img/anzeigen/gagel-pickelmann-480.jpg differ diff --git a/public/assets/img/anzeigen/gagel-pickelmann-960.jpg b/public/assets/img/anzeigen/gagel-pickelmann-960.jpg new file mode 100644 index 0000000..0bad61a Binary files /dev/null and b/public/assets/img/anzeigen/gagel-pickelmann-960.jpg differ diff --git a/public/assets/img/anzeigen/schramm-1440.jpg b/public/assets/img/anzeigen/schramm-1440.jpg new file mode 100644 index 0000000..629dca4 Binary files /dev/null and b/public/assets/img/anzeigen/schramm-1440.jpg differ diff --git a/public/assets/img/anzeigen/schramm-480.jpg b/public/assets/img/anzeigen/schramm-480.jpg new file mode 100644 index 0000000..85ec374 Binary files /dev/null and b/public/assets/img/anzeigen/schramm-480.jpg differ diff --git a/public/assets/img/anzeigen/schramm-960.jpg b/public/assets/img/anzeigen/schramm-960.jpg new file mode 100644 index 0000000..15aa789 Binary files /dev/null and b/public/assets/img/anzeigen/schramm-960.jpg differ diff --git a/public/assets/img/anzeigen/tagesskifahrt-2027-1440.jpg b/public/assets/img/anzeigen/tagesskifahrt-2027-1440.jpg new file mode 100644 index 0000000..9e36d34 Binary files /dev/null and b/public/assets/img/anzeigen/tagesskifahrt-2027-1440.jpg differ diff --git a/public/assets/img/anzeigen/tagesskifahrt-2027-480.jpg b/public/assets/img/anzeigen/tagesskifahrt-2027-480.jpg new file mode 100644 index 0000000..749cc3d Binary files /dev/null and b/public/assets/img/anzeigen/tagesskifahrt-2027-480.jpg differ diff --git a/public/assets/img/anzeigen/tagesskifahrt-2027-960.jpg b/public/assets/img/anzeigen/tagesskifahrt-2027-960.jpg new file mode 100644 index 0000000..422d58c Binary files /dev/null and b/public/assets/img/anzeigen/tagesskifahrt-2027-960.jpg differ diff --git a/public/assets/img/instagram/Db-XCrOsd4q.jpg b/public/assets/img/instagram/Db-XCrOsd4q.jpg new file mode 100644 index 0000000..de08636 Binary files /dev/null and b/public/assets/img/instagram/Db-XCrOsd4q.jpg differ diff --git a/public/assets/img/instagram/Db2ya5TDMLC.jpg b/public/assets/img/instagram/Db2ya5TDMLC.jpg new file mode 100644 index 0000000..b24092b Binary files /dev/null and b/public/assets/img/instagram/Db2ya5TDMLC.jpg differ diff --git a/public/assets/img/instagram/Dbk0vKCs-p2.jpg b/public/assets/img/instagram/Dbk0vKCs-p2.jpg new file mode 100644 index 0000000..c4e0a61 Binary files /dev/null and b/public/assets/img/instagram/Dbk0vKCs-p2.jpg differ diff --git a/public/assets/img/instagram/Dbs_SENMqBr.jpg b/public/assets/img/instagram/Dbs_SENMqBr.jpg new file mode 100644 index 0000000..e64d5ff Binary files /dev/null and b/public/assets/img/instagram/Dbs_SENMqBr.jpg differ diff --git a/public/assets/img/instagram/DcJDDkEMo0d.jpg b/public/assets/img/instagram/DcJDDkEMo0d.jpg new file mode 100644 index 0000000..33eeafa Binary files /dev/null and b/public/assets/img/instagram/DcJDDkEMo0d.jpg differ diff --git a/public/assets/img/instagram/DcPBlNMjKbP.jpg b/public/assets/img/instagram/DcPBlNMjKbP.jpg new file mode 100644 index 0000000..c8eb135 Binary files /dev/null and b/public/assets/img/instagram/DcPBlNMjKbP.jpg differ diff --git a/public/assets/img/instagram/DcQa-pwshfy.jpg b/public/assets/img/instagram/DcQa-pwshfy.jpg new file mode 100644 index 0000000..45f4de7 Binary files /dev/null and b/public/assets/img/instagram/DcQa-pwshfy.jpg differ diff --git a/public/assets/img/instagram/DcavewWMsVH.jpg b/public/assets/img/instagram/DcavewWMsVH.jpg new file mode 100644 index 0000000..31806e9 Binary files /dev/null and b/public/assets/img/instagram/DcavewWMsVH.jpg differ diff --git a/public/assets/img/instagram/DcjmUaMMJnD.jpg b/public/assets/img/instagram/DcjmUaMMJnD.jpg new file mode 100644 index 0000000..9a4c16f Binary files /dev/null and b/public/assets/img/instagram/DcjmUaMMJnD.jpg differ diff --git a/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/qr-aufruf.png b/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/qr-aufruf.png new file mode 100644 index 0000000..59387ac Binary files /dev/null and b/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/qr-aufruf.png differ diff --git a/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/qr.png b/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/qr.png new file mode 100644 index 0000000..6fe6fd7 Binary files /dev/null and b/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/qr.png differ diff --git a/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/rueckseite-1410.jpg b/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/rueckseite-1410.jpg new file mode 100644 index 0000000..3d23fc6 Binary files /dev/null and b/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/rueckseite-1410.jpg differ diff --git a/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/rueckseite-480.jpg b/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/rueckseite-480.jpg new file mode 100644 index 0000000..d042fa5 Binary files /dev/null and b/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/rueckseite-480.jpg differ diff --git a/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/rueckseite-960.jpg b/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/rueckseite-960.jpg new file mode 100644 index 0000000..a171c75 Binary files /dev/null and b/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/rueckseite-960.jpg differ diff --git a/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/spieler-1000.png b/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/spieler-1000.png new file mode 100644 index 0000000..c64c1a0 Binary files /dev/null and b/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/spieler-1000.png differ diff --git a/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/spieler-320.png b/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/spieler-320.png new file mode 100644 index 0000000..6d807e2 Binary files /dev/null and b/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/spieler-320.png differ diff --git a/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/spieler-640.png b/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/spieler-640.png new file mode 100644 index 0000000..cfcd852 Binary files /dev/null and b/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/spieler-640.png differ diff --git a/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/verfasser-120.jpg b/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/verfasser-120.jpg new file mode 100644 index 0000000..3c791cb Binary files /dev/null and b/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/verfasser-120.jpg differ diff --git a/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/verfasser-222.jpg b/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/verfasser-222.jpg new file mode 100644 index 0000000..f455616 Binary files /dev/null and b/public/assets/img/stadionzeitung/2026-08-29-asv-marktschorgast/verfasser-222.jpg differ