"Event des Jahres": Aktivieren-Schalter, leer bis befuellt, Detail-Fenster

Nutzer-Wunsch 20.08.2026: "diese zwei kisten sollen leer sein solang wie
ich nichts rein setze, am besten sollen die sogar immer nur erscheinen
wenn ich was rein setze und sie aktiviere ... wen ich drauf druecke dass
dann ein kleines fenster aufgeht wo das bild bissl groesser ist mit einem
groesseren text und beschreibung, und mit einem link ... die kacheln
sollen auch bissl spezieller sein."

- Kein hartkodierter Standardinhalt mehr auf der Startseite -- die Kachel
  UND der ganze Abschnitt bleiben komplett unsichtbar, bis mindestens ein
  Event in der Verwaltung ausgefuellt UND ueber einen neuen "Aktiv"-Schalter
  freigeschaltet ist. Genau 1 aktives Event -> zentrierte Einzelkachel
  statt halbleerem Zwei-Spalten-Raster.
- Klick auf eine Kachel oeffnet jetzt ein Detail-Fenster (groesseres Bild,
  groesserer Titel/Text, optionaler direkter Link) statt sofort
  wegzunavigieren.
- Kacheln bekommen einen goldenen Trophaeen-Akzent + dezenten wandernden
  Lichtschimmer statt der neutralen Standardkarten-Optik.
- Bugfix unterwegs gefunden (Playwright-Screenshot): .jahres-event-card
  blieb trotz [hidden]-Attribut sichtbar (dieselbe Ursache wie der
  frühere .jahres-event-bild-Bug: display:block ueberschreibt die
  eingebaute [hidden]-Regel bei gleicher Spezifitaet) -- explizite
  [hidden]-Regel ergaenzt.
- Backend: server-internal/routes/events.js liefert oeffentlich NUR noch
  aktivierte Slots aus (getEventsPublic), neuer authentifizierter Endpunkt
  getEventsAdmin liefert der Verwaltung auch Entwuerfe zum Vorausfuellen.
  10 automatisierte Tests gegen eine Fake-DB bestanden.

Backend-Teil (server-internal/) noch ohne Deploy-Zugriff -- Dogi muss ihn
manuell auf dogiintern ausrollen, sonst bleibt die Startseite beim alten
Verhalten (immer beide Slots zeigen, kein Aktiv-Schalter in der Verwaltung).

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-08-20 22:43:28 +02:00
co-authored by Claude Opus 5
parent 208b5ba4ed
commit b3e191d3ca
39 changed files with 545 additions and 318 deletions
+128 -6
View File
@@ -1613,18 +1613,57 @@ header.site-header {
gap: 1.2rem;
}
@media (max-width: 760px) { .jahres-events-grid { grid-template-columns: 1fr; } }
/* Nutzer-Wunsch 20.08.2026: "die kacheln sollen auch bissl spezieller sein" —
goldener Trophäen-Akzent statt der neutralen Standard-Kartenoptik (eigener,
gedeckter Farbton, kein grelles Gold — augenschonend), plus ein dezenter
wandernder Lichtschimmer oben (".jahres-event-shine"), der die Kachel als
etwas Besonderes markiert statt als normale Karte. Jetzt ein <button>
(öffnet ein Detail-Fenster) statt eines <a> (navigierte sofort weg) —
deshalb hier zusätzlich ein vollständiger Button-Reset. */
/* [hidden] explizit VOR der Klassenregel + als eigene Regel danach: ein
simples "display:block" in .jahres-event-card hat dieselbe Spezifität
wie die eingebaute [hidden]-UA-Regel des Browsers und würde sie sonst im
Zweifel überschreiben (identischer Bug wie schon bei .jahres-event-bild
weiter unten, hier per Playwright-Screenshot erneut gefunden — eine
"leere" Kachel blieb trotz hidden-Attribut sichtbar). */
.jahres-event-card[hidden] { display: none; }
.jahres-event-card {
display: block;
width: 100%;
text-align: left;
font: inherit;
color: inherit;
cursor: pointer;
position: relative;
overflow: hidden;
isolation: isolate;
padding: 1.2rem 1.4rem;
border-radius: calc(var(--radius) - 4px);
border: 1px solid var(--border);
background: rgba(255, 255, 255, .02);
transition: border-color .15s ease, transform .15s ease;
border: 1px solid rgba(212, 175, 55, .35);
background:
radial-gradient(circle at 15% 0%, rgba(212, 175, 55, .08), transparent 55%),
rgba(255, 255, 255, .02);
transition: border-color .2s ease, transform .2s ease, box-shadow .2s ease;
}
.jahres-event-card:hover { border-color: var(--accent); transform: translateY(-3px); }
.jahres-event-card:hover, .jahres-event-card:focus-visible {
border-color: rgba(212, 175, 55, .7);
transform: translateY(-3px);
box-shadow: 0 10px 26px rgba(0, 0, 0, .35), 0 0 22px rgba(212, 175, 55, .18);
}
.jahres-event-shine {
content: "";
position: absolute;
top: 0; left: 6%; right: 6%;
height: 1px;
background: linear-gradient(90deg, transparent, rgba(255, 214, 102, .9), transparent);
animation: jahres-event-goldglanz 4.5s ease-in-out infinite;
pointer-events: none;
}
@keyframes jahres-event-goldglanz { 0%, 100% { opacity: .3; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .jahres-event-shine { animation: none; opacity: .6; } }
.jahres-event-datum {
display: block;
color: var(--accent);
color: #e8c465;
font-weight: 700;
font-size: .82rem;
letter-spacing: .02em;
@@ -1632,7 +1671,16 @@ header.site-header {
}
.jahres-event-card h3 { margin: 0 0 .4rem; font-size: 1.15rem; }
.jahres-event-card p { margin: 0 0 .6rem; color: var(--text-muted); font-size: .93rem; line-height: 1.55; }
.jahres-event-mehr { color: var(--accent); font-weight: 600; font-size: .88rem; }
.jahres-event-mehr { color: #e8c465; font-weight: 600; font-size: .88rem; }
/* Genau EIN aktives Event: zentrierte, etwas größere Einzelkachel statt
halbleerem Zwei-Spalten-Raster (Nutzer-Wunsch: "spezieller"). */
.jahres-events-grid-einzeln {
grid-template-columns: 1fr;
max-width: 480px;
margin: 0 auto;
}
.jahres-events-grid-einzeln .jahres-event-card { padding: 1.6rem 1.8rem; }
.jahres-events-grid-einzeln .jahres-event-card h3 { font-size: 1.3rem; }
/* Optionales Admin-Bild pro Event (20.08.2026, "Event des Jahres" jetzt in
der Verwaltung pflegbar) — bleibt per [hidden] unsichtbar, solange kein
Bild gesetzt ist, damit die textbasierten Standard-Karten unverändert
@@ -1651,6 +1699,80 @@ header.site-header {
margin-bottom: .9rem;
}
/* ---------- "Event des Jahres" — Detail-Fenster (20.08.2026) ----------
Nutzer-Wunsch: "wen ich drauf drücke dass dein ein kleines fenster
aufgeht wo das bild bissl größer ist mit einem größeren text und
beschreibung, und mit einem link ... bereite das richtig geil krank
vor." Augenschonend gehalten (siehe Projektregel): kein grelles Weiß,
sanftes Ein-/Ausblenden statt hartem Umschalten, respektiert
prefers-reduced-motion. */
.jahres-event-modal-overlay {
position: fixed;
inset: 0;
z-index: 200;
display: flex;
align-items: center;
justify-content: center;
padding: 4vh 5vw;
background: rgba(5, 7, 11, .78);
backdrop-filter: blur(6px);
opacity: 0;
transition: opacity .22s ease;
}
.jahres-event-modal-overlay.offen { opacity: 1; }
.jahres-event-modal-overlay[hidden] { display: none; }
body.modal-offen { overflow: hidden; }
.jahres-event-modal {
position: relative;
width: min(640px, 100%);
max-height: 90vh;
overflow-y: auto;
background: var(--card-bg);
border: 1px solid rgba(212, 175, 55, .4);
border-radius: var(--radius);
box-shadow: 0 24px 60px rgba(0, 0, 0, .5), 0 0 40px rgba(212, 175, 55, .12);
transform: scale(.94) translateY(10px);
transition: transform .25s ease;
}
.jahres-event-modal-overlay.offen .jahres-event-modal { transform: scale(1) translateY(0); }
@media (prefers-reduced-motion: reduce) {
.jahres-event-modal-overlay, .jahres-event-modal { transition: none; }
}
.jahres-event-modal-close {
position: absolute;
top: .9rem; right: .9rem;
z-index: 2;
width: 38px; height: 38px;
border-radius: 50%;
border: 1px solid rgba(255, 255, 255, .25);
background: rgba(5, 7, 11, .7);
color: var(--text);
font-size: 1.1rem;
cursor: pointer;
transition: border-color .15s ease, transform .15s ease;
}
.jahres-event-modal-close:hover { border-color: rgba(212, 175, 55, .7); transform: scale(1.06); }
.jahres-event-modal-bild {
display: block;
width: 100%;
max-height: 46vh;
object-fit: cover;
border-radius: var(--radius) var(--radius) 0 0;
}
.jahres-event-modal-bild[hidden] { display: none; }
.jahres-event-modal-body { padding: 1.8rem 2rem 2.2rem; }
.jahres-event-modal-datum {
display: block;
color: #e8c465;
font-weight: 700;
font-size: .92rem;
letter-spacing: .03em;
margin-bottom: .5rem;
}
.jahres-event-modal-body h2 { font-size: 1.7rem; margin: 0 0 .8rem; }
.jahres-event-modal-body p { font-size: 1.08rem; line-height: 1.7; color: var(--text-muted); margin: 0 0 1.4rem; }
.jahres-event-modal-link[hidden] { display: none; }
/* ---------- Cards ---------- */
.card {
background: var(--card-bg);
+6 -32
View File
@@ -89,39 +89,13 @@ window.I18N_PAGE = {
de: "🏆 Event des Jahres", "de-CH": "🏆 Event vom Jahr",
en: "🏆 Event of the Year", fr: "🏆 Événement de l'année", pt: "🏆 Evento do ano",
},
idx_jahres_event1_datum: {
de: "7. März 2026", "de-CH": "7. März 2026",
en: "March 7, 2026", fr: "7 mars 2026", pt: "7 de março de 2026",
},
idx_jahres_event1_h3: {
de: "Der 28-Stunden-Stream", "de-CH": "De 28-Stunde-Stream",
en: "The 28-Hour Stream", fr: "Le stream de 28 heures", pt: "A live de 28 horas",
},
idx_jahres_event1_p: {
de: "DogFather stellt sich einer besonderen Herausforderung und streamt 28 Stunden am Stück.",
"de-CH": "DogFather stellt sich ere bsundere Herusforderig und streamt 28 Stund am Stück.",
en: "DogFather takes on a very special challenge and streams for 28 hours straight.",
fr: "DogFather se lance un défi hors norme et streame 28 heures d'affilée.",
pt: "DogFather encara um desafio especial e transmite ao vivo por 28 horas seguidas.",
},
idx_jahres_event2_datum: {
de: "27. Juli bis 2. August 2026", "de-CH": "27. Juli bis 2. Auguscht 2026",
en: "July 27 – August 2, 2026", fr: "Du 27 juillet au 2 août 2026", pt: "De 27 de julho a 2 de agosto de 2026",
},
idx_jahres_event2_h3: {
de: "Der Creator Cup", "de-CH": "De Creator Cup",
en: "The Creator Cup", fr: "Le Creator Cup", pt: "O Creator Cup",
},
idx_jahres_event2_p: {
de: "Gemeinsam mit Cidem organisiert DogFather den Creator Cup für die Streamer von Spicy Media.",
"de-CH": "Zäme mit Cidem organisiert DogFather de Creator Cup für d Streamer vo Spicy Media.",
en: "Together with Cidem, DogFather organizes the Creator Cup for Spicy Media's streamers.",
fr: "Avec Cidem, DogFather organise le Creator Cup pour les streamers de Spicy Media.",
pt: "Junto com Cidem, DogFather organiza o Creator Cup para os streamers da Spicy Media.",
},
idx_jahres_events_mehr: {
de: "Zur Zeitreise →", "de-CH": "Zur Ziitreis →",
en: "To the timeline →", fr: "Voir la chronologie →", pt: "Ver a linha do tempo →",
de: "Mehr erfahren →", "de-CH": "Mehr erfahre →",
en: "Learn more →", fr: "En savoir plus →", pt: "Saiba mais →",
},
idx_jahres_event_modal_link: {
de: "Direkt ansehen →", "de-CH": "Direkt aluege →",
en: "View directly →", fr: "Voir directement →", pt: "Ver diretamente →",
},
idx_char_eyebrow: {