← back to Dead Agentabrams
auto-data-snapshot: 2026-09-02T09:04:08 (28 data files) — .playwright-mcp/page-2026-09-02T16-00-16-757Z.yml .playwright-mcp/page-2026-09-02T16-04-10-719Z.yml docs/TK-11101-perf-a11y.patch verification/tk11100-crossbrowser/REPORT.md verification/tk11100-crossbrowser/results.json
306d63a4837e2858d6d093ab9dc2bd3c4c28ed19 · 2026-09-02 09:04:17 -0700 · auto-commit-fleet
Files touched
A .playwright-mcp/page-2026-09-02T16-00-16-757Z.ymlA .playwright-mcp/page-2026-09-02T16-04-10-719Z.ymlA docs/TK-11101-perf-a11y.patch
Diff
commit 306d63a4837e2858d6d093ab9dc2bd3c4c28ed19
Author: auto-commit-fleet <steve@designerwallcoverings.com>
Date: Wed Sep 2 09:04:17 2026 -0700
auto-data-snapshot: 2026-09-02T09:04:08 (28 data files) — .playwright-mcp/page-2026-09-02T16-00-16-757Z.yml .playwright-mcp/page-2026-09-02T16-04-10-719Z.yml docs/TK-11101-perf-a11y.patch verification/tk11100-crossbrowser/REPORT.md verification/tk11100-crossbrowser/results.json
---
.playwright-mcp/page-2026-09-02T16-00-16-757Z.yml | 14 +++
.playwright-mcp/page-2026-09-02T16-04-10-719Z.yml | 11 +++
docs/TK-11101-perf-a11y.patch | 113 ++++++++++++++++++++++
3 files changed, 138 insertions(+)
diff --git a/.playwright-mcp/page-2026-09-02T16-00-16-757Z.yml b/.playwright-mcp/page-2026-09-02T16-00-16-757Z.yml
new file mode 100644
index 0000000..7e74fa2
--- /dev/null
+++ b/.playwright-mcp/page-2026-09-02T16-00-16-757Z.yml
@@ -0,0 +1,14 @@
+- generic [active] [ref=e1]:
+ - link "Skip to controls" [ref=e2] [cursor=pointer]:
+ - /url: "#dock"
+ - link "Back to The Main Stage" [ref=e3] [cursor=pointer]:
+ - /url: https://stage.agentabrams.com
+ - text: ← The Main Stage
+ - main "Scarlet Riverboat Masquerade — an animated visual gallery you can steer with the controls and keyboard" [ref=e4]:
+ - heading "Scarlet Riverboat Masquerade — an animated generative gallery" [level=1] [ref=e5]
+ - generic:
+ - paragraph: A Riverboat Listening Room
+ - heading [level=1] [aria-hidden]: Scarlet Riverboat Masquerade
+ - paragraph: Chapter I · Departure
+ - button "☰ Controls" [ref=e8] [cursor=pointer]
+ - paragraph [ref=e9]: Wide river view. Chapter one, Departure.
\ No newline at end of file
diff --git a/.playwright-mcp/page-2026-09-02T16-04-10-719Z.yml b/.playwright-mcp/page-2026-09-02T16-04-10-719Z.yml
new file mode 100644
index 0000000..9c1b749
--- /dev/null
+++ b/.playwright-mcp/page-2026-09-02T16-04-10-719Z.yml
@@ -0,0 +1,11 @@
+- generic [active] [ref=e1]:
+ - link "Skip to controls" [ref=e2] [cursor=pointer]:
+ - /url: "#dock"
+ - main "Scarlet Riverboat Masquerade — an animated visual gallery you can steer with the controls and keyboard" [ref=e3]:
+ - heading "Scarlet Riverboat Masquerade — an animated generative gallery" [level=1] [ref=e4]
+ - generic:
+ - paragraph: A Riverboat Listening Room
+ - heading [level=1] [aria-hidden]: Scarlet Riverboat Masquerade
+ - paragraph: Chapter I · Departure
+ - button "☰ Controls" [ref=e7] [cursor=pointer]
+ - paragraph [ref=e8]: Wide river view. Chapter one, Departure.
\ No newline at end of file
diff --git a/docs/TK-11101-perf-a11y.patch b/docs/TK-11101-perf-a11y.patch
new file mode 100644
index 0000000..784740a
--- /dev/null
+++ b/docs/TK-11101-perf-a11y.patch
@@ -0,0 +1,113 @@
+--- a/room/index.html 2026-09-02 08:59:47
++++ b/room/index.html 2026-09-02 09:03:51
+@@ -237,6 +237,10 @@
+ }
+ @media (prefers-reduced-motion: reduce){
+ .museum,.chapters button,.btn,.skip{transition:none}
++ /* also silence the always-on keyframe loops (live-dot pulse, loading tiles) */
++ *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important}
++ .musicroom.playing .live-dot{animation:none}
++ .mr-yr.loading{animation:none}
+ }
+ </style>
+ </head>
+@@ -266,9 +270,9 @@
+ </header>
+ <div class="mrbody" id="mrbody">
+ <input class="mr-search" id="mrSearch" type="search" placeholder="🔍 Search the archive — date, city, song…" aria-label="Search the Grateful Dead archive">
+- <div class="mr-src" id="mrSrc" role="tablist" aria-label="Choose a music source"></div>
++ <div class="mr-src" id="mrSrc" role="group" aria-label="Choose a music source"></div>
+ <div class="mr-map-head"><span id="mrMapLabel">Tap a year</span><button type="button" class="mr-allbtn on" id="mrAll">All years</button></div>
+- <div class="mr-map" id="mrMap" role="listbox" aria-label="Browse shows by year"></div>
++ <div class="mr-map" id="mrMap" role="group" aria-label="Browse shows by year"></div>
+ <input type="hidden" id="mrYear" value="">
+ <div class="mr-results" id="mrResults" role="list"></div>
+ <div class="mr-picks">Curated nights:</div>
+@@ -401,6 +405,18 @@
+ if (window.matchMedia && matchMedia('(prefers-reduced-motion: reduce)').matches){
+ S.reduced = true;
+ }
++// ...and keep honoring it if the visitor flips the OS setting mid-session
++if (window.matchMedia){
++ const _rmq = matchMedia('(prefers-reduced-motion: reduce)');
++ const _sync = e => {
++ S.reduced = e.matches;
++ const rb = document.getElementById('reduceBtn');
++ if (rb) rb.setAttribute('aria-pressed', String(S.reduced));
++ if (S.reduced) ctx.clearRect(0,0,S.W,S.H);
++ };
++ if (_rmq.addEventListener) _rmq.addEventListener('change', _sync);
++ else if (_rmq.addListener) _rmq.addListener(_sync);
++}
+
+ // ---------- Palettes + per-chapter choreography ----------
+ const CHAPTERS = [
+@@ -1240,6 +1256,8 @@
+ const reacting = !!(window.SRM && window.SRM.react);
+ S.amp = reacting ? (window.SRM.level||0) : 0;
+ S.pulse = reacting ? (window.SRM.pulse||0) : 0; // sharp per-beat throb for lamps
++ // bridge visual state to the separate WebGL orb loop so it can honor reduced motion + pause
++ if(window.SRM){ window.SRM.reduced = S.reduced; window.SRM.playing = S.playing; }
+ // fire a burst on each new detected beat
+ if(reacting && !S.reduced && window.SRM.beat>_seenBeat){ _seenBeat=window.SRM.beat; spawnFirework(); }
+ else if(!reacting){ _seenBeat=window.SRM?(window.SRM.beat||0):0; } // let fireworks decay naturally
+@@ -1619,6 +1637,8 @@
+ }
+ let _avg=0, _clock=0, _lastBeat=-99;
+ function sampleLevel(){
++ // stop the rAF loop when it has nothing to analyze; reactBtn / audio 'play' restart it
++ if(!window.SRM.react || audio.paused){ _looping=false; return; }
+ if(_analyser){
+ _analyser.getByteFrequencyData(_freq);
+ let sum=0, n=Math.max(1,Math.floor(_freq.length/6)); // low-end (bass) energy
+@@ -1647,7 +1667,9 @@
+ announce(on?'Reacting to the music — lanterns, fireflies, and dancers now move to the live audio.':'Back to authored motion.');
+ });
+
+-audio.addEventListener('play',()=>setPlay(true));
++audio.addEventListener('play',()=>{ setPlay(true);
++ if(window.SRM.react && _actx){ if(_actx.state==='suspended') _actx.resume(); if(!_looping){ _looping=true; sampleLevel(); } }
++});
+ audio.addEventListener('pause',()=>setPlay(false));
+ audio.addEventListener('ended',()=>{ if(trackIdx<tracks.length-1) playTrack(trackIdx+1); else setPlay(false); });
+ audio.addEventListener('timeupdate',()=>{
+@@ -1707,7 +1729,7 @@
+ mapEl.innerHTML='';
+ YEARS.forEach(y=>{
+ const b=document.createElement('button'); b.type='button'; b.className='mr-yr loading';
+- b.dataset.y=String(y); b.setAttribute('role','option'); b.title=y+' — counting…';
++ b.dataset.y=String(y); b.title=y+' — counting…';
+ b.innerHTML=`<span class="yl">${y}</span><span class="yc">…</span>`;
+ b.addEventListener('click',()=>setYear(y));
+ b.addEventListener('mouseenter',()=>{ const c=counts[ck(window.MR_SRC,y)]; if(c!=null) mapLabel.textContent=`${y} · ${c.toLocaleString()} shows`; });
+@@ -1734,11 +1756,11 @@
+
+ if(srcEl){
+ srcEl.innerHTML=Object.entries(window.MR_SOURCES).map(([k,s])=>
+- `<button type="button" data-src="${k}" class="${k===window.MR_SRC?'on':''}" role="tab" aria-selected="${k===window.MR_SRC}"><b>${s.label}</b><span class="yr">${s.years}</span></button>`).join('');
++ `<button type="button" data-src="${k}" class="${k===window.MR_SRC?'on':''}" aria-pressed="${k===window.MR_SRC}"><b>${s.label}</b><span class="yr">${s.years}</span></button>`).join('');
+ srcEl.addEventListener('click',e=>{
+ const btn=e.target.closest('button[data-src]'); if(!btn||btn.dataset.src===window.MR_SRC) return;
+ window.MR_SRC=btn.dataset.src;
+- [...srcEl.children].forEach(c=>{ const on=c.dataset.src===window.MR_SRC; c.classList.toggle('on',on); c.setAttribute('aria-selected',String(on)); });
++ [...srcEl.children].forEach(c=>{ const on=c.dataset.src===window.MR_SRC; c.classList.toggle('on',on); c.setAttribute('aria-pressed',String(on)); });
+ yearEl.value=''; allBtn.classList.add('on'); mapLabel.textContent='Tap a year';
+ buildMap(); searchArchive(searchEl?searchEl.value:'');
+ });
+@@ -1804,8 +1826,16 @@
+ scene.add(new THREE.AmbientLight(0x402028,0.9));
+ const col=new THREE.Color();
+ addEventListener('resize',()=>{ W=innerWidth;H=innerHeight; camera.aspect=W/H; camera.updateProjectionMatrix(); renderer.setSize(W,H,false); });
++ let _orbStatic=false;
+ function loop(){ requestAnimationFrame(loop);
+ const s=window.SRM||{}, t=performance.now()/1000;
++ // Honor reduced motion (WCAG 2.3.3): draw one calm static frame, then stop spinning + re-rendering.
++ if(s.reduced){
++ if(!_orbStatic){ group.rotation.set(Math.sin(t*0.3)*0.18,0,0); group.scale.setScalar(1);
++ core.material.emissiveIntensity=0.7; renderer.render(scene,camera); _orbStatic=true; }
++ return;
++ }
++ _orbStatic=false;
+ const pulse=s.pulse||0, level=(s.react?(s.level||0):0);
+ const idle=0.5+0.5*Math.sin(t*1.2); // gentle breathing when no music
+ const energy=s.react ? (level*0.6+pulse*0.7) : idle*0.12;
← 570c039 room: archive.org fetch timeout + graceful failure (5x harde
·
back to Dead Agentabrams
·
docs(TK-11101): perf+a11y audit of room/index.html — finding 062e20e →