mirror of
https://gitlab.w-hs.de/an14051/backerup-website.git
synced 2026-07-27 17:35:29 +00:00
0d58fafe4e
- Add user management API endpoints for listing and creating users. - Implement login and logout functionality with rate limiting. - Create UI components for login form, logout button, and animated elements. - Add session management with JWT and secure cookie handling. - Seed initial admin user if no users exist. - Introduce utility functions for password hashing and user authentication. - Set up proxy middleware for route protection and security headers. - Create a JSON file for user data storage. - Add links configuration for external resources.
286 lines
8.3 KiB
CSS
286 lines
8.3 KiB
CSS
@import "tailwindcss";
|
|
|
|
@theme inline {
|
|
--color-background: #060810;
|
|
--color-foreground: #e2e8f0;
|
|
--font-sans: var(--font-geist-sans);
|
|
--font-mono: var(--font-geist-mono);
|
|
|
|
--animate-fade-in: fadeIn 0.8s ease-out both;
|
|
--animate-slide-up: slideUp 0.8s ease-out both;
|
|
--animate-glow: glow 3s ease-in-out infinite alternate;
|
|
--animate-float: float 6s ease-in-out infinite;
|
|
--animate-gradient: gradientShift 8s ease infinite;
|
|
--animate-blink: blink 1s step-end infinite;
|
|
--animate-spin-slow: spinSlow 25s linear infinite;
|
|
--animate-pulse-slow: pulseSlow 5s ease-in-out infinite;
|
|
--animate-shimmer: shimmerSlide 3s ease infinite;
|
|
--animate-scan: scanLine 4s linear infinite;
|
|
--animate-aurora-1: aurora1 18s ease-in-out infinite alternate;
|
|
--animate-aurora-2: aurora2 23s ease-in-out infinite alternate-reverse;
|
|
--animate-aurora-3: aurora3 15s ease-in-out infinite alternate;
|
|
--animate-border-glow: borderGlow 3s ease-in-out infinite alternate;
|
|
}
|
|
|
|
:root {
|
|
--background: #060810;
|
|
--foreground: #e2e8f0;
|
|
}
|
|
|
|
body {
|
|
background: var(--background);
|
|
color: var(--foreground);
|
|
}
|
|
|
|
@keyframes fadeIn {
|
|
from { opacity: 0; }
|
|
to { opacity: 1; }
|
|
}
|
|
|
|
@keyframes slideUp {
|
|
from { opacity: 0; transform: translateY(32px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
|
|
@keyframes glow {
|
|
from {
|
|
box-shadow: 0 0 20px rgba(6, 182, 212, 0.15), 0 0 40px rgba(6, 182, 212, 0.05);
|
|
}
|
|
to {
|
|
box-shadow: 0 0 40px rgba(6, 182, 212, 0.45), 0 0 80px rgba(6, 182, 212, 0.2), 0 0 120px rgba(6, 182, 212, 0.05);
|
|
}
|
|
}
|
|
|
|
@keyframes float {
|
|
0%, 100% { transform: translateY(0px); }
|
|
33% { transform: translateY(-14px); }
|
|
66% { transform: translateY(-7px); }
|
|
}
|
|
|
|
@keyframes gradientShift {
|
|
0%, 100% { background-position: 0% 50%; }
|
|
50% { background-position: 100% 50%; }
|
|
}
|
|
|
|
@keyframes blink {
|
|
0%, 100% { opacity: 1; }
|
|
50% { opacity: 0; }
|
|
}
|
|
|
|
@keyframes spinSlow {
|
|
from { transform: rotate(0deg); }
|
|
to { transform: rotate(360deg); }
|
|
}
|
|
|
|
@keyframes pulseSlow {
|
|
0%, 100% { opacity: 0.12; transform: scale(0.97); }
|
|
50% { opacity: 0.35; transform: scale(1.03); }
|
|
}
|
|
|
|
@keyframes shimmerSlide {
|
|
0% { transform: translateX(-100%); }
|
|
100% { transform: translateX(200%); }
|
|
}
|
|
|
|
@keyframes scanLine {
|
|
0% { transform: translateY(-100%); }
|
|
100% { transform: translateY(500%); }
|
|
}
|
|
|
|
/* ── Glassmorphism ─────────────────────────────────────────── */
|
|
.glass {
|
|
background: rgba(255, 255, 255, 0.025);
|
|
backdrop-filter: blur(16px);
|
|
-webkit-backdrop-filter: blur(16px);
|
|
border: 1px solid rgba(255, 255, 255, 0.06);
|
|
}
|
|
|
|
.glass-heavy {
|
|
background: rgba(6, 8, 16, 0.85);
|
|
backdrop-filter: blur(24px);
|
|
-webkit-backdrop-filter: blur(24px);
|
|
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
|
|
}
|
|
|
|
/* ── Gradient text ─────────────────────────────────────────── */
|
|
.gradient-text {
|
|
background: linear-gradient(135deg, #22d3ee 0%, #a78bfa 55%, #22d3ee 100%);
|
|
background-size: 200% auto;
|
|
-webkit-background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
background-clip: text;
|
|
animation: gradientShift 8s ease infinite;
|
|
}
|
|
|
|
/* ── Grid background ───────────────────────────────────────── */
|
|
.grid-bg {
|
|
background-image:
|
|
linear-gradient(rgba(6, 182, 212, 0.035) 1px, transparent 1px),
|
|
linear-gradient(90deg, rgba(6, 182, 212, 0.035) 1px, transparent 1px);
|
|
background-size: 48px 48px;
|
|
}
|
|
|
|
/* ── Card hover glow ───────────────────────────────────────── */
|
|
.card-hover {
|
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
}
|
|
|
|
.card-hover:hover {
|
|
transform: translateY(-3px);
|
|
border-color: rgba(6, 182, 212, 0.3) !important;
|
|
box-shadow:
|
|
0 0 0 1px rgba(6, 182, 212, 0.06),
|
|
0 16px 48px rgba(0, 0, 0, 0.5),
|
|
0 0 40px rgba(6, 182, 212, 0.08);
|
|
}
|
|
|
|
/* ── Neon glow border ──────────────────────────────────────── */
|
|
.neon-cyan {
|
|
box-shadow:
|
|
0 0 0 1px rgba(6, 182, 212, 0.5),
|
|
0 0 16px rgba(6, 182, 212, 0.2);
|
|
}
|
|
|
|
/* ── Shimmer overlay ───────────────────────────────────────── */
|
|
.shimmer {
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
.shimmer::after {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 40%;
|
|
height: 100%;
|
|
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.04), transparent);
|
|
animation: shimmerSlide 3s ease infinite;
|
|
pointer-events: none;
|
|
}
|
|
|
|
/* ── Terminal scan effect ──────────────────────────────────── */
|
|
.terminal-scan {
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
.terminal-scan::before {
|
|
content: '';
|
|
position: absolute;
|
|
left: 0;
|
|
right: 0;
|
|
height: 60px;
|
|
background: linear-gradient(to bottom, transparent, rgba(6, 182, 212, 0.025), transparent);
|
|
animation: scanLine 4s linear infinite;
|
|
pointer-events: none;
|
|
z-index: 1;
|
|
}
|
|
|
|
/* ── Step connector line ───────────────────────────────────── */
|
|
.step-connector {
|
|
position: relative;
|
|
}
|
|
.step-connector::after {
|
|
content: '';
|
|
position: absolute;
|
|
top: 20px;
|
|
left: calc(100% + 0px);
|
|
width: calc(100% - 40px);
|
|
height: 1px;
|
|
background: linear-gradient(90deg, rgba(6, 182, 212, 0.4), rgba(6, 182, 212, 0.05));
|
|
}
|
|
|
|
/* ── Aurora blob keyframes ────────────────────────────────── */
|
|
@keyframes aurora1 {
|
|
0% { transform: translate( 0px, 0px) scale(1.00); }
|
|
33% { transform: translate( 80px, -70px) scale(1.15); }
|
|
66% { transform: translate(-50px, 55px) scale(0.90); }
|
|
100% { transform: translate( 25px, -20px) scale(1.05); }
|
|
}
|
|
|
|
@keyframes aurora2 {
|
|
0% { transform: translate( 0px, 0px) scale(1.00); }
|
|
33% { transform: translate(-75px, 65px) scale(0.88); }
|
|
66% { transform: translate( 90px, -45px) scale(1.12); }
|
|
100% { transform: translate(-25px, 30px) scale(0.95); }
|
|
}
|
|
|
|
@keyframes aurora3 {
|
|
0% { transform: translate( 0px, 0px) scale(1.00); }
|
|
33% { transform: translate( 55px, 75px) scale(1.10); }
|
|
66% { transform: translate(-65px, -55px) scale(0.92); }
|
|
100% { transform: translate( 15px, 45px) scale(1.08); }
|
|
}
|
|
|
|
/* ── Border glow pulse ─────────────────────────────────────── */
|
|
@keyframes borderGlow {
|
|
from { box-shadow: 0 0 12px rgba(6,182,212,0.3), 0 0 24px rgba(6,182,212,0.1); }
|
|
to { box-shadow: 0 0 24px rgba(6,182,212,0.6), 0 0 60px rgba(6,182,212,0.25), 0 0 100px rgba(139,92,246,0.1); }
|
|
}
|
|
|
|
/* ── Spotlight card ────────────────────────────────────────── */
|
|
.spotlight {
|
|
--mx: -9999px;
|
|
--my: -9999px;
|
|
position: relative;
|
|
}
|
|
|
|
.spotlight::before {
|
|
content: '';
|
|
position: absolute;
|
|
inset: 0;
|
|
border-radius: inherit;
|
|
background: radial-gradient(
|
|
280px circle at var(--mx) var(--my),
|
|
rgba(6, 182, 212, 0.09),
|
|
transparent 70%
|
|
);
|
|
opacity: 0;
|
|
transition: opacity 0.4s ease;
|
|
pointer-events: none;
|
|
z-index: 0;
|
|
}
|
|
|
|
.spotlight:hover::before {
|
|
opacity: 1;
|
|
}
|
|
|
|
.spotlight > * {
|
|
position: relative;
|
|
z-index: 1;
|
|
}
|
|
|
|
/* ── Nav link underline animation ──────────────────────────── */
|
|
.nav-link {
|
|
position: relative;
|
|
}
|
|
|
|
.nav-link::after {
|
|
content: '';
|
|
position: absolute;
|
|
bottom: -2px;
|
|
left: 0;
|
|
width: 0;
|
|
height: 1px;
|
|
background: linear-gradient(90deg, #22d3ee, #818cf8);
|
|
transition: width 0.3s cubic-bezier(0.22, 1, 0.36, 1);
|
|
}
|
|
|
|
.nav-link:hover::after {
|
|
width: 100%;
|
|
}
|
|
|
|
/* ── Scrollbar ─────────────────────────────────────────────── */
|
|
::-webkit-scrollbar {
|
|
width: 8px;
|
|
height: 8px;
|
|
}
|
|
::-webkit-scrollbar-track {
|
|
background: #060810;
|
|
}
|
|
::-webkit-scrollbar-thumb {
|
|
background: rgba(255, 255, 255, 0.1);
|
|
border-radius: 4px;
|
|
}
|
|
::-webkit-scrollbar-thumb:hover {
|
|
background: rgba(255, 255, 255, 0.2);
|
|
} |