Stadionzeitungs-Archiv: Liste über die volle Breite statt Regal

Cover links, Angaben rechts daneben — dasselbe Muster wie .veranstaltung-card,
und aus demselben Grund: der Bestand ist klein.

Vorher war es ein horizontales Regal (grid-auto-flow: column, 280px-Spalten,
Scroll-Snap). Der Kommentar dort nannte genau die richtige Gefahr, "bei 1-3
Karten wie eine leere Fläche mit einer verlorenen Karte", löste sie aber nicht:
mit einer veröffentlichten Ausgabe stand eine 280px-Karte allein links auf einer
1280px breiten Seite. Eine Zeile über die volle Breite füllt die Fläche bei jeder
Anzahl.

Zwei Dinge sind dabei anders als bei den Veranstaltungen, beide begründet:
- Die Medienspalte ist schmaler (clamp bis 230px statt 26%), weil das Medium
  hier die live gerenderte Cover-Seite mit festem A5-Verhältnis ist. Ein <img>
  liesse sich per object-fit beschneiden, das Cover nicht — es bestimmt die
  Zeilenhöhe. 230px Cover ergeben 326px Zeile.
- Das margin-top: auto am CTA ist weg. Es stammte aus der hochformatigen Karte,
  wo der Link an den Kartenfuss gehörte; in der breiten Zeile riss es die drei
  kurzen Zeilen auf 150px auseinander.

Neu in der Zeile: die Coverzeile des Interviews als Teaser (interview.teaser,
dieselbe Quelle wie "Im Heft" auf dem Cover). Sie füllt die Breite mit echtem
Inhalt statt Leerfläche und sagt, warum man die Ausgabe öffnen sollte; ohne
Interview entfällt sie, wie .veranstaltung-card__text.

Geprüft per Screenshot bei 1280px und bei echten 390px (iframe-Wrapper, weil
headless Chrome sonst eine Mindestbreite erzwingt): mobil steht das Cover über
den Angaben.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
This commit is contained in:
2026-07-31 18:30:16 +02:00
parent e24b63147d
commit f6efdfb4b4
3 changed files with 72 additions and 25 deletions

View File

@@ -434,8 +434,13 @@ Besucher laden alle Matchcenter-Inhalte ausschließlich von unserer Domain.
## Stadionzeitung (Ausgaben-Archiv)
Digitale Fassung der Stadionzeitung zu jedem Heimspiel — Archiv-Übersicht (`/stadionzeitung`) mit
Vorschau-Karten, pro Ausgabe ein Swipe-Viewer (`/stadionzeitung/<ausgabe-slug>`, dynamische Route,
Digitale Fassung der Stadionzeitung zu jedem Heimspiel — Archiv-Übersicht (`/stadionzeitung`) als
**Liste über die volle Breite, Cover links und die Angaben rechts daneben** (dasselbe Muster wie
`.veranstaltung-card`, und aus demselben Grund: der Bestand ist klein). Vorher war das ein
horizontales Regal mit 280px-Karten; bei **einer** veröffentlichten Ausgabe stand die Karte allein
links auf einer 1280px breiten Seite (geändert 31.07.2026). Die Zeile trägt als Teaser die
**Coverzeile des Interviews** (`interview.teaser`, dieselbe Quelle wie „Im Heft" auf dem Cover) —
ohne Interview entfällt sie. Pro Ausgabe ein Swipe-Viewer (`/stadionzeitung/<ausgabe-slug>`, dynamische Route,
siehe „Architektur-Muster"). **Bewusst kein PDF auf der Website** — die Ausgabe entsteht ohnehin in
Canva, jede Seite wird dort direkt als Bild (PNG/JPG) statt als PDF exportiert. Ein PDF-Export der
Muster-Datei war ~80 MB (hochauflösende Druck-Scans) und hätte serverseitig Ghostscript/Imagick

View File

@@ -36,6 +36,14 @@ $issues = $issues ?? [];
<time datetime="<?= e($issue['date']) ?>"><?= e(german_date($issue['date'])) ?></time>
· <?= (int) $issue['pages'] ?> Seiten
</p>
<?php /* Coverzeile des Interviews als Teaser — dieselbe Quelle, die auch auf dem
Cover unter „Im Heft" steht. Sie füllt die breite Zeile mit echtem Inhalt
statt Leerfläche und sagt, warum man die Ausgabe öffnen sollte. Trägt eine
Ausgabe kein Interview, entfällt die Zeile (wie bei .veranstaltung-card__text). */
$kartenTeaser = trim((string) ($issue['interview']['teaser'] ?? '')); ?>
<?php if ($kartenTeaser !== ''): ?>
<p class="stadionzeitung-card__text"><?= e($kartenTeaser) ?></p>
<?php endif; ?>
<span class="stadionzeitung-card__cta">Ausgabe lesen <?= icon('arrow-right', 'stadionzeitung-card__arrow') ?></span>
</div>
</a>

View File

@@ -3341,44 +3341,49 @@
}
/* === stadionzeitung-cards (Ausgaben-Archiv) === */
/* Regal statt Grid: 7-10 Ausgaben pro Saison sind zu wenig für ein Raster, das
nicht bei 1-3 Karten wie eine leere Fläche mit einer verlorenen Karte
wirkt. Dasselbe Muster wie .instagram__grid (dort nur mobil, hier immer,
weil die Kartenzahl selbst auf Desktop-Breite selten eine Zeile füllt) —
angeschnittene Folgekarte als Wisch-Affordance, kein eigener JS-Code nötig
(natives Scrollen reicht, Buttons gäbe es sonst nirgends im Projekt für
dieses Muster). */
/* Liste über die volle Breite, Cover links und die Angaben rechts daneben —
dasselbe Muster wie .veranstaltung-card, und aus demselben Grund: der Bestand
ist klein (eine Handvoll Ausgaben pro Saison).
Hier stand vorher ein horizontales Regal (grid-auto-flow: column, 280px-Spalten,
Scroll-Snap). Der Kommentar dazu nannte genau die richtige Gefahr — „bei 1-3
Karten wie eine leere Fläche mit einer verlorenen Karte" — löste sie aber nicht:
mit EINER veröffentlichten Ausgabe stand eine 280px-Karte allein links auf einer
1280px breiten Seite (31.07.2026). Eine Zeile über die volle Breite füllt die
Fläche bei jeder Anzahl, von einer Ausgabe bis zwanzig.
Unterschied zu .veranstaltung-card, der die Maße erklärt: dort ist das Medium ein
<img>, das per object-fit beschnitten wird. Hier ist es die live gerenderte
Cover-Seite mit festem A5-Verhältnis — die lässt sich nicht beschneiden, sie
bestimmt die Zeilenhöhe. Die Medienspalte ist deshalb schmaler als die 26% dort:
230px Cover ergeben 326px Zeilenhöhe. */
.stadionzeitung-cards__grid {
display: grid;
grid-auto-flow: column;
grid-auto-columns: min(66vw, 280px);
gap: var(--space-l);
margin: var(--space-l) 0 0;
padding: 0 0 var(--space-2xs);
padding: 0;
list-style: none;
overflow-x: auto;
scroll-snap-type: x mandatory;
scrollbar-width: none;
}
.stadionzeitung-cards__grid::-webkit-scrollbar {
display: none;
}
.stadionzeitung-card {
display: grid;
grid-template-rows: auto 1fr;
height: 100%;
display: flex;
align-items: stretch;
color: var(--clr-text);
text-decoration: none;
background: var(--clr-glass-bg);
border: 1px solid var(--clr-glass-border);
border-radius: var(--radius-card);
overflow: hidden;
scroll-snap-align: start;
transition: transform var(--transition), box-shadow var(--transition);
}
/* clamp statt fester Breite: unter ~700px Kartenbreite wären 230px Cover mehr als
ein Drittel der Zeile und der Text bekäme zu wenig. */
.stadionzeitung-card__media {
flex: 0 0 clamp(140px, 18%, 230px);
overflow: hidden;
}
.stadionzeitung-card:hover,
.stadionzeitung-card:focus-visible {
transform: translateY(-4px);
@@ -3417,8 +3422,9 @@
.stadionzeitung-card__body {
display: flex;
flex-direction: column;
justify-content: center;
gap: var(--space-3xs);
padding: var(--space-l);
padding: var(--space-2xl);
}
.stadionzeitung-card__name {
@@ -3435,14 +3441,26 @@
color: var(--clr-text-muted);
}
/* Teaser wie .veranstaltung-card__text: Lesespalte begrenzt, damit die Zeile auf
breiten Bildschirmen nicht über die halbe Seite läuft. */
.stadionzeitung-card__text {
max-width: 60ch;
margin-top: var(--space-2xs);
color: var(--clr-text-muted);
}
.stadionzeitung-card__cta {
display: inline-flex;
align-items: center;
gap: var(--space-2xs);
margin-top: auto;
padding-top: var(--space-s);
font-size: var(--fs-500);
color: var(--clr-accent);
/* KEIN margin-top: auto. Das stammte aus der hochformatigen Karte, wo der
Link an den Kartenfuß gehörte. In der breiten Zeile riss es die drei
kurzen Zeilen auseinander: Titel oben, Link unten, dazwischen 150px
Leere. Jetzt stehen sie als Gruppe zusammen, mittig zur Cover-Höhe
(justify-content: center am __body). */
}
.stadionzeitung-card__arrow {
@@ -3453,6 +3471,22 @@
transform: translateX(3px);
}
@media (max-width: 768px) {
/* Am Handy steht das Cover über den Angaben — nebeneinander bliebe für keines
von beidem genug Breite. Gleiche Entscheidung wie bei .veranstaltung-card. */
.stadionzeitung-card {
flex-direction: column;
}
.stadionzeitung-card__media {
flex: none;
}
.stadionzeitung-card__body {
padding: var(--space-l);
}
}
/* === team-roster (Kader + Trainerstab) === */
.team-roster > .container {
text-align: center;