Things we ran into while building real pages. Read this before verifying.
__explainer.overlaps(), not by eye.SCREEN_RIGHT by an offset.fitW, fitH, and target. For a horizontally long scene, fitW decides. The stage is
usually taller than wide, so leftover empty space above and below is normal.overlaps() is
empty on desktop, labels can overlap at 390px wide. declutter() pulls labels in and shifts them apart when the stage is narrower than 700px,
but overlaps beyond the cap (56px) remain. Write short labels and do not place two big labels close together.clipped() measures against the canvas cell.pre.code to white-space: pre and scrolls horizontally inside the block only (desktop keeps pre-wrap). Shorter code lines help even more.flash for emphasis, only briefly.flash is at its peak, a slab looks deep blue or
red, like a color bug. Do not wait a fixed time; use await __explainer.run(name).reset() shows up on the second run. If you changed a label’s text (tag.element.textContent),
restore it, and hide again in reset anything that must start with visible = false. Run each chapter twice.temporaryGroup(),
remove a finished object with disposeObject(), and use clearGroup(temp) in reset. These helpers unregister labels, remove their
DOM/state, and dispose owned geometry/materials. The engine clears temporary groups on chapter changes too. List borrowed geometry
and materials in the temporary group’s shared-resource argument so cleanup leaves their external owner in control.
syncTags still hides persistent labels when an ancestor is hidden or scaled down; do not delete their elements yourself.touch-action: none, so a swipe on the stage blocks page scrolling. The template overrides it with
touch-action: pan-y after construction. Do not delete that line.IntersectionObserver notifies only once, when a chapter enters the line,
so a run left pending during the block is released by the scroll listener (tryAutorun) the moment scroll passes 40px.svh instead of dvh for the stage height. When the address bar collapses and expands, dvh changes and the stage keeps refitting.white-space: pre-wrap on pre.code (for phones see the “Screen” section above).<li> a grid splits the text and <code> into separate cells. Attach the number with absolute positioning on ::before
(ol.steps in the template).word-break: keep-all. The template has it./tmp is refused. A relative path lands in the
working directory root (the repository root) and makes a mess. Give an absolute path inside an allowed folder (usually the working directory, or its
.playwright-mcp/), and if it is inside a repository, check that the folder is gitignored.http.server started in the background gets killed by the session’s background time limit. Tell the user the absolute path of the
file before the server address.Input.synthesizeScrollGesture (gestureSourceType: 'touch').
This is how you can confirm that touch-action is actually applied.timeout command.scroll-behavior: smooth, so during verification, calling scrollBy right after scrollIntoView interrupts
the earlier scroll. When scrolling by hand, use window.scrollTo({ top, behavior: 'instant' }).