Nandrx 53f9691376 Redesign frontend with hero section, auth modal, and animations
- Replace header auth inputs with Bootstrap modal (Login/Register tabs)
- Add hero section with dark gradient, decorative grid lines, teal glows
- Floating search card with strong shadow inside hero
- Add card entrance animation (fadeSlideUp) with staggered nth-child delays
- Add skeleton loader shown while events are fetching
- Add empty state components with emoji icon and description
- Remove all alert() calls, replace with inline DOM error messages
- Add CSS custom properties for consistent design tokens
- Add Inter font, modern typography scale
- Document input validation under OWASP A03 in README
2026-05-31 17:52:40 +02:00

443 lines
9.4 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* =========================
INTER FONT (Google Fonts)
========================= */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap');
/* =========================
CSS CUSTOM PROPERTIES (Design Tokens)
========================= */
:root {
--color-bg: #f1f5f9;
--color-surface: #ffffff;
--color-header: #0f172a;
--color-accent: #0d9488;
--color-accent-light: #14b8a6;
--color-accent-dark: #0f766e;
--color-text: #1e293b;
--color-text-muted: #64748b;
--color-border: #e2e8f0;
--color-danger: #ef4444;
--color-success: #10b981;
--radius-xs: 6px;
--radius-sm: 10px;
--radius-md: 14px;
--radius-card: 18px;
--shadow-xs: 0 1px 2px rgba(0,0,0,0.05);
--shadow-sm: 0 1px 3px rgba(0,0,0,0.06), 0 4px 12px rgba(0,0,0,0.04);
--shadow-md: 0 4px 16px rgba(0,0,0,0.08), 0 1px 4px rgba(0,0,0,0.04);
--shadow-lg: 0 12px 40px rgba(0,0,0,0.12), 0 2px 8px rgba(0,0,0,0.06);
--transition: 0.2s ease;
}
/* =========================
RESET & BASIS
========================= */
*, *::before, *::after {
box-sizing: border-box;
}
body {
margin: 0;
font-family: 'Inter', Arial, sans-serif;
background-color: var(--color-bg);
color: var(--color-text);
line-height: 1.6;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
img {
max-width: 100%;
height: auto;
}
/* =========================
KARTEN-ERSCHEINUNGS-ANIMATION
Wird auf Event-Karten angewendet wenn sie ins DOM kommen
========================= */
@keyframes fadeSlideUp {
from {
opacity: 0;
transform: translateY(22px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Shimmer-Animation für Skeleton-Karten (transform statt background-position → GPU-composited) */
@keyframes shimmer {
from { transform: translateX(-100%); }
to { transform: translateX(200%); }
}
/* =========================
HEADER Dunkel & Sticky
========================= */
.site-header {
background-color: var(--color-header);
padding: 0.75rem 0;
position: sticky;
top: 0;
z-index: 200;
box-shadow: 0 1px 0 rgba(255,255,255,0.06), 0 2px 16px rgba(0,0,0,0.2);
}
.site-logo {
font-size: 1.5rem;
font-weight: 800;
color: var(--color-accent-light);
margin: 0;
letter-spacing: -0.04em;
-webkit-user-select: none;
user-select: none;
}
.site-header .nav-link {
color: rgba(255,255,255,0.65);
font-size: 0.875rem;
font-weight: 500;
padding: 0.375rem 0.75rem;
border-radius: var(--radius-xs);
transition: color var(--transition), background var(--transition);
text-decoration: none;
}
.site-header .nav-link:hover {
color: #fff;
background: rgba(255,255,255,0.08);
}
/* Anmeldebereich nur noch Buttons */
#auth-area {
display: flex;
align-items: center;
gap: 0.5rem;
}
.header-btn-outline {
background: transparent;
border: 1.5px solid rgba(255,255,255,0.25);
border-radius: var(--radius-xs);
color: rgba(255,255,255,0.8);
font-weight: 500;
font-size: 0.875rem;
padding: 0.4rem 1rem;
cursor: pointer;
transition: border-color var(--transition), color var(--transition);
white-space: nowrap;
}
.header-btn-outline:hover {
border-color: rgba(255,255,255,0.55);
color: #fff;
}
.header-btn-accent {
background: var(--color-accent);
border: none;
border-radius: var(--radius-xs);
color: #fff;
font-weight: 600;
font-size: 0.875rem;
padding: 0.4rem 1rem;
cursor: pointer;
transition: background var(--transition);
white-space: nowrap;
}
.header-btn-accent:hover {
background: var(--color-accent-dark);
color: #fff;
}
/* Nutzerbereich (eingeloggt) */
#user-area {
display: flex;
align-items: center;
gap: 0.625rem;
}
#user-name {
color: rgba(255,255,255,0.85);
font-size: 0.875rem;
font-weight: 500;
}
/* =========================
HAUPTINHALT
========================= */
main {
min-height: calc(100vh - 200px);
}
/* =========================
HERO-BEREICH (Suchsektion)
Volle Breite, dunkler Gradient-Hintergrund
========================= */
.hero {
background:
radial-gradient(ellipse 70% 80% at 15% 60%, rgba(13,148,136,0.15) 0%, transparent 60%),
radial-gradient(ellipse 50% 60% at 85% 20%, rgba(20,184,166,0.08) 0%, transparent 55%),
linear-gradient(155deg, #0f172a 0%, #1a2744 45%, #0c1a2c 100%);
padding: 4.5rem 0 3.5rem;
position: relative;
overflow: hidden;
}
/* Dekoratives Gitternetz-Muster im Hintergrund */
.hero::before {
content: '';
position: absolute;
inset: 0;
background-image:
linear-gradient(rgba(255,255,255,0.025) 1px, transparent 1px),
linear-gradient(90deg, rgba(255,255,255,0.025) 1px, transparent 1px);
background-size: 40px 40px;
pointer-events: none;
}
.hero__text {
text-align: center;
margin-bottom: 2.5rem;
position: relative;
}
.hero__title {
font-size: clamp(2.25rem, 5vw, 3.5rem);
font-weight: 800;
color: #ffffff;
letter-spacing: -0.04em;
margin: 0 0 0.625rem;
line-height: 1.1;
}
/* Teal Akzent auf dem letzten Wort */
.hero__title span {
color: var(--color-accent-light);
}
.hero__subtitle {
font-size: 1.05rem;
color: rgba(255,255,255,0.5);
margin: 0;
font-weight: 400;
letter-spacing: 0.01em;
}
/* Suchkarte schwebend über dem Hero-Hintergrund */
.hero .search {
background: rgba(255,255,255,0.98);
border: none;
border-radius: var(--radius-card);
padding: 1.5rem 1.75rem;
box-shadow:
0 30px 80px rgba(0,0,0,0.4),
0 8px 30px rgba(0,0,0,0.25),
0 0 0 1px rgba(255,255,255,0.1);
position: relative;
}
/* =========================
SUCHFORMULAR
========================= */
.search__controls {
display: flex;
flex-direction: column;
gap: 0.625rem;
}
.search__controls .form-control,
.search__controls input[type="date"],
.search__controls select {
background: var(--color-bg);
border: 1.5px solid var(--color-border);
border-radius: var(--radius-sm);
color: var(--color-text);
font-family: inherit;
font-size: 0.9rem;
padding: 0.55rem 0.9rem;
height: 42px;
transition: border-color var(--transition), box-shadow var(--transition);
}
.search__controls .form-control:focus,
.search__controls input[type="date"]:focus,
.search__controls select:focus {
border-color: var(--color-accent);
box-shadow: 0 0 0 3px rgba(13,148,136,0.15);
outline: none;
background: var(--color-surface);
}
.search__controls label {
color: var(--color-text-muted);
font-size: 0.8rem;
font-weight: 500;
white-space: nowrap;
}
#load-events {
background: var(--color-accent);
border: none;
border-radius: var(--radius-sm);
color: #fff;
font-family: inherit;
font-size: 0.9rem;
font-weight: 600;
padding: 0 1.5rem;
height: 42px;
cursor: pointer;
transition: background var(--transition), transform var(--transition), box-shadow var(--transition);
white-space: nowrap;
}
#load-events:hover {
background: var(--color-accent-dark);
transform: translateY(-1px);
box-shadow: 0 4px 14px rgba(13,148,136,0.35);
}
#load-events:active {
transform: translateY(0);
}
/* =========================
SECTION (EVENTS / SAVED / INVITATIONS)
========================= */
.events-section {
padding: 2.5rem 0 1rem;
}
.events-section h2 {
font-size: 1.375rem;
font-weight: 700;
color: var(--color-text);
margin: 0 0 1.5rem;
letter-spacing: -0.02em;
}
/* =========================
EVENT-GRID
========================= */
#event-list,
#saved-list {
display: flex;
flex-direction: column;
gap: 1rem;
}
#invitation-list {
display: flex;
flex-direction: column;
gap: 1rem;
max-width: 640px;
}
/* =========================
EMPTY STATE
========================= */
.empty-state {
text-align: center;
padding: 3.5rem 1rem;
color: var(--color-text-muted);
}
.empty-state__icon {
font-size: 3rem;
margin-bottom: 1rem;
opacity: 0.5;
}
.empty-state__text {
font-size: 1.1rem;
font-weight: 600;
color: var(--color-text);
margin: 0 0 0.375rem;
}
.empty-state__sub {
font-size: 0.9rem;
margin: 0;
}
/* =========================
SKELETON LOADER
Shimmer via ::after Pseudo-Element + transform (GPU-composited)
========================= */
.skeleton-card {
background: var(--color-surface);
border-radius: var(--radius-card);
border: 1px solid var(--color-border);
min-height: 180px;
position: relative;
overflow: hidden;
}
.skeleton-card::after {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(
90deg,
transparent 0%,
rgba(255, 255, 255, 0.65) 50%,
transparent 100%
);
transform: translateX(-100%);
animation: shimmer 1.6s ease-in-out infinite;
will-change: transform;
}
/* =========================
FOOTER
========================= */
.site-footer {
background-color: var(--color-header);
color: rgba(255,255,255,0.35);
font-size: 0.85rem;
padding: 1.75rem 0;
margin-top: 3rem;
}
.site-footer p {
margin: 0;
}
/* =========================
TABLET (≥768px)
========================= */
@media (min-width: 768px) {
.search__controls {
flex-direction: row;
align-items: center;
flex-wrap: wrap;
}
#city-input { flex: 2; min-width: 160px; }
#date-from,
#date-to { flex: 1; min-width: 130px; }
#category-input { flex: 0 0 160px; }
#event-list,
#saved-list {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1.25rem;
}
}
/* =========================
DESKTOP (≥1024px)
========================= */
@media (min-width: 1024px) {
#event-list,
#saved-list {
grid-template-columns: repeat(3, 1fr);
}
}