Quadrille Showroom
Search the build
-
17535f52026-07-03 chore: macstudio3 migration — reconcile from mac2 + repoint paths (stevestudio2→macstudio3, node/npm/npx→/opt/homebrew) -
e7f3b0f2026-07-02 auto-save: 2026-07-02T11:47:40 (2 files) — public/js/rack.js public/js/showroom.js -
a1560522026-07-02 5x sweep 1: keep bottom-corner panels clear of the centre pager (fix #g-next occlusion) -
b657af02026-07-02 auto-save: 2026-07-02T10:47:21 (3 files) — package-lock.json public/js/dock.js public/showroom.html -
bf8db8a2026-07-02 chore: v1.3.2 (session close — furniture style selector + art direction) -
02b4e0a2026-07-02 furniture FIX 2: Transitional now unmistakably distinct from Contemporary -
6bdf2b52026-07-02 furniture FIX 1: onload = clean empty room + table+chair only (no room-type dressing on boot) -
0a7d7ab2026-07-02 furniture: art-direction fixes — concrete-grey Brutalist, warm-wood Transitional, visible walnut Traditional -
646f4b92026-07-02 auto-save: 2026-07-02T09:46:55 (1 files) — public/js/showroom.js -
20c04ec2026-07-02 chore: v1.3.1 (session close — thumb/proxy upstream hardening + ContrarianGo) -
97b809a2026-07-02 ContrarianGo iter1: shared fetchUpstreamBuffered for BOTH thumb + proxy; split transient/permanent; warn-log -
b6f8daf2026-07-02 5x sweeps 2-5: upstream concurrency cap + placeholder fail-safe for sliver thumbs -
aec52fe2026-07-02 auto-save: 2026-07-02T08:46:35 (30 files) — data/thumb-cache/099160b17f710e570c5aa9ac.jpg data/thumb-cache/0b9c68a67796dd1ccce90a5a.jpg data/thumb-cache/2ba7e03368ff27763d2ef6a1.jpg data/thumb-cache/3f441bb0f30a6e1d2e049c99.jpg data/thumb-cache/44fbcf466a13d44c920bf876.jpg -
d9cf3b22026-07-02 5x sweep 1: retry transient upstream in /api/thumb (cold-cache burst 502s) -
3ac09a02026-07-02 chore: lint, refactor, v1.3.0 (session close) -
fb869a92026-07-02 Wire the George email picker for sample requests (sending gated) -
38c41722026-07-02 Build sample-request submit: endpoint + tray form + admin cards (steps 1-3) -
cc9d4282026-07-02 Scope the sample-request submit endpoint (age rides along) -
d6a840c2026-07-01 chore: refactor + v1.2.2 (session close) -
df1dc512026-07-01 auto-save: 2026-07-01T11:11:52 (2 files) — public/js/showroom.js scripts/_reverify.mjs -
59eede32026-07-01 Capture visitor age as a plain data point on the Sample Tray (replaces Age View) -
88e4cd82026-07-01 chore: v1.2.0 → v1.2.1 (session close — /5x fixes + verification suite) -
e4d7eca2026-07-01 Remove Age View / age-adaptive theming entirely (per Steve's call) -
e0bed2f2026-07-01 verify: At-the-Table behavioral test (nook hide/restore + seated set + sample-add) + verify-all runner -
48406612026-07-01 5x follow-up: WebGL scene-correctness + FPS verifier (closes the biggest coverage gap) -
504a0ed2026-07-01 5x sweep 3 (contrarian-driven): persist sort+density to localStorage (standing rule) + repeatable reload test -
f0433172026-07-01 auto-save: 2026-07-01T10:11:20 (2 files) — public/js/showroom.js scripts/verify-sort-density-persist.mjs -
da296672026-07-01 5x: prove sort/density reachable+functional via ☰→Controls (selectOption OK, density OK, 0 errors) — closes the false-positive gap -
682e04f2026-07-01 5x: REPORT.md — six-way GREEN after sweep 2 (6/6, 0 console errors, cross-browser); dup-id fixed; sort-in-dock false-positive documented + design question surfaced -
604475e2026-07-01 5x sweep 1: fix duplicate id=density-wrap (7x → class); document sort/density-in-dock false-positives -
bb091f82026-07-01 Age View Phase-5.5 (contrarian pass): coalesce avatar rebuild, tighten in-page gate, capture screenshots -
d4295bd2026-07-01 Age View Phase-5.3: cross-engine render gate (Chromium/Firefox/WebKit) -
1ea5d2b2026-07-01 Age View Phase-5 gate: fix under-spec type sizes on Senior/Elder bands + add re-runnable verifier -
e0349102026-07-01 auto-save: 2026-07-01T09:10:58 (1 files) — public/js/dock.js -
842a1dc2026-07-01 showroom polish (070126A): wrap consultation nook in a group + hide it in the At-the-Table view (only the centre table shows), restore on exit -
90fe8f02026-07-01 showroom: boot = first-person user standing in the doorway at the entrance end, stopped (no auto-walk); uniform same-size control pills + small pills on the bottom bar -
8dfe0722026-07-01 showroom P3: At-the-Table view — seated avatar + click-pattern-to-center + add/drag/remove samples on the table (basket persisted); fix addSample null-deref + table recorder -
0fb3c6b2026-06-30 auto-save: 2026-06-30T21:43:31 (2 files) — public/js/showroom.js public/js/viewmodes.js -
5388cf12026-06-30 showroom P2: 5 room types (bedroom/office/living/lobby/gallery) + hybrid furniture (2 real GLB heroes + primitives) + flooring/room pickers + adjustable room; null empty model slots (no 404s) -
02a9c212026-06-30 auto-save: 2026-06-30T20:43:13 (9 files) — public/js/showroom.js public/js/viewmodes.js public/showroom.html public/js/GLTFLoader.js public/models/ -
bc32b4a2026-06-30 showroom P1: remove angled/orbit/topdown, boot=walk-through-center, macro=2.5ft, carousel=continuous parade, compare=user-choosable two designs -
2b90e022026-06-30 spec: 5 room types for showroom room-preview -
6c84fb02026-06-30 add boot-walk + carousel screen-recording harnesses -
c66a5872026-06-30 fix Wing° control: VIEW_OPEN was set by the slider but never read — now rakes the focused open board live (+re-ease nudge) -
4bb3eba2026-06-30 chore: lint, refactor, v1.2.0 (session close) -
de7d9e42026-06-30 Avatar nav: comfortable centred boot framing + grounded scroll/arrow walk, drag-turn, and always-available Return to Center -
b81c3932026-06-30 chore: vN minor bump (session close — Age View bands, walls-on-Next, dock fixes) -
66c765f2026-06-29 Loop ledger iter5: two clean clickthrough sweeps + visual confirmation of bar-legibility fix -
67caf4d2026-06-29 Age View bar legibility: fix invisible readout text on light-panel bands + add per-band bar-legibility gate -
796c25f2026-06-29 walls-on-next: add Age-View-ON regression pass (paging under senior band still clads all 4 walls) -
71784da2026-06-29 Add measured env-morph verifier: asserts real rendered wall-luminance delta (35 vs 85), not just intensity scalars -
08a84792026-06-29 Age View FPS gate: measure steady-state by discarding morph-rebuild transient window (floor unchanged) -
e40c08a2026-06-29 Feature: Next/Prev book-page renders the new design on all 4 walls -
c3784732026-06-29 Age View band-differentiation: split young/adult/established into 3 hue families -
c4fd7f22026-06-29 dock polish: stow pager on boot (P1), cascade first-open (P2), auto-close menu on launch (P3), Controls first-open height (P5) -
95724fe2026-06-29 Arrow keys (left/right) page prev/next pattern on the wings; body-turn moves to A/D -
2bef6b42026-06-29 /5x REPORT: 2 dock.js bugs fixed, 2 clean sweeps -
b3ca21a2026-06-29 /5x: showroom-aware clickthrough + fix 2 real dock.js bugs it caught -
52d16fc2026-06-29 snapshot: clickthrough script + 5x report from review pass -
d5980302026-06-29 Next/Previous step one pattern across all 883 + keep pager visible while walking -
3b94ca12026-06-29 Hamburger dock: stow all panels on load + launch each as movable modal; hide first-person avatar in framed views -
a785d8a2026-06-29 Center book starts open at 20 degrees (was 65) -
80267e92026-06-29 Center book: open leaves FORWARD at 65° + wire Open° slider to live splay -
61450902026-06-29 auto-save: 2026-06-29T15:24:16 (3 files) — public/js/showroom.js public/js/dock.js public/js/modal-rig.js -
f1439ea2026-06-29 Fix center-book leaf orientation: leaves face the viewer (drop the PI group flip) -
fa8ee902026-06-29 Default view = walk the avatar + single centered mirrored book + minimal caption bar -
04948ab2026-06-29 Phase 5.5 /contrarian final pass: prove the AVATAR half + fix 2 weak non-senior CTAs -
71a067a2026-06-29 Phase 5.3 cross-engine verifier: Age View slider PASS on WebKit + Firefox -
d84af5b2026-06-29 Phase 5 senior-usability HARD gate: measured verifier + 3 cascade/wiring fixes -
fc2441f2026-06-29 Age View: continuous avatar age-morph (ageRigParams + upperRig stoop sub-group) + default-off age slider with banded UI/env snap + senior-opaque APCA gate -
3048f972026-06-29 AGE-VIEWS-SPEC: apply /contrarian plan-gate fixes (opaque HUD backing for senior APCA-over-WebGL, gate the slider at 85, upperRig sub-group for stoop, differentiate bands 21/28, per-band env FPS profiling) -
bdcbe782026-06-29 Add AGE-VIEWS-SPEC.md — overseer plan for 10 age-adaptive avatar showroom views (12-85) -
f94d9662026-06-29 High-end versions batch 3: V18 Infinity Mirror + V19 Conservatory Garden + V20 Penthouse Dusk — ALL 10 high-end versions (V12-V21) now built + registered in the picker -
c4480af2026-06-29 High-end versions batch 2: V13 Atrium Daylight + V14 Velvet Lounge + V15 Brutalist Concrete + V17 Japanese Tatami (protos + registered in picker; 7/10 high-end versions live) -
607b67f2026-06-29 auto-save: 2026-06-29T06:19:10 (4 files) — public/proto/v13-atrium-daylight.html public/proto/v14-velvet-lounge.html public/proto/v15-brutalist-concrete.html public/proto/v17-tatami.html -
fad82ea2026-06-29 Register V12 Gallery Noir + V16 Art-Deco Salon + V21 Garcia Room in the version picker (overlay entries + VERSION_ORDER + element lists for the code system) -
fbe45482026-06-29 High-end versions: add V12 Gallery Noir + V16 Art-Deco Brass/Marble + V21 Garcia Room proto scenes (PBR/PMREM/ACES, real China Seas textures, 0 errors) -
1c4a04e2026-06-28 Avatar polish: lighten 1st-person sweater 0x2e3138->0x3d424d (look-down readability, /contrarian note) -
09cf8ad2026-06-28 Chunk K (first-person Steve avatar, yaw-only rig) + Chunk A′ (20'×20' room) -
33391a62026-06-28 Boot raycaster race fix: queue pre-ready canvas clicks + replay on ready (durable) -
1303c942026-06-28 Finalize definitive build: remove dev 30s auto-reload scaffolding from showroom.html (contrarian whole-build sign-off polish) -
18497fa2026-06-28 auto-save: 2026-06-28T21:16:50 (125 files) — cta/rec/chrome.mp4 cta/shots/chrome/all-designs-after.png cta/shots/chrome/all-designs-before.png cta/shots/chrome/auto-tour-after.png cta/shots/chrome/auto-tour-before.png -
229a7b02026-06-28 Slice3 gate hygiene: annotate headless FPS flag as HEADLESS-SKIPPED + commit real-GPU artifact (scripts/slice3-fps-realgpu-result.json — M2 Max Metal 72fps, gate55_met:true) — one authoritative truth source per /contrarian -
0979b2b2026-06-28 Slice-3 F: FPS.ms.draws HUD readout + off-thread wall-clad decode (kills the select-moment dip) -
1b5eb932026-06-28 Slice-3 H: globally-unique element build codes (1000QH<version>) -
c4a14bb2026-06-28 Slice-2 contrarian fixes: HOLE-3 detail starts COLLAPSED on every fresh selection (drop localStorage override footgun) + spec-legal proof harness (real ArrowL/R yaw to +/-72 clamp, NO mode switch). HOLE-1/HOLE-2 verified already-correct: hero opens flip=0.999 / 6.02x neighbour width; clad walls visible front (252 cells) + side at clamp (680/643 cells); posDelta 0; 16/16 assertions pass, errorCount 0. -
34871bc2026-06-28 auto-save: 2026-06-28T18:16:07 (2 files) — public/js/showroom.js scripts/diag-probe.mjs -
0e9e5642026-06-28 Open-face clean: hero board pushes forward + re-centres so the open 30x6 face reads full-bleed edge-to-edge with NO neighbour slat-bars/frames crossing the pattern -
f0eacf12026-06-28 auto-save: 2026-06-28T17:45:58 (1 files) — SHOWROOM-REFERENCE-FROM-VIDEOS.md -
6b2e2012026-06-28 Slice 2 (D+E) verified: click=selection (board opens flat, detail card collapsed-by-default, expandable to 27x27 China Seas specs) + every selection clads ALL 4 walls (front wall now in roomWalls[], wallsAutoClad default ON, clad unconditional on focus, 27in repeat). Boot stays Slice-1 clean: no selection/panel, neutral walls (cladToken race-guard + _qhBootSettled boot-guard prevents transient Hero-focus leak). 4/4 walls assert PASS, posDelta 0, yaw clamp +/-72 intact, errorCount 0. V1-V11 + V11 seated overlay untouched. -
15572c32026-06-28 Add Playwright carousel verifier + npm verify-carousel script (Chunk I proof harness) -
396a02d2026-06-28 Chunk I: dry-cleaner/tie-rack carousel — click any sliver conveyor-shifts the whole rack so the clicked board eases to the dead-front centre slot, then fans open (camera stays fixed-centre) -
0ae67ed2026-06-28 snapshot before carousel build: Slice-2 boot-guard (_qhBootSettled) + cladToken + verify-slice2 artifacts -
966628f2026-06-28 auto-save: 2026-06-28T17:15:46 (1 files) — public/js/showroom.js -
13c193b2026-06-28 snapshot before Slice 2: cladToken boot-race guard (in-flight onload invalidation) -
04ca1672026-06-28 /5x sweep-1 report: Slice-1 build verified clean (HTTP/render/3-browser/0-errors/real-controls); clickthrough failures = harness vocabulary mismatch, not app defects -
2c946ef2026-06-28 Slice1 fix-it: 72° yaw clamp (non-empty), 50 boards, ~36° resting-open middle -
37affeb2026-06-28 Slice 1: open-angle slider (qh_open_angle, 45° default, 20-90°, live re-rake) + middle board opens at measured 45° on boot; bump density max to 50 -
c38484d2026-06-28 auto-save: 2026-06-28T16:15:32 (1 files) — LIQUID-UI-SPEC.md -
1fbedd22026-06-28 Slice 1 (A+B+C): 14x14 room, fixed-centre yaw-spin camera (clamped), 50 wings w/ ~2in slivers + middle open-at-angle on boot -
8c6da3e2026-06-28 auto-save: 2026-06-28T15:45:20 (1 files) — cta/ -
49978bc2026-06-28 auto-save: 2026-06-28T10:44:13 (5 files) — data/thumb-cache/143b196e361cfcabac432402.jpg data/thumb-cache/2592d7f617769f8a4a430efd.jpg data/thumb-cache/607c51b820948e86e419768a.jpg data/thumb-cache/66509ef89fd93c999d240cba.jpg data/thumb-cache/ee078617ded1664759e51f12.jpg -
731f06d2026-06-28 auto-save: 2026-06-28T10:14:06 (1 files) — data/thumb-cache/c987c8b51e74d135d6c0670b.jpg -
d9c5d8c2026-06-28 Wire Sample Table into the version picker as V11 (Add Sample drops swatch on the table; full-screen overlay + Back + numbered elements) -
61fe1e22026-06-28 auto-save: 2026-06-28T09:43:58 (3 files) — public/js/showroom.js server.js data/thumb-cache/ -
765e0042026-06-28 Proto V6-V10: refresh final verification screenshots (0 console errors each) -
27c72af2026-06-28 V10 Concierge Nook: boards now genuinely LIE on the table — share the table's exact perspective + 58deg rake + vanishing point (coplanar with the wood), counter-rotate ONLY the placard so labels stay readable, in-plane foreshortened cast shadows seat each board on the felt; placard color dot grounded on enrichment hue -
cbee4bb2026-06-28 V9 Walk-In Room: photo-real depth — soft contact shadows ground sofa/rug/lamp, vertex-baked corner AO modulated by window light (bright near window, deep far), procedural paper bump for surface tooth; killed the stacked-multiply black wedge by softening + offsetting layers -
7f3989c2026-06-28 V8 Swipe Tower: keep biases the queue via enrichment taste model (family/bucket/hue affinity) — shuffle deck on load so bias is observable, soft re-rank on every verdict, FREEZE=3 protects visible stack, 1-in-4 exploration curveball so it curates without a filter bubble; legible 'More like X' + 'change of pace' badges. Proven: keep 3 blue -> blue top-20 share 15%->65%, 4/20 explore cards -
206ff852026-06-28 auto-save: 2026-06-28T09:13:51 (4 files) — public/js/rack.js public/js/showroom.js public/proto/v7-moodboard.html public/proto/shots/v7-moodboard.png -
f541de62026-06-28 Sample Table: add-sample drops the square swatch onto the consultation table -
b271af42026-06-28 V6 Color River: ground hue on enrichment.json; bridge the neutral mid-river pause — density-steer neutrals into thin chromatic stretches, lift gap neutrals up as stepping stones in the stream, add legible near-edge waterline + per-swatch flow bob -
e142ff72026-06-28 auto-save: 2026-06-28T08:43:43 (1 files) — public/js/versions.js -
12235142026-06-28 Docs: VERSIONS.md — close the V6-V10 fork; document the integrated 10 (real mechanics as full-screen overlays + integration test) -
51ceefa2026-06-28 Clean stale proxy-server comment in v10 proto (now served same-origin from public/proto) -
962e2f72026-06-28 Enrichment: coarsen patternBase family to first-word family (778 -> 121 families, 99 multi-colorway) for pairs-well-with; regroup in-place preserving hue; add family key to enrich.js -
3fb55962026-06-28 Wire V6-V10 as real full-screen mechanic overlays (Color River, Mood-Board, Swipe Tower, Walk-In, Concierge); proto-chrome Back+legend bridge; integration test passes 72fps/0 errors -
e40b5192026-06-28 Off-thread texture decode (fetch+createImageBitmap) kills the rapid-nav stall: senior 69/72, 2min 72/72, 0 errors. + smaller FullDesign detect canvas. Both FPS gates now rock-solid above 50. -
e4cdbac2026-06-28 Data enrichment: hue/color_bucket (878/883) + patternBase/room sidecar (data/enrichment.json) + 5 new-mechanic prototypes (Color River/Mood-Board/Swipe Tower/Walk-In Room/Concierge) in proto/, all contrarian-gated -
6241da82026-06-28 auto-save: 2026-06-28T08:13:35 (4 files) — proto/shots/v10-concierge.png proto/v10-concierge.html proto/verify-v10.cjs public/js/showroom.js -
597fb5b2026-06-28 proto: COLOR RIVER — shop China Seas by hue as a flowing Three.js color current -
cbd8fb92026-06-28 Tighter arc (86deg span, ~75% overlap = thinner slivers) + warmer cream plaster + calmer exposure to match PJ photo; gates hold (senior 50/69, 2min 69/71, 0 err) -
72bd4762026-06-28 proto v7: mood-board table — drag swatches, build palette, pairs-well-with -
0ecda362026-06-28 Thin slivers (reveal 70 / steeper rake) + walls stay cream plaster like the PJ photo (auto-clad off) → senior FPS 51/69, 2min 69/71, 0 errors; rapid-nav hitch gone -
47aa29a2026-06-28 auto-save sync: showroom.html (font link + versions.js script wiring) -
e6c14ec2026-06-28 Add V1-vs-reference comparison + 10-version contact sheet; document build status + flag contrarian V6-V10 fork -
59541062026-06-28 V1 establishing arc (matches pj-dallas-showroom.png) + V2 step-driven conveyor + rail layout -
f75fcc72026-06-28 Perf + PJ-accurate isolate: hero stays AMID the sliver arc (not hidden); only hero casts shadow; shared board geometry + cached placards + shadow-rebake budget → 2min FPS 57/68, 0 errors, specs intact -
fecd0e82026-06-28 auto-save: 2026-06-28T07:43:27 (4 files) — public/css/showroom.css public/js/showroom.js public/js/versions.js scripts/test-versions.js -
1a31ad62026-06-28 10 VERSIONS system: V1-V10 picker rail + numbered-element overlay + Chosen Elements tray -
c421efa2026-06-28 Contrarian pass: corrected 10 to genuinely-distinct mechanics (killed 5 reskins; added Color River / Mood-Board Table / Swipe Tower / Walk-In Room / Concierge Nook) -
c499d152026-06-28 Consultation nook (round table + 2 boucle chairs + plant + swatch cards) in arc foreground; 18-board packed arc; reveal slider verified live (20/62/90) -
f51220a2026-06-28 PJ arc rack v1: single-vertical-hinge boards on a curved brass rail (rack.js), reveal slider, flip-to-open hero; replaces flat-wall butterfly -
6593c482026-06-28 VERSIONS.md: 10 numbered showroom versions w/ numbered elements for in-UI select-and-choose; + card-wall/conveyor/fan/carousel specs -
24bbad72026-06-28 auto-save: 2026-06-28T07:13:19 (1 files) — WINGBOARD-SPEC.md -
360b17f2026-06-28 Lock PJ wingboard-rack spec (Image #6 Dallas showroom) + save reference: arc rack of sliver-packed wingboards, bronze frames, flip-to-open, consultation nook, user-adjustable reveal -
cd16d7f2026-06-28 Perf: on-demand shadow maps (autoUpdate off, rebake only on geometry/light/visibility change) — p95 render-ms ~0.9ms→0.5ms, zero visual change; wire requestShadowUpdate into focus/flip/theme/mode changes -
afcaf8b2026-06-28 auto-save: 2026-06-28T06:13:03 (3 files) — public/js/showroom.js public/js/viewmodes.js scripts/test-views.js -
52f212e2026-06-28 Add 10 switchable view modes + 6 lighting themes + toggleable perf readout (View/Theme panel) -
c1cf76b2026-06-28 TEMP dev aid: auto-reload open tab every 30s (idle-guarded 6s; skips Playwright/webdriver so tests aren't disrupted) -
4df383e2026-06-28 Detail popup starts COLLAPSED on load (chevron to expand, persisted); step camera back on focus (board fills ~70% of frame with margin, was overfilling/too close) -
155681c2026-06-27 REVIEW.md: pass 7 — senior-first guided nav + subtle bloom, gates passed -
ed4ad462026-06-27 Realism: subtle additive-blend bloom halo on ceiling cove strips (no postproc stack); FPS-neutral (min 65) -
2b0c2692026-06-27 Senior-first Guided Mode: big no-keyboard nav (Prev/Next/Auto Tour/All Designs), Explore toggle off by default, large title+instruction -
d7f73cb2026-06-27 REVIEW.md: pass 6 — gap A blocked (no hi-res source, 1000px ceiling), gap B dominant key done -
ffa75d52026-06-27 Dominant key light: ambient 0.72→0.5, hemi 0.58→0.45, key 0.7→1.05 — committed to one warm key for photographic modelling/direction; fill kept high enough swatches stay true+legible. FPS 72, specs intact -
fb6800c2026-06-27 REVIEW.md: FINAL pass-5 section — honest B- grade (up from D+ at pass 1) vs a real Phillip Jeffries showroom photo. Documents what the per-board lighting pass resolved (gradient+sheen / wall drop-shadow / real picture-light shadows, all measured) and the top 2 remaining gaps: swatch-tile resolution (source-side) + commit-to-one-dominant-key lighting authoring. -
ac87a362026-06-27 REAL PICTURE-LIGHT SHADOWS: enable castShadow on the gallery picture-light spot so each board casts a soft, physically-correct shadow onto the wall behind it (and faintly onto neighbours) — genuine depth the fake drop-sprite can't give, esp. on the focused hero board. Tight shadow camera (near 0.4/far 3.6) + 1024 map + wide PCF radius keeps cost low. MEASURED: 2-min soak min 59 / avg 68 FPS (holds the >=55 real-shadow gate, with margin), walkthrough 72 FPS, errorCount 0, specs intact (27x27, China Seas). 2nd shadow-casting light, lights still 6. -
ce3b7f32026-06-27 BOARD WALL DROP-SHADOW: each board casts a faint soft shadow onto the back wall behind it (shared soft-box sprite, dropped down+left to match the upper-right key light, opacity 0.34, just in front of the wall surface) so boards have real depth OFF the wall — not flush decals. Cheap: pure sprite, no shadow-map/light cost. Auto-hides on focus/isolate (board swings forward off the wall) and restores on close. FPS 72, errorCount 0, specs intact (27x27, China Seas) -
433800b2026-06-27 PER-BOARD LIGHT GRADIENT: each 6-ft board face gets a baked top-to-bottom luminance falloff + faint warm specular sheen band (shared RGBA gradient overlay parented per-leaf, NormalBlending, low alpha) so boards read as physical objects in a lit room, not evenly-lit decals. Plus modest board-material specular (roughness 0.85->0.6, envMap up) so the picture-light grazes the face. Swatch colour stays TRUE + legible (neutral mid-band, never crushed). Works for pool AND focused loadWingBook materials. FPS 72, errorCount 0, specs intact (27x27, China Seas) -
b44c0aa2026-06-27 auto-save: 2026-06-27T12:39:11 (1 files) — public/js/showroom.js -
d2c6df42026-06-27 PHOTOGRAPHIC DEPTH: subtle CSS vignette + soft top-down directional gradient over the canvas (multiply blend, z-index 5 under HUD, pointer-events none) — adds photographic corner falloff + depth with ZERO GL/render cost (does not touch the WebGL pipeline). Light touch per ART-DIRECTION, not a heavy post stack. FPS 72, errorCount 0 -
c49c3db2026-06-27 CONTACT GROUNDING: soft radial-gradient contact shadows on the floor under each wingboard + the planter + the console — a shared warm-charcoal alpha sprite (no light/shadow-map cost, depthWrite off, polygonOffset). Boards now sit IN the room instead of floating ON it — the #1 'is it real' tell after the shell. FPS 72, errorCount 0, specs intact (27x27, China Seas) -
7dcf8462026-06-27 CEILING: replace crude 64px procedural grid (read as a wireframe) with a clean, bright, EVEN soft warm off-white gallery ceiling + two slim emissive recessed warm-light strips (no light cost, no harsh lines). Reads like a real gallery ceiling. FPS 72, errorCount 0 -
bb93cda2026-06-27 WALL realism: derive subtle normal+roughness maps from wall-limewash.png (scripts/derive-wall-maps.py, $0 local PIL+numpy) — apply to MAT.wall + MAT.brick at normalScale 0.2 so limewash plaster has faint trowel relief catching grazing light, no longer a flat tiled photo. FPS 72, errorCount 0, specs intact -
a38c66c2026-06-27 NOW VIEWING navigator HUD: museum media-player strip (swatch thumb + serif name + tracked colorway + 27x27 spec + Back/Peruse-play-pause/Next + 'N of N' brass progress). Vanilla CSS/HTML, brass-hairline museum glass per ART-DIRECTION; reuses gotoBoardOffset+togglePeruse, syncs play glyph to tour state. FPS 72/min51, errorCount 0. Figma/Magic MCP design phase tool-gated this session (noted) -
1e557352026-06-27 PJ hero framing: narrow FOV (55->30) on focus + back off proportionally so the 6ft board fills the frame flat/dead-on with no perspective flare; restore FOV on unfocus. Distance solved from fillH=2*d*tan(fov/2). FPS 72, errorCount 0 -
df964122026-06-27 Floor normal+roughness maps derived locally from floor-oak.png (scripts/derive-floor-maps.py): plank grain now catches grazing light, satin sheen breaks across boards. $0 local. FPS 72, errorCount 0 -
b1e3c752026-06-27 PJ hero framing: focused board presents FLAT/dead-on (near-flat default) not a 65° V; add user-adjustable Wing° angle slider (0-90°, persisted, live); keep splay as walk-up browse gesture -
a08b36a2026-06-27 PJ polish: true hi-res (4096px) engraved-brass wall wordmark, fix stale book-match comments -
e7268c62026-06-27 Photoreal room (SDXL warm-oak floor + limewash plaster walls), brighter white-box light, CONTINUOUS open-board design (L=U0-0.5 / R=U0.5-1, no mirror), HUD copy -
17933842026-06-27 Add 2-min soak-test recorder (walk/open/Back-Next/Peruse; logs console errors + FPS) -
6e2efdd2026-06-27 Usable view: 6ft back + dead-centre + 65° open + ISOLATE (hide other boards); replace Fan with Back/Next board nav; remove 'fanning' wording -
80afbd82026-06-27 Add 30s captioned how-to-use demo recorder -
15f8c332026-06-27 Clean+clear pass: bright even gallery lighting, true-colour crisp swatches (low env wash), hi-res brass CHINA SEAS plaque + hi-res placards -
575ee372026-06-27 Scene luxury pass 1: limewash plaster left wall (was brick), warm wide-plank oak floor, removed TV/medallion rug/sphere plants/framed art, single olive in stone planter, brass frame + gallery placard per board, picture-light graze on board wall, cognac-leather chairs -
59219512026-06-27 Boards 30"×6ft (real sample wings, 8/wall + paging); fan-out opens the board's L/R panels to present 1 design; Peruse 4ft-centered, 5s dwell -
a76a8f62026-06-27 Add automated Playwright walkthrough recorder (move-around screen-record + scene stats + spec-card proof) -
72bec592026-06-27 China Seas specs (27"×27" / Grasscloth 36") + spec-sheet detail card + graphics pass (soft 2048 shadows, rim light, richer env, exposure 1.06) -
8a478972026-06-26 Realism pass + proximity book-match wings -
c208bf22026-06-26 auto-save: 2026-06-26T12:33:24 (1 files) — server.js -
98df95d2026-06-26 Wall-cladding: focused/perused wing renders its pattern onto all room walls at architectural scale (toggle in HUD) -
b98ec592026-06-26 Record DTD hosting verdict (C: keep local, defer deploy; Option A when remote need is concrete) -
6ae51b82026-06-26 Image-model pipeline: $0 local seamless tiles + Gemini room backdrops (gated, cost-shown); window-handle refresh; README -
592fa6a2026-06-26 Quadrille House Endless Wings showroom — fused engine + 883 wallcoverings, peruse loop, FullDesign tiling, windowed paging
Authors
- Steve173
- steve2
Agents used
Skills used
- /showroom19
- /thumb-cache12
- /shots8
- /proto7
- /contrarian6
- /chrome6
- /thumb4
- /rack3
- /dock3
- /proxy3
- /viewmodes3
- /right3
- /v7-moodboard3
- /image2
- /sample-requests2
- /pending2
- /verify-sort-density-persist2
- /density2
- /room2
- /established2
- /sliders2
- /near-black2
- /white2
- /legs2
- /feet2
- /walls2
- /render2
- /versions2
- /v10-concierge2
- /light2
Creative ideas + design notes
02b4e0a · 2026-07-02 · furniture FIX 2: Transitional now unmistakably distinct from Contemporary
Chair upholstery moved OFF cream/greige to a deep sage-olive (mattMat env-0 so the ~1.6x showroom light-lift can't wash it back to cream) so the CHAIR — the dominant visual mass — reads clearly green vs Contemporary's white seat. Table wood darkened to a matte mid-oak (env-0) so it reads as solid wood, not pale blonde. Also gates the resizeRoom re-dress: a resize only re-dresses if the user had actively chosen a room type, preserving the FIX-1 clean-empty-room boot invariant. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6bdf2b5 · 2026-07-02 · furniture FIX 1: onload = clean empty room + table+chair only (no room-type dressing on boot)
Boot no longer builds a fully-dressed 'living' room type (sofa/lamps/wingchair/ rug/sculpture/plant). Room-type dressing now appears ONLY when the user clicks a room-type chip; a returning user also boots to the clean empty room. Verified via probe-boot-scene: currentRoomType null, no roomType group, 1 furnitureRoot (table+chair). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
0a7d7ab · 2026-07-02 · furniture: art-direction fixes — concrete-grey Brutalist, warm-wood Transitional, visible walnut Traditional
- Brutalist recolored to raw béton-brut concrete grey (dark bases that read ~#8a8a86 on camera under the bright showroom light) + board-form groove lines; no longer white foam - Contemporary table now crisp white lacquer + steel blade legs (was warm oak) - Transitional table warm honey-oak + soft rounded barrel-back upholstered chair, so it reads clearly distinct from Contemporary (material + silhouette) - Traditional chair reworked: matte no-env walnut frame + tall curved upholstered back + crown rail so the walnut tone and curved back read from the default camera - Added mattMat() + buildBoardFormLines() helpers Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
20c04ec · 2026-07-02 · chore: v1.3.1 (session close — thumb/proxy upstream hardening + ContrarianGo)
server.js hardening (retry + concurrency cap + placeholder fail-safe + shared fetchUpstreamBuffered for both /api/thumb and /api/proxy/image) already passed /5x (5 sweeps, clean twice cold) + /contrarian (cleared the bar) this session. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
97b809a · 2026-07-02 · ContrarianGo iter1: shared fetchUpstreamBuffered for BOTH thumb + proxy; split transient/permanent; warn-log
Closes the 3 contrarian holes in the 5x sliver-thumb fix: - /api/proxy/image (open hero) now shares the SAME cap+retry hardening as /api/thumb via one fetchUpstreamBuffered() helper — no more fixing only the tested endpoint. - fallback distinguishes transient (blip) from PERMANENT (dead 4xx) and console.warns every fallback so a dead upstream leaves a trail a canary can grep — not a silent gray lie. - both routes de-duplicated onto the shared helper (the twin functions collapsed). Verified: healthy hero serves real 124KB image (no fallback header); permanent 404 → placeholder 200 + logged PERMANENT; clickthrough CLEAN twice cold; verify-all 0 failures. Adds /ContrarianGo skill (this loop). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
b6f8daf · 2026-07-02 · 5x sweeps 2-5: upstream concurrency cap + placeholder fail-safe for sliver thumbs
Cold-cache concurrent sliver-thumb bursts tripped transient cdn.shopify.com 502s surfacing as browser console errors. Fix in /api/thumb url= path: - upstream-concurrency cap (6) so a ~24-thumb cold burst doesn't hammer the CDN - retries 1->3 w/ exponential backoff (transient only, never a real 4xx) - neutral-placeholder fail-safe: serve quiet 200 (X-Thumb-Fallback) on exhaustion instead of a console-erroring 502 — decorative slivers must fail-safe. Verified: 0 dead URLs across all 883 catalog images; healthy images still serve the real thumb; clickthrough CLEAN twice on cold cache; verify-all all green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3ac09a0 · 2026-07-02 · chore: lint, refactor, v1.3.0 (session close)
- hoist crypto require to module top (drop 2 inline requires) - age handler == null -> === null (strict-equality consistency) - version 1.2.2 -> 1.3.0 (sample-request submit feature landed this session) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
fb869a9 · 2026-07-02 · Wire the George email picker for sample requests (sending gated)
- scripts/send-sample-request-emails.js: reads data/sample-request-emails.jsonl, sends each pending row via George (POST /api/send, Basic auth from GEORGE_BASIC_AUTH or dw-agents Keychain, optional X-Send-Approval), from steve-office. Marks rows sent/sent_at/message_id; idempotent. --dry-run previews; --health probes George. - npm run send-sample-emails. - Safe by default: refuses to send unless SAMPLE_REQUEST_EMAIL_TO is set; NOT scheduled. Verified: George reachable from Mac2 (status ready), health + dry-run + gated-refusal all pass without sending; queued row stays sent:false. Still gated: recipient inbox (SAMPLE_REQUEST_EMAIL_TO) + SAMPLE_REQUEST_EMAIL=on + consent copy. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
38c4172 · 2026-07-02 · Build sample-request submit: endpoint + tray form + admin cards (steps 1-3)
- POST /api/sample-request: validated (samples 1..50, age 0..120, email, 32kb cap), server-stamped created_at, append-only data/sample-requests.jsonl persist. - Email via George gated behind SAMPLE_REQUEST_EMAIL env (default off) -> queue file only. - Sample Tray: name/email/phone/notes fields + Request Samples button (disabled when empty) + consent line + confirmation UX that keeps input on failure. Age rides along. - Admin /admin/sample-requests: card list with created date+time chip (standing rule). Verified: curl (ok+400s+GET), Playwright load (7 elements, button gated, 0 console errors). Gated/pending: consent wording + email recipient (spec steps 4-5). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
d6a840c · 2026-07-01 · chore: refactor + v1.2.2 (session close)
javascript-pro refactor pass on the session's age-field code found + fixed a real
edge case in initHUD(): restoring a stored age of 0 from localStorage coerced to null
(parseInt('0')||null → null) while the input still showed '0'. Now uses
parseInt(saved,10) + Number.isFinite guard, mirroring the live input handler. Re-verified
(Playwright): 67 persists across reload, and the 0-case now restores as 0, 0 console errors.
No linter configured in repo — lint gate had no toolchain to run.
59eede3 · 2026-07-01 · Capture visitor age as a plain data point on the Sample Tray (replaces Age View)
Per Steve's call: age is no longer an in-showroom control — it's a plain field on the
sample-request surface. Added an optional 'Your age' number input to the Sample Tray
(#tray-age), persisted to localStorage('qh_visitor_age'), clamped 0–120, exposed via
window._qh.visitorAge so a future request submit can include it. Styled to match the tray.
Also fixed a PRE-EXISTING bug this surfaced: the dock stows #sample-tray on boot with
.qh-stowed (display:none!important), which the tray's own .visible (display:block) could
never override — so the Sample Tray never actually appeared even when samples were added.
updateSampleTray() now clears qh-stowed when populated (re-adds it when empty).
Verified (Playwright): field renders + is visible when the tray populates; value persists
across reload; _qh.visitorAge reflects it; clamps 999→120; blank clears the key to null;
0 console errors.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
e4d7eca · 2026-07-01 · Remove Age View / age-adaptive theming entirely (per Steve's call)
Age becomes a plain signup data point (signup flow to be scoped separately) — not an in-showroom control. Ripped out the whole apparatus: • deleted public/js/ageview.js + its <script> tag • deleted all 6 scripts/verify-ageview-*.mjs + AGE-VIEWS-SPEC.md • removed the _qh Age View control surface (setAvatarAge/coalesceAvatarAge/avatarAge/ ageRigParams export/upperRigState/setEnvForAge/resetEnv) from showroom.js • dropped the '#btn-ageview' dock entry + clickthrough selector; removed the Age-View-ON pass from verify-walls-on-next; dropped the two ageview npm scripts KEPT byte-for-byte: the baseline age-28 avatar. buildAvatar()/ageRigParams() are the normal showroom body's own material/dimension helpers (isBaseline fast-paths) and predate Age View — nothing can now drive a non-28 age or age-tint the env. Verified: fresh Playwright smoke — _ageview undefined, no levers, no #btn-ageview, avatar present (6 children), 50 wings, 0 console errors; verify-walls-on-next still PASS. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
e0bed2f · 2026-07-01 · verify: At-the-Table behavioral test (nook hide/restore + seated set + sample-add) + verify-all runner
scripts/verify-table-view.mjs (npm run verify-table-view) drives window._viewmode.set('table'),
asserts the consultation nook hides (only centre table shows), the table+chair set and seated avatar
appear, addSample() grows the basket, then exits and asserts the nook is restored — 9/9 pass, 0 console
errors. Covers the newest committed feature (842a1dc). Added npm run verify-all to chain the 4 headless verifiers.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
4840661 · 2026-07-01 · 5x follow-up: WebGL scene-correctness + FPS verifier (closes the biggest coverage gap)
scripts/verify-scene-render.mjs (npm run verify-scene-render) asserts the Three.js scene actually renders the wallcoverings — not just 'canvas drew something': 50 wing boards in the arc, 639 meshes /227 textured (maps loaded), centre book present + book-matched (L mirrored/R normal), renderer draw calls>0, frame loop alive. FPS measured avg 72 headless Chrome (>=55 spec target; real hw higher), 0 console errors. Closes the contrarian's #3 (24KB screenshot proves nothing) + the Age View Phase-5.1 FPS gate. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
504a0ed · 2026-07-01 · 5x sweep 3 (contrarian-driven): persist sort+density to localStorage (standing rule) + repeatable reload test
/contrarian gate caught a real bug the six-way suite can't: sort (currentSort) and density (windowSize) never persisted to localStorage though the standing sort+density rule requires it — every other slider did. Fixed: init from qh_sort/qh_density, write on change, reflect into the select/slider on boot. Proven with scripts/verify-sort-density-persist.mjs (npm run verify-sort-density-persist) — sets sort=newest+density=30, RELOADS, asserts both localStorage + restored control values survive. ✅ passes. Report updated with an honest coverage boundary (WebGL scene correctness / FPS / mobile NOT covered here). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
604475e · 2026-07-01 · 5x sweep 1: fix duplicate id=density-wrap (7x → class); document sort/density-in-dock false-positives
Six-way verify: 5/6 + 0 console errors. The 2 clickthrough/E2E failures are false positives — #bottom-bar and #window-bar(sort/density) are intentionally stowed into the hamburger dock at boot (dock.js progressive-disclosure UX), verified reachable via ☰→Controls with zero console errors. Real defect fixed: 7 duplicate density-wrap ids → .density-wrap class + CSS selector update. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
bb091f8 · 2026-07-01 · Age View Phase-5.5 (contrarian pass): coalesce avatar rebuild, tighten in-page gate, capture screenshots
Contrarian final gate found three real holes; fixed the two code ones:
1. setAvatarAge() rebuilt the whole primitive avatar on EVERY slider input tick →
dozens of full teardown/rebuilds per second mid-drag (the real FPS-gate failure
mechanism). Now coalesced to ≤1 rebuild/animation-frame via coalesceAvatarAge();
buildAvatar() stays synchronous + byte-for-byte (boot + OFF-reset call it directly).
2. In-page seniorGate() used coarse type-size steps and never checked HEAD size — a
softer bar than the spec, so its 'all-pass' would've been green even before the
band type-size fix. Retightened to the interpolated 65→85 bar incl. heads, matching
verify-ageview-gate.mjs. Still all-pass (the bands genuinely meet the stricter bar).
3. Cross-engine harness now captures a screenshot per engine/age (was counters-only).
Re-ran both verifiers post-edit (validation-loop): static gate ALL 10 PASS; cross-engine
PASS on Chromium/Firefox/WebKit, 0 console errors, tightened seniorGate all-pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
d4295bd · 2026-07-01 · Age View Phase-5.3: cross-engine render gate (Chromium/Firefox/WebKit)
Playwright harness drives the live showroom, turns Age View on, sets the REAL #av-slider to ages 12/45/85, and asserts per engine: 0 console errors, in-page seniorGate() all-pass (APCA + type/target on 65/75/85 + slider85), and China Seas wing wall intact. RESULT: PASS on all 3 engines, 0 console errors anywhere, readouts correct (12→Tween, 45→Connoisseur, 85→Legacy). FPS is reported but advisory only — headless uses software GL (swiftshader/llvmpipe) so it under-represents real-hardware FPS; the 5.1 FPS gate still needs a real-browser run on-device. npm run verify-ageview-crossengine (exit 1 on hard fail). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1ea5d2b · 2026-07-01 · Age View Phase-5 gate: fix under-spec type sizes on Senior/Elder bands + add re-runnable verifier
Ran the spec's HARD senior-usability gate (APCA + target-size + type-size) measured against the real BANDS tokens. APCA contrast passed everywhere with wide margins, but the two mid-senior bands were short on type size once the 65→85 requirement is interpolated to the oldest age each band serves: • Senior (≤70): body 20→22, head 30→34 • Elder (≤80): body 22→26, head 32→42 Re-ran the gate post-edit (validation-loop): all 10 bands PASS. Added scripts/verify-ageview-gate.mjs (npm run verify-ageview-gate, exit 1 on fail). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
4bb3eba · 2026-06-30 · chore: lint, refactor, v1.2.0 (session close)
- refactor: reset _dragTurned in onCanvasPointerDown discard path (prevents a stale flag swallowing the next click after toggling explore off) - lint: log unfocusWing failures instead of silently swallowing - node --check clean; nav re-verified green in headed Chrome (wheel/C-key/Center button, 0 errors)
de7d9e4 · 2026-06-30 · Avatar nav: comfortable centred boot framing + grounded scroll/arrow walk, drag-turn, and always-available Return to Center
- Boot: pull eye back to z=0.7 + BOOT_PITCH -0.12 so the open book frames with headroom (was 'way too close') - Single-ownership nav: disable OrbitControls rotate/pan/zoom in both modes (killed the dolly-too-close / aerial-tilt / behind-furniture vectors) - Scroll wheel + arrows walk; drag or A/D turns (vertical drag ignored = always grounded); eye height never changes = never aerial - Grounded walkable box clamp excludes the closet/rack/nook/olive keep-outs (no walking behind the closet) - Add ⊕ Center button + C/Home key + recenterView() glide back to middle, facing forward - All-ages hint copy refreshed across HUD + guided instruction
e40c08a · 2026-06-29 · Feature: Next/Prev book-page renders the new design on all 4 walls
In BOOK_MODE (the default landing) gotoBoardOffset→pageCenterBook flipped the open book but never clad the room. Added cladWalls(imageUrl) in setCenterBook — the single funnel for book paging + load — so every Next/Prev renders the NEW design onto all 4 sides (back/left/right/front), gated on wallsAutoClad so 'Walls: neutral' still wins. Initial landing stays neutral (clean cream walls) by design; the design appears on first Next. Verified: scripts/verify-walls-on-next.mjs — next×3 + prev all clad all 4 sides (SKU advances 703346→703446→703546), 0 console errors, screenshot confirms. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
c378473 · 2026-06-29 · Age View band-differentiation: split young/adult/established into 3 hue families
Contrarian residual #4: adult(28)/established(40) were ~90% identical (both blue-grey, violet CTA, gap 12). Now three distinct identities on palette + CTA hue + density: - young(21) Emerging Adult: electric VIOLET #7c3aed, purple-dark, gap 10 (energetic) - adult(28) Young Pro: dashboard BLUE #1d4ed8 (Lc 87), cool blue-grey, gap 12 (modern) - established(40) Established: deep TEAL #155e75 (Lc 90), teal-slate, gap 9 (dense/assured) All CTAs white-text + contrast-verified. Also drop #guided-bar from clickthrough PANELS (Steve made it a permanent fixture, not a dock panel). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
b3ca21a · 2026-06-29 · /5x: showroom-aware clickthrough + fix 2 real dock.js bugs it caught
The generic /3x clickthrough can't open the dock hamburger, so it false-failed on
intentionally-stowed controls. Built scripts/clickthrough-showroom.mjs that drives the
app like a user (open hamburger → launch each panel → exercise sort/sliders/nav → proxy
every tool). It caught 2 GENUINE defects the blind clickthrough never could:
1. dock.js quote-in-selector: TOOLS entries '#top-bar [data-section="wings"]' / '...overview'
were interpolated raw into data-tool="..." (inner quotes close the attr) and into
reflectMenu's querySelector('[data-tool="..."]') (throws 'not a valid selector'). Wings +
Overview were unreachable from the menu and reflectMenu threw 14× PAGEERROR. Fix: key tools
by index (data-tool-idx), resolve TOOLS[idx].sel in JS.
2. dock.js launched panels showed EMPTY: launch() removed qh-stowed from the wrapper but not
from the panel element, so every launched panel's CONTENT stayed display:none!important —
only the header bar showed (sort select measured 0×0, which is why selectOption timed out).
Fix: el.classList.remove('qh-stowed') on launch. Panels now render their real content
(verified by screenshot: Versions list + Controls sort/sliders visible).
Sweep 4 clean: sort all 5 options, all ranges, all nav, all 10 tools, 0 console errors.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
f1439ea · 2026-06-29 · Fix center-book leaf orientation: leaves face the viewer (drop the PI group flip)
The PI group rotation pointed each leaf's textured +Z front AWAY from the spawn and put the right leaf on the -x side. Removed it -- the plane's +Z front already faces the +Z viewer -- and splayed each leaf's OUTER edge back so the book opens as a gentle V toward the avatar. Verified: both leaves normalZ ~+0.95, R worldX +0.36 / repeat.x +1, L worldX -0.36 / repeat.x -1 (true horizontal mirror).
fa8ee90 · 2026-06-29 · Default view = walk the avatar + single centered mirrored book + minimal caption bar
- Walking is now the default: exploreMode ON + persisted; arrows = up/down walk along facing dir, left/right turn the body. Avatar rig + camera move together, clamped to room. - Spawn dead-centre, stationary, facing the wing -- no boot auto-fly (enterFixedCentre / enterGuidedDefault are no-ops in book mode). - SKU display is now a quiet fixed #wing-caption strip (Pattern . Colorway . SKU . Vendor), never pops/animates; the old wing-detail popup card is suppressed in book mode. - The view is ONE open sample book centred on -Z with two leaves hinged at the spine; left leaf is a horizontal MIRROR of the right (repeat.x flipped). The 50-board arc is hidden. [ ] / N-P page the catalog. - Consultation table+chairs nudged so the furnished 20x20 room reads in the scene.
04948ab · 2026-06-29 · Phase 5.5 /contrarian final pass: prove the AVATAR half + fix 2 weak non-senior CTAs
Contrarian (correctly) flagged the Phase-5 gate verified only the HUD half and proved regression on a phantom hook. Closes both: - scripts/verify-ageview-avatar.mjs — proves the avatar morph on the REAL _qh hooks (avatarAge getter + upperRigState): eye-height arc 1.40→1.62→1.61→1.58→1.48m, stoop monotonic rotX 0@28 → -0.070@65 → -0.209@85, regression OFF==age28 rotX=0, + look-down body screenshots at 12/28/45/65/85 (setSpin to PITCH_MIN). 0 errors. - ageview.js BANDS: teen CTA #ff2fd6/near-black (APCA 47) -> #c01a9e/white (Lc 81); young CTA #a855f7/near-black (APCA 38, a real miss for the 21-yo band) -> #7c3aed/white (Lc 83). Same neon/violet identity, legible filled buttons. Validation-loop re-run after edits: FPS floor 67 all 11 bands, senior 65/75/85 PASS, regression PASS, cross-engine PASS, avatar PASS, 0 console errors. Residual (honest, non-blocking): env-morph per-band is implemented + FPS-safe but asserted by intensity values, not a measured rendered-luminance delta; adult(28)/ established(40) bands still ~90% identical (plan-gate fallback: merge or differentiate). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
71a067a · 2026-06-29 · Phase 5.3 cross-engine verifier: Age View slider PASS on WebKit + Firefox
scripts/verify-ageview-3x.mjs drives the 12/45/85 anchors in Safari(WebKit) and Gecko(Firefox): scene built (50 boards), bands snap (tween/connoisseur/legacy), postMessage bridge intact, 0 console errors in both. Chrome/Blink covered by the real-GPU phase5 verifier. All 3 engines green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
d84af5b · 2026-06-29 · Phase 5 senior-usability HARD gate: measured verifier + 3 cascade/wiring fixes
Add scripts/verify-ageview-phase5.mjs — measures RENDERED composited hex (not
declared tokens) over the live WebGL scene on real-GPU Chrome, the contrarian
fix #1 requirement. It caught 3 real gaps the in-code seniorGate() self-test
passes:
1. CTA dead: #g-tour is a .g-btn, so '#guided-bar .g-btn' (color:--av-fg)
out-specified the '#g-tour' cta rule -> CTA text rendered in --av-fg over
--av-cta (APCA 9/9/0). Fix: name both ids to win the cascade (Lc now 99/99/101).
2. Body type-size vars set but never applied to #guided-instruction (stayed 18px).
Fix: wire --av-body/--av-head onto the real text elements (now 20/22/28 + 30/32/44).
3. #btn-ageview (36px) + #av-slider track (18px) under the senior target floor.
Fix: grow to >=48px (65/75) / >=56px (85).
Measured verdict: FPS>=67 all 11 bands, senior 65/75/85 PASS, regression OFF==age28,
0 console errors.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
09cf8ad · 2026-06-28 · Chunk K (first-person Steve avatar, yaw-only rig) + Chunk A′ (20'×20' room)
K: first-person body built from THREE primitives (capsule limbs + boxes, $0, no GLTF) — torso/shoulders/two arms+hands/legs/feet, charcoal sweater + indigo jeans + dark shoes, NO head mesh (camera is the eyes). Parented to a YAW-ONLY rig (avatarRig.rotation.y = spinYaw, position pinned under lockedSpinEye) so the body turns with yaw but NEVER tilts with pitch — look down (PITCH_MIN deepened -0.62→-1.05, ~60°) and you see a stationary torso/lap/hands/legs/feet on the floor (BE Steve); straight-ahead the body sits below the sight line so the wing bank reads clean. updateAvatarRig() runs every frame after the spin pose; camera.position untouched. A′: CONFIG.room 4.27→6.10 (20'×20'); arc re-fit arcRadius 2.2→3.2, arcCenter.z 0.4→0.5 so the 50-board bank still fans with ~2" slivers at a comfortable ~8.9' distance; consultation nook relocated proportionally (1.25,-0.55)→(1.78,-0.78), same +66° yaw inside the ±72° clamp. buildRoom/walls/baseboards/crown scale off CONFIG. QH API: avatarPresent / avatarState() / setSpin() verification surface. Proof bar (real-GPU Chrome, scripts/shot-chunkK-avatar.mjs): posDelta yaw 0, rigPitch 0 across all poses, 50 boards, clad 4 walls on click, errorCount 0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
33391a6 · 2026-06-28 · Boot raycaster race fix: queue pre-ready canvas clicks + replay on ready (durable)
The canvas click listener is wired at init() but wingBoards stays empty until the async loadProducts()->buildWingWall() chain finishes (~2-3s). A click in that window used to silently no-op (empty raycaster targets) — to a 65-year-old that reads as 'it's broken.' Now: - wingWallReady flips true the instant the full 50-board bank is wired into the raycaster (end of buildWingWall). - onCanvasClick, when not ready, QUEUES the click coords (latest wins) and shows a gentle 'Loading the collection — your selection is queued…' cue via the existing loader status — never a dead click. - drainBootClick() replays the queued click as the FINAL boot action (+2600ms, after the version engine's boot-time V1 apply), through the exact onCanvasClick path, so the board the user pointed at is selected + conveyored-to-front + 4-wall clad + detail shown. Their click WINS, durably. - enterGuidedDefault / enterFixedCentre yield to a consumed/pending boot click during the boot window (_bootClickConsumed / _bootFixedCentreYield) so the resting-middle re-asserts and the versions.js V1 build cannot stomp the user's selection. No Slice-1/2/3 regression: slice1 PASS (resting-middle, posDelta 0, clamp ±72°, 50 boards, errorCount 0), slice2 PASS (boot no-clad, select allFourClad, posDelta 0). Proof: scripts/verify-bootrace.mjs — pre-ready click queued+cue shown, replay selects board durably (allFourClad, detail visible), normal click no-regression, errorCount 0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
0979b2b · 2026-06-28 · Slice-3 F: FPS.ms.draws HUD readout + off-thread wall-clad decode (kills the select-moment dip)
MEASURE: added window._perf {fps,ms,draws,pixelRatio} + 'N FPS . M ms . D draws'
readout to the bottom HUD (measurable on demand; read by the proof harness).
Real-GPU (Apple M2 Max ANGLE/Metal via system Chrome) nav sweep BEFORE fix held
72 FPS everywhere EXCEPT one 51-FPS select-moment dip (4-wall clad upload + hero
flip on the same frame). FIX (low-risk): cladWalls() now decodes the wall image
OFF-thread via createImageBitmap (was a main-thread new Image()), mirroring the
hero path; applyWallImage uses CanvasTexture for ImageBitmap sources (correct
flipY — walls verified right-side-up). AFTER: nav sweep pins at 72 FPS / 13.9ms
on EVERY sample incl. the select frame — gate >=55 met, errorCount 0.
Headless SwiftShader can't measure real FPS so the gate is verified on real GPU;
the headless harness gates the structural H + Slice 1/2 invariants.
1b5eb93 · 2026-06-28 · Slice-3 H: globally-unique element build codes (1000QH<version>)
assignElementCodes() runs once at registry load — iterates VERSION_ORDER, each version's elements by ascending n, handing out base-1000 global seq across all 11 builds; stamps elt.code (e.g. seq 0 + QH + V2 -> 1000QHV2). Deterministic + stable. BUILD_CODE='QH' isolated to one swappable constant. Pin identity, Chosen tray, and Copy-as-text now key on the durable global code, not the version-local 'V1.4' key (which collided across versions). Pins show the code chip + friendly badge n. qh_chosen localStorage migrates old key-only rows (backfills code, never crashes).
0e9e564 · 2026-06-28 · Open-face clean: hero board pushes forward + re-centres so the open 30x6 face reads full-bleed edge-to-edge with NO neighbour slat-bars/frames crossing the pattern
Root cause: an open hero stayed in the rail plane at the same depth as its raked neighbours, so their tilted sliver faces + dark frame bars projected IN FRONT of the open face (the gray/colored vertical bars crossing the pattern). The left-hinge face-offset also pushed the open face halfWidth to the right of dead-front. Fix (rack.js flipUpdate): the opening hero now (1) slides forward along the inward normal toward the room centre (OPEN_FORWARD_M=0.42m, flip-scaled) so it sits clearly in front of every raked neighbour — normal depth-testing then occludes them, nothing crosses the pattern; (2) shifts left by faceHalf*flip so the 30in face is centred dead-front (same pattern left & right of the open middle). placeBoard records the rail base pos + inward normal + faceHalf; relayout re-reads the clean base each carousel frame. Proof (verify-openface.mjs occlusion raycast): 25/25 grid points over the open face hit the hero FIRST, 0 offenders, real texture full-bleed, face-centre world-X ~0, errorCount 0. Carousel/clad/fixed-centre invariants intact (verify-carousel green, now measuring the face centre not the left-hinge pivot). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2c946ef · 2026-06-28 · Slice1 fix-it: 72° yaw clamp (non-empty), 50 boards, ~36° resting-open middle
FIX-1 YAW_CLAMP 105°→72° + nook pulled forward (yaw +66°, within clamp) so boards + side wall stay in frame at both clamps; never an empty void. FIX-2 wing.totalCount 20→50 so the real data path fans all 50 slivers. FIX-3 OPEN_ANGLE_DEG 45→37 → resting-open middle sits ~36° off dead-on (restFlip 0.51), foreshortened ~24" — unmistakably angled, not flat, no detail panel/selection. verify-slice1 tightened to gate non-empty clamp. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
597fb5b · 2026-06-28 · proto: COLOR RIVER — shop China Seas by hue as a flowing Three.js color current
- v6-colorriver.html: client-side hue extraction (sat-weighted, ground-aware), swatches laid out along a continuous spectrum riverbed with undulating flow, hue-rail navigation, click-to-focus big swatch + 27x27 spec card - headless playwright verifiers: 120/120 swatches, sorted-by-hue, 0 console errors, click-to-focus surfaces real pattern name + spec - proto/ only; touches nothing in public/ or shared app files Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
72bd476 · 2026-06-28 · proto v7: mood-board table — drag swatches, build palette, pairs-well-with
Standalone proto/v7-moodboard.html: designer's felt table where swatch cards drag from a tray onto the board (free-position + rotation + overlap), emit an aggregated color palette, and surface PAIRS WELL WITH (same pattern-family colorways + same color bucket) that are themselves draggable onto the table. Pulls from /api/showroom/products?limit=120. Verified headless: 120 swatches, 2-card pointer-drag, pairs render, palette aggregates, 0 console errors. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
e6c14ec · 2026-06-28 · Add V1-vs-reference comparison + 10-version contact sheet; document build status + flag contrarian V6-V10 fork
- recordings/shots/ver-V1-vs-reference.png: side-by-side of pj-dallas-showroom.png vs V1 build - recordings/shots/ver-contact-sheet.png: all 10 versions in one grid (distinct looks) - VERSIONS.md: BUILT note + OPEN FORK flag — built original V1-V10; contrarian-pass V6-V10 mechanic upgrade is a per-preset swap when Steve wants it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5954106 · 2026-06-28 · V1 establishing arc (matches pj-dallas-showroom.png) + V2 step-driven conveyor + rail layout
- V1: wide establishing shot (high front-right, FOV 64) showing the sliver-packed corner arc + consultation nook + warm oak floor like the reference photo, instead of isolating one board. restoreBoards()+revertWalls()+open middle; boot defers to 1800ms so it wins the race vs the guided auto-focus (which was re-isolating to 1 board). - V2 conveyor: real step controller (NOT auto-spin) — user dead-centre+stationary, the RACK yaws so each product rotates INTO centre; ArrowRight/Left + guided Next/Prev step one board at a time (capture-phase intercept while V2 active only), eased anim, idle = zero shadow rebakes. Verified: ArrowRight steps fwd, ArrowLeft steps back. - setVersion now calls the prior version's exit() (conveyor key/click/frame cleanup). - Rail layout: anchored top-right + max-height capped so it never collides with the bottom-right Chosen tray (was overlapping at 1600x900); collapse transform fixed. - test-versions samples steady-state FPS (after settle) — all 10 versions hold 72fps; earlier sub-50 reads were camera-fly/texture-upload settling frames. 0 errors. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1a31ad6 · 2026-06-28 · 10 VERSIONS system: V1-V10 picker rail + numbered-element overlay + Chosen Elements tray
- versions.js: bolt-on module (DTD verdict A) talking only through window._qh; each
version = preset {name, build(), elements:[{n,label,anchor}]}. V1 PJ arc rack, V2
dry-clean conveyor, V6 flat gallery (current) built for real; V3-V5/V7-V10 scaffolded
by composing existing view-modes/themes so all 10 appear in the picker.
- Persistent V1..V10 rail (right-centre), big tabular V-numbers + serif names, brass
active state; collapsible w/ pull-out tab. Remembers last version.
- Numbered-element overlay: circled-number pins projected onto each element via new
_qh.projectToScreen/boardWorldPos/namedAnchor hooks + overlayHook in animate loop;
click a pin -> Chosen Elements tray (chips like 'V1.4 Flip-to-open'), copy-as-text
export, remove/clear, chosen pins show check state, persists to localStorage.
- PERF fix: carousel/V2 was 31fps (full scene.traverse + per-frame shadow rebake each
frame); cached wall group + throttled shadow to ~6/s -> 56fps.
- Cormorant Garamond webfont for serif version names (ART-DIRECTION).
- LOCKED features verified intact: senior Next/Back/Auto-Tour, collapsed popup, 27x27
China Seas specs, photoreal surfaces, on-demand shadows. test-versions.js + test-senior.js
both pass: 0 errors, FPS 56-73, all 10 apply, overlay+tray work.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
8a47897 · 2026-06-26 · Realism pass + proximity book-match wings
Renderer/materials/lighting → PBR: - antialias on, adaptive pixelRatio (1.5→1.0 auto-ratchet guard), sRGB output, exposure 1.2→1.0, PCF shadow map (1024) — real key-light contact shadows - MeshLambert/Phong → MeshStandard across floor/walls/chrome/wood/furniture - PMREM studio-gradient environment for believable chrome/floor reflections - color maps tagged sRGB + max anisotropy (kills slat moiré) Wings rebuilt as two-leaf BOOK-MATCH boards (thin boxes, cast+receive shadow): - walk within 4 ft (1.22m) of the wall → nearest wing opens like a sample book, left leaf mirrored / right leaf normal across a center spine - updateBooks() proximity driver; focused/clicked wing also opens - B key + book HUD toggle to enable/disable; loadWingBook() applies the normal+mirrored texture pair (cached per URL) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
File tree
- .deploy.conf
- .gitignore
- 5x/REPORT.md
- 5x/loop-ledger.md
- 5x/sweep-1.md
- ART-DIRECTION.md
- HIGH-END-VERSIONS-SPEC.md
- LIQUID-UI-SPEC.md
- README.md
- RESEARCH.md
- REVIEW.md
- SAMPLE-REQUEST-SPEC.md
- SHOWROOM-REFERENCE-FROM-VIDEOS.md
- VERSIONS.md
- WINGBOARD-SPEC.md
- cta/CTA-REPORT.md
- cta/cta-harness.js
- cta/cta-v1-harness.js
- cta/rec/chrome.mp4
- cta/rec/chrome/page@005780cf82e25d7a610952578a1e8b01.webm
- cta/rec/chrome/page@0d47eaf4e739239db687c75f5ef86e35.webm
- cta/rec/chrome/page@1718402717c8f87f513a422a7bc4d375.webm
- cta/rec/chrome/page@276ba27d702558593b3f7df9491e1e7f.webm
- cta/rec/chrome/page@36c329fa87ea2500c594894cbece88d7.webm
- cta/rec/chrome/page@48cc178074f4c5578c38760ad8dbbac5.webm
- cta/rec/chrome/page@4c377b9c693b2dfac5d9b52071b53401.webm
- cta/rec/chrome/page@52919fd1750ab7668ebd008ad424761a.webm
- cta/rec/chrome/page@5ddd10790d765a4515a25b81cff0b8e1.webm
- cta/rec/chrome/page@606eb2d575ea0509a05fcbf0103af978.webm
- cta/rec/chrome/page@8d3b7b31973fa296d9c51ef2f8ae6b42.webm
- cta/rec/chrome/page@a0098a5e9493eedc18f8813fcf437f2e.webm
- cta/rec/chrome/page@a3dd034c2ed4f5b21c45f853d04f00f3.webm
- cta/rec/chrome/page@be45df8b3a4421746a5fa5a5ddecb27d.webm
- cta/rec/safari.mp4
- cta/rec/safari/page@288a40b0202f45eacaa58fa542e15641.webm
- cta/rec/safari/page@3daafb41dbfaabef535966f83222d564.webm
- cta/rec/safari/page@62a510a0306c05508fd46493a8880255.webm
- cta/rec/safari/page@71d0f8a938317854fd0c303382d4ac5c.webm
- cta/rec/safari/page@a96ad0bedb994412972a220218273ca6.webm
- cta/rec/safari/page@b14f70573e14220c20e09915ff054e06.webm
- cta/rec/safari/page@b60d9b1ed1b787681487db1c6e068fd1.webm
- cta/rec/safari/page@f78fde9d966c8d36e218e68c1624c20e.webm
- cta/shots/chrome/all-designs-after.png
- cta/shots/chrome/all-designs-before.png
- cta/shots/chrome/all-designs.png
- cta/shots/chrome/auto-tour-after.png
- cta/shots/chrome/auto-tour-before.png
- cta/shots/chrome/auto-tour.png
- cta/shots/chrome/final-state.png
- cta/shots/chrome/final.png
- cta/shots/chrome/guided-bar.png
- cta/shots/chrome/guided-next-after.png
- cta/shots/chrome/guided-next-before.png
- cta/shots/chrome/guided-next.png
- cta/shots/chrome/guided-prev-after.png
- cta/shots/chrome/initial-state.png
- cta/shots/chrome/numbers-before.png
- cta/shots/chrome/numbers-off.png
- cta/shots/chrome/numbers-on.png
- cta/shots/chrome/numbers-overlay-before.png
- cta/shots/chrome/numbers-overlay-off.png
- cta/shots/chrome/numbers-overlay-on.png
- cta/shots/chrome/page-loaded.png
- cta/shots/chrome/pin-clicked-tray.png
- cta/shots/chrome/pin-clicked.png
- cta/shots/chrome/sample-table-after.png
- cta/shots/chrome/sample-table-before.png
- cta/shots/chrome/slider-angle-after.png
- cta/shots/chrome/slider-angle-before.png
- cta/shots/chrome/slider-angle-range-after.png
- cta/shots/chrome/slider-angle-range-before.png
- cta/shots/chrome/slider-density-after.png
- cta/shots/chrome/slider-density-before.png
- cta/shots/chrome/slider-density-range-after.png
- cta/shots/chrome/slider-density-range-before.png
- cta/shots/chrome/slider-reveal-after.png
- cta/shots/chrome/slider-reveal-before.png
- cta/shots/chrome/slider-reveal-range-after.png
- cta/shots/chrome/slider-reveal-range-before.png
- cta/shots/chrome/sliders.png
- cta/shots/chrome/sort-after.png
- cta/shots/chrome/sort-before.png
- cta/shots/chrome/v10-concierge-after.png
- cta/shots/chrome/v10-concierge-before.png
- cta/shots/chrome/v6-colorriver-after.png
- cta/shots/chrome/v6-colorriver-before.png
- cta/shots/chrome/v7-moodboard-after.png
- cta/shots/chrome/v7-moodboard-before.png
- cta/shots/chrome/v8-swipe-after.png
- cta/shots/chrome/v8-swipe-before.png
- cta/shots/chrome/v9-walkin-after.png
- cta/shots/chrome/v9-walkin-before.png
- cta/shots/chrome/version-picker-before.png
- cta/shots/chrome/window-nav.png
- cta/shots/chrome/window-next-before.png
- cta/shots/chrome/wing-after.png
- cta/shots/chrome/wing-before.png
- cta/shots/chrome/wing-click-before.png
- cta/shots/chrome/wing-detail-after-click.png
- cta/shots/chrome/wing-detail-appears.png
- cta/shots/chrome/yaw-before.png
- cta/shots/chrome/yaw-left-after.png
- cta/shots/chrome/yaw-left.png
- cta/shots/safari/all-designs-after.png
- cta/shots/safari/all-designs-before.png
- cta/shots/safari/all-designs.png
- cta/shots/safari/auto-tour-after.png
- cta/shots/safari/auto-tour-before.png
- cta/shots/safari/auto-tour.png
- cta/shots/safari/final-state.png
- cta/shots/safari/final.png
- cta/shots/safari/guided-bar.png
- cta/shots/safari/guided-next-after.png
- cta/shots/safari/guided-next-before.png
- cta/shots/safari/guided-next.png
- cta/shots/safari/guided-prev-after.png
- cta/shots/safari/initial-state.png
- cta/shots/safari/numbers-before.png
- cta/shots/safari/numbers-off.png
- cta/shots/safari/numbers-on.png
- cta/shots/safari/numbers-overlay-before.png
- cta/shots/safari/numbers-overlay-off.png
- cta/shots/safari/numbers-overlay-on.png
- cta/shots/safari/page-loaded.png
- cta/shots/safari/pin-clicked-tray.png
- cta/shots/safari/pin-clicked.png
- cta/shots/safari/sample-table-after.png
- cta/shots/safari/sample-table-before.png
- cta/shots/safari/slider-angle-range-after.png
- cta/shots/safari/slider-angle-range-before.png
- cta/shots/safari/slider-density-range-after.png
- cta/shots/safari/slider-density-range-before.png
- cta/shots/safari/slider-reveal-range-after.png
- cta/shots/safari/slider-reveal-range-before.png
- cta/shots/safari/sliders.png
- cta/shots/safari/sort-after.png
- cta/shots/safari/sort-before.png
- cta/shots/safari/v10-concierge-after.png
- cta/shots/safari/v10-concierge-before.png
- cta/shots/safari/v6-colorriver-after.png
- cta/shots/safari/v6-colorriver-before.png
- cta/shots/safari/v7-moodboard-after.png
- cta/shots/safari/v7-moodboard-before.png
- cta/shots/safari/v8-swipe-after.png
- cta/shots/safari/v8-swipe-before.png
- cta/shots/safari/v9-walkin-after.png
- cta/shots/safari/v9-walkin-before.png
- cta/shots/safari/version-picker-before.png
- cta/shots/safari/window-nav.png
- cta/shots/safari/window-next-before.png
- cta/shots/safari/wing-after.png
- cta/shots/safari/wing-before.png
- cta/shots/safari/wing-click-before.png
- cta/shots/safari/wing-detail-appears.png
- cta/shots/safari/wing-detail-expanded.png
- cta/shots/safari/yaw-before.png
- cta/shots/safari/yaw-left-after.png
- cta/shots/safari/yaw-left.png
- cta/targeted-results.json
- cta/targeted-test.js
- data/enrichment.json
- data/showroom-products.json
- data/thumb-cache/143b196e361cfcabac432402.jpg
- data/thumb-cache/2592d7f617769f8a4a430efd.jpg
- data/thumb-cache/263e90a8e86b9099564d880f.jpg
- data/thumb-cache/2ae01b0b7d1fd04c00fdf66d.jpg
- data/thumb-cache/2fbfa15f2853f912623aed15.jpg
- data/thumb-cache/3cc44c54cb55798449090548.jpg
- data/thumb-cache/48d8be87436cc93bf2c43e97.jpg
- data/thumb-cache/5e1bde985d0a6b5cc21f78e8.jpg
- data/thumb-cache/607c51b820948e86e419768a.jpg
- data/thumb-cache/66509ef89fd93c999d240cba.jpg
- data/thumb-cache/7003563012c91195ea481f8f.jpg
- data/thumb-cache/7174d03da23235f90f17ff7b.jpg
- data/thumb-cache/9231e0fba1551d50554f2e92.jpg
- data/thumb-cache/aa0a9191f35c84434c33b570.jpg
- data/thumb-cache/ac0ed992279779cadf9c433c.jpg
- data/thumb-cache/ad86a76bc4444c833d22c5bc.jpg
- data/thumb-cache/b31fac5aa5f543e812424505.jpg
- data/thumb-cache/b692f428447edc40905a2004.jpg
- data/thumb-cache/bb60ef27cefed3b5da7c243e.jpg
- data/thumb-cache/c081b75ff0d0981452933ea8.jpg
- data/thumb-cache/c6c585cdffa240943d9ed183.jpg
- data/thumb-cache/cb421f06cd11e014ecb53cbd.jpg
- data/thumb-cache/d38d6ade32f93a27bf1e720c.jpg
- data/thumb-cache/d6b094caae0de0ba16eea5db.jpg
- data/thumb-cache/de14e7e731878c255eecddb4.jpg
- data/thumb-cache/e934fd973f3fbcc4acc0f809.jpg
- data/thumb-cache/ee078617ded1664759e51f12.jpg
- data/thumb-cache/f551b80de266aad6e43aead7.jpg
- docs/ROOM-TYPES-SPEC.md
- ecosystem.config.cjs
- package-lock.json
- package.json
- photos/Claude-Code-Assets/IMG_6244.heic
- photos/Claude-Code-Assets/IMG_6245.heic
- photos/Claude-Code-Assets/IMG_6246.heic
- photos/Claude-Code-Assets/IMG_6247.heic
- photos/Claude-Code-Assets/IMG_6248.heic
- photos/Claude-Code-Assets/IMG_6249.heic
- photos/Claude-Code-Assets/IMG_6250.heic
- photos/Claude-Code-Assets/IMG_6251.heic
- photos/Claude-Code-Assets/IMG_6252.heic
- photos/Claude-Code-Assets/IMG_6253.heic
- photos/Claude-Code-Assets/IMG_6254.heic
- photos/Claude-Code-Assets/IMG_6255.heic
- photos/Claude-Code-Assets/IMG_6256.heic
- photos/Claude-Code-Assets/IMG_6257.heic
- photos/Claude-Code-Assets/IMG_6258.heic
- photos/Claude-Code-Assets/IMG_6259.heic
- photos/Claude-Code-Assets/IMG_6260.heic
- photos/Claude-Code-Assets/IMG_6261.heic
- photos/Claude-Code-Assets/IMG_6262.heic
- photos/Claude-Code-Assets/IMG_6263.heic
- photos/Claude-Code-Assets/IMG_6264.heic
- photos/jpg/IMG_6244-urn:com:apple:photo:2020:aux:hdrgainmap.jpg
- photos/jpg/IMG_6244.jpg
- photos/jpg/IMG_6245-urn:com:apple:photo:2020:aux:hdrgainmap.jpg
- photos/jpg/IMG_6245.jpg
- photos/jpg/IMG_6246-urn:com:apple:photo:2020:aux:hdrgainmap.jpg
- photos/jpg/IMG_6246.jpg
- photos/jpg/IMG_6247-urn:com:apple:photo:2020:aux:hdrgainmap.jpg
- photos/jpg/IMG_6247.jpg
- photos/jpg/IMG_6248-urn:com:apple:photo:2020:aux:hdrgainmap.jpg
- photos/jpg/IMG_6248.jpg
- photos/jpg/IMG_6249-urn:com:apple:photo:2020:aux:hdrgainmap.jpg
- photos/jpg/IMG_6249.jpg
- photos/jpg/IMG_6250-urn:com:apple:photo:2020:aux:hdrgainmap.jpg
- photos/jpg/IMG_6250.jpg
- photos/jpg/IMG_6251-urn:com:apple:photo:2020:aux:hdrgainmap.jpg
- photos/jpg/IMG_6251.jpg
- photos/jpg/IMG_6252-urn:com:apple:photo:2020:aux:hdrgainmap.jpg
- photos/jpg/IMG_6252.jpg
- photos/jpg/IMG_6253-urn:com:apple:photo:2020:aux:hdrgainmap.jpg
- photos/jpg/IMG_6253.jpg
- photos/jpg/IMG_6254-urn:com:apple:photo:2020:aux:hdrgainmap.jpg
- photos/jpg/IMG_6254.jpg
- photos/jpg/IMG_6255-urn:com:apple:photo:2020:aux:hdrgainmap.jpg
- photos/jpg/IMG_6255.jpg
- photos/jpg/IMG_6256-urn:com:apple:photo:2020:aux:hdrgainmap.jpg
- photos/jpg/IMG_6256.jpg
- photos/jpg/IMG_6257-urn:com:apple:photo:2020:aux:hdrgainmap.jpg
- photos/jpg/IMG_6257.jpg
- photos/jpg/IMG_6258-urn:com:apple:photo:2020:aux:hdrgainmap.jpg
- photos/jpg/IMG_6258.jpg
- photos/jpg/IMG_6259-urn:com:apple:photo:2020:aux:hdrgainmap.jpg
- photos/jpg/IMG_6259.jpg
- photos/jpg/IMG_6260-urn:com:apple:photo:2020:aux:hdrgainmap.jpg
- photos/jpg/IMG_6260.jpg
- photos/jpg/IMG_6261-urn:com:apple:photo:2020:aux:hdrgainmap.jpg
- photos/jpg/IMG_6261.jpg
- photos/jpg/IMG_6262-urn:com:apple:photo:2020:aux:hdrgainmap.jpg
- photos/jpg/IMG_6262.jpg
- photos/jpg/IMG_6263-urn:com:apple:photo:2020:aux:hdrgainmap.jpg
- photos/jpg/IMG_6263.jpg
- photos/jpg/IMG_6264-urn:com:apple:photo:2020:aux:hdrgainmap.jpg
- photos/jpg/IMG_6264.jpg
- proto/OrbitControls.js
- proto/proxy-server.cjs
- proto/shot-colorriver.cjs
- proto/shot-focus.cjs
- proto/shots/new-mechanics-contact.png
- proto/shots/sample-table-filled.png
- proto/shots/sample-table-spread.png
- proto/shots/sample-table.png
- proto/shots/v10-concierge.png
- proto/shots/v6-colorriver-focus.png
- proto/shots/v6-colorriver.png
- proto/shots/v7-moodboard.png
- proto/shots/v8-swipe-filled.png
- proto/shots/v8-swipe.png
- proto/shots/v9-walkin-angle2.png
- proto/shots/v9-walkin.png
- proto/three.min.js
- proto/v10-concierge.html
- proto/v6-colorriver.html
- proto/v7-moodboard.html
- proto/v8-swipe.html
- proto/v9-walkin.html
- proto/verify-v10.cjs
- proto/verify-v7.cjs
- proto/verify-v8.cjs
- public/admin/sample-requests.html
- public/css/showroom.css
- public/favicon.svg
- public/js/GLTFLoader.js
- public/js/OrbitControls.js
- public/js/dock.js
- public/js/furniture-styles.js
- public/js/modal-rig.js
- public/js/rack.js
- public/js/showroom.js
- public/js/three.min.js
- public/js/versions.js
- public/js/viewmodes.js
- public/models/CREDITS.md
- public/models/office-chair.glb
- public/models/sofa.glb
- public/proto/OrbitControls.js
- public/proto/enrichment.json
- public/proto/proto-chrome.js
- public/proto/sample-table.html
- public/proto/shots/v10-concierge.png
- public/proto/shots/v6-colorriver.png
- public/proto/shots/v7-moodboard.png
- public/proto/shots/v8-swipe.png
- public/proto/shots/v9-walkin-floor.png
- public/proto/shots/v9-walkin-sofa.png
- public/proto/shots/v9-walkin.png
- public/proto/three.min.js
- public/proto/v10-concierge.html
- public/proto/v12-gallery-noir.html
- public/proto/v13-atrium-daylight.html
- public/proto/v14-velvet-lounge.html
- public/proto/v15-brutalist-concrete.html
- public/proto/v16-artdeco-brass.html
- public/proto/v17-tatami.html
- public/proto/v18-infinity-mirror.html
- public/proto/v19-conservatory.html
- public/proto/v20-penthouse-dusk.html
- public/proto/v21-garcia-room.html
- public/proto/v6-colorriver.html
- public/proto/v7-moodboard.html
- public/proto/v8-swipe.html
- public/proto/v9-walkin.html
- public/ref/pj-dallas-showroom.png
- public/showroom.html
- public/textures/floor-oak-normal.png
- public/textures/floor-oak-rough.png
- public/textures/floor-oak.png
- public/textures/floor-stone.png
- public/textures/wall-limewash-normal.png
- public/textures/wall-limewash-rough.png
- public/textures/wall-limewash.png
- scripts/build-showroom-data.js
- scripts/clickthrough-showroom.mjs
- scripts/demo-record.js
- scripts/derive-floor-maps.py
- scripts/derive-wall-maps.py
- scripts/diag-probe.mjs
- scripts/enrich.js
- scripts/gen-assets.js
- scripts/gen-room-textures.js
- scripts/gitify-phase2.sh
- scripts/glbcheck.cjs
- scripts/img_tools.py
- scripts/probe-boot-scene.mjs
- scripts/record-boot-walk.mjs
- scripts/record-carousel.mjs
- scripts/record-table.mjs
- scripts/send-sample-request-emails.js
- scripts/shot-chunkK-avatar.mjs
- scripts/shot-clad-realgpu.mjs
- scripts/shot-numbers-realgpu.mjs
- scripts/shot-pins-tight.mjs
- scripts/slice3-fps-realgpu-result.json
- scripts/syntax-check.cjs
- scripts/test-2min.js
- scripts/test-integration.js
- scripts/test-senior.js
- scripts/test-versions.js
- scripts/test-views.js
- scripts/verify-bootrace.mjs
- scripts/verify-carousel.mjs
- scripts/verify-openface.mjs
- scripts/verify-qh6.mjs
- scripts/verify-roomtypes.mjs
- scripts/verify-sample-table.js
- scripts/verify-scene-render.mjs
- scripts/verify-slice1.js
- scripts/verify-slice2-spec-legal.mjs
- scripts/verify-slice2.mjs
- scripts/verify-slice3-fps-realgpu.mjs
- scripts/verify-slice3.mjs
- scripts/verify-sort-density-persist.mjs
- scripts/verify-table-view.mjs
- scripts/verify-walls-on-next.mjs
- scripts/walkthrough-record.js
- server.js