fix(bg): add translucent veil so animated bgs don't bleed UI
The single bg-fx layer was painting at full vibrancy behind the entire
app. Most UI elements use rgba() fills — chips, sub-panels, the
achievements .ach-item, the goal-tier bar — so saturated colors bled
right through, hurting readability on the Достижения / dashboard /
mocks tabs.
Layered fix:
• bg-fx drops to z-index:-2 (the animated layer)
• new #ls-bg-veil sits on z-index:-1 with rgba(245,247,251,.78)
(light) or rgba(15,23,42,.55) when body[data-bg-tone='dark']
• applyCosmetics injects both elements and tags the body with
bg-tone based on the slug (dark/stars/aurora/nebula/grid go dark,
everything else light)
• clearing the bg removes both layers + the tone attribute
Result: animations stay perceptible (~22% of the chosen palette comes
through the veil), but the page chrome reads at normal contrast.
Shop swatches keep full vibrancy — the .bg-preview is meant to show
the raw palette so users can compare.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+19
-1
@@ -1211,12 +1211,30 @@ body.no-gamification [data-gamified] { display: none !important; }
|
||||
#ls-bg-fx {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: -1;
|
||||
z-index: -2;
|
||||
pointer-events: none;
|
||||
overflow: hidden;
|
||||
will-change: opacity, transform, background-position;
|
||||
transition: opacity .4s ease;
|
||||
}
|
||||
/* The veil: a translucent white sheet that sits between the animated
|
||||
bg layer and page content. Without it, vibrant backgrounds bleed
|
||||
straight through every UI element that uses an rgba() fill — chips,
|
||||
cards, panel backdrops. With it, the animation reads as a subtle
|
||||
accent rather than a takeover. */
|
||||
#ls-bg-veil {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: -1;
|
||||
pointer-events: none;
|
||||
background: rgba(245, 247, 251, 0.78);
|
||||
transition: background .4s ease;
|
||||
}
|
||||
/* On the 'dark' preset we want a darker veil so light content still
|
||||
pops. body[data-bg-tone="dark"] is set by api.js for dark slugs. */
|
||||
body[data-bg-tone="dark"] #ls-bg-veil {
|
||||
background: rgba(15, 23, 42, 0.55);
|
||||
}
|
||||
.bg-preview {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
@@ -1080,19 +1080,33 @@ async function applyCosmetics() {
|
||||
|
||||
// ── Background: paint a fixed div behind the whole UI ──
|
||||
// The element is created on demand and reused on subsequent calls
|
||||
// so swapping backgrounds doesn't flash.
|
||||
// so swapping backgrounds doesn't flash. A second fixed div sits
|
||||
// ON TOP of it (#ls-bg-veil, z-index:-1 vs bg-fx -2) acting as a
|
||||
// translucent veil so vibrant animations don't drown out the UI.
|
||||
// The tone attr on <body> lets the veil darken for dark presets.
|
||||
const DARK_BG_SLUGS = new Set(['dark', 'stars', 'aurora', 'nebula', 'grid']);
|
||||
if (c.background && c.background.slug && c.background.slug !== 'none') {
|
||||
const slug = String(c.background.slug).replace(/[^a-z0-9_-]/gi, '');
|
||||
let bgEl = document.getElementById('ls-bg-fx');
|
||||
if (!bgEl) {
|
||||
bgEl = document.createElement('div');
|
||||
bgEl.id = 'ls-bg-fx';
|
||||
document.body.insertBefore(bgEl, document.body.firstChild);
|
||||
}
|
||||
bgEl.className = 'bg-' + String(c.background.slug).replace(/[^a-z0-9_-]/gi, '');
|
||||
bgEl.className = 'bg-' + slug;
|
||||
let veilEl = document.getElementById('ls-bg-veil');
|
||||
if (!veilEl) {
|
||||
veilEl = document.createElement('div');
|
||||
veilEl.id = 'ls-bg-veil';
|
||||
// Insert just after bg-fx so it paints above (same z-index gap).
|
||||
bgEl.parentNode.insertBefore(veilEl, bgEl.nextSibling);
|
||||
}
|
||||
document.body.dataset.bgTone = DARK_BG_SLUGS.has(slug) ? 'dark' : 'light';
|
||||
} else {
|
||||
// Active bg was cleared — remove the element if present.
|
||||
const bgEl = document.getElementById('ls-bg-fx');
|
||||
if (bgEl) bgEl.remove();
|
||||
// Active bg was cleared — remove both layers.
|
||||
document.getElementById('ls-bg-fx')?.remove();
|
||||
document.getElementById('ls-bg-veil')?.remove();
|
||||
delete document.body.dataset.bgTone;
|
||||
}
|
||||
|
||||
// ── Frame: apply CSS to sidebar avatar on every page ──
|
||||
|
||||
Reference in New Issue
Block a user