Neubau Fundament + Startseite: Designsystem, PHP-Komponenten, Brevo-Formular, Instagram-Sync
- Ordnerstruktur mit public/-Docroot, Deny-.htaccess für app/bin/config/data/storage
- CLAUDE.md mit Leitplanken (self-hosted only, Single Source of Truth, Component-first)
- Design-Tokens aus alter Seite extrahiert (Akzent #e20612, Coolvetica/Abel als woff2)
- Front Controller mit Routen-Register, Sitemap, Canonical, JSON-LD (SportsClub)
- Startseite: Hero, Instagram-Feed (lokaler Cache), Historie/Sportheim, Stats, Partner, Kontakt
- Kontaktformular via PHPMailer/Brevo mit Honeypot + HMAC-Time-Trap (kein reCAPTCHA)
- bin/instagram-sync.php: Scraper mit Strategie-Kette, flock, atomarem Cache, lokalen Bildern
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 21:16:25 +02:00
|
|
|
/* ============================================================
|
|
|
|
|
COMPONENTS — eine Sektion pro Komponente, Banner-Kommentare
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
|
|
|
|
/* === hero === */
|
|
|
|
|
.hero {
|
|
|
|
|
position: relative;
|
|
|
|
|
display: grid;
|
|
|
|
|
align-items: end;
|
|
|
|
|
min-height: min(92vh, 900px);
|
|
|
|
|
padding-block: calc(var(--header-h) + 80px) var(--space-section);
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hero__media {
|
|
|
|
|
position: absolute;
|
|
|
|
|
inset: 0;
|
|
|
|
|
z-index: -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hero__img {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
object-fit: cover;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-11 21:23:29 +02:00
|
|
|
.hero__video {
|
|
|
|
|
position: absolute;
|
|
|
|
|
inset: 0;
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
object-fit: cover;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
|
|
|
.hero__video {
|
|
|
|
|
display: none;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Neubau Fundament + Startseite: Designsystem, PHP-Komponenten, Brevo-Formular, Instagram-Sync
- Ordnerstruktur mit public/-Docroot, Deny-.htaccess für app/bin/config/data/storage
- CLAUDE.md mit Leitplanken (self-hosted only, Single Source of Truth, Component-first)
- Design-Tokens aus alter Seite extrahiert (Akzent #e20612, Coolvetica/Abel als woff2)
- Front Controller mit Routen-Register, Sitemap, Canonical, JSON-LD (SportsClub)
- Startseite: Hero, Instagram-Feed (lokaler Cache), Historie/Sportheim, Stats, Partner, Kontakt
- Kontaktformular via PHPMailer/Brevo mit Honeypot + HMAC-Time-Trap (kein reCAPTCHA)
- bin/instagram-sync.php: Scraper mit Strategie-Kette, flock, atomarem Cache, lokalen Bildern
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 21:16:25 +02:00
|
|
|
/* Dunkler Verlauf wie auf der alten Seite: oben transparent → unten Seitenhintergrund */
|
|
|
|
|
.hero__media::after {
|
|
|
|
|
content: '';
|
|
|
|
|
position: absolute;
|
|
|
|
|
inset: 0;
|
|
|
|
|
background: linear-gradient(180deg, rgb(20 20 20 / 0.25) 0%, rgb(20 20 20 / 0.55) 55%, var(--clr-bg) 100%);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hero__content {
|
|
|
|
|
width: 100%;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hero__title {
|
|
|
|
|
text-shadow: 0 2px 24px rgb(0 0 0 / 0.5);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hero__text {
|
|
|
|
|
margin-top: 1rem;
|
|
|
|
|
max-width: 60ch;
|
|
|
|
|
text-shadow: 0 1px 12px rgb(0 0 0 / 0.6);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hero__actions {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
gap: 0.75rem;
|
|
|
|
|
margin-top: 1.75rem;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-11 21:24:45 +02:00
|
|
|
/* Variante: Text mittig zentriert (z. B. Startseite) */
|
|
|
|
|
.hero--center {
|
|
|
|
|
align-items: center;
|
|
|
|
|
text-align: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hero--center .hero__text {
|
|
|
|
|
margin-inline: auto;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hero--center .hero__actions {
|
|
|
|
|
justify-content: center;
|
|
|
|
|
}
|
|
|
|
|
|
Neubau Fundament + Startseite: Designsystem, PHP-Komponenten, Brevo-Formular, Instagram-Sync
- Ordnerstruktur mit public/-Docroot, Deny-.htaccess für app/bin/config/data/storage
- CLAUDE.md mit Leitplanken (self-hosted only, Single Source of Truth, Component-first)
- Design-Tokens aus alter Seite extrahiert (Akzent #e20612, Coolvetica/Abel als woff2)
- Front Controller mit Routen-Register, Sitemap, Canonical, JSON-LD (SportsClub)
- Startseite: Hero, Instagram-Feed (lokaler Cache), Historie/Sportheim, Stats, Partner, Kontakt
- Kontaktformular via PHPMailer/Brevo mit Honeypot + HMAC-Time-Trap (kein reCAPTCHA)
- bin/instagram-sync.php: Scraper mit Strategie-Kette, flock, atomarem Cache, lokalen Bildern
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 21:16:25 +02:00
|
|
|
/* === instagram === */
|
|
|
|
|
.instagram__grid {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
|
|
|
gap: 1rem;
|
|
|
|
|
margin-top: 2rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media (max-width: 600px) {
|
|
|
|
|
.instagram__grid {
|
|
|
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
|
|
|
gap: 0.75rem;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.instagram__link {
|
|
|
|
|
position: relative;
|
|
|
|
|
display: block;
|
|
|
|
|
border-radius: var(--radius-card);
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
box-shadow: var(--shadow-card);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.instagram__link img {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: auto;
|
2026-06-11 21:29:36 +02:00
|
|
|
/* Instagram-Portrait 1080x1350 */
|
|
|
|
|
aspect-ratio: 4 / 5;
|
Neubau Fundament + Startseite: Designsystem, PHP-Komponenten, Brevo-Formular, Instagram-Sync
- Ordnerstruktur mit public/-Docroot, Deny-.htaccess für app/bin/config/data/storage
- CLAUDE.md mit Leitplanken (self-hosted only, Single Source of Truth, Component-first)
- Design-Tokens aus alter Seite extrahiert (Akzent #e20612, Coolvetica/Abel als woff2)
- Front Controller mit Routen-Register, Sitemap, Canonical, JSON-LD (SportsClub)
- Startseite: Hero, Instagram-Feed (lokaler Cache), Historie/Sportheim, Stats, Partner, Kontakt
- Kontaktformular via PHPMailer/Brevo mit Honeypot + HMAC-Time-Trap (kein reCAPTCHA)
- bin/instagram-sync.php: Scraper mit Strategie-Kette, flock, atomarem Cache, lokalen Bildern
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 21:16:25 +02:00
|
|
|
object-fit: cover;
|
|
|
|
|
transition: transform var(--transition);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.instagram__link:hover img,
|
|
|
|
|
.instagram__link:focus-visible img {
|
|
|
|
|
transform: scale(1.05);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.instagram__badge {
|
|
|
|
|
position: absolute;
|
|
|
|
|
top: 0.75rem;
|
|
|
|
|
right: 0.75rem;
|
|
|
|
|
display: grid;
|
|
|
|
|
place-items: center;
|
|
|
|
|
width: 2rem;
|
|
|
|
|
height: 2rem;
|
|
|
|
|
background: rgb(0 0 0 / 0.6);
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
font-size: 0.8rem;
|
|
|
|
|
color: var(--clr-text);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.instagram__fallback {
|
|
|
|
|
margin-top: 1.5rem;
|
|
|
|
|
padding: 2.5rem;
|
|
|
|
|
background: var(--clr-glass-bg);
|
|
|
|
|
border: 1px solid var(--clr-glass-border);
|
|
|
|
|
border-radius: var(--radius-card);
|
|
|
|
|
text-align: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.instagram__fallback p {
|
|
|
|
|
margin-inline: auto;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.instagram__fallback .btn {
|
|
|
|
|
margin-top: 1rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* === split (Bild/Text-Sektion) === */
|
|
|
|
|
.split__inner {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 3rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.split--flip .split__text {
|
|
|
|
|
order: 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.split--flip .split__media {
|
|
|
|
|
order: 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.split__text p {
|
|
|
|
|
margin-top: 1rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.split__cta {
|
|
|
|
|
margin-top: 1.5rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.split__img {
|
|
|
|
|
width: 100%;
|
|
|
|
|
border-radius: var(--radius-card);
|
|
|
|
|
box-shadow: var(--shadow-card);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media (max-width: 992px) {
|
|
|
|
|
.split__inner {
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
gap: 2rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.split--flip .split__text {
|
|
|
|
|
order: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.split--flip .split__media {
|
|
|
|
|
order: 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* === stats === */
|
|
|
|
|
.stats {
|
|
|
|
|
background: var(--clr-bg-deep);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.stats__list {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
|
|
|
gap: 2rem;
|
|
|
|
|
text-align: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media (max-width: 600px) {
|
|
|
|
|
.stats__list {
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.stats__item {
|
|
|
|
|
display: grid;
|
|
|
|
|
gap: 0.25rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.stats__value {
|
|
|
|
|
font-family: var(--ff-heading);
|
|
|
|
|
font-size: var(--fs-800);
|
|
|
|
|
line-height: var(--lh-heading);
|
|
|
|
|
color: var(--clr-accent);
|
|
|
|
|
text-shadow: 0 0 30px rgb(var(--clr-accent-rgb) / 0.35);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.stats__label {
|
|
|
|
|
font-size: var(--fs-500);
|
|
|
|
|
text-transform: uppercase;
|
|
|
|
|
letter-spacing: 0.08em;
|
|
|
|
|
color: var(--clr-text-muted);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* === partners === */
|
|
|
|
|
.partners__grid {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: repeat(auto-fit, minmax(180px, 220px));
|
|
|
|
|
justify-content: center;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 2rem;
|
|
|
|
|
margin-block: 2.5rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.partners__item {
|
|
|
|
|
display: grid;
|
|
|
|
|
place-items: center;
|
|
|
|
|
padding: 1.5rem;
|
|
|
|
|
/* Dunkles Glas — die Partner-Logos sind weiße Varianten */
|
|
|
|
|
background: var(--clr-glass-bg);
|
|
|
|
|
border: 1px solid var(--clr-glass-border);
|
|
|
|
|
border-radius: var(--radius-card);
|
|
|
|
|
min-height: 120px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.partners__item img {
|
|
|
|
|
max-height: 80px;
|
|
|
|
|
width: auto;
|
|
|
|
|
max-width: 100%;
|
|
|
|
|
object-fit: contain;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* === contact form === */
|
|
|
|
|
.contact__inner {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
|
|
|
|
|
gap: 3rem;
|
|
|
|
|
align-items: start;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media (max-width: 992px) {
|
|
|
|
|
.contact__inner {
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.contact__intro p {
|
|
|
|
|
margin-top: 1rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form {
|
|
|
|
|
display: grid;
|
|
|
|
|
gap: 1.25rem;
|
|
|
|
|
padding: 2rem;
|
|
|
|
|
background: var(--clr-glass-bg);
|
|
|
|
|
border: 1px solid var(--clr-glass-border);
|
|
|
|
|
border-radius: var(--radius-card);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form__row {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
|
|
|
|
gap: 1.25rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media (max-width: 600px) {
|
|
|
|
|
.form__row {
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form__field {
|
|
|
|
|
display: grid;
|
|
|
|
|
gap: 0.4rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form__field label {
|
|
|
|
|
font-size: var(--fs-500);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form__field input,
|
|
|
|
|
.form__field select,
|
|
|
|
|
.form__field textarea {
|
|
|
|
|
width: 100%;
|
|
|
|
|
padding: 10px 12px;
|
|
|
|
|
background: var(--clr-glass-bg);
|
|
|
|
|
border: 1px solid var(--clr-glass-border);
|
|
|
|
|
border-radius: var(--radius-btn);
|
|
|
|
|
color: var(--clr-text);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form__field select option {
|
|
|
|
|
background: var(--clr-bg);
|
|
|
|
|
color: var(--clr-text);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form__field textarea {
|
|
|
|
|
resize: vertical;
|
|
|
|
|
min-height: 8rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form__field--checkbox {
|
|
|
|
|
grid-template-columns: auto 1fr;
|
|
|
|
|
align-items: start;
|
|
|
|
|
gap: 0.6rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form__field--checkbox input {
|
|
|
|
|
width: 1.25rem;
|
|
|
|
|
height: 1.25rem;
|
|
|
|
|
margin-top: 0.2rem;
|
|
|
|
|
accent-color: var(--clr-accent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form__field--checkbox label {
|
|
|
|
|
font-size: var(--fs-400);
|
|
|
|
|
color: var(--clr-text-muted);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form__status:empty {
|
|
|
|
|
display: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form__success {
|
|
|
|
|
padding: 0.75rem 1rem;
|
|
|
|
|
border: 1px solid var(--clr-success);
|
|
|
|
|
border-radius: var(--radius-btn);
|
|
|
|
|
color: var(--clr-success);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form__error {
|
|
|
|
|
padding: 0.75rem 1rem;
|
|
|
|
|
border: 1px solid var(--clr-error);
|
|
|
|
|
border-radius: var(--radius-btn);
|
|
|
|
|
color: var(--clr-error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form__submit {
|
|
|
|
|
margin: 0;
|
|
|
|
|
}
|