[object Object]

← 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

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 →