Surfaced from #225 PR1 (#250 / #254) headset smoke (Brad, 2026-05-22). The vertical rack — three SectionTabs + the canonical-forms heading at the left edge of the plinth working surface — picks up the surface tilt via the slot model (orientation: 'surface'), but the result reads janky from two directions:
What headset smoke surfaced
-
Anchoring is not "satisfyingly centered." Canonical-forms heading sits at PLINTH_SECTION_TAB_HEADING_Y = 0.55 slot-local, which is exactly the working-surface back edge (PLINTH_WORKING_HEIGHT_QUADRICS = 0.55). The button's vertical extent extends past the back edge in slot-Y, so the upper half is "in the air" behind the plinth surface rather than seated on it. The three section tabs below are within the surface but the rack as a whole reads as drifting off the back.
-
Yaw-billboarded label text intersects the tilted plinth surface. TapButton.faceCamera rotates the child Text node toward the camera while leaving this.group (the button body) tilted with the plinth slot. At ~20° tilt the text plane and button-body plane diverge enough that the troika text mesh visibly clips into the plinth slab from typical viewing poses. Tightening the offsets won't fix this — it's the rendering-model mismatch (yaw-billboarded text on a non-billboarded surface).
Direction
This will probably need a new rendering / design model for plinth-mounted labels rather than a tuning pass:
- Anchoring (1): straightforward — compress the rack vertically + shift the heading down so the full 4-element stack centers within
[0, workingSurfaceHeight] with margin. May want a per-scene PLINTH_SECTION_TAB_* retune driven by smoke. Cheapest fix.
- Label-vs-surface (2): open. Options to evaluate (non-exhaustive):
- Drop the per-button
faceCamera for plinth-mounted buttons and let labels surface-tilt with the body (legibility tradeoff at glancing angles).
- Move labels off the button body — e.g. a single column of slot-anchored labels next to the button column, with the buttons reduced to glyph/color affordances.
- Bake labels onto a textured plane sized to the button (drop troika for plinth-mounted buttons specifically).
- Counter-rotate the label child inside the button so the text plane re-aligns with the surface (works but introduces a per-frame compose step).
Sister concern to #252 (panel-backed readout visual) — both bump into "yaw-billboarded text on a tilted surface looks wrong"; whatever design language we land on for readouts will probably inform this too.
Code anchors
- Slot positions:
src/exhibits/quadrics/index.ts — PLINTH_SECTION_TAB_X = -0.42, PLINTH_SECTION_TAB_HEADING_Y = 0.55, PLINTH_SECTION_TAB_TOP_Y = 0.42, PLINTH_SECTION_TAB_PITCH = 0.13.
- Working surface depth:
PLINTH_WORKING_HEIGHT_QUADRICS = 0.55 (slot-Y range [0, 0.55]).
- Per-button label rendering:
src/scaffold/ui/TapButton.ts faceCamera (:194 per current main).
- Plinth slot model:
src/scaffold/staging/Plinth.ts (SlotOrientation + billboarded-primitive carve-out at the file-top doc-comment).
Refs
🤖 Generated with Claude Code
Surfaced from #225 PR1 (#250 / #254) headset smoke (Brad, 2026-05-22). The vertical rack — three
SectionTabs + the canonical-forms heading at the left edge of the plinth working surface — picks up the surface tilt via the slot model (orientation: 'surface'), but the result reads janky from two directions:What headset smoke surfaced
Anchoring is not "satisfyingly centered." Canonical-forms heading sits at
PLINTH_SECTION_TAB_HEADING_Y = 0.55slot-local, which is exactly the working-surface back edge (PLINTH_WORKING_HEIGHT_QUADRICS = 0.55). The button's vertical extent extends past the back edge in slot-Y, so the upper half is "in the air" behind the plinth surface rather than seated on it. The three section tabs below are within the surface but the rack as a whole reads as drifting off the back.Yaw-billboarded label text intersects the tilted plinth surface.
TapButton.faceCamerarotates the childTextnode toward the camera while leavingthis.group(the button body) tilted with the plinth slot. At ~20° tilt the text plane and button-body plane diverge enough that the troika text mesh visibly clips into the plinth slab from typical viewing poses. Tightening the offsets won't fix this — it's the rendering-model mismatch (yaw-billboarded text on a non-billboarded surface).Direction
This will probably need a new rendering / design model for plinth-mounted labels rather than a tuning pass:
[0, workingSurfaceHeight]with margin. May want a per-scenePLINTH_SECTION_TAB_*retune driven by smoke. Cheapest fix.faceCamerafor plinth-mounted buttons and let labels surface-tilt with the body (legibility tradeoff at glancing angles).Sister concern to #252 (panel-backed readout visual) — both bump into "yaw-billboarded text on a tilted surface looks wrong"; whatever design language we land on for readouts will probably inform this too.
Code anchors
src/exhibits/quadrics/index.ts—PLINTH_SECTION_TAB_X = -0.42,PLINTH_SECTION_TAB_HEADING_Y = 0.55,PLINTH_SECTION_TAB_TOP_Y = 0.42,PLINTH_SECTION_TAB_PITCH = 0.13.PLINTH_WORKING_HEIGHT_QUADRICS = 0.55(slot-Y range[0, 0.55]).src/scaffold/ui/TapButton.tsfaceCamera(:194per currentmain).src/scaffold/staging/Plinth.ts(SlotOrientation+ billboarded-primitive carve-out at the file-top doc-comment).Refs
_private/plans/225-control-plinth.md§3.3 (the billboarded-primitive carve-out the slot model deliberately accepts; this issue is the first concrete case where that carve-out is materially uncomfortable).🤖 Generated with Claude Code