diff --git a/CLAUDE.md b/CLAUDE.md index 45a5a8b..94ec89d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -294,6 +294,18 @@ nicht durchgezogen. **3,50:1** und verfehlt die 4,5:1 für Fließtext; Weiß liegt bei 17,22:1. Genau daran sind die Beitragspreise hängengeblieben, die zuerst rot waren. Hervorhebung über Schriftart und Größe (Coolvetica 28px gegen 21px Fließtext) trägt ohne Farbe. +- **Hervorgehobene Hinweise laufen über `component('notice')`** (`app/components/notice.php`, + Klassen `.notice`/`.notice--info`/`.notice--stop`), nie als eigenes Markup. Die Tonlage trägt + Bedeutung und ist keine Geschmacksfrage: **`--stop` (gefüllt rot) heißt „geht nicht"** + (Wartelisten-Stopp der Turnabteilung), **`--info` (Glas-Fläche, Rot nur im Icon) heißt „geht"** + (neue Kinder dürfen zum Schnuppern kommen). Eine Einladung in Alarmrot liest sich wie eine + Absage, und wenn alles rot ist, stumpft Rot ab und der echte Stopp verliert seine Wirkung. + **`--info` ist der Default, Rot die Ausnahme.** Der Text und die Tonlage stehen in der + `data/*.json` der Seite (`notice`, `notice_title`, `notice_tone`, `notice_icon`), nie im + Template; eingebettet wird über eine Zusatzklasse, die **nur** Position bzw. Breite setzt + (`.turnen-dash__notice` = `grid-area`, `.contact__notice` = Formularbreite). + Eine Überschrift ist Pflicht, wenn der Hinweis rot ist: ohne sie liest sich die rote Fläche + wie eine Fehlermeldung. - Alle Werte als CSS Custom Properties in `tokens.css`; Breakpoints: 1249 (Burger) / 1024 / 992 / 768 / 600 / 500. ### Token-Disziplin (gilt für jede CSS-Änderung) diff --git a/app/components/contact-form.php b/app/components/contact-form.php index b416d63..9679956 100644 --- a/app/components/contact-form.php +++ b/app/components/contact-form.php @@ -10,7 +10,7 @@ declare(strict_types=1); * leitet nach PRG hierher zurück (whitelist-validiert), damit /kontakt nicht auf die * Startseite springt. * $notice string optional — hervorgehobener Hinweis DIREKT über dem Formular, plus - * $noticeTitle für die Überschrift dazu. Für Dinge, die man wissen muss, BEVOR + * $noticeTitle, $noticeTone und $noticeIcon (siehe components/notice.php). Für Dinge, die man wissen muss, BEVOR * man schreibt (Wartelisten-Status der Turnabteilung). Steht bewusst außerhalb * des
und damit außerhalb der role="status"-Region: das ist ein * dauerhafter Hinweis, keine Rückmeldung zum Absenden — in der Live-Region @@ -32,6 +32,8 @@ $return = $return ?? ''; $intro = $intro ?? null; $notice = $notice ?? ''; $noticeTitle = $noticeTitle ?? ''; +$noticeTone = $noticeTone ?? 'info'; +$noticeIcon = $noticeIcon ?? 'info-circle'; $variant = contact_variant((string) ($department ?? '')); $interests = $variant['interests']; @@ -81,18 +83,17 @@ $f = [ - - + + $noticeTitle, + 'text' => $notice, + 'tone' => $noticeTone, + 'icon' => $noticeIcon, + 'level' => 'h3', + 'class' => 'contact__notice', +]); ?> diff --git a/app/components/group-schedule.php b/app/components/group-schedule.php index 81a448b..3e172d2 100644 --- a/app/components/group-schedule.php +++ b/app/components/group-schedule.php @@ -7,10 +7,12 @@ declare(strict_types=1); * $location array{venue, street?, zip?, city?} (optional) — Trainingsort + „Route planen" * $lead string (optional) — verantwortliche Übungsleitung (Akzent-Kachel) * $notice string (optional) — hervorgehobener Hinweis (z. B. Wartelisten-Status) - * $noticeTitle string (optional) — Überschrift dazu. Ohne sie liest sich die rote Kachel - * wie eine Fehlermeldung; mit ihr ist auf einen Blick klar, dass es eine - * Information ist. Dieselben zwei Felder rendert contact-form.php über dem - * Formular, damit der Hinweis nur EINMAL in data/turnen.json steht. + * $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. * $groups array von Gruppen: * { name, level?, intro?, details?:[{heading,text}], recommendation?, note?, * trainers?:[…], sessions:[{ label?, day, time, note?, trainers?:[…] }] } @@ -27,6 +29,8 @@ $groupsTitle = $groupsTitle ?? 'Unsere Gruppen'; $lead = $lead ?? ''; $notice = $notice ?? ''; $noticeTitle = $noticeTitle ?? ''; +$noticeTone = $noticeTone ?? 'info'; +$noticeIcon = $noticeIcon ?? 'info-circle'; $footnote = $footnote ?? ''; $groups = $groups ?? []; $location = $location ?? []; @@ -83,15 +87,13 @@ $soleNote = $single ? ($groups[0]['note'] ?? '') : '';
-
- -
- -

- -

-
-
+ $noticeTitle, + 'text' => $notice, + 'tone' => $noticeTone, + 'icon' => $noticeIcon, + 'class' => 'turnen-dash__notice', +]); ?>
diff --git a/app/components/notice.php b/app/components/notice.php new file mode 100644 index 0000000..78448a9 --- /dev/null +++ b/app/components/notice.php @@ -0,0 +1,43 @@ + +
+ +
+ + < class="notice__title">> + +

+
+
diff --git a/app/pages/turnen-eltern-kind.php b/app/pages/turnen-eltern-kind.php index 6e2c0ce..6ad5248 100644 --- a/app/pages/turnen-eltern-kind.php +++ b/app/pages/turnen-eltern-kind.php @@ -29,6 +29,8 @@ component('group-schedule', [ 'lead' => $d['lead'] ?? '', 'notice' => $d['notice'] ?? '', 'noticeTitle' => $d['notice_title'] ?? '', + 'noticeTone' => $d['notice_tone'] ?? 'info', + 'noticeIcon' => $d['notice_icon'] ?? 'info-circle', 'groups' => $d['groups'] ?? [], 'footnote' => $data['footnote'] ?? '', ]); \ No newline at end of file diff --git a/app/pages/turnen-trampolin.php b/app/pages/turnen-trampolin.php index cd9e1e9..b3925f0 100644 --- a/app/pages/turnen-trampolin.php +++ b/app/pages/turnen-trampolin.php @@ -22,7 +22,11 @@ $meta = [ component('hero', ['hero' => $d['hero']]); component('group-schedule', [ - 'location' => $d['location'] ?? [], - 'lead' => $d['lead'] ?? '', - 'groups' => $d['groups'] ?? [], + 'location' => $d['location'] ?? [], + 'lead' => $d['lead'] ?? '', + 'notice' => $d['notice'] ?? '', + 'noticeTitle' => $d['notice_title'] ?? '', + 'noticeTone' => $d['notice_tone'] ?? 'info', + 'noticeIcon' => $d['notice_icon'] ?? 'info-circle', + 'groups' => $d['groups'] ?? [], ]); \ No newline at end of file diff --git a/app/pages/turnen.php b/app/pages/turnen.php index 093ca02..5c75a4c 100644 --- a/app/pages/turnen.php +++ b/app/pages/turnen.php @@ -107,4 +107,6 @@ component('contact-form', [ 'department' => 'turnen', 'notice' => $kinderturnen['notice'] ?? '', 'noticeTitle' => $kinderturnen['notice_title'] ?? '', + 'noticeTone' => $kinderturnen['notice_tone'] ?? 'info', + 'noticeIcon' => $kinderturnen['notice_icon'] ?? 'info-circle', ]); diff --git a/data/turnen.json b/data/turnen.json index c311f59..41950fe 100644 --- a/data/turnen.json +++ b/data/turnen.json @@ -104,7 +104,8 @@ "layout": "blocks", "location": { "venue": "Mäximum Gym", "street": "Thurnauer Str. 51", "zip": "95326", "city": "Kulmbach" }, "lead": "Annelie Frisque", - "notice_title": "Hinweis zur Warteliste", + "notice_tone": "stop", + "notice_title": "Hinweis zur Warteliste", "notice": "Für die Gruppen „Tiger“ und „Hühner“ (ab 8 Jahre) können wir derzeit leider keine neuen Mitglieder aufnehmen und führen deshalb aktuell keine Warteliste. Die übrigen Kinderturngruppen sind ebenfalls belegt, dort nehmen wir dein Kind aber gerne auf die Warteliste.", "groups": [ { @@ -203,6 +204,9 @@ }, "location": { "venue": "Dreifachturnhalle der Carl-von-Linde-Realschule", "city": "Kulmbach" }, "lead": "Tina Kornatz", + "notice_icon": "calendar-event", + "notice_title": "Schnuppern ab September", + "notice": "Mit dem Schulbeginn im September können neue Kinder bei uns gerne zum Schnuppern vorbeikommen. Schreib uns davor einfach kurz eine Nachricht, dann sagen wir dir, wann es am besten passt.", "groups": [ { "name": "Trampolinturnen", diff --git a/public/assets/css/components.css b/public/assets/css/components.css index 3a9a138..cd10b9e 100644 --- a/public/assets/css/components.css +++ b/public/assets/css/components.css @@ -1771,45 +1771,12 @@ margin-top: var(--space-s); } -/* Hinweis direkt über dem Formular (Wartelisten-Status). Bewusst dieselbe Optik wie - .turnen-dash__notice, damit es auf /turnen und der Kinderturn-Unterseite als ein und - derselbe Hinweis erkennbar ist. Kommt ein dritter Ort dazu, gehören die gemeinsamen - Eigenschaften in eine geteilte .notice-Klasse; für zwei wäre das verfrüht. - Weiß auf --clr-accent erreicht 4,92:1 und trägt damit Fließtext (WCAG 1.4.3); - die Breite folgt dem Formular (.form max-width: 720px), sonst stünde der Kasten - sichtbar über die Feldkante hinaus. */ +/* Nur die Breite: der Hinweis über dem Formular soll genau so breit sein wie das + Formular (.form max-width: 720px), sonst stünde er sichtbar über die Feldkante + hinaus. Alles andere kommt von .notice. */ .contact__notice { - display: flex; - align-items: flex-start; - gap: var(--space-xs); width: 100%; max-width: 720px; - padding: var(--pad-card); - border-radius: var(--radius-card); - background: var(--clr-accent); - color: #fff; -} - -.contact__notice-icon { - flex: none; - margin-top: 0.15em; - font-size: var(--icon-inline-lg); -} - -.contact__notice-title { - margin: 0 0 var(--space-3xs); - font-family: var(--ff-body); - font-size: var(--fs-600); - letter-spacing: var(--ls-caps); - text-transform: uppercase; - color: #fff; -} - -.contact__notice p { - margin: 0; - max-width: none; - font-size: var(--fs-600); - line-height: 1.5; } .form { @@ -2693,7 +2660,8 @@ .turnen-dash:not(.turnen-dash--single) .turnen-dash__contact { grid-area: lead; } .turnen-dash:not(.turnen-dash--single) .turnen-dash__venue { grid-area: venue; } -/* Mit Hinweis-Kachel: rote Banner-Zeile ganz oben (volle Breite). */ +/* Mit Hinweis: Banner-Zeile ganz oben über die volle Breite. Die Farbe entscheidet die + Tonlage der .notice-Komponente, nicht dieses Raster. */ .turnen-dash--notice.turnen-dash--single { grid-template-areas: "notice notice notice" @@ -2705,42 +2673,9 @@ "notice notice notice" "venue venue lead"; } +/* Nur die Position im Bento-Raster — Fläche, Farbe und Innenaufbau kommen von .notice. */ .turnen-dash__notice { grid-area: notice; } -/* Hinweis-Kachel: klar rot, weiße Schrift, Icon links (z. B. Wartelisten-Status). */ -.turnen-dash__notice { - flex-direction: row; - align-items: flex-start; - gap: var(--space-xs); - background: var(--clr-accent); - border-color: var(--clr-accent); - color: #fff; -} - -.turnen-dash__notice p { - margin: 0; - max-width: none; - font-size: var(--fs-600); - line-height: 1.5; -} - -/* Abel statt Coolvetica: die Zeile ist mit ~19px weit unter den 28px, ab denen der - Condensed-Schnitt in Versalien lesbar bleibt (siehe CLAUDE.md, Design). */ -.turnen-dash__notice-title { - margin: 0 0 var(--space-3xs); - font-family: var(--ff-body); - font-size: var(--fs-600); - letter-spacing: var(--ls-caps); - text-transform: uppercase; - color: #fff; -} - -.turnen-dash__notice-icon { - flex: none; - margin-top: 0.1em; - font-size: var(--icon-l); -} - /* Trainingsort: Adresse links, Route-Button rechts (wie team-bento__venue). */ .turnen-dash__venue { flex-direction: row; @@ -2817,6 +2752,66 @@ } } +/* === notice === */ +/* Hervorgehobener Hinweis in zwei Tonlagen (app/components/notice.php). Wird an drei + Stellen eingebettet: als Kachel im Turn-Dashboard, über dem Anfrageformular und auf + den Disziplin-Unterseiten. Die einbettende Klasse liefert nur Position bzw. Breite. + + Zwei Tonlagen, weil die Farbe eine Bedeutung hat: --stop steht für „geht nicht" + (Wartelisten-Stopp), --info für „geht" (neue Kinder dürfen schnuppern). Eine + Einladung in Alarmrot liest sich wie eine Absage. Rot bleibt die Ausnahme. */ +.notice { + display: flex; + align-items: flex-start; + gap: var(--space-xs); + padding: var(--pad-card); + background: var(--clr-glass-bg); + border: 1px solid var(--clr-glass-border); + border-radius: var(--radius-card); +} + +/* Neutral: Glas wie jede andere Karte, das Akzentrot trägt nur das Icon. Damit + unterscheidet sich der Hinweis von normalem Text, ohne wie eine Warnung zu wirken. */ +.notice--info .notice__icon { + color: var(--clr-accent); +} + +/* Weiß auf --clr-accent erreicht 4,92:1 und trägt damit Fließtext (WCAG 1.4.3). */ +.notice--stop { + background: var(--clr-accent); + border-color: var(--clr-accent); + color: #fff; +} + +.notice__icon { + flex: none; + margin-top: 0.15em; + font-size: var(--icon-inline-lg); +} + +.notice__body { + min-width: 0; +} + +/* Abel statt Coolvetica: die Zeile ist mit ~19px weit unter den 28px, ab denen der + Condensed-Schnitt in Versalien lesbar bleibt (siehe CLAUDE.md, Design). */ +.notice__title { + margin: 0 0 var(--space-3xs); + font-family: var(--ff-body); + font-size: var(--fs-600); + letter-spacing: var(--ls-caps); + text-transform: uppercase; + color: inherit; +} + +.notice p { + margin: 0; + max-width: none; + font-size: var(--fs-600); + line-height: 1.5; +} + + /* === group-list (Turn-Gruppen einer Disziplin) === */ .group-list__title { margin-bottom: var(--space-l);