# LANE C — INTERIORS (every door opens) > **Prompt for Opus 4.8.** You are working in `/Users/jing/Documents/PROCITY`. Read > `docs/CITY_SPEC.md` and `docs/RESEARCH.md` first, then the two sources you are porting: > `thriftgod/web/index.html` `buildShop()` (line ~1109+, archetypes `SHOP_SHAPES`, wall-slot > system, seeded decor) and `90sDJsim/web/world/fittings.js` (parametric fittings kit — read it > whole, it was written to be lifted). You own `web/js/interiors/*` and `web/interior_test.html`. > Do not touch other lanes' files. Plain ES modules, three.js from `web/vendor/` importmap, > randomness via `core/prng.js` only. Commit in small, described steps on `main`. ## Mission The Vuntra move: **every shop door opens into a unique, believable, seeded interior** — generated on demand in <50ms, byte-identical every revisit (`shop.seed`), themed by `shop.type`. This lane is a standalone library + test page; Lane B wires it to real doors later via the `procity:enterShop` / `procity:exitShop` events (contract in LANE_B). ## Architecture - `web/js/interiors/interiors.js` — public API: ```js buildInterior(shop, THREE) → { group, spawn:{x,z,ry}, exits:[{x,z,w, toStreet:true}], places:[…userData-tagged interactables], dispose() } ``` Pure function of `shop` (a CityPlan shop record + its lot dims). No global state. - `web/js/interiors/shell.js` — the room shell: floor/walls/ceiling sized from the lot (`lot.w × lot.d`, storeys → ceiling height 3.2–4.5m), seeded from the 5 thriftgod archetypes (**cosy / gallery / wide / hall / pokey**) adapted to lot proportions, plus door/shopfront wall with real glazing (you can see a hint of street), back room doorway (blocked v1). Materials: seeded pick of `wall-*.jpg` wallpapers, `tex-carpet-*`/`tex-lino-*` floors, `tex-*` counters — all already in `web/assets/gen/`, all with flat-colour fallbacks. - `web/js/interiors/fittings.js` — port 90sDJsim's kit and extend it. Needed set (see the registry's fittings mixes): record bins & crates, clothes racks, wall/cube/metal shelving, bookshelves, VHS aisle shelving, glass display case, counter + till, trestle tables, fridge, magazine rack, poster/art frames (`art-*` future), pegboard walls. Parametric primitives first; where a GLB upgrade exists use the manifest (see below) with primitive fallback. - `web/js/interiors/layout.js` — the placer: per-archetype floor zones (window display / aisles / walls / counter-corner), the thriftgod **shuffled wall-slot system** so nothing overlaps, density from shop seed (some shops crammed, some sparse), guaranteed walkable path from door to counter (grid-mark occupied cells; verify connectivity with a flood fill — assert it). - `web/js/interiors/stock.js` — v1 *visual* stock only: product boxes/sleeves/spines as canvas-texture blocks on shelves (steal the dig.js sleeve-canvas trick — coloured cardboard + price stickers). Real items are the content phase; leave a `stockAdapter` hook: `(shop, slotKind) => texture/mesh` so BaseGod data can plug in without touching layout code. - **GLB upgrades**: read `web/assets/manifest.json` if present (Lane E ships it) mapping fitting ids → 3GOD depot files; promise-cached loader, placeholder-persists pattern. The test page must be fully usable with no manifest and no network. - Windows-from-street problem (Lane B fakes it): you own the *inside-looking-out* — a simple backdrop plane beyond the glazing (street-ish gradient / `sky-*` slice) sells it in v1. ## Type theming (registry-driven) Import `SHOP_TYPES` from `core/registry.js`; every type in CITY_SPEC's table gets a distinct recipe (fittings mix, wallpaper bias, clutter level, counter position, signage-inside flavour). A `record` shop must *instantly* read different from a `toy` shop from the doorway. Milk bar counter faces the door; pawn shop is counter-forward with wall hooks; dept anchor is the "grand hall" archetype with mixed sections. ## Test page (`web/interior_test.html`) Standalone: seed input, type dropdown, archetype override dropdown, "re-roll", first-person walk inside (reuse PointerLock pattern), wireframe/occupancy-grid debug toggle, and a "50-room soak" button that builds+disposes 50 seeded interiors and reports ms/room + leaked geometries (`renderer.info.memory` before vs after — must return to baseline). ## Acceptance - Same seed twice → identical room (soak test asserts deep-equal on placement lists). - All 9 types × 5 archetypes render sensibly (screenshot grid into `docs/shots/laneC/`). - Build <50ms/room, dispose leak-free, flood-fill path door→counter always exists. - Runs with zero assets (fallback colours) and zero network.