From 75fce4f680bc9deabc121a40b7c5ddc75020f880 Mon Sep 17 00:00:00 2001 From: fs Date: Thu, 17 Sep 2026 10:10:08 +0200 Subject: [PATCH] Logo-Downloadseite /logo mit Erzeuger-Skript MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Damit die Abteilungen das Wappen selbst holen können, statt jedes Mal zu fragen: drei Varianten (farbig, einfarbig schwarz, einfarbig weiß) in SVG, PDF, PNG und JPG, dazu ein ZIP über alles und die Vereinsfarben. Verlinkt nur in der Fußzeile. Bisher lag das Logo genau einmal im Projekt, als eine einzige SVG. Es gab kein PNG, kein JPG, kein PDF und keine einfarbige Fassung. bin/logo-build.php erzeugt alle Dateien aus einer Master-SVG unter storage/logo-quellen/. Gerastert wird mit headless Chrome, weil GD kein SVG lesen kann und weder Inkscape noch rsvg-convert noch ImageMagick verfügbar sind; das PDF ist dabei echter Vektor. Das Skript läuft einmalig lokal, nichts davon im Request-Pfad. bin/preflight.php meldet als Fehler, wenn eine Download-Datei fehlt: die Komponente ließe den Knopf sonst still weg. Die beiden einfarbigen Fassungen sind exakte Negative voneinander, nur Linien, alle Flächen frei. EPS gibt es bewusst nicht, dafür fehlt jedes Werkzeug; SVG und PDF decken die Druckereien ab. Frühere Vereinslogos sind vorbereitet, aber im Projekt liegt bisher kein einziges historisches Wappen vor. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01J9mubC8gtpjtJntbhSJBRS --- CLAUDE.md | 63 ++- app/components/footer.php | 2 +- app/components/logo-downloads.php | 136 +++++++ app/pages/logo.php | 96 +++++ app/routes.php | 1 + bin/logo-build.php | 368 ++++++++++++++++++ bin/preflight.php | 42 ++ data/logo.json | 74 ++++ data/navigation.json | 1 + public/assets/css/components.css | 209 ++++++++++ public/assets/css/tokens.css | 4 + public/assets/downloads/logo/LIESMICH.txt | 27 ++ ...8-kulmbach-logo-einfarbig-schwarz-1000.jpg | Bin 0 -> 119101 bytes ...8-kulmbach-logo-einfarbig-schwarz-1000.png | Bin 0 -> 44764 bytes ...8-kulmbach-logo-einfarbig-schwarz-2000.jpg | Bin 0 -> 306318 bytes ...8-kulmbach-logo-einfarbig-schwarz-2000.png | Bin 0 -> 98706 bytes ...08-kulmbach-logo-einfarbig-schwarz-500.png | Bin 0 -> 21585 bytes .../tsv08-kulmbach-logo-einfarbig-schwarz.pdf | Bin 0 -> 3819 bytes .../tsv08-kulmbach-logo-einfarbig-schwarz.svg | 30 ++ ...v08-kulmbach-logo-einfarbig-weiss-1000.jpg | Bin 0 -> 116091 bytes ...v08-kulmbach-logo-einfarbig-weiss-1000.png | Bin 0 -> 47759 bytes ...v08-kulmbach-logo-einfarbig-weiss-2000.jpg | Bin 0 -> 298488 bytes ...v08-kulmbach-logo-einfarbig-weiss-2000.png | Bin 0 -> 107736 bytes ...sv08-kulmbach-logo-einfarbig-weiss-500.png | Bin 0 -> 23112 bytes .../tsv08-kulmbach-logo-einfarbig-weiss.pdf | Bin 0 -> 3818 bytes .../tsv08-kulmbach-logo-einfarbig-weiss.svg | 30 ++ .../logo/tsv08-kulmbach-logo-farbig-1000.jpg | Bin 0 -> 149747 bytes .../logo/tsv08-kulmbach-logo-farbig-1000.png | Bin 0 -> 60905 bytes .../logo/tsv08-kulmbach-logo-farbig-2000.jpg | Bin 0 -> 369715 bytes .../logo/tsv08-kulmbach-logo-farbig-2000.png | Bin 0 -> 132993 bytes .../logo/tsv08-kulmbach-logo-farbig-500.png | Bin 0 -> 30011 bytes .../logo/tsv08-kulmbach-logo-farbig.pdf | Bin 0 -> 4333 bytes .../logo/tsv08-kulmbach-logo-farbig.svg | 30 ++ .../logo/tsv08-kulmbach-logo-paket.zip | Bin 0 -> 1065917 bytes storage/logo-quellen/aktuell.svg | 30 ++ 35 files changed, 1141 insertions(+), 2 deletions(-) create mode 100644 app/components/logo-downloads.php create mode 100644 app/pages/logo.php create mode 100644 bin/logo-build.php create mode 100644 data/logo.json create mode 100644 public/assets/downloads/logo/LIESMICH.txt create mode 100644 public/assets/downloads/logo/tsv08-kulmbach-logo-einfarbig-schwarz-1000.jpg create mode 100644 public/assets/downloads/logo/tsv08-kulmbach-logo-einfarbig-schwarz-1000.png create mode 100644 public/assets/downloads/logo/tsv08-kulmbach-logo-einfarbig-schwarz-2000.jpg create mode 100644 public/assets/downloads/logo/tsv08-kulmbach-logo-einfarbig-schwarz-2000.png create mode 100644 public/assets/downloads/logo/tsv08-kulmbach-logo-einfarbig-schwarz-500.png create mode 100644 public/assets/downloads/logo/tsv08-kulmbach-logo-einfarbig-schwarz.pdf create mode 100644 public/assets/downloads/logo/tsv08-kulmbach-logo-einfarbig-schwarz.svg create mode 100644 public/assets/downloads/logo/tsv08-kulmbach-logo-einfarbig-weiss-1000.jpg create mode 100644 public/assets/downloads/logo/tsv08-kulmbach-logo-einfarbig-weiss-1000.png create mode 100644 public/assets/downloads/logo/tsv08-kulmbach-logo-einfarbig-weiss-2000.jpg create mode 100644 public/assets/downloads/logo/tsv08-kulmbach-logo-einfarbig-weiss-2000.png create mode 100644 public/assets/downloads/logo/tsv08-kulmbach-logo-einfarbig-weiss-500.png create mode 100644 public/assets/downloads/logo/tsv08-kulmbach-logo-einfarbig-weiss.pdf create mode 100644 public/assets/downloads/logo/tsv08-kulmbach-logo-einfarbig-weiss.svg create mode 100644 public/assets/downloads/logo/tsv08-kulmbach-logo-farbig-1000.jpg create mode 100644 public/assets/downloads/logo/tsv08-kulmbach-logo-farbig-1000.png create mode 100644 public/assets/downloads/logo/tsv08-kulmbach-logo-farbig-2000.jpg create mode 100644 public/assets/downloads/logo/tsv08-kulmbach-logo-farbig-2000.png create mode 100644 public/assets/downloads/logo/tsv08-kulmbach-logo-farbig-500.png create mode 100644 public/assets/downloads/logo/tsv08-kulmbach-logo-farbig.pdf create mode 100644 public/assets/downloads/logo/tsv08-kulmbach-logo-farbig.svg create mode 100644 public/assets/downloads/logo/tsv08-kulmbach-logo-paket.zip create mode 100644 storage/logo-quellen/aktuell.svg diff --git a/CLAUDE.md b/CLAUDE.md index f5d6835..ab2a534 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -60,6 +60,7 @@ selbst gehosteter Stack ohne Abhängigkeiten von Drittanbietern. | Veranstaltungen (`/veranstaltungen` + Detailseiten) | `data/veranstaltungen.json` + `public/assets/img/veranstaltungen/` | Termin, Texte, Programm, Turnierpläne (`turniere[]`, nur fürs Heft), Abschnitte von Claude im Chat gepflegt — **außer `plakate` und `galerie`: die schreibt ausschließlich `bin/veranstaltung-bilder.php`**. Adresse nie in die Texte schreiben (steht in `club.json`) | | News (`/news` + optionale Detailseiten) | `data/news.json` (redaktionelle Meldungen; `artikel[]` = Fließtext-Blöcke, `status` = Entwurf/veröffentlicht) — Instagram-Posts und Ergebnisse kommen weiterhin nur aus `data/instagram.json`/`data/matchcenter.json`, werden auf der News-Seite nur gemergt | Von Claude im Chat gepflegt wie `events.json`/`teams.json` — **keine** Automatisierung, kein Bin-Skript. Instagram/Ergebnisse nie hier duplizieren. `text` bleibt der Teaser (Feed, Meta-Description, Article-Schema), der Artikel steht in `artikel[]` | | Dateiablage `/dateien` (Konfiguration) | `public/dateien/_filesconfig.php` (Rechte pro Konto: `storage/dateien/system/users/admin/config.php`) | **`storage/dateien/system/config/config.php` von Hand editieren** — die App generiert sie selbst und überschreibt sie bei jedem Update. Passwörter/Lizenz gehören in `config.php` (`dateien.*`) | +| Logo-Downloads (`/logo`) | Texte: `data/logo.json` · Master: `storage/logo-quellen/*.svg` | Die Dateien unter `public/assets/downloads/logo/` sind **maschinenverwaltet von `bin/logo-build.php`** — nie von Hand skalieren, nie von Hand umfärben, nie einzeln nachlegen. Auch keine Dateiliste in die JSON schreiben: welche Formate es gibt, entscheidet das Skript, Größen liest die Seite von der Platte | | Icons | `public/assets/icons/` (Bootstrap Icons, lokal) via `icon()`-Helper | Inline-SVG-Pfade von Hand ins Markup, Emoji/Unicode-Glyphen, gezeichnete CSS-Icons, Icon-Font/CDN | Per-Page-Meta (Title/Description/OG) lebt in der jeweiligen Page-Datei (`app/pages/*.php`) im `$meta`-Array. @@ -239,7 +240,7 @@ Funktion, sie ist die einzige Stelle, an der aus JSON HTML entsteht. Web wie CLI. Kein `error_log()`, kein `file_put_contents()` auf eine Logdatei, keine eigene Log-Closure in einem neuen Skript. - Kanal = Dateiname unter `storage/logs/`: `mail` · `spam` · `instagram` · `matchcenter` · - `stadionzeitung` · `veranstaltungen` · `chronik` · `filesgallery` · `logrotate` + `stadionzeitung` · `veranstaltungen` · `chronik` · `filesgallery` · `logo` · `logrotate` (letzterer nur für den Übersprungen-Hinweis des Cron-Endpoints, der seinen Kanal aus dem Job-Namen bildet) (`php-errors.log` schreibt PHP selbst, eigenes Format). @@ -1180,6 +1181,66 @@ funktionieren hier **nicht** — sie brauchen eine öffentliche URL, unser `stor `public/dateien/.htaccess` (braucht `'unsafe-inline'` für Scripts/Styles: die App interpoliert Inline-Code per PHP und kennt keine Nonces) — sie gilt nur dort, die Seiten behalten die strikte. +## Logo-Downloadseite `/logo` + +Damit die Abteilungen das Wappen selbst holen können, statt jedes Mal zu fragen: eine +öffentliche Seite mit jeder Variante in jedem gängigen Format, dazu die Farbwerte und die +Nutzungsregeln. Verlinkt **nur in der Fußzeile** (`navigation.json` → `legal`), nicht im +Hauptmenü. Die Dateien werden **einmalig lokal** erzeugt und committet; nichts davon läuft +auf dem Server, es gibt keinen Cron und keine Laufzeit-Abhängigkeit. + +**Drei Varianten, alle aus EINER Master-SVG** (`storage/logo-quellen/aktuell.svg`, identisch +zum Website-Asset `public/assets/img/logo.svg`): `farbig`, `einfarbig-schwarz` und +`einfarbig-weiss`. Die Umfärbung passiert durch Austausch der Farbklassen im ``-Block +der CorelDRAW-Datei (`.fil0`/`.fil3` schwarz, `.fil1` weiß, `.fil2` rot) — +`bin/logo-build.php` bricht ab, wenn eine erwartete Klasse fehlt, sonst entstünde stillschweigend +dreimal dasselbe Logo. +**Die beiden einfarbigen Fassungen sind exakte Negative voneinander:** nur Linien, ALLE +Flächen frei. Zwei Irrwege dahin, beide am 17.09.2026 korrigiert: eine Fassung „für dunklen +Grund" behielt das rote Schild und war damit keine einfarbige, sondern ein farbiges Logo mit +weißen Konturen; und `einfarbig-schwarz` ersetzte Rot durch **Weiß**, wodurch im PNG eine +deckend weiße Schildfläche steckte (auf farbigem Papier ein weißer Klotz). **Einfarbig heißt +einfarbig:** ein Vollton, der Rest transparent. Nachweisbar über die Volltonfarben im PNG, +je Variante darf genau eine vorkommen. + +**Gerastert wird mit headless Chrome, nicht mit GD.** `bin/img-resize.php` kann keine SVG lesen, +und Inkscape, rsvg-convert oder ImageMagick gibt es hier nicht (auf dem Shared Hosting erst +recht nicht). Chrome kann beides, was gebraucht wird: transparent rastern (`--screenshot` + +`--default-background-color=00000000`) und ein **echtes Vektor-PDF** drucken (`--print-to-pdf`, +nachgemessen: Kurven-Operatoren im Inhaltsstrom, kein eingebettetes Pixelbild). +**Kein `--user-data-dir`** — der naheliegende eigene Profilordner lässt Chrome 152 beim ersten +Aufruf endlos hängen, ohne Bild und ohne Meldung. Ohne den Schalter läuft jeder Aufruf in +Sekunden durch, auch bei geöffnetem Chrome. Wer das ändert, misst die Laufzeit nach. + +**Der JPG-Hintergrund gehört zur Variante**, nicht zum Format: JPG kann keine Transparenz, und +die weiße Fassung auf weißem Grund wäre ein leeres Blatt. `einfarbig-weiss` wird deshalb auf +Anthrazit (`#222`) flachgelegt, alle anderen auf Weiß (`jpg_bg` je Eintrag in `$OUTPUTS`). + +**EPS gibt es bewusst nicht.** Dafür bräuchte es Illustrator, Inkscape oder Ghostscript; ein +Composer-Paket verbietet Regel 1. Druckereien nehmen PDF oder SVG, beides liegt als Vektor +bereit. Steht die Frage doch im Raum, beantwortet sie die FAQ auf der Seite. + +**Retro-Logos:** `retro[]` in `data/logo.json` ist vorbereitet und vorerst leer — im Projekt +existiert kein einziges historisches Wappen (weder im Repo noch in `.context/`, der alten +CMS-Datenbank oder der Chronik-Sammlung). Kommt ein Scan, wird er eine weitere Datei in +`storage/logo-quellen/` plus ein Eintrag in `$OUTPUTS`; liegt er nur als Pixelbild vor, erzeugt +das Skript PNG und JPG über `resize_image_variants()` und lässt SVG und PDF weg. + +**Die Seite ist bewusst karg** (Felix, 17.09.2026): Einleitungstext, Nutzungshinweis +(„nicht verzerren, nicht einfärben"), die Abschnittsüberschrift über den Karten und eine +fünfteilige FAQ waren gebaut und sind alle wieder entfernt worden; das ZIP über alle +Varianten hatte ebenfalls eine eigene Sektion samt Überschrift „Alles auf einmal" und ist +jetzt nur noch ein Knopf unter dem Karten-Raster (Prop `paket` der Komponente) — „alles +davon" gehört direkt unter das, worauf es sich bezieht. Eine Downloadseite ist ein +Regal, kein Text: Wappen, Knöpfe, Farben, fertig. Die Variantenbeschreibungen sind auf drei +Wörter gekürzt („Stempel, Gravur, einfarbiger Druck."). Die Überschrift steht noch als +`visually-hidden` im DOM, damit die Heading-Kette nicht von `h1` auf `h3` springt. +**Nichts davon wieder hinzuerklären.** + +`bin/preflight.php` prüft, dass zu jeder Variante die Dateien existieren (**Fehler**, nicht +Warnung: die Komponente lässt einen Knopf ohne Datei still weg, man sähe es der Seite nicht an) +und warnt, wenn eine Master-SVG neuer ist als das Erzeugte. + ## Chronik 2028 (Materialsammlung fürs Jubiläum) Sammelt Fundstücke für die Vereinschronik zum 120-jährigen Bestehen. **Reine Recherche-Werkzeuge, diff --git a/app/components/footer.php b/app/components/footer.php index a78259f..5c3f92d 100644 --- a/app/components/footer.php +++ b/app/components/footer.php @@ -91,7 +91,7 @@ $extraLinks = array_merge($extraLinks, $nav['ctas'] ?? []);