Rate monitor: call embers rise off the bars in proportion to real traffic
1-3 tiny accent sparks per socket update drift up from each bar's fill tip, scaled by the real (unclamped) rate — motion strictly means API calls are happening right now. Self-removing DOM nodes with a per-bar live cap of 6, suppressed during cooldown and under reduced-effects mode. The taste-risk one of the set: revert this commit alone if it reads as noise.
This commit is contained in:
parent
7efb5da893
commit
1ad3dac222
2 changed files with 45 additions and 0 deletions
|
|
@ -383,6 +383,14 @@ function _renderEqualizerBars(grid, data) {
|
|||
}
|
||||
bar.classList.toggle('cooldown', cooling);
|
||||
|
||||
// Call embers: tiny accent sparks rise off the fill tip, spawned per
|
||||
// socket update in proportion to REAL traffic — motion strictly means
|
||||
// API calls are happening right now. Suppressed during cooldown and
|
||||
// under reduced-effects.
|
||||
if (!window._reduceEffectsActive && !cooling && realPct > 0.03) {
|
||||
_spawnEmbers(bar, pct, realPct > 0.6 ? 3 : realPct > 0.25 ? 2 : 1);
|
||||
}
|
||||
|
||||
// Daily-budget ring (Spotify is the only service with a real daily
|
||||
// cap): a conic rim inside the avatar disc fills as the budget is
|
||||
// spent — green → amber → red, purple once the worker has bridged
|
||||
|
|
@ -409,6 +417,23 @@ function _renderEqualizerBars(grid, data) {
|
|||
}
|
||||
}
|
||||
|
||||
// Spawn ember particles at a bar's fill tip. Self-removing DOM sparks with
|
||||
// a per-bar live cap so a busy hour can't accumulate nodes.
|
||||
function _spawnEmbers(bar, pct, count) {
|
||||
const track = bar.querySelector('.rate-eq-track');
|
||||
if (!track || track.querySelectorAll('.rate-eq-ember').length > 6) return;
|
||||
for (let i = 0; i < count; i++) {
|
||||
const e = document.createElement('span');
|
||||
e.className = 'rate-eq-ember';
|
||||
e.style.left = `${20 + Math.random() * 60}%`;
|
||||
e.style.bottom = `${Math.min(96, pct * 100)}%`;
|
||||
e.style.setProperty('--ember-drift', `${(Math.random() - 0.5) * 14}px`);
|
||||
e.style.animationDuration = `${1.1 + Math.random() * 0.7}s`;
|
||||
e.addEventListener('animationend', () => e.remove());
|
||||
track.appendChild(e);
|
||||
}
|
||||
}
|
||||
|
||||
// Animate a single integer counter from `from` to `to` with an
|
||||
// easeOutCubic curve. Used by the equalizer bars so the live count
|
||||
// digit-rolls instead of snapping when sockets push a new value.
|
||||
|
|
|
|||
|
|
@ -63340,6 +63340,26 @@ body.reduce-effects .dash-card::after {
|
|||
text-shadow: 0 0 8px rgba(239, 68, 68, 0.8);
|
||||
}
|
||||
|
||||
/* Call embers — tiny accent sparks rising off the fill tip, spawned per
|
||||
* socket update in proportion to real traffic. Motion == actual API calls. */
|
||||
.rate-eq-ember {
|
||||
position: absolute;
|
||||
width: 3px;
|
||||
height: 3px;
|
||||
border-radius: 50%;
|
||||
background: color-mix(in srgb, var(--eq-accent) 60%, white 40%);
|
||||
box-shadow: 0 0 6px var(--eq-accent);
|
||||
pointer-events: none;
|
||||
animation: rate-eq-ember-rise 1.4s ease-out forwards;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
@keyframes rate-eq-ember-rise {
|
||||
0% { opacity: 0; transform: translate(0, 0) scale(1); }
|
||||
15% { opacity: 0.9; }
|
||||
100% { opacity: 0; transform: translate(var(--ember-drift, 0px), -26px) scale(0.4); }
|
||||
}
|
||||
|
||||
/* Recovery flash — the moment a ban expires the track blinks back alive */
|
||||
.rate-eq.recovered .rate-eq-track {
|
||||
animation: rate-eq-recovered 1.2s ease-out;
|
||||
|
|
|
|||
Loading…
Reference in a new issue