HardYards/web/world
type-two 6e5f4b5222 Sprint 13 gate 3: the front door — splash, pause, touch notice, Enter pinned
The URL is public, so this is the first thing a stranger meets.

ENTER, PINNED. The exploit shipped because the rule lived in a keydown closure
inside boot(), behind a canvas and a WebGL context — nowhere a test could
reach. That's WHY it went out: not carelessness, no seam. `enterCommits(phase,
cardOpen)` is a value now, asserted exhaustively over PHASES so a sixth phase
is covered the day it appears, and the safe default (may not advance) is the
one it gets. Mutation-checked: reverting the guard reddens forecast, storm and
aftermath.

SPLASH. A cold visitor used to land on a job sheet — an invoice-shaped card
from a business they'd never heard of, quoting money for a job nobody had
explained, controls revealed later on prep's help line. It's a good SECOND
card. One more .card, not a menu system: there is nothing to configure. Built
on E's letterhead because the masthead IS the game's name. boot({splash:false})
for benches and D's harness.

P PAUSE — and the test is the story. The pause lives in frame(), frame() is
only called by rAF, and rAF DOES NOT FIRE IN A HIDDEN TAB. My first probe drove
the real loop and reported success: simT advanced 0 while paused... and 0 while
running. It was measuring a frozen tab, and it would have passed no matter what
I wrote. So the rule is a value: accumulate(acc, raw, paused). Paused DRAINS
the accumulator rather than carrying it — a kept `acc` spends time that elapsed
while you were paused on the first frame after resume, which is a free sixtieth
of a second of storm and exactly how two runs of a deterministic sim come to
disagree. Storm-only, and cleared at every phase change: a pause flag left set
where P is inert would be a soft-lock built out of a comfort feature.

M MUTE — wired, honest, and not advertised yet. C's bus has no tap: createAudio
holds `master` inside skyfx's closure and exposes only unlockAudio(). Asked in
THREADS. `sky.setMute?.(on)` behind a key the splash promises would be D's
night-3 soft-lock with a keycap on it — `rigging.setWorld?.(world)` sat in this
same file for a sprint doing nothing, silently, because ?.() on a missing method
looks exactly like a call. So the UI asks before it advertises, and M lights up
by itself the day C lands the tap.

TOUCH NOTICE. The naive check is the bug: `(pointer: coarse)` asks what the
PRIMARY pointer is, so a touchscreen laptop answers coarse and gets locked out
of a game it can play — worse than the dead canvas it replaces. `(any-pointer:
fine)` asks whether a mouse exists at all. Detection errs toward letting people
in; unknown browsers get the game, not a lecture.

DEV LINE. Out from under B's anchor panel (both were top-left, typesetting on
each other), and off unless localhost or ?dev=1 — a stranger on partly.party was
reading "60 fps · storm 12.3s · debris 4" on the front door.

selftest 338/0/0 (was 335).
2026-07-17 23:59:27 +10:00
..
data Rule the gutter $90 (E's proposal adopted); teach collateralFor/wreckStructure the house; action B's effective-rating flag 2026-07-17 20:45:49 +10:00
js Sprint 13 gate 3: the front door — splash, pause, touch notice, Enter pinned 2026-07-17 23:59:27 +10:00
models Gutter priced and wrecked: GUTTER_COLLATERAL=90 baked with reasoning; torn-gutter house wreck, carport pattern 2026-07-17 20:21:24 +10:00
vendor Vendor three.js r175, add stdlib dev server and launch config 2026-07-16 21:33:42 +10:00
dev_player.html Merge all lanes; add importmap; fix /world/ absolute paths 2026-07-16 22:23:20 +10:00
dev_rigging.html Lane B S11: audit the venturi, land setWorld/setBudget, revive the harness 2026-07-17 17:42:54 +10:00
dev_skyfx.html skyfx: the change announces itself — a front wall in the sky (gate 3.4) 2026-07-17 20:24:51 +10:00
index.html Sprint 13 gate 3: the front door — splash, pause, touch notice, Enter pinned 2026-07-17 23:59:27 +10:00
selftest.html Add tools/site_audit; retract the p1 claim against C; show LANE BAL 2026-07-17 14:52:31 +10:00