Add optional ambient animated background with toggle

Three blurred color blobs (green, blue, purple) slowly drift behind
the UI for atmosphere. Toggled via cloud icon in header, persisted
in localStorage, off by default. Works with both dark and light themes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-12 11:06:56 +03:00
parent 2f221f6219
commit 40ea2e3b99
5 changed files with 112 additions and 0 deletions

View File

@@ -83,6 +83,89 @@ body.modal-open {
width: 100%;
}
/* ── Ambient animated background ── */
#bg-anim-layer {
display: none;
position: fixed;
inset: 0;
z-index: -1;
pointer-events: none;
overflow: hidden;
background: var(--bg-color);
}
[data-bg-anim="on"] #bg-anim-layer {
display: block;
}
[data-bg-anim="on"] body {
background: transparent;
}
#bg-anim-layer .bg-blob {
position: absolute;
border-radius: 50%;
filter: blur(80px);
will-change: transform;
}
#bg-anim-layer .bg-blob-a {
width: 600px;
height: 400px;
top: 10%;
left: 10%;
background: var(--bg-anim-a);
animation: blobA 20s ease-in-out infinite alternate;
}
#bg-anim-layer .bg-blob-b {
width: 500px;
height: 500px;
top: 40%;
right: 5%;
background: var(--bg-anim-b);
animation: blobB 25s ease-in-out infinite alternate;
}
#bg-anim-layer .bg-blob-c {
width: 450px;
height: 550px;
bottom: 5%;
left: 30%;
background: var(--bg-anim-c);
animation: blobC 22s ease-in-out infinite alternate;
}
[data-theme="dark"] {
--bg-anim-a: rgba(76, 175, 80, 0.10);
--bg-anim-b: rgba(33, 150, 243, 0.08);
--bg-anim-c: rgba(156, 39, 176, 0.07);
}
[data-theme="light"] {
--bg-anim-a: rgba(76, 175, 80, 0.10);
--bg-anim-b: rgba(33, 150, 243, 0.08);
--bg-anim-c: rgba(156, 39, 176, 0.07);
}
@keyframes blobA {
0% { transform: translate(0, 0) scale(1); }
50% { transform: translate(15vw, 10vh) scale(1.15); }
100% { transform: translate(-5vw, 20vh) scale(0.9); }
}
@keyframes blobB {
0% { transform: translate(0, 0) scale(1); }
50% { transform: translate(-20vw, -10vh) scale(1.1); }
100% { transform: translate(5vw, 15vh) scale(0.95); }
}
@keyframes blobC {
0% { transform: translate(0, 0) scale(1); }
50% { transform: translate(10vw, -15vh) scale(1.2); }
100% { transform: translate(-10vw, -5vh) scale(0.85); }
}
.container {
padding: 20px;
}