Stadionzeitung, Veranstaltungen, News-Artikel, Lightbox und Anzeigen-Verteilung

Stadionzeitung: Live-Seiten (Tabellen, Ergebnisse, Vorschau, Termine, News,
Kontakt, Historie, Sportheim, Partner, Momente, Impressum), automatisches Cover,
Swipe-Viewer mit Vollbildmodus und die Druckfassung als Falt-Heft. Anzeigen
kommen jetzt aus dem Bestand und werden gleichmäßig verteilt, nie mehr als zwei
hintereinander (vorher vier Blöcke à fünf). Die Doppelseiten-Regel rechnet das
Skript selbst, statt sie von Hand zu prüfen.

Veranstaltungen: Bereich /veranstaltungen mit Detailseite pro Fest, Lebenszyklus
über das Datum (Ankündigung vor dem Fest, Rückblick danach), Galerie mit
Lightbox. veranstaltungen.json ist dritte Termin-Quelle, damit ein Fest nie
doppelt gepflegt wird.

News-Artikel als dritte dynamische Prefix-Route, gemeinsamer detail-head.

Behobene Fehler:
- Wappen-Kontexte setzten Zeilen-Layout auf .crest statt auf die Zeile; das
  Wappen wurde zum Grid, Vereinsname und Tore rutschten darunter zusammen
  (Ergebnis-Rückblick, Vorschau, Cover).
- --header-h (60px) unterschätzt die Kopfleiste um 32px (Logo 72px + 20px
  Versatz): neues abgeleitetes --header-space, sonst klebten Zurück-Links
  unter dem Logo.
- base_url in der Produktions-Config ohne www, während .htaccess auf www
  umleitet; preflight prüft das jetzt.
- .lightbox brauchte display:none mit (0,2,0), sonst lag das Overlay offen.

Neue Werkzeuge: bin/anzeige-add.php (Anzeigen-Bestand), bin/veranstaltung-bilder.php
(Plakate und Galerien, Alt-Texte folgen der Quelldatei), bin/qr.php (Druck-QR mit
Warnung, wenn base_url nicht auf die echte Domain zeigt).

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 14:55:27 +02:00
parent 3fb480dd78
commit a101b0c3ec
861 changed files with 75244 additions and 487 deletions

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2018 Transloadit
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
(()=>{var e={pluralize(l){return l===1?0:1}};e.strings={addMore:"Tilf\xF8j flere",addMoreFiles:"Tilf\xF8j flere filer",addingMoreFiles:"Tilf\xF8j flere filer",allowAccessDescription:"For at kunne tage billeder eller video med dit kamera, skal du tillade adgang til dit kamera for denne side.",allowAccessTitle:"Venligst giv adgang til dit kamera",authenticateWith:"Forbind til %{pluginName}",authenticateWithTitle:"Venligst autentificer med %{pluginName} for at v\xE6lge filer",back:"Tilbage",browse:"gennemse",browseFiles:"gennemse",cancel:"Annuller",cancelUpload:"Annuller upload",chooseFiles:"V\xE6lg filer",closeModal:"Luk Modal",companionError:"Forbindelse til Companion fejlede",complete:"Afsluttet",connectedToInternet:"Forbundet til internettet",copyLink:"Kopier link",copyLinkToClipboardFallback:"Kopier URLen forneden",copyLinkToClipboardSuccess:"Link kopieret til udklipsholderen",creatingAssembly:"Forbereder upload...",creatingAssemblyFailed:"Transloadit: Kunne ikke oprette Assembly",dashboardTitle:"Fil Uploader",dashboardWindowTitle:"Fil Uploader Vindue (Tryk escape for at lukke)",dataUploadedOfTotal:"%{complete} af %{total}",done:"F\xE6rdig",dropHereOr:"Tr\xE6k filer her eller %{browse}",dropHint:"Tr\xE6k dine filer her",dropPasteBoth:"Tr\xE6k filer her, s\xE6t ind eller %{browse}",dropPasteFiles:"Tr\xE6k filer her, s\xE6t ind eller %{browse}",dropPasteFolders:"Tr\xE6k filer her, s\xE6t ind eller %{browse}",dropPasteImportBoth:"Tr\xE6k filer her, s\xE6t ind, %{browse} eller importer fra",dropPasteImportFiles:"Tr\xE6k filer her, s\xE6t ind, %{browse} eller importer fra",dropPasteImportFolders:"Tr\xE6k filer her, s\xE6t ind, %{browse} eller importer fra",editFile:"Rediger fil",editing:"Redigerer %{file}",emptyFolderAdded:"Ingen filer blev tilf\xF8jet fra en tom mappe",encoding:"Encoding...",enterCorrectUrl:"Forkert URL: Venligst s\xF8rg for at du indtaster et direkte link til en fil",enterUrlToImport:"Indtast URL for at importerer en fil",exceedsSize:"Denne fil overskrider den maksimale tilladte st\xF8rrelse af %{size}",failedToFetch:"Companion kunne ikke hente denne URL, venligst unders\xF8g om denne er korrekt",failedToUpload:"Fejlede upload af %{file}",fileSource:"Fil kilde: %{name}",filesUploadedOfTotal:{0:"%{complete} af %{smart_count} filer uploaded",1:"%{complete} af %{smart_count} fil uploaded",2:"%{complete} af %{smart_count} filer uploaded"},filter:"Filter",finishEditingFile:"F\xE6rddigg\xF8r redigering af fil",folderAdded:{0:"Tilf\xF8jet %{smart_count} filer fra %{folder}",1:"Tilf\xF8jet %{smart_count} fil fra %{folder}",2:"Tilf\xF8jet %{smart_count} filer fra %{folder}"},import:"Importer",importFrom:"Importer fra %{name}",loading:"Loading...",logOut:"Log ud",myDevice:"Min enhed",noFilesFound:"Du har ingen filer eller mapper her",noInternetConnection:"Ingen Internet forbindelse",openFolderNamed:"\xC5ben mappe %{name}",pause:"Pause",pauseUpload:"Pause upload",paused:"Sat p\xE5 pause",poweredBy:"Drevet af %{uppy}",processingXFiles:{0:"Behandler %{smart_count} filer",1:"Behandler %{smart_count} fil",2:"Behandler %{smart_count} filer"},removeFile:"Fjern fil",resetFilter:"Nulstil filter",resume:"Genoptag",resumeUpload:"Genoptag upload",retry:"Fors\xF8g igen",retryUpload:"Fors\xF8g upload igen",saveChanges:"Gem \xE6ndringer",selectFileNamed:"V\xE6lg fil %{name}",selectX:{0:"V\xE6lg %{smart_count}",1:"V\xE6lg %{smart_count}",2:"V\xE6lg %{smart_count}"},smile:"Smil!",startRecording:"Start video optagelse",stopRecording:"Stop video optagelse",takePicture:"Tag et billede",timedOut:"Upload g\xE5et i st\xE5 for %{seconds} sekunder, afbryder.",unselectFileNamed:"Afmarker filen %{name}",upload:"Upload",uploadComplete:"Upload f\xE6rdig",uploadFailed:"Upload fejlede",uploadPaused:"Upload sat p\xE5 pause",uploadXFiles:{0:"Upload %{smart_count} fil",1:"Upload %{smart_count} filer",2:"Upload %{smart_count} filer"},uploadXNewFiles:{0:"Upload +%{smart_count} fil",1:"Upload +%{smart_count} filer",2:"Upload +%{smart_count} filer"},uploading:"Uploader",uploadingXFiles:{0:"Uploader %{smart_count} fil",1:"Uploader %{smart_count} filer",2:"Uploader %{smart_count} filer"},xFilesSelected:{0:"%{smart_count} fil valgt",1:"%{smart_count} filer valgt",2:"%{smart_count} filer valgt"},xMoreFilesAdded:{0:"%{smart_count} flere filer tilf\xF8jet",1:"%{smart_count} flere filer tilf\xF8jet",2:"%{smart_count} flere filer tilf\xF8jet"},xTimeLeft:"%{time} tilbage",youCanOnlyUploadFileTypes:"Du kan kun uploade: %{types}",youCanOnlyUploadX:{0:"Du kan kun uploade %{smart_count} fil",1:"Du kan kun uploade %{smart_count} filer",2:"Du kan kun uploade %{smart_count} filer"},youHaveToAtLeastSelectX:{0:"Du skal v\xE6lge mindst %{smart_count} fil",1:"Du skal v\xE6lge mindst %{smart_count} filer",2:"Du skal v\xE6lge mindst %{smart_count} filer"}};typeof Uppy<"u"&&(globalThis.Uppy.locales.da_DK=e);var r=e;})();
//# sourceMappingURL=da_DK.min.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
(()=>{var e={pluralize(i){return i===1?0:1}};e.strings={addMoreFiles:"Aggiungi pi\xF9 file",addingMoreFiles:"Sto aggiungendo altri file",allowAccessDescription:"Per acquisire foto o video con la tua fotocamera, abilitane l'accesso da questo sito.",allowAccessTitle:"Abilita l'accesso alla fotocamera",authenticateWith:"Connetti a %{pluginName}",authenticateWithTitle:"Autenticati con %{pluginName} per selezionare i file",back:"Indietro",addMore:"Aggiungi pi\xF9",browse:"sfoglia",browseFiles:"sfoglia",cancel:"Annulla",cancelUpload:"Annulla upload",chooseFiles:"Scegli i file",closeModal:"Chiudi modale",companionError:"Connessione con Companion fallita",complete:"Completato",connectedToInternet:"Connesso a internet",copyLink:"Copia link",copyLinkToClipboardFallback:"Copia l'URL sottostante",copyLinkToClipboardSuccess:"Link copiato",creatingAssembly:"Upload in preparazione...",creatingAssemblyFailed:"Transloadit: Non ho potuto creare l'Assembly",dashboardTitle:"File Uploader",dashboardWindowTitle:"File Uploader (Premi Esc per chiudere)",dataUploadedOfTotal:"%{complete} di %{total}",done:"Fatto",dropHereOr:"Trascina i file qui o %{browse}",dropHint:"Trascina i file qui",dropPasteBoth:"Trascina i file qui, incolla o %{browse}",dropPasteFiles:"Trascina i file qui, incolla o %{browse}",dropPasteFolders:"Trascina i file qui, incolla o %{browse}",dropPasteImportBoth:"Trascina i file qui, incolla, %{browse} o importa da",dropPasteImportFiles:"Trascina i file qui, incolla, %{browse} o importa da",dropPasteImportFolders:"Trascina i file qui, incolla, %{browse} o importa da",editFile:"Modifica file",editing:"Modifica %{file}",emptyFolderAdded:"Nessun file aggiunto dalla cartella vuota",encoding:"Encoding...",enterCorrectUrl:"URL non corretta: assicurati che sia un link diretto ad un file",enterUrlToImport:"Immetti l'URL per importare un file",exceedsSize:"Questo file supera la dimensione massima di %{size}",failedToFetch:"Impossibile verificare questa URL, assicurati che sia corretta",failedToUpload:"Upload del file %{file} non riuscito",fileSource:"Sorgente file: %{name}",filesUploadedOfTotal:{0:"%{complete} di %{smart_count} file caricato",1:"%{complete} di %{smart_count} file caricati",2:"%{complete} di %{smart_count} file caricati"},filter:"Filter",finishEditingFile:"Finish editing file",folderAdded:{0:"Aggiunto %{smart_count} file da %{folder}",1:"Aggiunti %{smart_count} file da %{folder}",2:"Aggiunti %{smart_count} file da %{folder}"},import:"Importa",importFrom:"Importa da %{name}",loading:"Caricamento...",logOut:"Logout",myDevice:"Il mio computer",noFilesFound:"Non hai file o cartelle qui",noInternetConnection:"Nessuna connessione a internet",pause:"Pausa",pauseUpload:"Pausa upload",paused:"In pausa",poweredBy:"Powered by %{uppy}",processingXFiles:{0:"Sto processando %{smart_count} file",1:"Sto processando %{smart_count} file",2:"Sto processando %{smart_count} file"},removeFile:"Rimuovi il file",resetFilter:"Ripristina filtro",resume:"Riprendi",resumeUpload:"Riprendi l'upload",retry:"Riprova",retryUpload:"Riprova l'upload",saveChanges:"Salva le modifiche",selectX:{0:"Seleziona %{smart_count}",1:"Seleziona %{smart_count}",2:"Seleziona %{smart_count}"},smile:"Sorridi!",startRecording:"Inizia la registrazione del video",stopRecording:"Interrompi la registrazione del video",takePicture:"Scatta una foto",timedOut:"Upload fermo da %{seconds} secondi, sto annullando.",upload:"Upload",uploadComplete:"Upload completato",uploadFailed:"Upload non riuscito",uploadPaused:"Upload in pausa",uploadXFiles:{0:"Upload di %{smart_count} file",1:"Upload di %{smart_count} file",2:"Upload di %{smart_count} file"},uploadXNewFiles:{0:"Upload +%{smart_count} file",1:"Upload +%{smart_count} file",2:"Upload +%{smart_count} file"},uploading:"In caricamento",uploadingXFiles:{0:"Caricando %{smart_count} file",1:"Caricando %{smart_count} file",2:"Caricando %{smart_count} file"},xFilesSelected:{0:"%{smart_count} file selezionato",1:"%{smart_count} file selezionati",2:"%{smart_count} file selezionati"},xMoreFilesAdded:{0:"%{smart_count} alto file aggiunto",1:"%{smart_count} altri file aggiunti",2:"%{smart_count} ltri file aggiunti"},xTimeLeft:"%{time} rimasto",youCanOnlyUploadFileTypes:"Puoi caricare solamente: %{types}",youCanOnlyUploadX:{0:"Puoi caricare %{smart_count} solo file",1:"Puoi caricare solo %{smart_count} file",2:"Puoi caricare solo %{smart_count} file"},youHaveToAtLeastSelectX:{0:"Devi selezionare almeno %{smart_count} file",1:"Devi selezionare almeno %{smart_count} file",2:"Devi selezionare almeno %{smart_count} file"},selectFileNamed:"Seleziona il file %{name}",unselectFileNamed:"Deseleziona il file %{name}",openFolderNamed:"Cartella aperta %{name}"};typeof Uppy<"u"&&(globalThis.Uppy.locales.it_IT=e);var o=e;})();
//# sourceMappingURL=it_IT.min.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
(()=>{var e={pluralize(o){return o===1?0:1}};e.strings={addMore:"Adicionar mais",addMoreFiles:"Adicionar mais ficheiros",addingMoreFiles:"A adicionar mais ficheiros",allowAccessDescription:"Para poder tirar fotos e gravar v\xEDdeos com a sua c\xE2mera, por favor permita que este site a acesse.",allowAccessTitle:"Por favor permita o acesso \xE0 sua c\xE2mera",authenticateWith:"Ligar a %{pluginName}",authenticateWithTitle:"Por favor ligue-se a %{pluginName} para selecionar ficheiros",back:"Voltar",browse:"procure",browseFiles:"procure",cancel:"Cancelar",cancelUpload:"Cancelar envio de ficheiros",chooseFiles:"Selecionar ficheiros",closeModal:"Fechar Modal",companionError:"Falha na conex\xE3o com servi\xE7o",complete:"Conclu\xEDdo",connectedToInternet:"Ligado \xE0 internet",copyLink:"Copiar link",copyLinkToClipboardFallback:"Copiar URL abaixo",copyLinkToClipboardSuccess:"Link copiado para a \xE1rea de transfer\xEAncia",creatingAssembly:"A preparar o envio de ficheiros...",creatingAssemblyFailed:"Transloadit: N\xE3o foi poss\xEDvel criar o Assembly",dashboardTitle:"Envio de ficheiros",dashboardWindowTitle:"Janela para envio de ficheiros (Pressione esc para fechar)",dataUploadedOfTotal:"%{complete} de %{total}",done:"Concluir",dropHereOr:"Arraste ficheiros ou %{browse}",dropHint:"Pode simplesmente arrastar os seus ficheiros para aqui",dropPasteBoth:"Arraste ficheiros, cole ou %{browse}",dropPasteFiles:"Arraste ficheiros, cole ou %{browse}",dropPasteFolders:"Arraste ficheiros, cole ou %{browse}",dropPasteImportBoth:"Arraste ficheiros, cole, %{browse} ou importe de",dropPasteImportFiles:"Arraste ficheiros, cole, %{browse} ou importe de",dropPasteImportFolders:"Arraste ficheiros, cole, %{browse} ou importe de",editFile:"Editar ficheiro",editing:"A editar %{file}",emptyFolderAdded:"A pasta est\xE1 vazia e nenhum ficheiro foi adicionado.",encoding:"A codificar...",enterCorrectUrl:"URL incorrecto: Por favor garanta que inseriu um link direto para um ficheiro",enterUrlToImport:"Coloque o URL para importar um ficheiro",exceedsSize:"Este ficheiro excedeu o tamanho m\xE1ximo permitido %{size}",failedToFetch:"Servi\xE7o falhou ao fazer fetch deste URL. Por favor garante que o URL est\xE1 correto",failedToUpload:"Falha ao enviar %{file}",fileSource:"Origem do ficheiro: %{name}",filesUploadedOfTotal:{0:"%{complete} de %{smart_count} ficheiro enviado",1:"%{complete} de %{smart_count} ficheiros enviados"},filter:"Filtrar",finishEditingFile:"Concluir edi\xE7\xE3o de ficheiro",folderAdded:{0:"Adicionado %{smart_count} ficheiro de %{folder}",1:"Adicionado %{smart_count} ficheiros de %{folder}"},import:"Importar",importFrom:"Importar de %{name}",loading:"A carregar...",logOut:"Sair",myDevice:"O meu dispositivo",noFilesFound:"N\xE3o possui ficheiros ou pastas aqui",noInternetConnection:"Sem liga\xE7\xE3o \xE0 internet",pause:"Pausar",pauseUpload:"Pausar envio de ficheiros",paused:"Pausado",poweredBy:"Desenvolvido por %{uppy}",processingXFiles:{0:"A processar %{smart_count} ficheiro",1:"A processar %{smart_count} ficheiros"},removeFile:"Remover ficheiro",resetFilter:"Limpar filtro",resume:"Retomar",resumeUpload:"Retomar envio de ficheiros",retry:"Tentar novamente",retryUpload:"Tentar enviar novamente",saveChanges:"Salvar altera\xE7\xF5es",selectX:{0:"Selecionar %{smart_count}",1:"Selecionar %{smart_count}"},smile:"Sorria!",startRecording:"Come\xE7ar grava\xE7\xE3o de v\xEDdeo",stopRecording:"Parar grava\xE7\xE3o de v\xEDdeo",takePicture:"Tirar uma foto",timedOut:"Envio de ficheiros parado h\xE1 %{seconds} segundos, a abortar.",upload:"Enviar ficheiros",uploadComplete:"Envio de ficheiros finalizado",uploadFailed:"Envio de ficheiros falhou",uploadPaused:"Envio de ficheiros pausado",uploadXFiles:{0:"Enviar %{smart_count} ficheiro",1:"Enviar %{smart_count} ficheiros"},uploadXNewFiles:{0:"Enviar +%{smart_count} ficheiro",1:"Enviar +%{smart_count} ficheiros"},uploading:"A enviar",uploadingXFiles:{0:"A enviar %{smart_count} ficheiro",1:"A enviar %{smart_count} ficheiros"},xFilesSelected:{0:"%{smart_count} ficheiro selecionado",1:"%{smart_count} ficheiros selecionados"},xMoreFilesAdded:{0:"%{smart_count} ficheiro adicionados",1:"%{smart_count} ficheiros adicionados"},xTimeLeft:"%{time} restantes",youCanOnlyUploadFileTypes:"S\xF3 pode enviar ficheiros: %{types}",youCanOnlyUploadX:{0:"S\xF3 pode enviar %{smart_count} ficheiro",1:"S\xF3 pode enviar %{smart_count} ficheiros"},youHaveToAtLeastSelectX:{0:"Precisa de selecionar pelo menos %{smart_count} ficheiro",1:"Precisa de selecionar pelo menos %{smart_count} ficheiros"},selectFileNamed:"Selecione o ficheiro %{name}",unselectFileNamed:"Deselecionar ficheiro %{name}",openFolderNamed:"Pasta aberta %{name}"};typeof Uppy<"u"&&(globalThis.Uppy.locales.pt_PT=e);var r=e;})();
//# sourceMappingURL=pt_PT.min.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long