Unterseiten: Fußball-Übersicht, Mannschaften, Jugend, Verein, Rechtliches

Neue Seiten + Routen: fussball, fussball/{erste-mannschaft,zweite-mannschaft,
damen}, jugendfussball, verein, impressum, datenschutz. Dazu die Komponenten
team, team-cards/-roster/-photo/-bento, faq/faq-contact, key-facts, age-groups,
cta-band, training-location und der contact-slider.

Daten in teams/fussball/jugend/verein.json; club.json um Vorstand, Bankdaten,
Datenschutz-Kontakt erweitert. person-grid bekommt $names-Filter, partner-grid
einen Intro-Stil. Seiten setzen $meta['schema'] via team_/page_schema.
Styles für alle neuen Komponenten in components.css.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KDQZ6FuchNUh2bxSW9PeNv
This commit is contained in:
2026-06-19 08:13:04 +02:00
parent a933b76c4f
commit 3b6f630a72
81 changed files with 2513 additions and 78 deletions

View File

@@ -0,0 +1,75 @@
/* Ansprechpartner-Mini-Slider: zeigt bei mehreren Kontakten nur eine Karte und
wechselt automatisch durch. Progressive Enhancement:
- ohne JS bleiben alle Karten gestapelt sichtbar (kein Info-Verlust),
- bei prefers-reduced-motion findet keine Enhancement/Auto-Rotation statt
(alle Karten bleiben sichtbar),
- Pause bei Hover/Fokus, Punkte zur manuellen Auswahl. */
(function () {
'use strict';
var root = document.querySelector('[data-contact-slider]');
if (!root) {
return;
}
var slides = Array.prototype.slice.call(root.querySelectorAll('[data-contact-slide]'));
if (slides.length < 2) {
return;
}
// Bewegungsreduzierung: nicht enhancen → alle Karten bleiben sichtbar.
if (window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
return;
}
var dots = Array.prototype.slice.call(root.querySelectorAll('[data-contact-dot]'));
var INTERVAL = 5000;
var current = 0;
var timer = null;
function show(n) {
current = (n + slides.length) % slides.length;
slides.forEach(function (slide, idx) {
var active = idx === current;
slide.hidden = !active;
slide.classList.toggle('is-active', active);
});
dots.forEach(function (dot, idx) {
if (idx === current) {
dot.setAttribute('aria-current', 'true');
} else {
dot.removeAttribute('aria-current');
}
});
}
function stop() {
if (timer) {
window.clearInterval(timer);
timer = null;
}
}
function start() {
stop();
timer = window.setInterval(function () {
show(current + 1);
}, INTERVAL);
}
dots.forEach(function (dot, idx) {
dot.addEventListener('click', function () {
show(idx);
start();
});
});
root.addEventListener('mouseenter', stop);
root.addEventListener('mouseleave', start);
root.addEventListener('focusin', stop);
root.addEventListener('focusout', start);
root.classList.add('contact-slider--ready');
show(0);
start();
})();