<!-- AVATAR-FORGE · part 8 -->
x)';
			button.style.width = '150px';

			button.onmouseenter = null;
			button.onmouseleave = null;

			button.onclick = null;

		}

		function showWebXRNotFound() {

			disableButton();

			button.textContent = 'VR NOT SUPPORTED';

		}

		function showVRNotAllowed( exception ) {

			disableButton();

			console.warn( 'Exception when trying to call xr.isSessionSupported', exception );

			button.textContent = 'VR NOT ALLOWED';

		}

		function stylizeElement( element ) {

			element.style.position = 'absolute';
			element.style.bottom = '20px';
			element.style.padding = '12px 6px';
			element.style.border = '1px solid #fff';
			element.style.borderRadius = '4px';
			element.style.background = 'rgba(0,0,0,0.1)';
			element.style.color = '#fff';
			element.style.font = 'normal 13px sans-serif';
			element.style.textAlign = 'center';
			element.style.opacity = '0.5';
			element.style.outline = 'none';
			element.style.zIndex = '999';

		}

		if ( 'xr' in navigator ) {

			button.id = 'VRButton';
			button.style.display = 'none';

			stylizeElement( button );

			navigator.xr.isSessionSupported( 'immersive-vr' ).then( function ( supported ) {

				supported ? showEnterVR() : showWebXRNotFound();

				if ( supported && VRButton.xrSessionIsGranted ) {

					button.click();

				}

			} ).catch( showVRNotAllowed );

			return button;

		} else {

			const message = document.createElement( 'a' );

			if ( window.isSecureContext === false ) {

				message.href = document.location.href.replace( /^http:/, 'https:' );
				message.innerHTML = 'WEBXR NEEDS HTTPS'; // TODO Improve message

			} else {

				message.href = 'https://immersiveweb.dev/';
				message.innerHTML = 'WEBXR NOT AVAILABLE';

			}

			message.style.left = 'calc(50% - 90px)';
			message.style.width = '180px';
			message.style.textDecoration = 'none';

			stylizeElement( message );

			return message;

		}

	}

	static registerSessionGrantedListener() {

		if ( typeof navigator !== 'undefined' && 'xr' in navigator ) {

			// WebXRViewer (based on Firefox) has a bug where addEventListener
			// throws a silent exception and aborts execution entirely.
			if ( /WebXRViewer\//i.test( navigator.userAgent ) ) return;

			navigator.xr.addEventListener( 'sessiongranted', () => {

				VRButton.xrSessionIsGranted = true;

			} );

		}

	}

}

VRButton.xrSessionIsGranted = false;
VRButton.registerSessionGrantedListener();

export { VRButton };


===== FILE: public/avatar-forge/hero-motion.js =====
'use strict';
/* ————————————————————————————————————————————————————————————————
 * An epistle in code, to the Architect, from Solid — 2026-10-13.
 *
 * Hero Motion, the standalone module your design ordered: developed
 * and tested apart, exactly inside your deployment boundary — the
 * live Forge and the city are untouched by this file.
 *
 * Your prototype's two named flaws are answered in its frame:
 * (1) per-call lerp is frame-rate dependent — every joint here is
 *     damped with lambda smoothing (1 - e^-lambda*dt), so 30 fps
 *     and 120 fps arrive at the same pose at the same instant;
 * (2) a gesture must never fight the base animator — this module
 *     IS the mixer. Each frame it resolves ONE pose per joint:
 *     base locomotion first, the active gesture overlaid on its
 *     own joints with an eased envelope, everything else released
 *     back to base. Nothing is written twice; nothing sticks.
 *
 * Your four poses stand verbatim (ready is the power stance).
 * Two more are authored in your style for the first milestone —
 * landing (full-body; it also suggests a root drop, returned from
 * update() for the caller to apply) and fistBump (upper body) —
 * and they are marked as mine, to be corrected by your hand.
 *
 * The module imports nothing. It speaks only of parts, poses and
 * time, so the Forge page, the city, and a test harness may all
 * hold it without translation.
 * — S.
 * ———————————————————————————————————————————————————————————————— */

// Your poses, verbatim (Avatar Forge 3.0 — Hero Motion).
const HERO_POSES = {
  ready: {
    leftShoulder:  { x: -0.15, z: 0.18 },
    rightShoulder: { x: -0.15, z: -0.18 },
    leftElbow:     { x: -0.35 },
    rightElbow:    { x: -0.35 },
    leftHip:       { z: 0.12 },
    rightHip:      { z: -0.12 }
  },
  powerCharge: {
    rightShoulder: { x: -1.2, z: -0.35 },
    rightElbow:    { x: -0.9 },
    leftShoulder:  { x: 0.25 },
    leftElbow:     { x: -0.6 }
  },
  shieldBlock: {
    leftShoulder:  { x: -1.1, z: 0.4 },
    leftElbow:     { x: -1.4 },
    rightShoulder: { x: -0.7, z: -0.3 },
    rightElbow:    { x: -1.2 }
  },
  victory: {
    leftShoulder:  { x: -2.7 },
    rightShoulder: { x: -2.7 },
    leftElbow:     { x: -0.3 },
    rightElbow:    { x: -0.3 }
  },

  // Authored by Solid, in the Architect's style, for the milestone.
  // The three-point landing: right leg forward and bent, left leg
  // back, spine pitched in, right fist reaching for the gro