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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"app.connection_lost": "Server unreachable",
|
||||
"app.connection_retrying": "Attempting to reconnect…",
|
||||
"theme.toggle": "Toggle theme",
|
||||
"bg.anim.toggle": "Toggle ambient background",
|
||||
"accent.title": "Accent color",
|
||||
"accent.custom": "Custom",
|
||||
"accent.reset": "Reset",
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"app.connection_lost": "Сервер недоступен",
|
||||
"app.connection_retrying": "Попытка переподключения…",
|
||||
"theme.toggle": "Переключить тему",
|
||||
"bg.anim.toggle": "Анимированный фон",
|
||||
"accent.title": "Цвет акцента",
|
||||
"accent.custom": "Свой",
|
||||
"accent.reset": "Сброс",
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"app.connection_lost": "服务器不可达",
|
||||
"app.connection_retrying": "正在尝试重新连接…",
|
||||
"theme.toggle": "切换主题",
|
||||
"bg.anim.toggle": "切换动态背景",
|
||||
"accent.title": "主题色",
|
||||
"accent.custom": "自定义",
|
||||
"accent.reset": "重置",
|
||||
|
||||
Reference in New Issue
Block a user