visuals: frosted-glass terminal/msgflow, row fade-in, badge pulses

agent terminal-wrap + dashboard msgflow get a translucent bg with
backdrop-filter blur+saturate so page-bg glow softens behind them.
new rows in the live panel and the dashboard message flow fade in
with a 4px slide-up. unread badge pulses; pending-operator-questions
section pulses its glow. history-backfilled rows skip the animation
(.no-anim) so the page doesn't stagger 100 fade-ins on load.
This commit is contained in:
müde 2026-05-15 19:20:15 +02:00
parent 3f2aba4adc
commit fd39226883
3 changed files with 49 additions and 5 deletions

View file

@ -250,10 +250,13 @@
function clearPlaceholder() {
if (placeholder) { log.innerHTML = ''; placeholder = null; }
}
// Backfill replays mark rows .no-anim so we don't stagger 100 fade-ins
// on page load. Set via `currentNoAnim` before the row helpers fire.
let currentNoAnim = false;
function row(cls, text) {
clearPlaceholder();
const e = document.createElement('div');
e.className = 'row ' + (cls || '');
e.className = 'row ' + (cls || '') + (currentNoAnim ? ' no-anim' : '');
e.textContent = text;
log.appendChild(e);
log.scrollTop = log.scrollHeight;
@ -262,7 +265,7 @@
function details(cls, summary, body) {
clearPlaceholder();
const d = document.createElement('details');
d.className = 'row ' + (cls || '');
d.className = 'row ' + (cls || '') + (currentNoAnim ? ' no-anim' : '');
const s = document.createElement('summary');
s.textContent = summary;
d.appendChild(s);
@ -394,11 +397,13 @@
if (!resp.ok) return;
const events = await resp.json();
let openTurns = 0;
currentNoAnim = true;
for (const ev of events) {
handle(ev, { fromHistory: true });
if (ev.kind === 'turn_start') openTurns += 1;
else if (ev.kind === 'turn_end') openTurns = Math.max(0, openTurns - 1);
}
currentNoAnim = false;
for (let i = 0; i < openTurns; i++) setBannerActive(true);
if (events.length) row('note', '─── live (older above) ───');
else setPlaceholder('(connected — waiting for events)');