# Overnight log Branch `redesign/overnight`, forked from `redesign/award-worthy` (96ef776, frozen). Deadline 09:00 UTC 2026-10-11. Rules: one substantial move per round, commit per round, don't revisit a topic touched in the last 3 rounds. Run: `npm run build:preview` then serve `dist` (dev server shows a blank page). Node 22.22.1. ## Baseline - 688 vitest tests pass at fork. ## Round 1: The 03:12 Window (Infrastructure) - **What:** scroll-driven maintenance window across the Infrastructure chapter. HUD sub-line ("MAINTENANCE WINDOW · 03:12" -> BACKUP -> CONVERT · TRANSFER -> VERIFY -> "CUTOVER OK · 03:51", "ROLLBACK CHECKPOINT" on reverse scroll), storm sky tint, soft capped lightning (<=0.31 Hz, >=2.8 s apart), district power-down/relight, amber backup packets to a far "offsite" block, rain on the lens (LensFinishPass uRain), diagram nodes 01-04 lighting per step. Progress is scroll-driven, so scrolling back is a rollback. - **Why:** makes the "night shift" idea literal and dramatises the real Nextcloud migration (backups, convert, transfer, verify, cutover) with no invented copy. Closes the gaps "Infrastructure has no world beat" and "no rain / sky event". - **Build:** src/journey/maintenance-progress.ts, src/scene/world/maintenance-window.ts, useMaintenanceWindow.ts, maintenance.css; edits in environment, districts, palette, cinematic-grade, JourneyHud, AppShell. Reduced motion/static: no scene, diagram and sub-line still step. Low tier: dim/relight only. - **Verdict: KEEP with fixes** (Fable review on hardware GL, 1440 and 390): storm tint and lightning strengthened, clock holds 03:51 to end of chapter, phone sub-line fits. 709 tests green (+21), budgets clean (initial JS 111.7 KB gz, scene chunk +6.9 KB). - **Known weakness:** the reading panel covers the scene during p 0.1-0.75, so district power-down, packets and offsite are barely visible; relight uses the normal accent so the payoff reads as "back to normal". Audio rain bed skipped. Do not revisit before round 5. - Screenshots: docs/overnight/round1/ (before-* vs p*-1440/390). ## Round 2: High Beam (hero, road, plates) - **What:** the cursor steers the headlights. Fine-pointer hero name first paints as an outline, a 1.6 s sweep lights it, then a pointer-following halo lights the letters, plate edges and sparks; in the world the road cones yaw, terrain/districts catch the light, a warm SpotLight rakes the truss (high/medium), and a haze cone shows in the gaps between chapters. Click hero/gantry window flashes (rate-limited). Idle 4 s returns to centre. Touch/low tier: slow sway and tap flash only. Reduced motion: no effect, name stays lit. - **Why:** first thing a juror does is move the mouse; the hero had no pointer response and the scene none at all (direction.md signature moment 3, never built). Lives where round 1 said drama should: hero, gaps, panel edges. - **Build:** src/journey/headlight-beam.ts, useHeadlightBeam.ts, scene/world/headlights.ts, styles/headlight.css; beam terms in road, districts, terrain shaders. Initial JS +1.3 KB gz (113.0), 732 tests green. - **Verdict: KEEP with fixes.** Fable found the DOM half dead on delivery (NaN sentinel), fixed it, removed a drop-shadow rectangle artefact, raised the resting level. Frame times unchanged (p95 16.7 ms on hardware GL). - **Known weaknesses:** the outline-to-lit sweep beat is short (~300 ms visible); haze cone slightly flat/white; spark boost barely perceptible. - Screenshots: docs/overnight/round2/. ## Round 3: End of Shift (Contact daybreak finale) - **What:** arriving at Contact turns the night into dawn over 7 s: sky mauve/peach, stars drain, sun lifts and becomes a solid gold disc, warm rim light on road/terrain/districts, warm grade and bloom, bars warm, credit types at sunrise, HUD "END OF SHIFT · 05:48" (the joke: round 1's window ended 03:51), and a synthesized four-voice dawn pad (new mixer `dawnInput`) swells. Scrolling back rewinds in ~1.6 s. html[data-dawn] steps night/first-light/sunrise/day. Reduced motion/static: CSS-only daybreak gradient. - **Why:** the ending was engine-off but still night with a sun that never moved; the finale is the last impression, and the plumbing (sun, meteors, outroProgress, palette) was already there. - **Build:** src/journey/dawn.ts, scene/world/dawn-light.ts, audio/dawn-resolve.ts; edits in palette, environment, sun, atmosphere, horizon-air, road/terrain/districts, cinematic-grade, post-processing, adaptive-mixer, soundtrack-engine, world.css. 746 tests green, initial JS +0.7 KB gz, scene chunk +1.2 KB, outro frame times unchanged on hardware GL. - **Verdict: KEEP with fixes** (Fable): the sun/halo stack washed out to a white blob, so the sun is now gold with a smaller halo; the "DESTINATION" eyebrow was invisible on the peach sky, darkened at sunrise. - **Known weaknesses:** the "SHIFT OVER" label swap is invisible (HUD arrival label collapsed); the bottom credit is mostly hidden by the Contact panel (pre-existing); horizon still bright at full day; reduced-motion version reads as dusk rather than sunrise; audio checked by code review only. - Screenshots: docs/overnight/round3/. ## Round 4: Mile Markers (Profile + Experience) - **What:** the gantry HUD subline becomes a scroll-driven ROUTE LOG odometer ("LOG 02/04 · JUN 2025 → AUG 2025 · CCF", digit roll, " · REWIND" on reverse), and lit kilometre posts with accent plates and warm light pools come down the free shoulder, one per role/fact, flashing as their plate crosses the activation line. - **Why:** Profile and Experience were the only chapters with no world beat and left half the viewport empty. Career dates are real content, parsed from the JSON, nothing invented. - **Build:** src/journey/route-log.ts, useRouteLog.ts, scene/world/milestones.ts, styles/route-log.css; generalised maintenance-progress helpers. 766 tests green, initial JS +1.25 KB gz (115.9 of 120 - **budget nearly spent, keep DOM-side additions tiny**). - **Verdict: KEEP with fixes** (Fable): the delivered 0.18 x 2.6 m posts were 25 px specks at 80 m, so they were scaled to the ~2.3x world (0.4 x 6.4 m, 2.2 x 1.0 m plate), the pass point moved to z -12 to coincide with the tick, additive light pools added, and the phone subline overflow fixed. - **Known weaknesses:** the free side is narrow because of the camera frame shift, so the big pass is brief; plates read mostly white under tonemapping; no lit number glyphs on the plates. - Screenshots: docs/overnight/round4/. ## Round 5: Drive-In (Selected builds billboard) - **What:** a floodlit roadside billboard (22 x 15 m, right shoulder) carries the case-study media in the world: medication tracker triptych, opinion-dynamics chart pair, footy-tracker typographic plate. Floods relight per project as scroll passes each case study (reverse runs backwards), light spill on the shoulder, hover on a gallery image zooms that shot onto the board, floods breathe with the bass pulse. Reduced motion/static: CSS flood gradient on the active gallery. - **Why:** Selected builds hold the only real proof and had no world beat; DOM evidence and scene now share one object. - **Build:** scene/world/billboard.ts, journey/billboard-progress.ts + billboard-feed.ts, useBillboard.ts, billboard.css. 786 tests, initial JS 116.5 KB gz (**3.5 KB left**), scene chunk ~210 KB. - **Verdict: KEEP with fixes** (Fable, hardware GL): the delivered board was an 80 px speck, so it was rebuilt at 2.4x, moved to x 24, lit at chapter entry, floods widened, charts dimmed so bloom does not blow them out; narrow-viewport placement added. - **Known weaknesses:** the 92%-wide panel hides the board while reading (visible at chapter entry, in gaps between case studies and at exit); phone screenshots read dim; ~140 px on phones; test-only telemetry. - Screenshots: docs/overnight/round5/. ## Round 6: Dashcam (photo mode + postcard) - **What:** a camera button in the drive controls (or key `c`) folds the reading plates away, closes letterbox bars, and shows a dashcam frame with live telemetry (REC dot on the bass, chapter + exit, Bucharest clock, route %, coordinates + name). The lens drifts with the pointer (+-1.6 units, re-centres after 3 s idle). "Save postcard" downloads a 1600x900 PNG of the live scene with credit line, a white shutter flash and a synthesized shutter click when sound is on. Tab title becomes "DASHCAM · 47% · INFRASTRUCTURE · 03:51" while open. Esc/c/Close exits and returns focus. Absent for reduced motion/static/visitor-pause and below 768 px. - **Why:** the recurring weakness of rounds 1-5: the reading panels hide the world. This gives a juror one deliberate full-screen moment, and a shareable artefact. - **Build:** journey/dashcam-feed.ts, scene/world/dashcam-lens.ts, composables/useDashcam.ts, lazy components/DashcamFrame.vue + lib/dashcam-postcard.ts + audio/switchboard-click.ts, styles/dashcam.css. 820 tests, initial JS 117.73 KB gz (2.3 KB left), lazy chunk 3.7 KB gz. - **Verdict: KEEP with fixes** (Fable, hardware GL): Contact bars were striped (aubergine outro bars under black), now frame draws its own bars; canvas resized on open due to overflow lock (removed); focus dropped after save; `c` worked on phones where the button is hidden; round 5's HUD exit tab had been dropped, restored; REC dot got a no-music blink. - **Known weaknesses:** postcard is the 1440x900 buffer scaled to 1600 (slightly soft) and keeps the lens bars; no phone version; shutter click only while soundtrack runs; two chapter-label vocabularies in the frame. - Screenshots: docs/overnight/round6/ (postcard.webp is the real downloaded file). ## Round 7: Relay Station (Toolkit transmitter masts) - **What:** the Toolkit chapter is a pre-dawn relay station. Four lattice masts (one per toolkit group, rung count = technology count: 11/8/4/3) stand in the side margins; as scroll passes 0.04/0.22/0.40/0.58 each comes online: violet lamp rungs ignite bottom-up, a red beacon blinks at 0.5 Hz, a violet sky beam sweeps. The reading plates get an accent "· ONLINE" state in the same order. Hovering a technology flashes its rung. Reverse scroll takes it offline. A short synthesized chirp plays per mast when sound is on. Lite tier: static lit masts; reduced motion: CSS-only ONLINE plates. - **Why:** Toolkit was the last chapter with no world beat and the dullest content in any portfolio; lists become a lit skyline with honest counts, placed in the margins the panel does not cover. - **Build:** journey/relay-progress.ts, composables/useRelay.ts, scene/world/relay-masts.ts, audio/relay-tone.ts (lazy), styles/relay.css. 839 tests, initial JS 118.08 KB gz (**1.9 KB left**), scene chunk 214 KB. - **Verdict: KEEP with fixes** (Fable, hardware GL): near/far pairs overlapped and the near-right mast clipped, so layout is now aspect-aware with the far mast closer to centre; lamps were white and rungs grey, now hot violet above the bloom threshold; beams brightened and widened with a eased base; hover flash made visible. - **Known weaknesses:** lamp cores still tonemap to lavender-white (violet lives in the halo); masts are slivers on phones and modest at 1024 wide; hover flash is a peripheral beat; chirp verified by unit test only. - Screenshots: docs/overnight/round7/. ## Round 8: IGNITION (the first three seconds) - **What:** the site opens as a film: the first rendered frame is cold (exposure 0.35, lamps off, road stopped) and dissolves over the SSR poster in 0.6 s; dipped lamps at +0.6 s, main beam at +1.0 s with the hero-name sweep; from +1.0 to +3.0 s the road and streaks ease to cruise while the exposure rises and the crane starts; the HUD subline reads IGNITION, then SHIFT START · 02:58, fading out by +4.5 s. html[data-ignition] walks cold → lamps → rolling and is removed. Returning visitors (localStorage nightdrive:route) get the short form; a scroll, nav, dashcam or section change inside 3 s cuts to driving in 0.4 s; deep links skip it; reduced motion, static and data-saver keep the poster only. - **Why:** the previous opening was a poster that silently became a lit, cruising scene: a loading state. An ignition beat is a reason for the dark first frame and makes the pull-away the first thing the visitor watches. - **Build:** scene/world/ignition.ts, journey/ignition-feed.ts, styles/ignition.css; environment.ts, useHeadlightBeam.ts, car.ts, road.ts. 854 tests (74 files), initial JS 118.23 KB gz (1.8 KB left), CSS 26.73 KB gz, scene chunk 215 KB gz. - **Verdict: SHIP** (Fable, hardware GL 1440x900, fresh context): beats land on the spec clock (lamps +0.60, rolling +1.00, sweep +1.05, attribute removed +4.5 s); the dissolve is one exposure pull (the poster darkens with the canvas fade, frame luminance 47.7 → 28 with no step over 15 per 200 ms); rAF p50 16.7 / p95 16.8 ms after the first frame. Fixes made during review: (1) the ignition clock no longer counts the first-frame shader stall, so the cold hold is a real 0.6 s; (2) the poster dims with the dissolve instead of a bright image giving way to a dark one; (3) the hero name is unlit until the sweep (the lamp's idle drift pre-lit letters the hold then darkened); (4) every program is compiled in frame 0 behind the poster by a warm render of the whole scene (hidden objects visible, culling off) through the real post-processing pipeline. renderer.compile() keys programs for the screen and never matched the composer's linear targets, so the car, the sign and the streaks each compiled on first sight: 230-280 ms stalls on the first scroll, which tripped the 250 ms catastrophic-frame downgrade and rebuilt the scene mid-opening (a 350 ms freeze and a brightness pop). After the fix no long task follows the first frame in any scenario; the first scroll cuts cleanly in 0.4 s. - **Known weaknesses:** the first frame now lands ~1.7-1.9 s after navigation on a cold GPU (all ~60 programs compile behind the poster in one 1.2 s task; the poster holds, nothing is blank); clicking a nav link inside the opening fires the pre-existing exit-sign flare, one bright frame (mean 80/255) on arrival; the phone opening is quieter (no hero sweep on coarse pointers); the short form's road start is a small 5-point dip in luminance before cruise. - Screenshots: docs/overnight/round8/ (01 long contact sheet 1.5-6.0 s, 02 cold frame, 03 lamps on, 04 rolling + sweep, 05 short form, 06 early-scroll cut sheet, 07 phone 390x844). ## Round 9: UNDERPASS (chapter transitions) - **What:** every chapter boundary is an overpass deck (exits 02-08, 'EXIT 0N' face plate in the exit accent). It rises out of the haze once the exit sign has fired, holds behind the sign while it comes in, and passes over the camera as the next heading crosses the line; the cut happens in its shadow. The sky, fog and the sky-lit road/terrain terms dip at most 35% (edges >= 300 ms, latched once per pass, >= 1 s apart), three sodium strips and a road pool wash amber, the palette settles x4 under the deck, html[data-underpass='under'] tints the HUD label, and a 600 ms noise swell plays if the soundtrack is audible. Scrolling back re-emerges under the same deck. Brisk scrolls and nav long-scrolls get the structure only. Low tier: deck and strips. - **Build:** journey/underpass.ts (pure), scene/world/underpass.ts, audio/underpass-pass.ts (lazy); environment.ts, palette.ts (dampPalette moved here, rate arg), road.ts, terrain.ts, world.css, bundle-budgets.mjs (lazy chunk class), flash-analysis.md. 872 tests (75 files), initial JS unchanged (+6 B gzip hash noise), CSS +50 B gz, scene chunk +2.8 KB gz. - **Deviation:** deck clearance 22, not 14: the docked exit sign's top edge stands 14-20.4 m above the road at 1440x900. - **Verdict: SHIP** (Fable, hardware GL 1440x900 high tier, wheel-driven passes, frames every ~100 ms): the deck is big, reads as a concrete overpass (parapet, soffit, piers, three strips) and the plate is legible from mid-distance; the sign/deck hand-off is clean (the deck holds in the haze until the sign has passed, and on a brisk approach it sits behind the sign, never through it); the shade beat is one slow dip and release with no step over 22/255 in frame mean (sky band <= 45) at any of Start->Profile, Profile->Experience, Infra->Builds, Builds->Additional, Toolkit->Contact; reverse scroll re-emerges under the same deck (shade latches again, 1 s apart); brisk and nav-jump passes get the structure and no shade/sound; reduced motion renders the static poster with nothing; 1024x700 (medium) shades, 390x844 (low) shows deck+strips only; rAF p50 16.7 / p95 16.7-16.8 ms in every serial run, 0-1 frames over 34 ms, no console errors. Fixes made during review: (1) DECK_PASS_Z 30 -> 25 (the chase camera's z): the deck had gone overhead ~5% of the gap (~1 s at a slow scroll) before the HUD cut, now the cut lands ~0.5 s after 'under' sets, in the deck's shadow; (2) STRIP_GLOW 2.4 -> 1.3 and POOL_GAIN 1.6 -> 1.1: the strips crossed the 0.85 bloom threshold and washed the frame then dropped (sky band 146 -> 32 in one step at Contact), now the strips read as sodium tubes without a flash; (3) plate 11x2.75 -> 16x4.2 over the deck face + parapet, 168 px type, 14 px accent bars: 'EXIT 0N' is readable at z ~ -100 instead of only in the last 30 m; (4) pier shader: 2.6 m form lines, grime at the base and the sodium pool bouncing up the lower faces, so the close pier is poured concrete, not a flat slab. - **Known weaknesses:** the pier at x 16 crosses the left edge of the Selected-builds billboard (stilt at x 17) in front of it for ~6 m of travel, and one expressway lamp head pokes past the right pier at Infra->Builds (both brief, both read as foreground structure); the Contact deck is lit by the dawn sun and reads paler than the night decks (intentional, but less massive); a moderate approach walk can set data-underpass for ~50 ms once before the real pass (hidden by the 0.3 s HUD colour transition, no visible effect); the low tier never shades, so phones get the structure without the beat; `portfolio-underpass-frame` events only exist in test builds, so the review read html[data-underpass] and screencast frames instead. - Screenshots: docs/overnight/round9/ (01 EXIT 02 rising behind the docked sign, 02 under the deck with strips and piers, 03 EXIT 03 overhead at the cut with the amber HUD label, 04 EXIT 08 at dawn into Contact, 05 EXIT 05 pier against the Selected-builds billboard, 06 phone 390x844 low tier, 07 contact sheet of the Profile->Experience pass 20.5-25.5 s). ## Round 10: PARKING LIGHTS (living tab title + favicon) - **What:** the browser tab is part of the drive. After mount, document.title follows the route in 5% steps ("ROUTE 45% · INFRASTRUCTURE", "ARRIVED · CONTACT"), reads "PARKED · 45% · INFRASTRUCTURE" while the tab is hidden, keeps the metadata title through the ignition opening and while the scene is still coming up, hands the title to the dashcam while it is open and resumes on close. The favicon is a lazy SVG data URI: the index.html plate and 'L' plus two headlight beams that lengthen and brighten with the route in the chapter accent (SIGN_ACCENTS), two amber parking lights when the tab is hidden, gold on peach at html[data-dawn='day']. Writes are rate-limited to one per 400 ms (visibility, dashcam hand-back and the scene settling write at once). Reduced motion / static: live title, one fixed lit icon. SSR output and index.html unchanged. - **Why:** the drive had no presence outside the viewport; a juror with twelve tabs open sees the route resume in the tab strip, and the parked state is the last thing the site says when they look away. - **Build:** journey/tab-feed.ts (pure, initial chunk: title + 5% quantiser), journey/tab-icon.ts (lazy chunk, 0.67 KB gz), composables/useLivingTab.ts, AppShell.vue (one call), bundle-budgets.mjs (tab-icon chunk class). 894 tests (77 files, +22), initial JS 119.07 KB gz (+0.04 KB; **0.9 KB left**), CSS 26.78 KB gz, scene chunk unchanged. - **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). ## Polish pass (owner feedback) - **What:** traffic as real vehicles (dark low-poly cars and box trucks, paired tail lamps, a centre brake lamp, amber clearance lamps on trucks, fog-coloured sheen, one pool per vehicle with its own tint); shoulder reflectors became delineator plates on the guardrail posts, and the amber road studs were removed; the owner's name left the navbar (it stays in the hero); icon buttons centred (the play/eq tile inherited `justify-content: space-between`); the "Email me" preview is a flex item after the button, so it clears it at any width; DASHCAM opens in two phases (the page folds only once the frame has mounted), retries its chunk once, abandons after 4 s, always has an enabled Close, recovers from an unanswered capture, closes on scene loss, motion withdrawal or a resize below 768, no click-to-capture on the empty frame, and keeps focus inside the dialog on such a click. - **Weaknesses addressed:** postcard at native resolution (largest 16:9 crop up to 2560 wide) and one chapter vocabulary (EXIT nn); dashcam percent quantised like the tab (5%); reduced-motion SceneCanvas writes html[data-dawn] only on change; SHIFT OVER now turns over on the HUD sub-line at full day; the reduced-motion dawn masks the poster's sunset sky for a blue-zenith, gold-horizon daybreak; mile-marker plates stay in the chapter accent (below the tonemap shoulder) and do not flash while swept past by a navigator jump or a fling (nav-click peak frame mean 91-101 -> 58-62, no rising step over 12); html[data-underpass] waits for the shade to hold 120 ms; lite billboard keeps both floods on (phone board brighter). - **Budgets:** initial JS 115.43 KB gz (from 119.08: IconGlyph draws the six Phosphor glyphs from their regular-weight paths instead of importing the package components, which ship all six weights each), CSS 26.93 KB gz (+0.24), scene chunk 222.95 KB gz (+1.6), DashcamFrame 3.74 KB gz. 925 tests (79 files), violations []. - **Left:** relay lamp cores (a saturated violet cannot pass the luminance bloom threshold, so a violet core loses its glow); mast girth at 1024/phones (bounded by the panel-margin layout test); cold-GPU first frame; underpass pier vs billboard edge; yard lens slide and far-stack lean. Headless hardware-GL Chromium loses its GPU process when a project video starts (SharedImage BGRA failure), also at ca12cfd; not an app fault. - Screenshots: docs/overnight/polish/ (WEBP). ## Polish: mile markers ride the road (owner feedback) - **What:** the kilometre posts were parked at scroll-mapped z and stood still while idle ("way too static... half implemented"). They are now road furniture on a fixed 60 m lattice (4 posts, one InstancedMesh) driven by the drive's travel distance, like the rails, delineators and pylons, so they stream past at idle cruise and speed up with the drive. Plain posts carry a small dark plate with an accent rule and a lit three-digit kilometre number (digit strip in a canvas atlas). The route log rides the lattice: a post still in the haze (z < -165) is handed the next entry when, from the smoothed scroll rate and road speed, it would reach the pass line about when that entry's plate crosses the activation line, or straight away once the reader has stopped (0.4 s) on an entry it has not passed. That feature post gets a large dark plate (accent band "LOG 02/04 · EXP", the dates "JUN→AUG 2025", the organisation code "CCF", lettered from the page's inert input snapshot so nothing is added to the initial bundle), a lamp head that warms up as it approaches, an accent-tinted pool that sweeps the shoulder and lane as it passes, a +8% bass swell, and a soft glint at the pass line. - **Rules kept:** the road never runs backwards; scrolling back re-arms entries and their posts come up the road again. Predictions only reach the next entry either way and wait 0.3 s after a chapter change and 0.6 s after a sweep, so a navigator jump hands nothing out mid-flight; no glint while sweeping, at most one every 0.6 s. Chapter changes are linear 0.35/0.25 s screen-door ramps (no pop; Profile's left-shoulder posts fade as Experience's right-shoulder posts arrive). Plates stay under the bloom threshold; only the lamp blooms when close. Low tier/touch: no beam, pools, pulse or glint. Reduced motion and SSR untouched. - **Budgets:** initial JS 115.54 kB gz by Vite (+13 B gz: three more export bindings from route-log for the scene), scene chunk 225.05 kB gz (+2.1). 932 tests (79 files), violations []. - **Review (Sonnet, hardware GL):** per-frame allocations removed, non-finite distance guarded; featured plates now hang on a 4.2 m arm over the road (clears traffic at ~6.3 m) so the Experience plate is fully in frame at 1440. - **Fixed after (opening entry):** a chapter's first entry used to arrive up to two entries late when the reader started at the heading, because only posts in the haze (~150 m out) could take an entry. Now, for 0.75 s after a chapter change, the posts already on the road stay dark; once the reading pace is known, the one that will pass closest to the first entry's activation takes it (the nearest when the reader is still), unless a post from the haze would be on time anyway. Haze assignments wait for that, and there is no glint in the 0.3 s after a change or on a post leaving its chapter. Unit tests show entry 0 now passes within 0.4 of an entry's share of its line (it used to miss by up to about 2 shares), and within 6.5 s when the reader stays at the heading. - Screenshots: docs/overnight/polish/posts-*.webp (before/after, idle contact strips before and after, feature plate zoom).