{"version":3,"sources":["jsdelivr-header.js","/npm/p5.tree@0.0.43/deps/tree/dist/index.js","/npm/p5.tree@0.0.43/src/matrix.js","/npm/p5.tree@0.0.43/src/visibility.js","/npm/p5.tree@0.0.43/src/gizmos.js","/npm/p5.tree@0.0.43/src/picking.js","/npm/p5.tree@0.0.43/src/track.js","/npm/p5.tree@0.0.43/deps/ui/dist/index.js","/npm/p5.tree@0.0.43/src/panel.js","/npm/p5.tree@0.0.43/src/index.js","/npm/p5.tree@0.0.43/src/constants.js","/npm/p5.tree@0.0.43/src/hud.js","/npm/p5.tree@0.0.43/src/pipe.js"],"names":[],"mappings":"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","file":"/npm/p5.tree@0.0.43/dist/p5.tree.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/p5.tree@0.0.43/dist/p5.tree.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","/**\n * @file Core constants — zero dependencies.\n * @module tree/constants\n * @license AGPL-3.0-only\n */\n\n// Coordinate spaces\nconst WORLD  = 'WORLD';\nconst EYE    = 'EYE';\nconst NDC    = 'NDC';\nconst SCREEN = 'SCREEN';\nconst MODEL  = 'MODEL';\nconst MATRIX = 'MATRIX';\n\n// NDC Z convention (only difference between backends)\nconst WEBGL  = -1;   // z ∈ [−1, 1]\nconst WEBGPU =  0;   // z ∈ [0, 1]\n\n// Visibility results\nconst INVISIBLE   = 0;\nconst VISIBLE     = 1;\nconst SEMIVISIBLE = 2;\n\n// Basis vectors (frozen plain arrays — duck-typed Vec3)\nconst ORIGIN = Object.freeze([0, 0, 0]);\nconst i  = Object.freeze([1, 0, 0]);\nconst j  = Object.freeze([0, 1, 0]);\nconst k  = Object.freeze([0, 0, 1]);\nconst _i = Object.freeze([-1, 0, 0]);\nconst _j = Object.freeze([0, -1, 0]);\nconst _k = Object.freeze([0, 0, -1]);\n\n/**\n * @file Quaternion algebra and mat4/mat3 conversions.\n * @module tree/quat\n * @license AGPL-3.0-only\n *\n * Quaternions are stored as flat [x, y, z, w] arrays (w-last, glTF layout).\n *\n * All functions follow the out-first, zero-allocation contract.\n * Conversion functions bridge between quaternion and matrix representations\n * but do not perform any higher-level graphics operations — those belong\n * in form.js (matrix construction from specs) or track.js (animation).\n */\n\n\n// =========================================================================\n// Basic ops\n// =========================================================================\n\n/** Set all four components. @returns {number[]} out */\nconst qSet = (out, x, y, z, w) => {\n  out[0] = x; out[1] = y; out[2] = z; out[3] = w; return out;\n};\n\n/** Copy quaternion a into out. @returns {number[]} out */\nconst qCopy = (out, a) => {\n  out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; return out;\n};\n\n/** Dot product of two quaternions. */\nconst qDot = (a, b) => a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3];\n\n/** Normalise quaternion in-place. @returns {number[]} out */\nconst qNormalize = (out) => {\n  const l = Math.sqrt(out[0]*out[0]+out[1]*out[1]+out[2]*out[2]+out[3]*out[3]) || 1;\n  out[0]/=l; out[1]/=l; out[2]/=l; out[3]/=l; return out;\n};\n\n/** Negate quaternion (same rotation, different hemisphere). @returns {number[]} out */\nconst qNegate = (out, a) => {\n  out[0]=-a[0]; out[1]=-a[1]; out[2]=-a[2]; out[3]=-a[3]; return out;\n};\n\n/** Hamilton product out = a * b. @returns {number[]} out */\nconst qMul = (out, a, b) => {\n  const ax=a[0],ay=a[1],az=a[2],aw=a[3], bx=b[0],by=b[1],bz=b[2],bw=b[3];\n  out[0]=aw*bx+ax*bw+ay*bz-az*by;\n  out[1]=aw*by-ax*bz+ay*bw+az*bx;\n  out[2]=aw*bz+ax*by-ay*bx+az*bw;\n  out[3]=aw*bw-ax*bx-ay*by-az*bz;\n  return out;\n};\n\n// =========================================================================\n// Interpolation\n// =========================================================================\n\n/** Spherical linear interpolation. @returns {number[]} out */\nconst qSlerp = (out, a, b, t) => {\n  let bx=b[0],by=b[1],bz=b[2],bw=b[3];\n  let d = a[0]*bx+a[1]*by+a[2]*bz+a[3]*bw;\n  if (d < 0) { bx=-bx; by=-by; bz=-bz; bw=-bw; d=-d; }\n  let f0, f1;\n  if (1-d > 1e-10) {\n    const th=Math.acos(d), st=Math.sin(th);\n    f0=Math.sin((1-t)*th)/st; f1=Math.sin(t*th)/st;\n  } else {\n    f0=1-t; f1=t;\n  }\n  out[0]=a[0]*f0+bx*f1; out[1]=a[1]*f0+by*f1;\n  out[2]=a[2]*f0+bz*f1; out[3]=a[3]*f0+bw*f1;\n  return qNormalize(out);\n};\n\n/**\n * Normalised linear interpolation (nlerp).\n * Cheaper than slerp; slightly non-constant angular velocity.\n * Handles antipodal quats by flipping b when dot < 0.\n * @returns {number[]} out\n */\nconst qNlerp = (out, a, b, t) => {\n  let bx=b[0],by=b[1],bz=b[2],bw=b[3];\n  if (a[0]*bx+a[1]*by+a[2]*bz+a[3]*bw < 0) { bx=-bx; by=-by; bz=-bz; bw=-bw; }\n  out[0]=a[0]+t*(bx-a[0]); out[1]=a[1]+t*(by-a[1]);\n  out[2]=a[2]+t*(bz-a[2]); out[3]=a[3]+t*(bw-a[3]);\n  return qNormalize(out);\n};\n\n// =========================================================================\n// Construction\n// =========================================================================\n\n/**\n * Build a quaternion from axis-angle.\n * @param {number[]} out\n * @param {number} ax @param {number} ay @param {number} az  Axis (need not be unit).\n * @param {number} angle  Radians.\n * @returns {number[]} out\n */\nconst qFromAxisAngle = (out, ax, ay, az, angle) => {\n  const half = angle * 0.5;\n  const s    = Math.sin(half);\n  const len  = Math.sqrt(ax*ax + ay*ay + az*az) || 1;\n  out[0] = s * ax / len; out[1] = s * ay / len; out[2] = s * az / len;\n  out[3] = Math.cos(half);\n  return out;\n};\n\n/**\n * Build a quaternion from a look direction (−Z forward) and optional up (default +Y).\n * @param {number[]} out\n * @param {number[]} dir  Forward direction [x,y,z].\n * @param {number[]} [up] Up vector [x,y,z].\n * @returns {number[]} out\n */\nconst qFromLookDir = (out, dir, up) => {\n  let fx=dir[0],fy=dir[1],fz=dir[2];\n  const fl=Math.sqrt(fx*fx+fy*fy+fz*fz)||1;\n  fx/=fl; fy/=fl; fz/=fl;\n  let ux=up?up[0]:0, uy=up?up[1]:1, uz=up?up[2]:0;\n  let rx=uy*fz-uz*fy, ry=uz*fx-ux*fz, rz=ux*fy-uy*fx;\n  const rl=Math.sqrt(rx*rx+ry*ry+rz*rz)||1;\n  rx/=rl; ry/=rl; rz/=rl;\n  ux=fy*rz-fz*ry; uy=fz*rx-fx*rz; uz=fx*ry-fy*rx;\n  return qFromRotMat3x3(out, rx,ry,rz, ux,uy,uz, -fx,-fy,-fz);\n};\n\n/**\n * Build a quaternion from a 3×3 rotation matrix (9 row-major scalars).\n * @returns {number[]} out (normalised)\n */\nconst qFromRotMat3x3 = (out, m00,m01,m02, m10,m11,m12, m20,m21,m22) => {\n  const tr = m00+m11+m22;\n  if (tr > 0) {\n    const s=0.5/Math.sqrt(tr+1);\n    out[3]=0.25/s; out[0]=(m21-m12)*s; out[1]=(m02-m20)*s; out[2]=(m10-m01)*s;\n  } else if (m00>m11 && m00>m22) {\n    const s=2*Math.sqrt(1+m00-m11-m22);\n    out[3]=(m21-m12)/s; out[0]=0.25*s; out[1]=(m01+m10)/s; out[2]=(m02+m20)/s;\n  } else if (m11>m22) {\n    const s=2*Math.sqrt(1+m11-m00-m22);\n    out[3]=(m02-m20)/s; out[0]=(m01+m10)/s; out[1]=0.25*s; out[2]=(m12+m21)/s;\n  } else {\n    const s=2*Math.sqrt(1+m22-m00-m11);\n    out[3]=(m10-m01)/s; out[0]=(m02+m20)/s; out[1]=(m12+m21)/s; out[2]=0.25*s;\n  }\n  return qNormalize(out);\n};\n\n/**\n * Extract a unit quaternion from the upper-left 3×3 of a column-major mat4.\n * @param {number[]} out\n * @param {Float32Array|number[]} m  Column-major mat4.\n * @returns {number[]} out\n */\nconst qFromMat4 = (out, m) =>\n  qFromRotMat3x3(out, m[0],m[4],m[8], m[1],m[5],m[9], m[2],m[6],m[10]);\n\n/**\n * Write a quaternion into the rotation block of a column-major mat4.\n * Translation and perspective rows/cols are set to identity values.\n * @param {Float32Array|number[]} out  16-element array.\n * @param {number[]} q  [x,y,z,w].\n * @returns {Float32Array|number[]} out\n */\nconst qToMat4 = (out, q) => {\n  const x=q[0],y=q[1],z=q[2],w=q[3];\n  const x2=x+x,y2=y+y,z2=z+z;\n  const xx=x*x2,xy=x*y2,xz=x*z2,yy=y*y2,yz=y*z2,zz=z*z2,wx=w*x2,wy=w*y2,wz=w*z2;\n  out[0]=1-(yy+zz); out[1]=xy+wz;     out[2]=xz-wy;     out[3]=0;\n  out[4]=xy-wz;     out[5]=1-(xx+zz); out[6]=yz+wx;     out[7]=0;\n  out[8]=xz+wy;     out[9]=yz-wx;     out[10]=1-(xx+yy); out[11]=0;\n  out[12]=0;        out[13]=0;        out[14]=0;          out[15]=1;\n  return out;\n};\n\n// =========================================================================\n// Decomposition\n// =========================================================================\n\n/**\n * Decompose a unit quaternion into { axis:[x,y,z], angle } (radians).\n * @param {number[]} q  [x,y,z,w].\n * @param {Object}  [out]\n * @returns {{ axis: number[], angle: number }}\n */\nconst qToAxisAngle = (q, out) => {\n  out = out || {};\n  const x=q[0],y=q[1],z=q[2],w=q[3];\n  const sinHalf = Math.sqrt(x*x+y*y+z*z);\n  if (sinHalf < 1e-8) { out.axis=[0,1,0]; out.angle=0; return out; }\n  out.angle = 2*Math.atan2(sinHalf, w);\n  out.axis  = [x/sinHalf, y/sinHalf, z/sinHalf];\n  return out;\n};\n\n/**\n * @file Matrix construction from geometric specs and partial decomposition.\n * @module tree/form\n * @license AGPL-3.0-only\n *\n * Constructs mat4s from higher-level specs: TRS transforms, orthonormal\n * bases, lookat parameters, projection parameters, and special-purpose\n * matrices (bias, reflection).\n *\n * Design invariant: form.js has no dependency on query.js. Construction\n * from specs requires only scalar arithmetic and quaternion conversions.\n * Callers compose the resulting matrices using query.js (mat4Mul etc.).\n *\n * ── NDC Z convention ──────────────────────────────────────────────────────\n * Controlled by `ndcZMin` in every projection constructor:\n *   WEBGL  = −1   near → NDC z = −1,  far → NDC z = +1\n *   WEBGPU =  0   near → NDC z =  0,  far → NDC z = +1\n *\n * ── NDC Y convention ──────────────────────────────────────────────────────\n * Controlled by `ndcYSign` in every projection constructor (default +1):\n *   +1  NDC y-up   — standard: OpenGL / WebGL / WebGPU browser / Three.js / p5v2\n *   −1  NDC y-down — native Vulkan clip space\n *\n * Negating ndcYSign flips row 1 of the projection matrix (elements\n * out[1], out[5], out[9], out[13]), reversing the y-axis in clip space.\n * mat4View, mat4Eye, and all non-projection constructors are convention-\n * agnostic — they produce the same matrix regardless of the NDC y direction.\n *\n * ── Screen Y convention ───────────────────────────────────────────────────\n * Screen-y direction (DOM y-down vs OpenGL y-up) is a separate concern from\n * NDC-y direction and is handled in query.js via the signed viewport height.\n * See the query.js module header for details.\n *\n * All functions follow the out-first, zero-allocation contract.\n */\n\n\n// =========================================================================\n// Frame construction\n// =========================================================================\n\n/**\n * Rigid frame from orthonormal basis + translation.\n * Column-major layout: col0=right, col1=up, col2=forward, col3=translation.\n *\n * @param {Float32Array|number[]} out  16-element destination.\n * @param {number} rx,ry,rz  Right vector (col 0).\n * @param {number} ux,uy,uz  Up vector    (col 1).\n * @param {number} fx,fy,fz  Forward vec  (col 2).\n * @param {number} tx,ty,tz  Translation  (col 3).\n */\nfunction mat4FromBasis(out, rx,ry,rz, ux,uy,uz, fx,fy,fz, tx,ty,tz) {\n  out[0]=rx;  out[1]=ry;  out[2]=rz;  out[3]=0;\n  out[4]=ux;  out[5]=uy;  out[6]=uz;  out[7]=0;\n  out[8]=fx;  out[9]=fy;  out[10]=fz; out[11]=0;\n  out[12]=tx; out[13]=ty; out[14]=tz; out[15]=1;\n  return out;\n}\n\n/**\n * View matrix (world→eye) from lookat parameters.\n * Camera looks along −Z in eye space; right = normalize(up × (−Z)).\n * Cheaper than building the eye matrix and inverting.\n *\n * @param {Float32Array|number[]} out  16-element destination.\n * @param {number} ex,ey,ez   Eye (camera) position.\n * @param {number} cx,cy,cz   Look-at target.\n * @param {number} ux,uy,uz   World up hint (need not be unit).\n */\nfunction mat4View(out, ex,ey,ez, cx,cy,cz, ux,uy,uz) {\n  let zx=ex-cx, zy=ey-cy, zz=ez-cz;\n  const zl=Math.sqrt(zx*zx+zy*zy+zz*zz)||1;\n  zx/=zl; zy/=zl; zz/=zl;\n  let xx=uy*zz-uz*zy, xy=uz*zx-ux*zz, xz=ux*zy-uy*zx;\n  const xl=Math.sqrt(xx*xx+xy*xy+xz*xz)||1;\n  xx/=xl; xy/=xl; xz/=xl;\n  const yx=zy*xz-zz*xy, yy=zz*xx-zx*xz, yz=zx*xy-zy*xx;\n  out[0]=xx;              out[1]=yx;              out[2]=zx;              out[3]=0;\n  out[4]=xy;              out[5]=yy;              out[6]=zy;              out[7]=0;\n  out[8]=xz;              out[9]=yz;              out[10]=zz;             out[11]=0;\n  out[12]=-(xx*ex+xy*ey+xz*ez);\n  out[13]=-(yx*ex+yy*ey+yz*ez);\n  out[14]=-(zx*ex+zy*ey+zz*ez);\n  out[15]=1;\n  return out;\n}\n\n/**\n * Eye matrix (eye→world) from lookat parameters.\n * Transpose of the rotation block + direct translation column.\n * Same parameters as mat4View.\n *\n * @param {Float32Array|number[]} out  16-element destination.\n * @param {number} ex,ey,ez   Eye position.\n * @param {number} cx,cy,cz   Look-at target.\n * @param {number} ux,uy,uz   World up hint.\n */\nfunction mat4Eye(out, ex,ey,ez, cx,cy,cz, ux,uy,uz) {\n  let zx=ex-cx, zy=ey-cy, zz=ez-cz;\n  const zl=Math.sqrt(zx*zx+zy*zy+zz*zz)||1;\n  zx/=zl; zy/=zl; zz/=zl;\n  let xx=uy*zz-uz*zy, xy=uz*zx-ux*zz, xz=ux*zy-uy*zx;\n  const xl=Math.sqrt(xx*xx+xy*xy+xz*xz)||1;\n  xx/=xl; xy/=xl; xz/=xl;\n  const yx=zy*xz-zz*xy, yy=zz*xx-zx*xz, yz=zx*xy-zy*xx;\n  out[0]=xx;  out[1]=xy;  out[2]=xz;  out[3]=0;\n  out[4]=yx;  out[5]=yy;  out[6]=yz;  out[7]=0;\n  out[8]=zx;  out[9]=zy;  out[10]=zz; out[11]=0;\n  out[12]=ex; out[13]=ey; out[14]=ez; out[15]=1;\n  return out;\n}\n\n// =========================================================================\n// TRS construction\n// =========================================================================\n\n/**\n * Column-major mat4 from flat TRS scalars. No struct allocation.\n *\n * @param {Float32Array|number[]} out  16-element destination.\n * @param {number} tx,ty,tz      Translation.\n * @param {number} qx,qy,qz,qw   Rotation quaternion [x,y,z,w].\n * @param {number} sx,sy,sz      Scale.\n */\nfunction mat4FromTRS(out, tx,ty,tz, qx,qy,qz,qw, sx,sy,sz) {\n  const x2=qx+qx,y2=qy+qy,z2=qz+qz;\n  const xx=qx*x2,xy=qx*y2,xz=qx*z2,yy=qy*y2,yz=qy*z2,zz=qz*z2;\n  const wx=qw*x2,wy=qw*y2,wz=qw*z2;\n  out[0]=(1-(yy+zz))*sx; out[1]=(xy+wz)*sx;      out[2]=(xz-wy)*sx;      out[3]=0;\n  out[4]=(xy-wz)*sy;     out[5]=(1-(xx+zz))*sy;  out[6]=(yz+wx)*sy;      out[7]=0;\n  out[8]=(xz+wy)*sz;     out[9]=(yz-wx)*sz;      out[10]=(1-(xx+yy))*sz; out[11]=0;\n  out[12]=tx; out[13]=ty; out[14]=tz; out[15]=1;\n  return out;\n}\n\n/**\n * Translation-only mat4.\n * @param {Float32Array|number[]} out  16-element destination.\n * @param {number} tx,ty,tz\n */\nfunction mat4FromTranslation(out, tx,ty,tz) {\n  out[0]=1; out[1]=0; out[2]=0;  out[3]=0;\n  out[4]=0; out[5]=1; out[6]=0;  out[7]=0;\n  out[8]=0; out[9]=0; out[10]=1; out[11]=0;\n  out[12]=tx; out[13]=ty; out[14]=tz; out[15]=1;\n  return out;\n}\n\n/**\n * Scale-only mat4.\n * @param {Float32Array|number[]} out  16-element destination.\n * @param {number} sx,sy,sz\n */\nfunction mat4FromScale(out, sx,sy,sz) {\n  out[0]=sx; out[1]=0;  out[2]=0;   out[3]=0;\n  out[4]=0;  out[5]=sy; out[6]=0;   out[7]=0;\n  out[8]=0;  out[9]=0;  out[10]=sz; out[11]=0;\n  out[12]=0; out[13]=0; out[14]=0;  out[15]=1;\n  return out;\n}\n\n// =========================================================================\n// Projection construction\n// =========================================================================\n\n/**\n * Orthographic projection matrix.\n *\n * @param {Float32Array|number[]} out  16-element destination.\n * @param {number} left,right,bottom,top  Frustum extents.\n * @param {number} near,far              Clip plane distances (positive).\n * @param {number} ndcZMin               −1 (WEBGL) or 0 (WEBGPU).\n * @param {number} [ndcYSign=1]          +1 = NDC y-up (default); −1 = NDC y-down (native Vulkan).\n */\nfunction mat4Ortho(out, left, right, bottom, top, near, far, ndcZMin, ndcYSign=1) {\n  const rl=1/(right-left), tb=1/(top-bottom), fn=1/(far-near);\n  out[0]=2*rl;              out[1]=0;                       out[2]=0;               out[3]=0;\n  out[4]=0;                 out[5]=ndcYSign*2*tb;           out[6]=0;               out[7]=0;\n  out[8]=0;                 out[9]=0;                       out[10]=(ndcZMin-1)*fn; out[11]=0;\n  out[12]=-(right+left)*rl; out[13]=ndcYSign*(-(top+bottom)*tb);\n  out[14]=(ndcZMin*far-near)*fn;\n  out[15]=1;\n  return out;\n}\n\n/**\n * Perspective projection matrix (general / off-centre frustum).\n * Symmetric case: left=-right, bottom=-top — derive from fov+aspect in user space:\n *   top = near * Math.tan(fov / 2);  right = top * aspect\n *   mat4Persp(out, -right, right, -top, top, near, far, ndcZMin)\n *\n * @param {Float32Array|number[]} out  16-element destination.\n * @param {number} left,right,bottom,top  Near-plane extents (signed, y-up: top>0, bottom<0).\n * @param {number} near,far              Clip plane distances (positive).\n * @param {number} ndcZMin               −1 (WEBGL) or 0 (WEBGPU).\n * @param {number} [ndcYSign=1]          +1 = NDC y-up (default); −1 = NDC y-down (native Vulkan).\n */\nfunction mat4Persp(out, left, right, bottom, top, near, far, ndcZMin, ndcYSign=1) {\n  const rl=1/(right-left), tb=1/(top-bottom);\n  out[0]=2*near*rl;        out[1]=0;                          out[2]=0;  out[3]=0;\n  out[4]=0;                out[5]=ndcYSign*2*near*tb;         out[6]=0;  out[7]=0;\n  out[8]=(right+left)*rl;  out[9]=ndcYSign*(top+bottom)*tb;\n  out[10]=(ndcZMin*near-far)/(far-near);\n  out[11]=-1;\n  out[12]=0; out[13]=0;\n  out[14]=(ndcZMin-1)*far*near/(far-near);\n  out[15]=0;\n  return out;\n}\n\n// =========================================================================\n// Special-purpose construction\n// =========================================================================\n\n/**\n * Bias matrix: remaps xyz from NDC to texture/UV space [0, 1].\n * xy remap from [−1, 1]; z remaps from [ndcZMin, 1].\n * Used to convert light-space NDC coordinates to shadow map UV.\n *\n * Convention note: the standard bias maps NDC y = −1 → texture v = 0 and\n * NDC y = +1 → texture v = 1. This is correct for both NDC y-up and y-down\n * conventions because the shadow map was rendered with the same projection.\n *\n * Column-major (WEBGL, ndcZMin=−1):   Column-major (WEBGPU, ndcZMin=0):\n *   [ 0.5  0    0    0.5 ]              [ 0.5  0    0    0.5 ]\n *   [ 0    0.5  0    0.5 ]              [ 0    0.5  0    0.5 ]\n *   [ 0    0    0.5  0.5 ]              [ 0    0    1    0   ]\n *   [ 0    0    0    1   ]              [ 0    0    0    1   ]\n *\n * @param {Float32Array|number[]} out  16-element destination.\n * @param {number} ndcZMin  WEBGL (−1) or WEBGPU (0).\n */\nfunction mat4Bias(out, ndcZMin) {\n  const sz=1/(1-ndcZMin), tz=-ndcZMin/(1-ndcZMin);\n  out[0]=0.5; out[1]=0;   out[2]=0;   out[3]=0;\n  out[4]=0;   out[5]=0.5; out[6]=0;   out[7]=0;\n  out[8]=0;   out[9]=0;   out[10]=sz; out[11]=0;\n  out[12]=0.5; out[13]=0.5; out[14]=tz; out[15]=1;\n  return out;\n}\n\n/**\n * Reflection matrix across a plane ax + by + cz = d.\n * [nx, ny, nz] must be a unit normal.\n *\n * @param {Float32Array|number[]} out  16-element destination.\n * @param {number} nx,ny,nz  Unit plane normal.\n * @param {number} d         Plane offset (dot(point_on_plane, normal)).\n */\nfunction mat4Reflect(out, nx,ny,nz,d) {\n  out[0]=1-2*nx*nx;  out[1]=-2*ny*nx;  out[2]=-2*nz*nx;  out[3]=0;\n  out[4]=-2*nx*ny;   out[5]=1-2*ny*ny; out[6]=-2*nz*ny;  out[7]=0;\n  out[8]=-2*nx*nz;   out[9]=-2*ny*nz;  out[10]=1-2*nz*nz; out[11]=0;\n  out[12]=2*d*nx;    out[13]=2*d*ny;   out[14]=2*d*nz;   out[15]=1;\n  return out;\n}\n\n/**\n * @file Matrix arithmetic, space-transform dispatch, and projection queries.\n * @module tree/query\n * @license AGPL-3.0-only\n *\n * The operative layer — receives matrices and extracts information.\n * Contrast with form.js which constructs matrices from specs.\n *\n *   form.js  — specs  → matrix\n *   query.js — matrix → information\n *\n * Storage: column-major Float32Array / ArrayLike<number>.\n * Multiply: mat4Mul(out, A, B) = A · B  (standard math order).\n * Pipeline: clip = P · V · M · v\n *\n * ── NDC Z convention ──────────────────────────────────────────────────────\n * Passed as `ndcZMin` to every space-transform function:\n *   WEBGL  = −1   z ∈ [−1,  1]\n *   WEBGPU =  0   z ∈ [ 0,  1]\n *\n * ── NDC Y convention ──────────────────────────────────────────────────────\n * Standard (OpenGL / WebGL / WebGPU browser / Three.js / p5v2):\n *   NDC y-up  — y = +1 at top, y = −1 at bottom.\n * Native Vulkan: NDC y-down — projections constructed with ndcYSign = −1\n * (see form.js).  Query functions are convention-agnostic: they work on\n * whatever matrices are passed in.\n *\n * ── Viewport convention ───────────────────────────────────────────────────\n * vp = [x, y, w, h] — w and h are SIGNED.\n *\n * The sign of h encodes the relationship between NDC y and screen y:\n *   h < 0 (e.g. −canvasH): screen y-DOWN  (DOM / p5 mouseX·mouseY / Vulkan surface)\n *                            NDC y=+1 → screen y=0  (top)\n *                            NDC y=−1 → screen y=H  (bottom)\n *   h > 0 (e.g. +canvasH): screen y-UP   (OpenGL desktop / WebGL gl_FragCoord)\n *                            NDC y=−1 → screen y=0  (bottom)\n *                            NDC y=+1 → screen y=H  (top)\n *\n * Pass [0, canvasH, canvasW, −canvasH] for p5/DOM coordinates.\n * Pass [0, 0, canvasW, canvasH] for WebGL gl_FragCoord / OpenGL bottom-left.\n * All helpers use vp[2]/vp[3] signed — no Math.abs — so both conventions\n * work automatically without any branching.\n *\n * All functions follow the out-first, zero-allocation contract.\n * Returns null on degeneracy (singular matrix, etc.).\n */\n\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Mat4 arithmetic\n// ═══════════════════════════════════════════════════════════════════════════\n\n/** out = A · B  (column-major) */\nfunction mat4Mul(out, A, B) {\n  const a0=A[0],a1=A[1],a2=A[2],a3=A[3],\n        a4=A[4],a5=A[5],a6=A[6],a7=A[7],\n        a8=A[8],a9=A[9],a10=A[10],a11=A[11],\n        a12=A[12],a13=A[13],a14=A[14],a15=A[15];\n  let b0=B[0],b1=B[1],b2=B[2],b3=B[3];\n  out[0]=a0*b0+a4*b1+a8*b2+a12*b3;\n  out[1]=a1*b0+a5*b1+a9*b2+a13*b3;\n  out[2]=a2*b0+a6*b1+a10*b2+a14*b3;\n  out[3]=a3*b0+a7*b1+a11*b2+a15*b3;\n  b0=B[4];b1=B[5];b2=B[6];b3=B[7];\n  out[4]=a0*b0+a4*b1+a8*b2+a12*b3;\n  out[5]=a1*b0+a5*b1+a9*b2+a13*b3;\n  out[6]=a2*b0+a6*b1+a10*b2+a14*b3;\n  out[7]=a3*b0+a7*b1+a11*b2+a15*b3;\n  b0=B[8];b1=B[9];b2=B[10];b3=B[11];\n  out[8]=a0*b0+a4*b1+a8*b2+a12*b3;\n  out[9]=a1*b0+a5*b1+a9*b2+a13*b3;\n  out[10]=a2*b0+a6*b1+a10*b2+a14*b3;\n  out[11]=a3*b0+a7*b1+a11*b2+a15*b3;\n  b0=B[12];b1=B[13];b2=B[14];b3=B[15];\n  out[12]=a0*b0+a4*b1+a8*b2+a12*b3;\n  out[13]=a1*b0+a5*b1+a9*b2+a13*b3;\n  out[14]=a2*b0+a6*b1+a10*b2+a14*b3;\n  out[15]=a3*b0+a7*b1+a11*b2+a15*b3;\n  return out;\n}\n\n/** out = inverse(src). Returns null if singular (|det| < 1e-12). */\nfunction mat4Invert(out, src) {\n  const s0=src[0],s1=src[1],s2=src[2],s3=src[3],\n        s4=src[4],s5=src[5],s6=src[6],s7=src[7],\n        s8=src[8],s9=src[9],s10=src[10],s11=src[11],\n        s12=src[12],s13=src[13],s14=src[14],s15=src[15];\n  const b0=s0*s5-s1*s4, b1=s0*s6-s2*s4, b2=s0*s7-s3*s4,\n        b3=s1*s6-s2*s5, b4=s1*s7-s3*s5, b5=s2*s7-s3*s6,\n        b6=s8*s13-s9*s12, b7=s8*s14-s10*s12, b8=s8*s15-s11*s12,\n        b9=s9*s14-s10*s13, b10=s9*s15-s11*s13, b11=s10*s15-s11*s14;\n  let det=b0*b11-b1*b10+b2*b9+b3*b8-b4*b7+b5*b6;\n  if (Math.abs(det) < 1e-12) return null;\n  det = 1/det;\n  out[0]=(s5*b11-s6*b10+s7*b9)*det;\n  out[1]=(s2*b10-s1*b11-s3*b9)*det;\n  out[2]=(s13*b5-s14*b4+s15*b3)*det;\n  out[3]=(s10*b4-s9*b5-s11*b3)*det;\n  out[4]=(s6*b8-s4*b11-s7*b7)*det;\n  out[5]=(s0*b11-s2*b8+s3*b7)*det;\n  out[6]=(s14*b2-s12*b5-s15*b1)*det;\n  out[7]=(s8*b5-s10*b2+s11*b1)*det;\n  out[8]=(s4*b10-s5*b8+s7*b6)*det;\n  out[9]=(s1*b8-s0*b10-s3*b6)*det;\n  out[10]=(s12*b4-s13*b2+s15*b0)*det;\n  out[11]=(s9*b2-s8*b4-s11*b0)*det;\n  out[12]=(s5*b7-s4*b9-s6*b6)*det;\n  out[13]=(s0*b9-s1*b7+s2*b6)*det;\n  out[14]=(s13*b1-s12*b3-s14*b0)*det;\n  out[15]=(s8*b3-s9*b1+s10*b0)*det;\n  return out;\n}\n\n/**\n * Normal matrix: inverseTranspose(upper-left 3×3 of src).\n * On degeneracy writes zeros and returns out.\n * @param {Float32Array|number[]} out  9-element destination.\n * @param {Float32Array|number[]} src  16-element mat4.\n */\nfunction mat3NormalFromMat4(out, src) {\n  const a00=src[0],a01=src[1],a02=src[2],\n        a10=src[4],a11=src[5],a12=src[6],\n        a20=src[8],a21=src[9],a22=src[10];\n  const b01=a22*a11-a12*a21, b11=-a22*a01+a02*a21, b21=a12*a01-a02*a11;\n  let det=a00*b01+a10*b11+a20*b21;\n  if (Math.abs(det) < 1e-12) { for(let i=0;i<9;i++)out[i]=0; return out; }\n  det=1/det;\n  out[0]=b01*det;           out[1]=(-a22*a10+a12*a20)*det; out[2]=(a21*a10-a11*a20)*det;\n  out[3]=b11*det;           out[4]=(a22*a00-a02*a20)*det;  out[5]=(-a21*a00+a01*a20)*det;\n  out[6]=b21*det;           out[7]=(-a12*a00+a02*a10)*det; out[8]=(a11*a00-a01*a10)*det;\n  return out;\n}\n\n/** out = mat4 * [x,y,z,1], perspective-divides, writes xyz. */\nfunction mat4MulPoint(out, m, x, y, z) {\n  const rx=m[0]*x+m[4]*y+m[8]*z+m[12], ry=m[1]*x+m[5]*y+m[9]*z+m[13],\n        rz=m[2]*x+m[6]*y+m[10]*z+m[14], rw=m[3]*x+m[7]*y+m[11]*z+m[15];\n  if (rw!==0&&rw!==1) { out[0]=rx/rw; out[1]=ry/rw; out[2]=rz/rw; }\n  else                 { out[0]=rx;    out[1]=ry;    out[2]=rz;    }\n  return out;\n}\n\n/**\n * Apply only the 3×3 linear block of a mat4 to a direction (no translation,\n * no perspective divide). Use mat3NormalFromMat4 for normals under non-uniform scale.\n */\nfunction mat4MulDir(out, m, dx, dy, dz) {\n  out[0]=m[0]*dx+m[4]*dy+m[8]*dz;\n  out[1]=m[1]*dx+m[5]*dy+m[9]*dz;\n  out[2]=m[2]*dx+m[6]*dy+m[10]*dz;\n  return out;\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Projection queries\n// ═══════════════════════════════════════════════════════════════════════════\n\n/** @returns {boolean} true if orthographic. */\nfunction projIsOrtho(p) { return p[15] !== 0; }\n\n/**\n * Near plane distance.\n * @param {ArrayLike<number>} p       Projection mat4.\n * @param {number}            ndcZMin WEBGL (−1) or WEBGPU (0).\n */\nfunction projNear(p, ndcZMin) {\n  return p[15]===0 ? p[14]/(p[10]+ndcZMin) : (p[14]-ndcZMin)/p[10];\n}\n\n/** Far plane distance (far always maps to NDC z = 1, convention-independent). */\nfunction projFar(p) {\n  return p[15]===0 ? p[14]/(1+p[10]) : (p[14]-1)/p[10];\n}\n\nfunction projLeft  (p, ndcZMin) { return p[15]===1 ? -(1+p[12])/p[0]  : projNear(p,ndcZMin)*(p[8]-1)/p[0];  }\nfunction projRight (p, ndcZMin) { return p[15]===1 ?  (1-p[12])/p[0]  : projNear(p,ndcZMin)*(1+p[8])/p[0];  }\n\n/**\n * Top extent of the near plane in camera space (y_max, positive for standard y-up camera).\n * Sign-normalized: returns the larger of the two y boundaries regardless of whether\n * the projection was built with ndcYSign = +1 or −1.\n */\nfunction projTop(p, ndcZMin) {\n  return p[15]===1\n    ? ( Math.sign(p[5]) - p[13]) / p[5]   // ortho\n    : projNear(p,ndcZMin)*(1+p[9])/p[5];  // perspective (p[5]>0 in practice)\n}\n\n/**\n * Bottom extent of the near plane in camera space (y_min, negative for standard y-up camera).\n */\nfunction projBottom(p, ndcZMin) {\n  return p[15]===1\n    ? (-Math.sign(p[5]) - p[13]) / p[5]   // ortho\n    : projNear(p,ndcZMin)*(p[9]-1)/p[5];  // perspective\n}\n\n/** Vertical field of view in radians (perspective only). */\nfunction projFov (p) { return Math.abs(2*Math.atan(1/p[5])); }\n/** Horizontal field of view in radians (perspective only). */\nfunction projHfov(p) { return Math.abs(2*Math.atan(1/p[0])); }\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Derived matrices\n// ═══════════════════════════════════════════════════════════════════════════\n\n/** out = P · V */\nfunction mat4PV(out, proj, view)  { return mat4Mul(out, proj, view); }\n/** out = V · M */\nfunction mat4MV(out, model, view) { return mat4Mul(out, view, model); }\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Frame-relative transforms\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Location transform between frames: out = inv(to) · from.\n * Assumes both matrices are affine (bottom row [0,0,0,1]).\n * @returns {ArrayLike<number>|null} out, or null if `to` is singular.\n */\nfunction mat4Location(out, from, to) {\n  // Same as: return mat4Invert(out, to) && mat4Mul(out, out, from);\n  const a00=to[0],a01=to[1],a02=to[2],\n        a10=to[4],a11=to[5],a12=to[6],\n        a20=to[8],a21=to[9],a22=to[10];\n  const b01=a22*a11-a12*a21, b11=a12*a20-a22*a10, b21=a21*a10-a11*a20;\n  let det=a00*b01+a01*b11+a02*b21;\n  if (Math.abs(det) < 1e-12) return null;\n  det=1/det;\n  const i00=b01*det,             i01=(a02*a21-a22*a01)*det, i02=(a12*a01-a02*a11)*det;\n  const i10=b11*det,             i11=(a22*a00-a02*a20)*det, i12=(a02*a10-a12*a00)*det;\n  const i20=b21*det,             i21=(a01*a20-a21*a00)*det, i22=(a11*a00-a01*a10)*det;\n  const f00=from[0],f01=from[1],f02=from[2],\n        f10=from[4],f11=from[5],f12=from[6],\n        f20=from[8],f21=from[9],f22=from[10];\n  out[0]=i00*f00+i01*f01+i02*f02; out[1]=i10*f00+i11*f01+i12*f02; out[2]=i20*f00+i21*f01+i22*f02; out[3]=0;\n  out[4]=i00*f10+i01*f11+i02*f12; out[5]=i10*f10+i11*f11+i12*f12; out[6]=i20*f10+i21*f11+i22*f12; out[7]=0;\n  out[8]=i00*f20+i01*f21+i02*f22; out[9]=i10*f20+i11*f21+i12*f22; out[10]=i20*f20+i21*f21+i22*f22; out[11]=0;\n  const dx=from[12]-to[12], dy=from[13]-to[13], dz=from[14]-to[14];\n  out[12]=i00*dx+i01*dy+i02*dz; out[13]=i10*dx+i11*dy+i12*dz; out[14]=i20*dx+i21*dy+i22*dz; out[15]=1;\n  return out;\n}\n\n/**\n * Direction transform between frames: out = to₃ · inv(from₃).\n * Uses only the upper-left 3×3 blocks (rotation/scale, no translation).\n * @returns {ArrayLike<number>|null} out, or null if `from` is singular.\n */\nfunction mat3Direction(out, from, to) {\n  const a00=from[0],a01=from[1],a02=from[2],\n        a10=from[4],a11=from[5],a12=from[6],\n        a20=from[8],a21=from[9],a22=from[10];\n  const b01=a22*a11-a12*a21, b11=a12*a20-a22*a10, b21=a21*a10-a11*a20;\n  let det=a00*b01+a01*b11+a02*b21;\n  if (Math.abs(det) < 1e-12) return null;\n  det=1/det;\n  const i00=b01*det,             i01=(a02*a21-a22*a01)*det, i02=(a12*a01-a02*a11)*det;\n  const i10=b11*det,             i11=(a22*a00-a02*a20)*det, i12=(a02*a10-a12*a00)*det;\n  const i20=b21*det,             i21=(a01*a20-a21*a00)*det, i22=(a11*a00-a01*a10)*det;\n  const t00=to[0],t01=to[1],t02=to[2], t10=to[4],t11=to[5],t12=to[6], t20=to[8],t21=to[9],t22=to[10];\n  out[0]=t00*i00+t10*i01+t20*i02; out[1]=t01*i00+t11*i01+t21*i02; out[2]=t02*i00+t12*i01+t22*i02;\n  out[3]=t00*i10+t10*i11+t20*i12; out[4]=t01*i10+t11*i11+t21*i12; out[5]=t02*i10+t12*i11+t22*i12;\n  out[6]=t00*i20+t10*i21+t20*i22; out[7]=t01*i20+t11*i21+t21*i22; out[8]=t02*i20+t12*i21+t22*i22;\n  return out;\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Space transforms — mapLocation / mapDirection\n// ═══════════════════════════════════════════════════════════════════════════\n//\n// Flat dispatch: every from→to pair is a self-contained leaf with only stack\n// locals — no reentrancy, no shared state between calls.\n//\n// Matrices bag `m`:\n//   mat4Proj    Float32Array(16)  projection  (eye → clip)\n//   mat4View    Float32Array(16)  view        (world → eye)\n//   mat4Eye?    Float32Array(16)  eye         (eye → world); caller fills before passing\n//   mat4PV?     Float32Array(16)  P · V;      caller fills or _ensurePV allocates once\n//   mat4PVInv?  Float32Array(16)  inv(P · V); caller fills\n//   fromFrame?  Float32Array(16)  MATRIX source frame\n//   toFrameInv? Float32Array(16)  inv(MATRIX dest frame)\n//\n// Viewport `vp` = [x, y, w, h]:\n//   Use SIGNED h to encode screen-y direction (see module header).\n//   Core formula: screen = (ndc*0.5+0.5)*vp[k] + vp[k-2]  (k=2 for x, k=3 for y)\n//   Inverse:      ndc    = ((screen-vp[k-2])/vp[k])*2 - 1\n//   Negative vp[3] flips NDC y-up to screen y-down automatically.\n//\n\n// ── Location helpers ─────────────────────────────────────────────────────\n\nfunction _worldToScreen(out, px, py, pz, pv, vp, ndcZMin) {\n  const x=pv[0]*px+pv[4]*py+pv[8]*pz+pv[12], y=pv[1]*px+pv[5]*py+pv[9]*pz+pv[13],\n        z=pv[2]*px+pv[6]*py+pv[10]*pz+pv[14], w=pv[3]*px+pv[7]*py+pv[11]*pz+pv[15];\n  const xi=(w!==0&&w!==1)?1/w:1;\n  out[0]=(x*xi*0.5+0.5)*vp[2]+vp[0];\n  out[1]=(y*xi*0.5+0.5)*vp[3]+vp[1];\n  out[2]=(z*xi-ndcZMin)/(1-ndcZMin);\n  return out;\n}\n\nfunction _screenToWorld(out, sx, sy, sz, ipv, vp, ndcZMin) {\n  return mat4MulPoint(out, ipv,\n    ((sx-vp[0])/vp[2])*2-1,\n    ((sy-vp[1])/vp[3])*2-1,\n    sz*(1-ndcZMin)+ndcZMin);\n}\n\nfunction _worldToNDC(out, px, py, pz, pv) {\n  const x=pv[0]*px+pv[4]*py+pv[8]*pz+pv[12], y=pv[1]*px+pv[5]*py+pv[9]*pz+pv[13],\n        z=pv[2]*px+pv[6]*py+pv[10]*pz+pv[14], w=pv[3]*px+pv[7]*py+pv[11]*pz+pv[15];\n  const xi=(w!==0&&w!==1)?1/w:1;\n  out[0]=x*xi; out[1]=y*xi; out[2]=z*xi;\n  return out;\n}\n\nfunction _ndcToWorld(out, nx, ny, nz, ipv) { return mat4MulPoint(out,ipv,nx,ny,nz); }\n\nfunction _screenToNDC(out, sx, sy, sz, vp, ndcZMin) {\n  out[0]=((sx-vp[0])/vp[2])*2-1;\n  out[1]=((sy-vp[1])/vp[3])*2-1;\n  out[2]=sz*(1-ndcZMin)+ndcZMin;\n  return out;\n}\n\nfunction _ndcToScreen(out, nx, ny, nz, vp, ndcZMin) {\n  out[0]=(nx*0.5+0.5)*vp[2]+vp[0];\n  out[1]=(ny*0.5+0.5)*vp[3]+vp[1];\n  out[2]=(nz-ndcZMin)/(1-ndcZMin);\n  return out;\n}\n\nfunction _ensurePV(m) {\n  if (m.mat4PV) return m.mat4PV;\n  m.mat4PV = new Float32Array(16);\n  mat4Mul(m.mat4PV, m.mat4Proj, m.mat4View);\n  return m.mat4PV;\n}\n\n/**\n * Map a point between named coordinate spaces.\n *\n * @param {number[]} out     3-element destination — written and returned.\n * @param {number}   px,py,pz Input point.\n * @param {string}   from    Source space (WORLD, EYE, SCREEN, NDC, MATRIX).\n * @param {string}   to      Destination space.\n * @param {object}   m       Matrices bag — see module header.\n * @param {number[]} vp      Viewport [x, y, w, h]; sign of h encodes screen-y direction.\n * @param {number}   ndcZMin WEBGL (−1) or WEBGPU (0).\n * @returns {number[]} out\n */\nfunction mapLocation(out, px, py, pz, from, to, m, vp, ndcZMin) {\n  if (from===WORLD && to===SCREEN) return _worldToScreen(out,px,py,pz,_ensurePV(m),vp,ndcZMin);\n  if (from===SCREEN && to===WORLD) return _screenToWorld(out,px,py,pz,m.mat4PVInv,vp,ndcZMin);\n\n  if (from===WORLD && to===NDC)   return _worldToNDC(out,px,py,pz,_ensurePV(m));\n  if (from===NDC   && to===WORLD) return _ndcToWorld(out,px,py,pz,m.mat4PVInv);\n\n  if (from===SCREEN && to===NDC)    return _screenToNDC(out,px,py,pz,vp,ndcZMin);\n  if (from===NDC    && to===SCREEN) return _ndcToScreen(out,px,py,pz,vp,ndcZMin);\n\n  if (from===WORLD && to===EYE) return mat4MulPoint(out,m.mat4View,px,py,pz);\n  if (from===EYE && to===WORLD) return mat4MulPoint(out,m.mat4Eye,px,py,pz);\n\n  if (from===EYE && to===SCREEN) {\n    const e=m.mat4Eye;\n    return _worldToScreen(out,e[0]*px+e[4]*py+e[8]*pz+e[12],\n                              e[1]*px+e[5]*py+e[9]*pz+e[13],\n                              e[2]*px+e[6]*py+e[10]*pz+e[14],_ensurePV(m),vp,ndcZMin);\n  }\n  if (from===SCREEN && to===EYE) {\n    _screenToWorld(out,px,py,pz,m.mat4PVInv,vp,ndcZMin);\n    return mat4MulPoint(out,m.mat4View,out[0],out[1],out[2]);\n  }\n\n  if (from===EYE && to===NDC) {\n    const e=m.mat4Eye;\n    return _worldToNDC(out,e[0]*px+e[4]*py+e[8]*pz+e[12],\n                           e[1]*px+e[5]*py+e[9]*pz+e[13],\n                           e[2]*px+e[6]*py+e[10]*pz+e[14],_ensurePV(m));\n  }\n  if (from===NDC && to===EYE) {\n    _ndcToWorld(out,px,py,pz,m.mat4PVInv);\n    return mat4MulPoint(out,m.mat4View,out[0],out[1],out[2]);\n  }\n\n  if (from===MATRIX && to===WORLD) return mat4MulPoint(out,m.fromFrame,px,py,pz);\n  if (from===WORLD && to===MATRIX) return mat4MulPoint(out,m.toFrameInv,px,py,pz);\n\n  if (from===MATRIX && to===EYE) {\n    const f=m.fromFrame;\n    return mat4MulPoint(out,m.mat4View,f[0]*px+f[4]*py+f[8]*pz+f[12],\n                                       f[1]*px+f[5]*py+f[9]*pz+f[13],\n                                       f[2]*px+f[6]*py+f[10]*pz+f[14]);\n  }\n  if (from===EYE && to===MATRIX) {\n    const e=m.mat4Eye;\n    return mat4MulPoint(out,m.toFrameInv,e[0]*px+e[4]*py+e[8]*pz+e[12],\n                                         e[1]*px+e[5]*py+e[9]*pz+e[13],\n                                         e[2]*px+e[6]*py+e[10]*pz+e[14]);\n  }\n\n  if (from===MATRIX && to===SCREEN) {\n    const f=m.fromFrame;\n    return _worldToScreen(out,f[0]*px+f[4]*py+f[8]*pz+f[12],\n                              f[1]*px+f[5]*py+f[9]*pz+f[13],\n                              f[2]*px+f[6]*py+f[10]*pz+f[14],_ensurePV(m),vp,ndcZMin);\n  }\n  if (from===SCREEN && to===MATRIX) {\n    _screenToWorld(out,px,py,pz,m.mat4PVInv,vp,ndcZMin);\n    return mat4MulPoint(out,m.toFrameInv,out[0],out[1],out[2]);\n  }\n\n  if (from===MATRIX && to===NDC) {\n    const f=m.fromFrame;\n    return _worldToNDC(out,f[0]*px+f[4]*py+f[8]*pz+f[12],\n                           f[1]*px+f[5]*py+f[9]*pz+f[13],\n                           f[2]*px+f[6]*py+f[10]*pz+f[14],_ensurePV(m));\n  }\n  if (from===NDC && to===MATRIX) {\n    _ndcToWorld(out,px,py,pz,m.mat4PVInv);\n    return mat4MulPoint(out,m.toFrameInv,out[0],out[1],out[2]);\n  }\n\n  if (from===MATRIX && to===MATRIX) {\n    const f=m.fromFrame;\n    return mat4MulPoint(out,m.toFrameInv,f[0]*px+f[4]*py+f[8]*pz+f[12],\n                                         f[1]*px+f[5]*py+f[9]*pz+f[13],\n                                         f[2]*px+f[6]*py+f[10]*pz+f[14]);\n  }\n\n  out[0]=px; out[1]=py; out[2]=pz;\n  return out;\n}\n\n// ── Direction helpers ────────────────────────────────────────────────────\n//\n// Directions use only the linear 3×3 block — no translation, no w-divide.\n// The signed vp[2]/vp[3] carries the y-convention automatically.\n//\n\nfunction _applyDir(out, m, dx, dy, dz) {\n  out[0]=m[0]*dx+m[4]*dy+m[8]*dz;\n  out[1]=m[1]*dx+m[5]*dy+m[9]*dz;\n  out[2]=m[2]*dx+m[6]*dy+m[10]*dz;\n  return out;\n}\n\nfunction _worldToScreenDir(out, dx, dy, dz, proj, view, vpW, vpH, ndcZMin) {\n  const vx=view[0]*dx+view[4]*dy+view[8]*dz,\n        vy=view[1]*dx+view[5]*dy+view[9]*dz,\n        vz=view[2]*dx+view[6]*dy+view[10]*dz;\n  // vpH is signed — negative flips y component automatically.\n  out[0]=(proj[0]*vx+proj[4]*vy+proj[8]*vz)*vpW*0.5;\n  out[1]=(proj[1]*vx+proj[5]*vy+proj[9]*vz)*vpH*0.5;\n  out[2]=(proj[2]*vx+proj[6]*vy+proj[10]*vz)*(1-ndcZMin)*0.5;\n  return out;\n}\n\nfunction _screenToWorldDir(out, dx, dy, dz, proj, eye, vpW, vpH, ndcZMin) {\n  // Inverse of _worldToScreenDir; signed vpW/vpH cancel the y-flip.\n  _applyDir(out, eye, dx/(vpW*0.5)/proj[0], dy/(vpH*0.5)/proj[5], dz/((1-ndcZMin)*0.5));\n  return out;\n}\n\nfunction _screenToNDCDir(out, dx, dy, dz, vpW, vpH, ndcZMin) {\n  out[0]=dx/(vpW*0.5); out[1]=dy/(vpH*0.5); out[2]=dz/((1-ndcZMin)*0.5);\n  return out;\n}\n\nfunction _ndcToScreenDir(out, dx, dy, dz, vpW, vpH, ndcZMin) {\n  out[0]=dx*vpW*0.5; out[1]=dy*vpH*0.5; out[2]=dz*(1-ndcZMin)*0.5;\n  return out;\n}\n\n/**\n * Map a direction between named coordinate spaces.\n * Same bag and viewport contract as mapLocation.\n *\n * @param {number[]} out     3-element destination.\n * @param {number}   dx,dy,dz Input direction.\n * @param {string}   from    Source space.\n * @param {string}   to      Destination space.\n * @param {object}   m       Matrices bag — see module header.\n * @param {number[]} vp      Viewport [x, y, w, h]; sign of h encodes screen-y direction.\n * @param {number}   ndcZMin WEBGL (−1) or WEBGPU (0).\n * @returns {number[]} out\n */\nfunction mapDirection(out, dx, dy, dz, from, to, m, vp, ndcZMin) {\n  const vpW=vp[2], vpH=vp[3];  // signed — carry y-convention through all helpers\n\n  if (from===EYE   && to===WORLD)  return _applyDir(out,m.mat4Eye, dx,dy,dz);\n  if (from===WORLD && to===EYE)    return _applyDir(out,m.mat4View,dx,dy,dz);\n\n  if (from===WORLD  && to===SCREEN) return _worldToScreenDir(out,dx,dy,dz,m.mat4Proj,m.mat4View,vpW,vpH,ndcZMin);\n  if (from===SCREEN && to===WORLD)  return _screenToWorldDir(out,dx,dy,dz,m.mat4Proj,m.mat4Eye, vpW,vpH,ndcZMin);\n\n  if (from===SCREEN && to===NDC)    return _screenToNDCDir(out,dx,dy,dz,vpW,vpH,ndcZMin);\n  if (from===NDC    && to===SCREEN) return _ndcToScreenDir(out,dx,dy,dz,vpW,vpH,ndcZMin);\n\n  if (from===WORLD && to===NDC) {\n    _worldToScreenDir(out,dx,dy,dz,m.mat4Proj,m.mat4View,vpW,vpH,ndcZMin);\n    return _screenToNDCDir(out,out[0],out[1],out[2],vpW,vpH,ndcZMin);\n  }\n  if (from===NDC && to===WORLD) {\n    _ndcToScreenDir(out,dx,dy,dz,vpW,vpH,ndcZMin);\n    return _screenToWorldDir(out,out[0],out[1],out[2],m.mat4Proj,m.mat4Eye,vpW,vpH,ndcZMin);\n  }\n\n  if (from===EYE && to===SCREEN) {\n    _applyDir(out,m.mat4Eye,dx,dy,dz);\n    return _worldToScreenDir(out,out[0],out[1],out[2],m.mat4Proj,m.mat4View,vpW,vpH,ndcZMin);\n  }\n  if (from===SCREEN && to===EYE) {\n    _screenToWorldDir(out,dx,dy,dz,m.mat4Proj,m.mat4Eye,vpW,vpH,ndcZMin);\n    return _applyDir(out,m.mat4View,out[0],out[1],out[2]);\n  }\n\n  if (from===EYE && to===NDC) {\n    _applyDir(out,m.mat4Eye,dx,dy,dz);\n    _worldToScreenDir(out,out[0],out[1],out[2],m.mat4Proj,m.mat4View,vpW,vpH,ndcZMin);\n    return _screenToNDCDir(out,out[0],out[1],out[2],vpW,vpH,ndcZMin);\n  }\n  if (from===NDC && to===EYE) {\n    _ndcToScreenDir(out,dx,dy,dz,vpW,vpH,ndcZMin);\n    _screenToWorldDir(out,out[0],out[1],out[2],m.mat4Proj,m.mat4Eye,vpW,vpH,ndcZMin);\n    return _applyDir(out,m.mat4View,out[0],out[1],out[2]);\n  }\n\n  if (from===MATRIX && to===WORLD)  return _applyDir(out,m.fromFrame, dx,dy,dz);\n  if (from===WORLD  && to===MATRIX) return _applyDir(out,m.toFrameInv,dx,dy,dz);\n\n  if (from===MATRIX && to===EYE) {\n    _applyDir(out,m.fromFrame,dx,dy,dz);\n    return _applyDir(out,m.mat4View,out[0],out[1],out[2]);\n  }\n  if (from===EYE && to===MATRIX) {\n    _applyDir(out,m.mat4Eye,dx,dy,dz);\n    return _applyDir(out,m.toFrameInv,out[0],out[1],out[2]);\n  }\n\n  if (from===MATRIX && to===SCREEN) {\n    _applyDir(out,m.fromFrame,dx,dy,dz);\n    return _worldToScreenDir(out,out[0],out[1],out[2],m.mat4Proj,m.mat4View,vpW,vpH,ndcZMin);\n  }\n  if (from===SCREEN && to===MATRIX) {\n    _screenToWorldDir(out,dx,dy,dz,m.mat4Proj,m.mat4Eye,vpW,vpH,ndcZMin);\n    return _applyDir(out,m.toFrameInv,out[0],out[1],out[2]);\n  }\n\n  if (from===MATRIX && to===NDC) {\n    _applyDir(out,m.fromFrame,dx,dy,dz);\n    _worldToScreenDir(out,out[0],out[1],out[2],m.mat4Proj,m.mat4View,vpW,vpH,ndcZMin);\n    return _screenToNDCDir(out,out[0],out[1],out[2],vpW,vpH,ndcZMin);\n  }\n  if (from===NDC && to===MATRIX) {\n    _ndcToScreenDir(out,dx,dy,dz,vpW,vpH,ndcZMin);\n    _screenToWorldDir(out,out[0],out[1],out[2],m.mat4Proj,m.mat4Eye,vpW,vpH,ndcZMin);\n    return _applyDir(out,m.toFrameInv,out[0],out[1],out[2]);\n  }\n\n  if (from===MATRIX && to===MATRIX) {\n    _applyDir(out,m.fromFrame,dx,dy,dz);\n    return _applyDir(out,m.toFrameInv,out[0],out[1],out[2]);\n  }\n\n  out[0]=dx; out[1]=dy; out[2]=dz;\n  return out;\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// pixelRatio\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * World-units-per-pixel at a given eye-space Z depth.\n * @param {ArrayLike<number>} proj    Projection mat4.\n * @param {number}            vpH     Viewport height in pixels (positive).\n * @param {number}            eyeZ    Eye-space Z — negative means in front of camera.\n * @param {number}            ndcZMin WEBGL (−1) or WEBGPU (0).\n */\nfunction pixelRatio(proj, vpH, eyeZ, ndcZMin) {\n  return projIsOrtho(proj)\n    ? Math.abs(projTop(proj,ndcZMin)-projBottom(proj,ndcZMin)) / vpH\n    : 2*Math.abs(eyeZ)*Math.tan(projFov(proj)/2) / vpH;\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Pick-matrix\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Mutate a projection matrix in-place so that the pixel at (px, py) maps to\n * the full NDC square — making a 1×1 FBO render contain exactly that pixel.\n *\n * Premultiplies by M_pick (column-major, rows 2 and 3 unchanged):\n *\n *   ┌  sx   0   0   tx ┐     sx = |vp[2]|,   sy = |vp[3]|\n *   │   0  sy   0   ty │     cx = ((px−vp[0])/vp[2])·2 − 1   (NDC x of pixel centre)\n *   │   0   0   1    0 │     cy = ((py−vp[1])/vp[3])·2 − 1   (NDC y, sign-aware)\n *   └   0   0   0    1 ┘     tx = −cx·sx,  ty = −cy·sy\n *\n * Result: P_pick = M_pick · P_original.\n * The viewport sign convention (vp[3] < 0 for screen y-down) is preserved\n * automatically through cx/cy — no separate flip needed.\n *\n * @param {Float32Array} proj  Projection mat4 — mutated in place.\n * @param {number} px  Query pixel X in screen coordinates.\n * @param {number} py  Query pixel Y in screen coordinates.\n * @param {number[]} vp  Viewport [x, y, w, h]; same signed convention as mapLocation.\n */\nfunction mat4Pick(proj, px, py, vp) {\n  const cx=((px-vp[0])/vp[2])*2-1;\n  const cy=((py-vp[1])/vp[3])*2-1;\n  const sx=Math.abs(vp[2]), sy=Math.abs(vp[3]);\n  const tx=-cx*sx, ty=-cy*sy;\n  for (let j=0; j<4; j++) {\n    const a=proj[j*4], b=proj[j*4+1], d=proj[j*4+3];\n    proj[j*4]   = sx*a + tx*d;\n    proj[j*4+1] = sy*b + ty*d;\n  }\n}\n\n// =========================================================================\n// Decomposition\n// =========================================================================\n\n/**\n * Extract translation from a column-major mat4 (column 3).\n * @param {Float32Array|number[]} out3  3-element destination.\n * @param {Float32Array|number[]} m     16-element source.\n */\nfunction mat4ToTranslation(out3, m) {\n  out3[0]=m[12]; out3[1]=m[13]; out3[2]=m[14];\n  return out3;\n}\n\n/**\n * Extract scale from a column-major mat4 (column lengths of the rotation block).\n * Assumes no shear.\n * @param {Float32Array|number[]} out3  3-element destination.\n * @param {Float32Array|number[]} m     16-element source.\n */\nfunction mat4ToScale(out3, m) {\n  out3[0]=Math.sqrt(m[0]*m[0]+m[1]*m[1]+m[2]*m[2]);\n  out3[1]=Math.sqrt(m[4]*m[4]+m[5]*m[5]+m[6]*m[6]);\n  out3[2]=Math.sqrt(m[8]*m[8]+m[9]*m[9]+m[10]*m[10]);\n  return out3;\n}\n\n/**\n * Extract rotation as a unit quaternion from a column-major mat4.\n * Scale is factored out from each column. Assumes no shear.\n * @param {number[]} out4  4-element [x,y,z,w] destination.\n * @param {Float32Array|number[]} m  16-element source.\n */\nfunction mat4ToRotation(out4, m) {\n  const sx=Math.sqrt(m[0]*m[0]+m[1]*m[1]+m[2]*m[2])||1;\n  const sy=Math.sqrt(m[4]*m[4]+m[5]*m[5]+m[6]*m[6])||1;\n  const sz=Math.sqrt(m[8]*m[8]+m[9]*m[9]+m[10]*m[10])||1;\n  return qFromRotMat3x3(out4,\n    m[0]/sx, m[4]/sy, m[8]/sz,\n    m[1]/sx, m[5]/sy, m[9]/sz,\n    m[2]/sx, m[6]/sy, m[10]/sz);\n}\n\n/**\n * @file Spline math and keyframe animation state machines.\n * @module tree/track\n * @license AGPL-3.0-only\n *\n * Quaternion algebra is provided by quat.js; projection matrix construction\n * by form.js. Spline helpers (hermiteVec3, lerpVec3) and TRS↔mat4 conversions\n * (transformToMat4, mat4ToTransform) live here because they are tightly\n * coupled to the PoseTrack keyframe shape.\n *\n * Zero dependencies on p5, DOM, WebGL, or WebGPU.\n *\n * ── Exports ──────────────────────────────────────────────────────────────\n *  Quaternion helpers   (re-exported from quat.js)\n *    qSet qCopy qDot qNormalize qNegate qMul qSlerp qNlerp\n *    qFromAxisAngle qFromLookDir qFromRotMat3x3 qFromMat4 qToMat4\n *    qToAxisAngle\n *  Spline / vector helpers\n *    hermiteVec3  lerpVec3\n *  Transform / mat4 helpers\n *    transformToMat4  mat4ToTransform\n *  Tracks\n *    PoseTrack    — { pos, rot, scl } TRS keyframes\n *    CameraTrack  — { eye, center, up, fov?, halfHeight?, near, far }\n *                   lookat keyframes\n *\n * ── Public path access (all zero-alloc, no cursor side effects) ──────────\n *  PoseTrack\n *    samplePos        (out)  |  (out, seg, t)              vec3\n *    mat4Model        (out)  |  (out, seg, t)              mat4  — TRS model\n *    tangents         (outIn, outOut, index)               vec3 × 2 at keyframe\n *    eval             (out?)                               TRS object at cursor\n *\n *  CameraTrack\n *    sampleEye        (out)  |  (out, seg, t)              vec3\n *    sampleCenter     (out)  |  (out, seg, t)              vec3\n *    mat4Eye          (out)  |  (out, seg, t)              mat4  — lookat frame\n *    eyeTangents      (outIn, outOut, index)               vec3 × 2 at keyframe\n *    centerTangents   (outIn, outOut, index)               vec3 × 2 at keyframe\n *    eval             (out?)                               { eye, center, up,\n *                                                            fov, halfHeight,\n *                                                            near, far }\n *\n *  Two arities for the continuous family:\n *    (out)          cursor form — reads track.seg / track.f. Useful when the\n *                   track's own transport is driving the animation.\n *    (out, seg, t)  explicit form — continuous (seg, t) coordinate, no cursor\n *                   side effects. seg ∈ [0, segments−1] integer, t ∈ [0, 1]\n *                   local to that segment. As a convenience, seg === segments\n *                   is accepted and rewritten to (segments−1, 1) — so the\n *                   idiom sampleX(out, i, 0) uniformly addresses keyframe i\n *                   for every i ∈ [0, keyframes.length−1].\n *\n *  All honour the track's interpolation mode (hermite / linear / step) and\n *  the same stored-tangent → centripetal-CR fallback chain that eval() uses.\n *\n *  `tangents` / `eyeTangents` / `centerTangents` are keyframe-indexed — a\n *  keyframe's incoming tangent belongs to the previous segment, outgoing to\n *  the next. At boundary keyframes the missing side mirrors the present one\n *  so drawing arrows at endpoints always yields a visible vector.\n *\n *  Projection matrices are deliberately not exposed as a track method. Each\n *  CameraTrack keyframe stores `fov` (perspective) or `halfHeight` (ortho)\n *  directly on track.keyframes[i] — callers wanting a projection build one\n *  with the free mat4Persp / mat4Ortho constructors. Animated fov in\n *  sketches flows through the bridge's camera-binding via eval().fov and\n *  eval().halfHeight (the bridge calls cam.perspective() / cam.ortho() each\n *  frame).\n *\n * ── Class hierarchy ──────────────────────────────────────────────────────\n *  Track (unexported, never instantiated directly)\n *    └── PoseTrack   (exported)\n *    └── CameraTrack (exported)\n *\n * ── Hook architecture ────────────────────────────────────────────────────\n *  Lib-space hooks (underscore prefix — host layer / UI layer):\n *    _onActivate / _onDeactivate  — fire on playing false→true / true→false.\n *    _onPlay / _onEnd / _onStop   — mirror the user-space hooks.\n *\n *  User-space hooks:\n *    onPlay : fires in play()  on false→true transition.\n *    onEnd  : fires in tick()  at natural boundary (once mode only).\n *    onStop : fires in stop() / reset().\n *\n *  Firing order:\n *    play()  → onPlay → _onPlay → _onActivate\n *    tick()  → onEnd  → _onEnd  → _onDeactivate\n *    stop()  → onStop → _onStop → _onDeactivate\n *    reset() → onStop → _onStop → _onDeactivate\n *\n * ── Loop modes ───────────────────────────────────────────────────────────\n *  loop:false, bounce:false  — play once, stop at end (fires onEnd)\n *  loop:true,  bounce:false  — repeat, wrap back to start\n *  loop:true,  bounce:true   — bounce forever at boundaries\n *  loop:false, bounce:true   — bounce once: flip at far boundary, stop at origin\n *\n * ── Playback semantics (rate + _dir) ─────────────────────────────────────\n *  rate > 0   forward       rate < 0   backward       rate === 0 frozen\n *\n *  play() is the sole setter of playing = true.\n *  stop() is the sole setter of playing = false.\n *  Assigning rate never starts or stops playback.\n *\n *  _dir (internal, ±1) tracks the current bounce travel direction.\n *  tick() advances by rate * _dir and flips _dir at boundaries.\n *  _dir is reset to 1 only in reset().\n *\n * ── One-keyframe behaviour ───────────────────────────────────────────────\n *  play() with exactly one keyframe snaps eval() to that keyframe without\n *  setting playing = true and without firing hooks.\n */\n\n\n// =========================================================================\n// S2  Spline / vector helpers\n// =========================================================================\n\nfunction _dist3(a, b) {\n  const dx=a[0]-b[0], dy=a[1]-b[1], dz=a[2]-b[2];\n  return Math.sqrt(dx*dx+dy*dy+dz*dz);\n}\n\n/**\n * Cubic Hermite interpolation between p0 and p1 with explicit tangents.\n * @param {number[]} out  3-element result.\n * @param {number[]} p0   Segment start.\n * @param {number[]} m0   Outgoing tangent at p0.\n * @param {number[]} p1   Segment end.\n * @param {number[]} m1   Incoming tangent at p1.\n * @param {number}   t    Blend [0, 1].\n * @returns {number[]} out\n */\nconst hermiteVec3 = (out, p0, m0, p1, m1, t) => {\n  const t2=t*t, t3=t2*t;\n  const h00=2*t3-3*t2+1, h10=t3-2*t2+t, h01=-2*t3+3*t2, h11=t3-t2;\n  out[0]=h00*p0[0]+h10*m0[0]+h01*p1[0]+h11*m1[0];\n  out[1]=h00*p0[1]+h10*m0[1]+h01*p1[1]+h11*m1[1];\n  out[2]=h00*p0[2]+h10*m0[2]+h01*p1[2]+h11*m1[2];\n  return out;\n};\n\n// Centripetal CR outgoing tangent at p1 for segment p1→p2.\n// Signature: (out, p0, p1, p2). Returns tangent AT p1 (the middle point).\nconst _crTanOut = (out, p0, p1, p2) => {\n  const dt0=Math.pow(_dist3(p0,p1),0.5)||1, dt1=Math.pow(_dist3(p1,p2),0.5)||1;\n  for (let i=0;i<3;i++) out[i]=((p1[i]-p0[i])/dt0-(p2[i]-p0[i])/(dt0+dt1)+(p2[i]-p1[i])/dt1)*dt1;\n  return out;\n};\n\n// Centripetal CR incoming tangent at p2 for segment p1→p2.\n// Signature: (out, p1, p2, p3). Returns tangent AT p2 (the middle point).\nconst _crTanIn = (out, p1, p2, p3) => {\n  const dt1=Math.pow(_dist3(p1,p2),0.5)||1, dt2=Math.pow(_dist3(p2,p3),0.5)||1;\n  for (let i=0;i<3;i++) out[i]=((p2[i]-p1[i])/dt1-(p3[i]-p1[i])/(dt1+dt2)+(p3[i]-p2[i])/dt2)*dt1;\n  return out;\n};\n\n// Module-level scratch — shared across track instances (non-reentrant hot path).\nconst _m0=[0,0,0], _m1=[0,0,0];\nconst _trsScratch = { pos:[0,0,0], rot:[0,0,0,1], scl:[1,1,1] };\nconst _eyeScratch = { eye:[0,0,0], center:[0,0,0], up:[0,1,0] };\n\n/**\n * Linear interpolation between two vec3s.\n */\nconst lerpVec3 = (out, a, b, t) => {\n  out[0]=a[0]+t*(b[0]-a[0]);\n  out[1]=a[1]+t*(b[1]-a[1]);\n  out[2]=a[2]+t*(b[2]-a[2]);\n  return out;\n};\n\n// =========================================================================\n// S2b  Path samplers — shared core\n// =========================================================================\n\n/** @private — sample interpolated vec3 path at (seg, t) into out. */\nfunction _samplePathCore(out, kfs, interp, field, tanInName, tanOutName, seg, t) {\n  const n = kfs.length;\n  if (n === 0) { out[0]=0; out[1]=0; out[2]=0; return out; }\n  if (n === 1) {\n    const p = kfs[0][field];\n    out[0]=p[0]; out[1]=p[1]; out[2]=p[2];\n    return out;\n  }\n  const nSeg = n - 1;\n  seg = seg | 0;\n  if (seg >= nSeg) { seg = nSeg - 1; t = 1; }\n  else if (seg < 0) { seg = 0; t = 0; }\n  t   = _clamp01(t);\n  const k0 = kfs[seg];\n  const k1 = kfs[seg + 1];\n\n  if (interp === 'step') {\n    const p = k0[field];\n    out[0]=p[0]; out[1]=p[1]; out[2]=p[2];\n    return out;\n  }\n  if (interp === 'linear') {\n    return lerpVec3(out, k0[field], k1[field], t);\n  }\n\n  const p0 = seg > 0      ? kfs[seg - 1][field] : k0[field];\n  const p3 = seg + 2 < n  ? kfs[seg + 2][field] : k1[field];\n  const m0 = k0[tanOutName] != null ? k0[tanOutName]\n           : k0[tanInName]  != null ? k0[tanInName]\n           : _crTanOut(_m0, p0, k0[field], k1[field]);\n  const m1 = k1[tanInName]  != null ? k1[tanInName]\n           : k1[tanOutName] != null ? k1[tanOutName]\n           : _crTanIn(_m1, k0[field], k1[field], p3);\n  return hermiteVec3(out, k0[field], m0, k1[field], m1, t);\n}\n\n/** @private — write effective in/out tangents at keyframe i. */\nfunction _sampleTangentsCore(outIn, outOut, kfs, field, tanInName, tanOutName, i) {\n  const n = kfs.length;\n  if (n === 0) {\n    outIn[0]=outIn[1]=outIn[2]=0; outOut[0]=outOut[1]=outOut[2]=0;\n    return;\n  }\n  i = _clampS(i | 0, 0, n - 1);\n  const ki = kfs[i];\n  const hasTI = ki[tanInName]  != null;\n  const hasTO = ki[tanOutName] != null;\n\n  if (hasTO) {\n    outOut[0]=ki[tanOutName][0]; outOut[1]=ki[tanOutName][1]; outOut[2]=ki[tanOutName][2];\n  } else if (hasTI) {\n    outOut[0]=ki[tanInName][0];  outOut[1]=ki[tanInName][1];  outOut[2]=ki[tanInName][2];\n  } else if (i < n - 1) {\n    const k1 = kfs[i + 1];\n    const p0 = i > 0 ? kfs[i - 1][field] : ki[field];\n    _crTanOut(outOut, p0, ki[field], k1[field]);\n  } else {\n    outOut[0]=0; outOut[1]=0; outOut[2]=0;\n  }\n\n  if (hasTI) {\n    outIn[0]=ki[tanInName][0];  outIn[1]=ki[tanInName][1];  outIn[2]=ki[tanInName][2];\n  } else if (hasTO) {\n    outIn[0]=ki[tanOutName][0]; outIn[1]=ki[tanOutName][1]; outIn[2]=ki[tanOutName][2];\n  } else if (i > 0) {\n    const k0 = kfs[i - 1];\n    const p3 = i + 1 < n ? kfs[i + 1][field] : ki[field];\n    _crTanIn(outIn, k0[field], ki[field], p3);\n  } else {\n    outIn[0]=outOut[0]; outIn[1]=outOut[1]; outIn[2]=outOut[2];\n  }\n\n  if (i === n - 1 && !hasTO && !hasTI) {\n    outOut[0]=outIn[0]; outOut[1]=outIn[1]; outOut[2]=outIn[2];\n  }\n}\n\n// =========================================================================\n// S3  Transform <-> Mat4\n// =========================================================================\n\n/**\n * Write a TRS transform into a column-major mat4.\n */\nconst transformToMat4 = (out, xform) => {\n  qToMat4(out, xform.rot);\n  const sx=xform.scl[0], sy=xform.scl[1], sz=xform.scl[2];\n  out[0]*=sx; out[1]*=sx; out[2]*=sx;\n  out[4]*=sy; out[5]*=sy; out[6]*=sy;\n  out[8]*=sz; out[9]*=sz; out[10]*=sz;\n  out[12]=xform.pos[0]; out[13]=xform.pos[1]; out[14]=xform.pos[2];\n  return out;\n};\n\n/**\n * Decompose a column-major mat4 into a TRS transform.\n */\nconst mat4ToTransform = (out, m) => {\n  out.pos[0]=m[12]; out.pos[1]=m[13]; out.pos[2]=m[14];\n  const sx=Math.sqrt(m[0]*m[0]+m[1]*m[1]+m[2]*m[2]);\n  const sy=Math.sqrt(m[4]*m[4]+m[5]*m[5]+m[6]*m[6]);\n  const sz=Math.sqrt(m[8]*m[8]+m[9]*m[9]+m[10]*m[10]);\n  out.scl[0]=sx; out.scl[1]=sy; out.scl[2]=sz;\n  qFromRotMat3x3(out.rot,\n    m[0]/sx,m[4]/sy,m[8]/sz,\n    m[1]/sx,m[5]/sy,m[9]/sz,\n    m[2]/sx,m[6]/sy,m[10]/sz);\n  return out;\n};\n\n// =========================================================================\n// S4a  Spec parser — PoseTrack\n// =========================================================================\n\nconst _isNum   = (x) => typeof x === 'number' && Number.isFinite(x);\nconst _clamp01 = (x) => x < 0 ? 0 : (x > 1 ? 1 : x);\nconst _clampS  = (x, lo, hi) => x < lo ? lo : (x > hi ? hi : x);\n\nfunction _parseVec3(v) {\n  if (!v) return null;\n  if (ArrayBuffer.isView(v) && v.length >= 3) return [v[0], v[1], v[2]];\n  if (Array.isArray(v) && v.length >= 3 && v.every(n => typeof n === 'number')) return [v[0], v[1], v[2]];\n  if (typeof v === 'object' && 'x' in v) return [v.x || 0, v.y || 0, v.z || 0];\n  return null;\n}\n\nconst _EULER_AXES   = { X:[1,0,0], Y:[0,1,0], Z:[0,0,1] };\nconst _EULER_ORDERS = new Set(['XYZ','XZY','YXZ','YZX','ZXY','ZYX']);\n\n/**\n * Parse any rotation representation into a unit quaternion [x,y,z,w].\n *\n * Accepted forms:\n *   [x,y,z,w]                        — raw quaternion array\n *   { axis:[x,y,z], angle }          — axis-angle (angle in radians)\n *   { dir:[x,y,z], up?:[x,y,z] }     — forward direction (−Z) with optional up\n *   { mat4Eye: mat4 }                — rotation block of an eye matrix\n *   { mat3: mat3 }                   — column-major 3×3 rotation matrix\n *   { euler:[rx,ry,rz], order? }     — intrinsic Euler (default order: YXZ)\n *   { from:[x,y,z], to:[x,y,z] }     — shortest-arc rotation between two vectors\n *\n * @param {*} v\n * @returns {number[]|null}  [x,y,z,w] or null if unparseable.\n */\nfunction _parseQuat(v) {\n  if (!v) return null;\n\n  // [x,y,z,w]\n  if (Array.isArray(v) && v.length === 4) return [v[0],v[1],v[2],v[3]];\n  if (ArrayBuffer.isView(v) && v.length >= 4) return [v[0],v[1],v[2],v[3]];\n\n  if (typeof v !== 'object') return null;\n\n  // { axis, angle }\n  if (v.axis != null && v.angle != null) {\n    const ax = Array.isArray(v.axis) ? v.axis : [v.axis.x||0, v.axis.y||0, v.axis.z||0];\n    return qFromAxisAngle([0,0,0,1], ax[0],ax[1],ax[2], v.angle);\n  }\n\n  // { dir, up? }\n  if (v.dir != null) {\n    const d = Array.isArray(v.dir) ? v.dir : [v.dir.x||0, v.dir.y||0, v.dir.z||0];\n    const u = v.up ? (Array.isArray(v.up) ? v.up : [v.up.x||0, v.up.y||0, v.up.z||0]) : null;\n    return qFromLookDir([0,0,0,1], d, u);\n  }\n\n  // { mat4Eye }\n  if (v.mat4Eye != null) {\n    const m = (ArrayBuffer.isView(v.mat4Eye) || Array.isArray(v.mat4Eye))\n      ? v.mat4Eye : (v.mat4Eye.mat4 ?? null);\n    if (!m || m.length < 16) return null;\n    return qFromRotMat3x3([0,0,0,1], m[0],m[4],m[8], m[1],m[5],m[9], m[2],m[6],m[10]);\n  }\n\n  // { mat3 }\n  if (v.mat3 != null) {\n    const m = (ArrayBuffer.isView(v.mat3) || Array.isArray(v.mat3)) ? v.mat3 : null;\n    if (!m || m.length < 9) return null;\n    return qFromRotMat3x3([0,0,0,1], m[0],m[3],m[6], m[1],m[4],m[7], m[2],m[5],m[8]);\n  }\n\n  // { euler, order? }\n  if (v.euler != null) {\n    const e = v.euler;\n    if (!Array.isArray(e) || e.length < 3) return null;\n    const order = (v.order && _EULER_ORDERS.has(v.order)) ? v.order : 'YXZ';\n    const q = [0,0,0,1], s = [0,0,0,1];\n    for (let i = 0; i < 3; i++) {\n      const ax = _EULER_AXES[order[i]];\n      qMul(q, q, qFromAxisAngle(s, ax[0],ax[1],ax[2], e[i]));\n    }\n    return q;\n  }\n\n  // { from, to }\n  if (v.from != null && v.to != null) {\n    const f = Array.isArray(v.from) ? v.from : [v.from.x||0, v.from.y||0, v.from.z||0];\n    const t = Array.isArray(v.to)   ? v.to   : [v.to.x||0,   v.to.y||0,   v.to.z||0];\n    const fl = Math.sqrt(f[0]*f[0]+f[1]*f[1]+f[2]*f[2]) || 1;\n    const tl = Math.sqrt(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]) || 1;\n    const fx=f[0]/fl, fy=f[1]/fl, fz=f[2]/fl;\n    const tx=t[0]/tl, ty=t[1]/tl, tz=t[2]/tl;\n    const dot = fx*tx + fy*ty + fz*tz;\n    if (dot >= 1 - 1e-8) return [0,0,0,1];\n    if (dot <= -1 + 1e-8) {\n      let px=0, py=fz, pz=-fy;\n      let pl = Math.sqrt(px*px+py*py+pz*pz);\n      if (pl < 1e-8) { px=fy; py=-fx; pz=0; pl = Math.sqrt(px*px+py*py+pz*pz); }\n      if (pl < 1e-8) return [0,0,0,1];\n      return qFromAxisAngle([0,0,0,1], px/pl,py/pl,pz/pl, Math.PI);\n    }\n    let ax=fy*tz-fz*ty, ay=fz*tx-fx*tz, az=fx*ty-fy*tx;\n    const al = Math.sqrt(ax*ax+ay*ay+az*az) || 1;\n    return qFromAxisAngle([0,0,0,1], ax/al,ay/al,az/al,\n      Math.acos(Math.max(-1, Math.min(1, dot))));\n  }\n\n  return null;\n}\n\n/**\n * Parse a PoseTrack keyframe spec into internal form.\n *\n * Accepted forms:\n *   { mat4Model }\n *     Decompose a column-major mat4 into TRS via mat4ToTransform.\n *     Float32Array(16), plain Array, or { mat4 } wrapper.\n *\n *   { pos?, rot?, scl?, tanIn?, tanOut? }\n *     Explicit TRS. pos and scl are vec3; rot accepts any form from _parseQuat.\n *     All fields are optional — missing pos/scl default to [0,0,0] / [1,1,1],\n *     missing rot defaults to identity.\n *     tanIn/tanOut are optional vec3 tangents for Hermite interpolation.\n *\n * @param {Object} spec\n * @returns {{ pos:number[], rot:number[], scl:number[],\n *             tanIn:number[]|null, tanOut:number[]|null } | null}\n */\nfunction _parseSpec(spec) {\n  if (!spec || typeof spec !== 'object') return null;\n\n  // { mat4Model } — full TRS decomposition from model matrix\n  if (spec.mat4Model != null) {\n    const m = (ArrayBuffer.isView(spec.mat4Model) || Array.isArray(spec.mat4Model))\n      ? spec.mat4Model : (spec.mat4Model.mat4 ?? null);\n    if (!m || m.length < 16) return null;\n    const kf = mat4ToTransform({ pos:[0,0,0], rot:[0,0,0,1], scl:[1,1,1] }, m);\n    kf.tanIn = null; kf.tanOut = null;\n    return kf;\n  }\n\n  // { pos?, rot?, scl?, tanIn?, tanOut? } — explicit TRS\n  const pos    = _parseVec3(spec.pos)    || [0,0,0];\n  const rot    = _parseQuat(spec.rot)    || [0,0,0,1];\n  const scl    = _parseVec3(spec.scl)    || [1,1,1];\n  const tanIn  = _parseVec3(spec.tanIn)  || null;\n  const tanOut = _parseVec3(spec.tanOut) || null;\n  return { pos, rot, scl, tanIn, tanOut };\n}\n\nfunction _sameTransform(a, b) {\n  for (let i=0;i<3;i++) if (a.pos[i]!==b.pos[i]||a.scl[i]!==b.scl[i]) return false;\n  for (let i=0;i<4;i++) if (a.rot[i]!==b.rot[i]) return false;\n  return true;\n}\n\n// =========================================================================\n// S4b  Spec parser — CameraTrack\n// =========================================================================\n\n// Lens defaults used when a spec omits near/far. Match the three.js /\n// Bevy conventions and are safe for typical p5 v2 scene scales.\nconst _DEFAULT_NEAR = 0.1;\nconst _DEFAULT_FAR  = 1000;\n\n/**\n * Parse a CameraTrack keyframe spec into internal form.\n *\n * Required: eye (vec3). Everything else is optional.\n *   center       defaults to [0, 0, 0]\n *   up           defaults to [0, 1, 0] and is normalised\n *   fov          vertical fov (radians), perspective only — null if absent\n *   halfHeight   world-unit half-height of ortho frustum — null if absent\n *   near         near clip distance (positive) — defaults to 0.1\n *   far          far  clip distance (positive) — defaults to 1000\n *   eyeTanIn/Out       optional Hermite tangents for the eye path\n *   centerTanIn/Out    optional Hermite tangents for the center path\n *\n * fov and halfHeight are mutually exclusive (perspective xor ortho) and\n * therefore left nullable; eval() lerps each only when both adjacent\n * keyframes carry a non-null value, passing null through otherwise.\n *\n * near and far are always meaningful regardless of projection type, so\n * they receive real defaults and are linearly interpolated unconditionally.\n *\n * @param {Object} spec\n * @returns {Object|null}  Parsed keyframe or null if eye is missing/malformed.\n */\nfunction _parseCameraSpec(spec) {\n  if (!spec || typeof spec !== 'object') return null;\n  const eye = _parseVec3(spec.eye);\n  if (!eye) return null;\n  const center = _parseVec3(spec.center) || [0,0,0];\n  const upRaw  = spec.up ? _parseVec3(spec.up) : null;\n  const up     = upRaw || [0,1,0];\n  const ul     = Math.sqrt(up[0]*up[0]+up[1]*up[1]+up[2]*up[2]) || 1;\n  return {\n    eye, center,\n    up: [up[0]/ul, up[1]/ul, up[2]/ul],\n    fov:          typeof spec.fov        === 'number' ? spec.fov        : null,\n    halfHeight:   typeof spec.halfHeight === 'number' ? spec.halfHeight : null,\n    near:         typeof spec.near       === 'number' ? spec.near       : _DEFAULT_NEAR,\n    far:          typeof spec.far        === 'number' ? spec.far        : _DEFAULT_FAR,\n    eyeTanIn:     _parseVec3(spec.eyeTanIn)    || null,\n    eyeTanOut:    _parseVec3(spec.eyeTanOut)   || null,\n    centerTanIn:  _parseVec3(spec.centerTanIn) || null,\n    centerTanOut: _parseVec3(spec.centerTanOut)|| null,\n  };\n}\n\nfunction _sameCameraKeyframe(a, b) {\n  for (let i=0;i<3;i++) {\n    if (a.eye[i]!==b.eye[i]) return false;\n    if (a.center[i]!==b.center[i]) return false;\n    if (a.up[i]!==b.up[i]) return false;\n  }\n  if (a.fov !== b.fov) return false;\n  if (a.halfHeight !== b.halfHeight) return false;\n  if (a.near !== b.near) return false;\n  if (a.far  !== b.far)  return false;\n  return true;\n}\n\n// =========================================================================\n// S5  Track — unexported base class (transport machinery only)\n// =========================================================================\n\nclass Track {\n  constructor() {\n    /** @type {Array} Keyframe array — shape depends on subclass. */\n    this.keyframes = [];\n    /** Whether playback is currently active. @type {boolean} */\n    this.playing   = false;\n    /** Loop at boundaries. @type {boolean} */\n    this.loop      = false;\n    /** Ping-pong bounce at boundaries (independent of loop). @type {boolean} */\n    this.bounce    = false;\n    /** Frames per segment (≥1). @type {number} */\n    this.duration  = 30;\n    /** Current segment index. @type {number} */\n    this.seg       = 0;\n    /** Frame offset within current segment (can be fractional). @type {number} */\n    this.f         = 0;\n\n    // Playback rate (signed: negative = reverse; 0 = frozen).\n    this._rate = 1;\n    // Current bounce travel direction (±1). Reset to 1 only on reset().\n    this._dir  = 1;\n    // Whether a bounce-once has already flipped direction.\n    this._bounced = false;\n\n    /** User hook: fires on play() false→true transition. @type {Function|null} */\n    this.onPlay = null;\n    /** User hook: fires on natural boundary in once mode. @type {Function|null} */\n    this.onEnd  = null;\n    /** User hook: fires on stop() / reset() / end-of-bounce-once. @type {Function|null} */\n    this.onStop = null;\n\n    // Lib-space hooks (underscore prefix — host layer / UI layer only).\n    this._onActivate = null; this._onDeactivate = null;\n    this._onPlay     = null; this._onEnd         = null; this._onStop = null;\n  }\n\n  /** Playback rate. Signed: negative reverses, 0 freezes. Assigning never starts or stops playback. @type {number} */\n  get rate()  { return this._rate; }\n  set rate(v) { this._rate = (_isNum(v)) ? v : 1; }\n\n  /** Number of interpolatable segments (keyframes.length − 1, min 0). @type {number} */\n  get segments() { return Math.max(0, this.keyframes.length - 1); }\n\n  /**\n   * @private — resolve cursor (seg, f) into continuous (seg, t).\n   * Shared backing of every cursor-form sampler / matrix method.\n   */\n  _cursorSegT() {\n    const nSeg = this.segments;\n    const dur  = Math.max(1, this.duration | 0);\n    const seg  = nSeg > 0 ? _clampS(this.seg, 0, nSeg - 1) : 0;\n    const t    = _clamp01(this.f / dur);\n    return [seg, t];\n  }\n\n  /**\n   * Start or update playback. Sole setter of `playing = true`.\n   *\n   * Fires `onPlay → _onPlay → _onActivate` only on a false→true transition.\n   * Zero keyframes: no-op. Exactly one keyframe: snaps eval() to it but does\n   * not set `playing` and fires no hooks.\n   *\n   * @param {number|{duration?:number,loop?:boolean,bounce?:boolean,\n   *                 rate?:number,onPlay?:Function,onEnd?:Function,\n   *                 onStop?:Function}} [rateOrOpts]\n   *        A bare number is taken as `rate`; an object configures multiple\n   *        fields in one call.\n   * @returns {Track} this\n   */\n  play(rateOrOpts) {\n    if (this.keyframes.length === 0) return this;\n    if (this.keyframes.length === 1) { this.seg = 0; this.f = 0; return this; }\n\n    if (typeof rateOrOpts === 'number' && Number.isFinite(rateOrOpts)) {\n      this._rate = rateOrOpts;\n    } else if (rateOrOpts && typeof rateOrOpts === 'object') {\n      const o = rateOrOpts;\n      if (_isNum(o.duration))             this.duration = Math.max(1, o.duration | 0);\n      if ('loop'   in o) this.loop   = !!o.loop;\n      if ('bounce' in o) this.bounce = !!o.bounce;\n      if (typeof o.onPlay === 'function') this.onPlay = o.onPlay;\n      if (typeof o.onEnd  === 'function') this.onEnd  = o.onEnd;\n      if (typeof o.onStop === 'function') this.onStop = o.onStop;\n      if (_isNum(o.rate))                 this._rate  = o.rate;\n    }\n\n    const nSeg = this.segments, dur = Math.max(1, this.duration | 0);\n    if (this.seg < 0)     this.seg = 0;\n    if (this.seg >= nSeg) this.seg = nSeg - 1;\n    if (this.f   < 0)     this.f   = 0;\n    if (this.f   > dur)   this.f   = dur;\n\n    const wasPlaying = this.playing;\n    this.playing = true;\n    if (!wasPlaying) {\n      this._bounced = false;\n      if (typeof this.onPlay === 'function') { try { this.onPlay(this); } catch (_) {} }\n      this._onPlay?.();\n      this._onActivate?.();\n    }\n    return this;\n  }\n\n  /**\n   * Stop playback. Sole setter of `playing = false`. Fires\n   * `onStop → _onStop → _onDeactivate` on a true→false transition.\n   *\n   * @param {boolean} [rewind]  If true, seek to the origin end after stopping\n   *                            (0 when playing forward, 1 when playing backward).\n   * @returns {Track} this\n   */\n  stop(rewind) {\n    const wasPlaying = this.playing;\n    this.playing = false;\n    if (wasPlaying) {\n      this._bounced = false;\n      if (typeof this.onStop === 'function') { try { this.onStop(this); } catch (_) {} }\n      this._onStop?.();\n      this._onDeactivate?.();\n      if (rewind && this.keyframes.length > 1) this.seek(this._rate * this._dir < 0 ? 1 : 0);\n    }\n    return this;\n  }\n\n  /**\n   * Clear all keyframes and stop. Fires stop-side hooks if it was playing.\n   * Unlike stop(), this also resets `_dir` to +1.\n   * @returns {Track} this\n   */\n  reset() {\n    const wasPlaying = this.playing;\n    this.playing = false;\n    if (wasPlaying) {\n      if (typeof this.onStop === 'function') { try { this.onStop(this); } catch (_) {} }\n      this._onStop?.();\n      this._onDeactivate?.();\n    }\n    this.keyframes.length = 0;\n    this.seg = 0; this.f = 0; this._dir = 1; this._bounced = false;\n    return this;\n  }\n\n  /**\n   * Remove the keyframe at `index`. Adjusts the cursor if the removal shrinks\n   * the track below the current segment.\n   * @param {number} index\n   * @returns {boolean}  true if removed; false if index was invalid.\n   */\n  remove(index) {\n    if (!_isNum(index)) return false;\n    const i = index | 0;\n    if (i < 0 || i >= this.keyframes.length) return false;\n    this.keyframes.splice(i, 1);\n    const nSeg = this.segments;\n    if (nSeg === 0) { this.seg = 0; this.f = 0; }\n    else if (this.seg >= nSeg) { this.seg = nSeg - 1; }\n    return true;\n  }\n\n  /**\n   * Move the cursor.\n   *   seek(t)            Scrub to normalised position t ∈ [0, 1] across the\n   *                      whole track.\n   *   seek(t, segIndex)  Position within a specific segment — t is local to\n   *                      that segment.\n   * Does not affect `playing`.\n   *\n   * @param {number} t\n   * @param {number} [segIndex]\n   * @returns {Track} this\n   */\n  seek(t, segIndex) {\n    const nSeg = this.segments;\n    if (nSeg === 0) { this.seg = 0; this.f = 0; return this; }\n    const dur = Math.max(1, this.duration | 0);\n    if (_isNum(segIndex)) {\n      this.seg = _clampS(segIndex | 0, 0, nSeg - 1);\n      this.f   = _clamp01(t) * dur;\n    } else {\n      this._setCursorFromScalar(_clamp01(t) * nSeg * dur);\n    }\n    return this;\n  }\n\n  /**\n   * Normalised cursor position across the whole track.\n   * @returns {number}  ∈ [0, 1]; 0 when there are no segments.\n   */\n  time() {\n    const nSeg = this.segments;\n    if (nSeg === 0) return 0;\n    const dur = Math.max(1, this.duration | 0);\n    return _clamp01((this.seg * dur + this.f) / (nSeg * dur));\n  }\n\n  /**\n   * Snapshot of transport state. Allocates a new object per call — intended\n   * for UI / debugging, not hot loops.\n   * @returns {{keyframes:number, segments:number, seg:number, f:number,\n   *            playing:boolean, loop:boolean, bounce:boolean, rate:number,\n   *            duration:number, time:number}}\n   */\n  info() {\n    return {\n      keyframes: this.keyframes.length,\n      segments:  this.segments,\n      seg:       this.seg,\n      f:         this.f,\n      playing:   this.playing,\n      loop:      this.loop,\n      bounce:    this.bounce,\n      rate:      this._rate,\n      duration:  this.duration,\n      time:      this.segments > 0 ? this.time() : 0\n    };\n  }\n\n  /**\n   * Advance the cursor by `rate * _dir` in frames. Handles loop / bounce /\n   * once modes per the table in the module header. Fires `onEnd → _onEnd →\n   * _onDeactivate` at a natural boundary in once mode.\n   *\n   * Intended to be called once per animation frame by the bridge / UI layer.\n   * rate === 0 freezes the cursor but keeps `playing` unchanged.\n   *\n   * @returns {boolean}  Current `playing` state after advancing.\n   */\n  tick() {\n    if (!this.playing) return false;\n    const nSeg = this.segments;\n    if (nSeg === 0) { this.playing = false; this._onDeactivate?.(); return false; }\n    if (this._rate === 0) return true;\n\n    const dur   = Math.max(1, this.duration | 0);\n    const total = nSeg * dur;\n    const s     = _clampS(this.seg * dur + this.f, 0, total);\n    const next  = s + this._rate * this._dir;\n\n    if (this.loop && this.bounce) {\n      let pos = next, flips = 0;\n      while (pos < 0 || pos > total) {\n        if (pos < 0) { pos = -pos; flips++; }\n        else         { pos = 2 * total - pos; flips++; }\n      }\n      if (flips & 1) this._dir = -this._dir;\n      this._setCursorFromScalar(pos);\n      return true;\n    }\n\n    if (!this.loop && this.bounce) {\n      if (next >= total) {\n        this._setCursorFromScalar(Math.min(total, 2 * total - next));\n        this._dir = -this._dir;\n        this._bounced = true;\n        return true;\n      }\n      if (next <= 0) {\n        this._setCursorFromScalar(0);\n        this.playing = false;\n        this._dir = 1; this._bounced = false;\n        if (typeof this.onEnd === 'function') { try { this.onEnd(this); } catch (_) {} }\n        this._onEnd?.();\n        this._onDeactivate?.();\n        return false;\n      }\n      this._setCursorFromScalar(next);\n      return true;\n    }\n\n    if (this.loop) {\n      this._setCursorFromScalar(((next % total) + total) % total);\n      return true;\n    }\n\n    if (next <= 0) {\n      this._setCursorFromScalar(0);\n      this.playing = false;\n      if (typeof this.onEnd === 'function') { try { this.onEnd(this); } catch (_) {} }\n      this._onEnd?.();\n      this._onDeactivate?.();\n      return false;\n    }\n    if (next >= total) {\n      this._setCursorFromScalar(total);\n      this.playing = false;\n      if (typeof this.onEnd === 'function') { try { this.onEnd(this); } catch (_) {} }\n      this._onEnd?.();\n      this._onDeactivate?.();\n      return false;\n    }\n\n    this._setCursorFromScalar(next);\n    return true;\n  }\n\n  /** @private */\n  _setCursorFromScalar(s) {\n    const dur  = Math.max(1, this.duration | 0);\n    const nSeg = this.segments;\n    this.seg = Math.floor(s / dur);\n    this.f   = s - this.seg * dur;\n    if (this.seg >= nSeg) { this.seg = nSeg - 1; this.f = dur; }\n    if (this.seg < 0)     { this.seg = 0;         this.f = 0;   }\n  }\n}\n\n// =========================================================================\n// S6  PoseTrack\n// =========================================================================\n\n/**\n * Renderer-agnostic TRS keyframe track.\n *\n * Keyframe shape: { pos:[x,y,z], rot:[x,y,z,w], scl:[x,y,z],\n *                   tanIn?:[x,y,z], tanOut?:[x,y,z] }\n *\n * tanIn  — incoming position tangent at this keyframe (Hermite mode).\n * tanOut — outgoing position tangent at this keyframe (Hermite mode).\n * When only one is supplied, the other mirrors it at sample time.\n * When neither is supplied, centripetal Catmull-Rom tangents are auto-computed.\n */\nclass PoseTrack extends Track {\n  constructor() {\n    super();\n    /**\n     * Position interpolation mode.\n     * - 'hermite' — cubic Hermite; auto-computes centripetal Catmull-Rom\n     *               tangents when none are stored (default)\n     * - 'linear'  — lerp\n     * - 'step'    — snap to k0; useful for discrete state changes\n     * @type {'hermite'|'linear'|'step'}\n     */\n    this.posInterp = 'hermite';\n    /**\n     * Rotation interpolation mode.\n     * - 'slerp'  — constant angular velocity (default)\n     * - 'nlerp'  — normalised lerp; cheaper, slightly non-constant speed\n     * - 'step'   — snap to k0 quaternion\n     * @type {'slerp'|'nlerp'|'step'}\n     */\n    this.rotInterp = 'slerp';\n  }\n\n  /**\n   * Append one or more keyframes. Adjacent duplicates are skipped by default.\n   * Accepts any spec form understood by _parseSpec, or an array of them.\n   * @param {Object|Object[]} spec\n   * @param {{ deduplicate?: boolean }} [opts]\n   */\n  add(spec, opts) {\n    if (Array.isArray(spec)) { for (const s of spec) this.add(s, opts); return; }\n    const kf = _parseSpec(spec);\n    if (!kf) return;\n    const dedup = !opts || opts.deduplicate !== false;\n    if (dedup && this.keyframes.length > 0) {\n      if (_sameTransform(this.keyframes[this.keyframes.length - 1], kf)) return;\n    }\n    this.keyframes.push(kf);\n  }\n\n  /**\n   * Replace the keyframe at `index`, or append at the end if `index` equals\n   * the current keyframe count.\n   * @param {number} index\n   * @param {Object} spec  Any spec form understood by _parseSpec.\n   * @returns {boolean}  true on success; false for invalid index or spec.\n   */\n  set(index, spec) {\n    if (!_isNum(index)) return false;\n    const i = index | 0, kf = _parseSpec(spec);\n    if (!kf || i < 0 || i > this.keyframes.length) return false;\n    if (i === this.keyframes.length) this.keyframes.push(kf);\n    else this.keyframes[i] = kf;\n    return true;\n  }\n\n  /**\n   * Sample the position path. Zero-alloc, no cursor side effects. Honours\n   * posInterp and the stored-tangent → auto-CR fallback chain.\n   *\n   * Two signatures:\n   *   samplePos(out)              cursor form — reads current seg/f\n   *   samplePos(out, seg, t)      explicit (seg, t), continuous on the path\n   *\n   * @param {number[]} out  3-element result buffer.\n   * @param {number} [seg]  Segment index in [0, segments−1]. Omit for cursor.\n   * @param {number} [t]    Local parameter in [0, 1]. Omit for cursor.\n   * @returns {number[]} out\n   */\n  samplePos(out, seg, t) {\n    if (arguments.length < 3) [seg, t] = this._cursorSegT();\n    return _samplePathCore(out, this.keyframes, this.posInterp, 'pos', 'tanIn', 'tanOut', seg, t);\n  }\n\n  /**\n   * Write the TRS pose as a column-major model mat4. Zero-alloc, no cursor\n   * side effects.\n   *\n   * Two signatures:\n   *   mat4Model(out)              cursor form — reads current seg/f\n   *   mat4Model(out, seg, t)      explicit (seg, t), continuous on the path\n   *\n   * Replaces the previous toMatrix() method.\n   *\n   * @param {Float32Array|number[]} out  16-element result buffer.\n   * @param {number} [seg]  Segment index in [0, segments−1]. Omit for cursor.\n   * @param {number} [t]    Local parameter in [0, 1]. Omit for cursor.\n   * @returns {Float32Array|number[]} out\n   */\n  mat4Model(out, seg, t) {\n    if (arguments.length < 3) [seg, t] = this._cursorSegT();\n    this._sampleTRS(_trsScratch, seg, t);\n    return transformToMat4(out, _trsScratch);\n  }\n\n  /**\n   * Effective incoming / outgoing position tangents at keyframe `index`.\n   * Stored tanIn/tanOut take precedence; each mirrors the other when only\n   * one is stored; else centripetal Catmull-Rom tangents are auto-computed\n   * from neighbours. Boundary keyframes mirror across the missing side.\n   *\n   * @param {number[]} outIn   3-element result — incoming tangent.\n   * @param {number[]} outOut  3-element result — outgoing tangent.\n   * @param {number} index     Keyframe index.\n   * @returns {PoseTrack} this\n   */\n  tangents(outIn, outOut, index) {\n    _sampleTangentsCore(outIn, outOut, this.keyframes, 'pos', 'tanIn', 'tanOut', index);\n    return this;\n  }\n\n  /** @private — write interpolated TRS at (seg, t). */\n  _sampleTRS(out, seg, t) {\n    const n = this.keyframes.length;\n    if (n === 0) return out;\n    if (n === 1) {\n      const k = this.keyframes[0];\n      out.pos[0]=k.pos[0]; out.pos[1]=k.pos[1]; out.pos[2]=k.pos[2];\n      out.rot[0]=k.rot[0]; out.rot[1]=k.rot[1]; out.rot[2]=k.rot[2]; out.rot[3]=k.rot[3];\n      out.scl[0]=k.scl[0]; out.scl[1]=k.scl[1]; out.scl[2]=k.scl[2];\n      return out;\n    }\n    const nSeg = n - 1;\n    seg = seg | 0;\n    if (seg >= nSeg) { seg = nSeg - 1; t = 1; }\n    else if (seg < 0) { seg = 0; t = 0; }\n    t   = _clamp01(t);\n    const k0 = this.keyframes[seg];\n    const k1 = this.keyframes[seg + 1];\n\n    _samplePathCore(out.pos, this.keyframes, this.posInterp, 'pos', 'tanIn', 'tanOut', seg, t);\n\n    if (this.rotInterp === 'step') {\n      out.rot[0]=k0.rot[0]; out.rot[1]=k0.rot[1]; out.rot[2]=k0.rot[2]; out.rot[3]=k0.rot[3];\n    } else if (this.rotInterp === 'nlerp') {\n      qNlerp(out.rot, k0.rot, k1.rot, t);\n    } else {\n      qSlerp(out.rot, k0.rot, k1.rot, t);\n    }\n\n    lerpVec3(out.scl, k0.scl, k1.scl, t);\n    return out;\n  }\n\n  /**\n   * Evaluate interpolated TRS pose at current cursor.\n   * @param {{ pos:number[], rot:number[], scl:number[] }} [out]\n   * @returns {{ pos:number[], rot:number[], scl:number[] }} out\n   */\n  eval(out) {\n    out = out || { pos:[0,0,0], rot:[0,0,0,1], scl:[1,1,1] };\n    const n = this.keyframes.length;\n    if (n === 0) return out;\n    if (n === 1) return this._sampleTRS(out, 0, 0);\n    const [seg, t] = this._cursorSegT();\n    return this._sampleTRS(out, seg, t);\n  }\n}\n\n// =========================================================================\n// S7  CameraTrack\n// =========================================================================\n\n/**\n * Lookat camera keyframe track.\n *\n * Keyframe shape: { eye:[x,y,z], center:[x,y,z], up:[x,y,z],\n *                   fov?:number, halfHeight?:number,\n *                   near:number, far:number,\n *                   eyeTanIn?:[x,y,z], eyeTanOut?:[x,y,z],\n *                   centerTanIn?:[x,y,z], centerTanOut?:[x,y,z] }\n *\n * fov        — vertical fov (radians) for perspective cameras; null for ortho.\n * halfHeight — world-unit half-height of ortho frustum; null for perspective.\n * Both are optional and nullable because exactly one is meaningful per\n * keyframe (perspective xor ortho). eval() lerps each only when both\n * adjacent keyframes carry a non-null value for that field; mixed or\n * missing entries pass `null` through.\n *\n * near, far — clip plane distances (positive, world units). Always real\n * numbers. Defaults: near = 0.1, far = 1000 (three.js / Bevy convention).\n * Linearly interpolated between keyframes without null-passthrough.\n *\n * eyeTanIn/Out and centerTanIn/Out are optional vec3 tangents for Hermite\n * interpolation of the eye and center paths respectively. When absent,\n * centripetal Catmull-Rom tangents are auto-computed at sample time.\n *\n * Missing fields default to: center → [0,0,0], up → [0,1,0],\n * near → 0.1, far → 1000.\n *\n * For matrix-based capture of a camera-like pose use\n * PoseTrack.add({ mat4Model: mat4Eye }) for full TRS fidelity including roll,\n * or a lookat spec here for camera-style interpolation.\n */\nclass CameraTrack extends Track {\n  constructor() {\n    super();\n    /**\n     * Eye-path interpolation mode.\n     * @type {'hermite'|'linear'|'step'}\n     */\n    this.eyeInterp = 'hermite';\n    /**\n     * Center-path interpolation mode.\n     * @type {'hermite'|'linear'|'step'}\n     */\n    this.centerInterp = 'linear';\n  }\n\n  /**\n   * Append one or more camera keyframes. Adjacent duplicates are skipped by\n   * default.\n   * @param {Object|Object[]} spec\n   * @param {{ deduplicate?: boolean }} [opts]\n   */\n  add(spec, opts) {\n    if (Array.isArray(spec)) { for (const s of spec) this.add(s, opts); return; }\n    const kf = _parseCameraSpec(spec);\n    if (!kf) return;\n    const dedup = !opts || opts.deduplicate !== false;\n    if (dedup && this.keyframes.length > 0) {\n      if (_sameCameraKeyframe(this.keyframes[this.keyframes.length - 1], kf)) return;\n    }\n    this.keyframes.push(kf);\n  }\n\n  /**\n   * Replace the camera keyframe at `index`, or append at the end if `index`\n   * equals the current keyframe count.\n   * @param {number} index\n   * @param {Object} spec\n   * @returns {boolean}\n   */\n  set(index, spec) {\n    if (!_isNum(index)) return false;\n    const i = index | 0, kf = _parseCameraSpec(spec);\n    if (!kf || i < 0 || i > this.keyframes.length) return false;\n    if (i === this.keyframes.length) this.keyframes.push(kf);\n    else this.keyframes[i] = kf;\n    return true;\n  }\n\n  /**\n   * Sample the eye path. Zero-alloc, no cursor side effects.\n   *\n   * Two signatures:\n   *   sampleEye(out)              cursor form — reads current seg/f\n   *   sampleEye(out, seg, t)      explicit (seg, t), continuous on the path\n   *\n   * @param {number[]} out\n   * @param {number} [seg]\n   * @param {number} [t]\n   * @returns {number[]} out\n   */\n  sampleEye(out, seg, t) {\n    if (arguments.length < 3) [seg, t] = this._cursorSegT();\n    return _samplePathCore(out, this.keyframes, this.eyeInterp, 'eye', 'eyeTanIn', 'eyeTanOut', seg, t);\n  }\n\n  /**\n   * Sample the center path. Zero-alloc, no cursor side effects.\n   *\n   * Two signatures:\n   *   sampleCenter(out)              cursor form — reads current seg/f\n   *   sampleCenter(out, seg, t)      explicit (seg, t)\n   *\n   * @param {number[]} out\n   * @param {number} [seg]\n   * @param {number} [t]\n   * @returns {number[]} out\n   */\n  sampleCenter(out, seg, t) {\n    if (arguments.length < 3) [seg, t] = this._cursorSegT();\n    return _samplePathCore(out, this.keyframes, this.centerInterp, 'center', 'centerTanIn', 'centerTanOut', seg, t);\n  }\n\n  /**\n   * Write the interpolated lookat eye matrix as a column-major mat4\n   * (eye→world rigid frame). Zero-alloc, no cursor side effects.\n   *\n   * Two signatures:\n   *   mat4Eye(out)              cursor form — reads current seg/f\n   *   mat4Eye(out, seg, t)      explicit (seg, t), continuous on the path\n   *\n   * @param {Float32Array|number[]} out  16-element result buffer.\n   * @param {number} [seg]\n   * @param {number} [t]\n   * @returns {Float32Array|number[]} out\n   */\n  mat4Eye(out, seg, t) {\n    if (arguments.length < 3) [seg, t] = this._cursorSegT();\n    this._sampleEyePose(_eyeScratch, seg, t);\n    const e = _eyeScratch;\n    return mat4Eye(out,\n      e.eye[0], e.eye[1], e.eye[2],\n      e.center[0], e.center[1], e.center[2],\n      e.up[0], e.up[1], e.up[2]);\n  }\n\n  /**\n   * Effective in/out eye tangents at keyframe `index`.\n   */\n  eyeTangents(outIn, outOut, index) {\n    _sampleTangentsCore(outIn, outOut, this.keyframes, 'eye', 'eyeTanIn', 'eyeTanOut', index);\n    return this;\n  }\n\n  /**\n   * Effective in/out center tangents at keyframe `index`.\n   */\n  centerTangents(outIn, outOut, index) {\n    _sampleTangentsCore(outIn, outOut, this.keyframes, 'center', 'centerTanIn', 'centerTanOut', index);\n    return this;\n  }\n\n  /** @private — write interpolated { eye, center, up } at (seg, t). */\n  _sampleEyePose(out, seg, t) {\n    const n = this.keyframes.length;\n    if (n === 0) return out;\n    if (n === 1) {\n      const k = this.keyframes[0];\n      out.eye[0]=k.eye[0];       out.eye[1]=k.eye[1];       out.eye[2]=k.eye[2];\n      out.center[0]=k.center[0]; out.center[1]=k.center[1]; out.center[2]=k.center[2];\n      out.up[0]=k.up[0];         out.up[1]=k.up[1];         out.up[2]=k.up[2];\n      return out;\n    }\n    const nSeg = n - 1;\n    seg = seg | 0;\n    if (seg >= nSeg) { seg = nSeg - 1; t = 1; }\n    else if (seg < 0) { seg = 0; t = 0; }\n    t   = _clamp01(t);\n    const k0 = this.keyframes[seg];\n    const k1 = this.keyframes[seg + 1];\n\n    _samplePathCore(out.eye,    this.keyframes, this.eyeInterp,    'eye',    'eyeTanIn',    'eyeTanOut',    seg, t);\n    _samplePathCore(out.center, this.keyframes, this.centerInterp, 'center', 'centerTanIn', 'centerTanOut', seg, t);\n\n    lerpVec3(out.up, k0.up, k1.up, t);\n    const ul = Math.sqrt(out.up[0]*out.up[0]+out.up[1]*out.up[1]+out.up[2]*out.up[2]) || 1;\n    out.up[0]/=ul; out.up[1]/=ul; out.up[2]/=ul;\n    return out;\n  }\n\n  /**\n   * Evaluate interpolated camera pose at current cursor.\n   *\n   * `fov` / `halfHeight` are lerped only when both adjacent keyframes carry\n   * a non-null value; mixed entries pass `null` through so the bridge can\n   * leave the projection unchanged.\n   *\n   * `near` / `far` are always real numbers and are linearly interpolated\n   * unconditionally.\n   *\n   * @param {{ eye:number[], center:number[], up:number[],\n   *           fov:number|null, halfHeight:number|null,\n   *           near:number, far:number }} [out]\n   * @returns {{ eye:number[], center:number[], up:number[],\n   *             fov:number|null, halfHeight:number|null,\n   *             near:number, far:number }} out\n   */\n  eval(out) {\n    out = out || { eye:[0,0,0], center:[0,0,0], up:[0,1,0],\n                   fov:null, halfHeight:null,\n                   near:_DEFAULT_NEAR, far:_DEFAULT_FAR };\n    const n = this.keyframes.length;\n    if (n === 0) return out;\n    if (n === 1) {\n      const k = this.keyframes[0];\n      this._sampleEyePose(out, 0, 0);\n      out.fov = k.fov; out.halfHeight = k.halfHeight;\n      out.near = k.near; out.far = k.far;\n      return out;\n    }\n    const [seg, t] = this._cursorSegT();\n    const k0 = this.keyframes[seg];\n    const k1 = this.keyframes[seg + 1];\n\n    this._sampleEyePose(out, seg, t);\n\n    out.fov = (k0.fov != null && k1.fov != null)\n      ? k0.fov + t * (k1.fov - k0.fov) : (k0.fov ?? k1.fov ?? null);\n    out.halfHeight = (k0.halfHeight != null && k1.halfHeight != null)\n      ? k0.halfHeight + t * (k1.halfHeight - k0.halfHeight)\n      : (k0.halfHeight ?? k1.halfHeight ?? null);\n\n    // near / far carry real defaults on every keyframe — always lerp.\n    out.near = k0.near + t * (k1.near - k0.near);\n    out.far  = k0.far  + t * (k1.far  - k0.far);\n\n    return out;\n  }\n}\n\n/**\n * @file Frustum planes and visibility tests — zero allocations.\n * @module tree/visibility\n * @license AGPL-3.0-only\n *\n * Planes are a flat Float64Array(24): 6 planes × 4 floats [a, b, c, d].\n * All inputs are scalars. All outputs are INVISIBLE | VISIBLE | SEMIVISIBLE.\n */\n\n\n// Plane indices\nconst PLANE_LEFT = 0, PLANE_RIGHT = 1, PLANE_NEAR = 2,\n             PLANE_FAR = 3, PLANE_TOP = 4, PLANE_BOTTOM = 5;\n\n/**\n * Compute 6 frustum planes from camera basis (world space) + projection params.\n * All inputs are scalars — the addon extracts them from the inverse view matrix\n * and projection queries before calling.\n *\n * @param {Float64Array} out  24-float output.\n * @param {number} posX,posY,posZ  Camera world position.\n * @param {number} vdX,vdY,vdZ    View direction (−Z in eye space, world).\n * @param {number} upX,upY,upZ    Camera up.\n * @param {number} rtX,rtY,rtZ    Camera right.\n * @param {boolean} ortho         true if orthographic.\n * @param {number} near,far,left,right,top,bottom\n *   Projection extents in camera space.\n *   Sign contract: top > 0, bottom < 0, right > 0, left < 0 for standard y-up camera.\n */\nfunction frustumPlanes(\n  out,\n  posX, posY, posZ,\n  vdX, vdY, vdZ,\n  upX, upY, upZ,\n  rtX, rtY, rtZ,\n  ortho,\n  near, far, left, right, top, bottom\n) {\n  const posViewDir = posX*vdX + posY*vdY + posZ*vdZ;\n  const posRight   = posX*rtX + posY*rtY + posZ*rtZ;\n  const posUp      = posX*upX + posY*upY + posZ*upZ;\n\n  if (ortho) {\n    // Left: normal = −right\n    out[0] = -rtX; out[1] = -rtY; out[2] = -rtZ;\n    out[3] = -(posRight - left) * -1; // dot(pos - right*left, -right) ... simplified:\n    // Actually: d = dot(pointOnPlane, normal)\n    // pointOnPlane = pos + right*left (left is negative for standard ortho)\n    // normal = -right\n    // d = dot(pos + right*left, -right) = -posRight - left\n    out[3] = -posRight - left;\n\n    // Right: normal = right\n    out[4] = rtX; out[5] = rtY; out[6] = rtZ;\n    out[7] = posRight + right;\n\n    // Top: normal = up\n    out[16] = upX; out[17] = upY; out[18] = upZ;\n    out[19] = posUp + top;\n\n    // Bottom: normal = -up\n    out[20] = -upX; out[21] = -upY; out[22] = -upZ;\n    out[23] = -posUp - bottom;\n  } else {\n    // Left\n    const hfovl = Math.atan2(left, near);\n    const shfovl = Math.sin(hfovl), chfovl = Math.cos(hfovl);\n    out[0] = vdX*shfovl - rtX*chfovl;\n    out[1] = vdY*shfovl - rtY*chfovl;\n    out[2] = vdZ*shfovl - rtZ*chfovl;\n    out[3] = shfovl*posViewDir - chfovl*posRight;\n\n    // Right\n    const hfovr = Math.atan2(right, near);\n    const shfovr = Math.sin(hfovr), chfovr = Math.cos(hfovr);\n    out[4] = -vdX*shfovr + rtX*chfovr;\n    out[5] = -vdY*shfovr + rtY*chfovr;\n    out[6] = -vdZ*shfovr + rtZ*chfovr;\n    out[7] = -shfovr*posViewDir + chfovr*posRight;\n\n    // Top\n    const fovt = Math.atan2(top, near);\n    const sfovt = Math.sin(fovt), cfovt = Math.cos(fovt);\n    out[16] = -vdX*sfovt + upX*cfovt;\n    out[17] = -vdY*sfovt + upY*cfovt;\n    out[18] = -vdZ*sfovt + upZ*cfovt;\n    out[19] = -sfovt*posViewDir + cfovt*posUp;\n\n    // Bottom\n    const fovb = Math.atan2(bottom, near);\n    const sfovb = Math.sin(fovb), cfovb = Math.cos(fovb);\n    out[20] = vdX*sfovb - upX*cfovb;\n    out[21] = vdY*sfovb - upY*cfovb;\n    out[22] = vdZ*sfovb - upZ*cfovb;\n    out[23] = sfovb*posViewDir - cfovb*posUp;\n  }\n\n  // Near plane: normal = −viewDir\n  out[8]  = -vdX; out[9]  = -vdY; out[10] = -vdZ;\n  out[11] = -posViewDir - near;\n\n  // Far plane: normal = viewDir\n  out[12] = vdX; out[13] = vdY; out[14] = vdZ;\n  out[15] = posViewDir + far;\n\n  return out;\n}\n\n/**\n * Signed distance from point to one frustum plane.\n * @param {Float64Array} planes  24-float planes buffer.\n * @param {number} planeIdx  0–5 (LEFT, RIGHT, NEAR, FAR, TOP, BOTTOM).\n * @param {number} px,py,pz  Point coordinates.\n * @returns {number}\n */\nfunction distanceToPlane(planes, planeIdx, px, py, pz) {\n  const b = planeIdx * 4;\n  return planes[b]*px + planes[b+1]*py + planes[b+2]*pz - planes[b+3];\n}\n\n/** @returns {number} INVISIBLE | VISIBLE | SEMIVISIBLE */\nfunction pointVisibility(planes, px, py, pz) {\n  for (let i = 0; i < 6; i++) {\n    if (distanceToPlane(planes, i, px, py, pz) > 0) return INVISIBLE;\n  }\n  return VISIBLE;\n}\n\n/** @returns {number} INVISIBLE | VISIBLE | SEMIVISIBLE */\nfunction sphereVisibility(planes, cx, cy, cz, radius) {\n  let allIn = true;\n  for (let i = 0; i < 6; i++) {\n    const d = distanceToPlane(planes, i, cx, cy, cz);\n    if (d > radius) return INVISIBLE;\n    if (d > 0 || -d < radius) allIn = false;\n  }\n  return allIn ? VISIBLE : SEMIVISIBLE;\n}\n\n/** @returns {number} INVISIBLE | VISIBLE | SEMIVISIBLE */\nfunction boxVisibility(planes, x0, y0, z0, x1, y1, z1) {\n  let allIn = true;\n  for (let i = 0; i < 6; i++) {\n    const b = i * 4;\n    const a = planes[b], bv = planes[b+1], c = planes[b+2], d = planes[b+3];\n    let allOut = true;\n    for (let corner = 0; corner < 8; corner++) {\n      const cx = (corner & 4) ? x0 : x1;\n      const cy = (corner & 2) ? y0 : y1;\n      const cz = (corner & 1) ? z0 : z1;\n      const dist = a*cx + bv*cy + c*cz - d;\n      if (dist > 0) { allIn = false; }\n      else { allOut = false; }\n    }\n    if (allOut) return INVISIBLE;\n  }\n  return allIn ? VISIBLE : SEMIVISIBLE;\n}\n\nexport { CameraTrack, EYE, INVISIBLE, MATRIX, MODEL, NDC, ORIGIN, PLANE_BOTTOM, PLANE_FAR, PLANE_LEFT, PLANE_NEAR, PLANE_RIGHT, PLANE_TOP, PoseTrack, SCREEN, SEMIVISIBLE, VISIBLE, WEBGL, WEBGPU, WORLD, _i, _j, _k, boxVisibility, distanceToPlane, frustumPlanes, hermiteVec3, i, j, k, lerpVec3, mapDirection, mapLocation, mat3Direction, mat3NormalFromMat4, mat4Bias, mat4Eye, mat4FromBasis, mat4FromScale, mat4FromTRS, mat4FromTranslation, mat4Invert, mat4Location, mat4MV, mat4Mul, mat4MulDir, mat4MulPoint, mat4Ortho, mat4PV, mat4Persp, mat4Pick, mat4Reflect, mat4ToRotation, mat4ToScale, mat4ToTransform, mat4ToTranslation, mat4View, pixelRatio, pointVisibility, projBottom, projFar, projFov, projHfov, projIsOrtho, projLeft, projNear, projRight, projTop, qCopy, qDot, qFromAxisAngle, qFromLookDir, qFromMat4, qFromRotMat3x3, qMul, qNegate, qNlerp, qNormalize, qSet, qSlerp, qToAxisAngle, qToMat4, sphereVisibility, transformToMat4 };\n//# sourceMappingURL=index.js.map\n","/**\n * @file Matrix queries, space transforms, and frustum scalar queries.\n * @module p5.tree/matrix\n * @license AGPL-3.0-only\n *\n * ── Two distinct contracts ─────────────────────────────────────────────────\n *\n * Matrix-fill methods (mat4Proj, mat4View, mat4PV, …):\n *   out-first, mandatory, zero-allocation.\n *   `out` is a caller-owned buffer (Float32Array | ArrayLike | p5.Matrix).\n *   The function writes into it and returns it.\n *\n * Space-query methods (mapLocation, mapDirection):\n *   point/dir is positional; everything else is in opts.\n *   opts.out is optional — if absent a fresh p5.Vector is allocated.\n *   Return type matches opts.out: Float32Array, ArrayLike, or p5.Vector.\n *   Hot paths pass opts.out = buf (zero-alloc); non-hot paths omit it.\n *\n * ── Viewport convention ───────────────────────────────────────────────────\n * The bridge always builds vp = [0, canvasH, canvasW, −canvasH].\n * Negative h encodes DOM/p5 screen-y-down. See query.js for full details.\n */\n\n'use strict';\n\nimport {\n  EYE, NDC, SCREEN, MATRIX, WEBGL, WEBGPU,\n  mat4Mul, mat4Invert, mat3NormalFromMat4,\n  mat4Location, mat3Direction,\n  mapLocation as _mapLocation,\n  mapDirection as _mapDirection,\n  projIsOrtho, projNear, projFar, projFov, projHfov,\n  projLeft, projRight, projTop, projBottom,\n  pixelRatio as corePixelRatio,\n  mat4View  as _mat4View,\n  mat4Eye   as _mat4Eye,\n  mat4Persp as _mat4Persp,\n  mat4Ortho as _mat4Ortho,\n  mat4ToTranslation,\n  mat4ToScale,\n  mat4ToRotation,\n} from '@nakednous/tree';\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Module-level working buffers — internal intermediates, never returned\n// ═══════════════════════════════════════════════════════════════════════════\n\nconst _pv   = new Float32Array(16);  // mat4PV intermediate\nconst _ipv  = new Float32Array(16);  // mat4PVInv intermediate\nconst _wa   = new Float32Array(16);  // single-step intermediate (mat4Eye, MV, …)\nconst _wb   = new Float32Array(16);  // toFrameInv for custom MATRIX space\nconst _vp   = new Float32Array(4);   // viewport [0, h, w, −h]\nconst _tmp3 = new Float32Array(3);   // p5.Vector write-back scratch\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Unified type normalisers — zero alloc\n// ═══════════════════════════════════════════════════════════════════════════\n\nconst _rawMat4 = (m) => (m != null && m.mat4 != null) ? m.mat4 : m;\nconst _rawMat3 = (m) => (m != null && m.mat3 != null) ? m.mat3 : m;\n\n// ═══════════════════════════════════════════════════════════════════════════\n// NDC convention — detected once in postsetup\n// ═══════════════════════════════════════════════════════════════════════════\n\nlet _ndcZ = WEBGL;\n\n/** Detect NDC Z convention from renderer context. Called from postsetup. */\nexport function detectNDC(renderer) {\n  _ndcZ = (renderer.drawingContext &&\n           typeof WebGL2RenderingContext !== 'undefined' &&\n           renderer.drawingContext instanceof WebGL2RenderingContext) ? WEBGL : WEBGPU;\n}\n\nexport const getNdcZ = () => _ndcZ;\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Raw p5 state access — direct Float32Array refs, no copies\n// ═══════════════════════════════════════════════════════════════════════════\n\nconst _projMat4  = (r) => r.states.uPMatrix.mat4;\nconst _viewMat4  = (r) => r.states.curCamera.cameraMatrix.mat4;\nconst _modelMat4 = (r) => r.states.uModelMatrix.mat4;\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Install\n// ═══════════════════════════════════════════════════════════════════════════\n\nexport function installMatrix(p5, fn) {\n\n  // True for Float32Array, plain Array, or p5.Vector — the three accepted\n  // point/direction types. Plain opts objects do not match.\n  const _isVec = (v) => v != null &&\n    (Array.isArray(v) || ArrayBuffer.isView(v) || v instanceof p5.Vector);\n\n  // Resolve opts.out for mapLocation / mapDirection.\n  // Returns opts.out if provided, otherwise allocates a fresh p5.Vector.\n  const _resolveOut = (opts) => opts?.out ?? new p5.Vector();\n\n  // ── p5.Matrix utility ─────────────────────────────────────────────────────\n\n  fn.createMatrix = (...args) => new p5.Matrix(...args);\n\n  // ── Simple matrix queries ─────────────────────────────────────────────────\n  //   out: Float32Array | ArrayLike | p5.Matrix — 16-element destination.\n\n  /** Projection matrix (eye → clip) — reads live renderer state (perspective or ortho). */\n  p5.Renderer3D.prototype.mat4Proj = function (out) {\n    const buf = _rawMat4(out), s = _projMat4(this);\n    for (let i = 0; i < 16; i++) buf[i] = s[i];\n    return out;\n  };\n  fn.mat4Proj = function (out) { return this._renderer.mat4Proj(out); };\n\n  /**\n   * Projection matrix (eye → clip) of a specific p5.Camera.\n   *\n   * Reads from the camera's own `projMatrix` field, populated when\n   * `cam.perspective()`, `cam.ortho()`, or `cam.frustum()` is called.\n   * Symmetric with `cam.mat4View` / `cam.mat4Eye` which read from\n   * `cam.cameraMatrix`.\n   *\n   * @param {Float32Array|ArrayLike|p5.Matrix} out  16-element destination.\n   */\n  p5.Camera.prototype.mat4Proj = function (out) {\n    const buf = _rawMat4(out), s = this.projMatrix.mat4;\n    for (let i = 0; i < 16; i++) buf[i] = s[i];\n    return out;\n  };\n\n  /**\n   * Perspective projection matrix (standalone constructor, general frustum).\n   * mat4Persp(out, left, right, bottom, top, near, far[, ndcZMin[, ndcYSign]])\n   * Symmetric: left=-right, bottom=-top — derive from fov+aspect in user space.\n   * @param {Float32Array|ArrayLike|p5.Matrix} out\n   */\n  fn.mat4Persp = function (out, ...args) {\n    if (args[6] == null) args[6] = _ndcZ;\n    _mat4Persp(_rawMat4(out), ...args);\n    return out;\n  };\n\n  /**\n   * Orthographic projection matrix (standalone constructor).\n   * mat4Ortho(out, left, right, bottom, top, near, far[, ndcZMin[, ndcYSign]])\n   * @param {Float32Array|ArrayLike|p5.Matrix} out\n   */\n  fn.mat4Ortho = function (out, ...args) {\n    if (args[6] == null) args[6] = _ndcZ;\n    _mat4Ortho(_rawMat4(out), ...args);\n    return out;\n  };\n\n  /** Model matrix (local → world). */\n  p5.Renderer3D.prototype.mat4Model = function (out) {\n    const buf = _rawMat4(out), s = _modelMat4(this);\n    for (let i = 0; i < 16; i++) buf[i] = s[i];\n    return out;\n  };\n  fn.mat4Model = function (out) { return this._renderer.mat4Model(out); };\n\n  /** View matrix (world → eye). */\n  p5.Camera.prototype.mat4View = function (out) {\n    const buf = _rawMat4(out), s = this.cameraMatrix.mat4;\n    for (let i = 0; i < 16; i++) buf[i] = s[i];\n    return out;\n  };\n  p5.Renderer3D.prototype.mat4View = function (out) { return this.states.curCamera.mat4View(out); };\n  fn.mat4View = function (out, ...args) {\n    if (args.length === 0) return this._renderer.mat4View(out);\n    _mat4View(_rawMat4(out), ...args);\n    return out;\n  };\n\n  /** Eye matrix (eye → world, i.e. inverse view). Returns null if singular. */\n  p5.Camera.prototype.mat4Eye = function (out) {\n    const buf = _rawMat4(out);\n    return mat4Invert(buf, this.cameraMatrix.mat4) === null ? null : out;\n  };\n  p5.Renderer3D.prototype.mat4Eye = function (out) { return this.states.curCamera.mat4Eye(out); };\n  fn.mat4Eye = function (out, ...args) {\n    if (args.length === 0) return this._renderer.mat4Eye(out);\n    _mat4Eye(_rawMat4(out), ...args);\n    return out;\n  };\n\n  // ── Composite matrix queries ──────────────────────────────────────────────\n  //   opts may supply precomputed matrices to skip redundant multiplications.\n\n  /**\n   * Projection-view matrix: P · V.\n   * @param {Float32Array|ArrayLike|p5.Matrix} out\n   * @param {{ mat4Proj?, mat4View? }} [opts]\n   */\n  p5.Renderer3D.prototype.mat4PV = function (out, { mat4Proj, mat4View } = {}) {\n    mat4Mul(_rawMat4(out), _rawMat4(mat4Proj) ?? _projMat4(this), _rawMat4(mat4View) ?? _viewMat4(this));\n    return out;\n  };\n  fn.mat4PV = function (out, opts) { return this._renderer.mat4PV(out, opts); };\n\n  /**\n   * Inverse projection-view matrix: inv(P · V).\n   * Pass mat4PV to skip recomputing P · V. Returns null if singular.\n   * @param {Float32Array|ArrayLike|p5.Matrix} out\n   * @param {{ mat4Proj?, mat4View?, mat4PV? }} [opts]\n   */\n  p5.Renderer3D.prototype.mat4PVInv = function (out, { mat4Proj, mat4View, mat4PV } = {}) {\n    const pv = _rawMat4(mat4PV) ??\n      (mat4Mul(_pv, _rawMat4(mat4Proj) ?? _projMat4(this), _rawMat4(mat4View) ?? _viewMat4(this)), _pv);\n    return mat4Invert(_rawMat4(out), pv) === null ? null : out;\n  };\n  fn.mat4PVInv = function (out, opts) { return this._renderer.mat4PVInv(out, opts); };\n\n  /**\n   * Model-view matrix: V · M.\n   * @param {Float32Array|ArrayLike|p5.Matrix} out\n   * @param {{ mat4Model?, mat4View? }} [opts]\n   */\n  p5.Renderer3D.prototype.mat4MV = function (out, { mat4Model, mat4View } = {}) {\n    mat4Mul(_rawMat4(out), _rawMat4(mat4View) ?? _viewMat4(this), _rawMat4(mat4Model) ?? _modelMat4(this));\n    return out;\n  };\n  fn.mat4MV = function (out, opts) { return this._renderer.mat4MV(out, opts); };\n\n  /**\n   * Projection-model-view matrix: P · V · M.\n   * @param {Float32Array|ArrayLike|p5.Matrix} out\n   * @param {{ mat4Proj?, mat4Model?, mat4View? }} [opts]\n   */\n  p5.Renderer3D.prototype.mat4PMV = function (out, { mat4Proj, mat4Model, mat4View } = {}) {\n    mat4Mul(_wa, _rawMat4(mat4View) ?? _viewMat4(this), _rawMat4(mat4Model) ?? _modelMat4(this));\n    mat4Mul(_rawMat4(out), _rawMat4(mat4Proj) ?? _projMat4(this), _wa);\n    return out;\n  };\n  fn.mat4PMV = function (out, opts) { return this._renderer.mat4PMV(out, opts); };\n\n  /**\n   * Normal matrix: inverseTranspose(upper 3×3 of V · M).\n   * Pass mat4MV to skip recomputing V · M.\n   * @param {Float32Array|ArrayLike|p5.Matrix} out  9-element destination.\n   * @param {{ mat4Model?, mat4View?, mat4MV? }} [opts]\n   */\n  p5.Renderer3D.prototype.mat3Normal = function (out, { mat4Model, mat4View, mat4MV } = {}) {\n    const mv = _rawMat4(mat4MV) ??\n      (mat4Mul(_wa, _rawMat4(mat4View) ?? _viewMat4(this), _rawMat4(mat4Model) ?? _modelMat4(this)), _wa);\n    mat3NormalFromMat4(_rawMat3(out), mv);\n    return out;\n  };\n  fn.mat3Normal = function (out, opts) { return this._renderer.mat3Normal(out, opts); };\n\n  /**\n   * Location transform between frames: out = inv(to) · from.\n   * Returns null if `to` is singular.\n   * @param {Float32Array|ArrayLike|p5.Matrix} out  16-element destination.\n   * @param {Float32Array|ArrayLike|p5.Matrix} from\n   * @param {Float32Array|ArrayLike|p5.Matrix} to\n   */\n  p5.Renderer3D.prototype.mat4Location = function (out, from, to) {\n    return mat4Location(_rawMat4(out), _rawMat4(from), _rawMat4(to)) === null ? null : out;\n  };\n  fn.mat4Location = function (out, from, to) { return this._renderer.mat4Location(out, from, to); };\n\n  /**\n   * Direction transform between frames: out = to₃ · inv(from₃).\n   * Returns null if `from` is singular.\n   * @param {Float32Array|ArrayLike|p5.Matrix} out  9-element destination.\n   * @param {Float32Array|ArrayLike|p5.Matrix} from\n   * @param {Float32Array|ArrayLike|p5.Matrix} to\n   */\n  p5.Renderer3D.prototype.mat3Direction = function (out, from, to) {\n    return mat3Direction(_rawMat3(out), _rawMat4(from), _rawMat4(to)) === null ? null : out;\n  };\n  fn.mat3Direction = function (out, from, to) { return this._renderer.mat3Direction(out, from, to); };\n\n  // ── Raw math forwarders ───────────────────────────────────────────────────\n  //   For sketches that need custom matrix arithmetic (e.g. bias·lightPV for\n  //   shadow mapping) without importing @nakednous/tree directly.\n\n  /** out = A · B  (column-major) */\n  p5.Renderer3D.prototype.mat4Mul = function (out, A, B) {\n    mat4Mul(_rawMat4(out), _rawMat4(A), _rawMat4(B));\n    return out;\n  };\n  fn.mat4Mul = function (out, A, B) { return this._renderer.mat4Mul(out, A, B); };\n\n  /** out = inv(src). Returns null if singular. */\n  p5.Renderer3D.prototype.mat4Invert = function (out, src) {\n    return mat4Invert(_rawMat4(out), _rawMat4(src)) === null ? null : out;\n  };\n  fn.mat4Invert = function (out, src) { return this._renderer.mat4Invert(out, src); };\n\n  // ── Decomposition ─────────────────────────────────────────────────────────────────────────────\n  //   Extract components from an existing mat4 — matrix → information.\n  //   m is normalised via _rawMat4 (handles Float32Array | ArrayLike | p5.Matrix).\n  //   out3: Float32Array | number[] | p5.Vector — p5.Vector written back via _tmp3.\n  //   out4: Float32Array | number[] only — quaternion is 4-component, no p5.Vector.\n\n  /** Extract translation (column 3) from a mat4. */\n  fn.mat4ToTranslation = function (out3, m) {\n    const isVec = out3 instanceof p5.Vector;\n    const buf = isVec ? _tmp3 : out3;\n    mat4ToTranslation(buf, _rawMat4(m));\n    if (isVec) { out3.x = buf[0]; out3.y = buf[1]; out3.z = buf[2]; }\n    return out3;\n  };\n\n  /** Extract scale (column vector lengths) from a mat4. Assumes no shear. */\n  fn.mat4ToScale = function (out3, m) {\n    const isVec = out3 instanceof p5.Vector;\n    const buf = isVec ? _tmp3 : out3;\n    mat4ToScale(buf, _rawMat4(m));\n    if (isVec) { out3.x = buf[0]; out3.y = buf[1]; out3.z = buf[2]; }\n    return out3;\n  };\n\n  /** Extract rotation as a unit quaternion [x,y,z,w]. Assumes no shear. */\n  fn.mat4ToRotation = function (out4, m) {\n    mat4ToRotation(out4, _rawMat4(m));\n    return out4;\n  };\n\n  // ── Projection scalar queries ─────────────────────────────────────────────\n  //   Read scalars from the current projection matrix — no buffer needed.\n\n  p5.Renderer3D.prototype.projIsOrtho = function () { return projIsOrtho(_projMat4(this)); };\n  p5.Renderer3D.prototype.projNear    = function () { return projNear   (_projMat4(this), _ndcZ); };\n  p5.Renderer3D.prototype.projFar     = function () { return projFar    (_projMat4(this)); };\n  p5.Renderer3D.prototype.projLeft    = function () { return projLeft   (_projMat4(this), _ndcZ); };\n  p5.Renderer3D.prototype.projRight   = function () { return projRight  (_projMat4(this), _ndcZ); };\n  p5.Renderer3D.prototype.projTop     = function () { return projTop    (_projMat4(this), _ndcZ); };\n  p5.Renderer3D.prototype.projBottom  = function () { return projBottom (_projMat4(this), _ndcZ); };\n  p5.Renderer3D.prototype.projFov     = function () { return projFov    (_projMat4(this)); };\n  p5.Renderer3D.prototype.projHfov    = function () { return projHfov   (_projMat4(this)); };\n\n  fn.projIsOrtho = function () { return this._renderer.projIsOrtho(); };\n  fn.projNear    = function () { return this._renderer.projNear();    };\n  fn.projFar     = function () { return this._renderer.projFar();     };\n  fn.projLeft    = function () { return this._renderer.projLeft();    };\n  fn.projRight   = function () { return this._renderer.projRight();   };\n  fn.projTop     = function () { return this._renderer.projTop();     };\n  fn.projBottom  = function () { return this._renderer.projBottom();  };\n  fn.projFov     = function () { return this._renderer.projFov();     };\n  fn.projHfov    = function () { return this._renderer.projHfov();    };\n\n  // ── _buildBag ─────────────────────────────────────────────────────────────\n  //   Builds the matrices bag for _mapLocation / _mapDirection.\n  //   from / to: space-string constant or mat4 for a custom MATRIX frame.\n  //   _wb holds toFrameInv; valid until coreMap* returns.\n\n  function _buildBag(renderer, options, from, to) {\n    const bag = {\n      mat4Proj: _rawMat4(options.mat4Proj) ?? _projMat4(renderer),\n      mat4View: _rawMat4(options.mat4View) ?? _viewMat4(renderer),\n      mat4Eye: null, mat4PV: null, mat4PVInv: null,\n    };\n    let fromStr, toStr;\n    if (from != null && typeof from !== 'string') {\n      bag.fromFrame = _rawMat4(from); fromStr = MATRIX;\n    } else { fromStr = from; }\n    if (to != null && typeof to !== 'string') {\n      const toRaw = _rawMat4(to);\n      mat4Invert(_wb, toRaw);\n      bag.toFrameInv = _wb; bag.toFrame = toRaw; toStr = MATRIX;\n    } else { toStr = to; }\n    return { bag, fromStr, toStr };\n  }\n\n  // ── mapLocation ───────────────────────────────────────────────────────────\n\n  fn.mapLocation = function (...args) { return this._renderer.mapLocation(...args); };\n\n  /**\n   * Map a point between coordinate spaces.\n   *\n   * Hot path (zero-alloc):  pass `opts.out` as a caller-owned buffer.\n   * Ergonomic path:         omit `opts.out`; a fresh p5.Vector is returned.\n   *\n   * @param {Float32Array|number[]|p5.Vector} [point]  Input point. Default: ORIGIN.\n   * @param {{\n   *   out?:       Float32Array | number[] | p5.Vector,\n   *   from?:      string | Float32Array | number[] | p5.Matrix,\n   *   to?:        string | Float32Array | number[] | p5.Matrix,\n   *   mat4Eye?:   Float32Array | number[] | p5.Matrix,\n   *   mat4Proj?:  Float32Array | number[] | p5.Matrix,\n   *   mat4View?:  Float32Array | number[] | p5.Matrix,\n   *   mat4PV?:    Float32Array | number[] | p5.Matrix,\n   *   mat4PVInv?: Float32Array | number[] | p5.Matrix,\n   * }} [opts]\n   * @returns {Float32Array|number[]|p5.Vector}  opts.out if provided, else a fresh p5.Vector.\n   */\n  p5.Renderer3D.prototype.mapLocation = function (...args) {\n    const hasVec = _isVec(args[0]);\n    const point  = hasVec ? args[0] : p5.Tree.ORIGIN;\n    const opts   = (hasVec ? args[1] : args[0]) ?? {};\n\n    const out = _resolveOut(opts);\n\n    const px = point.x ?? point[0] ?? 0;\n    const py = point.y ?? point[1] ?? 0;\n    const pz = point.z ?? point[2] ?? 0;\n\n    let from = opts.from ?? p5.Tree.EYE;\n    let to   = opts.to   ?? p5.Tree.WORLD;\n    if (from === p5.Tree.MODEL) from = _modelMat4(this);\n    if (to   === p5.Tree.MODEL) to   = _modelMat4(this);\n\n    const { bag, fromStr, toStr } = _buildBag(this, opts, from, to);\n\n    if (fromStr === EYE || toStr === EYE ||\n        fromStr === SCREEN || toStr === SCREEN ||\n        fromStr === NDC    || toStr === NDC) {\n      bag.mat4Eye = _rawMat4(opts.mat4Eye) ??\n        (mat4Invert(_wa, bag.mat4View), _wa);\n    }\n    if (toStr === SCREEN || toStr === NDC || fromStr === SCREEN || fromStr === NDC) {\n      bag.mat4PV = _rawMat4(opts.mat4PV) ??\n        (mat4Mul(_pv, bag.mat4Proj, bag.mat4View), _pv);\n      if (fromStr === SCREEN || fromStr === NDC) {\n        bag.mat4PVInv = _rawMat4(opts.mat4PVInv) ??\n          (mat4Invert(_ipv, bag.mat4PV), _ipv);\n      }\n    }\n\n    _vp[0] = 0; _vp[1] = this.height; _vp[2] = this.width; _vp[3] = -this.height;\n\n    const isVecOut = out instanceof p5.Vector;\n    const buf = isVecOut ? _tmp3 : out;\n    _mapLocation(buf, px, py, pz, fromStr, toStr, bag, _vp, _ndcZ);\n    if (isVecOut) { out.x = buf[0]; out.y = buf[1]; out.z = buf[2]; }\n    return out;\n  };\n\n  // ── mapDirection ──────────────────────────────────────────────────────────\n\n  fn.mapDirection = function (...args) { return this._renderer.mapDirection(...args); };\n\n  /**\n   * Map a direction between coordinate spaces.\n   *\n   * Hot path (zero-alloc):  pass `opts.out` as a caller-owned buffer.\n   * Ergonomic path:         omit `opts.out`; a fresh p5.Vector is returned.\n   *\n   * @param {Float32Array|number[]|p5.Vector} [dir]  Input direction. Default: −Z (look direction).\n   * @param {{\n   *   out?:      Float32Array | number[] | p5.Vector,\n   *   from?:     string | Float32Array | number[] | p5.Matrix,\n   *   to?:       string | Float32Array | number[] | p5.Matrix,\n   *   mat4Eye?:  Float32Array | number[] | p5.Matrix,\n   *   mat4Proj?: Float32Array | number[] | p5.Matrix,\n   *   mat4View?: Float32Array | number[] | p5.Matrix,\n   * }} [opts]\n   * @returns {Float32Array|number[]|p5.Vector}  opts.out if provided, else a fresh p5.Vector.\n   */\n  p5.Renderer3D.prototype.mapDirection = function (...args) {\n    const hasVec = _isVec(args[0]);\n    const dir    = hasVec ? args[0] : p5.Tree._k;\n    const opts   = (hasVec ? args[1] : args[0]) ?? {};\n\n    const out = _resolveOut(opts);\n\n    const dx = dir.x ?? dir[0] ?? 0;\n    const dy = dir.y ?? dir[1] ?? 0;\n    const dz = dir.z ?? dir[2] ?? 0;\n\n    let from = opts.from ?? p5.Tree.EYE;\n    let to   = opts.to   ?? p5.Tree.WORLD;\n    if (from === p5.Tree.MODEL) from = _modelMat4(this);\n    if (to   === p5.Tree.MODEL) to   = _modelMat4(this);\n\n    const { bag, fromStr, toStr } = _buildBag(this, opts, from, to);\n\n    bag.mat4Eye = _rawMat4(opts.mat4Eye) ??\n      (mat4Invert(_wa, bag.mat4View), _wa);\n\n    _vp[0] = 0; _vp[1] = this.height; _vp[2] = this.width; _vp[3] = -this.height;\n\n    const isVecOut = out instanceof p5.Vector;\n    const buf = isVecOut ? _tmp3 : out;\n    _mapDirection(buf, dx, dy, dz, fromStr, toStr, bag, _vp, _ndcZ);\n    if (isVecOut) { out.x = buf[0]; out.y = buf[1]; out.z = buf[2]; }\n    return out;\n  };\n\n  // ── pixelRatio ────────────────────────────────────────────────────────────\n\n  /**\n   * World-units-per-pixel at a world position (defaults to camera position).\n   * @param {Float32Array|number[]|p5.Vector} [worldPos]\n   * @param {{ mat4Proj?, mat4View? }} [opts]\n   * @returns {number}\n   */\n  p5.Renderer3D.prototype.pixelRatio = function (worldPos, { mat4Proj, mat4View } = {}) {\n    const proj = _rawMat4(mat4Proj) ?? _projMat4(this);\n    const view = _rawMat4(mat4View) ?? _viewMat4(this);\n    let eyeZ;\n    if (worldPos) {\n      const wx = worldPos.x ?? worldPos[0] ?? 0;\n      const wy = worldPos.y ?? worldPos[1] ?? 0;\n      const wz = worldPos.z ?? worldPos[2] ?? 0;\n      eyeZ = view[2]*wx + view[6]*wy + view[10]*wz + view[14];\n    } else {\n      eyeZ = view[14];\n    }\n    return corePixelRatio(proj, this.height, eyeZ, _ndcZ);\n  };\n  fn.pixelRatio = function (worldPos, opts) { return this._renderer.pixelRatio(worldPos, opts); };\n\n  // ── screenSize ────────────────────────────────────────────────────────────\n\n  /**\n   * Physical canvas size in pixels: [pixelDensity×width, pixelDensity×height].\n   * Use as `u_resolution` for shaders that use `gl_FragCoord.xy`.\n   * @returns {number[]} [w, h]\n   */\n  p5.Renderer3D.prototype.screenSize = function () {\n    const pd = this._pInst.pixelDensity();\n    return [pd * this.width, pd * this.height];\n  };\n  fn.screenSize = function () { return this._renderer.screenSize(); };\n\n  // ── texelSize ─────────────────────────────────────────────────────────────\n\n  /**\n   * Texel size of an image-like object: [1/width, 1/height].\n   * Accepts p5.Image, p5.Framebuffer, p5.Graphics, or any `{ width, height }`.\n   * @param {{ width:number, height:number }} img\n   * @returns {number[]} [1/w, 1/h]\n   */\n  fn.texelSize = function (img) { return [1/img.width, 1/img.height]; };\n}\n","/**\n * @file Visibility — frustum culling bridge: computePlanes, visibility, bounds, distanceToBound.\n * @module p5.tree/visibility\n * @license AGPL-3.0-only\n *\n * Delegates all math to @nakednous/tree. Zero allocations in hot paths.\n *\n * ── Usage pattern ─────────────────────────────────────────────────────────\n *\n *   // setup\n *   m._c1 = new Float32Array(3)\n *   m._c2 = new Float32Array(3)\n *\n *   // draw — zero allocations\n *   m._c1.set([px - hw, py - hh, pz - hd])\n *   m._c2.set([px + hw, py + hh, pz + hd])\n *   m.visibility = p.visibility({ corner1: m._c1, corner2: m._c2 })\n *\n * ── Sign contract ─────────────────────────────────────────────────────────\n *\n * Frustum extents are near-plane coordinates in camera space (y-up, z into\n * screen):\n *\n *   top    > 0   bottom < 0   (y axis)\n *   right  > 0   left   < 0   (x axis)\n *   near, far > 0              (positive distances along −z)\n *\n * All of frustumPlanes, viewFrustum, projTop/projBottom, projLeft/projRight,\n * mat4Proj, mat4Ortho, and p5 v2's frustum()/ortho() share this contract.\n * p5 v2 call order: frustum(left, right, bottom, top, near, far).\n */\n\n'use strict';\n\nimport {\n  mat4Invert, mat4MulPoint,\n  projIsOrtho, projNear, projFar,\n  projLeft, projRight, projTop, projBottom,\n  frustumPlanes,\n  pointVisibility, sphereVisibility, boxVisibility,\n} from '@nakednous/tree';\n\nimport { getNdcZ } from './matrix.js';\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Module-level working buffers — never returned to caller\n// ═══════════════════════════════════════════════════════════════════════════\n\nconst _eye    = new Float32Array(16);  // eye matrix scratch for computePlanes\nconst _planes = new Float64Array(24);  // 6 frustum planes × [a,b,c,d]\nconst _tMin   = new Float32Array(3);   // transformed AABB min scratch\nconst _tMax   = new Float32Array(3);   // transformed AABB max scratch\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Local p5 state accessors\n// ═══════════════════════════════════════════════════════════════════════════\n\nconst _rawMat4  = (m) => (m != null && m.mat4 != null) ? m.mat4 : m;\nconst _projMat4 = (r) => r.states.uPMatrix.mat4;\nconst _viewMat4 = (r) => r.states.curCamera.cameraMatrix.mat4;\n\n// ═══════════════════════════════════════════════════════════════════════════\n// computePlanes — exported for gizmos (viewFrustum); not part of public API\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Fill the module-level _planes buffer from the current renderer state.\n * @param {p5.Renderer3D} renderer\n * @param {Float32Array}  [eRaw]  Pre-computed eye matrix — skips inversion.\n * @returns {Float64Array} _planes\n */\nexport function computePlanes(renderer, eRaw) {\n  const view = _viewMat4(renderer);\n  const e    = eRaw ?? (mat4Invert(_eye, view), _eye);\n  const proj = _projMat4(renderer);\n  const ndcZ = getNdcZ();\n  frustumPlanes(\n    _planes,\n    e[12], e[13], e[14],\n    -e[8], -e[9], -e[10],\n     e[4],  e[5],  e[6],\n     e[0],  e[1],  e[2],\n    projIsOrtho(proj),\n    projNear(proj, ndcZ), projFar(proj),\n    projLeft(proj, ndcZ), projRight(proj, ndcZ),\n    projTop(proj, ndcZ),  projBottom(proj, ndcZ)\n  );\n  return _planes;\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Install\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Install visibility helpers on fn and p5.Renderer3D.\n * @param {p5}    p5\n * @param {Object} fn  p5 prototype.\n */\nexport function installVisibility(p5, fn) {\n\n  // ── Public forwarders ─────────────────────────────────────────────────────\n\n  fn.visibility      = function (...args) { return this._renderer.visibility(...args); };\n  fn.bounds          = function (opts)    { return this._renderer.bounds(opts); };\n  fn.distanceToBound = function (...args) { return this._renderer.distanceToBound(...args); };\n\n  // ── Argument parser ───────────────────────────────────────────────────────\n\n  p5.Renderer3D.prototype._parseVisibilityArgs = function (...args) {\n    let corner1, corner2, center, radius, pendingRadius, bounds, mat4Model;\n    const vecs = [];\n    const isPlainObject = v => {\n      if (!v || typeof v !== 'object') return false;\n      if (Array.isArray(v) || ArrayBuffer.isView(v)) return false;\n      return Object.getPrototypeOf(v) === Object.prototype;\n    };\n    for (const arg of args) {\n      if (arg instanceof p5.Vector || Array.isArray(arg) || ArrayBuffer.isView(arg)) {\n        vecs.push(arg); continue;\n      }\n      if (typeof arg === 'number' && Number.isFinite(arg) && radius === undefined) {\n        center ? (radius = arg) : (pendingRadius = arg); continue;\n      }\n      if (isPlainObject(arg)) {\n        if ('corner1' in arg || 'corner2' in arg || 'center' in arg ||\n            'radius'  in arg || 'bounds'  in arg) {\n          corner1   = arg.corner1 ?? corner1; corner2 = arg.corner2 ?? corner2;\n          center    = arg.center  ?? center;  radius  = arg.radius  ?? radius;\n          bounds    = arg.bounds  ?? bounds;\n          mat4Model = arg.mat4Model ?? mat4Model;\n        } else { bounds = arg; }\n      }\n    }\n    if (!corner1 && !corner2) {\n      if (!center && vecs.length === 1) { center = vecs[0]; }\n      else if (vecs.length >= 2) { corner1 = vecs[0]; corner2 = vecs[1]; }\n    }\n    if (radius === undefined && pendingRadius !== undefined && center) { radius = pendingRadius; }\n    return { corner1, corner2, center, radius, bounds, mat4Model };\n  };\n\n  // ── visibility ────────────────────────────────────────────────────────────\n  \n  /**\n   * Test visibility of a point, sphere, or AABB against the view frustum.\n   *\n   * Three query forms:\n   *   visibility({ corner1, corner2 })          // axis-aligned box\n   *   visibility({ center, radius })            // sphere\n   *   visibility({ center })                    // point\n   *\n   * All corner/center values accept Float32Array(3), plain array, or p5.Vector.\n   *\n   * ── mat4Model (optional) ────────────────────────────────────────────────────\n   * When supplied, transforms bounds from local/object space to world space\n   * before the frustum test. Accepts Float32Array(16) | ArrayLike | p5.Matrix.\n   * Useful when bounds are defined in object space and the model matrix is\n   * available without a push()/pop() context — mirrors the mat4Model option\n   * already accepted by axes(), bullsEye(), and pointerHit().\n   *\n   *   AABB  → all 8 corners transformed; result is a conservative world-space\n   *           AABB (larger than tight OBB — correct for culling, never false negative).\n   *   Sphere → center transformed; radius scaled by max column length\n   *            (conservative under non-uniform scale).\n   *   Point  → straight mat4 × point.\n   *\n   * ── Performance notes ───────────────────────────────────────────────────────\n   * Fast path (no `bounds` option): calls core boxVisibility / sphereVisibility /\n   * pointVisibility directly — zero allocations per call.\n   * Fallback (user-supplied `bounds` object): scalar arithmetic on the keyed\n   * plane object.\n   *\n   * @method visibility\n   * @for p5\n   * @param {{\n   *   corner1?:   Float32Array | ArrayLike | p5.Vector,\n   *   corner2?:   Float32Array | ArrayLike | p5.Vector,\n   *   center?:    Float32Array | ArrayLike | p5.Vector,\n   *   radius?:    number,\n   *   bounds?:    object,\n   *   mat4Model?: Float32Array | ArrayLike | p5.Matrix,\n   * }} opts\n   * @returns {number} p5.Tree.VISIBLE | SEMIVISIBLE | INVISIBLE\n   */\n  p5.Renderer3D.prototype.visibility = function (...args) {\n    const { corner1, corner2, center, radius, bounds: userBounds, mat4Model } = this._parseVisibilityArgs(...args);\n    \n    // ── Optional model-space → world-space transform ──────────────────────\n    // If mat4Model supplied, transform bounds before frustum test.\n    // AABB: transform all 8 corners, recompute conservative AABB (zero-alloc).\n    // Sphere: transform center; scale radius by max column length.\n    // Point: straight mat4MulPoint.\n    let c1 = corner1, c2 = corner2, ct = center, rt = radius;\n    if (mat4Model != null) {\n      const m = _rawMat4(mat4Model);\n      if (m != null) {\n        if (c1 && c2) {\n          // Transform 8 AABB corners, find new min/max\n          const x0 = c1.x ?? c1[0] ?? 0, y0 = c1.y ?? c1[1] ?? 0, z0 = c1.z ?? c1[2] ?? 0;\n          const x1 = c2.x ?? c2[0] ?? 0, y1 = c2.y ?? c2[1] ?? 0, z1 = c2.z ?? c2[2] ?? 0;\n          _tMin[0] =  Infinity; _tMin[1] =  Infinity; _tMin[2] =  Infinity;\n          _tMax[0] = -Infinity; _tMax[1] = -Infinity; _tMax[2] = -Infinity;\n          for (let i = 0; i < 8; i++) {\n            const cx = (i & 4) ? x0 : x1;\n            const cy = (i & 2) ? y0 : y1;\n            const cz = (i & 1) ? z0 : z1;\n            mat4MulPoint(_tMin, m, [cx, cy, cz]);   // reuse _tMin as temp\n            if (_tMin[0] < _tMax[0] || i === 0) {}  // update min/max below\n            // ── inline to avoid a second scratch ─────────────────────────\n            const tx = m[0]*cx + m[4]*cy + m[8]*cz  + m[12];\n            const tw = m[3]*cx + m[7]*cy + m[11]*cz + m[15];\n            const ty = m[1]*cx + m[5]*cy + m[9]*cz  + m[13];\n            const tz = m[2]*cx + m[6]*cy + m[10]*cz + m[14];\n            const wx = tx/tw, wy = ty/tw, wz = tz/tw;\n            if (i === 0 || wx < _tMin[0]) _tMin[0] = wx;\n            if (i === 0 || wy < _tMin[1]) _tMin[1] = wy;\n            if (i === 0 || wz < _tMin[2]) _tMin[2] = wz;\n            if (i === 0 || wx > _tMax[0]) _tMax[0] = wx;\n            if (i === 0 || wy > _tMax[1]) _tMax[1] = wy;\n            if (i === 0 || wz > _tMax[2]) _tMax[2] = wz;\n          }\n          c1 = _tMin; c2 = _tMax;\n        } else if (ct) {\n          // Transform center\n          const cx = ct.x ?? ct[0] ?? 0;\n          const cy = ct.y ?? ct[1] ?? 0;\n          const cz = ct.z ?? ct[2] ?? 0;\n          const tw = m[3]*cx + m[7]*cy + m[11]*cz + m[15];\n          _tMin[0] = (m[0]*cx + m[4]*cy + m[8]*cz  + m[12]) / tw;\n          _tMin[1] = (m[1]*cx + m[5]*cy + m[9]*cz  + m[13]) / tw;\n          _tMin[2] = (m[2]*cx + m[6]*cy + m[10]*cz + m[14]) / tw;\n          ct = _tMin;\n          if (rt != null) {\n            // Scale radius by max column length (conservative under non-uniform scale)\n            const s0 = Math.sqrt(m[0]*m[0] + m[1]*m[1] + m[2]*m[2]);\n            const s1 = Math.sqrt(m[4]*m[4] + m[5]*m[5] + m[6]*m[6]);\n            const s2 = Math.sqrt(m[8]*m[8] + m[9]*m[9] + m[10]*m[10]);\n            rt = rt * Math.max(s0, s1, s2);\n          }\n        }\n      }\n    }\n\n    if (!userBounds) {\n      const planes = computePlanes(this);\n      if (ct) {\n        const cx = ct.x ?? ct[0] ?? 0;\n        const cy = ct.y ?? ct[1] ?? 0;\n        const cz = ct.z ?? ct[2] ?? 0;\n        return rt != null\n          ? sphereVisibility(planes, cx, cy, cz, rt)\n          : pointVisibility(planes, cx, cy, cz);\n      }\n      if (c1 && c2) {\n        return boxVisibility(\n          planes,\n          c1.x ?? c1[0] ?? 0, c1.y ?? c1[1] ?? 0, c1.z ?? c1[2] ?? 0,\n          c2.x ?? c2[0] ?? 0, c2.y ?? c2[1] ?? 0, c2.z ?? c2[2] ?? 0\n        );\n      }\n      console.error('[p5.tree] visibility: could not parse query.');\n      return p5.Tree.INVISIBLE;\n    }\n\n    // ── Fallback: user-supplied keyed bounds ───────────────────────────────\n    if (ct) {\n      return rt != null\n        ? this._ballVisibility(ct, rt, userBounds)\n        : this._pointVisibility(ct, userBounds);\n    }\n    if (c1 && c2) return this._boxVisibility(c1, c2, userBounds);\n    console.error('[p5.tree] visibility: could not parse query.');\n    return p5.Tree.INVISIBLE;\n  };\n\n  // ── Keyed-bounds visibility helpers (fallback path) ───────────────────────\n\n  p5.Renderer3D.prototype._pointVisibility = function (point, bounds) {\n    const px = point.x ?? point[0] ?? 0;\n    const py = point.y ?? point[1] ?? 0;\n    const pz = point.z ?? point[2] ?? 0;\n    for (const key in bounds) {\n      const { a, b, c, d } = bounds[key];\n      const dist = a * px + b * py + c * pz - d;\n      if (dist > 0)   return p5.Tree.INVISIBLE;\n      if (dist === 0) return p5.Tree.SEMIVISIBLE;\n    }\n    return p5.Tree.VISIBLE;\n  };\n\n  p5.Renderer3D.prototype._ballVisibility = function (center, radius, bounds) {\n    const cx = center.x ?? center[0] ?? 0;\n    const cy = center.y ?? center[1] ?? 0;\n    const cz = center.z ?? center[2] ?? 0;\n    let allIn = true;\n    for (const key in bounds) {\n      const { a, b, c, d } = bounds[key];\n      const dist = a * cx + b * cy + c * cz - d;\n      if (dist > radius)              return p5.Tree.INVISIBLE;\n      if (dist > 0 || -dist < radius) allIn = false;\n    }\n    return allIn ? p5.Tree.VISIBLE : p5.Tree.SEMIVISIBLE;\n  };\n\n  p5.Renderer3D.prototype._boxVisibility = function (corner1, corner2, bounds) {\n    const x0 = corner1.x ?? corner1[0] ?? 0, y0 = corner1.y ?? corner1[1] ?? 0, z0 = corner1.z ?? corner1[2] ?? 0;\n    const x1 = corner2.x ?? corner2[0] ?? 0, y1 = corner2.y ?? corner2[1] ?? 0, z1 = corner2.z ?? corner2[2] ?? 0;\n    let allIn = true;\n    for (const key in bounds) {\n      const { a, b, c, d } = bounds[key];\n      let allOut = true;\n      for (let corner = 0; corner < 8; corner++) {\n        const cx = (corner & 4) ? x0 : x1;\n        const cy = (corner & 2) ? y0 : y1;\n        const cz = (corner & 1) ? z0 : z1;\n        if (a * cx + b * cy + c * cz - d > 0) { allIn  = false; }\n        else                                   { allOut = false; }\n      }\n      if (allOut) return p5.Tree.INVISIBLE;\n    }\n    return allIn ? p5.Tree.VISIBLE : p5.Tree.SEMIVISIBLE;\n  };\n\n  // ── bounds ────────────────────────────────────────────────────────────────\n\n  /**\n   * Compute the six view-frustum planes as a keyed object.\n   *\n   * Returns `{ [LEFT|RIGHT|NEAR|FAR|TOP|BOTTOM]: { a, b, c, d } }`.\n   * For per-object visibility tests prefer calling `visibility()` directly —\n   * its fast path bypasses this object entirely.\n   *\n   * @method bounds\n   * @for p5\n   * @param {{ mat4Eye?: Float32Array | ArrayLike | p5.Matrix }} [opts]\n   * @returns {object}\n   */\n  p5.Renderer3D.prototype.bounds = function ({ mat4Eye } = {}) {\n    const eRaw = _rawMat4(mat4Eye) ?? (mat4Invert(_eye, _viewMat4(this)), _eye);\n    computePlanes(this, eRaw);\n    const keys   = [p5.Tree.LEFT, p5.Tree.RIGHT, p5.Tree.NEAR, p5.Tree.FAR, p5.Tree.TOP, p5.Tree.BOTTOM];\n    const result = {};\n    for (let i = 0; i < 6; i++) {\n      const b = i * 4;\n      result[keys[i]] = { a: _planes[b], b: _planes[b+1], c: _planes[b+2], d: _planes[b+3] };\n    }\n    return result;\n  };\n\n  // ── distanceToBound ───────────────────────────────────────────────────────\n\n  /**\n   * Signed distance from a point to one frustum plane.\n   * Positive → outside (invisible side).\n   *\n   * @method distanceToBound\n   * @for p5\n   * @param {ArrayLike|p5.Vector} point\n   * @param {number|string} key  p5.Tree plane constant (LEFT, RIGHT, NEAR, FAR, TOP, BOTTOM).\n   * @param {object} [bounds]    Keyed bounds object. Defaults to current frustum.\n   * @returns {number}\n   */\n  p5.Renderer3D.prototype.distanceToBound = function (...args) {\n    let point, key, bounds;\n    for (const arg of args) {\n      if (Array.isArray(arg) || ArrayBuffer.isView(arg) || arg instanceof p5.Vector) { point = arg; }\n      else if (typeof arg === 'string' || typeof arg === 'number') { key = arg; }\n      else if (arg && typeof arg === 'object') { bounds = arg; }\n    }\n    if (!point || key === undefined) {\n      console.error('[p5.tree] distanceToBound: could not parse query.'); return 0;\n    }\n    const { a, b, c, d } = (bounds ?? this.bounds())[key];\n    const px = point.x ?? point[0] ?? 0;\n    const py = point.y ?? point[1] ?? 0;\n    const pz = point.z ?? point[2] ?? 0;\n    return a * px + b * py + c * pz - d;\n  };\n}\n","/**\n * @file Gizmos — scene-space diagnostic helpers.\n * @module p5.tree/gizmos\n * @license AGPL-3.0-only\n *\n * axes        — coordinate frame (X/Y/Z, optional labels), semantic colouring\n * grid        — ground plane\n * cross       — screen-space crosshair centred on current model origin\n * bullsEye    — screen-space bulls-eye centred on current model origin\n * plane       — (native p5) axis-aligned plane at model origin\n * pane        — textured/untextured quad primitive (4 corners, optional UVs)\n * viewFrustum — another renderer's view frustum drawn in this renderer; NEAR\n *               and FAR planes optionally textured (e.g. the scene rendered\n *               from that camera) to visualise projection as a projection\n *               ONTO the frustum plane\n * hermite     — a single Hermite segment given endpoints and tangents\n * trackPath   — PoseTrack / CameraTrack path + control polygon + tangents +\n *               per-keyframe marker (pluggable via opts.marker)\n *\n * Depends on p5.tree/hud (beginHUD / endHUD), p5.tree/matrix (mapLocation,\n * pixelRatio, p5.Tree constants), and p5.tree/visibility (computePlanes).\n */\n\n'use strict';\n\nimport {\n  projIsOrtho, projNear, projFar,\n  projLeft, projRight, projTop, projBottom,\n  hermiteVec3,\n  mat4Eye  as _mat4Eye,\n  mat4Persp as _mat4Persp,\n  mat4Ortho as _mat4Ortho,\n} from '@nakednous/tree';\n\nimport { getNdcZ } from './matrix.js';\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Module-level working buffers — never returned to caller\n// ═══════════════════════════════════════════════════════════════════════════\n\nconst _sl    = new Float32Array(3);\nconst _wl    = new Float32Array(3);\nconst _eye   = new Float32Array(16);\nconst _proj  = new Float32Array(16);\n\n// Scratch pose for viewFrustum's polymorphic camera dispatch — populated\n// from a CameraTrack via track.eval(out), or normalised from a user-supplied\n// pose spec, then consumed by _buildEyeFromPose / _buildProjFromPose.\nconst _vfPose = {\n  eye:   [0,0,0], center: [0,0,0], up: [0,1,0],\n  fov:   null,    halfHeight: null,\n  near:  0.1,     far: 1000,\n};\n\n// trackPath sample buffers\nconst _sp    = new Float32Array(3);\nconst _prev  = new Float32Array(3);\nconst _tIn   = new Float32Array(3);\nconst _tOut  = new Float32Array(3);\nconst _kfEye = new Float32Array(16);\n\n// Default UVs for pane() — frozen so the fallback path allocates nothing.\n// Layout: p0 top-left, p1 top-right, p2 bottom-right, p3 bottom-left.\nconst _DEFAULT_UVS = Object.freeze([\n  Object.freeze([0, 0]),\n  Object.freeze([1, 0]),\n  Object.freeze([1, 1]),\n  Object.freeze([0, 1]),\n]);\n\n// V-flipped UVs for framebuffer color attachments — their rendered contents\n// are stored bottom-up in texture space (WebGL convention), so sampling with\n// the default top-down UVs produces an inverted image relative to image() and\n// to geometry in the main view. Per p5's own framebuffer docs: \"By default,\n// a framebuffer's y-coordinates are flipped compared to images and videos.\"\nconst _FBO_UVS = Object.freeze([\n  Object.freeze([0, 1]),\n  Object.freeze([1, 1]),\n  Object.freeze([1, 0]),\n  Object.freeze([0, 0]),\n]);\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Local p5 state accessors\n// ═══════════════════════════════════════════════════════════════════════════\n\nconst _rawMat4   = (m) => (m != null && m.mat4 != null) ? m.mat4 : m;\nconst _projMat4  = (r) => r.states.uPMatrix.mat4;\nconst _viewMat4  = (r) => r.states.curCamera.cameraMatrix.mat4;\nconst _modelMat4 = (r) => r.states.uModelMatrix.mat4;\n\nconst _AXIS_COLORS = ['Red', 'Lime', 'DodgerBlue'];\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Polymorphic camera resolution for viewFrustum\n// ═══════════════════════════════════════════════════════════════════════════\n//\n// `viewFrustum({ camera })` accepts three input shapes:\n//\n//   p5.Camera         — read pose + projection from the camera directly\n//   CameraTrack       — sample track at the cursor (track.eval + track.mat4Eye)\n//   pose spec object  — { eye, center?, up?, fov?, halfHeight?, near?, far? },\n//                       same shape capturePose() and CameraTrack.add() use\n//\n// Detection is duck-typed on the public surface of each input — we test for\n// the methods we'd actually call rather than instanceof, so the contract is\n// \"looks like X\" rather than \"is exactly X\". Two consequences:\n//\n//   * a third-party object that implements .eval(poseOut) + .mat4Eye(out) +\n//     keyframes[] will be detected as a CameraTrack and animate correctly\n//   * a plain object literal with .eye is treated as a pose spec\n//\n// Order matters: track detection runs first because a track has an .eye\n// keyframe in keyframes[0] which would otherwise satisfy the spec heuristic.\n\n/**\n * @returns {boolean} true if `c` looks like a CameraTrack (cursor + lookat samplers).\n */\nfunction _isCameraTrack(c) {\n  return !!c\n      && typeof c.eval === 'function'\n      && typeof c.mat4Eye === 'function'\n      && Array.isArray(c.keyframes);\n}\n\n/**\n * @returns {boolean} true if `c` looks like a p5.Camera (renderer-bound matrix readers).\n */\nfunction _isP5Camera(c) {\n  return !!c\n      && typeof c.mat4Eye === 'function'\n      && typeof c.mat4Proj === 'function'\n      && !Array.isArray(c.keyframes);   // disambiguate from CameraTrack\n}\n\n/**\n * @returns {boolean} true if `c` is a plain pose spec (has .eye but no methods).\n */\nfunction _isPoseSpec(c) {\n  return !!c && Array.isArray(c.eye);\n}\n\n/**\n * Build the eye→world matrix from a pose spec via the lookAt constructor.\n * Defaults applied: center=[0,0,0], up=[0,1,0].\n * @param {Object} pose  { eye, center?, up? }\n * @param {Float32Array} out  16-element destination.\n */\nfunction _buildEyeFromPose(pose, out) {\n  const e = pose.eye;\n  const c = pose.center || [0, 0, 0];\n  const u = pose.up     || [0, 1, 0];\n  return _mat4Eye(out, e[0], e[1], e[2], c[0], c[1], c[2], u[0], u[1], u[2]);\n}\n\n/**\n * Build the projection matrix from a pose spec's lens fields.\n * Aspect comes from the renderer (ambient state, parallel to textureMode).\n * Defaults applied: fov = π/3 if neither fov nor halfHeight, near = 0.1, far = 1000.\n * ndcYSign is hardcoded to -1 to match p5 v2's WEBGL Camera.perspective/ortho\n * convention (p[5] < 0). WEBGPU testing pending.\n * @param {Object} pose  { fov?, halfHeight?, near?, far? }\n * @param {number} aspect  width / height of the rendering surface.\n * @param {number} ndcZMin\n * @param {Float32Array} out  16-element destination.\n */\nfunction _buildProjFromPose(pose, aspect, ndcZMin, out) {\n  const near = pose.near ?? 0.1;\n  const far  = pose.far  ?? 1000;\n  if (typeof pose.halfHeight === 'number') {\n    const top    = pose.halfHeight;\n    const right  = top * aspect;\n    return _mat4Ortho(out, -right, right, -top, top, near, far, ndcZMin, -1);\n  }\n  const fov   = (typeof pose.fov === 'number') ? pose.fov : Math.PI / 3;\n  const top   = near * Math.tan(fov * 0.5);\n  const right = top * aspect;\n  return _mat4Persp(out, -right, right, -top, top, near, far, ndcZMin, -1);\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Install\n// ═══════════════════════════════════════════════════════════════════════════\n\nexport function installGizmos(p5, fn) {\n\n  // ── Axes ──────────────────────────────────────────────────────────────────\n\n  fn.axes = function (opts) { this._renderer.axes(opts); return this; };\n\n  /**\n   * Draw a 3D coordinate frame at the current model origin.\n   *\n   * Colouring:\n   *   semantic: true  (default) — X red, Y lime, Z blue; labels inherit axis colour.\n   *   semantic: false           — every axis and label uses ambient stroke.\n   *\n   * @param {{ size?: number, semantic?: boolean, bits?: number }} [opts]\n   */\n  p5.Renderer3D.prototype.axes = function ({\n    size     = 100,\n    semantic = true,\n    bits     = p5.Tree.LABELS | p5.Tree.X | p5.Tree.Y | p5.Tree.Z\n  } = {}) {\n    const p = this._pInst;\n    if (!p) return;\n\n    const setAxis = semantic ? (i) => p.stroke(_AXIS_COLORS[i]) : (_i) => {};\n\n    p.push();\n    if ((bits & p5.Tree.LABELS) !== 0) {\n      const cw = size/40, ch = size/30, cs = 1.04*size;\n      setAxis(0);\n      p.line(cs,  cw, -ch, cs, -cw,  ch);\n      p.line(cs, -cw, -ch, cs,  cw,  ch);\n      setAxis(1);\n      p.line( cw, cs,  ch,  0, cs,   0);\n      p.line(  0, cs,   0, -cw, cs,  ch);\n      p.line(-cw, cs,  ch,  0, cs,   0);\n      p.line(  0, cs,   0,  0, cs, -ch);\n      setAxis(2);\n      p.line(-cw, -ch, cs,  cw, -ch, cs);\n      p.line( cw, -ch, cs, -cw,  ch, cs);\n      p.line(-cw,  ch, cs,  cw,  ch, cs);\n    }\n    setAxis(0);\n    (bits & p5.Tree.X)  !== 0 && p.line(0,0,0,  size,0,0);\n    (bits & p5.Tree._X) !== 0 && p.line(0,0,0, -size,0,0);\n    setAxis(1);\n    (bits & p5.Tree.Y)  !== 0 && p.line(0,0,0, 0, size,0);\n    (bits & p5.Tree._Y) !== 0 && p.line(0,0,0, 0,-size,0);\n    setAxis(2);\n    (bits & p5.Tree.Z)  !== 0 && p.line(0,0,0, 0,0, size);\n    (bits & p5.Tree._Z) !== 0 && p.line(0,0,0, 0,0,-size);\n    p.pop();\n  };\n\n  // ── Grid ──────────────────────────────────────────────────────────────────\n\n  fn.grid = function (opts) { this._renderer.grid(opts); return this; };\n\n  p5.Renderer3D.prototype.grid = function ({ size = 100, subdivisions = 10 } = {}) {\n    const p = this._pInst;\n    if (!p) return;\n    subdivisions = Math.max(1, subdivisions);\n    p.push();\n    for (let i = 0; i <= subdivisions; ++i) {\n      const pos = size * (2*i/subdivisions - 1);\n      p.line(pos, -size, 0, pos, +size, 0);\n      p.line(-size, pos, 0, +size, pos, 0);\n    }\n    p.pop();\n  };\n\n  // ── Circle primitive ──────────────────────────────────────────────────────\n\n  p5.Renderer3D.prototype._circle = function ({\n    filled = false, x = this.width/2, y = this.height/2, radius = 100, detail = 50\n  } = {}) {\n    const p = this._pInst;\n    if (!p) return;\n    p.push(); p.translate(x, y);\n    if (filled) {\n      p.beginShape(p.TRIANGLE_STRIP);\n      for (let t = 0; t <= detail; t++) {\n        const cx = Math.cos(t*(2*Math.PI)/detail), cy = Math.sin(t*(2*Math.PI)/detail);\n        p.vertex(0, 0, 0, 0.5, 0.5);\n        p.vertex(radius*cx, radius*cy, 0, cx*0.5+0.5, cy*0.5+0.5);\n      }\n      p.endShape();\n    } else {\n      const angle = (2*Math.PI)/detail;\n      let lx = radius, ly = 0;\n      for (let i = 1; i <= detail; i++) {\n        const nx = Math.cos(i*angle)*radius, ny = Math.sin(i*angle)*radius;\n        p.line(lx, ly, nx, ny); lx = nx; ly = ny;\n      }\n    }\n    p.pop();\n  };\n\n  // ── Cross ─────────────────────────────────────────────────────────────────\n\n  fn.cross = function (opts) { this._renderer.cross(opts); return this; };\n\n  p5.Renderer3D.prototype.cross = function ({\n    mat4Model, x, y, size = 50, mat4Eye, mat4Proj, mat4View, mat4PV\n  } = {}) {\n    const p = this._pInst;\n    if (!p) return;\n    const mm = _rawMat4(mat4Model) ?? _modelMat4(this);\n    if (x == null || y == null) {\n      this.mapLocation(p5.Tree.ORIGIN, { from: mm, to: p5.Tree.SCREEN, out: _sl, mat4Proj, mat4View, mat4PV });\n      x = _sl[0]; y = _sl[1];\n      this.mapLocation(p5.Tree.ORIGIN, { from: mm, to: p5.Tree.WORLD, out: _wl, mat4Eye });\n      size = size / this.pixelRatio(_wl);\n    }\n    const half = size / 2;\n    this.beginHUD();\n    p.line(x-half, y, x+half, y);\n    p.line(x, y-half, x, y+half);\n    this.endHUD();\n  };\n\n  // ── BullsEye ──────────────────────────────────────────────────────────────\n\n  fn.bullsEye = function (opts) { this._renderer.bullsEye(opts); return this; };\n\n  p5.Renderer3D.prototype.bullsEye = function ({\n    mat4Model, x, y, size = 50, shape = p5.Tree.CIRCLE,\n    mat4Eye, mat4Proj, mat4View, mat4PV\n  } = {}) {\n    const p = this._pInst;\n    if (!p) return;\n    const mm = _rawMat4(mat4Model) ?? _modelMat4(this);\n    if (x == null || y == null) {\n      this.mapLocation(p5.Tree.ORIGIN, { from: mm, to: p5.Tree.SCREEN, out: _sl, mat4Proj, mat4View, mat4PV });\n      x = _sl[0]; y = _sl[1];\n      this.mapLocation(p5.Tree.ORIGIN, { from: mm, to: p5.Tree.WORLD, out: _wl, mat4Eye });\n      size = size / this.pixelRatio(_wl);\n    }\n    const half = size/2, corner = 0.6*half;\n    this.beginHUD();\n    if (shape === p5.Tree.CIRCLE) {\n      this._circle({ x, y, radius: half });\n    } else {\n      p.line(x-half, y-half+corner, x-half, y-half);\n      p.line(x-half, y-half, x-half+corner, y-half);\n      p.line(x+half-corner, y-half, x+half, y-half);\n      p.line(x+half, y-half, x+half, y-half+corner);\n      p.line(x+half, y+half-corner, x+half, y+half);\n      p.line(x+half, y+half, x+half-corner, y+half);\n      p.line(x-half+corner, y+half, x-half, y+half);\n      p.line(x-half, y+half, x-half, y+half-corner);\n    }\n    const ch = 0.6*half;\n    p.line(x-ch, y, x+ch, y);\n    p.line(x, y-ch, x, y+ch);\n    this.endHUD();\n  };\n\n  // ── pane — atomic textured quad primitive ─────────────────────────────────\n  //\n  // \"pane\" as in window pane — a bounded flat quad, optionally textured.\n  // Distinct from p5's native `plane(w, h)` (axis-aligned at origin) by\n  // name AND signature: `pane` takes four 3D corner points. Used\n  // internally by `viewFrustum` for NEAR / FAR / BODY quads and by the\n  // default `CameraTrack` marker for the per-keyframe near plane.\n\n  fn.pane = function (p0, p1, p2, p3, opts) {\n    this._renderer.pane(p0, p1, p2, p3, opts);\n    return this;\n  };\n\n  /**\n   * Draw a textured or untextured quad from four 3D corner points.\n   *\n   * Corners are consumed in the order given — counter-clockwise when\n   * viewed from the intended front face yields outward-facing normals.\n   * Default UVs place the texture origin at p0 and (1,1) at p2:\n   *\n   *     p0 ──── p1        uv (0,0) ──── (1,0)\n   *      │       │                │         │\n   *      │       │                │         │\n   *     p3 ──── p2        uv (0,1) ──── (1,1)\n   *\n   * `texture` accepts anything p5's `texture()` accepts — `p5.Framebuffer`,\n   * `p5.Image`, `p5.Graphics`, `p5.Texture`. push/pop isolates the\n   * texture state so it doesn't leak into subsequent draws. `uvs`\n   * overrides the default layout — supply four [u,v] pairs in p0..p3\n   * order.\n   *\n   *     pane([-100,-100,0], [100,-100,0], [100,100,0], [-100,100,0])\n   *     pane(tl, tr, br, bl, { texture: myFbo })\n   *     pane(tl, tr, br, bl, { texture: myImg, uvs: [[0,1],[1,1],[1,0],[0,0]] })\n   *\n   * @method pane\n   * @for p5\n   * @param {number[]} p0,p1,p2,p3  Corner positions (CCW when viewed from front).\n   * @param {{ texture?:*, uvs?:number[][] }} [opts]\n   */\n  p5.Renderer3D.prototype.pane = function (p0, p1, p2, p3, { texture = null, uvs = null } = {}) {\n    const p = this._pInst;\n    if (!p) return;\n    // Default UV selection:\n    //   - Explicit `uvs` — always wins (user knows what they want).\n    //   - p5.FramebufferTexture (fbo.color) — V-flipped to match image() /\n    //     geometry orientation. p5 stores FBO color textures bottom-up;\n    //     sampling with top-down UVs produces an inverted image.\n    //   - Everything else — top-down UVs.\n    const u = uvs\n      || (texture instanceof p5.FramebufferTexture ? _FBO_UVS : _DEFAULT_UVS);\n    // p5's default textureMode is IMAGE (UVs in pixel space). Our default\n    // and FBO UVs are normalized 0..1, so we switch to NORMAL while drawing.\n    // Save/restore explicitly: per p5 v2's push() docs, textureMode is NOT\n    // in the list of state that push/pop saves (rectMode and ellipseMode\n    // are, but textureMode is not). Without this dance the NORMAL mode\n    // leaks to subsequent draws — a following image() call interprets its\n    // IMAGE-mode UVs against the lingering NORMAL setting and crashes\n    // inside _setFillUniforms.\n    const prevMode = this.states.textureMode;\n    p.push();\n    if (texture) {\n      p.textureMode(p.NORMAL);\n      p.texture(texture);\n    }\n    this.beginShape();\n    this.vertex(p0[0], p0[1], p0[2], u[0][0], u[0][1]);\n    this.vertex(p1[0], p1[1], p1[2], u[1][0], u[1][1]);\n    this.vertex(p2[0], p2[1], p2[2], u[2][0], u[2][1]);\n    this.vertex(p3[0], p3[1], p3[2], u[3][0], u[3][1]);\n    this.endShape(p.CLOSE);\n    p.pop();\n    this.states.textureMode = prevMode;\n  };\n\n  // ── View frustum ──────────────────────────────────────────────────────────\n\n  fn.viewFrustum = function (opts) { this._renderer.viewFrustum(opts); return this; };\n\n  /**\n   * Draw the view frustum of a secondary camera into this renderer.\n   *\n   * `camera` accepts three forms:\n   *   p5.Camera         — eye and projection read via cam.mat4Eye / cam.mat4Proj.\n   *   CameraTrack       — sampled at the cursor via track.eval + track.mat4Eye.\n   *                       The frustum animates with the track's playback.\n   *   pose spec object  — { eye, center?, up?, fov?, halfHeight?, near?, far? },\n   *                       same shape capturePose() and CameraTrack.add() use.\n   *                       Defaults: center=[0,0,0], up=[0,1,0], near=0.1, far=1000,\n   *                       fov=π/3 if neither fov nor halfHeight is set.\n   *\n   * Alternatively pass explicit `mat4Eye` + `mat4Proj` buffers. `mat4View`\n   * defaults to the current renderer's view — override when drawing from a\n   * third viewpoint.\n   *\n   * `bits` selects which parts render:\n   *   NEAR  — near plane (as closed shape; lines only if bit off)\n   *   FAR   — far plane  (as closed shape; lines only if bit off)\n   *   BODY  — four side walls between near and far (closed quads; diagonal\n   *           edge lines only if bit off)\n   *   APEX  — for perspective: replaces the near-corner body start with the\n   *           camera origin (0,0,0) so the body edges converge at the apex.\n   *           Ignored for orthographic projections.\n   *\n   * `viewer` is a callback invoked AFTER the view/eye matrices have been\n   * installed — use it to draw anything that belongs in the secondary\n   * camera's space (triad, HUD, grid, etc). Default: a three-axis triad\n   * `X | Y | _Z` (right, up, forward) at the apex.\n   *\n   * `nearTexture` / `farTexture` map a texture onto the corresponding plane\n   * via the `pane()` helper. Typical use: the scene as rendered from the\n   * secondary camera, mapped onto its own near plane to show \"what the\n   * camera sees\" as a projection ONTO the projection surface. Supply\n   * `myFbo.color` for a framebuffer's rendered contents.\n   *\n   * Draw order: `viewer` → untextured FAR outline → BODY → untextured NEAR\n   * outline → textured FAR → textured NEAR. Textured planes are drawn last\n   * so alpha can reveal the frustum interior through them; NEAR after FAR\n   * because NEAR sits in front of the external viewer in the typical\n   * \"look at the camera from outside\" configuration.\n   *\n   * @method viewFrustum\n   * @for p5\n   * @param {{\n   *   camera?:      p5.Camera | CameraTrack | { eye:number[], center?:number[], up?:number[], fov?:number, halfHeight?:number, near?:number, far?:number },\n   *   mat4Eye?:     Float32Array | ArrayLike | p5.Matrix,\n   *   mat4Proj?:    Float32Array | ArrayLike | p5.Matrix,\n   *   mat4View?:    Float32Array | ArrayLike | p5.Matrix,\n   *   bits?:        number,\n   *   viewer?:      Function,\n   *   nearTexture?: p5.Image | p5.Graphics | p5.Texture,\n   *   farTexture?:  p5.Image | p5.Graphics | p5.Texture,\n   * }} [opts]\n   */\n  p5.Renderer3D.prototype.viewFrustum = function ({\n    camera, mat4Eye, mat4Proj, mat4View,\n    bits   = p5.Tree.NEAR | p5.Tree.FAR | p5.Tree.BODY,\n    viewer = () => this.axes({\n      size: 50,\n      bits: p5.Tree.X | p5.Tree.Y | p5.Tree._Z\n    }),\n    nearTexture = null,\n    farTexture  = null,\n  } = {}) {\n    const p = this._pInst;\n    if (!p) return;\n\n    // ── Camera dispatch ───────────────────────────────────────────────\n    // Three forms: p5.Camera, CameraTrack, or plain pose spec.\n    // For tracks and pose specs we need to BUILD eye + proj matrices\n    // because the renderer-bound camera methods aren't available.\n    let eRaw = _rawMat4(mat4Eye);\n    let pRaw = _rawMat4(mat4Proj);\n    if (camera) {\n      if (_isCameraTrack(camera)) {\n        camera.eval(_vfPose);                 // fill _vfPose at cursor\n        camera.mat4Eye(_eye);                 // cursor-form eye matrix\n        eRaw = eRaw ?? _eye;\n        if (!pRaw) {\n          const aspect = (this.width && this.height) ? (this.width / this.height) : 1;\n          _buildProjFromPose(_vfPose, aspect, getNdcZ(), _proj);\n          pRaw = _proj;\n        }\n      } else if (_isP5Camera(camera)) {\n        if (!eRaw) { camera.mat4Eye(_eye);   eRaw = _eye; }\n        if (!pRaw) { camera.mat4Proj(_proj); pRaw = _proj; }\n      } else if (_isPoseSpec(camera)) {\n        if (!eRaw) { _buildEyeFromPose(camera, _eye); eRaw = _eye; }\n        if (!pRaw) {\n          const aspect = (this.width && this.height) ? (this.width / this.height) : 1;\n          _buildProjFromPose(camera, aspect, getNdcZ(), _proj);\n          pRaw = _proj;\n        }\n      }\n    }\n\n    if (!pRaw || !eRaw) {\n      console.error('viewFrustum requires either a camera (p5.Camera, CameraTrack, or pose spec) or both mat4Eye and mat4Proj'); return;\n    }\n\n    const states = this.states, uView = states?.uViewMatrix;\n    if (!uView) return;\n\n    const vRaw    = _rawMat4(mat4View) ?? _viewMat4(this);\n    const isOrtho = projIsOrtho(pRaw);\n    const ndcZ    = getNdcZ();\n    const apex    = !isOrtho && ((bits & p5.Tree.APEX) !== 0);\n    const n = -projNear(pRaw, ndcZ), f = -projFar(pRaw);\n    const l =  projLeft(pRaw, ndcZ),  r = projRight(pRaw, ndcZ);\n    const t =  projTop(pRaw, ndcZ),   b = projBottom(pRaw, ndcZ);\n    const ratio = isOrtho ? 1 : f/n;\n    const _l=ratio*l, _r=ratio*r, _b=ratio*b, _t=ratio*t;\n\n    // Far-plane corners (at z = f, negative)\n    const fTL = [_l, _t, f], fTR = [_r, _t, f], fBR = [_r, _b, f], fBL = [_l, _b, f];\n    // Near-plane corners (at z = n, negative)\n    const nTL = [ l,  t, n], nTR = [ r,  t, n], nBR = [ r,  b, n], nBL = [ l,  b, n];\n\n    p.push(); p.resetMatrix();\n    const prevView = uView.copy();\n    uView.set(vRaw);\n    this.applyMatrix(\n      eRaw[0],  eRaw[1],  eRaw[2],  eRaw[3],\n      eRaw[4],  eRaw[5],  eRaw[6],  eRaw[7],\n      eRaw[8],  eRaw[9],  eRaw[10], eRaw[11],\n      eRaw[12], eRaw[13], eRaw[14], eRaw[15]\n    );\n\n    // ── Viewer — opaque scene-in-eye-space callback ──────────────────────\n    typeof viewer === 'function' && viewer();\n\n    // Bit handling is orthogonal: each bit owns exactly its own edges.\n    // The 12 edges of a frustum partition cleanly across the bits:\n    //   NEAR  — 4 edges of the near rectangle (or filled/textured face)\n    //   FAR   — 4 edges of the far rectangle  (or filled/textured face)\n    //   BODY  — 4 connecting edges (near corner → far corner)\n    //   APEX  — 4 lines (origin → near corner) — perspective only\n    // Disabled bits draw nothing. Closure is the user's responsibility:\n    // `bits: NEAR | FAR | BODY` produces a full closed wireframe.\n\n    // ── FAR — outlined here if untextured; textured pass at the end ──────\n    if ((bits & p5.Tree.FAR) !== 0 && !farTexture) {\n      this.pane(fTL, fTR, fBR, fBL);\n    }\n\n    // ── BODY — four connecting edges (near corners → far corners) ────────\n    // Outline only; never fills the side walls. Users wanting filled walls\n    // (e.g. for a translucent slab effect) can call pane() in user space.\n    if ((bits & p5.Tree.BODY) !== 0) {\n      p.line(nTL[0],nTL[1],nTL[2], fTL[0],fTL[1],fTL[2]);\n      p.line(nTR[0],nTR[1],nTR[2], fTR[0],fTR[1],fTR[2]);\n      p.line(nBR[0],nBR[1],nBR[2], fBR[0],fBR[1],fBR[2]);\n      p.line(nBL[0],nBL[1],nBL[2], fBL[0],fBL[1],fBL[2]);\n    }\n\n    // ── APEX — converging lines from origin to near corners ──────────────\n    // Drawn regardless of BODY: APEX is a stand-alone visual cue for the\n    // \"perspective cone\" interpretation of the frustum.\n    if (apex) {\n      p.line(0,0,0, nTR[0], nTR[1], nTR[2]);\n      p.line(0,0,0, nTL[0], nTL[1], nTL[2]);\n      p.line(0,0,0, nBL[0], nBL[1], nBL[2]);\n      p.line(0,0,0, nBR[0], nBR[1], nBR[2]);\n    }\n\n    // ── NEAR — outlined here if untextured; textured pass at the end ─────\n    if ((bits & p5.Tree.NEAR) !== 0 && !nearTexture) {\n      this.pane(nTL, nTR, nBR, nBL);\n    }\n\n    // ── Textured planes — drawn LAST for correct alpha compositing ───────\n    // Far before near: in the typical \"external viewer in front of camera\"\n    // configuration, far sits behind near.\n    if ((bits & p5.Tree.FAR) !== 0 && farTexture) {\n      this.pane(fTL, fTR, fBR, fBL, { texture: farTexture });\n    }\n    if ((bits & p5.Tree.NEAR) !== 0 && nearTexture) {\n      this.pane(nTL, nTR, nBR, nBL, { texture: nearTexture });\n    }\n\n    uView.set(prevView);\n    p.pop();\n  };\n\n  // ── Hermite — atomic spline primitive ─────────────────────────────────────\n\n  fn.hermite = function (p0, m0, p1, m1, opts) {\n    this._renderer.hermite(p0, m0, p1, m1, opts);\n    return this;\n  };\n\n  /**\n   * Draw one cubic Hermite segment between two endpoints with explicit tangents.\n   *\n   *   hermite([0,0,0], [100,0,0], [200,0,0], [0,100,0])\n   *   hermite(p0, m0, p1, m1, { samples: 64 })\n   *\n   * @param {number[]} p0  Segment start — [x,y,z].\n   * @param {number[]} m0  Outgoing tangent at p0.\n   * @param {number[]} p1  Segment end — [x,y,z].\n   * @param {number[]} m1  Incoming tangent at p1.\n   * @param {{ samples?: number }} [opts]\n   */\n  p5.Renderer3D.prototype.hermite = function (p0, m0, p1, m1, { samples = 32 } = {}) {\n    const p = this._pInst;\n    if (!p) return;\n    const N = Math.max(2, samples | 0);\n    for (let i = 0; i <= N; i++) {\n      const t = i / N;\n      hermiteVec3(_sp, p0, m0, p1, m1, t);\n      if (i > 0) p.line(_prev[0], _prev[1], _prev[2], _sp[0], _sp[1], _sp[2]);\n      _prev[0] = _sp[0]; _prev[1] = _sp[1]; _prev[2] = _sp[2];\n    }\n  };\n\n  // ── trackPath ─────────────────────────────────────────────────────────────\n\n  fn.trackPath = function (track, opts) {\n    this._renderer.trackPath(track, opts);\n    return this;\n  };\n\n  /**\n   * Visualise a PoseTrack or CameraTrack: sampled path polyline, control\n   * polygon, tangent arrows, per-keyframe marker, and (CameraTrack only)\n   * gaze rays from each eye keyframe to its center.\n   *\n   * Bits:\n   *   PATH          — sampled polyline along the target path.\n   *   CONTROLS      — straight control polygon along the target path.\n   *   TANGENTS_IN   — incoming tangent arrow at each keyframe.\n   *   TANGENTS_OUT  — outgoing tangent arrow at each keyframe.\n   *   TANGENTS      — convenience alias (IN | OUT).\n   *   CENTER        — CameraTrack only. Gaze line from each kf.eye to\n   *                   kf.center, with a point() at kf.center. Target-\n   *                   independent — always expresses the eye→center\n   *                   relationship regardless of opts.target. The default\n   *                   CameraTrack marker already draws the same eye→center\n   *                   line as part of the \"mini camera\" it renders, so\n   *                   CENTER is most useful when a CUSTOM marker is\n   *                   supplied and gaze rays are wanted in a separate\n   *                   ambient stroke() colour.\n   *\n   * opts.target — 'eye' (default) or 'center'. CameraTrack only: redirects\n   * PATH / CONTROLS / TANGENTS_IN / TANGENTS_OUT to the center path instead\n   * of the eye path. PoseTrack ignores target (there is only one path).\n   * Call trackPath twice (once per target) to decorate both paths with\n   * different ambient stroke() colours.\n   *\n   * The `marker` callback is called once per keyframe with\n   *   marker(kf, index, track, ctx)\n   * where ctx = { near, far, aspect, ndcZMin } is read from the current\n   * renderer's projection. The gizmo does NOT pre-translate or rotate\n   * before calling marker — markers position themselves using kf.pos/kf.rot\n   * (PoseTrack) or kf.eye/kf.center/kf.up (CameraTrack) — or reach into\n   * track.mat4Model / track.mat4Eye if they need matrices at arbitrary\n   * path coordinates. Projection matrices (e.g. for a custom frustum\n   * marker) are built from the keyframe's raw scalars (kf.fov /\n   * kf.halfHeight / kf.near / kf.far) via the free mat4Persp / mat4Ortho\n   * constructors.\n   *\n   * Defaults (when `marker` is not supplied):\n   *   PoseTrack                    — six axes (length 30) at the keyframe's pose.\n   *   CameraTrack, target='eye'    — \"mini camera\" at each keyframe: triad\n   *                                  (X | Y | _Z, size = kf.near), apex\n   *                                  lines (perspective only, from origin\n   *                                  to near corners), near plane outline\n   *                                  at the keyframe's real extents (from\n   *                                  kf.fov or kf.halfHeight at the ambient\n   *                                  aspect), and a center line from\n   *                                  kf.eye to kf.center. All drawn at the\n   *                                  keyframe's real dimensions — shares\n   *                                  its geometry with viewFrustum. Supply\n   *                                  a custom marker if you want markers\n   *                                  that stay sane at any scene scale.\n   *   CameraTrack, target='center' — point() at each keyframe's center.\n   *\n   * Pass `marker: null` to suppress per-keyframe markers entirely.\n   *\n   * @param {PoseTrack|CameraTrack} track\n   * @param {{\n   *   bits?:    number,\n   *   samples?: number,\n   *   target?:  'eye' | 'center',\n   *   marker?:  Function | null,\n   * }} [opts]\n   */\n  p5.Renderer3D.prototype.trackPath = function (track, opts = {}) {\n    const p = this._pInst;\n    if (!p) return;\n    if (!track || !Array.isArray(track.keyframes)) return;\n    const kfs = track.keyframes;\n    const n   = kfs.length;\n    if (n === 0) return;\n\n    const isCameraTrack = (typeof track.sampleEye === 'function')\n                       || (n > 0 && kfs[0].eye !== undefined);\n\n    const {\n      bits    = p5.Tree.PATH,\n      samples = 32,\n      target  = 'eye',\n    } = opts;\n    const N = Math.max(2, samples | 0);\n\n    // Target resolves field + samplers for PATH / CONTROLS / TANGENTS.\n    // PoseTrack ignores target; CameraTrack redirects to the center path\n    // when target === 'center'.\n    const useCenter   = isCameraTrack && target === 'center';\n    const pathField   = isCameraTrack ? (useCenter ? 'center'         : 'eye')        : 'pos';\n    const pathSampler = isCameraTrack ? (useCenter ? 'sampleCenter'   : 'sampleEye')  : 'samplePos';\n    const tangentsFn  = isCameraTrack ? (useCenter ? 'centerTangents' : 'eyeTangents'): 'tangents';\n\n    let marker;\n    if ('marker' in opts) {\n      marker = opts.marker;\n    } else {\n      marker = isCameraTrack\n        ? _defaultCameraMarker(this, p5, useCenter)\n        : _defaultPoseMarker(this, p5);\n    }\n\n    let ctx = null;\n    if (marker) {\n      const curProj = _projMat4(this);\n      const ndcZMin = getNdcZ();\n      ctx = {\n        near:    projNear(curProj, ndcZMin),\n        far:     projFar(curProj),\n        aspect:  (this.width && this.height) ? (this.width / this.height) : 1,\n        ndcZMin: ndcZMin,\n      };\n    }\n\n    const hasPath        = (bits & p5.Tree.PATH)         !== 0;\n    const hasControls    = (bits & p5.Tree.CONTROLS)     !== 0;\n    const hasTangentsIn  = (bits & p5.Tree.TANGENTS_IN)  !== 0;\n    const hasTangentsOut = (bits & p5.Tree.TANGENTS_OUT) !== 0;\n    const hasCenter      = isCameraTrack && (bits & p5.Tree.CENTER) !== 0;\n\n    // ── PATH: sampled polyline along the target path ─────────────────────\n    if (hasPath) {\n      if (n === 1) {\n        const pt = kfs[0][pathField];\n        p.point(pt[0], pt[1], pt[2]);\n      } else {\n        let first = true;\n        for (let seg = 0; seg < n - 1; seg++) {\n          const end = (seg === n - 2) ? N : N - 1;\n          for (let i = 0; i <= end; i++) {\n            const t = i / N;\n            track[pathSampler](_sp, seg, t);\n            if (!first) p.line(_prev[0], _prev[1], _prev[2], _sp[0], _sp[1], _sp[2]);\n            _prev[0] = _sp[0]; _prev[1] = _sp[1]; _prev[2] = _sp[2];\n            first = false;\n          }\n        }\n      }\n    }\n\n    // ── CONTROLS: straight control polygon along the target path ─────────\n    if (hasControls && n >= 2) {\n      for (let i = 0; i < n - 1; i++) {\n        const a = kfs[i][pathField], b = kfs[i + 1][pathField];\n        p.line(a[0], a[1], a[2], b[0], b[1], b[2]);\n      }\n    }\n\n    // ── TANGENTS_IN / TANGENTS_OUT: arrows at each keyframe ──────────────\n    if (hasTangentsIn || hasTangentsOut) {\n      for (let i = 0; i < n; i++) {\n        track[tangentsFn](_tIn, _tOut, i);\n        const kp = kfs[i][pathField];\n        if (hasTangentsIn) {\n          p.line(kp[0] - _tIn[0], kp[1] - _tIn[1], kp[2] - _tIn[2],\n                 kp[0], kp[1], kp[2]);\n        }\n        if (hasTangentsOut) {\n          p.line(kp[0], kp[1], kp[2],\n                 kp[0] + _tOut[0], kp[1] + _tOut[1], kp[2] + _tOut[2]);\n        }\n      }\n    }\n\n    // ── CENTER: gaze line eye→center + endpoint dot (CameraTrack only) ───\n    // Target-independent: always expresses the eye→center relationship.\n    if (hasCenter) {\n      for (let i = 0; i < n; i++) {\n        const e = kfs[i].eye, c = kfs[i].center;\n        p.line(e[0], e[1], e[2], c[0], c[1], c[2]);\n        p.point(c[0], c[1], c[2]);\n      }\n    }\n\n    // ── Per-keyframe marker ──────────────────────────────────────────────\n    if (marker) {\n      for (let i = 0; i < n; i++) {\n        marker(kfs[i], i, track, ctx);\n      }\n    }\n  };\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Default markers\n// ═══════════════════════════════════════════════════════════════════════════\n\nfunction _defaultPoseMarker(renderer, p5) {\n  const p = renderer._pInst;\n  const bits = p5.Tree.X | p5.Tree._X | p5.Tree.Y | p5.Tree._Y | p5.Tree.Z | p5.Tree._Z;\n  return (kf, _i, _track, _ctx) => {\n    p.push();\n    p.translate(kf.pos[0], kf.pos[1], kf.pos[2]);\n    renderer.rotateQuat(kf.rot);\n    renderer.axes({ size: 30, bits });\n    p.pop();\n  };\n}\n\n// Default CameraTrack marker — \"mini camera\" at each keyframe.\n//\n// Shares structure with viewFrustum: triad + apex lines + near plane drawn\n// in eye-local space at the keyframe's real dimensions. The marker is\n// scoped to camera-local geometry — the eye→center gaze line is NOT part\n// of it. Enable the CENTER bit in trackPath to draw per-keyframe gaze\n// lines alongside.\n//\n// Real dims throughout:\n//   triad size      = kf.near        (the _Z axis tip lands at the near plane centre)\n//   near plane z    = -kf.near\n//   near extents    = kf.fov or kf.halfHeight + ambient aspect\n//\n// For tracks with typical small near values (e.g. 0.1) this produces\n// visually tiny markers. Supply a custom marker to scale for legibility\n// at distance.\nfunction _defaultCameraMarker(renderer, p5, useCenter) {\n  const p = renderer._pInst;\n\n  // target=center: no orientation to convey — just a dot at center.\n  if (useCenter) {\n    return (kf) => {\n      p.point(kf.center[0], kf.center[1], kf.center[2]);\n    };\n  }\n\n  const axesBits = p5.Tree.X | p5.Tree.Y | p5.Tree._Z;\n\n  return (kf, i, trk, ctx) => {\n    const near   = (typeof kf.near === 'number') ? kf.near : 0.1;\n    const aspect = ctx.aspect;\n\n    // Plane extents at z = -near. Fallback fov only if keyframe carries\n    // neither fov nor halfHeight — rare, since capturePose populates one\n    // of them for any real camera and _parseCameraSpec does not zero them.\n    let hh, hw, isOrtho = false;\n    if (typeof kf.halfHeight === 'number') {\n      isOrtho = true;\n      hh = kf.halfHeight;\n      hw = hh * aspect;\n    } else {\n      const fov = (typeof kf.fov === 'number') ? kf.fov : Math.PI / 3;\n      hh = near * Math.tan(fov * 0.5);\n      hw = hh * aspect;\n    }\n\n    // Eye-local near-plane corners (z = -near, forward direction).\n    const nTL = [-hw,  hh, -near];\n    const nTR = [ hw,  hh, -near];\n    const nBR = [ hw, -hh, -near];\n    const nBL = [-hw, -hh, -near];\n\n    trk.mat4Eye(_kfEye, i, 0);\n    p.push();\n    p.applyMatrix(\n      _kfEye[0],  _kfEye[1],  _kfEye[2],  _kfEye[3],\n      _kfEye[4],  _kfEye[5],  _kfEye[6],  _kfEye[7],\n      _kfEye[8],  _kfEye[9],  _kfEye[10], _kfEye[11],\n      _kfEye[12], _kfEye[13], _kfEye[14], _kfEye[15]\n    );\n\n    // Triad at the camera origin, oriented by lookat. Size = near so the\n    // _Z tip coincides with the near plane centre. Nested push/pop so the\n    // semantic axis colours don't leak into the apex / plane draws.\n    p.push();\n    renderer.axes({ size: near, bits: axesBits });\n    p.pop();\n\n    // Apex lines — perspective only (ortho has no apex).\n    if (!isOrtho) {\n      p.line(0, 0, 0, nTL[0], nTL[1], nTL[2]);\n      p.line(0, 0, 0, nTR[0], nTR[1], nTR[2]);\n      p.line(0, 0, 0, nBR[0], nBR[1], nBR[2]);\n      p.line(0, 0, 0, nBL[0], nBL[1], nBL[2]);\n    }\n\n    // Near plane (outline, or filled if user has fill() enabled).\n    renderer.pane(nTL, nTR, nBR, nBL);\n\n    p.pop();\n\n    // Note — the marker deliberately does NOT draw an eye→center gaze\n    // line. That's the CENTER bit's job (see trackPath). Keeping the\n    // responsibilities separate means CENTER is a meaningful toggle,\n    // and the marker stays scoped to camera-local geometry.\n  };\n}\n","/**\n * @file Picking — GPU color-ID picking and CPU proximity tests.\n * @module p5.tree/picking\n * @license AGPL-3.0-only\n *\n * ── GPU color-ID picking ──────────────────────────────────────────────────\n *\n * Technique: render the scene into a 1×1 FBO with a pick-matrix projection\n * aligned to the query pixel, read back RGBA via gl.readPixels, decode the\n * 24-bit integer id from RGB (R = LSB).\n *\n * id 0 is reserved for background / miss.\n * Valid user ids: 1 – 16 777 215 (2²⁴ − 1).\n *\n * Encoding: tag(id) → '#rrggbb'   e.g. tag(1) === '#010000'\n * Decoding: R | (G << 8) | (B << 16)\n *\n * ── CPU proximity picking ─────────────────────────────────────────────────\n *\n * Tests whether a pointer position falls within a radius of the projected\n * screen-space origin of the current model matrix. Zero GPU round-trip.\n * Call inside push()/pop() for each pickable object.\n *\n * ── API symmetry ──────────────────────────────────────────────────────────\n *\n *   colorPick(x, y, drawFn)   GPU — base form\n *   mousePick(drawFn)         GPU — shorthand for colorPick(mouseX, mouseY, fn)\n *\n *   pointerHit(x, y, opts)    CPU — base form (renderer method)\n *   mouseHit(opts)            CPU — shorthand for pointerHit(mouseX, mouseY, opts)\n */\n\n'use strict';\n\nimport { mat4Pick } from '@nakednous/tree';\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Module-level zero-alloc buffers\n// ═══════════════════════════════════════════════════════════════════════════\n\nconst _pickBuf      = new Uint8Array(4);      // gl.readPixels target\nconst _pickProjSave = new Float32Array(16);   // saved projection before fbo.begin()\nconst _pickViewSave = new Float32Array(16);   // saved view before fbo.begin()\nconst _pickVp       = new Float32Array(4);    // viewport [0, h, w, −h] for mat4Pick\nconst _sl           = new Float32Array(3);    // screen location scratch for pointerHit\nconst _wl           = new Float32Array(3);    // world location scratch for pointerHit\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Local helpers\n// ═══════════════════════════════════════════════════════════════════════════\n\nconst _rawMat4   = (m) => (m != null && m.mat4 != null) ? m.mat4 : m;\nconst _modelMat4 = (r) => r.states.uModelMatrix.mat4;\n\n// ═══════════════════════════════════════════════════════════════════════════\n// Install\n// ═══════════════════════════════════════════════════════════════════════════\n\nexport function installPicking(p5, fn) {\n\n  // ── tag ───────────────────────────────────────────────────────────────────\n\n  /**\n   * Encode an integer id as a CSS hex color string for use with `fill()`.\n   * id `0` is reserved — decodes as background / miss.\n   *\n   * @method tag\n   * @for p5\n   * @param {number} id  Integer in [1, 16_777_215].\n   * @returns {string}   CSS hex string, e.g. `'#010000'` for id `1`.\n   */\n  fn.tag = function (id) {\n    const r= id        & 0xff;\n    const g=(id >>  8) & 0xff;\n    const b=(id >> 16) & 0xff;\n    return '#' + r.toString(16).padStart(2,'0')\n               + g.toString(16).padStart(2,'0')\n               + b.toString(16).padStart(2,'0');\n  };\n\n  // ── colorPick ─────────────────────────────────────────────────────────────\n\n  /**\n   * Render `drawFn` into a cached 1×1 framebuffer aligned to pixel (px, py),\n   * then read back and decode the integer id under that pixel.\n   *\n   * Before `drawFn` is called the library unconditionally sets\n   * `noLights()`, `noStroke()`, `resetShader()`.\n   * The FBO is lazily allocated on first use and released in `lifecycles.remove`.\n   *\n   * @method colorPick\n   * @for p5\n   * @param {number}   px      X coordinate in canvas CSS pixels.\n   * @param {number}   py      Y coordinate in canvas CSS pixels.\n   * @param {function} drawFn  Scene draw callback — tag objects with fill(tag(id)).\n   * @returns {number}         Decoded id (0 = background / miss).\n   */\n  fn.colorPick = function (px, py, drawFn) {\n    const p        = this;\n    const renderer = p._renderer;\n    const states   = renderer.states;\n\n    // Save projection and view BEFORE fbo.begin() overwrites them.\n    const mainProj = states.uPMatrix.mat4;\n    for (let i = 0; i < 16; i++) _pickProjSave[i] = mainProj[i];\n    const mainView = states.uViewMatrix.mat4;\n    for (let i = 0; i < 16; i++) _pickViewSave[i] = mainView[i];\n\n    // Lazy-allocate the 1×1 pick FBO.\n    p._tree          ||= {};\n    p._tree._pickFbo ??= p.createFramebuffer({\n      width: 1, height: 1,\n      depth: true,       // depth test selects nearest hit, not draw order\n      antialias: false,  // blending would corrupt encoded integer colors\n    });\n    const fbo = p._tree._pickFbo;\n\n    fbo.begin();\n\n    // Restore view; install pick projection.\n    const view = states.uViewMatrix.mat4;\n    for (let i = 0; i < 16; i++) view[i] = _pickViewSave[i];\n    const proj = states.uPMatrix.mat4;\n    for (let i = 0; i < 16; i++) proj[i] = _pickProjSave[i];\n\n    // Viewport [0, h, w, −h] — negative h encodes p5/DOM screen-y-down.\n    _pickVp[0]=0; _pickVp[1]=p.height; _pickVp[2]=p.width; _pickVp[3]=-p.height;\n    mat4Pick(proj, px, py, _pickVp);\n\n    p.background(0);\n    p.noLights();\n    p.noStroke();\n    p.resetShader();\n\n    let hit = 0;\n    try {\n      drawFn();\n      renderer.drawingContext.readPixels(\n        0, 0, 1, 1,\n        renderer.drawingContext.RGBA,\n        renderer.drawingContext.UNSIGNED_BYTE,\n        _pickBuf,\n      );\n      hit = _pickBuf[0] | (_pickBuf[1] << 8) | (_pickBuf[2] << 16);\n    } finally {\n      fbo.end();\n    }\n\n    return hit;\n  };\n\n  // ── mousePick ─────────────────────────────────────────────────────────────\n\n  /**\n   * Shorthand for `colorPick(mouseX, mouseY, drawFn)`.\n   * @method mousePick\n   * @for p5\n   * @param {function} drawFn\n   * @returns {number}  Decoded id (0 = background / miss).\n   */\n  fn.mousePick = function (drawFn) {\n    return this.colorPick(this.mouseX, this.mouseY, drawFn);\n  };\n\n  // ── pointerHit ────────────────────────────────────────────────────────────\n\n  fn.pointerHit = function (...args) { return this._renderer.pointerHit(...args); };\n\n  /**\n   * Test whether a pointer position falls within a radius of the current\n   * model's screen-space origin. CPU — zero GPU round-trip.\n   * Call inside `push()`/`pop()` for each pickable object.\n   *\n   * @method pointerHit\n   * @for p5\n   * @param {number}  [pointerX]\n   * @param {number}  [pointerY]\n   * @param {{\n   *   mat4Model?:  Float32Array | ArrayLike | p5.Matrix,\n   *   x?, y?,\n   *   size?:       number,\n   *   shape?:      number,\n   *   mat4Eye?:    Float32Array | ArrayLike | p5.Matrix,\n   *   mat4Proj?:   Float32Array | ArrayLike | p5.Matrix,\n   *   mat4View?:   Float32Array | ArrayLike | p5.Matrix,\n   *   mat4PV?:     Float32Array | ArrayLike | p5.Matrix,\n   * }} [opts]\n   * @returns {boolean}\n   */\n  p5.Renderer3D.prototype.pointerHit = function (...args) {\n    let pointerX, pointerY;\n    const config = {};\n    for (const arg of args) {\n      if (typeof arg === 'number' && Number.isFinite(arg)) {\n        pointerX == null ? pointerX = arg : pointerY = arg;\n      } else if (arg && typeof arg === 'object') { Object.assign(config, arg); }\n    }\n    const p = this._pInst;\n    if (pointerX == null) pointerX = p ? p.mouseX : this.width  / 2;\n    if (pointerY == null) pointerY = p ? p.mouseY : this.height / 2;\n\n    let { mat4Model, x, y, size=50, shape=p5.Tree.CIRCLE,\n          mat4Eye, mat4Proj, mat4View, mat4PV } = config;\n    const mm = _rawMat4(mat4Model) ?? _modelMat4(this);\n\n    if (x == null || y == null) {\n      this.mapLocation(p5.Tree.ORIGIN, { from: mm, to: p5.Tree.SCREEN, out: _sl, mat4Proj, mat4View, mat4PV });\n      x = _sl[0]; y = _sl[1];\n      this.mapLocation(p5.Tree.ORIGIN, { from: mm, to: p5.Tree.WORLD, out: _wl, mat4Eye });\n      size = size / this.pixelRatio(_wl);\n    }\n    const r=size/2, dx=x-pointerX, dy=y-pointerY;\n    return shape === p5.Tree.CIRCLE\n      ? Math.sqrt(dx*dx+dy*dy) < r\n      : (Math.abs(dx) < r && Math.abs(dy) < r);\n  };\n\n  // ── mouseHit ──────────────────────────────────────────────────────────────\n\n  /**\n   * Shorthand for `pointerHit(mouseX, mouseY, opts)`.\n   * @method mouseHit\n   * @for p5\n   * @param {{\n   *   mat4Model?:  Float32Array | ArrayLike | p5.Matrix,\n   *   x?, y?,\n   *   size?:       number,\n   *   shape?:      number,\n   *   mat4Eye?:    Float32Array | ArrayLike | p5.Matrix,\n   *   mat4Proj?:   Float32Array | ArrayLike | p5.Matrix,\n   *   mat4View?:   Float32Array | ArrayLike | p5.Matrix,\n   *   mat4PV?:     Float32Array | ArrayLike | p5.Matrix,\n   * }} [opts]\n   * @returns {boolean}\n   */\n  fn.mouseHit = function (opts) {\n    return this._renderer.pointerHit(this.mouseX, this.mouseY, opts);\n  };\n}\n\n// ═══════════════════════════════════════════════════════════════════════════\n// FBO lifecycle\n// ═══════════════════════════════════════════════════════════════════════════\n\n/**\n * Release the cached pick FBO. Called from lifecycles.remove.\n * @param {p5} pInst\n */\nexport function releasePickFbo(pInst) {\n  const fbo = pInst._tree?._pickFbo;\n  if (fbo) { fbo.remove(); delete pInst._tree._pickFbo; }\n}\n","/**\n * @file PoseTrack / CameraTrack bridge: player registry, camera pose helpers.\n * @module p5.tree/track\n * @license AGPL-3.0-only\n *\n * ── What lives here ──────────────────────────────────────────────────────────\n *  Player registry\n *    registerPlayer / unregisterPlayer / tickPlayers / clearPlayers\n *\n *  fn.getCamera          Return the current p5 camera (curCamera).\n *  fn.createPoseTrack()        PoseTrack wired to the draw loop.\n *  fn.createCameraTrack([cam]) CameraTrack wired + auto-apply; defaults to current camera.\n *\n *  p5.Renderer3D.rotateQuat   rotate by [x,y,z,w] quaternion\n *  p5.Renderer3D.applyPose    apply TRS { pos, rot, scl } to the transform stack\n *  fn.rotateQuat / fn.applyPose   forwarders to the renderer\n *\n *  p5.Camera.capturePose  read live camera → { eye, center, up, fov, halfHeight, near, far }\n *  p5.Camera.applyPose    write { eye, center, up, fov, halfHeight, near, far } → cam.camera() + projection\n *\n * ── { camera } spec support ───────────────────────────────────────────────────\n *  CameraTrack.add() returned by createCameraTrack() accepts a { camera } spec:\n *    track.add({ camera: cam })        — capture live pose from a p5.Camera\n *    track.add({ camera: getCamera() })\n *  Interception is in the bridge (here), not in deps/tree — eyeX/centerX/upX\n *  are p5-specific property names; the numeric core stays renderer-agnostic.\n */\n\n'use strict';\n\nimport {\n  PoseTrack, CameraTrack, qToMat4,\n  projFov, projTop, projIsOrtho,\n  projNear, projFar,\n} from '@nakednous/tree';\nimport { getNdcZ } from './matrix.js';\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Player registry\n// ═══════════════════════════════════════════════════════════════════════════════\n\nconst PATH_PLAYERS = new WeakMap();\n\nfunction _getPlayers(pInst) {\n  let p = PATH_PLAYERS.get(pInst);\n  if (!p) { p = new Set(); PATH_PLAYERS.set(pInst, p); }\n  return p;\n}\n\n/**\n * Register a player with a p5 instance.\n * `player.tick()` is called each predraw; removed when it returns false.\n * @param {p5} pInst\n * @param {{ tick: () => boolean }} player\n */\nexport function registerPlayer(pInst, player) {\n  if (pInst && player) _getPlayers(pInst).add(player);\n}\n\n/**\n * Unregister a player from a p5 instance.\n * @param {p5} pInst\n * @param {{ tick: () => boolean }} player\n */\nexport function unregisterPlayer(pInst, player) {\n  if (pInst && player) _getPlayers(pInst).delete(player);\n}\n\n/**\n * Tick all registered players. Called from the predraw lifecycle.\n * @param {p5} pInst\n */\nexport function tickPlayers(pInst) {\n  const players = PATH_PLAYERS.get(pInst);\n  if (!players) return;\n  for (const p of [...players]) {\n    if (!p.tick()) players.delete(p);\n  }\n}\n\n/**\n * Remove all players. Called from the remove lifecycle.\n * @param {p5} pInst\n */\nexport function clearPlayers(pInst) {\n  const players = PATH_PLAYERS.get(pInst);\n  if (players) players.clear();\n}\n\n// ── Shared player wiring for PoseTrack ───────────────────────────────────────\n\nfunction _wirePoseTrack(track, pInst) {\n  let player = null;\n  track._onActivate   = () => {\n    player = player || { tick() { track.tick(); return track.playing; } };\n    registerPlayer(pInst, player);\n  };\n  track._onDeactivate = () => unregisterPlayer(pInst, player);\n}\n\n// ── { camera } spec → { eye, center, up } conversion (bridge-side only) ──────\n//\n// Duck-types on p5.Camera lookat properties: eyeX/Y/Z, centerX/Y/Z, upX/Y/Z.\n// Returns null when the object doesn't look like a lookat camera.\n\nfunction _cameraToSpec(cam) {\n  if (!cam || typeof cam !== 'object') return null;\n  if (cam.eyeX === undefined || cam.centerX === undefined) return null;\n  const ux = cam.upX !== undefined ? cam.upX : 0;\n  const uy = cam.upY !== undefined ? cam.upY : 1;\n  const uz = cam.upZ !== undefined ? cam.upZ : 0;\n  return {\n    eye:    [cam.eyeX,    cam.eyeY,    cam.eyeZ],\n    center: [cam.centerX, cam.centerY, cam.centerZ],\n    up:     [ux, uy, uz],\n  };\n}\n\n/**\n * Wrap CameraTrack.add() to intercept { camera } specs and the no-arg form.\n *\n * Accepts all forms the core supports, plus:\n *   (no args)    — capture the track's bound camera (track.camera); no-op if unset\n *   { camera }   — duck-typed lookat object (p5.Camera or compatible);\n *                  reads eyeX/Y/Z, centerX/Y/Z, upX/Y/Z\n *\n * Arrays are processed element-by-element so { camera } entries inside\n * bulk adds are also resolved.\n *\n * Equivalent forms for a track returned by createCameraTrack(cam):\n *   track.add()\n *   track.add({ camera: cam })\n *   track.add({ camera: getCamera() })\n *   track.add(cam.capturePose())   // zero-alloc, prefer in hot paths\n *\n * @param {CameraTrack} track\n */\nfunction _patchCameraTrackAdd(track) {\n  const _coreAdd = track.add.bind(track);\n  track.add = function (spec, opts) {\n    // No-arg shortcut — capture the bound camera if available.\n    if (spec == null) {\n      if (!track.camera) return;\n      spec = { camera: track.camera };\n    }\n    // Bulk array — recurse so { camera } entries are resolved per-element.\n    if (Array.isArray(spec)) {\n      for (const s of spec) track.add(s, opts);\n      return;\n    }\n    // { camera } — prefer capturePose() so fov/halfHeight/near/far are included;\n    // fall back to _cameraToSpec for non-p5 duck-typed cameras.\n    if (spec.camera != null) {\n      const converted = typeof spec.camera.capturePose === 'function'\n        ? spec.camera.capturePose()\n        : _cameraToSpec(spec.camera);\n      if (converted) { _coreAdd(converted, opts); return; }\n    }\n    _coreAdd(spec, opts);\n  };\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Install\n// ═══════════════════════════════════════════════════════════════════════════════\n\nexport function installTrack(p5, fn) {\n\n  p5.Tree.PoseTrack   = PoseTrack;\n  p5.Tree.CameraTrack = CameraTrack;\n\n  // ── fn.getCamera ───────────────────────────────────────────────────────────\n\n  /**\n   * Return the current p5 camera (curCamera).\n   *\n   * Returns null if called before createCanvas().\n   *\n   * @method getCamera\n   * @memberof p5\n   * @returns {p5.Camera|null}\n   */\n  fn.getCamera = function () {\n    return this._renderer?.states?.curCamera ?? null;\n  };\n\n  // ── fn.createPoseTrack ─────────────────────────────────────────────────────\n\n  /**\n   * Create a PoseTrack wired to the p5 draw loop.\n   *\n   * ```js\n   * const track = createPoseTrack()\n   * const out   = { pos:[0,0,0], rot:[0,0,0,1], scl:[1,1,1] }\n   *\n   * track.add({ pos:[0,0,0],   rot:[0,0,0,1], scl:[1,1,1] })\n   * track.add({ pos:[200,0,0], rot:[0,0,0,1], scl:[1,1,1] })\n   * track.play({ loop: true })\n   *\n   * // in draw():\n   * if (track.playing) {\n   *   push()\n   *   applyPose(track.eval(out))\n   *   box(60)\n   *   pop()\n   * }\n   * ```\n   *\n   * @method createPoseTrack\n   * @memberof p5\n   * @returns {PoseTrack}\n   */\n  fn.createPoseTrack = function () {\n    const track = new PoseTrack();\n    _wirePoseTrack(track, this);\n    return track;\n  };\n\n  // ── fn.createCameraTrack ───────────────────────────────────────────────────\n\n  /**\n   * Create a CameraTrack bound to a p5.Camera.\n   * Playback applies the interpolated lookat + projection automatically each frame.\n   *\n   * ```js\n   * // implicit — binds to the default camera\n   * const track = createCameraTrack()\n   *\n   * // explicit — same result\n   * const track = createCameraTrack(getCamera())\n   *\n   * // dedicated camera\n   * const cam   = createCamera()\n   * const track = createCameraTrack(cam)\n   * ```\n   *\n   * ```js\n   * track.add({ eye:[0,0,500], center:[0,0,0] })\n   * track.add({ eye:[300,-150,0], center:[0,0,0] })\n   * track.add()                          // capture bound camera (track.camera)\n   * track.add({ camera: cam })           // capture any p5.Camera\n   * track.play({ loop: true })\n   *\n   * // in draw(): no guard needed — applyPose fires automatically in predraw\n   * orbitControl()   // works freely when track is stopped\n   * ```\n   *\n   * Interpolation modes:\n   * ```js\n   * track.eyeInterp    = 'hermite'   // 'hermite' | 'linear' | 'step'\n   * track.centerInterp = 'linear'    // 'hermite' | 'linear' | 'step'\n   * ```\n   *\n   * @method createCameraTrack\n   * @memberof p5\n   * @param {p5.Camera} [cam]  Camera to drive. Defaults to the current camera.\n   *                           Use createCamera() for a dedicated camera.\n   * @returns {CameraTrack}\n   */\n  fn.createCameraTrack = function (cam) {\n    const pInst = this;\n    cam = cam ?? this.getCamera() ?? null;\n    const track  = new CameraTrack();\n    const out    = {\n      eye:[0,0,0], center:[0,0,0], up:[0,1,0],\n      fov:null, halfHeight:null,\n      near:0.1, far:1000,\n    };\n\n    track.camera = cam;\n    _patchCameraTrackAdd(track);\n\n    const applyPlayer = {\n      tick() {\n        if (!track.playing) return false;\n        track.tick();\n        if (cam) cam.applyPose(track.eval(out));\n        return track.playing;\n      }\n    };\n\n    track._onActivate   = () => registerPlayer(pInst, applyPlayer);\n    track._onDeactivate = () => {\n      unregisterPlayer(pInst, applyPlayer);\n      if (cam && track.keyframes.length > 0) cam.applyPose(track.eval(out));\n    };\n\n    return track;\n  };\n\n  // ── p5.Renderer3D — TRS helpers ────────────────────────────────────────────\n\n  /**\n   * Rotate by a unit quaternion [x,y,z,w].\n   * @method rotateQuat\n   * @memberof p5.Renderer3D\n   * @param {Float32Array|ArrayLike} q  Unit quaternion [x,y,z,w].\n   * @param {{ eps?:number }} [opts]\n   * @returns {p5.Renderer3D} this\n   */\n  p5.Renderer3D.prototype.rotateQuat = function (q, opts) {\n    const p = this._pInst, eps = opts?.eps ?? 1e-8;\n    const x=q[0], y=q[1], z=q[2];\n    const sinHalf = Math.sqrt(x*x + y*y + z*z);\n    if (sinHalf < eps) return this;\n    const angle = 2 * Math.atan2(sinHalf, q[3]);\n    p.rotate(angle, [x/sinHalf, y/sinHalf, z/sinHalf]);\n    return this;\n  };\n\n  /**\n   * Apply a TRS pose { pos, rot, scl } to the current transform stack.\n   * @method applyPose\n   * @memberof p5.Renderer3D\n   * @param {{ pos?:ArrayLike, rot?:ArrayLike, scl?:ArrayLike }} pose\n   * @returns {p5.Renderer3D} this\n   */\n  p5.Renderer3D.prototype.applyPose = function (pose) {\n    if (!pose) return this;\n    const p = this._pInst;\n    if (pose.pos) p.translate(pose.pos[0], pose.pos[1], pose.pos[2]);\n    if (pose.rot) this.rotateQuat(pose.rot);\n    if (pose.scl) p.scale(pose.scl[0], pose.scl[1], pose.scl[2]);\n    return this;\n  };\n\n  /** @method rotateQuat @memberof p5 */\n  fn.rotateQuat = function (q, opts) { this._renderer.rotateQuat(q, opts); return this; };\n  /** @method applyPose @memberof p5 */\n  fn.applyPose  = function (pose)    { this._renderer.applyPose(pose);     return this; };\n\n  // ── p5.Camera — capturePose / applyPose ────────────────────────────────────\n\n  /**\n   * Read the live camera state into a { eye, center, up, fov, halfHeight,\n   * near, far } object.\n   *\n   * - `eye`    ← [eyeX, eyeY, eyeZ]\n   * - `center` ← [centerX, centerY, centerZ]\n   * - `up`     ← [upX, upY, upZ]  (the hint p5 stores, not the orthogonalised up)\n   *\n   * Reads cam.upX/Y/Z directly — always the real hint, correct for both\n   * upright cameras (up=[0,1,0]) and pole-flipped cameras (up=[0,-1,0]).\n   *\n   * Also captures the camera's projection (read from `this.projMatrix` —\n   * the camera's own projection matrix, populated by `cam.perspective()`,\n   * `cam.ortho()`, or `cam.frustum()`. Does NOT depend on the camera\n   * being active on the renderer, so `otherCam.capturePose()` returns\n   * otherCam's actual projection regardless of what's live):\n   *   fov        — vertical fov (radians) for perspective cameras; null for ortho.\n   *   halfHeight — world-unit half-height of ortho frustum; null for perspective.\n   *   near, far  — clip plane distances (positive). Always real — extracted\n   *                from the projection matrix regardless of projection type.\n   *                Falls back to (0.1, 1000) when no projection matrix is\n   *                populated (e.g. pre-setup()).\n   *\n   * Pass a pre-allocated out to avoid allocation per frame:\n   * ```js\n   * const out = { eye:[0,0,0], center:[0,0,0], up:[0,1,0],\n   *               fov:null, halfHeight:null, near:0.1, far:1000 }\n   * track.add(cam.capturePose(out))\n   * ```\n   *\n   * @method capturePose\n   * @memberof p5.Camera\n   * @param {{ eye:number[], center:number[], up:number[],\n   *           fov:number|null, halfHeight:number|null,\n   *           near:number, far:number }} [out]\n   * @returns {{ eye:number[], center:number[], up:number[],\n   *             fov:number|null, halfHeight:number|null,\n   *             near:number, far:number }}\n   */\n  p5.Camera.prototype.capturePose = function (out) {\n    out = out || {\n      eye:[0,0,0], center:[0,0,0], up:[0,1,0],\n      fov:null, halfHeight:null,\n      near:0.1, far:1000,\n    };\n    out.eye[0]    = this.eyeX;    out.eye[1]    = this.eyeY;    out.eye[2]    = this.eyeZ;\n    out.center[0] = this.centerX; out.center[1] = this.centerY; out.center[2] = this.centerZ;\n    out.up[0]     = this.upX !== undefined ? this.upX : 0;\n    out.up[1]     = this.upY !== undefined ? this.upY : 1;\n    out.up[2]     = this.upZ !== undefined ? this.upZ : 0;\n    // Read the camera's own projection — not the renderer's live state.\n    // this.projMatrix is populated by cam.perspective / ortho / frustum,\n    // and by the default camera setup during createCamera().\n    const pMat = this.projMatrix?.mat4;\n    if (pMat) {\n      const ndcZ = getNdcZ();\n      if (projIsOrtho(pMat)) {\n        out.fov        = null;\n        out.halfHeight = projTop(pMat, ndcZ);\n      } else {\n        out.fov        = projFov(pMat);\n        out.halfHeight = null;\n      }\n      out.near = projNear(pMat, ndcZ);\n      out.far  = projFar(pMat);\n    } else {\n      out.fov = null; out.halfHeight = null;\n      out.near = 0.1; out.far = 1000;\n    }\n    return out;\n  };\n\n  /**\n   * Apply a { eye, center, up, fov?, halfHeight?, near?, far? } pose to this\n   * camera. Calls cam.camera(eye, center, up) directly — no matrix\n   * reconstruction, no up_ortho drift, exact roundtrip from capturePose().\n   *\n   * The projection is applied when fov or halfHeight is non-null:\n   *   fov set        — perspective(fov, aspect, near, far)\n   *   halfHeight set — ortho(-hw*aspect, hw*aspect, -hw, hw, near, far)\n   *\n   * `near` / `far` on the pose are used when present, falling back to\n   * (0.1, 1000) for back-compat with hand-built poses that predate those\n   * fields.\n   *\n   * Also handles legacy { pos, rot, scl } TRS poses from PoseTrack for\n   * object-on-camera effects (translate/rotate only; scl is ignored).\n   *\n   * @method applyPose\n   * @memberof p5.Camera\n   * @param {{ eye:number[], center:number[], up:number[],\n   *           fov?:number|null, halfHeight?:number|null,\n   *           near?:number, far?:number } |\n   *          { pos:number[], rot:number[], scl?:number[] }} pose\n   * @returns {p5.Camera} this\n   */\n  p5.Camera.prototype.applyPose = function (pose) {\n    if (!pose) return this;\n\n    // { eye, center, up } — native CameraTrack output\n    if (pose.eye && pose.center) {\n      const up = pose.up || [0,1,0];\n      this.camera(\n        pose.eye[0],    pose.eye[1],    pose.eye[2],\n        pose.center[0], pose.center[1], pose.center[2],\n        up[0],          up[1],          up[2]\n      );\n      const near = pose.near ?? 0.1;\n      const far  = pose.far  ?? 1000;\n      if (pose.fov != null) {\n        const aspect = (this._renderer.width / this._renderer.height) || 1;\n        this.perspective(pose.fov, aspect, near, far);\n      } else if (pose.halfHeight != null) {\n        const aspect = (this._renderer.width / this._renderer.height) || 1;\n        const hw = pose.halfHeight;\n        this.ortho(-hw * aspect, hw * aspect, -hw, hw, near, far);\n      }\n      return this;\n    }\n\n    // { pos, rot } — TRS form (translates + rotates the view)\n    // Useful for animating the camera like an object (shake, bob, etc.)\n    if (pose.pos && pose.rot) {\n      const rm = new Float32Array(16);\n      qToMat4(rm, pose.rot);\n      const upX=rm[4], upY=rm[5], upZ=rm[6];\n      const fwdX=-rm[8], fwdY=-rm[9], fwdZ=-rm[10];\n      const dx=this.centerX-this.eyeX, dy=this.centerY-this.eyeY, dz=this.centerZ-this.eyeZ;\n      const dist = Math.sqrt(dx*dx + dy*dy + dz*dz) || 1;\n      this.camera(\n        pose.pos[0], pose.pos[1], pose.pos[2],\n        pose.pos[0]+fwdX*dist, pose.pos[1]+fwdY*dist, pose.pos[2]+fwdZ*dist,\n        upX, upY, upZ\n      );\n    }\n    return this;\n  };\n}\n","/**\n * @file Shared vanilla DOM element factories.\n * @module ui/dom\n * @license AGPL-3.0-only\n *\n * Zero dependencies — no p5, no framework.\n * Each function creates and returns a raw HTMLElement.\n * CSS class names use prefix 'p5t-' for easy user overrides.\n */\n\n\nconst CLS = 'p5t';\n\nfunction _el(tag, cls, attrs) {\n  const e = document.createElement(tag);\n  if (cls) e.className = `${CLS}-${cls}`;\n  if (attrs) for (const k in attrs) e.setAttribute(k, attrs[k]);\n  return e;\n}\n\n/** Flex-column container, absolute positioned. */\nfunction createContainer(cls) {\n  const c = _el('div', cls || 'ui');\n  c.style.cssText = 'position:absolute;display:flex;flex-direction:column;gap:0px;';\n  return c;\n}\n\n/** Range slider. onChange receives parsed float. */\nfunction createSlider(min, max, value, step, onChange) {\n  const s = _el('input', 'slider', { type: 'range', min, max, step });\n  s.value = value;\n  if (onChange) s.addEventListener('input', () => onChange(parseFloat(s.value)));\n  return s;\n}\n\n/** Push button. */\nfunction createButton(label, onClick) {\n  const b = _el('button', 'btn');\n  b.textContent = label;\n  if (onClick) b.addEventListener('click', onClick);\n  return b;\n}\n\n/**\n * Checkbox with label text.\n * Returns the <label> element. Access the <input> via `.firstChild`.\n */\nfunction createCheckbox(label, checked, onChange) {\n  const lab = _el('label', 'check');\n  const inp = _el('input', null, { type: 'checkbox' });\n  inp.checked = !!checked;\n  lab.appendChild(inp);\n  lab.appendChild(document.createTextNode(' ' + label));\n  if (onChange) inp.addEventListener('change', () => onChange(inp.checked));\n  return lab;\n}\n\n/** Dropdown select. Options: array of values or { label, value } objects. */\nfunction createSelect(options, value, onChange) {\n  const s = _el('select', 'select');\n  (options || []).forEach(o => {\n    const opt = document.createElement('option');\n    if (o && typeof o === 'object') {\n      opt.value = o.value;\n      opt.textContent = o.label ?? `${o.value}`;\n    } else {\n      opt.value = o;\n      opt.textContent = `${o}`;\n    }\n    s.appendChild(opt);\n  });\n  if (value != null) s.value = value;\n  return s;\n}\n\n/** Color picker. onChange receives hex string. */\nfunction createColorPicker(value, onChange) {\n  const c = _el('input', 'color', { type: 'color' });\n  c.value = value || '#ffffff';\n  return c;\n}\n\n/** Text label (span). */\nfunction createLabel(text) {\n  const l = _el('span', 'label');\n  l.textContent = text;\n  return l;\n}\n\n// ── Color helpers (no p5 dependency) ────────────────────────────────────────\n\n/** '#rrggbb' -> [r, g, b, a] normalised 0-1 */\nfunction hexToVec4(hex) {\n  const h = (hex || '#000000').replace('#', '');\n  return [\n    parseInt(h.substring(0, 2), 16) / 255,\n    parseInt(h.substring(2, 4), 16) / 255,\n    parseInt(h.substring(4, 6), 16) / 255,\n    1.0\n  ];\n}\n\n/** [r, g, b (, a)] normalised 0-1 -> '#rrggbb' */\nfunction vec4ToHex(v) {\n  const c = n => Math.round(Math.max(0, Math.min(1, n ?? 0)) * 255)\n                    .toString(16).padStart(2, '0');\n  return `#${c(v[0])}${c(v[1])}${c(v[2])}`;\n}\n\n// ── Visibility helpers (Safari-safe) ────────────────────────────────────────\n\n/**\n * Show/hide a DOM element robustly.\n * Uses a data attribute to remember the previous display value so that\n * Safari input[range] workarounds are preserved on re-show.\n * @param {HTMLElement} el\n * @param {boolean} show\n */\nfunction setVisible(el, show) {\n  if (!el || !el.style) return;\n  if (show) {\n    const prev = el.dataset?._uiDisplay;\n    el.style.display = prev != null ? prev : '';\n    if (el.dataset) delete el.dataset._uiDisplay;\n  } else {\n    if (el.dataset) el.dataset._uiDisplay ??= el.style.display || '';\n    el.style.display = 'none';\n  }\n}\n\n/**\n * Append `child` to `parent`, ensuring parent has non-static positioning\n * so absolute children are anchored correctly.\n * Falls back to `document.body` when parent is null/undefined.\n * @param {HTMLElement} child\n * @param {HTMLElement|null} [parent]\n */\nfunction mount(child, parent) {\n  const p = parent || document.body;\n  if (p.style && getComputedStyle(p).position === 'static') {\n    p.style.position = 'relative';\n  }\n  p.appendChild(child);\n}\n\n/**\n * @file Schema-driven parameter panel — binds named controls to a target.\n * @module ui/bindUI\n * @license AGPL-3.0-only\n *\n * Zero p5 dependencies.  Pure vanilla DOM.\n *\n * ---------------------------------------------------------------------------\n * Core concept — binding\n * ---------------------------------------------------------------------------\n * A schema maps parameter names to control definitions.  Each entry produces\n * a DOM control whose value is *bound* to that name in two directions:\n *\n *   user interaction  →  control value changes  →  dirty flag set\n *   tick()            →  dirty controls pushed  →  target(name, value)\n *\n * The target is any receiver that accepts (name, value) pairs:\n *   target(name, value)          plain function\n *   target.set(name, value)      object with set method\n *\n * When target is omitted, bindings are read-only: values are accessible via\n * ui[name].value() but never pushed anywhere automatically.\n *\n * The term \"binding\" is intentional — this is the same concept used in shader\n * systems (uniform bindings), game-engine inspectors (property bindings), and\n * data-binding frameworks.  The schema key is the binding name; the control is\n * the binding's UI representation; the target is the binding's sink.\n *\n * ---------------------------------------------------------------------------\n * Tick model\n * ---------------------------------------------------------------------------\n * Designed for rendering pipelines where a host clock calls tick() once per\n * frame — the same clock that drives PoseTrack playback.\n *\n * Values are pushed to the target at most once per control per frame and only\n * when the control has changed since the last push (_dirty flag).  The first\n * tick always pushes all values to initialise target state.\n *\n * Multiple user interactions within a single frame (rapid slider drag,\n * programmatic set() calls) collapse to one push at tick() time.  This is the\n * correct behaviour for rendering sinks (shaders, scene params).  It is not\n * suitable for sinks that require every intermediate delta.\n *\n * ---------------------------------------------------------------------------\n * Supported control types (explicit or inferred from schema value)\n * ---------------------------------------------------------------------------\n * 'float'  : slider          'int'    : slider (integer step)\n * 'bool'   : checkbox        'color'  : color picker (→ normalised RGBA vec4)\n * 'vec2'   : 2 sliders       'vec3'   : 3 sliders      'vec4' : 4 sliders\n * 'select' : dropdown        'button' : action button (no value push)\n *\n * Type inference (when cfg.type is omitted):\n *   cfg.options        → 'select'\n *   cfg.onClick fn     → 'button'\n *   boolean value      → 'bool'\n *   array [2..4]       → 'vec2'/'vec3'/'vec4'\n *   string value       → 'color'\n *   number / default   → 'float'\n *\n * ---------------------------------------------------------------------------\n * Returned API\n * ---------------------------------------------------------------------------\n *   ui.el                       HTMLElement (container)\n *   ui.visible        get/set   boolean — whole panel visibility\n *   ui.collapsed      get/set   boolean — body visibility (requires collapsible+title)\n *   ui[name].visible  get/set   boolean — per-binding visibility\n *   ui[name].value()            current bound value\n *   ui[name].set(v)             set programmatically (marks dirty → pushed on next tick)\n *   ui[name].reset()            restore initial value (marks dirty)\n *   ui.each(fn)                 iterate bindings in schema order\n *   ui.elts()                   flat array of all bound DOM elements\n *   ui.reset()                  reset all bindings\n *   ui.parent(el)               re-mount container into a new parent HTMLElement\n *   ui.tick()                   push dirty bindings to target — call once per frame\n *   ui.dispose()                remove DOM, detach listeners\n */\n\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nconst isBool  = v => typeof v === 'boolean';\nconst isArr   = Array.isArray;\nconst isVec   = v => isArr(v) && v.length >= 2 && v.length <= 4;\nconst isStr   = v => typeof v === 'string';\nconst toFloat = v => { const n = parseFloat(v); return Number.isFinite(n) ? n : 0; };\n\nfunction inferType(cfg) {\n  if (cfg.type) return cfg.type;\n  if (cfg.options) return 'select';\n  if (typeof cfg.onClick === 'function') return 'button';\n  const v = cfg.value;\n  if (isBool(v)) return 'bool';\n  if (isVec(v)) return ['', 'vec2', 'vec3', 'vec4'][v.length] || 'vec4';\n  if (isStr(v)) return 'color';\n  return 'float';\n}\n\n// ── Factory ──────────────────────────────────────────────────────────────────\n\n/**\n * Build a parameter panel with named bindings.\n *\n * @param {Object<string,Object>} schema  Binding definitions keyed by name.\n * @param {Object} [opt]   Layout options.\n * @param {Function|Object} [opt.target]\n *   If a function `(name, value) => ...`, called for every binding on tick.\n *   If an object with `.set(name, value)`, that method is called instead.\n *   If omitted, read values manually via `ui[name].value()`.\n * @param {number}  [opt.x=0]            Container left (px).\n * @param {number}  [opt.y=0]            Container top (px).\n * @param {number}  [opt.width=120]      Default slider/select width (px).\n * @param {number}  [opt.offset=6]       Vertical gap between rows (px).\n * @param {string}  [opt.color]          Container text color.\n * @param {boolean} [opt.hidden=false]   Start hidden.\n * @param {boolean} [opt.labels=false]   Show per-binding labels.\n * @param {string}  [opt.title]          Bold title row.\n * @param {boolean} [opt.collapsible]    Make title row a collapse toggle (requires title).\n * @param {boolean} [opt.collapsed]      Start collapsed (requires collapsible + title).\n * @param {HTMLElement} [opt.parent]     Mount target (defaults to document.body).\n * @returns {Object} Panel handle — see \"Returned API\" above.\n */\nfunction createUI(schema, opt) {\n  schema = schema || {};\n  opt    = opt    || {};\n  const _target = opt.target || null;\n\n  const _order      = Object.keys(schema);\n  const _defaults   = {};\n  const _labels     = {};\n  const _w          = opt.width  ?? 120;\n  const _off        = opt.offset ?? 6;\n  const _showLabels = !!opt.labels;\n\n  const ui        = {};\n  const container = createContainer('param-ui');\n  container.style.left = `${opt.x ?? 0}px`;\n  container.style.top  = `${opt.y ?? 0}px`;\n  if (opt.color) container.style.color = opt.color;\n\n  let _vis = true;\n\n  // ── Collapsible setup ─────────────────────────────────────────────────────\n  // body is the content wrapper — everything below the title goes here.\n  // When not collapsible it's transparent: same layout, no extra click target.\n\n  const canCollapse = !!(opt.title && (opt.collapsible || 'collapsed' in opt));\n  let _collapsed    = canCollapse && !!opt.collapsed;\n\n  const body = document.createElement('div');\n  body.className = 'p5t-body';\n  body.style.cssText = 'display:flex;flex-direction:column;gap:0px;';\n\n  // ── Title ─────────────────────────────────────────────────────────────────\n\n  let chevron = null;\n  if (opt.title) {\n    const titleRow = document.createElement('div');\n    titleRow.style.cssText = 'display:flex;align-items:center;justify-content:space-between;';\n    titleRow.style.marginBottom = `${_off}px`;\n\n    const titleLabel = createLabel(opt.title);\n    titleLabel.style.fontWeight = 'bold';\n    titleRow.appendChild(titleLabel);\n\n    if (canCollapse) {\n      chevron = createLabel(_collapsed ? '\\u25B6' : '\\u25BC');\n      chevron.style.cssText = 'cursor:pointer;user-select:none;margin-left:6px;';\n      titleRow.style.cursor = 'pointer';\n      titleRow.appendChild(chevron);\n      titleRow.addEventListener('click', () => {\n        _collapsed = !_collapsed;\n        _applyCollapse();\n      });\n    }\n\n    container.appendChild(titleRow);\n  }\n\n  // ── Per-binding builder ───────────────────────────────────────────────────\n\n  function _setGap(el) { el.style.marginBottom = `${_off}px`; }\n\n  function addLabel(name, cfg) {\n    if (!_showLabels) return;\n    const l = createLabel(cfg.label || name);\n    l.style.marginBottom = `${_off}px`;\n    body.appendChild(l);\n    _labels[name] = l;\n  }\n\n  function wrap(name, type, el, value, set, reset) {\n    const c = { type, el, value, _dirty: true, _vis: true };\n    // set/reset mark dirty so the bound value is pushed on the next tick.\n    c.set   = v  => { set(v);  c._dirty = true; };\n    c.reset = () => { reset(); c._dirty = true; };\n    Object.defineProperty(c, 'visible', {\n      get() { return c._vis; },\n      set(v) {\n        c._vis = v !== false;\n        applyControlVis(name);\n      }\n    });\n    return c;\n  }\n\n  function applyControlVis(name) {\n    const c = ui[name];\n    if (!c) return;\n    const show = _vis && c._vis;\n    const els  = isArr(c.el) ? c.el : [c.el];\n    els.forEach(e => setVisible(e, show));\n    _labels[name] && setVisible(_labels[name], show);\n  }\n\n  function buildControl(name, cfg) {\n    cfg = cfg || {};\n    const type = inferType(cfg);\n    const w    = cfg.width ?? _w;\n\n    addLabel(name, cfg);\n\n    // ── bool ──\n    if (type === 'bool') {\n      const el  = createCheckbox('', cfg.value ?? false);\n      _setGap(el);\n      body.appendChild(el);\n      const inp = el.firstChild;\n      const c = wrap(name, 'bool', el,\n        () => inp.checked,\n        v  => { inp.checked = !!v; },\n        () => { inp.checked = !!_defaults[name]; }\n      );\n      inp.addEventListener('change', () => { c._dirty = true; });\n      return c;\n    }\n\n    // ── button ──\n    if (type === 'button') {\n      const el = createButton(cfg.label || name,\n        typeof cfg.onClick === 'function' ? cfg.onClick : null);\n      el.style.width = `${w}px`;\n      _setGap(el);\n      body.appendChild(el);\n      return wrap(name, 'button', el, () => null, () => {}, () => {});\n    }\n\n    // ── select ──\n    if (type === 'select') {\n      const el = createSelect(cfg.options, cfg.value);\n      el.style.width = `${w}px`;\n      _setGap(el);\n      body.appendChild(el);\n      const c = wrap(name, 'select', el,\n        () => el.value,\n        v  => { el.value = v; },\n        () => { el.value = _defaults[name]; }\n      );\n      el.addEventListener('change', () => { c._dirty = true; });\n      return c;\n    }\n\n    // ── color ──\n    if (type === 'color') {\n      const el = createColorPicker(cfg.value);\n      el.style.width = `${w}px`;\n      _setGap(el);\n      body.appendChild(el);\n      const c = wrap(name, 'color', el,\n        () => hexToVec4(el.value),\n        v  => { el.value = isStr(v) ? v : isArr(v) ? vec4ToHex(v) : v; },\n        () => { el.value = _defaults[name] || '#ffffff'; }\n      );\n      el.addEventListener('input', () => { c._dirty = true; });\n      return c;\n    }\n\n    // ── vec2 / vec3 / vec4 ──\n    if (type === 'vec2' || type === 'vec3' || type === 'vec4') {\n      const n    = type === 'vec2' ? 2 : type === 'vec3' ? 3 : 4;\n      const vals = isArr(cfg.value) ? cfg.value : new Array(n).fill(0);\n      const min  = cfg.min  ?? 0;\n      const max  = cfg.max  ?? 1;\n      const step = cfg.step ?? (cfg.type === 'int' ? 1 : 0.01);\n      const els  = [];\n      for (let i = 0; i < n; i++) {\n        const s = createSlider(min, max, toFloat(vals[i] ?? 0), step);\n        s.style.width = `${w}px`;\n        _setGap(s);\n        body.appendChild(s);\n        els.push(s);\n      }\n      const c = wrap(name, type, els,\n        ()    => els.map(s => toFloat(s.value)),\n        arr   => { isArr(arr) && els.forEach((s, i) => { s.value = toFloat(arr[i] ?? 0); }); },\n        ()    => { const d = _defaults[name]; isArr(d) && els.forEach((s, i) => { s.value = toFloat(d[i] ?? 0); }); }\n      );\n      els.forEach(s => s.addEventListener('input', () => { c._dirty = true; }));\n      return c;\n    }\n\n    // ── float / int (default) ──\n    const val  = toFloat(cfg.value ?? 0);\n    const min  = cfg.min  ?? 0;\n    const max  = cfg.max  ?? 1;\n    const step = cfg.step ?? (cfg.type === 'int' ? 1 : 0.01);\n    const el   = createSlider(min, max, val, step);\n    el.style.width = `${w}px`;\n    _setGap(el);\n    body.appendChild(el);\n    const c = wrap(name, cfg.type === 'int' ? 'int' : 'float', el,\n      () => toFloat(el.value),\n      v  => { el.value = toFloat(v); },\n      () => { el.value = toFloat(_defaults[name]); }\n    );\n    el.addEventListener('input', () => { c._dirty = true; });\n    return c;\n  }\n\n  // ── Build all bindings ─────────────────────────────────────────────────\n\n  _order.forEach(name => {\n    _defaults[name] = schema[name] ? schema[name].value : null;\n    ui[name] = buildControl(name, schema[name]);\n  });\n\n  container.appendChild(body);\n\n  // ── Collapse helper ────────────────────────────────────────────────────\n\n  function _applyCollapse() {\n    body.style.display = _collapsed ? 'none' : 'flex';\n    if (chevron) chevron.textContent = _collapsed ? '\\u25B6' : '\\u25BC';\n  }\n\n  // ── Container visibility ───────────────────────────────────────────────\n\n  function setContainerVis(show) {\n    _vis = show !== false;\n    if (_vis) {\n      container.style.display       = 'flex';\n      container.style.visibility    = 'visible';\n      container.style.pointerEvents = 'auto';\n    } else {\n      container.style.display       = 'none';\n      container.style.visibility    = 'hidden';\n      container.style.pointerEvents = 'none';\n    }\n    _order.forEach(applyControlVis);\n  }\n\n  Object.defineProperty(ui, 'visible', {\n    get() { return _vis; },\n    set(v) { setContainerVis(v); }\n  });\n\n  Object.defineProperty(ui, 'collapsed', {\n    get() { return _collapsed; },\n    set(v) {\n      if (!canCollapse) return;\n      _collapsed = !!v;\n      _applyCollapse();\n    }\n  });\n\n  // ── Public API ─────────────────────────────────────────────────────────\n\n  ui.el = container;\n\n  ui.each = fn => {\n    if (typeof fn !== 'function') return;\n    _order.forEach(name => fn(name, ui[name]));\n  };\n\n  ui.elts = () => {\n    const out = [];\n    ui.each((_, c) => {\n      if (!c || !c.el) return;\n      isArr(c.el) ? c.el.forEach(e => e && out.push(e)) : out.push(c.el);\n    });\n    return out;\n  };\n\n  ui.reset = () => {\n    _order.forEach(name => { const c = ui[name]; c && c.reset(); });\n  };\n\n  /**\n   * Re-mount container into a new parent HTMLElement.\n   * Accepts a raw HTMLElement (p5.Element unwrapping is the bridge's job).\n   * @param {HTMLElement} el\n   */\n  ui.parent = el => mount(container, el);\n\n  /**\n   * Push dirty bindings to target. Call once per frame.\n   *\n   * Invariant: the target is called at most once per binding per frame,\n   * and only if the bound value changed since the last push.\n   * The first tick always pushes all bindings to initialise target state.\n   */\n  ui.tick = () => {\n    if (!_target) return;\n    const push = typeof _target === 'function'\n      ? _target\n      : typeof _target.set === 'function'\n        ? (name, value) => _target.set(name, value)\n        : null;\n    if (!push) return;\n    _order.forEach(name => {\n      const c = ui[name];\n      if (!c || c.type === 'button' || !c._dirty) return;\n      c._dirty = false;\n      push(name, c.value());\n    });\n  };\n\n  /** Remove container from DOM. */\n  ui.dispose = () => {\n    container.parentNode && container.parentNode.removeChild(container);\n  };\n\n  // ── Mount & initial state ──────────────────────────────────────────────\n\n  mount(container, opt.parent);\n  setContainerVis(!opt.hidden);\n  _applyCollapse();\n\n  return ui;\n}\n\n/**\n * @file DOM-based transport controls for PoseTrack (or any compatible target).\n * @module ui/trackUI\n * @license AGPL-3.0-only\n *\n * Zero p5 dependencies.  Pure vanilla DOM.\n *\n * Transport model\n * ---------------\n *   The Play/Pause button is the **sole** control that starts or stops playback.\n *   The rate slider adjusts speed while playing but never starts or stops.\n *   rate === 0 is treated as \"frozen\" — playback state is unchanged.\n *   The seek slider scrubs position without affecting the playing flag.\n *   The loop checkbox and bounce checkbox change looping behaviour without\n *   starting playback.\n *\n * Loop modes\n * ----------\n *   loop:false, bounce:false  — play once, stop at end\n *   loop:true,  bounce:false  — repeat, wrap back to start\n *   loop:true,  bounce:true   — bounce forever at boundaries\n *   loop:false, bounce:true   — bounce once: flip at far boundary, stop at origin\n *\n *   bounce and loop are independent — no exclusivity enforced.\n *   Both checkboxes are always visible.\n *\n * Target contract (duck-typed)\n * ----------------------------\n *   target.play(opts?)   Start or update playback.\n *   target.stop()        Stop playback.\n *   target.seek(t)       Set normalised position [0, 1].\n *   target.time()        Returns normalised position [0, 1].\n *   target.playing       Boolean — true while playing.\n *   target._onPlay       Reserved lib-space slot — assigned by this panel.\n *   target._onEnd        Reserved lib-space slot — assigned by this panel.\n *   target._onStop       Reserved lib-space slot — assigned by this panel.\n *\n * Optional:\n *   target.add(d?)       Add keyframe at depth d [0..1] (near..far plane centre).\n *   target.reset()       Clear all keyframes and stop.\n *   target.info()        Returns { keyframes, segments, seg, f, time, ... }.\n *\n * State initialisation\n * --------------------\n *   _rate is seeded once at creation from the live track state (target.rate)\n *   with opt.rate as fallback.  After creation rate is fully UI-owned — the\n *   panel never reads rate back from the track.  This prevents spurious slider\n *   snaps when external play() calls omit rate (e.g. play({ bounce: true })).\n *\n *   _loop and _bounce are seeded the same way and additionally polled from\n *   the track every tick() while playing, so external play() calls that change\n *   loop/bounce mode are always reflected.\n *\n * Layout (top → bottom)\n * ---------------------\n *   Title row  — optional, becomes collapse toggle when collapsible=true\n *   Row 1  — controls:  [+]  [▶/⏸]  [↺]   (each independently optional)\n *   Row 1b — depth:     depth slider        (when target supports add)\n *   Row 2  — seek:      seek slider         (hidden when keyframes ≤ 1)\n *   Row 3  — rate:      rate label + slider (when showProps)\n *   Row 4  — loop + bounce: both checkboxes always visible, independent\n *   Row 5  — info:      time / keyframe     (when showInfo)\n *\n * Returned API\n * ------------\n *   ui.el              HTMLElement container\n *   ui.visible         get/set boolean\n *   ui.collapsed       get/set boolean (requires collapsible + title)\n *   ui.parent(el)      Re-mount container into a new parent HTMLElement.\n *   ui.tick()          Sync seek slider, play button, and enabled state from target.\n *   ui.dispose()       Remove DOM and clear lib-space hooks.\n */\n\n\n/**\n * Build a track transport UI.\n *\n * @param {Object} target    PoseTrack (or duck-compatible object).\n * @param {Object} [opt]     Options.\n * @param {boolean} [opt.seek=true]       Show seek slider.\n * @param {boolean} [opt.props=true]      Show rate slider + loop controls.\n * @param {boolean} [opt.info=false]      Show time/keyframe readout.\n * @param {boolean} [opt.play=true]       Show play/pause button. false hides it —\n *                                        seek slider becomes the sole transport control.\n * @param {number}  [opt.rate=1]          Initial rate (overridden by target.rate if set).\n * @param {boolean} [opt.loop=false]      Initial loop state (overridden by target.loop).\n * @param {boolean} [opt.bounce=false]    Initial bounce state (overridden by target.bounce).\n * @param {number}  [opt.depth=0.5]       Initial add-pose depth [0..1]: 0 = near, 1 = far.\n * @param {number}  [opt.x=0]            Container left (px).\n * @param {number}  [opt.y=0]            Container top (px).\n * @param {number}  [opt.width=220]      Slider width (px).\n * @param {number}  [opt.rateWidth]      Rate slider width (px). Defaults to opt.width.\n * @param {number}  [opt.depthWidth]     Depth slider width (px). Defaults to opt.width.\n * @param {string}  [opt.color]          Text color.\n * @param {boolean} [opt.hidden=false]   Start hidden.\n * @param {string}  [opt.title]          Optional title row.\n * @param {boolean} [opt.collapsible]    Make title row a collapse toggle (requires title).\n * @param {boolean} [opt.collapsed]      Start collapsed (requires collapsible + title).\n * @param {HTMLElement} [opt.parent]     Mount target (defaults to document.body).\n * @returns {Object} UI handle.\n */\nfunction createTrackUI(target, opt) {\n  opt = opt || {};\n\n  const showSeek  = opt.seek  !== false;\n  const showProps = opt.props !== false;\n  const showInfo  = opt.info  === true;\n  const showPlay  = opt.play  !== false;\n  const sliderW      = opt.width      ?? 120;\n  const rateSliderW  = opt.rateWidth  ?? sliderW;\n  const depthSliderW = opt.depthWidth ?? sliderW;\n\n  // ── Seed _rate, _loop, _bounce from live track state, fall back to opt ──\n\n  let _rate   = (typeof target.rate === 'number') ? target.rate : (opt.rate ?? 1);\n  let _loop   = !!(target.loop   || opt.loop);\n  let _bounce = !!(target.bounce || opt.bounce);\n  let _depth  = (typeof opt.depth === 'number') ? opt.depth : 0.5;\n\n  const container = createContainer('track-ui');\n  container.style.left = `${opt.x ?? 0}px`;\n  container.style.top  = `${opt.y ?? 0}px`;\n  if (opt.color) container.style.color = opt.color;\n\n  let _vis     = true;\n  let _seeking = false;\n  let _lastKf  = -1;\n\n  /** Assemble play() options from current UI state. */\n  function _playOpts() {\n    return { rate: _rate, loop: _loop, bounce: _bounce };\n  }\n\n  /** Keyframe count from target.info(), or -1 if unavailable. */\n  function _kfCount() {\n    return (typeof target.info === 'function') ? target.info().keyframes : -1;\n  }\n\n  // ── Collapsible setup ─────────────────────────────────────────────────────\n\n  const canCollapse = !!(opt.title && (opt.collapsible || 'collapsed' in opt));\n  let _collapsed    = canCollapse && !!opt.collapsed;\n  let chevron       = null;\n\n  const body = document.createElement('div');\n  body.className = 'p5t-body';\n  body.style.cssText = 'display:flex;flex-direction:column;gap:0px;';\n\n  // ── Title row (optional) ──────────────────────────────────────────────────\n\n  if (opt.title) {\n    const titleRow = document.createElement('div');\n    titleRow.style.cssText = 'display:flex;align-items:center;justify-content:space-between;margin-bottom:4px;';\n\n    const titleLabel = createLabel(opt.title);\n    titleLabel.style.fontWeight = 'bold';\n    titleRow.appendChild(titleLabel);\n\n    if (canCollapse) {\n      chevron = createLabel(_collapsed ? '\\u25B6' : '\\u25BC');\n      chevron.style.cssText = 'cursor:pointer;user-select:none;margin-left:6px;';\n      titleRow.style.cursor = 'pointer';\n      titleRow.appendChild(chevron);\n      titleRow.addEventListener('click', () => {\n        _collapsed = !_collapsed;\n        _applyCollapse();\n      });\n    }\n\n    container.appendChild(titleRow);\n  }\n\n  // ── Row 1 — controls: [+] [▶/⏸] [↺] ─────────────────────────────────────\n  //\n  // Each button is independently optional:\n  //   hasAdd   — target exposes add()          (+ button)\n  //   showPlay — opt.play !== false            (play/pause button)\n  //   hasReset — target exposes reset()        (reset button)\n  //\n  // The row is only appended when at least one button is present, so that\n  // fully button-free panels produce no empty DOM row.\n\n  const ctrlRow = document.createElement('div');\n  ctrlRow.className = 'p5t-controls';\n  ctrlRow.style.cssText = 'display:flex;gap:4px;margin-bottom:4px;align-items:center;';\n\n  const hasAdd = typeof target.add === 'function';\n  if (hasAdd) {\n    const btnAdd = createButton('\\u002B', () => {\n      target.add(_depth);\n      _lastKf = -1;\n    });\n    btnAdd.title = 'Add keyframe';\n    ctrlRow.appendChild(btnAdd);\n  }\n\n  let btnPlay = null;\n  if (showPlay) {\n    btnPlay = createButton('\\u25B6', () => {\n      if (target.playing) {\n        target.stop();\n      } else {\n        target.play(_playOpts());\n      }\n      _syncPlayBtn();\n    });\n    btnPlay.title = 'Play / Pause';\n    ctrlRow.appendChild(btnPlay);\n  }\n\n  let btnReset = null;\n  const hasReset = typeof target.reset === 'function';\n  if (hasReset) {\n    btnReset = createButton('\\u21BA', () => {\n      target.reset();\n      _syncPlayBtn();\n      _lastKf = -1;\n    });\n    btnReset.title = 'Reset (clear keyframes)';\n    ctrlRow.appendChild(btnReset);\n  }\n\n  if (hasAdd || showPlay || hasReset) {\n    body.appendChild(ctrlRow);\n  }\n\n  // ── Row 1b — depth slider ─────────────────────────────────────────────────\n\n  if (hasAdd && opt.depth !== false) {\n    const depthRow = document.createElement('div');\n    depthRow.className = 'p5t-depth';\n    depthRow.style.cssText = 'display:flex;align-items:center;gap:6px;margin-bottom:2px;font-size:11px;';\n\n    const depthLabel = createLabel(`depth: ${_depth.toFixed(2)}`);\n    depthLabel.style.minWidth = '72px';\n\n    const depthSlider = createSlider(0, 1, _depth, 0.01, v => {\n      _depth = v;\n      depthLabel.textContent = `depth: ${v.toFixed(2)}`;\n    });\n    depthSlider.style.width = `${depthSliderW}px`;\n\n    depthRow.appendChild(depthLabel);\n    depthRow.appendChild(depthSlider);\n    body.appendChild(depthRow);\n  }\n\n  // ── Row 2 — seek slider ───────────────────────────────────────────────────\n\n  let seekSlider, seekLabel;\n  if (showSeek) {\n    const seekRow = document.createElement('div');\n    seekRow.className = 'p5t-seek';\n    seekRow.style.cssText = 'display:flex;align-items:center;gap:6px;margin-bottom:2px;font-size:11px;';\n\n    seekLabel = createLabel('seek: 0.000');\n    seekLabel.style.minWidth = '72px';\n\n    seekSlider = createSlider(0, 1, 0, 0.001, v => {\n      _seeking = true;\n      seekLabel.textContent = `seek: ${parseFloat(v).toFixed(3)}`;\n      target.seek(v);\n    });\n    seekSlider.style.width = `${sliderW}px`;\n    seekSlider.addEventListener('change',    () => { _seeking = false; });\n    seekSlider.addEventListener('pointerup', () => { _seeking = false; });\n    seekSlider.addEventListener('touchend',  () => { _seeking = false; });\n\n    seekRow.appendChild(seekLabel);\n    seekRow.appendChild(seekSlider);\n    body.appendChild(seekRow);\n  }\n\n  // ── Row 3 — rate slider ───────────────────────────────────────────────────\n\n  let rateSlider, rateLabel;\n  if (showProps) {\n    const rateRow = document.createElement('div');\n    rateRow.className = 'p5t-rate';\n    rateRow.style.cssText = 'display:flex;align-items:center;gap:6px;margin-bottom:2px;font-size:11px;';\n\n    rateLabel = createLabel(`rate: ${_rate.toFixed(2)}`);\n    rateLabel.style.minWidth = '72px';\n\n    rateSlider = createSlider(-2, 2, _rate, 0.05, v => {\n      _rate = v;\n      rateLabel.textContent = `rate: ${v.toFixed(2)}`;\n      if (target.playing) target.play({ rate: _rate });\n    });\n    rateSlider.style.width = `${rateSliderW}px`;\n\n    rateRow.appendChild(rateLabel);\n    rateRow.appendChild(rateSlider);\n    body.appendChild(rateRow);\n  }\n\n  // ── Row 4 — loop + bounce checkboxes ─────────────────────────────────────\n\n  let loopInp, bounceInp;\n\n  if (showProps) {\n    const loopRow = document.createElement('div');\n    loopRow.className = 'p5t-loop';\n    loopRow.style.cssText = 'display:flex;align-items:center;gap:6px;margin-bottom:4px;font-size:11px;';\n\n    const loopLabel = createLabel('loop:');\n    loopLabel.style.minWidth = '40px';\n\n    const loopCheck = createCheckbox('', _loop, v => {\n      _loop = v;\n      if (target.playing) target.play(_playOpts());\n    });\n    loopInp = loopCheck.firstChild;\n\n    const bounceLabel = createLabel('bounce:');\n    bounceLabel.style.marginLeft = '10px';\n\n    const bounceCheck = createCheckbox('', _bounce, v => {\n      _bounce = v;\n      if (target.playing) target.play(_playOpts());\n    });\n    bounceInp = bounceCheck.firstChild;\n\n    loopRow.appendChild(loopLabel);\n    loopRow.appendChild(loopCheck);\n    loopRow.appendChild(bounceLabel);\n    loopRow.appendChild(bounceCheck);\n    body.appendChild(loopRow);\n  }\n\n  // ── Row 5 — info label (optional) ────────────────────────────────────────\n\n  let infoLabel;\n  if (showInfo) {\n    infoLabel = createLabel('');\n    infoLabel.style.cssText = 'font-size:11px;opacity:0.8;margin-bottom:4px;';\n    body.appendChild(infoLabel);\n  }\n\n  container.appendChild(body);\n\n  // ── Lib-space hooks ───────────────────────────────────────────────────────\n\n  target._onPlay = () => { _syncPlayBtn(); };\n  target._onEnd  = () => { _syncPlayBtn(); };\n  target._onStop = () => { _syncPlayBtn(); };\n\n  // ── Internal helpers ──────────────────────────────────────────────────────\n\n  function _syncPlayBtn() {\n    if (!btnPlay) return;\n    btnPlay.textContent = target.playing ? '\\u23F8' : '\\u25B6';\n  }\n\n  function _updateEnabledState() {\n    const kf = _kfCount();\n    if (kf === _lastKf) return;\n    _lastKf = kf;\n    if (btnPlay)    btnPlay.disabled    = kf === 0;\n    if (btnReset)   btnReset.disabled   = kf === 0;\n    if (seekSlider) seekSlider.disabled = kf < 2;\n  }\n\n  function _updateInfo() {\n    if (!infoLabel) return;\n    if (typeof target.info !== 'function') { infoLabel.textContent = ''; return; }\n    const i   = target.info();\n    const pct = (i.time * 100).toFixed(1);\n    infoLabel.textContent = `${pct}%  seg ${i.seg}/${i.segments}  kf ${i.keyframes}`;\n  }\n\n  function _applyCollapse() {\n    body.style.display = _collapsed ? 'none' : 'flex';\n    if (chevron) chevron.textContent = _collapsed ? '\\u25B6' : '\\u25BC';\n  }\n\n  // ── Visibility ────────────────────────────────────────────────────────────\n\n  function _setVis(show) {\n    _vis = show !== false;\n    container.style.display = _vis ? 'flex' : 'none';\n  }\n\n  // ── Public API ────────────────────────────────────────────────────────────\n\n  const ui = {};\n  ui.el = container;\n\n  Object.defineProperty(ui, 'visible', {\n    get() { return _vis; },\n    set(v) { _setVis(v); }\n  });\n\n  Object.defineProperty(ui, 'collapsed', {\n    get() { return _collapsed; },\n    set(v) {\n      if (!canCollapse) return;\n      _collapsed = !!v;\n      _applyCollapse();\n    }\n  });\n\n  ui.parent = parentEl => mount(container, parentEl);\n\n  ui.tick = () => {\n    if (!_seeking && seekSlider) {\n      const t = typeof target.time === 'function' ? target.time() : 0;\n      seekSlider.value = t;\n      if (seekLabel) seekLabel.textContent = `seek: ${t.toFixed(3)}`;\n    }\n    _syncPlayBtn();\n    _updateEnabledState();\n    if (showInfo) _updateInfo();\n\n    // Poll loop/bounce from track — covers external play() calls.\n    if (showProps && target.playing) {\n      const liveLoop   = !!target.loop;\n      const liveBounce = !!target.bounce;\n      if (liveLoop !== _loop) {\n        _loop = liveLoop;\n        if (loopInp) loopInp.checked = _loop;\n      }\n      if (liveBounce !== _bounce) {\n        _bounce = liveBounce;\n        if (bounceInp) bounceInp.checked = _bounce;\n      }\n    }\n  };\n\n  ui.dispose = () => {\n    target._onPlay = null;\n    target._onEnd  = null;\n    target._onStop = null;\n    container.parentNode && container.parentNode.removeChild(container);\n  };\n\n  // ── Mount & initial state ─────────────────────────────────────────────────\n\n  mount(container, opt.parent);\n  _setVis(!opt.hidden);\n  _applyCollapse();\n  _syncPlayBtn();\n  _updateEnabledState();\n\n  return ui;\n}\n\n/**\n * @file UI package entry point — parameter panels and transport controls.\n * @module ui\n * @license AGPL-3.0-only\n *\n * Pure vanilla DOM.  Zero p5 dependencies.\n * Mount into any container (canvas parent, Vue, React, plain HTML).\n *\n * Duck-type contract for track detection:\n *   typeof first?.play === 'function'  →  track panel  (_createTrackUI)\n *   otherwise                          →  param panel  (_createUI)\n */\n\n\n/**\n * Unified panel factory.\n *\n * First argument determines the panel type:\n *\n *   createPanel(track, opt)   — transport controls\n *     track must expose: play, stop, seek, time, playing\n *     opt.add present        → + button enabled\n *     opt.reset present      → ↺ button enabled\n *\n *   createPanel(schema, opt)  — parameter controls\n *     schema is a plain object of control definitions (no .play method)\n *     opt.target (function|{set}) → values pushed each tick\n *\n * Both paths share the same layout options: x, y, width, color, hidden, parent.\n *\n * @param {Object} trackOrSchema\n * @param {Object} [opt]\n * @returns {Object} UI handle with .el, .tick(), .dispose().\n */\nfunction createPanel(trackOrSchema, opt) {\n  if (typeof trackOrSchema?.play === 'function') {\n    return createTrackUI(trackOrSchema, opt);\n  }\n  return createUI(trackOrSchema, opt);\n}\n\nexport { createPanel };\n//# sourceMappingURL=index.js.map\n","/**\n * @file Unified panel bridge: parameter panels and track transport controls.\n * @module p5.tree/panel\n * @license AGPL-3.0-only\n *\n * ── What lives here ──────────────────────────────────────────────────────────\n *  fn.createPanel(trackOrSchema, opt)\n *    Unified factory — type-discriminated by first argument:\n *      track (has .play)  → transport panel (PoseTrack or CameraTrack)\n *      schema (plain obj) → parameter panel (shader uniforms, scene params)\n *\n * ── Bridge responsibilities ───────────────────────────────────────────────────\n *  1. Resolve opt.parent   → canvas parent element (default) or explicit mount\n *  2. Resolve opt.target   → wrap p5 shader's setUniform as plain (name,val)=>...\n *  3. Resolve opt.camera   → curCamera default for PoseTrack + button\n *  4. Wrap track           → build duck-typed wrapper for deps/ui (via _wrapTrack)\n *  5. Register player      → auto-tick via predraw loop\n *\n * ── Camera resolution for + button ───────────────────────────────────────────\n *  CameraTrack              → track.camera (set by createCameraTrack)\n *  PoseTrack + opt.camera   → use that camera explicitly\n *  PoseTrack, omitted       → curCamera (covers ~90% of use cases)\n *  Either  + null           → + button suppressed\n */\n\n'use strict';\n\nimport { createPanel as _createPanel } from '@nakednous/ui';\nimport {\n  NDC, WORLD,\n  mapLocation as coreMapLocation,\n  mat4Mul, mat4Invert,\n} from '@nakednous/tree';\nimport { registerPlayer } from './track.js';\nimport { CameraTrack } from '@nakednous/tree';\n\n// ── Module-level scratch (allocated once at import time) ──────────────────────\n\nconst _sc_pv  = new Float32Array(16);  // proj * view\nconst _sc_ipv = new Float32Array(16);  // inv(proj * view)\nconst _sc_v3  = new Float32Array(3);   // scratch 3-vector\n\n// ── Parent resolution ─────────────────────────────────────────────────────────\n\n/**\n * Resolve the mount parent for a panel.\n * Priority: explicit opt.parent → canvas parent → document.body.\n * Unwraps p5.Element to its raw HTMLElement.\n * @param {p5} pInst\n * @param {HTMLElement|p5.Element|undefined} parent\n * @returns {HTMLElement}\n */\nfunction _resolveParent(pInst, parent) {\n  if (parent) return (parent.elt !== undefined) ? parent.elt : parent;\n  return (pInst._renderer && pInst._renderer.canvas)\n    ? pInst._renderer.canvas.parentElement\n    : document.body;\n}\n\n// ── Depth helpers ─────────────────────────────────────────────────────────────\n\n/**\n * Detect NDC Z minimum from the renderer's drawing context.\n * Returns −1 for WebGL, 0 for WebGPU.\n * @param {Object} renderer\n * @returns {number}\n */\nfunction _ndcZMin(renderer) {\n  if (renderer.drawingContext &&\n      typeof WebGL2RenderingContext !== 'undefined' &&\n      renderer.drawingContext instanceof WebGL2RenderingContext) return -1;\n  return 0;\n}\n\n/**\n * Unproject the frustum centre at parametric depth d [0..1] into world space.\n * d=0 → near plane centre,  d=1 → far plane centre.\n * Returns [x,y,z] or null if renderer state is unavailable.\n * @param {p5} pInst\n * @param {number} d\n * @returns {number[]|null}\n */\nfunction _centerAtDepth(pInst, d) {\n  const renderer = pInst._renderer;\n  if (!renderer || !renderer.states) return null;\n  const proj = renderer.states.uPMatrix?.mat4;\n  const view = renderer.states.curCamera?.cameraMatrix?.mat4;\n  if (!proj || !view) return null;\n  const ndcMin = _ndcZMin(renderer);\n  const ndcZ   = ndcMin + d * (1 - ndcMin);\n  mat4Mul(_sc_pv, proj, view);\n  if (!mat4Invert(_sc_ipv, _sc_pv)) return null;\n  coreMapLocation(_sc_v3, 0, 0, ndcZ, NDC, WORLD, { mat4PVInv: _sc_ipv }, [0, 0, 1, 1], ndcMin);\n  return [_sc_v3[0], _sc_v3[1], _sc_v3[2]];\n}\n\n// ── Track wrapper ─────────────────────────────────────────────────────────────\n\n/**\n * Build a duck-typed wrapper around a track for consumption by deps/ui.\n *\n * The wrapper exposes the transport contract (_createTrackUI duck-type):\n *   play, stop, seek, time, playing, reset, info, add (optional)\n *\n * Lib-space hook slots (_onPlay, _onEnd, _onStop) are forwarded to the\n * underlying track via property getters/setters so that trackUI's assignments\n * reach the object that actually fires the hooks.\n *\n * For CameraTrack: apply is already wired in createCameraTrack; the wrapper only\n *   handles snap (1-kf), seek-while-stopped, and + button capture.\n *   Depth slider is suppressed (not meaningful for camera tracks).\n *\n * For PoseTrack: + button records position = frustum-centre at depth slider\n *   value, rotation = current camera orientation.\n *\n * @param {PoseTrack|CameraTrack} track\n * @param {p5.Camera|null} cam\n * @param {boolean} isCameraTrack\n * @param {p5} pInst\n * @param {boolean} showReset  When false, w.reset is omitted and _createPanel\n *   suppresses the reset button. Use when keyframes are immutable by design.\n * @returns {Object}\n */\nfunction _wrapTrack(track, cam, isCameraTrack, pInst, showReset) {\n  const _snapOut = isCameraTrack\n    ? { eye:[0,0,0], center:[0,0,0], up:[0,1,0], fov:null, halfHeight:null }\n    : { pos:[0,0,0], rot:[0,0,0,1], scl:[1,1,1] };\n\n  const _captureOut = { eye:[0,0,0], center:[0,0,0], up:[0,1,0], fov:null, halfHeight:null };\n  const _addOut     = { eye:[0,0,0], center:[0,0,0], up:[0,1,0], fov:null, halfHeight:null };\n\n  function _applySnap() {\n    const applyCam = isCameraTrack ? track.camera : null;\n    if (applyCam && track.keyframes.length > 0) applyCam.applyPose(track.eval(_snapOut));\n  }\n\n  // Chain onEnd so the final keyframe lands exactly when playback ends.\n  const _prevOnEnd = track.onEnd;\n  track.onEnd = function (t) {\n    if (typeof _prevOnEnd === 'function') { try { _prevOnEnd(t); } catch (_) {} }\n    _applySnap();\n  };\n\n  const w = {\n    get playing()  { return track.playing; },\n    get loop()     { return track.loop; },\n    get bounce() { return track.bounce; },\n    get rate()     { return track.rate; },\n    play:  (o) => {\n      track.play(o);\n      if (!track.playing && track.keyframes.length === 1) _applySnap();\n    },\n    stop:  ()  => track.stop(),\n    seek:  (t) => { track.seek(t); _applySnap(); },\n    time:  ()  => track.time(),\n  };\n  if (showReset && typeof track.reset === 'function') w.reset = () => track.reset();\n  if (typeof track.info === 'function') w.info = () => track.info();\n\n  // Forward lib-space hook slots to the underlying track.\n  // trackUI assigns w._onPlay / _onEnd / _onStop; track.play() fires track._onPlay.\n  // Without this forwarding the panel never receives playback events from\n  // track.play() called externally (e.g. via keyPressed).\n  Object.defineProperty(w, '_onPlay', {\n    get() { return track._onPlay; },\n    set(v) { track._onPlay = v; },\n  });\n  Object.defineProperty(w, '_onEnd', {\n    get() { return track._onEnd; },\n    set(v) { track._onEnd = v; },\n  });\n  Object.defineProperty(w, '_onStop', {\n    get() { return track._onStop; },\n    set(v) { track._onStop = v; },\n  });\n\n  if (cam !== null && typeof track.add === 'function') {\n    if (isCameraTrack) {\n      w.add = () => {\n        cam.capturePose(_addOut);\n        track.add(_addOut, { deduplicate: false });\n      };\n    } else {\n      w.add = (d) => {\n        const pos = _centerAtDepth(pInst, typeof d === 'number' ? d : 0.5) || [0,0,0];\n        cam.capturePose(_captureOut);\n        const e = _captureOut.eye, c = _captureOut.center;\n        const dir = [c[0]-e[0], c[1]-e[1], c[2]-e[2]];\n        track.add({ pos, rot: { dir, up: _captureOut.up } });\n      };\n    }\n  }\n\n  return w;\n}\n\n// ── installPanel ──────────────────────────────────────────────────────────────\n\n/**\n * Install fn.createPanel onto p5.\n * @param {p5} p5\n * @param {Object} fn  p5 prototype.\n */\nexport function installPanel(p5, fn) {\n\n  /**\n   * Unified panel factory.\n   *\n   * First argument determines the panel type:\n   *\n   * **Track panel** (PoseTrack or CameraTrack):\n   * ```js\n   * // CameraTrack — camera auto-resolved from track.camera\n   * const cam   = createCamera()\n   * const track = createCameraTrack(cam)\n   * createPanel(track, { x: 10, y: 10, color: 'white' })\n   *\n   * // PoseTrack — curCamera used for + button by default\n   * const track = createPoseTrack()\n   * createPanel(track, { x: 10, y: 10, color: 'white' })\n   *\n   * // PoseTrack — explicit camera override\n   * createPanel(track, { camera: cam2, x: 10, y: 10 })\n   *\n   * // Suppress + button (camera: null)\n   * createPanel(track, { camera: null, x: 10, y: 10 })\n   *\n   * // Suppress reset button\n   * createPanel(track, { reset: false, x: 10, y: 10 })\n   * ```\n   *\n   * **Param panel** (shader uniforms, scene parameters):\n   * ```js\n   * // Push to a p5 shader automatically each frame\n   * createPanel({\n   *   blurRadius: { min: 0, max: 10, value: 2, step: 0.1 }\n   * }, { target: myShader, x: 10, y: 10, labels: true })\n   *\n   * // Unbound — read values manually\n   * const panel = createPanel({\n   *   speed: { min: 0, max: 1, value: 0.5 }\n   * }, { x: 10, y: 10, labels: true, color: 'white' })\n   * // in draw(): use panel.speed.value()\n   * ```\n   *\n   * @method createPanel\n   * @memberof p5\n   * @param {PoseTrack|CameraTrack|Object} trackOrSchema\n   *   A track instance (PoseTrack / CameraTrack) or a plain schema object.\n   * @param {Object} [opt]\n   *   Layout and behaviour options.\n   * @param {p5.Camera|null} [opt.camera]\n   *   Track panels only. Override camera for + button.\n   *   null suppresses the + button. Defaults to track.camera for CameraTrack,\n   *   curCamera for PoseTrack.\n   * @param {boolean} [opt.reset=true]\n   *   Track panels only. Set false to suppress the reset button.\n   * @param {Object|Function} [opt.target]\n   *   Param panels only. Value sink: p5 shader, (name,val)=>..., or {set}.\n   * @param {(HTMLElement|p5.Element)} [opt.parent]\n   *   Mount target. Defaults to the canvas parent element.\n   * @returns {Object} Panel handle with .el, .tick(), .dispose().\n   */\n  fn.createPanel = function (trackOrSchema, opt) {\n    const pInst = this;\n    opt = Object.assign({}, opt);\n    opt.parent = _resolveParent(pInst, opt.parent);\n\n    const isTrack = typeof trackOrSchema?.play === 'function';\n\n    if (isTrack) {\n      const track         = trackOrSchema;\n      const isCameraTrack = track instanceof CameraTrack;\n\n      // Forward lifecycle hooks onto the track before wrapping.\n      if (typeof opt.onPlay === 'function') { track.onPlay = opt.onPlay; delete opt.onPlay; }\n      if (typeof opt.onEnd  === 'function') { track.onEnd  = opt.onEnd;  delete opt.onEnd;  }\n      if (typeof opt.onStop === 'function') { track.onStop = opt.onStop; delete opt.onStop; }\n\n      const showReset = opt.reset !== false;\n      delete opt.reset;\n\n      // Resolve camera for + button.\n      let cam;\n      if ('camera' in opt) {\n        cam = opt.camera === null             ? null\n            : opt.camera instanceof p5.Camera ? opt.camera\n            : (pInst._renderer?.states?.curCamera ?? null);\n      } else if (isCameraTrack) {\n        cam = track.camera ?? (pInst._renderer?.states?.curCamera ?? null);\n      } else {\n        cam = pInst._renderer?.states?.curCamera ?? null;\n      }\n      delete opt.camera;\n\n      // Depth slider not meaningful for camera tracks.\n      if (isCameraTrack && !('depth' in opt)) opt.depth = false;\n\n      const panel = _createPanel(_wrapTrack(track, cam, isCameraTrack, pInst, showReset), opt);\n      registerPlayer(pInst, { tick() { panel.tick(); return true; } });\n      return panel;\n    }\n\n    // ── Param panel path ──────────────────────────────────────────────────────\n    // Intercept p5 shader targets — wrap setUniform as a plain function.\n    if (opt.target && typeof opt.target.setUniform === 'function') {\n      const shader = opt.target;\n      // p5 wires _renderer into the shader on the first shader() call inside draw();\n      // guard against predraw ticks firing before the shader is activated.\n      opt.target = (name, value) => {\n        if (shader._renderer) shader.setUniform(name, value);\n      };\n    }\n\n    const panel = _createPanel(trackOrSchema, opt);\n    registerPlayer(pInst, { tick() { panel.tick(); return true; } });\n    return panel;\n  };\n}\n","/**\n * @file p5.tree addon entry point — registers onto p5, delegates to sub-modules.\n * @module p5.tree\n * @license AGPL-3.0-only\n */\n\n'use strict';\n\nimport p5 from 'p5';\n\nimport { installConstants } from './constants.js';\nimport { installMatrix, detectNDC } from './matrix.js';\nimport { installHud } from './hud.js';\nimport { installVisibility } from './visibility.js';\nimport { installGizmos } from './gizmos.js';\nimport { installPicking, releasePickFbo } from './picking.js';\nimport { installTrack, tickPlayers, clearPlayers } from './track.js';\nimport { installPipe } from './pipe.js';\nimport { installPanel } from './panel.js';\n\np5.registerAddon((p5, fn, lifecycles) => {\n\n  // §1 — Constants & namespace (includes WEBGL / WEBGPU)\n  installConstants(p5);\n\n  // §2 — Matrix queries, space transforms\n  installMatrix(p5, fn);\n\n  // §3 — HUD (beginHUD / endHUD)\n  installHud(p5, fn);\n\n  // §4 — Visibility (frustum culling bridge)\n  installVisibility(p5, fn);\n\n  // §5 — Gizmos (axes, grid, cross, bullsEye, viewFrustum)\n  installGizmos(p5, fn);\n\n  // §6 — Picking (colorPick, mousePick, mouseHit, pointerHit, tag)\n  installPicking(p5, fn);\n\n  // §7 — PoseTrack, adapters, camera path API + global forwarders\n  installTrack(p5, fn);\n\n  // §8 — Pipe (post-processing chain)\n  installPipe(p5, fn);\n\n  // §9 — Panel (parameter panels + track transport controls)\n  installPanel(p5, fn);\n\n  // ── Lifecycle hooks ────────────────────────────────────────────────\n\n  lifecycles.postsetup = function () {\n    if (!(this._renderer instanceof p5.Renderer3D)) {\n      throw new Error('p5.tree requires WEBGL or WEBGPU. Use createCanvas(w, h, WEBGL) or WEBGPU.');\n    }\n    // Detect NDC convention from the renderer context (3rd param to createCanvas)\n    detectNDC(this._renderer);\n  };\n\n  lifecycles.predraw = function () {\n    tickPlayers(this);\n  };\n\n  lifecycles.remove = function () {\n    clearPlayers(this);\n    this.releasePipe(true);\n    releasePickFbo(this);\n  };\n});\n","/**\n * @file Install constants onto p5.Tree.\n * @module p5.tree/constants\n * @license AGPL-3.0-only\n */\n\nimport * as C from '@nakednous/tree';\n\nexport function installConstants(p5) {\n  p5.Tree ||= {};\n\n  const CONST = value => ({ value, writable: false, enumerable: true, configurable: false });\n\n  Object.defineProperties(p5.Tree, {\n    VERSION: CONST('0.0.43'),\n    NONE: CONST(0),\n\n    // Core constants (spaces, visibility, NDC, basis vectors)\n    WORLD:  CONST(C.WORLD),\n    EYE:    CONST(C.EYE),\n    NDC:    CONST(C.NDC),\n    SCREEN: CONST(C.SCREEN),\n    MODEL:  CONST(C.MODEL),\n    OBJECT: CONST(C.MODEL),\n\n    WEBGL:  CONST(C.WEBGL),\n    WEBGPU: CONST(C.WEBGPU),\n\n    INVISIBLE:   CONST(C.INVISIBLE),\n    VISIBLE:     CONST(C.VISIBLE),\n    SEMIVISIBLE: CONST(C.SEMIVISIBLE),\n\n    ORIGIN: CONST(C.ORIGIN),\n    i:  CONST(C.i),\n    j:  CONST(C.j),\n    k:  CONST(C.k),\n    _i: CONST(C._i),\n    _j: CONST(C._j),\n    _k: CONST(C._k),\n\n    // ── Addon-only constants (drawing / frustum / trackPath bits) ─────────\n    //\n    // Bit namespaces are gizmo-local: the same numeric value carries different\n    // meanings to different gizmos.  Users pass each gizmo its own bit set and\n    // never mix them across gizmos.\n\n    // axes bits\n    X:      CONST(1 << 0),\n    _X:     CONST(1 << 1),\n    Y:      CONST(1 << 2),\n    _Y:     CONST(1 << 3),\n    Z:      CONST(1 << 4),\n    _Z:     CONST(1 << 5),\n    LABELS: CONST(1 << 6),\n\n    // bullsEye shape\n    CIRCLE: CONST(0),\n    SQUARE: CONST(1),\n\n    // viewFrustum bits\n    NEAR:   CONST(1 << 0),\n    FAR:    CONST(1 << 1),\n    LEFT:   CONST(1 << 2),\n    RIGHT:  CONST(1 << 3),\n    BOTTOM: CONST(1 << 4),\n    TOP:    CONST(1 << 5),\n    BODY:   CONST(1 << 6),\n    APEX:   CONST(1 << 7),\n\n    // trackPath bits — CameraTrack-aware: PATH/CONTROLS/TANGENTS_* respect\n    // the `target: 'eye' | 'center'` opt; CENTER is camera-only and always\n    // draws the gaze relationship (not a polyline).\n    PATH:         CONST(1 << 0),   // sampled polyline along the target path\n    CENTER:       CONST(1 << 1),   // camera — gaze line eye→center + endpoint dot at kf.center\n    CONTROLS:     CONST(1 << 2),   // straight control polygon along the target path\n    TANGENTS_IN:  CONST(1 << 3),   // incoming tangent arrows at keyframes of the target path\n    TANGENTS_OUT: CONST(1 << 4),   // outgoing tangent arrows at keyframes of the target path\n    TANGENTS:     CONST((1 << 3) | (1 << 4)),  // convenience — IN | OUT\n  });\n}\n","/**\n * @file HUD (Heads-Up Display) — 2D screen-space overlay mode.\n * @module p5.tree/hud\n * @license AGPL-3.0-only\n *\n * Coordinates: (x, y) ∈ [0, width] × [0, height], origin top-left,\n * y increasing downward.\n *\n * Usage:\n *   beginHUD()\n *   text('FPS: ' + frameRate().toFixed(1), 10, 20)\n *   endHUD()\n */\n\n'use strict';\n\n/**\n * Install beginHUD() and endHUD() on fn.\n * @param {p5}    p5\n * @param {Object} fn  p5 prototype.\n */\nexport function installHud(p5, fn) {\n\n  fn.beginHUD = function (...args) { this._renderer?.beginHUD?.(...args); return this; };\n  fn.endHUD   = function (...args) { this._renderer?.endHUD?.(...args);   return this; };\n\n  /**\n   * Begin drawing in screen space (HUD mode).\n   *\n   * Clears depth, installs an orthographic camera matching canvas pixel\n   * dimensions, origin top-left. Pair with `endHUD()`.\n   *\n   * @method beginHUD\n   * @for p5\n   */\n  p5.Renderer3D.prototype.beginHUD = function () {\n    if (this._hudActive === true) return;\n    const p = this._pInst;\n    const states = this.states;\n    if (!p || !states) return;\n    p.push();\n    p.resetShader();\n    p.resetMatrix();\n    this._hudPrevCam = states.curCamera;\n    this._hudDepthMode = undefined;\n    this._hudDepthWasEnabled = undefined;\n    if (typeof this.clearDepth === 'function') {\n      this.flushDraw?.();\n      this.clearDepth(1);\n      this._hudDepthMode = 'clearDepth';\n    } else {\n      const gl = this.drawingContext;\n      if (gl && typeof gl.isEnabled === 'function' && gl.DEPTH_TEST !== undefined) {\n        this._hudDepthWasEnabled = gl.isEnabled(gl.DEPTH_TEST);\n        gl.flush?.();\n        gl.disable(gl.DEPTH_TEST);\n        this._hudDepthMode = 'depthTestToggle';\n      }\n    }\n    if (this._hudCam === undefined) this._hudCam = p.createCamera();\n    const z = 1e6;\n    this._hudCam.ortho(0, p.width, -p.height, 0, -z, z);\n    this._hudCam.camera(0, 0, 1, 0, 0, 0, 0, 1, 0);\n    p.setCamera(this._hudCam);\n    this._hudActive = true;\n  };\n\n  /**\n   * End HUD mode, restoring the 3D camera and depth state.\n   *\n   * @method endHUD\n   * @for p5\n   */\n  p5.Renderer3D.prototype.endHUD = function () {\n    if (this._hudActive !== true) return;\n    const p = this._pInst;\n    if (!p) return;\n    if (this._hudDepthMode === 'depthTestToggle') {\n      const gl = this.drawingContext;\n      if (gl && gl.DEPTH_TEST !== undefined) {\n        gl.flush?.();\n        this._hudDepthWasEnabled ? gl.enable(gl.DEPTH_TEST) : gl.disable(gl.DEPTH_TEST);\n      }\n    }\n    p.pop();\n    this._hudPrevCam !== undefined && p.setCamera(this._hudPrevCam);\n    this._hudPrevCam = undefined;\n    this._hudDepthWasEnabled = undefined;\n    this._hudDepthMode = undefined;\n    this._hudActive = false;\n  };\n}\n","/**\n * @file Post-processing pipeline (pipe + releasePipe).\n * @module p5.tree/pipe\n * @license AGPL-3.0-only\n *\n * Contains the `fn.pipe()` and `fn.releasePipe()` functions.\n */\n\n'use strict';\n\n/**\n * Install pipe() and releasePipe() on fn.\n * @param {p5} p5  The p5 constructor.\n * @param {Object} fn  p5 prototype.\n */\nexport function installPipe(p5, fn) {\n  /**\n   * Pipes a source through one or more post-processing passes (filters), optionally displaying\n   * the final output on the main canvas.\n   *\n   * By default, pipe allocates and caches internal ping/pong framebuffers (keyed) and lazily\n   * resizes them to match the source. Advanced users may override ping/pong explicitly.\n   *\n   * Args may be provided in any order (source, pass(es), opt).\n   *\n   * Logical args:\n   * - source: p5.Framebuffer|p5.Texture|p5.Image|p5.Graphics (if a p5.Framebuffer is provided, its .color is used)\n   * - passes: a pass or array of passes (e.g. baseFilterShader().modify(...)); falsy entries ignored\n   * - opt: options object\n   *\n   * @method pipe\n   * @for p5\n   * @param {...*} args Source, pass(es), and options in any order.\n   * @param {boolean} [opt.display=true] If true, draw the final output to the main canvas.\n   * @param {boolean} [opt.allocate=true] If true, allocate internal ping/pong when missing (cached per key).\n   * @param {string} [opt.key='default'] Cache key for internal ping/pong (advanced; useful for multiple independent pipelines).\n   * @param {p5.Framebuffer} [opt.ping] Optional user-provided ping framebuffer (advanced override; not cached internally).\n   * @param {p5.Framebuffer} [opt.pong] Optional user-provided pong framebuffer (advanced override; not cached internally).\n   * @param {boolean} [opt.clear=true] If true, clear each ping/pong pass target before drawing into it.\n   * @param {boolean} [opt.clearDisplay=true] If true and opt.display is true, clear the main canvas before drawing final output.\n   * @param {function} [opt.clearFn] Clear strategy for ping/pong passes. Defaults to () => this.background(0).\n   * @param {function} [opt.clearDisplayFn] Clear strategy for display stage. Defaults to opt.clearFn.\n   * @param {function} [opt.draw] Draw strategy used to place the current texture on the current render target. Defaults to full-canvas blit.\n   * @returns {p5.Framebuffer|null} The final framebuffer used (ping or pong) when ping/pong are available; otherwise null.\n   */\n  fn.pipe = function (...args) {\n    const p = this;\n    let source;\n    let passes = [];\n    let opt = {};\n    args.forEach(arg => {\n      if (Array.isArray(arg) || arg instanceof p5.Shader) {\n        passes = arg;\n      } else if (arg && typeof arg === 'object') {\n        const isFramebuffer = typeof p5.Framebuffer !== 'undefined' && arg instanceof p5.Framebuffer;\n        const isGraphics = arg instanceof p5.Graphics;\n        const isImage = arg instanceof p5.Image;\n        const isTexture = typeof p5.Texture !== 'undefined' && arg instanceof p5.Texture;\n        (isFramebuffer || isGraphics || isImage || isTexture) ? (source = arg) : (opt = arg);\n      } else if (arg) {\n        source = arg;\n      }\n    });\n    const _rawPasses = Array.isArray(passes) ? passes : [passes];\n    const _passes = (_rawPasses || []).filter(Boolean);\n    const _opt = opt || {};\n    const display = _opt.display ?? true;\n    const allocate = _opt.allocate ?? true;\n    const key = _opt.key ?? 'default';\n    const clearPasses = _opt.clear ?? true;\n    const clearDisplay = _opt.clearDisplay ?? true;\n    const defaultClear = () => p.background(0);\n    const clearFn = typeof _opt.clearFn === 'function' ? _opt.clearFn : defaultClear;\n    const clearDisplayFn = typeof _opt.clearDisplayFn === 'function' ? _opt.clearDisplayFn : clearFn;\n    const defaultDraw = (tex) => {\n      p.imageMode(p.CORNER);\n      p.image(tex, -p.width / 2, -p.height / 2, p.width, p.height);\n    };\n    const draw = typeof _opt.draw === 'function' ? _opt.draw : defaultDraw;\n    const srcTex = source?.color ?? source;\n    if (!_passes.length) {\n      if (display && srcTex) {\n        clearDisplay && clearDisplayFn();\n        draw(srcTex);\n      }\n      return null;\n    }\n    const sizeFrom = (s) => {\n      const w = s?.width ?? s?.color?.width ?? p.width;\n      const h = s?.height ?? s?.color?.height ?? p.height;\n      return [w, h];\n    };\n    const [w, h] = sizeFrom(source);\n    const ensureSize = (fb) => {\n      fb && (fb.width !== w || fb.height !== h) && fb.resize(w, h);\n    };\n    const applyPassClear = () => {\n      clearPasses && clearFn();\n    };\n    const applyDisplayClear = () => {\n      clearDisplay && clearDisplayFn();\n    };\n    const hasPing = Object.prototype.hasOwnProperty.call(_opt, 'ping');\n    const hasPong = Object.prototype.hasOwnProperty.call(_opt, 'pong');\n    p._tree ||= {};\n    p._tree._pipe ||= {};\n    p._tree._pipe[key] ||= {};\n    const store = p._tree._pipe[key];\n    let ping = hasPing ? _opt.ping : store.ping;\n    let pong = hasPong ? _opt.pong : store.pong;\n    if (allocate) {\n      !ping && !hasPing && (ping = p.createFramebuffer());\n      !pong && !hasPong && (pong = p.createFramebuffer());\n      !hasPing && (store.ping = ping);\n      !hasPong && (store.pong = pong);\n    }\n    if (ping && pong) {\n      ensureSize(ping);\n      ensureSize(pong);\n    }\n    if (!ping || !pong) {\n      if (display && srcTex) {\n        applyDisplayClear();\n        draw(srcTex);\n        p.filter(_passes[0]);\n      }\n      return null;\n    }\n    let readTex = srcTex;\n    let out = null;\n    for (let i = 0; i < _passes.length; i++) {\n      const dst = (i % 2 === 0) ? ping : pong;\n      dst.begin();\n      applyPassClear();\n      draw(readTex);\n      p.filter(_passes[i]);\n      dst.end();\n      readTex = dst.color;\n      out = dst;\n    }\n    if (display && readTex) {\n      applyDisplayClear();\n      draw(readTex);\n    }\n    return out;\n  };\n  \n  /**\n   * Release internal cached pipe framebuffers created by pipe() when opt.allocate is true.\n   * Does NOT remove user-provided ping/pong passed via opt.ping/opt.pong.\n   *\n   * @method releasePipe\n   * @for p5\n   * @param {string|boolean} [key] If omitted, releases the default key ('default').\n   *                              If a string, releases only that key.\n   *                              If true, releases all keys.\n   */\n  fn.releasePipe = function (key) {\n    const p = this;\n    const store = p._tree?._pipe;\n    if (!store) return;\n    const releasePair = (pair) => {\n      pair?.ping && pair.ping.remove();\n      pair?.pong && pair.pong.remove();\n    };\n    if (key === true) {\n      Object.keys(store).forEach(k => {\n        releasePair(store[k]);\n        delete store[k];\n      });\n      return;\n    }\n    const k = typeof key === 'string' ? key : 'default';\n    releasePair(store[k]);\n    delete store[k];\n  };\n}\n\n/**\n * Release all pipe framebuffers. Called from lifecycles.remove.\n * @param {p5} pInst  The p5 instance.\n */\nexport function releaseAllPipes(pInst) {\n  if (typeof pInst.releasePipe === 'function') {\n    pInst.releasePipe(true);\n  }\n}\n"]}