A free, open, self-hosted app platform (GNU AGPLv3): one-click app deploys, Traefik reverse proxy with automatic SSL, rootless Docker support, gluetun VPN routing, and a web dashboard to manage it all. Free & open forever to self-host; optional paid hosted services fund it. See PROMISE.md. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: librelad <librelad@digitalangels.vip>
254 lines
7.5 KiB
CSS
254 lines
7.5 KiB
CSS
/*
|
|
Shared "aurora" background — cool sparkly-blue swirling water.
|
|
Applied to both the login overlay and the loading screen so they share
|
|
one visual identity.
|
|
|
|
Usage: a container element gets `.aurora-bg`. Two pseudo-element layers
|
|
paint:
|
|
::before — slowly rotating conic-gradient swirl
|
|
::after — drifting radial-gradient "blobs"
|
|
Plus a separate `.aurora-stars` overlay child for sparkle twinkles
|
|
(kept as a real element so its animation can stack on top of pseudo
|
|
layers without z-index gymnastics).
|
|
*/
|
|
|
|
.aurora-bg {
|
|
background:
|
|
radial-gradient(ellipse at 20% 30%, var(--gradient-mid) 0%, transparent 55%),
|
|
radial-gradient(ellipse at 80% 70%, var(--gradient-to) 0%, transparent 55%),
|
|
linear-gradient(135deg, var(--gradient-from) 0%, var(--gradient-from) 40%, var(--gradient-mid) 100%);
|
|
overflow: hidden;
|
|
isolation: isolate;
|
|
}
|
|
|
|
/* Pair with `.aurora-bg` only if the host element isn't already
|
|
positioned. Login overlay and loading screen are both `position: fixed`
|
|
so the pseudo-elements anchor correctly without us overriding their
|
|
positioning. */
|
|
|
|
/* Slow conic swirl — the "current" of the water */
|
|
.aurora-bg::before {
|
|
content: '';
|
|
position: absolute;
|
|
inset: -25%;
|
|
background: conic-gradient(
|
|
from 0deg at 50% 50%,
|
|
rgba(var(--accent-rgb), 0.0) 0deg,
|
|
rgba(var(--accent-rgb), 0.18) 60deg,
|
|
rgba(var(--accent-rgb), 0.22) 130deg,
|
|
rgba(var(--accent-rgb), 0.20) 200deg,
|
|
rgba(var(--accent-rgb), 0.18) 280deg,
|
|
rgba(var(--accent-rgb), 0.0) 360deg
|
|
);
|
|
filter: blur(60px);
|
|
animation: auroraSpin 38s linear infinite;
|
|
z-index: -2;
|
|
pointer-events: none;
|
|
}
|
|
|
|
/* Drifting glow blobs — the "sparkly" volumes */
|
|
.aurora-bg::after {
|
|
content: '';
|
|
position: absolute;
|
|
inset: -10%;
|
|
background:
|
|
radial-gradient(circle at 18% 22%, rgba(var(--accent-rgb), 0.45) 0%, transparent 35%),
|
|
radial-gradient(circle at 78% 18%, rgba(var(--accent-rgb), 0.40) 0%, transparent 32%),
|
|
radial-gradient(circle at 30% 78%, rgba(var(--accent-rgb), 0.38) 0%, transparent 38%),
|
|
radial-gradient(circle at 82% 80%, rgba(var(--accent-rgb), 0.45) 0%, transparent 36%),
|
|
radial-gradient(circle at 50% 50%, rgba(var(--accent-rgb), 0.18) 0%, transparent 50%);
|
|
filter: blur(40px);
|
|
animation: auroraDrift 22s ease-in-out infinite alternate;
|
|
z-index: -1;
|
|
pointer-events: none;
|
|
}
|
|
|
|
@keyframes auroraSpin {
|
|
to { transform: rotate(360deg); }
|
|
}
|
|
|
|
@keyframes auroraDrift {
|
|
0% { transform: translate(0, 0) scale(1); opacity: 0.85; }
|
|
50% { transform: translate(-3%, 4%) scale(1.08); opacity: 1; }
|
|
100% { transform: translate(2%, -3%) scale(0.95); opacity: 0.9; }
|
|
}
|
|
|
|
/*
|
|
Sparkles. We render a tiny tiling of radial-gradient dots and
|
|
modulate opacity so they twinkle. Two staggered layers feel less
|
|
uniform than one.
|
|
*/
|
|
.aurora-stars {
|
|
position: absolute;
|
|
inset: 0;
|
|
pointer-events: none;
|
|
z-index: 0;
|
|
}
|
|
|
|
.aurora-stars::before,
|
|
.aurora-stars::after {
|
|
content: '';
|
|
position: absolute;
|
|
inset: 0;
|
|
background-repeat: repeat;
|
|
}
|
|
|
|
.aurora-stars::before {
|
|
background-image:
|
|
radial-gradient(1.5px 1.5px at 12px 18px, rgba(var(--text-rgb),0.9), transparent 60%),
|
|
radial-gradient(1px 1px at 47px 92px, rgba(var(--accent-rgb),0.85), transparent 60%),
|
|
radial-gradient(1.2px 1.2px at 110px 40px, rgba(var(--text-rgb),0.75), transparent 60%),
|
|
radial-gradient(1px 1px at 165px 130px, rgba(var(--accent-rgb),0.7), transparent 60%);
|
|
background-size: 200px 200px;
|
|
animation: auroraTwinkleA 4.5s ease-in-out infinite;
|
|
}
|
|
|
|
.aurora-stars::after {
|
|
background-image:
|
|
radial-gradient(1px 1px at 30px 60px, rgba(var(--accent-rgb),0.8), transparent 60%),
|
|
radial-gradient(1.4px 1.4px at 88px 22px, rgba(var(--text-rgb),0.7), transparent 60%),
|
|
radial-gradient(1px 1px at 140px 100px, rgba(var(--accent-rgb),0.85), transparent 60%),
|
|
radial-gradient(1.2px 1.2px at 195px 70px, rgba(var(--text-rgb),0.6), transparent 60%);
|
|
background-size: 240px 240px;
|
|
background-position: 80px 50px;
|
|
animation: auroraTwinkleB 6.5s ease-in-out infinite;
|
|
}
|
|
|
|
@keyframes auroraTwinkleA {
|
|
0%, 100% { opacity: 0.55; }
|
|
50% { opacity: 1; }
|
|
}
|
|
|
|
@keyframes auroraTwinkleB {
|
|
0%, 100% { opacity: 1; }
|
|
50% { opacity: 0.45; }
|
|
}
|
|
|
|
/* Children of an aurora surface should sit above the FX layers */
|
|
.aurora-bg > :not(.aurora-stars) {
|
|
position: relative;
|
|
z-index: 2;
|
|
}
|
|
|
|
/* Shared header used by both the loading screen and the login overlay
|
|
so the two surfaces have identical branding. */
|
|
.aurora-header {
|
|
text-align: center;
|
|
margin-bottom: 2.5rem;
|
|
}
|
|
|
|
.aurora-logo {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 14px;
|
|
}
|
|
|
|
.aurora-logo img {
|
|
width: 48px;
|
|
height: 48px;
|
|
/* Fade in once the SVG actually loads — avoids the brief broken-image
|
|
flash on first paint. The .loaded class is added by the inline onload
|
|
handler on the img tag in each surface that uses this header. */
|
|
opacity: 0;
|
|
transition: opacity 0.45s ease;
|
|
}
|
|
|
|
.aurora-logo img.loaded {
|
|
opacity: 1;
|
|
}
|
|
|
|
.aurora-logo h1 {
|
|
font-size: 3rem;
|
|
font-weight: 700;
|
|
margin: 0;
|
|
background: linear-gradient(45deg, var(--accent), var(--accent-hover));
|
|
-webkit-background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
background-clip: text;
|
|
letter-spacing: -0.01em;
|
|
}
|
|
|
|
.aurora-subtitle {
|
|
margin: 0.6rem 0 0 0;
|
|
font-size: 1.05rem;
|
|
font-weight: 300;
|
|
color: var(--text-secondary);
|
|
font-style: italic;
|
|
letter-spacing: 0.01em;
|
|
}
|
|
|
|
/* Shrink the header on phones — 3rem title + 48px icon swallow the
|
|
viewport on small screens. */
|
|
@media (max-width: 480px) {
|
|
.aurora-header {
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
.aurora-logo {
|
|
gap: 10px;
|
|
}
|
|
|
|
.aurora-logo img {
|
|
width: 36px;
|
|
height: 36px;
|
|
}
|
|
|
|
.aurora-logo h1 {
|
|
font-size: 2.1rem;
|
|
}
|
|
|
|
.aurora-subtitle {
|
|
font-size: 0.9rem;
|
|
margin-top: 0.4rem;
|
|
padding: 0 12px;
|
|
}
|
|
}
|
|
|
|
/* Respect reduced-motion — drop the animations but keep the gradient */
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.aurora-bg::before,
|
|
.aurora-bg::after,
|
|
.aurora-stars::before,
|
|
.aurora-stars::after {
|
|
animation: none;
|
|
}
|
|
}
|
|
|
|
/*
|
|
Static modifier — pair with `.aurora-bg` to keep the gradient identity
|
|
but drop the per-frame work that was making login / loading / setup
|
|
sluggish on lower-power systems. We kill the animations only — the
|
|
blur filter is kept because, without the rotation, the blur layer
|
|
rasterises exactly once at first paint and then just composites each
|
|
frame for free. Removing the blur entirely created visible banding
|
|
and a dark seam where the conic gradient wraps from 360° back to 0°.
|
|
*/
|
|
.aurora-bg.aurora-static::before,
|
|
.aurora-bg.aurora-static::after,
|
|
.aurora-bg.aurora-static .aurora-stars::before,
|
|
.aurora-bg.aurora-static .aurora-stars::after {
|
|
animation: none !important;
|
|
}
|
|
|
|
/* dark-blue and light themes get a flat, solid loading/login surface
|
|
— the cyan swirl + glow blobs + stars belong to the Nebula identity. */
|
|
html[data-theme="dark-blue"] .aurora-bg::before,
|
|
html[data-theme="dark-blue"] .aurora-bg::after,
|
|
html[data-theme="dark-blue"] .aurora-stars::before,
|
|
html[data-theme="dark-blue"] .aurora-stars::after,
|
|
html[data-theme="light"] .aurora-bg::before,
|
|
html[data-theme="light"] .aurora-bg::after,
|
|
html[data-theme="light"] .aurora-stars::before,
|
|
html[data-theme="light"] .aurora-stars::after {
|
|
display: none;
|
|
}
|
|
|
|
/* Same suppression on the body-level layers Nebula uses. */
|
|
html[data-theme="dark-blue"]::before,
|
|
html[data-theme="dark-blue"]::after,
|
|
html[data-theme="light"]::before,
|
|
html[data-theme="light"]::after {
|
|
display: none;
|
|
}
|