feat: night freight container yard works through the additional work chapter

This commit is contained in:
2026-10-11 11:52:27 +03:00
parent 4e097e5ef9
commit ca12cfda44
13 changed files with 831 additions and 0 deletions

View File

@@ -87,3 +87,11 @@ Run: `npm run build:preview` then serve `dist` (dev server shows a blank page).
- **Verdict: SHIP with fixes** (Fable, hardware GL 1440x900, fresh contexts; title and link[rel=icon] observed with MutationObservers over a full drive, park/return at Contact and Infrastructure, reverse scroll, dashcam open/close, brisk 40% scroll, reduced motion, nav jumps, #contact deep link, return visit): the title steps per chapter exactly as the HUD does (5% → 90%, ARRIVED at Contact), the metadata title holds until html[data-ignition] is removed (+4.5 s on first visit, ~3.9 s on the short form), the deep link holds the metadata title until the scene is running then writes ARRIVED · CONTACT; the dashcam owns the title ("DASHCAM · 27% · INFRASTRUCTURE · 03:12") and the route title is back within the same tick the frame unmounts (no stale title after close, scroll after close steps normally); max 3 title/icon writes in any 1 s window on a brisk scroll (2.5 Hz cap holds); rAF p50 16.7 / p95 16.7-16.8 ms with 0 frames over 34 ms during the drive and the brisk scroll; no console errors or warnings, no hydration warnings. Fixes made during review: (1) **parked title read 0%**: useScrollDrive resets its snapshot to route 0 on visibilitychange (before this composable hears it) and keeps 0 for one frame after return, so the hidden tab said "PARKED · 0% · INFRASTRUCTURE" and briefly "ROUTE 0%" on return; the composable now freezes the route while hidden and re-syncs two frames after return (unit test added, two tests that had encoded the old behaviour corrected); (2) **beams invisible at tab size** in the first chapters: at 16 px the 0-20% beams were 2-4 px dots at 35-45% opacity; floor raised (beamMin 2 → 4 px, glowMin 0.35 → 0.55; max unchanged at 14 px / 0.95) so the icon reads as "lamps on" from the first write and still grows x3.5 to Contact. Judged at 16/24/32/128 px in light and dark tab strips: the 'L' reads at every size and state (dark plate on a light strip is a strong silhouette), the parked amber dots are unmistakable, the day plate is the one state that reads as a different icon at a glance (intended), chapter accents are distinct at 32 px and still tellable at 16 px for cyan vs violet vs coral (pink vs coral is a near miss at 16 px).
- **Known weaknesses:** at 16 px the accent is a tint on a 4-14 px smear, so the chapter colour is a subliminal cue rather than a readable signal; the dashcam title shows the raw percentage (27%) while the tab shows the quantised one (25%), two vocabularies for two seconds; pink is shared by Start/Profile/Additional work (SIGN_ACCENTS), so those chapters are told apart only by the beam length; headless Chromium cannot hide a tab, so the parked states were driven by dispatching visibilitychange with document.visibilityState overridden (the unit test does the same); under that emulation the scene loop paused and did not resume (html[data-dawn] stayed 'day' through the reverse drive in the timeline sheet), which a run without the emulation does not show (dawn rewinds to night at Infrastructure in ~1.6 s) — a real tab switch should be checked once by hand; under reduced motion SceneCanvas rewrites html[data-dawn] every frame (pre-existing), which fires this composable's MutationObserver at 60 Hz for a cheap no-op; return visits open at route 0 with the short ignition (route memory does not restore the scroll position, pre-existing).
- Screenshots: docs/overnight/round10/ (00-05 favicon contact sheets from the build; 06 favicon states at 128/32/24/16 px in light and dark tab strips; 07 observed title + favicon timeline over the 35 s review drive, every title write with the icon it shipped with; 09 ignition with the metadata title and the index.html icon held; 11 tab hidden at Infrastructure, "PARKED · 25%" with amber lights; 12 dashcam owning the title; 13 END OF SHIFT, gold on peach).
## Round 11: NIGHT FREIGHT (Additional work container yard)
- **What:** the Additional work chapter is a working container yard on the free left verge. A rail-mounted gantry crane (12 m portal, 29 m high) rides the chapter and stops once per additional project (section-local 0.1/0.33/0.56/0.79, 0.06 hold): the spreader lowers onto the stack, the top container's end plate lights in the chapter accent (#ff83c2, breathing with the bass) and the two work lamps strike (>= 0.35 s ramp, at most one strike per 0.6 s); two 36 m high-mast floods warm from sodium orange to HID blue-white over 1.5 s at chapter entry and cool on the way out, washing the stacks and two pools on the apron; the crane screen-doors out while an underpass deck is within 16-34 m of it. Everything is a pure function of section-local progress (journey/yard-progress.ts), so scrolling back lifts the spreader, dims the plate and runs the crane back. Lite (low tier, touch): crane, stacks and plates only. Reduced motion / static: nothing.
- **Why:** the chapter had no world beat and its left margin was empty; the four additional projects are literally four lifts on the night shift.
- **Build:** journey/yard-progress.ts (pure), scene/world/yard.ts (lazy scene chunk), environment.ts (create, update with the deck z and the viewport aspect). 909 tests (79 files, +15), initial JS 119.08 KB gz (+0.01 KB hash noise, no yard code in the initial chunk), CSS unchanged, scene chunk 221.38 KB gz.
- **Verdict: SHIP with fixes** (Fable, hardware GL 1440x900, wheel-driven drive, frames at eleven section-local points, reverse drive, 1920x1080, 1024x700, 390x844 low tier, reduced motion, perf run): the builder's yard sat on a fixed x -28 parallel to the road, so it converged into the vanishing point under the reading panel and was mostly visible only at the chapter entry (steel also darkened late, timing unwatched). Fixes made during review: (1) **the rails are now a radial siding**: the yard group pivots on the chapter lens and its -z axis is turned by `railYaw(aspect)` so the rail line projects to NDC -0.86 (the middle of the 15% left margin) once the chapter's lens shift is applied, for any viewport aspect; every stop, plate and the crane therefore sit at the same screen x inside the margin at 1440x900 and 1920x1080 and the crane rides *up* the margin, growing, from the far stop to the near one; (2) **the stacks step down toward the camera** (4, 3, 2, 1 containers, far to near) so no stack hides the plate or the crane behind it, and the spreader lands on whichever stack it is over; (3) a raised concrete apron (quay at y 5, 12 m deep, accent bay lines) under the yard so the rolling terrain swell no longer buries the far stacks; (4) span 18 -> 12 m so the near crane fits the 216 px margin with the lens settled; (5) floods x 0.42 -> 0.5 and 9 -> 13 m lamp glows, the road pool dropped (two apron pools remain). Observed: the plates light exactly at the stops forward and back, pink on mauve-grey steel with the night palette (nothing blown: structure stays under the 0.85 bloom threshold, only the lamp glows bloom, softly); the entry is under the EXIT 06 deck with the crane screen-doored and the yard already standing (01); the crane fades before the EXIT 07 deck and never crosses a deck, sign, billboard, relay mast or milestone (the yard is 40-95 m off the road); reverse drive runs the crane back and dims plates in the same places; rAF p50 16.7 / p95 16.8 ms, 0 frames over 34 ms through the whole chapter; no console errors or warnings in any run; reduced motion renders the static poster with nothing; 390x844 (low tier) gets the lite yard, which the full-width panel hides except for pink slivers at the left edge.
- **Known weaknesses:** the lens eases into the chapter over ~1 s (camera time constant 1.05 s), so for the first second of the chapter the whole yard slides left into the margin with everything else in the world (the first stop at 0.1 can be reached before it settles on a fast scroll, when the crane's right leg sits under the panel edge); at 1024x700 the compact-rail panel is 90% wide with a 5% margin (51 px), so the yard is legible only at the chapter entry and in the gaps between cards (05), not in the margin; the 4-tier far stack is seen at a 30 degree yaw and reads as leaning at a glance; the floods light the stacks as a flat uniform term (no shadows); both work lamps share one strike; the crane's exit run (-80 -> -62 m) is short, so the last 20% of the chapter is a crane standing over the near stack while the yard fades; the yard's screen placement is tuned to the chapter composition constants, so a composition change needs RAIL_NDC rechecked.
- Screenshots: docs/overnight/round11/ (01 entry under the EXIT 06 deck, crane screen-doored; 02 second stop with the panel up, pink plate in the margin; 03 last stop, the near one-container stack with the work lamps; 04 1920x1080 third stop; 05 1024x700 chapter entry; 06 390x844 low tier; 07 contact sheet of the left margin across the drive, entry to Toolkit).

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 KiB