← back to Quadrille Showroom
Remove Age View / age-adaptive theming entirely (per Steve's call)
e4d7ecae4e4e54c7b49035f0e1d6989b2872144b · 2026-07-01 10:40:11 -0700 · Steve
Age becomes a plain signup data point (signup flow to be scoped separately) — not an
in-showroom control. Ripped out the whole apparatus:
• deleted public/js/ageview.js + its <script> tag
• deleted all 6 scripts/verify-ageview-*.mjs + AGE-VIEWS-SPEC.md
• removed the _qh Age View control surface (setAvatarAge/coalesceAvatarAge/avatarAge/
ageRigParams export/upperRigState/setEnvForAge/resetEnv) from showroom.js
• dropped the '#btn-ageview' dock entry + clickthrough selector; removed the
Age-View-ON pass from verify-walls-on-next; dropped the two ageview npm scripts
KEPT byte-for-byte: the baseline age-28 avatar. buildAvatar()/ageRigParams() are the
normal showroom body's own material/dimension helpers (isBaseline fast-paths) and predate
Age View — nothing can now drive a non-28 age or age-tint the env.
Verified: fresh Playwright smoke — _ageview undefined, no levers, no #btn-ageview,
avatar present (6 children), 50 wings, 0 console errors; verify-walls-on-next still PASS.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Files touched
M package.jsonM public/js/dock.jsM public/js/showroom.jsM public/showroom.htmlM scripts/clickthrough-showroom.mjsM scripts/verify-walls-on-next.mjs
Diff
commit e4d7ecae4e4e54c7b49035f0e1d6989b2872144b
Author: Steve <steve@designerwallcoverings.com>
Date: Wed Jul 1 10:40:11 2026 -0700
Remove Age View / age-adaptive theming entirely (per Steve's call)
Age becomes a plain signup data point (signup flow to be scoped separately) — not an
in-showroom control. Ripped out the whole apparatus:
• deleted public/js/ageview.js + its <script> tag
• deleted all 6 scripts/verify-ageview-*.mjs + AGE-VIEWS-SPEC.md
• removed the _qh Age View control surface (setAvatarAge/coalesceAvatarAge/avatarAge/
ageRigParams export/upperRigState/setEnvForAge/resetEnv) from showroom.js
• dropped the '#btn-ageview' dock entry + clickthrough selector; removed the
Age-View-ON pass from verify-walls-on-next; dropped the two ageview npm scripts
KEPT byte-for-byte: the baseline age-28 avatar. buildAvatar()/ageRigParams() are the
normal showroom body's own material/dimension helpers (isBaseline fast-paths) and predate
Age View — nothing can now drive a non-28 age or age-tint the env.
Verified: fresh Playwright smoke — _ageview undefined, no levers, no #btn-ageview,
avatar present (6 children), 50 wings, 0 console errors; verify-walls-on-next still PASS.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---
package.json | 4 +--
public/js/dock.js | 1 -
public/js/showroom.js | 61 +--------------------------------------
public/showroom.html | 1 -
scripts/clickthrough-showroom.mjs | 2 +-
scripts/verify-walls-on-next.mjs | 22 +-------------
6 files changed, 4 insertions(+), 87 deletions(-)
diff --git a/package.json b/package.json
index 537a0d7..0f8a0e4 100644
--- a/package.json
+++ b/package.json
@@ -7,12 +7,10 @@
"build-data": "node scripts/build-showroom-data.js",
"gen-assets": "node scripts/gen-assets.js",
"verify-carousel": "node scripts/verify-carousel.mjs",
- "verify-ageview-gate": "node scripts/verify-ageview-gate.mjs",
"verify-sort-density-persist": "node scripts/verify-sort-density-persist.mjs",
"verify-scene-render": "node scripts/verify-scene-render.mjs",
- "verify-ageview-crossengine": "node scripts/verify-ageview-crossengine.mjs",
"verify-table-view": "node scripts/verify-table-view.mjs",
- "verify-all": "npm run verify-ageview-gate && npm run verify-sort-density-persist && npm run verify-scene-render && npm run verify-table-view"
+ "verify-all": "npm run verify-sort-density-persist && npm run verify-scene-render && npm run verify-table-view"
},
"license": "ISC",
"description": "The Quadrille House — 3D Endless Wings Wallcovering Showroom (China Seas)",
diff --git a/public/js/dock.js b/public/js/dock.js
index 5b2383e..13408cf 100644
--- a/public/js/dock.js
+++ b/public/js/dock.js
@@ -39,7 +39,6 @@
{ sel: '#top-bar [data-section="wings"]', label: 'Wing Boards' },
{ sel: '#top-bar [data-section="overview"]', label: 'Overview' },
{ sel: '#btn-explore', label: 'Explore (WASD)' },
- { sel: '#btn-ageview', label: 'Age View' },
{ sel: '#btn-bookmatch', label: 'Open Board' },
{ sel: '#btn-walls', label: 'Wallpaper Walls' },
{ sel: '#btn-music', label: 'Music' },
diff --git a/public/js/showroom.js b/public/js/showroom.js
index d1ea09d..cf44df1 100644
--- a/public/js/showroom.js
+++ b/public/js/showroom.js
@@ -1119,21 +1119,6 @@ function ageRigParams(age) {
let avatarAge = 28; // current avatar age; 28 == today's rig
let avatarUpperRig = null; // named sub-group (torso+neck+shoulders+arms) — the stoop pivot
-// Age View drags the slider continuously (one 'input' per pixel), and setAvatarAge does a
-// FULL primitive teardown+rebuild — unthrottled that's dozens of rebuilds/sec + GC churn
-// mid-drag (the real FPS-gate failure mode; contrarian 2026-07-01). Coalesce rapid
-// setAvatarAge calls to at most ONE rebuild per animation frame. buildAvatar() itself stays
-// synchronous + byte-for-byte identical (boot + OFF-reset paths call it directly).
-let _avatarAgePending = null, _avatarAgeRaf = 0;
-function coalesceAvatarAge(age) {
- _avatarAgePending = Math.max(12, Math.min(85, age));
- if (_avatarAgeRaf) return;
- _avatarAgeRaf = requestAnimationFrame(() => {
- _avatarAgeRaf = 0;
- if (_avatarAgePending != null) { const a = _avatarAgePending; _avatarAgePending = null; buildAvatar(a); }
- });
-}
-
function buildAvatar(age) {
// Clean rebuild safety (rebuilds shouldn't stack bodies)
if (avatarRig) { scene.remove(avatarRig); avatarRig = null; }
@@ -5139,7 +5124,7 @@ window._qh = {
get avatarPresent() { return !!avatarRig; },
// Show/hide the first-person body. Called by viewmodes: visible only in Walk-Through
// (true first-person), hidden in every framed view so the camera doesn't render the
- // avatar's back across the whole frame. Persists across setAvatarAge() rebuilds.
+ // avatar's back across the whole frame.
setAvatarVisible(v) { avatarWanted = !!v; if (avatarRig) avatarRig.visible = avatarWanted; },
get avatarVisible() { return avatarWanted; },
// ---- PHASE 3 "At the Table" surface — the SEATED third-person figure + consultation
@@ -5163,50 +5148,6 @@ window._qh = {
eye: lockedSpinEye ? { x: lockedSpinEye.x, y: lockedSpinEye.y, z: lockedSpinEye.z } : null
};
},
- // ---- Chunk K′ — AGE VIEW control surface (default-off; only used when Age View is ON).
- // setAvatarAge rebuilds the primitive rig at a continuous age (12→85). getAvatarAge
- // returns the current age. ageRigParams exposes the lerp for the HUD readout/tests.
- // upperRigState proves the named stoop sub-group exists + reports its rotation (0 at 28).
- // setEnvForAge does CHEAP scalar/colour env tweaks only (exposure + ambient/hemi/key
- // intensity + tint) — no geometry/layout change, so FPS is untouched (contrarian #5).
- // resetEnv restores the baseline gallery light.
- setAvatarAge(age) { coalesceAvatarAge(age); },
- get avatarAge() { return avatarAge; },
- ageRigParams,
- upperRigState() {
- if (!avatarUpperRig) return null;
- return { present: true, name: avatarUpperRig.name, rotX: avatarUpperRig.rotation.x, childCount: avatarUpperRig.children.length };
- },
- setEnvForAge(age) {
- age = Math.max(12, Math.min(85, age));
- const amb = scene.children.find(o => o.isAmbientLight);
- const hemi = scene.children.find(o => o.isHemisphereLight);
- const key = window._keyLight, pic = window._picLight;
- // Senior bands (65+) RAISE ambient + REDUCE harsh speculars (glare control for the
- // aging lens); youth bands are brighter/punchier; mid is neutral baseline.
- let exposure = 1.02, ambI = 0.42, hemiI = 0.42, keyI = 1.05, picI = 0.55;
- if (age <= 16) { exposure = 1.10; ambI = 0.46; hemiI = 0.48; keyI = 1.12; picI = 0.60; }
- else if (age <= 35) { exposure = 1.02; ambI = 0.42; hemiI = 0.42; keyI = 1.05; picI = 0.55; }
- else if (age <= 55) { exposure = 1.06; ambI = 0.46; hemiI = 0.46; keyI = 0.98; picI = 0.52; }
- else if (age <= 75) { exposure = 1.08; ambI = 0.60; hemiI = 0.58; keyI = 0.82; picI = 0.46; }
- else { exposure = 1.10; ambI = 0.68; hemiI = 0.64; keyI = 0.74; picI = 0.42; }
- renderer.toneMappingExposure = exposure;
- if (amb) amb.intensity = ambI;
- if (hemi) hemi.intensity = hemiI;
- if (key) key.intensity = keyI;
- if (pic) pic.intensity = picI;
- requestShadowUpdate(2);
- },
- resetEnv() {
- renderer.toneMappingExposure = 1.02;
- const amb = scene.children.find(o => o.isAmbientLight);
- const hemi = scene.children.find(o => o.isHemisphereLight);
- if (amb) amb.intensity = 0.42;
- if (hemi) hemi.intensity = 0.42;
- if (window._keyLight) window._keyLight.intensity = 1.05;
- if (window._picLight) window._picLight.intensity = 0.55;
- requestShadowUpdate(2);
- },
// Drive the spin pose for headless verification (no key events in screenshot harness).
setSpin(yaw, pitch) {
if (typeof yaw === 'number') spinYaw = Math.max(-YAW_CLAMP, Math.min(YAW_CLAMP, yaw));
diff --git a/public/showroom.html b/public/showroom.html
index 21e3f2b..39108f3 100644
--- a/public/showroom.html
+++ b/public/showroom.html
@@ -438,7 +438,6 @@
<script src="/js/showroom.js"></script>
<script src="/js/viewmodes.js"></script>
<script src="/js/versions.js"></script>
- <script src="/js/ageview.js"></script>
<!-- Hamburger dock: stows every panel on load, re-launches each as a movable modal -->
<script src="/js/modal-rig.js"></script>
<script src="/js/dock.js"></script>
diff --git a/scripts/clickthrough-showroom.mjs b/scripts/clickthrough-showroom.mjs
index b3e9aa0..93fa0aa 100644
--- a/scripts/clickthrough-showroom.mjs
+++ b/scripts/clickthrough-showroom.mjs
@@ -39,7 +39,7 @@ const PANELS = [
];
const TOOLS = [
'#btn-peruse', '#top-bar [data-section="wings"]', '#top-bar [data-section="overview"]',
- '#btn-explore', '#btn-ageview', '#btn-bookmatch', '#btn-walls', '#btn-music',
+ '#btn-explore', '#btn-bookmatch', '#btn-walls', '#btn-music',
'#btn-lighting', '#btn-fullscreen',
];
diff --git a/scripts/verify-walls-on-next.mjs b/scripts/verify-walls-on-next.mjs
index 67cf19c..a7c146c 100644
--- a/scripts/verify-walls-on-next.mjs
+++ b/scripts/verify-walls-on-next.mjs
@@ -31,28 +31,8 @@ await p.screenshot({path:'recordings/phase5/walls-after.png'});
await p.evaluate(()=>window._qh.pageCenterBook(-1)); await p.waitForTimeout(1400);
const pv=await snap(); rows.push(['prev 1',pv.idx,pv.sku,JSON.stringify(pv.clad),allClad(pv.clad)]); if(!allClad(pv.clad))pass=false;
-// ---- Age-View-ON pass: paging the book under Age View must STILL clad all 4 walls.
-// A demo user can be in Age View (senior band) when they hit Next/Prev; the env+
-// avatar morph must not break the wall-clad path. (Backlog (c) regression guard.)
-const ageviewPresent = await p.evaluate(()=>!!(window._ageview && window._ageview.apply));
-if (ageviewPresent) {
- await p.evaluate(()=>{ window._ageview.setOn(true); window._ageview.apply(75); });
- await p.waitForTimeout(1500);
- for (let i=1;i<=2;i++){
- await p.evaluate(()=>window._qh.pageCenterBook(1));
- await p.waitForTimeout(1400);
- const s=await snap();
- const ok=allClad(s.clad);
- rows.push([`AV next ${i}`,s.idx,s.sku,JSON.stringify(s.clad),ok]);
- if(!ok) pass=false;
- }
- await p.evaluate(()=>window._ageview.setOn(false)); await p.waitForTimeout(800);
-} else {
- rows.push(['AV skip','-','no _ageview','[]',false]); pass=false;
-}
-
console.log('step | idx | sku | cladSides | all4?');
rows.forEach(r=>console.log(r[0].padEnd(9),'|',String(r[1]).padEnd(3),'|',String(r[2]||'-').padEnd(14),'|',r[3].padEnd(34),'|',r[4]?'YES':'NO'));
console.log('console errors:',errs.length, errs.slice(0,5).join(' | '));
-console.log('OVERALL:', pass&&errs.length===0?'✅ PASS — Next clads all 4 walls (Age View OFF + ON)':'❌ FAIL');
+console.log('OVERALL:', pass&&errs.length===0?'✅ PASS — Next clads all 4 walls':'❌ FAIL');
await b.close(); process.exit(pass&&errs.length===0?0:1);
← e0bed2f verify: At-the-Table behavioral test (nook hide/restore + se
·
back to Quadrille Showroom
·
chore: v1.2.0 → v1.2.1 (session close — /5x fixes + verifica 88e4cd8 →