Links now live in data/links.json instead of hardcoded HTML, editable via /admin (add/rename/reorder/delete sections and links, per-link color and half-width side-by-side layout). New pages can be added without code changes. Docker image only needs rebuilding on code changes now, not on content changes (data/ is volume-mounted). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
348 lines
6.9 KiB
CSS
348 lines
6.9 KiB
CSS
|
|
* {
|
|
box-sizing: border-box;
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
|
|
body {
|
|
font-family: 'Inter', sans-serif;
|
|
color: #f3f4f6;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 40px 20px;
|
|
min-height: 100dvh;
|
|
overflow-x: hidden; /* verhindert horizontales Scrollen */
|
|
overflow-y: auto; /* nur vertikal scrollen, wenn nötig */
|
|
position: relative;
|
|
background: #0f172a;
|
|
}
|
|
|
|
.background-glow {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100vw;
|
|
height: 100vh;
|
|
z-index: -1;
|
|
pointer-events: none;
|
|
background: radial-gradient(circle at 30% 30%, rgba(0, 200, 255, 0.35), transparent 60%),
|
|
radial-gradient(circle at 70% 60%, rgba(255, 50, 160, 0.35), transparent 60%),
|
|
radial-gradient(circle at 50% 80%, rgba(80, 255, 180, 0.3), transparent 60%);
|
|
background-size: 200% 200%;
|
|
animation: flowBackground 40s ease-in-out infinite;
|
|
}
|
|
|
|
@keyframes flowBackground {
|
|
0% {
|
|
background-position: 0% 50%;
|
|
}
|
|
50% {
|
|
background-position: 100% 50%;
|
|
}
|
|
100% {
|
|
background-position: 0% 50%;
|
|
}
|
|
}
|
|
|
|
body::before {
|
|
content: '';
|
|
position: fixed; /* fixed statt absolute, bleibt innerhalb Viewport */
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
z-index: 0;
|
|
pointer-events: none;
|
|
background: radial-gradient(circle at 30% 30%, rgba(12, 75, 119, 0.534), transparent 70%),
|
|
radial-gradient(circle at 70% 60%, rgba(230, 86, 158, 0.35), transparent 70%),
|
|
radial-gradient(circle at 50% 80%, rgba(69, 218, 69, 0.3), transparent 70%);
|
|
animation: flowBackground 30s ease-in-out infinite;
|
|
}
|
|
|
|
.fade-in {
|
|
animation: fadeIn 1s ease-out forwards;
|
|
}
|
|
|
|
@keyframes fadeIn {
|
|
0% { opacity: 0; transform: translateY(10px); }
|
|
100% { opacity: 1; transform: translateY(0); }
|
|
}
|
|
|
|
|
|
@keyframes gradientShift {
|
|
0% { background-position: 0% 50%; }
|
|
50% { background-position: 100% 50%; }
|
|
100% { background-position: 0% 50%; }
|
|
}
|
|
|
|
.profile-pic {
|
|
width: 120px;
|
|
height: 120px;
|
|
border-radius: 50%;
|
|
object-fit: cover;
|
|
border: 3px solid #4b5563;
|
|
margin-bottom: 20px;
|
|
box-shadow: 0 0 8px rgba(0, 0, 0, 0.4);
|
|
filter: brightness(0.9) contrast(1.05);
|
|
border: 3px solid rgba(0, 0, 0, 0.3);
|
|
}
|
|
|
|
h1 {
|
|
font-size: 26px;
|
|
font-weight: 600;
|
|
margin-bottom: 8px;
|
|
text-align: center;
|
|
color: #eccb0ec5;
|
|
text-shadow: 0 0 10px rgba(0, 0, 0, 0.4);
|
|
}
|
|
|
|
p.bio {
|
|
color: #9ca3af;
|
|
font-size: 14px;
|
|
text-align: center;
|
|
max-width: 320px;
|
|
}
|
|
|
|
p.bio2 {
|
|
color: #9ca3af;
|
|
font-size: 14px;
|
|
margin-bottom: 32px;
|
|
text-align: center;
|
|
max-width: 320px;
|
|
}
|
|
|
|
h2.section-title {
|
|
font-size: 18px;
|
|
margin-bottom: 10px;
|
|
color: #a5f3fc;
|
|
text-shadow: 0 0 6px rgba(0, 255, 255, 0.2);
|
|
border-bottom: 1px solid #1a3458cb;
|
|
padding-bottom: 6px;
|
|
width: 100%;
|
|
max-width: 320px;
|
|
text-align: left;
|
|
}
|
|
|
|
.section-title {
|
|
font-size: 18px;
|
|
margin-bottom: 10px;
|
|
color: #f9fafb;
|
|
border-bottom: 1px solid #374151;
|
|
padding-bottom: 6px;
|
|
width: 100%;
|
|
max-width: 320px;
|
|
text-align: left;
|
|
animation: pulseGlow 3s ease-in-out infinite;
|
|
}
|
|
|
|
@keyframes pulseGlow {
|
|
0%, 100% { text-shadow: 0 0 3px rgba(255, 255, 255, 0.1); }
|
|
50% { text-shadow: 0 0 10px rgba(255, 255, 255, 0.3); }
|
|
}
|
|
|
|
|
|
.links-grid {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 10px;
|
|
width: 100%;
|
|
max-width: 320px;
|
|
margin-bottom: 14px;
|
|
}
|
|
|
|
.link {
|
|
display: block;
|
|
flex: 0 0 100%;
|
|
padding: 14px 24px;
|
|
background-color: rgba(255, 255, 255, 0.04);
|
|
color: #f3f4f6;
|
|
text-decoration: none;
|
|
border-radius: 10px;
|
|
border: 1px solid #4b5563;
|
|
transition: all 0.4s ease, box-shadow 0.6s ease;
|
|
font-weight: 600;
|
|
text-align: left;
|
|
}
|
|
|
|
/* Opt-in: two links next to each other instead of full width */
|
|
.link.half {
|
|
flex: 0 0 calc(50% - 5px);
|
|
padding: 14px 14px;
|
|
}
|
|
|
|
.link:hover {
|
|
background-color: rgba(255, 255, 255, 0.07); /* softer highlight */
|
|
color: #e0e7ff; /* gentle light blue tint */
|
|
transform: scale(1.04) translateZ(0);
|
|
box-shadow:
|
|
0 0 8px rgba(77, 180, 255, 0.3),
|
|
0 0 12px rgba(255, 105, 180, 0.25),
|
|
0 0 15px rgba(144, 238, 144, 0.2);
|
|
transition: background-color 0.3s ease, color 0.3s ease, transform 0.25s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.4s ease;
|
|
}
|
|
|
|
.blue-glow:hover {
|
|
box-shadow: 0 0 12px rgba(0, 200, 255, 0.3);
|
|
}
|
|
|
|
.pink-glow:hover {
|
|
box-shadow: 0 0 12px rgba(252, 111, 184, 0.527);
|
|
}
|
|
|
|
.green-glow:hover {
|
|
box-shadow: 0 0 12px rgba(144, 238, 144, 0.3);
|
|
}
|
|
|
|
.orange-glow:hover {
|
|
box-shadow: 0 0 12px rgba(197, 130, 29, 0.705);
|
|
}
|
|
|
|
.link-title {
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.link-note {
|
|
font-size: 13px;
|
|
color: #9ca3af;
|
|
margin-top: 4px;
|
|
font-weight: 400;
|
|
}
|
|
|
|
|
|
footer {
|
|
margin-top: 60px;
|
|
font-size: 12px;
|
|
color: #cbd5e1;
|
|
text-shadow: 0 0 4px rgba(255, 255, 255, 0.1);
|
|
text-align: center;
|
|
}
|
|
|
|
.link-footer {
|
|
text-decoration: none;
|
|
color: #21e4d3;
|
|
font-size: 1,5em;
|
|
}
|
|
|
|
.link-footer:hover {
|
|
color: #24ffed; /* lighter, glowing version of the base color */
|
|
text-shadow: 0 0 6px rgba(255, 209, 136, 0.6);
|
|
}
|
|
|
|
.firefly {
|
|
position: absolute;
|
|
width: 6px;
|
|
height: 6px;
|
|
background: hsl(55, 100%, 75%);
|
|
border-radius: 50%;
|
|
box-shadow: 0 0 12px 5px hsla(55, 100%, 60%, 0.3);
|
|
animation:
|
|
fly 14s ease-in-out infinite,
|
|
blink 2.5s ease-in-out infinite alternate,
|
|
hueShift 10s ease-in-out infinite;
|
|
}
|
|
|
|
@keyframes fly {
|
|
0% {
|
|
transform: translate(0, 0) scale(0.9) rotate(0deg);
|
|
}
|
|
25% {
|
|
transform: translate(50px, -60px) scale(1) rotate(20deg);
|
|
}
|
|
50% {
|
|
transform: translate(-80px, 40px) scale(1.1) rotate(-20deg);
|
|
}
|
|
75% {
|
|
transform: translate(60px, -20px) scale(1) rotate(10deg);
|
|
}
|
|
100% {
|
|
transform: translate(0, 0) scale(0.9) rotate(0deg);
|
|
}
|
|
}
|
|
@keyframes hueShift {
|
|
0% { filter: hue-rotate(0deg); }
|
|
50% { filter: hue-rotate(60deg); }
|
|
100% { filter: hue-rotate(0deg); }
|
|
}
|
|
|
|
@keyframes blink {
|
|
0% { opacity: 0.2; }
|
|
50% { opacity: 1; }
|
|
100% { opacity: 0.3; }
|
|
}
|
|
|
|
|
|
|
|
/* Random positions and delays */
|
|
.firefly:nth-child(1) { top: 10%; left: 20%; animation-delay: 0s; }
|
|
.firefly:nth-child(2) { top: 40%; left: 70%; animation-delay: 2s; }
|
|
.firefly:nth-child(3) { top: 80%; left: 30%; animation-delay: 4s; }
|
|
.firefly:nth-child(4) { top: 25%; left: 85%; animation-delay: 6s; }
|
|
.firefly:nth-child(5) { top: 60%; left: 15%; animation-delay: 8s; }
|
|
.firefly:nth-child(6) { top: 90%; left: 50%; animation-delay: 10s; }
|
|
|
|
@keyframes fadeInUpSmooth {
|
|
0% {
|
|
opacity: 0;
|
|
transform: translateY(30px) scale(0.96);
|
|
filter: blur(4px);
|
|
}
|
|
100% {
|
|
opacity: 1;
|
|
transform: translateY(0) scale(1);
|
|
filter: blur(0);
|
|
}
|
|
}
|
|
|
|
.animated-link {
|
|
opacity: 0;
|
|
transform: translateY(30px) scale(0.96);
|
|
animation: fadeInUpSmooth 0.9s cubic-bezier(0.22, 1, 0.36, 1) forwards;
|
|
animation-delay: calc(0.15s * var(--i));
|
|
will-change: opacity, transform, filter;
|
|
}
|
|
|
|
|
|
@media (max-width: 480px) {
|
|
.profile-pic {
|
|
width: 100px;
|
|
height: 100px;
|
|
}
|
|
|
|
h1 {
|
|
font-size: 22px;
|
|
}
|
|
|
|
.link {
|
|
font-size: 14px;
|
|
padding: 12px 20px;
|
|
}
|
|
|
|
.link.half {
|
|
flex-basis: 100%;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
body {
|
|
padding: 24px 16px;
|
|
}
|
|
|
|
.link {
|
|
font-size: 15px;
|
|
padding: 12px 18px;
|
|
}
|
|
|
|
h1 {
|
|
font-size: 24px;
|
|
}
|
|
|
|
.profile-pic {
|
|
width: 110px;
|
|
height: 110px;
|
|
}
|
|
}
|