2026-06-19 10:33:03 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Turn-Disziplin im einheitlichen Bento-Look (wie die Mannschaftsseiten). Props:
|
|
|
|
|
* $location array{venue, street?, zip?, city?} (optional) — Trainingsort + „Route planen"
|
„Trainerteam" statt „Übungsleitung", Eva Wünsch mit Sternchen
Eva Wünsch aus der Turnabteilung am 31.07.2026: „Der Sternchentext müsste
eigentlich sein, dass die Person mit dem Sternchen Übungsleiter ist. Von daher
müsste vor den Namen 'Trainerteam' stehen. Einige sind auch nicht ÜL."
Ich hatte davon nur die Fußnote erledigt. Das Label blieb „Übungsleitung" und
damit stand die falsche Aussage weiter auf der Seite: neun namentlich genannte
Personen liefen unter „Übungsleitung", vier davon sind es. Das ist keine
Formulierungsfrage, die Seite behauptete etwas über echte Menschen.
Label jetzt „Trainerteam:" an beiden Stellen (Trainingszeit und Gruppe), der
Stern bleibt die Auszeichnung und die Fußnote erklärt ihn. So stand es auch auf
der alten Seite: „TRAINERTEAM (* = ÜBUNGSLEITER)". Ein Kommentar an der Stelle
sagt, warum es nicht zurückbenannt werden darf.
Dabei fiel ein zweiter Datenfehler auf: die alte Seite führt „Annelie Frisque*,
Eva Wünsch*", bei uns stand Eva Wünsch ohne Stern. Sie ist Übungsleiterin.
Geprüft: „Übungsleitung" kommt auf keiner der sechs Turn-Seiten mehr vor, die
Grashüpfer-Zeile lautet jetzt Zeichen für Zeichen wie in Evas Screenshot. Die
Fußnote erscheint nur in Sektionen mit mehreren Gruppen — nachgezählt, dass
beide Disziplinen mit Sternchen-Namen mehrere Gruppen haben, die
Einzelgruppen-Disziplinen tragen keine Sterne.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
2026-07-31 22:57:31 +02:00
|
|
|
* $lead string (optional) — Ansprechperson der Disziplin (Akzent-Kachel)
|
2026-06-19 10:33:03 +02:00
|
|
|
* $notice string (optional) — hervorgehobener Hinweis (z. B. Wartelisten-Status)
|
Trampolin: Schnupper-Einladung, Hinweise bekommen zwei Tonlagen
Info von Eva aus der Trampolin-Gruppe: neue Kinder können ab September
(Schulbeginn) gerne schnuppern kommen. Die Info stand nirgends.
Rot wäre dafür falsch gewesen. Die Farbe bekommt deshalb eine Bedeutung:
--stop (gefüllt rot) heißt „geht nicht", --info (Glas-Fläche, Rot nur im Icon)
heißt „geht". Eine Einladung in Alarmrot liest sich wie eine Absage, und wenn
alles rot ist, stumpft Rot ab und der echte Wartelisten-Stopp bei „Tiger" und
„Hühner" verliert seine Wirkung. --info ist ab jetzt der Default.
Damit steht der Hinweis an drei Stellen, also greift die Bedingung aus dem
letzten Commit („kommt ein dritter Ort dazu, gehören die gemeinsamen
Eigenschaften in eine geteilte Klasse"): neu app/components/notice.php als
einzige Render-Stelle statt dreimal dasselbe Markup. Die beiden bestehenden
Klassen schrumpfen auf das, was sie wirklich beitragen —
.turnen-dash__notice nur noch grid-area, .contact__notice nur noch die
Formularbreite. Die tote .turnen-dash__notice-icon-Regel ist raus, der
CSS-Abschnitt neu sortiert (notice als eigener Block hinter turnen-dash statt
mitten hinein).
Text, Tonlage und Icon stehen wie gehabt in data/turnen.json bei der
Disziplin, nicht im Template. Kinderturnen trägt jetzt explizit
notice_tone: stop, Trampolin nichts und ist damit neutral.
Das Grid-Template für --notice + --single gab es schon, an beiden
Breakpoints — die Trampolin-Seite hat eine Gruppe und wäre sonst
auseinandergefallen.
Gemessen bei 390px: kein Überlauf auf allen drei Seiten, Trampolin-Fläche
rgba(0,0,0,0.22) (Glas), die beiden anderen #e20612. Zwölf Seiten geprüft,
alle 200. preflight ohne neue Meldungen.
OFFEN, mit Eva oder Tina zu klären: der zweite Satz („Schreib uns davor
einfach kurz eine Nachricht") ist von mir, Eva hat ihn nicht gesagt. Wenn die
Kinder einfach zum Training kommen dürfen, gehört er weg. Und die Einladung
steht bisher nur auf /turnen/trampolin, nicht auf der Übersicht /turnen.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
2026-07-31 22:04:41 +02:00
|
|
|
* $noticeTitle string (optional) — Überschrift dazu
|
|
|
|
|
* $noticeTone 'info' (Default) | 'stop' — Tonlage, siehe components/notice.php
|
|
|
|
|
* $noticeIcon string (optional) — Icon-Name, siehe components/notice.php
|
|
|
|
|
* Gerendert wird über component('notice') — dieselbe Komponente, die
|
|
|
|
|
* contact-form.php über dem Formular benutzt, damit derselbe Hinweis an
|
|
|
|
|
* beiden Orten gleich aussieht und nur EINMAL in data/turnen.json steht.
|
2026-06-19 10:33:03 +02:00
|
|
|
* $groups array von Gruppen:
|
Flamingos zum Wettkampfturnen, Inhalte gegen die alte Seite abgeglichen
Die Flamingos sind organisatorisch vom Kinderturnen zum Wettkampfturnen
gewechselt. Felix hat dazu die Fassung geschickt, die die Turnabteilung selbst
auf der alten Seite gepflegt hatte — dabei kamen sieben Abweichungen heraus,
alle korrigiert:
- Die zweite Gruppe heißt "Leistungsturnen", nicht "Wettkampfturnen" (so hieß
bei uns die Gruppe wie die Disziplin).
- Reihenfolge: Flamingos zuerst, Leistungsturnen danach.
- Den Flamingos fehlte eine Trainingszeit: Montag gibt es ZWEI Blöcke
(18:00–19:00 und 19:00–20:00), wir hatten nur den ersten.
- Ansprechpersonen sind pro Gruppe verschieden (Flamingos: Theresa Diener,
Leistungsturnen: Franziska Trotzke). Dafür ist `contact` neu an einer Gruppe.
Die Kontakt-Kachel oben kann nur EINE Person nennen und wäre für die andere
Gruppe falsch — deshalb ist `lead` bei dieser Disziplin jetzt leer, die Kachel
trägt nur noch die Abteilungs-Mail. So war es auf der alten Seite auch: dort
gab es keine Ansprechperson für die Disziplin, nur je Gruppe.
- Theresa Diener steht im Trainerteam vorn und ohne Stern (bei uns hinten).
- Intro, Trainingsinhalte, Wettkämpfe und der Hinweis waren gekürzt; jetzt im
Wortlaut der Abteilung. Den Gedankenstrich in "(Kür modifiziert –
Leistungsklasse 3)" ersetzt ein Komma (Sprache & Ton).
- Die Fußnote sagte "* So im Trainingsplan der Abteilung gekennzeichnet" — eine
Verlegenheitsformulierung, weil wir die Bedeutung nicht kannten. Die alte
Seite schreibt "* = ÜBUNGSLEITER", also jetzt "* Übungsleiterinnen und
Übungsleiter" (Paarform, Haus-Stil).
`level` bleibt "Turnen · fortgeschritten" ohne "Alter nach Absprache" — das
hatte Felix am 31.07.2026 ausdrücklich aus dem Chip genommen.
Zwei Folgen, die sonst still kaputtgegangen wären: die Seite hatte eine einzige
Gruppe ohne Beschreibung und lief damit im Einzelgruppen-Layout. Mit zwei
Gruppen, davon eine mit Beschreibung, rendert group-schedule eine Tab-Leiste —
die braucht group-tabs.js, das die Seite nicht lud (tote Tab-Knöpfe). Und drei
Flamingos-Trainerinnen tragen ein Sternchen, die erklärende Fußnote wurde auf
dieser Seite nicht übergeben (drei unerklärte Sterne).
Geprüft: Tabs "Flamingos" und "Leistungsturnen", Skript geladen, Fußnote da,
Flamingos auf /turnen/eltern-kind-turnen nicht mehr erwähnt, kein Überlauf bei
390px, alle sechs Turn-Seiten 200.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
2026-07-31 22:40:25 +02:00
|
|
|
* { name, level?, contact?, intro?, details?:[{heading,text}], recommendation?,
|
|
|
|
|
* note?, trainers?:[…], sessions:[{ label?, day, time, note?, trainers?:[…] }] }
|
|
|
|
|
* contact = Ansprechperson NUR dieser Gruppe. Braucht es, sobald eine Disziplin
|
|
|
|
|
* mehrere Gruppen mit verschiedenen Ansprechpersonen hat (Wettkampfturnen:
|
|
|
|
|
* Flamingos → Theresa Diener, Leistungsturnen → Franziska Trotzke) — die
|
|
|
|
|
* Kontakt-Kachel oben kann nur EINE nennen und wäre für die andere falsch.
|
|
|
|
|
* Beschriftet als „Kontakt" wie die Kachel, nicht als „Ansprechpartner":
|
|
|
|
|
* das Label kennt das Geschlecht der Person nicht (Haus-Stil Paarformen).
|
2026-06-19 10:33:03 +02:00
|
|
|
* $footnote string (optional) — Erläuterung (z. B. zur Sternchen-Kennzeichnung)
|
|
|
|
|
* $groupsTitle string (optional, Default 'Unsere Gruppen')
|
Wettkampfturnen: Karten offen untereinander statt hinter Tabs
Bei zwei Gruppen verstecken Tabs mehr Inhalt als sie ordnen, und die offene
Kartenreihe hält den Bento-Eindruck der Seite (Entscheidung Felix). Das
Kinderturnen bleibt bei Tabs, dort sind es drei textreiche Gruppen — die
Flamingos-Karte allein ist am Handy 2142px hoch.
.group-list--stacked lag vollständig im CSS, wurde aber von KEINEM PHP
ausgegeben: totes CSS aus der Zeit vor den Tabs, das heute morgen sogar noch
meine minmax(0, …)-Korrektur mitbekommen hat, ohne dass es jemand sehen konnte.
Jetzt ist es lebendig. Dritter toter Rest heute: "layout": "blocks" in
data/turnen.json las ebenfalls niemand, ist raus.
Der Karteninhalt steht dafür jetzt einmal statt zweimal. Er wird in zwei
Fassungen gebraucht (Tab-Panel mit role/aria und gestapelt ohne) und ist
deshalb eine Closure geworden — eine zweite Kopie wäre die Stelle, an der beide
in einem halben Jahr auseinanderlaufen.
Die Überschrift ist visually-hidden, nicht entfernt: sonst hätte die Sektion
keinen zugänglichen Namen und die Überschriften-Gliederung eine Lücke. Dasselbe
Muster wie $title_hidden in team-cards. Damit braucht die Seite auch kein
group-tabs.js mehr, das ich zwei Commits vorher erst dazugeschrieben hatte.
Zwei Nachbesserungen, beide gemessen:
- Die versteckte Überschrift hinterließ ein Loch. Zwischen Dashboard und erster
Karte standen 160px (80 unten von der einen Sektion, 80 oben von der anderen),
in denen nur nackte Hintergrund-Textur zu sehen war — vorher füllte die
Überschrift diesen Raum. .group-list-section--tight nimmt das obere Padding
weg, jetzt 80px.
- Die gestapelten Karten hatten feste 40px Innenabstand; auf --pad-card-lg
umgestellt, dieselbe Korrektur wie heute morgen beim Tab-Panel. Am Desktop
unverändert 40px, am Handy 28px.
Nicht behoben, weil kein Fehler: die Hintergrund-Textur wirkt in leeren Flächen
weich. Sie ist 1920x2545 groß und wird bei 1478px Fensterbreite auf Faktor 0,77
VERKLEINERT, ist also nicht unscharf gerechnet. Sichtbar wurde sie durch den
Leerraum plus background-attachment: fixed, das sie beim Scrollen stehen lässt.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
2026-07-31 22:56:21 +02:00
|
|
|
* $groupsTitleHidden bool (optional) — H2 bleibt im DOM (Dokumentgliederung für
|
|
|
|
|
* Screenreader, Sektion behält ihren Namen), ist aber visuell versteckt.
|
|
|
|
|
* Dasselbe Muster wie $title_hidden in team-cards. NICHT die Überschrift
|
|
|
|
|
* weglassen: dann hätte die Sektion keinen zugänglichen Namen mehr.
|
|
|
|
|
* $layout 'tabs' (Default) | 'stacked' — greift nur bei beschreibenden Gruppen.
|
|
|
|
|
* 'stacked' zeigt alle Karten offen untereinander (wenige Gruppen),
|
|
|
|
|
* 'tabs' ordnet viele textreiche Gruppen (Kinderturnen).
|
2026-06-19 10:33:03 +02:00
|
|
|
* $anchor string (optional, Default 'training')
|
|
|
|
|
*
|
|
|
|
|
* Eine Gruppe → Trainingszeiten landen als Bento-Kachel im Dashboard.
|
|
|
|
|
* Mehrere → Dashboard zeigt nur Ort/Verantwortlich, darunter eine Gruppen-Sektion.
|
|
|
|
|
* Gruppen mit Beschreibung werden gestapelt, schlichte Gruppen als Raster.
|
|
|
|
|
*/
|
|
|
|
|
$anchor = $anchor ?? 'training';
|
|
|
|
|
$groupsTitle = $groupsTitle ?? 'Unsere Gruppen';
|
Wettkampfturnen: Karten offen untereinander statt hinter Tabs
Bei zwei Gruppen verstecken Tabs mehr Inhalt als sie ordnen, und die offene
Kartenreihe hält den Bento-Eindruck der Seite (Entscheidung Felix). Das
Kinderturnen bleibt bei Tabs, dort sind es drei textreiche Gruppen — die
Flamingos-Karte allein ist am Handy 2142px hoch.
.group-list--stacked lag vollständig im CSS, wurde aber von KEINEM PHP
ausgegeben: totes CSS aus der Zeit vor den Tabs, das heute morgen sogar noch
meine minmax(0, …)-Korrektur mitbekommen hat, ohne dass es jemand sehen konnte.
Jetzt ist es lebendig. Dritter toter Rest heute: "layout": "blocks" in
data/turnen.json las ebenfalls niemand, ist raus.
Der Karteninhalt steht dafür jetzt einmal statt zweimal. Er wird in zwei
Fassungen gebraucht (Tab-Panel mit role/aria und gestapelt ohne) und ist
deshalb eine Closure geworden — eine zweite Kopie wäre die Stelle, an der beide
in einem halben Jahr auseinanderlaufen.
Die Überschrift ist visually-hidden, nicht entfernt: sonst hätte die Sektion
keinen zugänglichen Namen und die Überschriften-Gliederung eine Lücke. Dasselbe
Muster wie $title_hidden in team-cards. Damit braucht die Seite auch kein
group-tabs.js mehr, das ich zwei Commits vorher erst dazugeschrieben hatte.
Zwei Nachbesserungen, beide gemessen:
- Die versteckte Überschrift hinterließ ein Loch. Zwischen Dashboard und erster
Karte standen 160px (80 unten von der einen Sektion, 80 oben von der anderen),
in denen nur nackte Hintergrund-Textur zu sehen war — vorher füllte die
Überschrift diesen Raum. .group-list-section--tight nimmt das obere Padding
weg, jetzt 80px.
- Die gestapelten Karten hatten feste 40px Innenabstand; auf --pad-card-lg
umgestellt, dieselbe Korrektur wie heute morgen beim Tab-Panel. Am Desktop
unverändert 40px, am Handy 28px.
Nicht behoben, weil kein Fehler: die Hintergrund-Textur wirkt in leeren Flächen
weich. Sie ist 1920x2545 groß und wird bei 1478px Fensterbreite auf Faktor 0,77
VERKLEINERT, ist also nicht unscharf gerechnet. Sichtbar wurde sie durch den
Leerraum plus background-attachment: fixed, das sie beim Scrollen stehen lässt.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
2026-07-31 22:56:21 +02:00
|
|
|
$groupsTitleHidden = $groupsTitleHidden ?? false;
|
|
|
|
|
$layout = ($layout ?? 'tabs') === 'stacked' ? 'stacked' : 'tabs';
|
2026-06-19 10:33:03 +02:00
|
|
|
$lead = $lead ?? '';
|
|
|
|
|
$notice = $notice ?? '';
|
Wartelisten-Hinweis für Tiger und Hühner, über dem Anfrageformular
Die Turnabteilung (Maxi) beantwortet laufend Anfragen nach einem Wartelistenplatz
für „Tiger" und „Hühner", den es nicht gibt. Auf der alten Seite stand der Hinweis
direkt über dem Anfrageformular, hier fehlte er.
Schlimmer: an der Stelle stand das GEGENTEIL. Der bisherige Hinweis lautete
"Aktuell sind alle Kinderturngruppen belegt. Bei Interesse setzen wir sie gerne
auf die Warteliste." — für alle Kindergruppen, also auch für die beiden, die
keine Liste führen. Der Satz hat einen Teil der Anfragen vermutlich erst erzeugt.
Er ist nicht gelöscht, sondern auf die übrigen Gruppen eingegrenzt und aufs Du
umgestellt (Haus-Stil; vorher stand dort klein "sie").
Der Text steht genau EINMAL, in data/turnen.json unter
disciplines.eltern-kind-turnen.notice + notice_title. Zwei Stellen lesen ihn:
die rote Kachel auf /turnen/eltern-kind-turnen (gab es schon) und neu ein Block
direkt über dem Formular auf /turnen. Ändert die Abteilung die Lage, ist das eine
Zeile in einer Datei.
Umsetzung:
- notice_title ist neu, weil eine rote Fläche ohne Überschrift wie eine
Fehlermeldung liest. Abel statt Coolvetica, der Schnitt ist bei ~19px in
Versalien unleserlich (CLAUDE.md, Design).
- Der Block steht AUSSERHALB des <form> und damit außerhalb der
role="status"-Region: ein dauerhafter Hinweis, keine Rückmeldung zum Absenden.
In der Live-Region läse ihn ein Screenreader bei jeder Formularmeldung erneut
vor. Kein role="alert", er steht schon beim Laden da.
- Überschrift als h3 unter der h2 des Intro-Blocks, damit die Folge nicht springt.
- .contact__notice übernimmt bewusst die Optik von .turnen-dash__notice, damit
beide Stellen als derselbe Hinweis erkennbar sind. Weiß auf --clr-accent
erreicht 4,92:1 und trägt damit Fließtext (WCAG 1.4.3). Kommt ein dritter Ort
dazu, gehören die gemeinsamen Eigenschaften in eine geteilte .notice-Klasse;
für zwei wäre das verfrüht.
Gemessen: Hinweisbreite gleich Formularbreite (720px bei 1280, 347px bei 390),
kein Überlauf. preflight ohne neue Meldungen.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
2026-07-31 21:54:10 +02:00
|
|
|
$noticeTitle = $noticeTitle ?? '';
|
Trampolin: Schnupper-Einladung, Hinweise bekommen zwei Tonlagen
Info von Eva aus der Trampolin-Gruppe: neue Kinder können ab September
(Schulbeginn) gerne schnuppern kommen. Die Info stand nirgends.
Rot wäre dafür falsch gewesen. Die Farbe bekommt deshalb eine Bedeutung:
--stop (gefüllt rot) heißt „geht nicht", --info (Glas-Fläche, Rot nur im Icon)
heißt „geht". Eine Einladung in Alarmrot liest sich wie eine Absage, und wenn
alles rot ist, stumpft Rot ab und der echte Wartelisten-Stopp bei „Tiger" und
„Hühner" verliert seine Wirkung. --info ist ab jetzt der Default.
Damit steht der Hinweis an drei Stellen, also greift die Bedingung aus dem
letzten Commit („kommt ein dritter Ort dazu, gehören die gemeinsamen
Eigenschaften in eine geteilte Klasse"): neu app/components/notice.php als
einzige Render-Stelle statt dreimal dasselbe Markup. Die beiden bestehenden
Klassen schrumpfen auf das, was sie wirklich beitragen —
.turnen-dash__notice nur noch grid-area, .contact__notice nur noch die
Formularbreite. Die tote .turnen-dash__notice-icon-Regel ist raus, der
CSS-Abschnitt neu sortiert (notice als eigener Block hinter turnen-dash statt
mitten hinein).
Text, Tonlage und Icon stehen wie gehabt in data/turnen.json bei der
Disziplin, nicht im Template. Kinderturnen trägt jetzt explizit
notice_tone: stop, Trampolin nichts und ist damit neutral.
Das Grid-Template für --notice + --single gab es schon, an beiden
Breakpoints — die Trampolin-Seite hat eine Gruppe und wäre sonst
auseinandergefallen.
Gemessen bei 390px: kein Überlauf auf allen drei Seiten, Trampolin-Fläche
rgba(0,0,0,0.22) (Glas), die beiden anderen #e20612. Zwölf Seiten geprüft,
alle 200. preflight ohne neue Meldungen.
OFFEN, mit Eva oder Tina zu klären: der zweite Satz („Schreib uns davor
einfach kurz eine Nachricht") ist von mir, Eva hat ihn nicht gesagt. Wenn die
Kinder einfach zum Training kommen dürfen, gehört er weg. Und die Einladung
steht bisher nur auf /turnen/trampolin, nicht auf der Übersicht /turnen.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
2026-07-31 22:04:41 +02:00
|
|
|
$noticeTone = $noticeTone ?? 'info';
|
|
|
|
|
$noticeIcon = $noticeIcon ?? 'info-circle';
|
2026-06-19 10:33:03 +02:00
|
|
|
$footnote = $footnote ?? '';
|
|
|
|
|
$groups = $groups ?? [];
|
|
|
|
|
$location = $location ?? [];
|
|
|
|
|
|
|
|
|
|
if ($groups === []) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$club = json_load('club');
|
|
|
|
|
$email = $club['email_turnen'] ?? ($club['email'] ?? '');
|
|
|
|
|
|
|
|
|
|
$single = count($groups) === 1;
|
|
|
|
|
$rich = false;
|
|
|
|
|
foreach ($groups as $g) {
|
|
|
|
|
if (!empty($g['intro']) || !empty($g['details'])) {
|
|
|
|
|
$rich = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$hasVenue = !empty($location['venue']);
|
|
|
|
|
$mapsQuery = $hasVenue ? rawurlencode(trim(
|
|
|
|
|
($location['venue'] ?? '') . ', '
|
|
|
|
|
. ($location['street'] ?? '') . ', '
|
|
|
|
|
. ($location['zip'] ?? '') . ' ' . ($location['city'] ?? ''),
|
|
|
|
|
', '
|
|
|
|
|
)) : '';
|
|
|
|
|
|
„Trainerteam" statt „Übungsleitung", Eva Wünsch mit Sternchen
Eva Wünsch aus der Turnabteilung am 31.07.2026: „Der Sternchentext müsste
eigentlich sein, dass die Person mit dem Sternchen Übungsleiter ist. Von daher
müsste vor den Namen 'Trainerteam' stehen. Einige sind auch nicht ÜL."
Ich hatte davon nur die Fußnote erledigt. Das Label blieb „Übungsleitung" und
damit stand die falsche Aussage weiter auf der Seite: neun namentlich genannte
Personen liefen unter „Übungsleitung", vier davon sind es. Das ist keine
Formulierungsfrage, die Seite behauptete etwas über echte Menschen.
Label jetzt „Trainerteam:" an beiden Stellen (Trainingszeit und Gruppe), der
Stern bleibt die Auszeichnung und die Fußnote erklärt ihn. So stand es auch auf
der alten Seite: „TRAINERTEAM (* = ÜBUNGSLEITER)". Ein Kommentar an der Stelle
sagt, warum es nicht zurückbenannt werden darf.
Dabei fiel ein zweiter Datenfehler auf: die alte Seite führt „Annelie Frisque*,
Eva Wünsch*", bei uns stand Eva Wünsch ohne Stern. Sie ist Übungsleiterin.
Geprüft: „Übungsleitung" kommt auf keiner der sechs Turn-Seiten mehr vor, die
Grashüpfer-Zeile lautet jetzt Zeichen für Zeichen wie in Evas Screenshot. Die
Fußnote erscheint nur in Sektionen mit mehreren Gruppen — nachgezählt, dass
beide Disziplinen mit Sternchen-Namen mehrere Gruppen haben, die
Einzelgruppen-Disziplinen tragen keine Sterne.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
2026-07-31 22:57:31 +02:00
|
|
|
/**
|
|
|
|
|
* Eine Trainingszeit (Tag/Zeit + optional Label, Notiz, Trainerteam) ausgeben.
|
|
|
|
|
*
|
|
|
|
|
* Das Label heißt „Trainerteam", nicht „Übungsleitung": in der Liste stehen auch
|
|
|
|
|
* Personen, die KEINE Übungsleitung sind (Eva Wünsch aus der Abteilung, 31.07.2026).
|
|
|
|
|
* Wer eine ist, trägt ein Sternchen, und das erklärt die Fußnote der Sektion. Die alte
|
|
|
|
|
* Seite schrieb dafür „TRAINERTEAM (* = ÜBUNGSLEITER)". Nicht zurückbenennen.
|
|
|
|
|
*/
|
2026-06-19 10:33:03 +02:00
|
|
|
$renderSession = static function (array $s): void {
|
|
|
|
|
?>
|
|
|
|
|
<li class="schedule-row">
|
|
|
|
|
<?php if (!empty($s['label'])): ?>
|
|
|
|
|
<span class="schedule-row__label"><?= e($s['label']) ?></span>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
<span class="schedule-row__when">
|
|
|
|
|
<span class="schedule-row__day"><?= e($s['day']) ?></span>
|
|
|
|
|
<span class="schedule-row__time"><?= e($s['time']) ?></span>
|
|
|
|
|
</span>
|
|
|
|
|
<?php if (!empty($s['note'])): ?>
|
|
|
|
|
<span class="schedule-row__note text-muted"><?= e($s['note']) ?></span>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
<?php if (!empty($s['trainers'])): ?>
|
„Trainerteam" statt „Übungsleitung", Eva Wünsch mit Sternchen
Eva Wünsch aus der Turnabteilung am 31.07.2026: „Der Sternchentext müsste
eigentlich sein, dass die Person mit dem Sternchen Übungsleiter ist. Von daher
müsste vor den Namen 'Trainerteam' stehen. Einige sind auch nicht ÜL."
Ich hatte davon nur die Fußnote erledigt. Das Label blieb „Übungsleitung" und
damit stand die falsche Aussage weiter auf der Seite: neun namentlich genannte
Personen liefen unter „Übungsleitung", vier davon sind es. Das ist keine
Formulierungsfrage, die Seite behauptete etwas über echte Menschen.
Label jetzt „Trainerteam:" an beiden Stellen (Trainingszeit und Gruppe), der
Stern bleibt die Auszeichnung und die Fußnote erklärt ihn. So stand es auch auf
der alten Seite: „TRAINERTEAM (* = ÜBUNGSLEITER)". Ein Kommentar an der Stelle
sagt, warum es nicht zurückbenannt werden darf.
Dabei fiel ein zweiter Datenfehler auf: die alte Seite führt „Annelie Frisque*,
Eva Wünsch*", bei uns stand Eva Wünsch ohne Stern. Sie ist Übungsleiterin.
Geprüft: „Übungsleitung" kommt auf keiner der sechs Turn-Seiten mehr vor, die
Grashüpfer-Zeile lautet jetzt Zeichen für Zeichen wie in Evas Screenshot. Die
Fußnote erscheint nur in Sektionen mit mehreren Gruppen — nachgezählt, dass
beide Disziplinen mit Sternchen-Namen mehrere Gruppen haben, die
Einzelgruppen-Disziplinen tragen keine Sterne.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
2026-07-31 22:57:31 +02:00
|
|
|
<span class="schedule-row__trainers"><span class="schedule-row__trainers-label">Trainerteam:</span> <?= e(implode(', ', $s['trainers'])) ?></span>
|
2026-06-19 10:33:03 +02:00
|
|
|
<?php endif; ?>
|
|
|
|
|
</li>
|
|
|
|
|
<?php
|
|
|
|
|
};
|
|
|
|
|
|
Wettkampfturnen: Karten offen untereinander statt hinter Tabs
Bei zwei Gruppen verstecken Tabs mehr Inhalt als sie ordnen, und die offene
Kartenreihe hält den Bento-Eindruck der Seite (Entscheidung Felix). Das
Kinderturnen bleibt bei Tabs, dort sind es drei textreiche Gruppen — die
Flamingos-Karte allein ist am Handy 2142px hoch.
.group-list--stacked lag vollständig im CSS, wurde aber von KEINEM PHP
ausgegeben: totes CSS aus der Zeit vor den Tabs, das heute morgen sogar noch
meine minmax(0, …)-Korrektur mitbekommen hat, ohne dass es jemand sehen konnte.
Jetzt ist es lebendig. Dritter toter Rest heute: "layout": "blocks" in
data/turnen.json las ebenfalls niemand, ist raus.
Der Karteninhalt steht dafür jetzt einmal statt zweimal. Er wird in zwei
Fassungen gebraucht (Tab-Panel mit role/aria und gestapelt ohne) und ist
deshalb eine Closure geworden — eine zweite Kopie wäre die Stelle, an der beide
in einem halben Jahr auseinanderlaufen.
Die Überschrift ist visually-hidden, nicht entfernt: sonst hätte die Sektion
keinen zugänglichen Namen und die Überschriften-Gliederung eine Lücke. Dasselbe
Muster wie $title_hidden in team-cards. Damit braucht die Seite auch kein
group-tabs.js mehr, das ich zwei Commits vorher erst dazugeschrieben hatte.
Zwei Nachbesserungen, beide gemessen:
- Die versteckte Überschrift hinterließ ein Loch. Zwischen Dashboard und erster
Karte standen 160px (80 unten von der einen Sektion, 80 oben von der anderen),
in denen nur nackte Hintergrund-Textur zu sehen war — vorher füllte die
Überschrift diesen Raum. .group-list-section--tight nimmt das obere Padding
weg, jetzt 80px.
- Die gestapelten Karten hatten feste 40px Innenabstand; auf --pad-card-lg
umgestellt, dieselbe Korrektur wie heute morgen beim Tab-Panel. Am Desktop
unverändert 40px, am Handy 28px.
Nicht behoben, weil kein Fehler: die Hintergrund-Textur wirkt in leeren Flächen
weich. Sie ist 1920x2545 groß und wird bei 1478px Fensterbreite auf Faktor 0,77
VERKLEINERT, ist also nicht unscharf gerechnet. Sichtbar wurde sie durch den
Leerraum plus background-attachment: fixed, das sie beim Scrollen stehen lässt.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
2026-07-31 22:56:21 +02:00
|
|
|
/**
|
|
|
|
|
* Inhalt einer beschreibenden Gruppen-Karte (ohne das <article> drumherum). Als Closure,
|
|
|
|
|
* weil es diese Karte in zwei Fassungen gibt: als Tab-Panel (mit role/aria) und gestapelt
|
|
|
|
|
* (ohne). Vorher stand das Markup nur in der Tab-Fassung; eine zweite Kopie daneben wäre
|
|
|
|
|
* die Stelle, an der beide auseinanderlaufen.
|
|
|
|
|
*/
|
|
|
|
|
$renderCardBody = static function (array $g) use ($renderSession): void {
|
|
|
|
|
?>
|
|
|
|
|
<div class="group-card__body">
|
|
|
|
|
<div class="group-card__header">
|
|
|
|
|
<h3 class="group-card__name"><?= e($g['name']) ?></h3>
|
|
|
|
|
<?php if (!empty($g['level'])): ?>
|
|
|
|
|
<p class="group-card__level"><?= e($g['level']) ?></p>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
</div>
|
|
|
|
|
<?php if (!empty($g['intro'])): ?>
|
|
|
|
|
<p class="group-card__intro"><?= e($g['intro']) ?></p>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
<?php foreach ($g['details'] ?? [] as $det): ?>
|
|
|
|
|
<?php if (!empty($det['heading'])): ?>
|
|
|
|
|
<h4 class="group-card__detail-heading"><?= e($det['heading']) ?></h4>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
<?php if (!empty($det['text'])): ?>
|
|
|
|
|
<p class="group-card__detail-text"><?= e($det['text']) ?></p>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
<?php endforeach; ?>
|
|
|
|
|
<?php if (!empty($g['recommendation'])): ?>
|
|
|
|
|
<p class="group-card__recommendation text-muted"><?= e($g['recommendation']) ?></p>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
</div>
|
|
|
|
|
<?php if (!empty($g['sessions'])): ?>
|
|
|
|
|
<div class="group-card__schedule">
|
|
|
|
|
<p class="group-card__schedule-title"><?= icon('clock', 'group-card__schedule-icon') ?>Trainingszeiten</p>
|
|
|
|
|
<ul class="schedule-list">
|
|
|
|
|
<?php foreach ($g['sessions'] as $s): $renderSession($s); endforeach; ?>
|
|
|
|
|
</ul>
|
|
|
|
|
<?php if (!empty($g['contact'])): ?>
|
|
|
|
|
<p class="group-card__trainers"><span class="schedule-row__trainers-label">Kontakt:</span> <?= e($g['contact']) ?></p>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
<?php if (!empty($g['trainers'])): ?>
|
„Trainerteam" statt „Übungsleitung", Eva Wünsch mit Sternchen
Eva Wünsch aus der Turnabteilung am 31.07.2026: „Der Sternchentext müsste
eigentlich sein, dass die Person mit dem Sternchen Übungsleiter ist. Von daher
müsste vor den Namen 'Trainerteam' stehen. Einige sind auch nicht ÜL."
Ich hatte davon nur die Fußnote erledigt. Das Label blieb „Übungsleitung" und
damit stand die falsche Aussage weiter auf der Seite: neun namentlich genannte
Personen liefen unter „Übungsleitung", vier davon sind es. Das ist keine
Formulierungsfrage, die Seite behauptete etwas über echte Menschen.
Label jetzt „Trainerteam:" an beiden Stellen (Trainingszeit und Gruppe), der
Stern bleibt die Auszeichnung und die Fußnote erklärt ihn. So stand es auch auf
der alten Seite: „TRAINERTEAM (* = ÜBUNGSLEITER)". Ein Kommentar an der Stelle
sagt, warum es nicht zurückbenannt werden darf.
Dabei fiel ein zweiter Datenfehler auf: die alte Seite führt „Annelie Frisque*,
Eva Wünsch*", bei uns stand Eva Wünsch ohne Stern. Sie ist Übungsleiterin.
Geprüft: „Übungsleitung" kommt auf keiner der sechs Turn-Seiten mehr vor, die
Grashüpfer-Zeile lautet jetzt Zeichen für Zeichen wie in Evas Screenshot. Die
Fußnote erscheint nur in Sektionen mit mehreren Gruppen — nachgezählt, dass
beide Disziplinen mit Sternchen-Namen mehrere Gruppen haben, die
Einzelgruppen-Disziplinen tragen keine Sterne.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
2026-07-31 22:57:31 +02:00
|
|
|
<p class="group-card__trainers"><span class="schedule-row__trainers-label">Trainerteam:</span> <?= e(implode(', ', $g['trainers'])) ?></p>
|
Wettkampfturnen: Karten offen untereinander statt hinter Tabs
Bei zwei Gruppen verstecken Tabs mehr Inhalt als sie ordnen, und die offene
Kartenreihe hält den Bento-Eindruck der Seite (Entscheidung Felix). Das
Kinderturnen bleibt bei Tabs, dort sind es drei textreiche Gruppen — die
Flamingos-Karte allein ist am Handy 2142px hoch.
.group-list--stacked lag vollständig im CSS, wurde aber von KEINEM PHP
ausgegeben: totes CSS aus der Zeit vor den Tabs, das heute morgen sogar noch
meine minmax(0, …)-Korrektur mitbekommen hat, ohne dass es jemand sehen konnte.
Jetzt ist es lebendig. Dritter toter Rest heute: "layout": "blocks" in
data/turnen.json las ebenfalls niemand, ist raus.
Der Karteninhalt steht dafür jetzt einmal statt zweimal. Er wird in zwei
Fassungen gebraucht (Tab-Panel mit role/aria und gestapelt ohne) und ist
deshalb eine Closure geworden — eine zweite Kopie wäre die Stelle, an der beide
in einem halben Jahr auseinanderlaufen.
Die Überschrift ist visually-hidden, nicht entfernt: sonst hätte die Sektion
keinen zugänglichen Namen und die Überschriften-Gliederung eine Lücke. Dasselbe
Muster wie $title_hidden in team-cards. Damit braucht die Seite auch kein
group-tabs.js mehr, das ich zwei Commits vorher erst dazugeschrieben hatte.
Zwei Nachbesserungen, beide gemessen:
- Die versteckte Überschrift hinterließ ein Loch. Zwischen Dashboard und erster
Karte standen 160px (80 unten von der einen Sektion, 80 oben von der anderen),
in denen nur nackte Hintergrund-Textur zu sehen war — vorher füllte die
Überschrift diesen Raum. .group-list-section--tight nimmt das obere Padding
weg, jetzt 80px.
- Die gestapelten Karten hatten feste 40px Innenabstand; auf --pad-card-lg
umgestellt, dieselbe Korrektur wie heute morgen beim Tab-Panel. Am Desktop
unverändert 40px, am Handy 28px.
Nicht behoben, weil kein Fehler: die Hintergrund-Textur wirkt in leeren Flächen
weich. Sie ist 1920x2545 groß und wird bei 1478px Fensterbreite auf Faktor 0,77
VERKLEINERT, ist also nicht unscharf gerechnet. Sichtbar wurde sie durch den
Leerraum plus background-attachment: fixed, das sie beim Scrollen stehen lässt.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
2026-07-31 22:56:21 +02:00
|
|
|
<?php endif; ?>
|
|
|
|
|
<?php if (!empty($g['note'])): ?>
|
|
|
|
|
<p class="group-card__note text-muted"><?= e($g['note']) ?></p>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
</div>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
<?php
|
|
|
|
|
};
|
|
|
|
|
|
2026-06-19 10:33:03 +02:00
|
|
|
$soleSessions = $single ? ($groups[0]['sessions'] ?? []) : [];
|
|
|
|
|
$soleNote = $single ? ($groups[0]['note'] ?? '') : '';
|
|
|
|
|
?>
|
|
|
|
|
<section class="section turnen-dash-section" id="<?= e($anchor) ?>">
|
|
|
|
|
<div class="container">
|
|
|
|
|
<div class="turnen-dash<?= $single ? ' turnen-dash--single' : '' ?><?= $notice !== '' ? ' turnen-dash--notice' : '' ?>">
|
|
|
|
|
<?php if ($notice !== ''): ?>
|
Trampolin: Schnupper-Einladung, Hinweise bekommen zwei Tonlagen
Info von Eva aus der Trampolin-Gruppe: neue Kinder können ab September
(Schulbeginn) gerne schnuppern kommen. Die Info stand nirgends.
Rot wäre dafür falsch gewesen. Die Farbe bekommt deshalb eine Bedeutung:
--stop (gefüllt rot) heißt „geht nicht", --info (Glas-Fläche, Rot nur im Icon)
heißt „geht". Eine Einladung in Alarmrot liest sich wie eine Absage, und wenn
alles rot ist, stumpft Rot ab und der echte Wartelisten-Stopp bei „Tiger" und
„Hühner" verliert seine Wirkung. --info ist ab jetzt der Default.
Damit steht der Hinweis an drei Stellen, also greift die Bedingung aus dem
letzten Commit („kommt ein dritter Ort dazu, gehören die gemeinsamen
Eigenschaften in eine geteilte Klasse"): neu app/components/notice.php als
einzige Render-Stelle statt dreimal dasselbe Markup. Die beiden bestehenden
Klassen schrumpfen auf das, was sie wirklich beitragen —
.turnen-dash__notice nur noch grid-area, .contact__notice nur noch die
Formularbreite. Die tote .turnen-dash__notice-icon-Regel ist raus, der
CSS-Abschnitt neu sortiert (notice als eigener Block hinter turnen-dash statt
mitten hinein).
Text, Tonlage und Icon stehen wie gehabt in data/turnen.json bei der
Disziplin, nicht im Template. Kinderturnen trägt jetzt explizit
notice_tone: stop, Trampolin nichts und ist damit neutral.
Das Grid-Template für --notice + --single gab es schon, an beiden
Breakpoints — die Trampolin-Seite hat eine Gruppe und wäre sonst
auseinandergefallen.
Gemessen bei 390px: kein Überlauf auf allen drei Seiten, Trampolin-Fläche
rgba(0,0,0,0.22) (Glas), die beiden anderen #e20612. Zwölf Seiten geprüft,
alle 200. preflight ohne neue Meldungen.
OFFEN, mit Eva oder Tina zu klären: der zweite Satz („Schreib uns davor
einfach kurz eine Nachricht") ist von mir, Eva hat ihn nicht gesagt. Wenn die
Kinder einfach zum Training kommen dürfen, gehört er weg. Und die Einladung
steht bisher nur auf /turnen/trampolin, nicht auf der Übersicht /turnen.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
2026-07-31 22:04:41 +02:00
|
|
|
<?php component('notice', [
|
|
|
|
|
'title' => $noticeTitle,
|
|
|
|
|
'text' => $notice,
|
|
|
|
|
'tone' => $noticeTone,
|
|
|
|
|
'icon' => $noticeIcon,
|
|
|
|
|
'class' => 'turnen-dash__notice',
|
|
|
|
|
]); ?>
|
2026-06-19 10:33:03 +02:00
|
|
|
<?php endif; ?>
|
|
|
|
|
<?php if ($single): ?>
|
|
|
|
|
<article class="bento__tile turnen-dash__training">
|
|
|
|
|
<h2 class="bento__heading"><?= icon('clock', 'bento__hicon') ?>Trainingszeiten</h2>
|
|
|
|
|
<ul class="bento__sessions">
|
|
|
|
|
<?php foreach ($soleSessions as $s): ?>
|
|
|
|
|
<li>
|
|
|
|
|
<span class="bento__day"><?= e($s['day']) ?></span>
|
|
|
|
|
<span class="bento__time"><?= e($s['time']) ?></span>
|
|
|
|
|
</li>
|
|
|
|
|
<?php endforeach; ?>
|
|
|
|
|
</ul>
|
|
|
|
|
<?php if ($soleNote !== ''): ?>
|
|
|
|
|
<p class="bento__note text-muted"><?= e($soleNote) ?></p>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
<span class="bento__deco" aria-hidden="true"><?= icon('clock') ?></span>
|
|
|
|
|
</article>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
|
|
|
|
<?php if ($lead !== '' || $email !== ''): ?>
|
|
|
|
|
<article class="bento__tile bento__tile--accent turnen-dash__contact">
|
|
|
|
|
<span class="bento__stat-label">Kontakt</span>
|
|
|
|
|
<?php if ($lead !== ''): ?>
|
|
|
|
|
<span class="bento__stat-value"><?= e($lead) ?></span>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
<?php if ($email !== ''): ?>
|
|
|
|
|
<a class="turnen-dash__mail" href="mailto:<?= e($email) ?>"><?= icon('envelope', 'turnen-dash__mail-icon') ?>E-Mail schreiben</a>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
</article>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
|
|
|
|
<?php if ($hasVenue): ?>
|
|
|
|
|
<article class="bento__tile turnen-dash__venue">
|
|
|
|
|
<div class="turnen-dash__venue-main">
|
|
|
|
|
<h2 class="bento__heading"><?= icon('geo-alt', 'bento__hicon') ?>Trainingsort</h2>
|
|
|
|
|
<p class="bento__address">
|
|
|
|
|
<strong><?= e($location['venue']) ?></strong>
|
|
|
|
|
<?php if (!empty($location['street'])): ?> · <?= e($location['street']) ?><?php endif; ?>
|
|
|
|
|
<?php if (!empty($location['zip']) || !empty($location['city'])): ?>, <?= e(trim(($location['zip'] ?? '') . ' ' . ($location['city'] ?? ''))) ?><?php endif; ?>
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
<a class="btn btn--outline turnen-dash__route" href="https://www.google.com/maps/search/?api=1&query=<?= e($mapsQuery) ?>" target="_blank" rel="noopener">Route planen<span class="visually-hidden"> (öffnet Google Maps in neuem Tab)</span></a>
|
|
|
|
|
<span class="bento__deco" aria-hidden="true"><?= icon('geo-alt') ?></span>
|
|
|
|
|
</article>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
<?php if (!$single): ?>
|
Wettkampfturnen: Karten offen untereinander statt hinter Tabs
Bei zwei Gruppen verstecken Tabs mehr Inhalt als sie ordnen, und die offene
Kartenreihe hält den Bento-Eindruck der Seite (Entscheidung Felix). Das
Kinderturnen bleibt bei Tabs, dort sind es drei textreiche Gruppen — die
Flamingos-Karte allein ist am Handy 2142px hoch.
.group-list--stacked lag vollständig im CSS, wurde aber von KEINEM PHP
ausgegeben: totes CSS aus der Zeit vor den Tabs, das heute morgen sogar noch
meine minmax(0, …)-Korrektur mitbekommen hat, ohne dass es jemand sehen konnte.
Jetzt ist es lebendig. Dritter toter Rest heute: "layout": "blocks" in
data/turnen.json las ebenfalls niemand, ist raus.
Der Karteninhalt steht dafür jetzt einmal statt zweimal. Er wird in zwei
Fassungen gebraucht (Tab-Panel mit role/aria und gestapelt ohne) und ist
deshalb eine Closure geworden — eine zweite Kopie wäre die Stelle, an der beide
in einem halben Jahr auseinanderlaufen.
Die Überschrift ist visually-hidden, nicht entfernt: sonst hätte die Sektion
keinen zugänglichen Namen und die Überschriften-Gliederung eine Lücke. Dasselbe
Muster wie $title_hidden in team-cards. Damit braucht die Seite auch kein
group-tabs.js mehr, das ich zwei Commits vorher erst dazugeschrieben hatte.
Zwei Nachbesserungen, beide gemessen:
- Die versteckte Überschrift hinterließ ein Loch. Zwischen Dashboard und erster
Karte standen 160px (80 unten von der einen Sektion, 80 oben von der anderen),
in denen nur nackte Hintergrund-Textur zu sehen war — vorher füllte die
Überschrift diesen Raum. .group-list-section--tight nimmt das obere Padding
weg, jetzt 80px.
- Die gestapelten Karten hatten feste 40px Innenabstand; auf --pad-card-lg
umgestellt, dieselbe Korrektur wie heute morgen beim Tab-Panel. Am Desktop
unverändert 40px, am Handy 28px.
Nicht behoben, weil kein Fehler: die Hintergrund-Textur wirkt in leeren Flächen
weich. Sie ist 1920x2545 groß und wird bei 1478px Fensterbreite auf Faktor 0,77
VERKLEINERT, ist also nicht unscharf gerechnet. Sichtbar wurde sie durch den
Leerraum plus background-attachment: fixed, das sie beim Scrollen stehen lässt.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
2026-07-31 22:56:21 +02:00
|
|
|
<section class="section group-list-section<?= $groupsTitleHidden ? ' group-list-section--tight' : '' ?>" id="gruppen">
|
2026-06-19 10:33:03 +02:00
|
|
|
<div class="container">
|
Wettkampfturnen: Karten offen untereinander statt hinter Tabs
Bei zwei Gruppen verstecken Tabs mehr Inhalt als sie ordnen, und die offene
Kartenreihe hält den Bento-Eindruck der Seite (Entscheidung Felix). Das
Kinderturnen bleibt bei Tabs, dort sind es drei textreiche Gruppen — die
Flamingos-Karte allein ist am Handy 2142px hoch.
.group-list--stacked lag vollständig im CSS, wurde aber von KEINEM PHP
ausgegeben: totes CSS aus der Zeit vor den Tabs, das heute morgen sogar noch
meine minmax(0, …)-Korrektur mitbekommen hat, ohne dass es jemand sehen konnte.
Jetzt ist es lebendig. Dritter toter Rest heute: "layout": "blocks" in
data/turnen.json las ebenfalls niemand, ist raus.
Der Karteninhalt steht dafür jetzt einmal statt zweimal. Er wird in zwei
Fassungen gebraucht (Tab-Panel mit role/aria und gestapelt ohne) und ist
deshalb eine Closure geworden — eine zweite Kopie wäre die Stelle, an der beide
in einem halben Jahr auseinanderlaufen.
Die Überschrift ist visually-hidden, nicht entfernt: sonst hätte die Sektion
keinen zugänglichen Namen und die Überschriften-Gliederung eine Lücke. Dasselbe
Muster wie $title_hidden in team-cards. Damit braucht die Seite auch kein
group-tabs.js mehr, das ich zwei Commits vorher erst dazugeschrieben hatte.
Zwei Nachbesserungen, beide gemessen:
- Die versteckte Überschrift hinterließ ein Loch. Zwischen Dashboard und erster
Karte standen 160px (80 unten von der einen Sektion, 80 oben von der anderen),
in denen nur nackte Hintergrund-Textur zu sehen war — vorher füllte die
Überschrift diesen Raum. .group-list-section--tight nimmt das obere Padding
weg, jetzt 80px.
- Die gestapelten Karten hatten feste 40px Innenabstand; auf --pad-card-lg
umgestellt, dieselbe Korrektur wie heute morgen beim Tab-Panel. Am Desktop
unverändert 40px, am Handy 28px.
Nicht behoben, weil kein Fehler: die Hintergrund-Textur wirkt in leeren Flächen
weich. Sie ist 1920x2545 groß und wird bei 1478px Fensterbreite auf Faktor 0,77
VERKLEINERT, ist also nicht unscharf gerechnet. Sichtbar wurde sie durch den
Leerraum plus background-attachment: fixed, das sie beim Scrollen stehen lässt.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
2026-07-31 22:56:21 +02:00
|
|
|
<h2 class="group-list__title<?= $groupsTitleHidden ? ' visually-hidden' : '' ?>"><?= e($groupsTitle) ?></h2>
|
|
|
|
|
<?php if ($rich && $layout === 'stacked'): ?>
|
|
|
|
|
<?php /* Karten direkt untereinander, alle sichtbar. Für Disziplinen mit wenigen Gruppen:
|
|
|
|
|
Tabs verstecken dort mehr Inhalt als sie ordnen, und die offene Kartenreihe hält
|
|
|
|
|
den Bento-Eindruck der Seite. Bei vielen textreichen Gruppen (Kinderturnen) sind
|
|
|
|
|
Tabs weiter richtig, sonst wird die Seite endlos. */ ?>
|
|
|
|
|
<div class="group-list group-list--stacked">
|
|
|
|
|
<?php foreach ($groups as $g): ?>
|
|
|
|
|
<article class="group-card">
|
|
|
|
|
<?php $renderCardBody($g); ?>
|
|
|
|
|
</article>
|
|
|
|
|
<?php endforeach; ?>
|
|
|
|
|
</div>
|
|
|
|
|
<?php elseif ($rich): ?>
|
2026-06-20 20:48:39 +02:00
|
|
|
<div class="group-tabs" data-group-tabs>
|
|
|
|
|
<div class="group-tabs__bar" role="tablist" aria-label="<?= e($groupsTitle) ?>">
|
|
|
|
|
<?php foreach ($groups as $i => $g): ?>
|
Design-System: Button-Varianten konsolidieren, 44px-Trefferflächen
Dritter Teil. .btn hatte nur primary + outline + sm/lg, daneben lebten mehrere
Controls als Eigenbau — teils zeichengleich dupliziert.
Tabs: .group-tabs__tab und .filter-bar__tab waren bis auf flex-shrink und 4px
Innenabstand identisch. Beide laufen jetzt über eine gemeinsame .tab-Basis, die
aria-pressed (Filter) und aria-selected (Tabs) gleich behandelt; von den
BEM-Klassen bleibt nur das jeweilige Delta. Innenabstand vereinheitlicht auf
--space-m, die Gruppen-Tabs verlieren dadurch 4px pro Seite.
Icon-Buttons: .ad-banner__nav-btn und .ad-banner__toggle waren vollständige
Duplikate voneinander. Sie tragen jetzt .btn .btn--icon und behalten nur die
Glas-Optik als Delta. Der Selektor schreibt .btn mit — utilities.css lädt nach
components.css, bei gleicher Spezifität gewänne sonst die rote .btn-Fläche.
Trefferflächen auf 44px (WCAG 2.5.5): .btn bekommt min-height und wird
inline-flex, damit Icon und Label ohne Zusatz-Markup zentriert liegen.
Bezeichnend auch hier — .department-choice__btn hatte inline-flex, align-items
und exakt denselben gap bereits selbst deklariert und gibt sie jetzt ab.
Controls, die optisch klein bleiben sollen, strecken die Fläche stattdessen
unsichtbar per Pseudo-Element (.tap-target, automatisch auch für .btn--sm) —
gewertet wird die Trefferfläche, nicht die gezeichnete.
Der Banner-Indikator brauchte einen anderen Weg: er trug overflow: hidden, um
den Fortschrittsbalken zu beschneiden, was jede Erweiterung wieder abgeschnitten
hätte. Der sichtbare 6px-Balken liegt jetzt im ::before, der Fortschritt ist
selbst rund — overflow entfällt, der Button ist 48x44px.
Haupt-Nav-Links, Dropdown-Trigger und Footer-Social-Links bekommen min-height
statt einer Pseudo-Erweiterung: sie stehen in Reihen, wo überlappende
Trefferflächen den Nachbarn verdecken würden. In der 60px hohen Kopfleiste ist
die Höhe ohnehin nicht sichtbar.
Bewusst unverändert: die Formular-Checkbox bleibt bei 24px (WCAG 2.5.8).
<input> ist ein Replaced Element, dort greift ::after nicht zuverlässig — und
das zugehörige <label> ist klickbar und liefert die große Fläche.
.btn--ghost ist angelegt, hat aber aktuell keinen Abnehmer: die vermuteten
nackten Links sind bei näherem Hinsehen Bildkarten (.instagram__link),
Wrapper (.split__cta) oder eigenständige Karten-Affordanzen (.team-card__cta),
keine tertiären Buttons.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MSsVdooFLgPA8gPFp7HwZU
2026-07-27 10:28:02 +02:00
|
|
|
<button class="tab group-tabs__tab" role="tab" type="button"
|
2026-06-20 20:48:39 +02:00
|
|
|
id="gtab-<?= $i ?>"
|
|
|
|
|
aria-controls="gpanel-<?= $i ?>"
|
|
|
|
|
aria-selected="<?= $i === 0 ? 'true' : 'false' ?>"
|
|
|
|
|
><?= e($g['name']) ?></button>
|
|
|
|
|
<?php endforeach; ?>
|
|
|
|
|
</div>
|
|
|
|
|
<?php foreach ($groups as $i => $g): ?>
|
|
|
|
|
<article class="group-card group-tabs__panel" role="tabpanel"
|
|
|
|
|
id="gpanel-<?= $i ?>"
|
|
|
|
|
aria-labelledby="gtab-<?= $i ?>"
|
|
|
|
|
tabindex="0"
|
|
|
|
|
>
|
Wettkampfturnen: Karten offen untereinander statt hinter Tabs
Bei zwei Gruppen verstecken Tabs mehr Inhalt als sie ordnen, und die offene
Kartenreihe hält den Bento-Eindruck der Seite (Entscheidung Felix). Das
Kinderturnen bleibt bei Tabs, dort sind es drei textreiche Gruppen — die
Flamingos-Karte allein ist am Handy 2142px hoch.
.group-list--stacked lag vollständig im CSS, wurde aber von KEINEM PHP
ausgegeben: totes CSS aus der Zeit vor den Tabs, das heute morgen sogar noch
meine minmax(0, …)-Korrektur mitbekommen hat, ohne dass es jemand sehen konnte.
Jetzt ist es lebendig. Dritter toter Rest heute: "layout": "blocks" in
data/turnen.json las ebenfalls niemand, ist raus.
Der Karteninhalt steht dafür jetzt einmal statt zweimal. Er wird in zwei
Fassungen gebraucht (Tab-Panel mit role/aria und gestapelt ohne) und ist
deshalb eine Closure geworden — eine zweite Kopie wäre die Stelle, an der beide
in einem halben Jahr auseinanderlaufen.
Die Überschrift ist visually-hidden, nicht entfernt: sonst hätte die Sektion
keinen zugänglichen Namen und die Überschriften-Gliederung eine Lücke. Dasselbe
Muster wie $title_hidden in team-cards. Damit braucht die Seite auch kein
group-tabs.js mehr, das ich zwei Commits vorher erst dazugeschrieben hatte.
Zwei Nachbesserungen, beide gemessen:
- Die versteckte Überschrift hinterließ ein Loch. Zwischen Dashboard und erster
Karte standen 160px (80 unten von der einen Sektion, 80 oben von der anderen),
in denen nur nackte Hintergrund-Textur zu sehen war — vorher füllte die
Überschrift diesen Raum. .group-list-section--tight nimmt das obere Padding
weg, jetzt 80px.
- Die gestapelten Karten hatten feste 40px Innenabstand; auf --pad-card-lg
umgestellt, dieselbe Korrektur wie heute morgen beim Tab-Panel. Am Desktop
unverändert 40px, am Handy 28px.
Nicht behoben, weil kein Fehler: die Hintergrund-Textur wirkt in leeren Flächen
weich. Sie ist 1920x2545 groß und wird bei 1478px Fensterbreite auf Faktor 0,77
VERKLEINERT, ist also nicht unscharf gerechnet. Sichtbar wurde sie durch den
Leerraum plus background-attachment: fixed, das sie beim Scrollen stehen lässt.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
2026-07-31 22:56:21 +02:00
|
|
|
<?php $renderCardBody($g); ?>
|
2026-06-19 10:33:03 +02:00
|
|
|
</article>
|
|
|
|
|
<?php endforeach; ?>
|
|
|
|
|
</div>
|
2026-06-20 20:48:39 +02:00
|
|
|
<?php else: ?>
|
|
|
|
|
<div class="group-list group-list--grid">
|
|
|
|
|
<?php foreach ($groups as $g): ?>
|
|
|
|
|
<article class="group-card">
|
|
|
|
|
<div class="group-card__body">
|
|
|
|
|
<div class="group-card__header">
|
|
|
|
|
<h3 class="group-card__name"><?= e($g['name']) ?></h3>
|
|
|
|
|
<?php if (!empty($g['level'])): ?>
|
|
|
|
|
<p class="group-card__level"><?= e($g['level']) ?></p>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<?php if (!empty($g['sessions'])): ?>
|
|
|
|
|
<div class="group-card__schedule">
|
|
|
|
|
<ul class="schedule-list">
|
|
|
|
|
<?php foreach ($g['sessions'] as $s): $renderSession($s); endforeach; ?>
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
</article>
|
|
|
|
|
<?php endforeach; ?>
|
|
|
|
|
</div>
|
|
|
|
|
<?php endif; ?>
|
2026-06-19 10:33:03 +02:00
|
|
|
<?php if ($footnote !== ''): ?>
|
|
|
|
|
<p class="group-list__footnote text-muted"><?= e($footnote) ?></p>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
</div>
|
|
|
|
|
</section>
|
|
|
|
|
<?php endif; ?>
|