* fix(viewer): guard TextureNode updates against null textures three's override-material passes (shadow, prepasses) copy per-object texture slots onto shared materials whose cached per-mesh node graphs can disagree about a slot's presence; when a graph with a TextureNode pulls a null slot, the exception kills the whole render pass and the scene goes black. Patch TextureNode.prototype.update to skip null values (with a throttled warning) so the slot just renders textureless for a frame and recovers. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * revert(viewer): drop the always-on neutral displacement texture Giving every standard material a displacement texture put displacement TextureNodes into the shared shadow/prepass override graphs; in scenes mixing preset materials with GLB item materials (no displacementMap), an item's shadow render can hit a cached graph that expects the texture and pull null — build-order dependent, which is why it broke many-but-not-all projects at open right after the release. The TextureNode fallback guard covers the original paint-hover crash (black texel = zero displacement), so the broad neutral-texture approach is retired. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * style: sort guard imports Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>