{"version":3,"sources":["../src/scene.ts","../src/scene/manifest.ts","../src/core/random.ts","../src/core/palette.ts","../src/environment/terrain.ts","../src/environment/water.ts","../src/environment/sky.ts","../src/environment/lighting.ts","../src/environment/dayCycle.ts","../src/environment/wind.ts","../src/environment/path.ts","../src/generators/village.ts","../src/core/types.ts","../src/props/building.ts","../src/materials/surface.ts","../src/props/crate.ts","../src/props/lamp.ts","../src/scatter/scatter.ts","../src/props/tree.ts","../src/props/rock.ts","../src/props/fence.ts","../src/props/grass.ts","../src/scene/markers.ts","../src/kits/kit.ts","../src/kits/room.ts","../src/props/fire.ts","../src/kits/furnish.ts","../src/props/furniture.ts","../src/props/workshop.ts","../src/generators/bungalow.ts","../src/materials/glass.ts","../src/props/modern.ts","../src/generators/tower.ts"],"sourcesContent":["// SCENA — scene assembly: manifests, kits, scatter, generators\n//\n// A sub-path entry point. `import from 'scena3d'` still gives you everything;\n// this exists so a bundler can see module boundaries, and so an import says\n// what part of the library it depends on.\n//\n// GENERATED from src/index.ts by scripts/entries.mjs — every statement below\n// is the root barrel's own, partitioned by source directory. `npm run\n// entries:check` fails if this file and the barrel disagree.\n\n// ---- scene\nexport {\n  buildScene,\n  type SceneManifest,\n  type BuiltScene,\n  type ManifestScatter,\n  type ManifestScatterItem,\n  type ScatterPropType,\n} from './scene/manifest';\nexport { extractMarkers, type Markers } from './scene/markers';\n\n// ---- kits\nexport { KIT_UNIT, assembleKit, type Kit, type KitOptions } from './kits/kit';\nexport {\n  createRoom,\n  type Room,\n  type RoomOptions,\n  type RoomWindow,\n  type RoomHearth,\n  type RoomWall,\n} from './kits/room';\nexport {\n  furnishRoom,\n  type Furnished,\n  type FurnishOptions,\n  type RoomRole,\n  type RoomMarkers,\n} from './kits/furnish';\n\n// ---- scatter\nexport {\n  scatter,\n  type ScatterOptions,\n  type ScatterItem,\n  type ScatterResult,\n  type ScatterTile,\n  type Placement,\n} from './scatter/scatter';\n\n// ---- generators\nexport { createVillage, type Village, type VillageOptions } from './generators/village';\nexport { createBungalow, type Bungalow, type BungalowOptions } from './generators/bungalow';\nexport {\n  createHighrise,\n  type Highrise,\n  type HighriseOptions,\n} from './generators/tower';\n","import { CylinderGeometry, Group, Mesh, MeshStandardMaterial, type Scene } from 'three';\nimport { Rng } from '../core/random';\nimport { PALETTES, DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { Obstacle, Prop } from '../core/types';\nimport { createTerrain, type Terrain } from '../environment/terrain';\nimport { createWater, aboveWater, type Water } from '../environment/water';\nimport { createSky, type Sky } from '../environment/sky';\nimport {\n  createLightingRig,\n  applyFog,\n  type LightingRig,\n  type LightingPreset,\n  type FogPreset,\n} from '../environment/lighting';\nimport { createDayCycle, type DayCycle } from '../environment/dayCycle';\nimport { applyWind, type Wind } from '../environment/wind';\nimport { createPath, type WorldPath } from '../environment/path';\nimport { createVillage, type Village } from '../generators/village';\nimport { scatter, type ScatterResult, type ScatterItem } from '../scatter/scatter';\nimport { createTree } from '../props/tree';\nimport { createRock } from '../props/rock';\nimport { createCrate } from '../props/crate';\nimport { createFence } from '../props/fence';\nimport { createLamp } from '../props/lamp';\nimport { createGrassTuft, createBush } from '../props/grass';\n\n/** Prop vocabulary available to manifest scatters. */\nexport type ScatterPropType = 'tree' | 'rock' | 'bush' | 'grass' | 'crate' | 'fence' | 'lamp';\n\nexport interface ManifestScatterItem {\n  type: ScatterPropType;\n  weight?: number;\n  variants?: number;\n  scale?: [number, number];\n}\n\nexport interface ManifestScatter {\n  /** Defaults to the terrain footprint (slightly inset). */\n  area?: { min: { x: number; z: number }; max: { x: number; z: number } };\n  density?: number;\n  count?: number;\n  minSpacing?: number;\n  clumpScale?: number;\n  items: ManifestScatterItem[];\n  /** Reject spots above this ground height (keep peaks bare). */\n  maxHeight?: number;\n  /** Keep placements ashore. Default true when the scene has water. */\n  avoidWater?: boolean;\n  /** Keep placements off paths and out of the village. Default true. */\n  avoidPaths?: boolean;\n  /** Opt into tile-based LOD (see ScatterOptions.lod). */\n  lod?: { distance: number; tileSize?: number };\n}\n\n/**\n * A whole world as plain JSON — every field is data, so manifests can be\n * stored, diffed, sent over the network, or edited in a tool.\n */\nexport interface SceneManifest {\n  seed?: number;\n  palette?: keyof typeof PALETTES;\n  terrain?: {\n    size?: number;\n    resolution?: number;\n    amplitude?: number;\n    noiseScale?: number;\n    octaves?: number;\n    valleyFlatness?: number;\n  };\n  water?: { level: number; size?: number };\n  /** Sky dome. Default true. */\n  sky?: boolean;\n  lighting?: LightingPreset;\n  /** Fog preset, or false for none. Default 'haze'. */\n  fog?: FogPreset | false;\n  /** Animated day-night cycle. Off unless specified. */\n  dayCycle?: { dayLength?: number; timeOfDay?: number };\n  paths?: Array<{\n    points: Array<{ x: number; z: number }>;\n    width?: number;\n    loop?: boolean;\n  }>;\n  village?: {\n    center?: { x: number; z: number };\n    radius?: number;\n    houses?: number;\n    lampLights?: number;\n    tower?: boolean;\n    ruin?: boolean;\n  };\n  scatters?: ManifestScatter[];\n  /** Vegetation sway. Default on; false disables, or set the strength. */\n  wind?: boolean | { strength?: number };\n}\n\nexport interface BuiltScene {\n  /** Everything visual, ready to add to a scene (already added if one was passed). */\n  group: Group;\n  palette: Palette;\n  terrain?: Terrain;\n  water?: Water;\n  sky?: Sky;\n  rig: LightingRig;\n  cycle?: DayCycle;\n  paths: WorldPath[];\n  village?: Village;\n  scatters: ScatterResult[];\n  /** Combined steering obstacles from the village and every scatter. */\n  obstacles: Obstacle[];\n  /** Ground height (terrain's, or 0 for flat scenes). */\n  heightAt(x: number, z: number): number;\n  /** Advance water, wind and the day cycle. Call from your frame loop. */\n  update(dt: number): void;\n}\n\nconst PROP_FACTORIES: Record<ScatterPropType, (seed: number, palette: Palette) => Prop> = {\n  tree: (seed, palette) => createTree({ seed, palette }),\n  rock: (seed, palette) => createRock({ seed, palette }),\n  bush: (seed, palette) => createBush({ seed, palette }),\n  grass: (seed, palette) => createGrassTuft({ seed, palette }),\n  crate: (seed, palette) => createCrate({ seed, palette }),\n  fence: (seed, palette) => createFence({ seed, palette }),\n  lamp: (seed, palette) => createLamp({ seed, palette }),\n};\n\n// Far-distance stand-ins used when a manifest scatter opts into LOD:\n// trees collapse to a single cone, bushes to a squat cone, grass vanishes.\nconst FAR_FACTORIES: Partial<Record<ScatterPropType, (seed: number, palette: Palette) => Prop>> = {\n  tree: (seed, palette) => {\n    const rng = new Rng(seed);\n    const group = new Group();\n    const cone = new Mesh(\n      new CylinderGeometry(0, rng.range(1.0, 1.4), rng.range(2.6, 3.8), 5),\n      new MeshStandardMaterial({ color: rng.pick(palette.foliage), flatShading: true })\n    );\n    cone.position.y = cone.geometry.parameters.height / 2 + 0.3;\n    group.add(cone);\n    return { object: group, obstacleRadius: 0 };\n  },\n  bush: (seed, palette) => {\n    const rng = new Rng(seed);\n    const group = new Group();\n    const cone = new Mesh(\n      new CylinderGeometry(0.1, rng.range(0.5, 0.7), rng.range(0.5, 0.8), 5),\n      new MeshStandardMaterial({ color: rng.pick(palette.foliage), flatShading: true })\n    );\n    cone.position.y = 0.3;\n    group.add(cone);\n    return { object: group, obstacleRadius: 0 };\n  },\n  grass: () => ({ object: new Group(), obstacleRadius: 0 }),\n};\n\n/**\n * Compile a `SceneManifest` into a live world: terrain, water, sky,\n * lighting, fog, paths, a village, scatters and the day cycle — with all\n * the cross-feature wiring the forest demo does by hand applied\n * automatically (scatters stay ashore, off paths and out of the village;\n * the village avoids water and roads; village lamps and windows feed the\n * day cycle).\n *\n * ```ts\n * const world = buildScene(JSON.parse(manifestJson), scene);\n * game.onUpdate((t) => world.update(t.delta));\n * agent.addBehavior(new ObstacleAvoidance(() => world.obstacles));\n * ```\n */\nexport function buildScene(manifest: SceneManifest, scene?: Scene): BuiltScene {\n  const seed = manifest.seed ?? 1;\n  const palette = manifest.palette ? PALETTES[manifest.palette] : DEFAULT_PALETTE;\n  const group = new Group();\n  group.name = 'scena-scene';\n  const updates: Array<(dt: number) => void> = [];\n\n  // Ground and water.\n  let terrain: Terrain | undefined;\n  if (manifest.terrain) {\n    terrain = createTerrain({\n      ...manifest.terrain,\n      seed,\n      waterLevel: manifest.water?.level,\n      palette,\n    });\n    group.add(terrain.mesh);\n  }\n  const heightAt = terrain ? terrain.heightAt : () => 0;\n\n  let water: Water | undefined;\n  if (manifest.water) {\n    water = createWater({\n      level: manifest.water.level,\n      size: manifest.water.size ?? (terrain ? terrain.size * 1.4 : 200),\n      palette,\n    });\n    group.add(water.mesh);\n    updates.push((dt) => water!.update(dt));\n  }\n  const dryLand = terrain && water ? aboveWater(terrain, water, 0.3) : () => true;\n\n  // Sky, lights, fog.\n  let sky: Sky | undefined;\n  if (manifest.sky ?? true) {\n    sky = createSky({ palette });\n    group.add(sky.mesh);\n  }\n  const rig = createLightingRig(manifest.lighting ?? 'day');\n  group.add(rig.group);\n  if (scene && manifest.fog !== false) applyFog(scene, manifest.fog ?? 'haze', palette);\n\n  // Paths.\n  const paths: WorldPath[] = (manifest.paths ?? []).map((spec) => {\n    const path = createPath(spec.points, {\n      surface: heightAt,\n      width: spec.width,\n      loop: spec.loop,\n      palette,\n    });\n    group.add(path.mesh);\n    return path;\n  });\n  const onAnyPath = (x: number, z: number): boolean => paths.some((p) => p.contains(x, z));\n\n  // Village.\n  let village: Village | undefined;\n  if (manifest.village) {\n    village = createVillage({\n      ...manifest.village,\n      seed: seed + 1,\n      surface: heightAt,\n      mask: (x, z) => dryLand(x, z) && !onAnyPath(x, z),\n      palette,\n    });\n    group.add(village.group);\n  }\n\n  // Scatters, kept ashore / off roads / out of the village by default.\n  const wind = manifest.wind ?? true;\n  const scatters: ScatterResult[] = (manifest.scatters ?? []).map((spec, index) => {\n    const inset = terrain ? terrain.size * 0.45 : 40;\n    const avoidWater = spec.avoidWater ?? true;\n    const avoidPaths = spec.avoidPaths ?? true;\n    const result = scatter({\n      seed: seed + 10 + index,\n      area: spec.area ?? { min: { x: -inset, z: -inset }, max: { x: inset, z: inset } },\n      surface: heightAt,\n      density: spec.density,\n      count: spec.count,\n      minSpacing: spec.minSpacing,\n      clumpScale: spec.clumpScale,\n      lod: spec.lod,\n      items: spec.items.map((item): ScatterItem => {\n        const far = spec.lod ? FAR_FACTORIES[item.type] : undefined;\n        return {\n          create: (rng) => PROP_FACTORIES[item.type](rng.int(1, 1e9), palette),\n          createFar: far && ((rng) => far(rng.int(1, 1e9), palette)),\n          weight: item.weight,\n          variants: item.variants,\n          scale: item.scale,\n        };\n      }),\n      mask: (x, z, y) =>\n        (spec.maxHeight === undefined || y < spec.maxHeight) &&\n        (!avoidWater || dryLand(x, z)) &&\n        (!avoidPaths || !onAnyPath(x, z)),\n      keepOut: [\n        ...(avoidPaths ? paths.flatMap((p) => p.keepOut) : []),\n        ...(village ? village.keepOut : []),\n      ],\n    });\n    group.add(result.group);\n    if (wind !== false) {\n      const sway: Wind = applyWind(result.group, {\n        strength: typeof wind === 'object' ? wind.strength ?? 0.05 : 0.05,\n      });\n      updates.push((dt) => sway.update(dt));\n    }\n    return result;\n  });\n\n  // Day cycle last, so it can adopt the village's lamps and windows.\n  let cycle: DayCycle | undefined;\n  if (manifest.dayCycle) {\n    cycle = createDayCycle({\n      sky,\n      rig,\n      scene,\n      lamps: village?.lamps,\n      palette,\n      dayLength: manifest.dayCycle.dayLength,\n      timeOfDay: manifest.dayCycle.timeOfDay,\n    });\n    updates.push((dt) => cycle!.update(dt));\n  }\n\n  scene?.add(group);\n\n  return {\n    group,\n    palette,\n    terrain,\n    water,\n    sky,\n    rig,\n    cycle,\n    paths,\n    village,\n    scatters,\n    obstacles: [\n      ...(village ? village.obstacles : []),\n      ...scatters.flatMap((s) => s.obstacles),\n    ],\n    heightAt,\n    update(dt) {\n      for (const fn of updates) fn(dt);\n    },\n  };\n}\n","/**\n * Deterministic seeded randomness — the backbone of SCENA. Same seed,\n * same tree; forests are reproducible, diffable and network-syncable.\n */\nexport class Rng {\n  private state: number;\n\n  constructor(seed = 1) {\n    this.state = seed >>> 0 || 1;\n  }\n\n  /** Next float in [0, 1) (mulberry32). */\n  next(): number {\n    this.state = (this.state + 0x6d2b79f5) >>> 0;\n    let t = this.state;\n    t = Math.imul(t ^ (t >>> 15), t | 1);\n    t ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n    return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n  }\n\n  /** Float in [min, max). */\n  range(min: number, max: number): number {\n    return min + this.next() * (max - min);\n  }\n\n  /** Integer in [min, max] inclusive. */\n  int(min: number, max: number): number {\n    return min + Math.floor(this.next() * (max - min + 1));\n  }\n\n  /** Random element of a non-empty array. */\n  pick<T>(items: readonly T[]): T {\n    return items[Math.floor(this.next() * items.length)];\n  }\n\n  /** value ± spread (uniform). */\n  jitter(value: number, spread: number): number {\n    return value + (this.next() * 2 - 1) * spread;\n  }\n\n  /** A new independent Rng derived from this one. */\n  fork(): Rng {\n    return new Rng(Math.floor(this.next() * 0xffffffff) || 1);\n  }\n}\n\n/** Integer-lattice hash to [0, 1) — the base of the value noise. */\nexport function hash2(ix: number, iz: number, seed: number): number {\n  let h = (ix * 374761393 + iz * 668265263 + seed * 2246822519) >>> 0;\n  h = Math.imul(h ^ (h >>> 13), 1274126177) >>> 0;\n  return ((h ^ (h >>> 16)) >>> 0) / 4294967296;\n}\n\nconst smooth = (t: number): number => t * t * (3 - 2 * t);\n\n/** 2D value noise in [0, 1). Continuous; used by terrain and scatter density. */\nexport function valueNoise2(x: number, z: number, seed: number): number {\n  const ix = Math.floor(x);\n  const iz = Math.floor(z);\n  const fx = smooth(x - ix);\n  const fz = smooth(z - iz);\n  const a = hash2(ix, iz, seed);\n  const b = hash2(ix + 1, iz, seed);\n  const c = hash2(ix, iz + 1, seed);\n  const d = hash2(ix + 1, iz + 1, seed);\n  return a + (b - a) * fx + (c - a) * fz + (a - b - c + d) * fx * fz;\n}\n\n/** Fractal (octaved) value noise in [0, 1). */\nexport function fractalNoise2(\n  x: number,\n  z: number,\n  seed: number,\n  octaves = 4,\n  lacunarity = 2,\n  gain = 0.5\n): number {\n  let amplitude = 1;\n  let frequency = 1;\n  let sum = 0;\n  let total = 0;\n  for (let i = 0; i < octaves; i++) {\n    sum += valueNoise2(x * frequency, z * frequency, seed + i * 101) * amplitude;\n    total += amplitude;\n    amplitude *= gain;\n    frequency *= lacunarity;\n  }\n  return sum / total;\n}\n","/**\n * Theme palettes: one coherent set of colors shared by every generator,\n * so procedural props look like a matched set rather than a junk drawer.\n * Pass `palette` to any generator to restyle it; whole scenes retheme by\n * building with a different palette.\n */\nexport interface Palette {\n  foliage: number[];\n  trunk: number;\n  rock: number[];\n  wood: number;\n  woodDark: number;\n  metal: number;\n  lampGlow: number;\n  grassLow: number;\n  grassHigh: number;\n  cliff: number;\n  peak: number;\n  skyTop: number;\n  skyBottom: number;\n  fog: number;\n  water: number;\n  sand: number;\n  path: number;\n  /** Building plaster/wall color. */\n  wall: number;\n  /** Building roof color. */\n  roof: number;\n}\n\nexport const PALETTES: Record<'meadow' | 'autumn' | 'dusk' | 'winter' | 'urban', Palette> = {\n  meadow: {\n    foliage: [0x2f9e57, 0x37b26a, 0x2a8f4f, 0x45b878],\n    trunk: 0x6b4a33,\n    rock: [0x8a8f98, 0x767c86, 0x9aa0a8],\n    wood: 0x8a6642,\n    woodDark: 0x6b4a33,\n    metal: 0x3d4451,\n    lampGlow: 0xffd889,\n    grassLow: 0x3f9d5a,\n    grassHigh: 0x6fae66,\n    cliff: 0x7d7a72,\n    peak: 0xe8ecef,\n    skyTop: 0x3d70b8,\n    skyBottom: 0xbfd9e8,\n    fog: 0xb8cfdd,\n    water: 0x3f7fae,\n    sand: 0xc9b98a,\n    path: 0x9a815f,\n    wall: 0xd9ccb0,\n    roof: 0xa8563e,\n  },\n  autumn: {\n    foliage: [0xc9752f, 0xd98e3a, 0xb35c2a, 0xe0a545],\n    trunk: 0x5d4030,\n    rock: [0x8d8578, 0x776f63, 0x9c948a],\n    wood: 0x7d5a3a,\n    woodDark: 0x5d4030,\n    metal: 0x463f3a,\n    lampGlow: 0xffc571,\n    grassLow: 0x9d8a3f,\n    grassHigh: 0xb59b4a,\n    cliff: 0x82746a,\n    peak: 0xe3ded4,\n    skyTop: 0x8e6ca8,\n    skyBottom: 0xe8c9a8,\n    fog: 0xd9c1a8,\n    water: 0x4a7a92,\n    sand: 0xcbb083,\n    path: 0x8d7454,\n    wall: 0xccb894,\n    roof: 0x8a4a30,\n  },\n  dusk: {\n    foliage: [0x1f5e46, 0x24684f, 0x1a5240, 0x2d7458],\n    trunk: 0x413147,\n    rock: [0x565672, 0x484861, 0x646484],\n    wood: 0x5d4a63,\n    woodDark: 0x413147,\n    metal: 0x2b2b3d,\n    lampGlow: 0xffb35c,\n    grassLow: 0x2d6b52,\n    grassHigh: 0x3d7a5e,\n    cliff: 0x52516b,\n    peak: 0xb8b8d9,\n    skyTop: 0x1d2145,\n    skyBottom: 0xc96a4a,\n    fog: 0x6a5a7a,\n    water: 0x2d4a68,\n    sand: 0x8a7a6a,\n    path: 0x6a5a52,\n    wall: 0x8d8299,\n    roof: 0x453558,\n  },\n  winter: {\n    foliage: [0x2e5c48, 0x38695a, 0x527a68, 0x87a596],\n    trunk: 0x4a3a33,\n    rock: [0x9aa4ad, 0x848e98, 0xb0b8c0],\n    wood: 0x776049,\n    woodDark: 0x54453a,\n    metal: 0x39404d,\n    lampGlow: 0xffd889,\n    grassLow: 0xcfd9de,\n    grassHigh: 0xe4ebee,\n    cliff: 0x76797d,\n    peak: 0xf4f7fa,\n    skyTop: 0x5a7ba6,\n    skyBottom: 0xd8e4ec,\n    fog: 0xccd8e0,\n    water: 0x4a7086,\n    sand: 0xb8c2c6,\n    path: 0x8b8378,\n    wall: 0xd2c9bb,\n    roof: 0x6b4638,\n  },\n  // Modern district: warm-white render, charcoal trim, teak accents, clipped\n  // green — for bungalows, towers and the Tier-4 surfaces.\n  urban: {\n    foliage: [0x4a8f56, 0x5aa065, 0x3f7f4b, 0x6aae74],\n    trunk: 0x5d4a38,\n    rock: [0x9a9a96, 0x85857f, 0xaaaaa4],\n    wood: 0x8a5c36, // teak\n    woodDark: 0x54402c,\n    metal: 0x2f353c, // charcoal powder-coat\n    lampGlow: 0xffe0a8,\n    grassLow: 0x5a9a5e,\n    grassHigh: 0x7aae6e,\n    cliff: 0x8a8a84,\n    peak: 0xe8ecef,\n    skyTop: 0x4a7ec2,\n    skyBottom: 0xcfe0ec,\n    fog: 0xc8d4dd,\n    water: 0x3f7fae,\n    sand: 0xc9bfa8,\n    path: 0xb0aca2, // pale concrete\n    wall: 0xe8e2d6, // warm-white render\n    roof: 0x3a3d42, // charcoal fascia\n  },\n};\n\nexport const DEFAULT_PALETTE: Palette = PALETTES.meadow;\n","import {\n  BufferAttribute,\n  Color,\n  Mesh,\n  MeshStandardMaterial,\n  PlaneGeometry,\n} from 'three';\nimport { fractalNoise2 } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\n\nexport interface TerrainOptions {\n  seed?: number;\n  /** Square side length. Default 80. */\n  size?: number;\n  /** Vertices per side. Default 96. */\n  resolution?: number;\n  /** Peak height. Default 6. */\n  amplitude?: number;\n  /** Noise feature size in world units. Default 28. */\n  noiseScale?: number;\n  octaves?: number;\n  /** Flatten low areas into meadows (0–1, higher = flatter valleys). Default 0.55. */\n  valleyFlatness?: number;\n  /** Blend low bands toward sand below (waterLevel + shore margin). */\n  waterLevel?: number;\n  palette?: Palette;\n}\n\nexport interface Terrain {\n  mesh: Mesh;\n  /** Exact analytic height at any (x, z) — same function that built the\n   *  mesh, so agents/navmesh queries never disagree with the visuals. */\n  heightAt(x: number, z: number): number;\n  size: number;\n  seed: number;\n}\n\n/**\n * A seeded low-poly terrain: fractal value noise displacing a plane, with\n * height/slope-banded vertex colors (grass → high grass → cliff → peak).\n * The height function is exported, not just baked into vertices — that's\n * what lets gameplay (spawning, scattering, navmesh baking, agent ground\n * clamping) agree exactly with what's rendered.\n */\nexport function createTerrain(options: TerrainOptions = {}): Terrain {\n  const seed = options.seed ?? 1;\n  const size = options.size ?? 80;\n  const resolution = options.resolution ?? 96;\n  const amplitude = options.amplitude ?? 6;\n  const noiseScale = options.noiseScale ?? 28;\n  const octaves = options.octaves ?? 4;\n  const flatness = options.valleyFlatness ?? 0.55;\n  const palette = options.palette ?? DEFAULT_PALETTE;\n\n  const heightAt = (x: number, z: number): number => {\n    const n = fractalNoise2(x / noiseScale, z / noiseScale, seed, octaves);\n    // Push valleys down and flatten them; keep peaks.\n    const shaped = Math.pow(n, 1 + flatness * 2);\n    return shaped * amplitude;\n  };\n\n  const geometry = new PlaneGeometry(size, size, resolution - 1, resolution - 1);\n  geometry.rotateX(-Math.PI / 2);\n  const positions = geometry.getAttribute('position') as BufferAttribute;\n  for (let i = 0; i < positions.count; i++) {\n    positions.setY(i, heightAt(positions.getX(i), positions.getZ(i)));\n  }\n  geometry.computeVertexNormals();\n\n  // Vertex colors by height band + slope.\n  const normals = geometry.getAttribute('normal') as BufferAttribute;\n  const colors = new Float32Array(positions.count * 3);\n  const grassLow = new Color(palette.grassLow);\n  const grassHigh = new Color(palette.grassHigh);\n  const cliff = new Color(palette.cliff);\n  const peak = new Color(palette.peak);\n  const sand = new Color(palette.sand);\n  const waterLevel = options.waterLevel;\n  const scratch = new Color();\n  for (let i = 0; i < positions.count; i++) {\n    const y = positions.getY(i);\n    const h = y / amplitude;\n    const slope = 1 - normals.getY(i); // 0 flat … 1 vertical\n    scratch.copy(grassLow).lerp(grassHigh, Math.min(1, h * 1.6));\n    if (h > 0.75) scratch.lerp(peak, (h - 0.75) * 4);\n    if (slope > 0.15) scratch.lerp(cliff, Math.min(1, (slope - 0.15) * 4));\n    if (waterLevel !== undefined && y < waterLevel + 0.5) {\n      scratch.lerp(sand, Math.min(1, (waterLevel + 0.5 - y) * 1.6));\n    }\n    colors[i * 3] = scratch.r;\n    colors[i * 3 + 1] = scratch.g;\n    colors[i * 3 + 2] = scratch.b;\n  }\n  geometry.setAttribute('color', new BufferAttribute(colors, 3));\n\n  const mesh = new Mesh(\n    geometry,\n    new MeshStandardMaterial({ vertexColors: true, flatShading: true })\n  );\n  mesh.name = 'terrain';\n\n  return { mesh, heightAt, size, seed };\n}\n","import { BufferAttribute, Mesh, MeshStandardMaterial, PlaneGeometry } from 'three';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { Terrain } from './terrain';\n\nexport interface WaterOptions {\n  /** World-space water surface height. Default 0.8. */\n  level?: number;\n  size?: number;\n  resolution?: number;\n  /** Wave height. Default 0.06. */\n  amplitude?: number;\n  /** Wave speed multiplier. Default 1. */\n  speed?: number;\n  palette?: Palette;\n}\n\nexport interface Water {\n  mesh: Mesh;\n  level: number;\n  /** Advance the wave animation. Call from your frame loop. */\n  update(dt: number): void;\n  /** Is ground at this height below the surface? */\n  isUnderwater(groundHeight: number): boolean;\n}\n\n/**\n * A low-poly animated water plane at a fixed level. Pair it with a\n * terrain built using the same `waterLevel` so shores blend to sand, and\n * keep scatter/agents ashore with `aboveWater(terrain, water)`.\n */\nexport function createWater(options: WaterOptions = {}): Water {\n  const level = options.level ?? 0.8;\n  const size = options.size ?? 200;\n  const resolution = options.resolution ?? 40;\n  const amplitude = options.amplitude ?? 0.06;\n  const speed = options.speed ?? 1;\n  const palette = options.palette ?? DEFAULT_PALETTE;\n\n  const geometry = new PlaneGeometry(size, size, resolution, resolution);\n  geometry.rotateX(-Math.PI / 2);\n  const positions = geometry.getAttribute('position') as BufferAttribute;\n  const mesh = new Mesh(\n    geometry,\n    new MeshStandardMaterial({\n      color: palette.water,\n      transparent: true,\n      opacity: 0.85,\n      flatShading: true,\n      metalness: 0.35,\n      roughness: 0.4,\n    })\n  );\n  mesh.name = 'water';\n  mesh.position.y = level;\n\n  let time = 0;\n  const update = (dt: number): void => {\n    time += dt * speed;\n    for (let i = 0; i < positions.count; i++) {\n      const x = positions.getX(i);\n      const z = positions.getZ(i);\n      positions.setY(\n        i,\n        Math.sin(x * 0.35 + time) * Math.cos(z * 0.3 + time * 0.8) * amplitude\n      );\n    }\n    positions.needsUpdate = true;\n    geometry.computeVertexNormals();\n  };\n  update(0);\n\n  return {\n    mesh,\n    level,\n    update,\n    isUnderwater: (groundHeight) => groundHeight < level,\n  };\n}\n\n/**\n * A scatter mask keeping placements on dry land: true when the terrain\n * at (x, z) sits above the water level plus `margin`.\n */\nexport function aboveWater(\n  terrain: Terrain,\n  water: Pick<Water, 'level'>,\n  margin = 0.25\n): (x: number, z: number) => boolean {\n  return (x, z) => terrain.heightAt(x, z) > water.level + margin;\n}\n","import {\n  BackSide,\n  Color,\n  Mesh,\n  ShaderMaterial,\n  SphereGeometry,\n} from 'three';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\n\nexport interface SkyOptions {\n  topColor?: number;\n  bottomColor?: number;\n  radius?: number;\n  palette?: Palette;\n}\n\nexport interface Sky {\n  mesh: Mesh;\n  setColors(top: number, bottom: number): void;\n}\n\n/**\n * A gradient sky dome (vertical color blend on an inverted sphere).\n * Colors default to the palette, so themed scenes get matching skies.\n */\nexport function createSky(options: SkyOptions = {}): Sky {\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const material = new ShaderMaterial({\n    side: BackSide,\n    depthWrite: false,\n    uniforms: {\n      topColor: { value: new Color(options.topColor ?? palette.skyTop) },\n      bottomColor: { value: new Color(options.bottomColor ?? palette.skyBottom) },\n    },\n    vertexShader: /* glsl */ `\n      varying vec3 vWorld;\n      void main() {\n        vWorld = (modelMatrix * vec4(position, 1.0)).xyz;\n        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n      }`,\n    fragmentShader: /* glsl */ `\n      uniform vec3 topColor;\n      uniform vec3 bottomColor;\n      varying vec3 vWorld;\n      void main() {\n        float t = clamp(normalize(vWorld).y * 0.5 + 0.5, 0.0, 1.0);\n        gl_FragColor = vec4(mix(bottomColor, topColor, pow(t, 0.8)), 1.0);\n      }`,\n  });\n  const mesh = new Mesh(new SphereGeometry(options.radius ?? 400, 16, 12), material);\n  mesh.name = 'sky';\n\n  return {\n    mesh,\n    setColors(top, bottom) {\n      (material.uniforms.topColor.value as Color).setHex(top);\n      (material.uniforms.bottomColor.value as Color).setHex(bottom);\n    },\n  };\n}\n","import {\n  AmbientLight,\n  DirectionalLight,\n  Fog,\n  Group,\n  HemisphereLight,\n  type Scene,\n} from 'three';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\n\nexport type LightingPreset = 'day' | 'golden-hour' | 'overcast' | 'night';\n\nexport interface LightingRig {\n  group: Group;\n  sun: DirectionalLight;\n  ambient: AmbientLight;\n  hemisphere: HemisphereLight;\n}\n\nconst PRESETS: Record<\n  LightingPreset,\n  { sun: number; sunIntensity: number; sunPos: [number, number, number]; ambient: number; ambientIntensity: number; skyTint: number; groundTint: number }\n> = {\n  day: {\n    sun: 0xfff4e0, sunIntensity: 1.6, sunPos: [30, 45, 20],\n    ambient: 0xdfeaff, ambientIntensity: 0.35, skyTint: 0xbcd8ff, groundTint: 0x6a7d66,\n  },\n  'golden-hour': {\n    sun: 0xffb861, sunIntensity: 1.7, sunPos: [40, 14, -12],\n    ambient: 0xffdcc0, ambientIntensity: 0.3, skyTint: 0xffcf9e, groundTint: 0x7a6a58,\n  },\n  overcast: {\n    sun: 0xd8dee8, sunIntensity: 0.7, sunPos: [12, 40, 8],\n    ambient: 0xcfd6e0, ambientIntensity: 0.65, skyTint: 0xc8d0dc, groundTint: 0x707a78,\n  },\n  night: {\n    sun: 0x8ea6d8, sunIntensity: 0.35, sunPos: [-20, 30, -25],\n    ambient: 0x3a4468, ambientIntensity: 0.35, skyTint: 0x2c3560, groundTint: 0x1e2430,\n  },\n};\n\n/**\n * The three lights every scene rebuilds, as a preset: warm directional\n * \"sun\" (position doubles as light direction), ambient fill, and a\n * hemisphere tint. Retune any of them via the returned rig.\n */\nexport function createLightingRig(preset: LightingPreset = 'day'): LightingRig {\n  const config = PRESETS[preset];\n  const group = new Group();\n  group.name = `lighting-${preset}`;\n  const sun = new DirectionalLight(config.sun, config.sunIntensity);\n  sun.position.set(...config.sunPos);\n  const ambient = new AmbientLight(config.ambient, config.ambientIntensity);\n  const hemisphere = new HemisphereLight(config.skyTint, config.groundTint, 0.5);\n  group.add(sun, ambient, hemisphere);\n  return { group, sun, ambient, hemisphere };\n}\n\nexport type FogPreset = 'clear' | 'haze' | 'thick' | 'eerie';\n\nconst FOG: Record<Exclude<FogPreset, 'clear'>, { near: number; far: number }> = {\n  haze: { near: 45, far: 160 },\n  thick: { near: 12, far: 70 },\n  eerie: { near: 6, far: 42 },\n};\n\n/** Distance fog matched to the palette's fog color. 'clear' removes it. */\nexport function applyFog(scene: Scene, preset: FogPreset, palette: Palette = DEFAULT_PALETTE): void {\n  if (preset === 'clear') {\n    scene.fog = null;\n    return;\n  }\n  const { near, far } = FOG[preset];\n  scene.fog = new Fog(palette.fog, near, far);\n}\n","import { Color, PointLight, type MeshStandardMaterial, type Mesh, type Object3D, type Scene } from 'three';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { LightingRig } from './lighting';\nimport type { Sky } from './sky';\n\ninterface Keyframe {\n  t: number;\n  skyTop: number;\n  skyBottom: number;\n  sun: number;\n  sunIntensity: number;\n  ambientIntensity: number;\n  fog: number;\n}\n\nexport interface DayCycleOptions {\n  sky?: Sky;\n  rig?: LightingRig;\n  /** Scene whose fog color should track the cycle. */\n  scene?: Scene;\n  /** Lamp props/objects whose PointLights + glow bulbs ignite at night. */\n  lamps?: Array<{ object: Object3D } | Object3D>;\n  palette?: Palette;\n  /** Seconds per full day. Default 60. */\n  dayLength?: number;\n  /** Initial time: 0 = midnight, 0.25 = dawn, 0.5 = noon, 0.75 = dusk. */\n  timeOfDay?: number;\n}\n\nexport interface DayCycle {\n  timeOfDay: number;\n  /** Sun elevation in [-1, 1]; negative = below the horizon. */\n  readonly sunElevation: number;\n  readonly isNight: boolean;\n  /** Advance by dt seconds of real time and re-apply everything. */\n  update(dt: number): void;\n  /** Jump to a time of day and re-apply everything. */\n  set(t: number): void;\n}\n\n/**\n * One `timeOfDay` parameter driving the whole environment in lockstep:\n * sun position/color/intensity, sky gradient, ambient level, fog color,\n * and lamps that ignite as the sun drops below the horizon.\n *\n * ```ts\n * const cycle = createDayCycle({ sky, rig, scene, lamps: [lampA, lampB], dayLength: 120 });\n * game.onUpdate((t) => cycle.update(t.delta));\n * ```\n */\nexport function createDayCycle(options: DayCycleOptions = {}): DayCycle {\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const dayLength = options.dayLength ?? 60;\n\n  // Universal ramp; noon colors come from the palette so themes carry through.\n  const frames: Keyframe[] = [\n    { t: 0.0, skyTop: 0x0b1026, skyBottom: 0x1a2340, sun: 0x8ea6d8, sunIntensity: 0.03, ambientIntensity: 0.06, fog: 0x141a2e },\n    { t: 0.23, skyTop: 0x27335c, skyBottom: 0x6a5470, sun: 0xcf9a72, sunIntensity: 0.3, ambientIntensity: 0.12, fog: 0x4a4258 },\n    { t: 0.3, skyTop: 0x4a6ba0, skyBottom: 0xe8a97a, sun: 0xffb861, sunIntensity: 1.0, ambientIntensity: 0.26, fog: 0xb08a72 },\n    { t: 0.5, skyTop: palette.skyTop, skyBottom: palette.skyBottom, sun: 0xfff4e0, sunIntensity: 1.9, ambientIntensity: 0.45, fog: palette.fog },\n    { t: 0.7, skyTop: 0x4a5a94, skyBottom: 0xe0955e, sun: 0xffa050, sunIntensity: 1.0, ambientIntensity: 0.26, fog: 0xa07a68 },\n    { t: 0.78, skyTop: 0x232a52, skyBottom: 0x8a5560, sun: 0xd88a5a, sunIntensity: 0.25, ambientIntensity: 0.11, fog: 0x463e54 },\n    { t: 1.0, skyTop: 0x0b1026, skyBottom: 0x1a2340, sun: 0x8ea6d8, sunIntensity: 0.03, ambientIntensity: 0.06, fog: 0x141a2e },\n  ];\n\n  // Collect lamp lights and glowing bulb materials once.\n  const lampLights: Array<{ light: PointLight; base: number }> = [];\n  const lampBulbs: Array<{ material: MeshStandardMaterial; base: number }> = [];\n  for (const entry of options.lamps ?? []) {\n    const root = (entry as { isObject3D?: boolean }).isObject3D\n      ? (entry as Object3D)\n      : (entry as { object: Object3D }).object;\n    root.traverse((child) => {\n      if (child instanceof PointLight) {\n        lampLights.push({ light: child, base: child.intensity || 6 });\n      }\n      const material = (child as Mesh).material as MeshStandardMaterial | undefined;\n      if (material?.emissive && material.emissiveIntensity > 0.5) {\n        lampBulbs.push({ material, base: material.emissiveIntensity });\n      }\n    });\n  }\n\n  const colorA = new Color();\n  const colorB = new Color();\n  let timeOfDay = options.timeOfDay ?? 0.5;\n  let sunElevation = 0;\n\n  const sample = (t: number): Keyframe => {\n    let a = frames[0];\n    let b = frames[frames.length - 1];\n    for (let i = 0; i < frames.length - 1; i++) {\n      if (t >= frames[i].t && t <= frames[i + 1].t) {\n        a = frames[i];\n        b = frames[i + 1];\n        break;\n      }\n    }\n    const f = b.t === a.t ? 0 : (t - a.t) / (b.t - a.t);\n    const lerpHex = (ha: number, hb: number): number =>\n      colorA.setHex(ha).lerp(colorB.setHex(hb), f).getHex();\n    return {\n      t,\n      skyTop: lerpHex(a.skyTop, b.skyTop),\n      skyBottom: lerpHex(a.skyBottom, b.skyBottom),\n      sun: lerpHex(a.sun, b.sun),\n      sunIntensity: a.sunIntensity + (b.sunIntensity - a.sunIntensity) * f,\n      ambientIntensity: a.ambientIntensity + (b.ambientIntensity - a.ambientIntensity) * f,\n      fog: lerpHex(a.fog, b.fog),\n    };\n  };\n\n  const apply = (): void => {\n    const t = timeOfDay;\n    const frame = sample(t);\n    const sunAngle = (t - 0.25) * Math.PI * 2;\n    sunElevation = Math.sin(sunAngle);\n\n    options.sky?.setColors(frame.skyTop, frame.skyBottom);\n    if (options.rig) {\n      const { sun, ambient, hemisphere } = options.rig;\n      sun.color.setHex(frame.sun);\n      sun.intensity = frame.sunIntensity;\n      sun.position.set(Math.cos(sunAngle) * 40, Math.max(sunElevation, -0.2) * 45 + 6, 16);\n      ambient.intensity = frame.ambientIntensity;\n      // Hemisphere fill follows the ambient curve so nights actually darken.\n      hemisphere.intensity = frame.ambientIntensity * 1.4;\n    }\n    if (options.scene?.fog && 'color' in options.scene.fog) {\n      options.scene.fog.color.setHex(frame.fog);\n    }\n    // Lamps fade in as the sun dips below the horizon.\n    const night = Math.min(1, Math.max(0, (0.06 - sunElevation) / 0.16));\n    for (const { light, base } of lampLights) light.intensity = base * night;\n    for (const { material, base } of lampBulbs) {\n      material.emissiveIntensity = 0.15 * base + 0.85 * base * night;\n    }\n  };\n  apply();\n\n  return {\n    get timeOfDay() {\n      return timeOfDay;\n    },\n    set timeOfDay(t: number) {\n      timeOfDay = ((t % 1) + 1) % 1;\n      apply();\n    },\n    get sunElevation() {\n      return sunElevation;\n    },\n    get isNight() {\n      return sunElevation < 0;\n    },\n    update(dt) {\n      timeOfDay = (timeOfDay + dt / dayLength) % 1;\n      apply();\n    },\n    set(t) {\n      timeOfDay = ((t % 1) + 1) % 1;\n      apply();\n    },\n  };\n}\n","import { Mesh, Vector2, type Material, type Object3D } from 'three';\n\n/** The slice of the shader object `onBeforeCompile` receives. */\ninterface PatchableShader {\n  uniforms: Record<string, { value: unknown }>;\n  vertexShader: string;\n}\n\nexport interface WindFieldOptions {\n  /** Wind bearing: degrees (0 = +X, 90 = +Z) or a world [x, z] vector. Default 35°. */\n  direction?: number | [number, number];\n  /** Steady lean at full sway, in world units. Default 0.3. */\n  strength?: number;\n  /** Gustiness 0–1: 0 = constant lean, 1 = deep travelling gusts. Default 0.5. */\n  gust?: number;\n  /** Distance between gust crests, in metres (smaller = tighter ripples). Default 6. */\n  waveLength?: number;\n  /** Speed the gust crests travel downwind. Default 2.2. */\n  waveSpeed?: number;\n}\n\nexport interface SwayOptions {\n  /** Local height (metres) at which sway reaches full. Default 1. */\n  height?: number;\n  /** Stiffness curve exponent — higher keeps the base stiffer. Default 1.6. */\n  stiffness?: number;\n  /** Local height below which nothing moves (keeps trunks planted). Default 0. */\n  anchor?: number;\n}\n\nexport interface WindField {\n  /** The shared shader uniforms (one set, referenced by every bound material). */\n  readonly uniforms: Record<string, { value: unknown }>;\n  /** The (normalized) wind direction in world XZ. Mutate via `setDirection`. */\n  readonly direction: Vector2;\n  /** Current steady strength. */\n  strength: number;\n  /** Every material patched so far. */\n  materials: Material[];\n  /** Point the wind along a new bearing (degrees) or [x, z] vector. */\n  setDirection(direction: number | [number, number]): WindField;\n  /** Change the steady strength. */\n  setStrength(strength: number): WindField;\n  /** The wind vector at a world point (CPU side) — for pushing agents, particles, boats. */\n  sample(x: number, z: number, time?: number): Vector2;\n  /** Patch a material to sway. Composes with surface materials; idempotent per material. */\n  bind(material: Material, options?: SwayOptions): WindField;\n  /** Self-animate: drive the shared clock from a rendered object's `onBeforeRender`. */\n  attach(object: Object3D): WindField;\n  /** Convenience: `bind` every material under `target`, then `attach` the driver. */\n  sway(target: Object3D, options?: SwayOptions): WindField;\n  /** Advance the clock manually instead of self-driving (for deterministic loops). */\n  update(dt: number): void;\n}\n\nconst WIND_UNIFORMS = /* glsl */ `\nuniform vec2  uWindDir;\nuniform float uWindStrength;\nuniform float uWindGust;\nuniform float uWindWaveK;\nuniform float uWindWaveSpeed;\nuniform float uWindTime;\nuniform float uWindHeight;\nuniform float uWindStiff;\nuniform float uWindAnchor;\n`;\n\n// Vertex bend: displacement grows with local height (bases stay planted), leans\n// along the wind, and rides a gust that TRAVELS downwind (so a field ripples,\n// and neighbours never sway in lockstep). Computed in world space then folded\n// back to local (assumes uniform scale + rotation, true for scattered plants).\nconst WIND_BEGIN = /* glsl */ `\n{\n  mat4 scenaWM = modelMatrix;\n  #ifdef USE_INSTANCING\n    scenaWM = modelMatrix * instanceMatrix;\n  #endif\n  vec3 scenaBase = scenaWM[3].xyz;\n  float scenaLH = max(position.y - uWindAnchor, 0.0);\n  float scenaSway = pow(clamp(scenaLH / max(uWindHeight, 1e-3), 0.0, 1.0), uWindStiff);\n  if (uWindStrength > 0.0 && scenaSway > 0.0) {\n    float scenaPhase = dot(scenaBase.xz, uWindDir) * uWindWaveK - uWindTime * uWindWaveSpeed;\n    float scenaGust = mix(1.0, 0.5 + 0.5 * sin(scenaPhase), uWindGust);\n    float scenaLean = uWindStrength * scenaGust * scenaSway;\n    float scenaFlutter = 0.3 * uWindStrength * sin(scenaPhase * 1.7 + scenaBase.x) * scenaSway;\n    vec2 scenaPerp = vec2(-uWindDir.y, uWindDir.x);\n    vec3 scenaDisp = vec3(\n      uWindDir.x * scenaLean + scenaPerp.x * scenaFlutter,\n      -0.12 * abs(scenaLean),\n      uWindDir.y * scenaLean + scenaPerp.y * scenaFlutter\n    );\n    mat3 scenaLin = mat3(scenaWM);\n    float scenaInv = 1.0 / max(dot(scenaLin[0], scenaLin[0]), 1e-5);\n    // transpose(M) * v via column dots → world displacement back into local space.\n    transformed += vec3(dot(scenaLin[0], scenaDisp), dot(scenaLin[1], scenaDisp), dot(scenaLin[2], scenaDisp)) * scenaInv;\n  }\n}\n`;\n\nfunction toDir(direction: number | [number, number], out: Vector2): Vector2 {\n  if (Array.isArray(direction)) out.set(direction[0], direction[1]);\n  else {\n    const r = (direction * Math.PI) / 180;\n    out.set(Math.cos(r), Math.sin(r));\n  }\n  if (out.lengthSq() < 1e-9) out.set(1, 0);\n  return out.normalize();\n}\n\nfunction nowSeconds(): number {\n  return typeof performance !== 'undefined' ? performance.now() * 0.001 : 0;\n}\n\n/**\n * A shared wind field for vegetation and cloth — the environmental handshake\n * that makes a world breathe. One field drives many props: trees and grass\n * bend, a wheat field ripples, banners fly, all from the *same* gust, so a\n * breeze crosses the whole scene in step. The bend is a vertex-shader effect\n * (full PBR/shadows/fog survive), the gust travels downwind so nothing sways\n * in lockstep, and the field self-animates from the render loop — no update\n * wiring needed. `sample(x, z)` exposes the same wind on the CPU, so gameplay\n * (drifting agents, bobbing boats, blown particles) can read it too.\n *\n * ```ts\n * const wind = createWindField({ direction: 40, strength: 0.35 });\n * wind.sway(forest.group, { height: 4, anchor: 1.0 });      // canopies bend\n * wind.sway(wheat.group,  { height: 0.9, stiffness: 1.2 }); // blades ripple\n * ```\n */\nexport function createWindField(options: WindFieldOptions = {}): WindField {\n  const direction = toDir(options.direction ?? 35, new Vector2());\n  let strength = options.strength ?? 0.3;\n  const gust = Math.max(0, Math.min(1, options.gust ?? 0.5));\n  const waveLength = options.waveLength ?? 6;\n  const waveSpeed = options.waveSpeed ?? 2.2;\n\n  const uniforms = {\n    uWindDir: { value: direction },\n    uWindStrength: { value: strength },\n    uWindGust: { value: gust },\n    uWindWaveK: { value: (Math.PI * 2) / Math.max(waveLength, 0.01) },\n    uWindWaveSpeed: { value: waveSpeed },\n    uWindTime: { value: 0 },\n  };\n\n  const patched: Material[] = [];\n  let manual = false;\n\n  const field: WindField = {\n    uniforms,\n    direction,\n    get strength() {\n      return strength;\n    },\n    set strength(s: number) {\n      strength = s;\n      uniforms.uWindStrength.value = s;\n    },\n    materials: patched,\n\n    setDirection(dir) {\n      toDir(dir, direction);\n      return field;\n    },\n    setStrength(s) {\n      field.strength = s;\n      return field;\n    },\n\n    sample(x, z, time) {\n      const t = time ?? (manual ? uniforms.uWindTime.value : nowSeconds());\n      const phase = (x * direction.x + z * direction.y) * uniforms.uWindWaveK.value - t * waveSpeed;\n      const gustShape = 1 - gust + gust * (0.5 + 0.5 * Math.sin(phase));\n      const mag = strength * gustShape;\n      return new Vector2(direction.x * mag, direction.y * mag);\n    },\n\n    bind(material, opts = {}) {\n      const data = (material.userData ??= {}) as { __scenaWind?: boolean };\n      if (data.__scenaWind) return field;\n      data.__scenaWind = true;\n\n      const perMat = {\n        uWindHeight: { value: opts.height ?? 1 },\n        uWindStiff: { value: opts.stiffness ?? 1.6 },\n        uWindAnchor: { value: opts.anchor ?? 0 },\n      };\n      const prevCompile = material.onBeforeCompile;\n      // Capture the base cache key BEFORE overriding, so surface+wind stays a\n      // distinct program from plain+wind and from surface alone.\n      const baseKey = material.customProgramCacheKey ? material.customProgramCacheKey() : '';\n      material.onBeforeCompile = function (shader: PatchableShader, renderer: unknown) {\n        if (prevCompile) (prevCompile as (s: PatchableShader, r: unknown) => void).call(this, shader, renderer);\n        Object.assign(shader.uniforms, uniforms, perMat);\n        shader.vertexShader = shader.vertexShader\n          .replace('#include <common>', '#include <common>\\n' + WIND_UNIFORMS)\n          .replace('#include <begin_vertex>', '#include <begin_vertex>\\n' + WIND_BEGIN);\n      };\n      material.customProgramCacheKey = () => baseKey + '|scena-wind-v1';\n      material.needsUpdate = true;\n      patched.push(material);\n      return field;\n    },\n\n    attach(object) {\n      let mesh: Mesh | null = object instanceof Mesh ? object : null;\n      if (!mesh) {\n        object.traverse((o) => {\n          if (!mesh && o instanceof Mesh) mesh = o;\n        });\n      }\n      if (mesh) {\n        const target = mesh as Mesh;\n        const prev = target.onBeforeRender;\n        target.onBeforeRender = function (this: Mesh, ...args: unknown[]) {\n          if (prev) (prev as (...a: unknown[]) => void).apply(this, args);\n          if (!manual) uniforms.uWindTime.value = nowSeconds();\n        } as Mesh['onBeforeRender'];\n      }\n      return field;\n    },\n\n    sway(target, opts) {\n      const seen = new Set<Material>();\n      target.traverse((o) => {\n        if (!(o instanceof Mesh)) return;\n        const mats = Array.isArray(o.material) ? o.material : [o.material];\n        for (const m of mats) {\n          if (m && !seen.has(m)) {\n            seen.add(m);\n            field.bind(m, opts);\n          }\n        }\n      });\n      field.attach(target);\n      return field;\n    },\n\n    update(dt) {\n      manual = true;\n      uniforms.uWindTime.value += dt;\n    },\n  };\n\n  return field;\n}\n\n// --- Backwards-compatible convenience -----------------------------------\n\nexport interface WindOptions extends WindFieldOptions, SwayOptions {\n  /** @deprecated use `anchor`. Local height where sway begins. */\n  anchorHeight?: number;\n  /** Bind against an existing field instead of making a new one. */\n  field?: WindField;\n}\n\nexport type Wind = WindField;\n\n/**\n * Make everything under `target` sway in the wind — the one-call path. Builds\n * (or reuses) a {@link WindField}, binds every material and self-animates.\n * Returns the field, so you can `sample()` it, re-aim it, or share it with more\n * props. Kept `update()`-compatible for deterministic loops.\n *\n * ```ts\n * const wind = applyWind(forest.group, { strength: 0.3, height: 4, anchor: 1 });\n * // optional: game.onUpdate((t) => wind.update(t.delta));\n * ```\n */\nexport function applyWind(target: Object3D, options: WindOptions = {}): Wind {\n  const field = options.field ?? createWindField(options);\n  field.sway(target, {\n    height: options.height ?? 2.5,\n    stiffness: options.stiffness,\n    anchor: options.anchor ?? options.anchorHeight ?? 0,\n  });\n  return field;\n}\n","import {\n  BufferAttribute,\n  BufferGeometry,\n  CatmullRomCurve3,\n  Mesh,\n  MeshStandardMaterial,\n  Vector3,\n} from 'three';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\n\nexport interface PathOptions {\n  /** Ribbon width. Default 1.8. */\n  width?: number;\n  /** Ground height lookup; a number means flat ground. Default 0. */\n  surface?: number | ((x: number, z: number) => number);\n  /** Samples per world unit of path length. Default 1. */\n  samplesPerUnit?: number;\n  /** Close the path into a loop. Default false. */\n  loop?: boolean;\n  /** Extra clearance added to scatter keep-out circles. Default 0.6. */\n  keepOutMargin?: number;\n  palette?: Palette;\n}\n\nexport interface WorldPath {\n  mesh: Mesh;\n  /** Smoothed centerline draped on the surface — feed straight into a\n   *  GAMA `Path` for patrols, or use as camera dolly points. */\n  route: Vector3[];\n  /** Keep-out circles for `scatter()` so nothing grows on the road. */\n  keepOut: Array<{ center: { x: number; z: number }; radius: number }>;\n  /** Is (x, z) on the path surface? (e.g. to exclude grass) */\n  contains(x: number, z: number): boolean;\n  loop: boolean;\n}\n\n/**\n * A dirt path: a Catmull-Rom-smoothed ribbon draped over the surface.\n * One authored polyline feeds three things at once — the visual ribbon,\n * scatter keep-out, and a patrol route for agents. That's the SCENA\n * handshake applied to level design.\n *\n * ```ts\n * const road = createPath([a, b, c], { surface: terrain.heightAt, loop: true });\n * scene.add(road.mesh);\n * scatter({ ..., keepOut: road.keepOut });\n * agent.addBehavior(new FollowPath(new Path(road.route, road.loop), 1.5));\n * ```\n */\nexport function createPath(\n  points: Array<Vector3 | { x: number; z: number }>,\n  options: PathOptions = {}\n): WorldPath {\n  const width = options.width ?? 1.8;\n  const surface = options.surface ?? 0;\n  const heightAt =\n    typeof surface === 'number' ? () => surface : (x: number, z: number) => surface(x, z);\n  const loop = options.loop ?? false;\n  const palette = options.palette ?? DEFAULT_PALETTE;\n\n  const controls = points.map((p) => new Vector3(p.x, 0, 'z' in p ? p.z : 0));\n  const curve = new CatmullRomCurve3(controls, loop, 'centripetal');\n  const length = curve.getLength();\n  const samples = Math.max(8, Math.ceil(length * (options.samplesPerUnit ?? 1)));\n\n  const route: Vector3[] = [];\n  for (let i = 0; i <= samples; i++) {\n    if (loop && i === samples) break; // avoid duplicate closing point\n    const p = curve.getPoint(i / samples);\n    route.push(new Vector3(p.x, heightAt(p.x, p.z), p.z));\n  }\n\n  // Ribbon strip: left/right edge vertices per sample.\n  const edgeCount = loop ? route.length + 1 : route.length;\n  const positions = new Float32Array(edgeCount * 2 * 3);\n  const direction = new Vector3();\n  const perp = new Vector3();\n  for (let i = 0; i < edgeCount; i++) {\n    const current = route[i % route.length];\n    const previous = route[(i - 1 + route.length) % route.length];\n    const next = route[(i + 1) % route.length];\n    if (!loop && i === 0) direction.subVectors(next, current);\n    else if (!loop && i === edgeCount - 1) direction.subVectors(current, previous);\n    else direction.subVectors(next, previous);\n    perp.set(-direction.z, 0, direction.x).normalize().multiplyScalar(width / 2);\n    const left = i * 6;\n    positions[left] = current.x - perp.x;\n    positions[left + 1] = heightAt(current.x - perp.x, current.z - perp.z) + 0.05;\n    positions[left + 2] = current.z - perp.z;\n    positions[left + 3] = current.x + perp.x;\n    positions[left + 4] = heightAt(current.x + perp.x, current.z + perp.z) + 0.05;\n    positions[left + 5] = current.z + perp.z;\n  }\n  const indices: number[] = [];\n  for (let i = 0; i < edgeCount - 1; i++) {\n    const a = i * 2;\n    indices.push(a, a + 1, a + 2, a + 1, a + 3, a + 2);\n  }\n  const geometry = new BufferGeometry();\n  geometry.setAttribute('position', new BufferAttribute(positions, 3));\n  geometry.setIndex(indices);\n  geometry.computeVertexNormals();\n\n  const mesh = new Mesh(\n    geometry,\n    new MeshStandardMaterial({\n      color: palette.path,\n      flatShading: true,\n      polygonOffset: true,\n      polygonOffsetFactor: -1,\n    })\n  );\n  mesh.name = 'path';\n\n  const keepOutMargin = options.keepOutMargin ?? 0.6;\n  const keepOut = route\n    .filter((_p, i) => i % 2 === 0 || i === route.length - 1) // never drop the endpoint\n    .map((p) => ({ center: { x: p.x, z: p.z }, radius: width / 2 + keepOutMargin }));\n\n  const half = width / 2;\n  const contains = (x: number, z: number): boolean => {\n    const count = loop ? route.length : route.length - 1;\n    for (let i = 0; i < count; i++) {\n      const a = route[i];\n      const b = route[(i + 1) % route.length];\n      const abx = b.x - a.x;\n      const abz = b.z - a.z;\n      const lengthSq = abx * abx + abz * abz || 1e-9;\n      const t = Math.max(0, Math.min(1, ((x - a.x) * abx + (z - a.z) * abz) / lengthSq));\n      const dx = x - (a.x + abx * t);\n      const dz = z - (a.z + abz * t);\n      if (dx * dx + dz * dz <= half * half) return true;\n    }\n    return false;\n  };\n\n  return { mesh, route, keepOut, contains, loop };\n}\n","import { Group } from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport { collectObstacles, type Obstacle, type Prop } from '../core/types';\nimport { createHouse, createRuin, createTower, createWell } from '../props/building';\nimport { createCrate } from '../props/crate';\nimport { createLamp } from '../props/lamp';\n\nexport interface VillageOptions {\n  seed?: number;\n  /** Village center in the XZ plane. Default origin. */\n  center?: { x: number; z: number };\n  /** Ring radius the houses settle on. Default 12. */\n  radius?: number;\n  /** House count. Default 5. */\n  houses?: number;\n  /** Ground height lookup; a number means flat ground. Default 0. */\n  surface?: number | ((x: number, z: number) => number);\n  /** Veto candidate spots (e.g. water, roads). Return false to reject. */\n  mask?: (x: number, z: number, y: number) => boolean;\n  /** Add real PointLights to this many street lamps. Default 3. */\n  lampLights?: number;\n  /** Add a watchtower at the edge. Default true. */\n  tower?: boolean;\n  /** Add a ruin outside the ring. Default true. */\n  ruin?: boolean;\n  palette?: Palette;\n}\n\nexport interface Village {\n  group: Group;\n  /** Every placed prop (houses, well, lamps, crates, tower, ruin). */\n  props: Prop[];\n  /** World-space steering obstacles — feed GAMA's ObstacleAvoidance. */\n  obstacles: Obstacle[];\n  /**\n   * Props with something to ignite at night (street lamps AND house\n   * windows). Pass straight to `createDayCycle({ lamps })`.\n   */\n  lamps: Prop[];\n  /** One clearing circle covering the village — feed `scatter`'s keepOut. */\n  keepOut: Array<{ center: { x: number; z: number }; radius: number }>;\n  center: { x: number; z: number };\n}\n\n/**\n * A seeded hamlet: a well at the center, houses ringed around it facing\n * inward, street lamps between them, crates by the doors, a watchtower on\n * the edge and a ruin beyond. Everything is placed on the given surface\n * (steep or masked spots are rejected and re-rolled), and the result\n * carries the full gameplay handshake: `obstacles` for steering,\n * `keepOut` for scatter, and `lamps` for the day-night cycle — windows\n * and lamps ignite together at dusk.\n *\n * ```ts\n * const village = createVillage({ seed: 5, radius: 10, surface: terrain.heightAt, palette });\n * scene.add(village.group);\n * const cycle = createDayCycle({ sky, rig, scene, lamps: village.lamps, palette });\n * const forest = scatter({ ..., keepOut: village.keepOut });\n * ```\n */\nexport function createVillage(options: VillageOptions = {}): Village {\n  const rng = new Rng(options.seed ?? 1);\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const center = options.center ?? { x: 0, z: 0 };\n  const radius = options.radius ?? 12;\n  const houseCount = options.houses ?? 5;\n  const surface = options.surface ?? 0;\n  const heightAt =\n    typeof surface === 'number' ? () => surface : (x: number, z: number) => surface(x, z);\n\n  const group = new Group();\n  group.name = 'village';\n  const props: Prop[] = [];\n  const lamps: Prop[] = [];\n\n  const place = (prop: Prop, x: number, z: number, rotY: number): Prop => {\n    prop.object.position.set(x, heightAt(x, z), z);\n    prop.object.rotation.y = rotY;\n    group.add(prop.object);\n    props.push(prop);\n    return prop;\n  };\n\n  /**\n   * Find a buildable spot near (angle, distance): reasonably level across\n   * the footprint and not vetoed by the mask. Re-rolls up to 10 times,\n   * then falls back to the last candidate so layout never dead-ends.\n   */\n  const findSpot = (\n    angle: number,\n    distance: number,\n    footprint: number\n  ): { x: number; z: number } => {\n    let x = center.x;\n    let z = center.z;\n    for (let attempt = 0; attempt < 10; attempt++) {\n      const a = angle + rng.range(-0.25, 0.25) * (attempt > 0 ? 1 : 0.3);\n      const d = distance * rng.range(attempt > 0 ? 0.8 : 0.95, 1.1);\n      x = center.x + Math.cos(a) * d;\n      z = center.z + Math.sin(a) * d;\n      const y = heightAt(x, z);\n      if (options.mask && !options.mask(x, z, y)) continue;\n      let min = y;\n      let max = y;\n      for (const [dx, dz] of [[footprint, 0], [-footprint, 0], [0, footprint], [0, -footprint]]) {\n        const h = heightAt(x + dx, z + dz);\n        min = Math.min(min, h);\n        max = Math.max(max, h);\n      }\n      if (max - min <= Math.max(0.9, footprint * 0.35)) break;\n    }\n    return { x, z };\n  };\n\n  // The well anchors the plaza.\n  const well = createWell({ seed: rng.int(1, 1e9), palette });\n  place(well, center.x, center.z, rng.range(0, Math.PI * 2));\n\n  // Houses on the ring, facing the well.\n  let lightBudget = options.lampLights ?? 3;\n  for (let i = 0; i < houseCount; i++) {\n    const angle = (i / houseCount) * Math.PI * 2 + rng.range(-0.15, 0.15);\n    const house = createHouse({ seed: rng.int(1, 1e9), palette });\n    const spot = findSpot(angle, radius * rng.range(0.7, 0.95), house.obstacleRadius);\n    const facing = Math.atan2(center.x - spot.x, center.z - spot.z);\n    place(house, spot.x, spot.z, facing);\n    lamps.push(house);\n\n    // A crate by most doors, a lamp partway toward the plaza for some.\n    if (rng.next() < 0.7) {\n      const crateAngle = angle + rng.range(-0.5, 0.5);\n      const crateDistance = Math.hypot(spot.x - center.x, spot.z - center.z) - house.obstacleRadius - 0.7;\n      place(\n        createCrate({ seed: rng.int(1, 1e9), size: rng.range(0.7, 1), palette }),\n        center.x + Math.cos(crateAngle) * crateDistance,\n        center.z + Math.sin(crateAngle) * crateDistance,\n        rng.range(0, Math.PI)\n      );\n    }\n    if (i % 2 === 0) {\n      const lampDistance = Math.hypot(spot.x - center.x, spot.z - center.z) * 0.55;\n      const lamp = createLamp({ seed: rng.int(1, 1e9), light: lightBudget > 0, palette });\n      lightBudget--;\n      place(lamp, center.x + Math.cos(angle) * lampDistance, center.z + Math.sin(angle) * lampDistance, 0);\n      lamps.push(lamp);\n    }\n  }\n\n  if (options.tower ?? true) {\n    const angle = rng.range(0, Math.PI * 2);\n    const tower = createTower({ seed: rng.int(1, 1e9), palette });\n    const spot = findSpot(angle, radius * 1.05, tower.obstacleRadius);\n    place(tower, spot.x, spot.z, rng.range(0, Math.PI * 2));\n  }\n  if (options.ruin ?? true) {\n    const angle = rng.range(0, Math.PI * 2);\n    const ruin = createRuin({ seed: rng.int(1, 1e9), palette });\n    const spot = findSpot(angle, radius * 1.35, ruin.obstacleRadius);\n    place(ruin, spot.x, spot.z, rng.range(0, Math.PI * 2));\n  }\n\n  return {\n    group,\n    props,\n    obstacles: collectObstacles(props),\n    lamps,\n    keepOut: [{ center: { ...center }, radius: radius * 1.5 }],\n    center,\n  };\n}\n","import { Object3D, Vector3, type Group } from 'three';\n\n/**\n * A steering obstacle in world space — structurally identical to GAMA's\n * `Obstacle`, so SCENA props plug straight into `ObstacleAvoidance`\n * without either library importing the other.\n */\nexport interface Obstacle {\n  center: Vector3;\n  radius: number;\n}\n\n/**\n * An interaction slot — where and how a character uses this prop.\n * Structurally identical to ANIMA's `InteractionSlot` (anchor at floor\n * level, +z the facing direction, pitched for lying poses), so a prop's\n * slot drops straight into `new Interaction(rig, loco).use(slot)` without\n * either library importing the other.\n */\nexport interface PropSlot {\n  /** Free label: 'sit', 'sleep', 'driver', 'run'… */\n  kind: string;\n  /** The transform target for the character's root (a child of the prop). */\n  anchor: Object3D;\n  /** ANIMA pose name ('sit', 'sleep', 'drive', 'cycle', …) or 'run'. */\n  pose: string;\n  /** Optional arms loop ('strum', 'hammer', 'knead'). */\n  loop?: string;\n  /**\n   * Where a character should *stand* before taking the slot — beside the\n   * chair, not on it. Nobody materialises into a seat: they walk here, turn,\n   * then lower. ANIMA's `Interaction.use(slot, { approach: true })` reads it\n   * to stage the sit; steering agents path to it rather than to the anchor.\n   */\n  approach?: Object3D;\n}\n\n/** How a character holds a carryable — structurally ANIMA's `CarryStyle`. */\nexport type CarryStyle = 'crate' | 'tray' | 'shoulder' | 'side';\n\n/**\n * A prop a character can pick up and carry. Structurally identical to ANIMA's\n * `Holdable`, so a SCENA crate drops into `new Carry(rig, loco).pickUp(crate)`\n * with no cross-imports. The object's origin stays at its base (natural for\n * ground placement); `grip` offsets the *hold point* — where it rides in the\n * hands — from that origin.\n */\nexport interface Carryable extends Prop {\n  /** The carry pose the holder adopts. */\n  carry: CarryStyle;\n  /** Hold-point offset from the object's origin (metres). */\n  grip?: { x?: number; y?: number; z?: number };\n}\n\n/**\n * A flat surface on a prop that things can be put down on: a tabletop, a\n * shelf board, the lid of a chest, a windowsill.\n *\n * The anchor sits **on** the surface with +y up, +x along its width and +z\n * along its depth, so `dress` only has to think in two dimensions and the\n * height of whatever it places.\n */\nexport interface PropSurface {\n  /** Free label: 'top', 'shelf', 'sill'. */\n  kind: string;\n  /** Anchor at surface level, a child of the prop. */\n  anchor: Object3D;\n  /** Usable extent along the anchor's local x and z, in metres. */\n  width: number;\n  depth: number;\n}\n\n/**\n * A body of water something can be in, in **world** coordinates.\n *\n * The swimming handshake, and it mirrors `terrain.heightAt` and\n * `ocean.heightAt`: the prop answers questions about the water and ANIMA\n * decides what a body does about it. `depthAt` returns 0 anywhere outside,\n * so \"am I in the water\" needs no separate `contains`.\n *\n * The interesting number is the **depth**, not the surface. Whether a\n * character wades or swims is a decision made against their own height, and\n * a pool with one depth everywhere cannot pose that question at all.\n */\nexport interface WaterBody {\n  /** World Y of the still surface. */\n  readonly surfaceY: number;\n  /** Water depth at a world point, in metres. 0 anywhere outside. */\n  depthAt(x: number, z: number): number;\n  /** Ripple it at a world point — a stroke, a dive, a hand going in. */\n  disturb(x: number, z: number, strength?: number): void;\n}\n\n/** What a prop generator returns: the visual plus gameplay metadata. */\nexport interface Prop {\n  object: Group;\n  /**\n   * Footprint radius for steering/placement, in the prop's local space\n   * (centered at its origin). 0 means walk-through (e.g. grass).\n   */\n  obstacleRadius: number;\n  /** Interaction slots, on props a character can use. */\n  slots?: PropSlot[];\n  /** Flat surfaces things can be set down on — feed these to `dress`. */\n  surfaces?: PropSurface[];\n  /**\n   * Which way up this comes to rest when it is set down on something.\n   *\n   * Props are authored in the orientation they are *used* in, which for a\n   * phone is upright in a hand — put one down as authored and it stands on\n   * its short edge like a domino. `dress` works this out for itself from the\n   * shape (a slab lies down, a candle does not); set this only to override.\n   */\n  rest?: 'upright' | 'flat';\n}\n\n/** Build a surface: an anchor parented into the prop at (x, y, z). */\nexport function createPropSurface(\n  kind: string,\n  parent: Group,\n  x: number,\n  y: number,\n  z: number,\n  width: number,\n  depth: number,\n  rotY = 0\n): PropSurface {\n  const anchor = new Object3D();\n  anchor.name = `surface:${kind}`;\n  anchor.position.set(x, y, z);\n  anchor.rotation.y = rotY;\n  parent.add(anchor);\n  return { kind, anchor, width, depth };\n}\n\n/**\n * A prop several characters use *together* — a dining table, a bench, a\n * game board. Beyond the seats it publishes a **focus**: the thing the\n * occupants attend to. Point every sitter's gaze at it and a row of bodies\n * becomes a group; without it they are strangers who happen to be adjacent.\n */\nexport interface Gathering extends Prop {\n  /** The places, in a stable order — index 0 is the head of the table. */\n  seats: PropSlot[];\n  /** What the occupants look at: table centre, game board, campfire. */\n  focus: Object3D;\n}\n\n/** Build a slot: an anchor Object3D parented into the prop at (x, y, z). */\nexport function createSlot(\n  kind: string,\n  pose: string,\n  parent: Group,\n  x: number,\n  y: number,\n  z: number,\n  rotY = 0,\n  rotX = 0\n): PropSlot {\n  const anchor = new Object3D();\n  anchor.name = `slot:${kind}`;\n  anchor.position.set(x, y, z);\n  anchor.rotation.set(rotX, rotY, 0);\n  parent.add(anchor);\n  return { kind, anchor, pose };\n}\n\n/**\n * Give a slot its standing-room-before: an approach anchor `distance` metres\n * from the seat, facing the same way. The character walks here, turns, and\n * lowers backwards into the slot — which is how sitting actually works.\n *\n * `from` picks the side the character comes at it from, and it must be the\n * side that is *open*. A dining chair is approached from behind (the table\n * is in front of it); a park bench is approached from the front (the\n * backrest is behind it). Get this backwards and characters walk through\n * the furniture to reach their seats.\n */\nexport function addApproach(\n  slot: PropSlot,\n  parent: Group,\n  distance = 0.7,\n  from: 'behind' | 'front' = 'behind'\n): PropSlot {\n  const anchor = new Object3D();\n  anchor.name = `approach:${slot.kind}`;\n  const rotY = slot.anchor.rotation.y;\n  const sign = from === 'front' ? 1 : -1;\n  anchor.position.set(\n    slot.anchor.position.x + Math.sin(rotY) * distance * sign,\n    slot.anchor.position.y,\n    slot.anchor.position.z + Math.cos(rotY) * distance * sign\n  );\n  anchor.rotation.y = rotY;\n  parent.add(anchor);\n  slot.approach = anchor;\n  return slot;\n}\n\n/** Collect world-space obstacles from placed props (call after positioning). */\nexport function collectObstacles(props: Iterable<Prop>): Obstacle[] {\n  const obstacles: Obstacle[] = [];\n  for (const prop of props) {\n    if (prop.obstacleRadius <= 0) continue;\n    prop.object.updateWorldMatrix(true, false);\n    obstacles.push({\n      center: prop.object.getWorldPosition(new Vector3()),\n      radius: prop.obstacleRadius * maxScale(prop.object),\n    });\n  }\n  return obstacles;\n}\n\nfunction maxScale(object: Object3D): number {\n  return Math.max(object.scale.x, object.scale.z);\n}\n","import {\n  BoxGeometry,\n  BufferAttribute,\n  BufferGeometry,\n  CylinderGeometry,\n  Group,\n  Mesh,\n  MeshStandardMaterial,\n} from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport { createSurface } from '../materials/surface';\nimport type { Prop } from '../core/types';\n\n/** A gabled-roof prism: ridge along local z, base resting on y = 0. */\nfunction prismGeometry(width: number, height: number, depth: number): BufferGeometry {\n  const w = width / 2;\n  const d = depth / 2;\n  // prettier-ignore\n  const positions = new Float32Array([\n    // front gable (z = +d)\n    -w, 0, d,   w, 0, d,   0, height, d,\n    // back gable (z = -d)\n    w, 0, -d,  -w, 0, -d,   0, height, -d,\n    // left slope\n    -w, 0, -d,  -w, 0, d,   0, height, d,\n    -w, 0, -d,   0, height, d,   0, height, -d,\n    // right slope\n    w, 0, d,   w, 0, -d,   0, height, -d,\n    w, 0, d,   0, height, -d,   0, height, d,\n    // bottom\n    -w, 0, -d,   w, 0, -d,   w, 0, d,\n    -w, 0, -d,   w, 0, d,  -w, 0, d,\n  ]);\n  const geometry = new BufferGeometry();\n  geometry.setAttribute('position', new BufferAttribute(positions, 3));\n  geometry.computeVertexNormals();\n  return geometry;\n}\n\nexport type WallStyle = 'plaster' | 'brick' | 'ashlar';\nexport type RoofStyle = 'tile' | 'shingle' | 'thatch';\n\nexport interface HouseOptions {\n  seed?: number;\n  /** Footprint width (gable side). Default seeded 3.2–4.2. */\n  width?: number;\n  depth?: number;\n  wallHeight?: number;\n  /** Wall surface. Default seeded (mostly plaster, some brick / ashlar). */\n  wall?: WallStyle;\n  /** Roof surface. Default seeded (tile, wooden shingle or straw thatch). */\n  roof?: RoofStyle;\n  palette?: Palette;\n}\n\n// Seed-weighted so a row of houses varies without any caller doing the work.\nconst WALL_STYLES: WallStyle[] = ['plaster', 'plaster', 'plaster', 'brick', 'ashlar'];\nconst ROOF_STYLES: RoofStyle[] = ['tile', 'tile', 'shingle', 'thatch'];\n\n/**\n * A cottage: plastered walls, gabled roof, door, chimney and emissive\n * windows. Pass the house in `createDayCycle`'s `lamps` list and its\n * windows glow at night along with the street lamps. A stone foundation\n * extends below ground so sloped terrain never shows a gap.\n */\nexport function createHouse(options: HouseOptions = {}): Prop {\n  const rng = new Rng(options.seed ?? 1);\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const width = options.width ?? rng.range(3.2, 4.2);\n  const depth = options.depth ?? width * rng.range(0.75, 0.9);\n  const wallHeight = options.wallHeight ?? rng.range(2.1, 2.4);\n\n  const group = new Group();\n  group.name = 'house';\n  const seed = options.seed ?? 1;\n  // Procedural surfaces: walls (plaster / brick / ashlar), roof (clay tile /\n  // wooden shingle / straw thatch), weathered stone foundation, planked door —\n  // all detail generated in-shader. Style is seeded, so a street of houses\n  // varies on its own.\n  const wallStyle = options.wall ?? rng.pick(WALL_STYLES);\n  const roofStyle = options.roof ?? rng.pick(ROOF_STYLES);\n  const wallColor =\n    wallStyle === 'brick' ? 0x9e4a34 : wallStyle === 'ashlar' ? palette.rock[0] : palette.wall;\n  const wall = createSurface(wallStyle, { color: wallColor, seed });\n  wall.color.offsetHSL(0, 0, rng.range(-0.03, 0.03));\n  const roofColor =\n    roofStyle === 'thatch' ? 0xb39a5c : roofStyle === 'shingle' ? palette.woodDark : palette.roof;\n  const roof = createSurface(roofStyle, { color: roofColor, seed: seed + 7 });\n  roof.color.offsetHSL(0, 0, rng.range(-0.04, 0.04));\n  const stone = createSurface('stone', { color: palette.rock[0], seed: seed + 13 });\n  const wood = createSurface('plank', { color: palette.woodDark, seed: seed + 21 });\n\n  const foundation = new Mesh(new BoxGeometry(width + 0.3, 1.6, depth + 0.3), stone);\n  foundation.position.y = -0.55;\n  group.add(foundation);\n\n  const body = new Mesh(new BoxGeometry(width, wallHeight, depth), wall);\n  body.position.y = wallHeight / 2;\n  group.add(body);\n\n  const ridgeHeight = width * rng.range(0.32, 0.4);\n  const roofMesh = new Mesh(prismGeometry(width + 0.5, ridgeHeight, depth + 0.6), roof);\n  roofMesh.position.y = wallHeight - 0.02;\n  group.add(roofMesh);\n\n  const chimney = new Mesh(new BoxGeometry(0.34, ridgeHeight + 0.8, 0.34), stone);\n  chimney.position.set(rng.pick([-1, 1]) * width * 0.22, wallHeight + ridgeHeight * 0.45, depth * 0.12);\n  group.add(chimney);\n\n  // Door on the front face (+z).\n  const door = new Mesh(new BoxGeometry(0.85, 1.5, 0.08), wood);\n  door.position.set(rng.range(-0.4, 0.4), 0.75, depth / 2 + 0.02);\n  group.add(door);\n\n  // Emissive windows — createDayCycle treats these like lamp bulbs.\n  const glass = new MeshStandardMaterial({\n    color: palette.lampGlow,\n    emissive: palette.lampGlow,\n    emissiveIntensity: 1.0,\n  });\n  const windowGeometry = new BoxGeometry(0.6, 0.62, 0.08);\n  const front = new Mesh(windowGeometry, glass);\n  front.position.set(door.position.x < 0 ? width * 0.28 : -width * 0.28, 1.35, depth / 2 + 0.02);\n  group.add(front);\n  for (const side of [-1, 1]) {\n    if (rng.next() < 0.35) continue;\n    const pane = new Mesh(windowGeometry, glass);\n    pane.position.set(side * (width / 2 + 0.02), 1.35, rng.range(-0.3, 0.3) * depth);\n    pane.rotation.y = Math.PI / 2;\n    group.add(pane);\n  }\n\n  return { object: group, obstacleRadius: Math.hypot(width + 0.5, depth + 0.5) / 2 };\n}\n\nexport interface TowerOptions {\n  seed?: number;\n  height?: number;\n  palette?: Palette;\n}\n\n/** A wooden watchtower: splayed legs, platform with railing, pyramid roof. */\nexport function createTower(options: TowerOptions = {}): Prop {\n  const rng = new Rng(options.seed ?? 1);\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const height = options.height ?? rng.range(4.2, 5.2);\n\n  const group = new Group();\n  group.name = 'tower';\n  const seed = options.seed ?? 1;\n  const wood = createSurface('wood', { color: palette.wood, seed });\n  const woodDark = createSurface('wood', { color: palette.woodDark, seed: seed + 9 });\n  const roof = createSurface('tile', { color: palette.roof, seed: seed + 17 });\n\n  const spread = 1.0;\n  for (const x of [-1, 1]) {\n    for (const z of [-1, 1]) {\n      const leg = new Mesh(new CylinderGeometry(0.09, 0.12, height, 6), woodDark);\n      leg.position.set(x * spread * 0.75, height / 2 - 0.6, z * spread * 0.75);\n      leg.rotation.z = -x * 0.1;\n      leg.rotation.x = z * 0.1;\n      group.add(leg);\n    }\n  }\n  // Cross-braces.\n  for (const level of [0.3, 0.62]) {\n    const brace = new Mesh(new BoxGeometry(spread * 2.1, 0.09, 0.07), wood);\n    brace.position.set(0, height * level, spread * 0.82 * (1 - level * 0.35));\n    brace.rotation.z = rng.pick([-0.5, 0.5]);\n    group.add(brace);\n    const braceSide = new Mesh(new BoxGeometry(0.07, 0.09, spread * 2.1), wood);\n    braceSide.position.set(spread * 0.82 * (1 - level * 0.35), height * level, 0);\n    braceSide.rotation.x = rng.pick([-0.5, 0.5]);\n    group.add(braceSide);\n  }\n\n  const platform = new Mesh(new BoxGeometry(spread * 2.2, 0.14, spread * 2.2), wood);\n  platform.position.y = height - 0.5;\n  group.add(platform);\n  for (const x of [-1, 1]) {\n    for (const z of [-1, 1]) {\n      const post = new Mesh(new BoxGeometry(0.08, 0.9, 0.08), woodDark);\n      post.position.set(x * spread * 1.0, height - 0.05, z * spread * 1.0);\n      group.add(post);\n    }\n  }\n  for (const [rx, rz, w, d] of [\n    [0, 1, spread * 2.1, 0.06],\n    [0, -1, spread * 2.1, 0.06],\n    [1, 0, 0.06, spread * 2.1],\n    [-1, 0, 0.06, spread * 2.1],\n  ] as const) {\n    const rail = new Mesh(new BoxGeometry(w, 0.07, d), wood);\n    rail.position.set(rx * spread, height + 0.28, rz * spread);\n    group.add(rail);\n  }\n\n  const cap = new Mesh(new CylinderGeometry(0, spread * 1.55, 1.0, 4), roof);\n  cap.position.y = height + 1.15;\n  cap.rotation.y = Math.PI / 4;\n  group.add(cap);\n\n  return { object: group, obstacleRadius: spread * 1.35 };\n}\n\nexport interface WellOptions {\n  seed?: number;\n  palette?: Palette;\n}\n\n/** A stone well: ring, posts, little gabled roof, hanging bucket. */\nexport function createWell(options: WellOptions = {}): Prop {\n  const rng = new Rng(options.seed ?? 1);\n  const palette = options.palette ?? DEFAULT_PALETTE;\n\n  const group = new Group();\n  group.name = 'well';\n  const seed = options.seed ?? 1;\n  // A little moss on the old rim, thin (high capUp) so only the very tops take.\n  const stone = createSurface('stone', {\n    color: rng.pick(palette.rock),\n    seed,\n    cap: 0.4,\n    capColor: 0x445a2e,\n    capUp: 0.5,\n  });\n  const wood = createSurface('wood', { color: palette.woodDark, seed: seed + 5 });\n  const roof = createSurface('tile', { color: palette.roof, seed: seed + 11 });\n\n  const ring = new Mesh(new CylinderGeometry(0.85, 0.95, 0.75, 10), stone);\n  ring.position.y = 0.375;\n  group.add(ring);\n  const inner = new Mesh(\n    new CylinderGeometry(0.62, 0.62, 0.05, 10),\n    new MeshStandardMaterial({ color: 0x16222e })\n  );\n  inner.position.y = 0.76;\n  group.add(inner);\n\n  for (const side of [-1, 1]) {\n    const post = new Mesh(new CylinderGeometry(0.06, 0.075, 1.9, 5), wood);\n    post.position.set(side * 0.72, 0.95, 0);\n    group.add(post);\n  }\n  const bar = new Mesh(new CylinderGeometry(0.045, 0.045, 1.5, 5), wood);\n  bar.rotation.z = Math.PI / 2;\n  bar.position.y = 1.72;\n  group.add(bar);\n\n  const cap = new Mesh(prismGeometry(2.0, 0.55, 0.65), roof);\n  cap.position.y = 1.86;\n  cap.rotation.y = Math.PI / 2;\n  group.add(cap);\n\n  const rope = new Mesh(new CylinderGeometry(0.012, 0.012, 0.6, 4), wood);\n  rope.position.y = 1.42;\n  group.add(rope);\n  const bucket = new Mesh(new CylinderGeometry(0.13, 0.1, 0.2, 7), wood);\n  bucket.position.y = 1.05;\n  group.add(bucket);\n\n  return { object: group, obstacleRadius: 1.0 };\n}\n\nexport interface RuinOptions {\n  seed?: number;\n  /** Footprint width. Default seeded 3.5–5. */\n  size?: number;\n  /** Moss reclaiming the up-facing stone. Default true. */\n  mossy?: boolean;\n  palette?: Palette;\n}\n\n/**\n * A ruined building: a partial rectangle of crumbling wall segments with\n * seeded gaps and heights, and tumbled blocks around the floor.\n */\nexport function createRuin(options: RuinOptions = {}): Prop {\n  const rng = new Rng(options.seed ?? 1);\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const size = options.size ?? rng.range(3.5, 5);\n  const depth = size * rng.range(0.7, 0.9);\n\n  const group = new Group();\n  group.name = 'ruin';\n  // Abandoned stone, reclaimed by moss on the up-facing tops and shoulders.\n  const mossy = options.mossy ?? true;\n  const stone = createSurface('stone', {\n    color: rng.pick(palette.rock),\n    seed: options.seed ?? 1,\n    ...(mossy ? { cap: 0.6, capColor: 0x415a2a, capUp: 0.3, capSharp: 0.32 } : {}),\n  });\n  stone.color.offsetHSL(0, 0, rng.range(-0.04, 0.02));\n\n  const thickness = 0.35;\n  // Wall runs: [centerX, centerZ, length, alongX]. Front wall mostly gone.\n  const runs: Array<[number, number, number, boolean]> = [\n    [0, -depth / 2, size, true],\n    [-size / 2, 0, depth, false],\n    [size / 2, 0, depth, false],\n    [size * 0.3, depth / 2, size * 0.35, true],\n  ];\n  for (const [cx, cz, length, alongX] of runs) {\n    const segments = Math.max(2, Math.round(length / 1.1));\n    const step = length / segments;\n    for (let i = 0; i < segments; i++) {\n      if (rng.next() < 0.22) continue; // collapsed gap\n      const height = rng.range(0.5, 2.2);\n      const wall = new Mesh(\n        new BoxGeometry(alongX ? step * 0.96 : thickness, height, alongX ? thickness : step * 0.96),\n        stone\n      );\n      const offset = -length / 2 + step * (i + 0.5);\n      wall.position.set(alongX ? cx + offset : cx, height / 2, alongX ? cz : cz + offset);\n      wall.rotation.y = rng.range(-0.03, 0.03);\n      group.add(wall);\n    }\n  }\n  // Tumbled blocks.\n  const blocks = rng.int(4, 7);\n  for (let i = 0; i < blocks; i++) {\n    const s = rng.range(0.25, 0.55);\n    const block = new Mesh(new BoxGeometry(s, s * rng.range(0.6, 1), s * rng.range(0.7, 1.2)), stone);\n    block.position.set(rng.range(-size * 0.6, size * 0.6), s * 0.3, rng.range(-depth * 0.6, depth * 0.7));\n    block.rotation.set(rng.range(-0.3, 0.3), rng.range(0, Math.PI), rng.range(-0.3, 0.3));\n    group.add(block);\n  }\n\n  return { object: group, obstacleRadius: Math.hypot(size, depth) / 2 };\n}\n","import { Color, MeshPhysicalMaterial, MeshStandardMaterial, Vector2, Vector3 } from 'three';\n\n/**\n * Procedural surface materials — the reason low-poly SCENA props can look\n * richer than a downloaded GLTF at a fraction of the bytes.\n *\n * A downloaded model ships baked albedo/normal/roughness textures (often\n * megabytes). Here the same detail — weathered stone, wood grain, mottled\n * plaster, thatch, tile — is generated in the shader from triplanar value\n * noise, so nothing is fetched and every prop is unique. The result is a\n * plain `MeshStandardMaterial` with an `onBeforeCompile` patch, so it keeps\n * three's full PBR lighting, shadows, fog, tone-mapping, and SCENA's\n * day/night emissive dimming — none of which a raw `ShaderMaterial` would.\n *\n * ```ts\n * const mat = createSurface('stone', { color: 0x8a8f98 });\n * mesh.material = mat;                       // that's it\n * ```\n *\n * Triplanar means no UVs are needed (a `BoxGeometry` has none worth using),\n * and because the noise is sampled in world space a wall built from several\n * abutting boxes reads as one continuous stone face with no visible seams.\n */\nexport type SurfaceKind =\n  | 'plaster'\n  | 'stone'\n  | 'wood'\n  | 'plank'\n  | 'thatch'\n  | 'tile'\n  | 'metal'\n  | 'dirt'\n  // Tier 1 — ground & terrain\n  | 'sand'\n  | 'gravel'\n  | 'mud'\n  | 'grass'\n  // Tier 1 — stone & masonry\n  | 'sandstone'\n  | 'granite'\n  | 'slate'\n  // Tier 1 — organic\n  | 'bark'\n  | 'leather'\n  | 'canvas'\n  | 'parchment'\n  | 'terracotta'\n  | 'bone'\n  // Tier 1 — metals\n  | 'rust'\n  | 'bronze'\n  | 'brass'\n  // Tier 2 — masonry tiling\n  | 'brick'\n  | 'cobblestone'\n  | 'ashlar'\n  | 'floortile'\n  | 'shingle'\n  // Tier 3 — cap & glow\n  | 'snow'\n  | 'moss'\n  | 'lava'\n  | 'crystal'\n  // Tier 4 — modern & machined\n  | 'concrete'\n  | 'paint'\n  | 'marble'\n  | 'terrazzo'\n  | 'steel'\n  | 'chrome'\n  | 'paintedMetal'\n  | 'corten'\n  | 'teak'\n  | 'porcelain'\n  | 'glaze'\n  | 'mosaic'\n  | 'parquet'\n  | 'patternedTile'\n  // Tier 5 — industrial\n  | 'corrugatedIron'\n  | 'asphalt'\n  | 'diamondPlate'\n  | 'galvanised'\n  | 'copperPatina'\n  | 'basalt'\n  // Tier 6 — physical (MeshPhysicalMaterial; see `physical`)\n  | 'velvet'\n  | 'silk'\n  | 'brushedMetal'\n  | 'nacre'\n  | 'ice'\n  | 'gemstone';\n\nexport interface SurfaceParams {\n  /**\n   * Natural base colour for this kind (hex int). Used when the caller passes\n   * no `color`, so `createSurface('sand')` looks like sand out of the box.\n   * A caller's `color` always wins.\n   */\n  baseColor?: number;\n  /** PBR base roughness. */\n  roughness: number;\n  /** PBR metalness. */\n  metalness: number;\n  /** Noise frequency in world units (higher = finer grain). */\n  scale: number;\n  /** How strongly the fine noise lightens/darkens the albedo (0–1). */\n  albedoVar: number;\n  /** Secondary colour blended into cavities, as a hex int. */\n  tint: number;\n  /** How much of `tint` shows in cavities (0–1). */\n  tintAmount: number;\n  /** Low-frequency cavity darkening — the baked-AO look (0–1). */\n  ao: number;\n  /** Surface relief strength (normal perturbation from the noise). */\n  bump: number;\n  /** Roughness variation added from the noise (0–1). */\n  roughVar: number;\n  /** Anisotropic grain strength for wood-like surfaces (0 = none). */\n  grain: number;\n  /** Grain ring frequency. */\n  grainScale: number;\n  /** World axis the grain runs along. */\n  grainAxis: Vector3;\n  /** flatShading default for this kind. */\n  flat: boolean;\n\n  // --- masonry tiling (all optional; `tile: 0` — the default — disables it) ---\n  /** Tiling strength (0 off, 1 full). Turns on the brick/tile grid. */\n  tile?: number;\n  /** Cell width in world metres (the length of a brick/tile). */\n  tileW?: number;\n  /** Cell height in world metres (the course height). */\n  tileH?: number;\n  /** Mortar-joint width in world metres. */\n  mortar?: number;\n  /** Row offset: 0 = aligned grid, 1 = half-cell running bond. */\n  bond?: number;\n  /** Cell profile: 0 = flat tiles, 1 = domed cobbles. */\n  round?: number;\n  /** Per-cell brightness/roughness jitter (0–1), so no two read alike. */\n  tileJitter?: number;\n  /** Mortar-joint colour, as a hex int. */\n  mortarColor?: number;\n  /** Groove relief strength for the joints (normal perturbation). */\n  tileRelief?: number;\n  /** Fraction of cells painted solid `tint` (mosaic accent chips, 0–1). */\n  tileTint?: number;\n  /** 1 = shear alternate column bands ±45° — chevron/herringbone parquet. */\n  chevron?: number;\n  /** Per-cell ring + dot motif painted in `tint` (patterned cement tiles). */\n  motif?: number;\n\n  // --- snow / moss cap (settles on up-facing faces; `cap: 0` disables it) ---\n  /** Cap strength (0 off, 1 full) — snow, moss, dust on the tops. */\n  cap?: number;\n  /** Cap colour, as a hex int (white snow, green moss…). */\n  capColor?: number;\n  /** How up-facing a face must be before the cap takes (0 everywhere … 1 only dead-level tops). */\n  capUp?: number;\n  /** Softness of the cap edge (bigger = more gradual). */\n  capSharp?: number;\n  /** Roughness inside the capped area (fresh snow reads matte/bright). */\n  capRough?: number;\n\n  // --- physical: light responses MeshStandardMaterial cannot produce -----\n  /**\n   * Build a `MeshPhysicalMaterial` instead of a `MeshStandardMaterial`.\n   *\n   * Some surfaces are defined by a light response the standard model has no\n   * term for at all — the retroreflective rim of velvet, the stretched\n   * highlight on silk, the thin-film hue shift on a shell, light going\n   * THROUGH ice. None of those can be faked with albedo and roughness.\n   *\n   * It costs: a physical material is a bigger shader, and `transmission` in\n   * particular makes three render the scene a second time into a buffer. Use\n   * it on OBJECTS, not on facades — which is exactly why `createGlass` fakes\n   * its glass rather than transmitting it.\n   */\n  physical?: boolean;\n  /** Sheen strength — velvet, felt, wool. The rim IS the material. */\n  sheen?: number;\n  /** Sheen colour, as a hex int. */\n  sheenColor?: number;\n  /** Sheen roughness. */\n  sheenRough?: number;\n  /**\n   * Anisotropy strength: a stretched highlight instead of a round one.\n   * Silk, brushed metal, carbon fibre. NOTE it follows the geometry's UVs,\n   * so a mesh with no UV attribute will not show it.\n   */\n  anisotropy?: number;\n  /** Which way the grain runs, in radians. */\n  anisotropyRotation?: number;\n  /** Thin-film iridescence — nacre, beetle shell, oil on water. */\n  iridescence?: number;\n  /** Iridescent film IOR. */\n  iridescenceIOR?: number;\n  /** Film thickness range in nanometres, [min, max]. */\n  iridescenceThickness?: [number, number];\n  /** Transmission: light passing THROUGH. Expensive — see `physical`. */\n  transmission?: number;\n  /** How thick the volume is, for transmission. */\n  thickness?: number;\n  /** Index of refraction (water 1.33, ice 1.31, glass 1.5, diamond 2.42). */\n  ior?: number;\n  /**\n   * Chromatic dispersion: how far apart the red and blue refractions fall.\n   *\n   * A real transparent solid has a DIFFERENT index of refraction for every\n   * wavelength, which is why a cut stone throws colour and a window does not.\n   * three refracts red, green and blue separately over\n   * `ior ± (ior - 1) * 0.025 * dispersion`, so the spread grows with the IOR\n   * as well — 0 is a plain glass, 10 on a diamond-grade IOR is a gemstone.\n   *\n   * Needs `transmission` and a non-zero `thickness`: with nothing passing\n   * through the volume there is nothing to split. Costs a third transmission\n   * sample per pixel.\n   */\n  dispersion?: number;\n  /** Colour light picks up on its way through, as a hex int. */\n  attenuationColor?: number;\n  /** How far light travels before it is fully attenuated, in metres. */\n  attenuationDistance?: number;\n\n  // --- ribs: parallel ridges (opt-in; `ribs: 0` — the default — is flat) ---\n  /** Ridge relief strength (0 off). Corrugated sheet, fluting, tread plate. */\n  ribs?: number;\n  /** Ridges per world metre. */\n  ribScale?: number;\n  /**\n   * 1 = turn the ridges through 90° on the face. Ribs are laid out in the\n   * FACE's own plane, not along a world axis: two world axes that differ in\n   * space collapse onto the same direction once projected onto a wall, which\n   * turned a crossed tread plate back into plain stripes.\n   */\n  ribTurn?: number;\n  /** 1 = a second set crossed over the first: the diamond studs of tread plate. */\n  ribCross?: number;\n\n  // --- aggregate: hard-edged chips (opt-in; `speck: 0` — the default — off) ---\n  /**\n   * Chip contrast. The rest of the shader runs on smooth fbm, which reads as\n   * mottling; asphalt is STONES IN TAR, and stones have edges.\n   */\n  speck?: number;\n  /** Chips per world metre. */\n  speckScale?: number;\n\n  // --- cells: warped Voronoi (opt-in; `cells: 0` — the default — off) ---\n  /**\n   * Cell strength. Irregular polygons: the columnar jointing of basalt and\n   * the zinc spangle on galvanised steel are the same function at two very\n   * different scales.\n   */\n  cells?: number;\n  /** Cells per world metre. */\n  cellScale?: number;\n  /** How dark and deep the seams between cells run (0–1). */\n  cellEdge?: number;\n  /** Per-cell brightness jitter (0–1). */\n  cellJitter?: number;\n  /**\n   * 1 = lay the cells out in PLAN and extrude them vertically, whatever the\n   * face is pointing at. That is what columnar jointing is — a crazy paving\n   * seen from above, pulled up into columns — and projecting it per-face\n   * instead gives blotches on a wall rather than columns in a cliff.\n   */\n  cellPlan?: number;\n\n  // --- crust: a mineral layer (opt-in; `crust: 0` — the default — off) ---\n  /**\n   * How much crust has grown: verdigris on copper, a rust bloom, lichen.\n   * It takes in the cavities and on the up-facing side, and it is a CRUST,\n   * not a tint — wherever it takes hold the metalness goes with it, because\n   * a mineral scab does not reflect like the metal underneath.\n   */\n  crust?: number;\n  /** Crust colour, as a hex int (verdigris green, rust orange…). */\n  crustColor?: number;\n  /** Roughness inside the crust. */\n  crustRough?: number;\n\n  // --- wear: water (opt-in; `wet: 0` — the default — is bone dry) ---\n  /**\n   * How wet the surface is: 0 dry, 1 running with water.\n   *\n   * This is a STATE, not a kind. Every one of the presets above can be\n   * rained on, and water behaves the same way on all of them — it darkens\n   * the albedo, collapses the roughness to a film, and, most of all, it\n   * POOLS: at a light wetting only the hollows and the mortar joints are\n   * dark and glossy, and the face only sheets over when it is properly\n   * raining.\n   */\n  wet?: number;\n  /**\n   * How well water clings to vertical faces: 0 = only the tops ever get\n   * wet, 1 = a wall wets as fast as a floor. Default 0.55 — rain falls\n   * down, so a sill soaks while the wall under it is merely damp. Sealed,\n   * shedding surfaces (glass, glaze, chrome) want less; things that wick\n   * (plaster, concrete, canvas) want more.\n   */\n  wetCling?: number;\n\n  // --- emissive glow (opt-in; `glow: 0` — the default — keeps it dark) ---\n  /** Glow strength added straight to emissive radiance (lava, crystal, runes). */\n  glow?: number;\n  /** Glow colour, as a hex int. */\n  glowColor?: number;\n  /** How much of the surface glows: low = only the deep cracks, high = most of it. */\n  glowThreshold?: number;\n}\n\nconst V = (x: number, y: number, z: number): Vector3 => new Vector3(x, y, z);\n\nexport const SURFACE_PRESETS: Record<SurfaceKind, SurfaceParams> = {\n  // Lime-washed cottage walls: soft warm mottle, gentle relief.\n  plaster: {\n    baseColor: 0xd9ccb0,\n    roughness: 0.92, metalness: 0, scale: 3.4, albedoVar: 0.14, tint: 0x9c8f74,\n    tintAmount: 0.12, ao: 0.18, bump: 0.15, roughVar: 0.1, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: true,\n  },\n  // Rough weathered stone: strong cavity AO + mossy tint, pitted relief.\n  stone: {\n    baseColor: 0x8a8f98,\n    roughness: 0.96, metalness: 0, scale: 2.6, albedoVar: 0.26, tint: 0x5c6b44,\n    tintAmount: 0.16, ao: 0.34, bump: 0.42, roughVar: 0.14, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: true,\n  },\n  // Structural timber: pronounced grain rings darkening the albedo.\n  wood: {\n    baseColor: 0x8a6642,\n    roughness: 0.82, metalness: 0, scale: 5.5, albedoVar: 0.12, tint: 0x3a2a1c,\n    tintAmount: 0.14, ao: 0.16, bump: 0.12, roughVar: 0.12, grain: 0.55,\n    grainScale: 3.2, grainAxis: V(0, 1, 0), flat: true,\n  },\n  // Sawn planks: finer, straighter grain, a touch smoother.\n  plank: {\n    baseColor: 0x9a7a52,\n    roughness: 0.78, metalness: 0, scale: 6.5, albedoVar: 0.1, tint: 0x40301f,\n    tintAmount: 0.1, ao: 0.12, bump: 0.1, roughVar: 0.1, grain: 0.4,\n    grainScale: 5.0, grainAxis: V(1, 0, 0), flat: true,\n  },\n  // Straw thatch: busy fibrous streaking, high roughness, deep shadowing.\n  thatch: {\n    baseColor: 0xb39a5c,\n    roughness: 0.98, metalness: 0, scale: 9.0, albedoVar: 0.3, tint: 0x6a5324,\n    tintAmount: 0.2, ao: 0.28, bump: 0.3, roughVar: 0.08, grain: 0.35,\n    grainScale: 8.0, grainAxis: V(0, 0, 1), flat: true,\n  },\n  // Clay roof tiles: regular ridged rows, warm cavity tint.\n  tile: {\n    baseColor: 0xa8563e,\n    roughness: 0.7, metalness: 0, scale: 4.0, albedoVar: 0.14, tint: 0x6e2f22,\n    tintAmount: 0.16, ao: 0.24, bump: 0.34, roughVar: 0.1, grain: 0.6,\n    grainScale: 6.0, grainAxis: V(1, 0, 0), flat: true,\n  },\n  // Aged iron/bronze: mild mottle, low roughness variance, metallic.\n  metal: {\n    baseColor: 0x3d4451,\n    roughness: 0.52, metalness: 0.85, scale: 4.5, albedoVar: 0.16, tint: 0x2a2118,\n    tintAmount: 0.18, ao: 0.22, bump: 0.16, roughVar: 0.2, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: true,\n  },\n  // Turf. There is a `createGrass` prop for blades you can see individually;\n  // this is the ground they stand in, and the ground on its own from any\n  // distance. `moss` is NOT this — it is a grey-green cap that grows ON stone,\n  // and reaching for it as a lawn gives a field the colour of a damp wall.\n  // (Written after doing exactly that.)\n  grass: {\n    baseColor: 0x5c7a3c,\n    roughness: 0.97, metalness: 0, scale: 5.5, albedoVar: 0.26, tint: 0x33471f,\n    tintAmount: 0.24, ao: 0.24, bump: 0.22, roughVar: 0.08, grain: 0.22,\n    grainScale: 11.0, grainAxis: V(0, 0, 1), flat: true,\n  },\n  // Packed earth: broad soft variation, strong low-frequency patches.\n  dirt: {\n    baseColor: 0x8a7a58,\n    roughness: 1.0, metalness: 0, scale: 2.0, albedoVar: 0.22, tint: 0x4a3524,\n    tintAmount: 0.2, ao: 0.3, bump: 0.1, roughVar: 0.05, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: false,\n  },\n\n  // --- Tier 1: ground & terrain -----------------------------------------\n  // Fine granular sand with soft wind ripples; smooth-shaded dunes.\n  sand: {\n    baseColor: 0xcbb98a,\n    roughness: 1.0, metalness: 0, scale: 7.0, albedoVar: 0.16, tint: 0x9c8048,\n    tintAmount: 0.14, ao: 0.14, bump: 0.14, roughVar: 0.06, grain: 0.18,\n    grainScale: 3.0, grainAxis: V(1, 0, 0), flat: false,\n  },\n  // Loose gravel / riverbed: chunky faceted stones, strong relief.\n  gravel: {\n    baseColor: 0x9a948a,\n    roughness: 0.95, metalness: 0, scale: 5.5, albedoVar: 0.3, tint: 0x605a4f,\n    tintAmount: 0.18, ao: 0.32, bump: 0.5, roughVar: 0.16, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: true,\n  },\n  // Wet churned mud: darkened patches with a damp sheen (lower roughness).\n  mud: {\n    baseColor: 0x4a3826,\n    roughness: 0.6, metalness: 0, scale: 2.4, albedoVar: 0.2, tint: 0x241708,\n    tintAmount: 0.3, ao: 0.34, bump: 0.16, roughVar: 0.24, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: false,\n  },\n\n  // --- Tier 1: stone & masonry ------------------------------------------\n  // Warm sandstone: soft, faintly streaked, gentle relief — temples, cliffs.\n  sandstone: {\n    baseColor: 0xc9a06a,\n    roughness: 0.9, metalness: 0, scale: 3.4, albedoVar: 0.18, tint: 0x8a6a3c,\n    tintAmount: 0.16, ao: 0.22, bump: 0.24, roughVar: 0.1, grain: 0.22,\n    grainScale: 2.4, grainAxis: V(0, 1, 0), flat: true,\n  },\n  // Speckled granite: fine mineral fleck, low relief, a hint of polish.\n  granite: {\n    baseColor: 0x8e8a94,\n    roughness: 0.58, metalness: 0, scale: 9.0, albedoVar: 0.34, tint: 0x45414d,\n    tintAmount: 0.14, ao: 0.14, bump: 0.12, roughVar: 0.2, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: true,\n  },\n  // Dark slate: blue-grey cleavage plates, low roughness, subtle streaks.\n  slate: {\n    baseColor: 0x50565e,\n    roughness: 0.55, metalness: 0, scale: 3.0, albedoVar: 0.14, tint: 0x2c3540,\n    tintAmount: 0.2, ao: 0.2, bump: 0.18, roughVar: 0.12, grain: 0.2,\n    grainScale: 3.0, grainAxis: V(1, 0, 0), flat: true,\n  },\n\n  // --- Tier 1: organic --------------------------------------------------\n  // Tree bark: deep vertical ridges (grain rings around the trunk axis).\n  bark: {\n    baseColor: 0x5a4535,\n    roughness: 0.92, metalness: 0, scale: 6.0, albedoVar: 0.2, tint: 0x2a1c10,\n    tintAmount: 0.2, ao: 0.26, bump: 0.45, roughVar: 0.12, grain: 0.7,\n    grainScale: 5.5, grainAxis: V(0, 1, 0), flat: true,\n  },\n  // Leather / hide: soft mottled grain with a gentle sheen — straps, armour.\n  leather: {\n    baseColor: 0x6a4630,\n    roughness: 0.62, metalness: 0, scale: 5.0, albedoVar: 0.16, tint: 0x2e1a0f,\n    tintAmount: 0.22, ao: 0.2, bump: 0.18, roughVar: 0.12, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: false,\n  },\n  // Woven canvas: fine directional weave, matte — tents, sails, sacks.\n  canvas: {\n    baseColor: 0xcabd9c,\n    roughness: 0.95, metalness: 0, scale: 11.0, albedoVar: 0.14, tint: 0x8a7a5c,\n    tintAmount: 0.12, ao: 0.14, bump: 0.12, roughVar: 0.06, grain: 0.3,\n    grainScale: 12.0, grainAxis: V(1, 0, 0), flat: false,\n  },\n  // Aged parchment: near-white with soft foxing stains — signs, scrolls.\n  parchment: {\n    baseColor: 0xe0d4b0,\n    roughness: 0.9, metalness: 0, scale: 3.0, albedoVar: 0.12, tint: 0x9a8558,\n    tintAmount: 0.18, ao: 0.16, bump: 0.08, roughVar: 0.06, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: false,\n  },\n  // Unglazed terracotta: warm clay, smooth, low relief — pots, urns.\n  terracotta: {\n    baseColor: 0xb5623a,\n    roughness: 0.72, metalness: 0, scale: 4.0, albedoVar: 0.12, tint: 0x7a3a20,\n    tintAmount: 0.16, ao: 0.16, bump: 0.14, roughVar: 0.08, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: false,\n  },\n  // Weathered bone / ivory: off-white with cavity staining — ossuaries, décor.\n  bone: {\n    baseColor: 0xdcd2ba,\n    roughness: 0.55, metalness: 0, scale: 6.0, albedoVar: 0.14, tint: 0x8a7f66,\n    tintAmount: 0.2, ao: 0.22, bump: 0.12, roughVar: 0.1, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: true,\n  },\n\n  // --- Tier 1: metals ---------------------------------------------------\n  // Rusted iron: patchy orange corrosion, part-metallic, high roughness spread.\n  rust: {\n    baseColor: 0x8a4a2c,\n    roughness: 0.85, metalness: 0.25, scale: 4.0, albedoVar: 0.28, tint: 0x5a2a12,\n    tintAmount: 0.3, ao: 0.26, bump: 0.28, roughVar: 0.3, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: true,\n  },\n  // Bronze: warm dark metal with patina in the cavities — bells, statues.\n  bronze: {\n    baseColor: 0x9a6a3a,\n    roughness: 0.44, metalness: 0.9, scale: 4.5, albedoVar: 0.16, tint: 0x3a2410,\n    tintAmount: 0.24, ao: 0.22, bump: 0.16, roughVar: 0.18, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: true,\n  },\n  // Brass: brighter warm metal, smoother and shinier — fittings, instruments.\n  brass: {\n    baseColor: 0xc9a24a,\n    roughness: 0.34, metalness: 0.95, scale: 5.0, albedoVar: 0.12, tint: 0x6a4a12,\n    tintAmount: 0.16, ao: 0.16, bump: 0.1, roughVar: 0.14, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: true,\n  },\n\n  // --- Tier 2: masonry tiling -------------------------------------------\n  // Fired brick in running bond: long thin courses, pale mortar, bricks that\n  // each weather a little differently.\n  brick: {\n    baseColor: 0x9e4a34,\n    roughness: 0.86, metalness: 0, scale: 6.0, albedoVar: 0.14, tint: 0x5a2418,\n    tintAmount: 0.16, ao: 0.2, bump: 0.1, roughVar: 0.12, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: true,\n    tile: 1, tileW: 0.25, tileH: 0.085, mortar: 0.014, bond: 1, round: 0,\n    tileJitter: 0.18, mortarColor: 0xb3a892, tileRelief: 0.06,\n  },\n  // Rounded cobblestones: small domed setts, wide earthy joints, heavy\n  // per-stone variation — streets and courtyards.\n  cobblestone: {\n    baseColor: 0x8a8f98,\n    roughness: 0.9, metalness: 0, scale: 5.0, albedoVar: 0.2, tint: 0x4a4436,\n    tintAmount: 0.18, ao: 0.28, bump: 0.2, roughVar: 0.14, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: true,\n    tile: 1, tileW: 0.17, tileH: 0.15, mortar: 0.03, bond: 1, round: 1,\n    tileJitter: 0.24, mortarColor: 0x35322b, tileRelief: 0.13,\n  },\n  // Ashlar: large squared blocks, tight fine joints — castle and keep walls.\n  ashlar: {\n    baseColor: 0xb9b2a4,\n    roughness: 0.9, metalness: 0, scale: 3.0, albedoVar: 0.16, tint: 0x7a725f,\n    tintAmount: 0.16, ao: 0.2, bump: 0.12, roughVar: 0.1, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: true,\n    tile: 1, tileW: 0.55, tileH: 0.32, mortar: 0.02, bond: 0.5, round: 0,\n    tileJitter: 0.1, mortarColor: 0x857e6f, tileRelief: 0.05,\n  },\n  // Floor tiles: an aligned grid of square flags, dark grout, low relief —\n  // halls and plazas.\n  floortile: {\n    baseColor: 0x6a6e72,\n    roughness: 0.5, metalness: 0, scale: 4.0, albedoVar: 0.12, tint: 0x33363a,\n    tintAmount: 0.16, ao: 0.16, bump: 0.08, roughVar: 0.1, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: true,\n    tile: 1, tileW: 0.4, tileH: 0.4, mortar: 0.014, bond: 0, round: 0,\n    tileJitter: 0.12, mortarColor: 0x2a2a2c, tileRelief: 0.045,\n  },\n  // Wooden shingles: overlapping courses with grain, deep shadow lines —\n  // roofs and spires.\n  shingle: {\n    baseColor: 0x6b4a33,\n    roughness: 0.85, metalness: 0, scale: 6.0, albedoVar: 0.16, tint: 0x2e2012,\n    tintAmount: 0.18, ao: 0.24, bump: 0.12, roughVar: 0.12, grain: 0.32,\n    grainScale: 6.0, grainAxis: V(0, 1, 0), flat: true,\n    tile: 1, tileW: 0.2, tileH: 0.13, mortar: 0.012, bond: 1, round: 0,\n    tileJitter: 0.2, mortarColor: 0x241811, tileRelief: 0.09,\n  },\n\n  // --- Tier 3: cap & glow -----------------------------------------------\n  // Snow settled on cold rock: white on every up-facing face, grey stone on\n  // the sides, its edge broken by the noise. Cap works on any surface.\n  snow: {\n    baseColor: 0x9aa0a8,\n    roughness: 0.9, metalness: 0, scale: 4.0, albedoVar: 0.14, tint: 0x6a7280,\n    tintAmount: 0.14, ao: 0.2, bump: 0.24, roughVar: 0.1, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: true,\n    cap: 0.95, capColor: 0xf4f8fc, capUp: 0.12, capSharp: 0.32, capRough: 0.9,\n  },\n  // Moss creeping over a boulder: grey stone with green growth on the tops\n  // and shoulders, thicker (lower capUp) than snow.\n  moss: {\n    baseColor: 0x8a8f88,\n    roughness: 0.94, metalness: 0, scale: 3.5, albedoVar: 0.2, tint: 0x4a5240,\n    tintAmount: 0.16, ao: 0.28, bump: 0.34, roughVar: 0.12, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: true,\n    cap: 0.74, capColor: 0x40592a, capUp: 0.34, capSharp: 0.3, capRough: 0.96,\n  },\n  // Cooling lava: dark basalt crust with molten orange glowing up through the\n  // cracks. The glow burns constant, day or night.\n  lava: {\n    baseColor: 0x2a1712,\n    roughness: 0.88, metalness: 0, scale: 3.2, albedoVar: 0.18, tint: 0x120806,\n    tintAmount: 0.26, ao: 0.34, bump: 0.5, roughVar: 0.14, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: true,\n    glow: 2.6, glowColor: 0xff5a1e, glowThreshold: 0.3,\n  },\n  // Glowing crystal: faceted blue mineral lit from within — most of the face\n  // emits, the deepest cavities darkest.\n  crystal: {\n    baseColor: 0x3a5c8a,\n    roughness: 0.22, metalness: 0, scale: 5.0, albedoVar: 0.14, tint: 0x1a2f52,\n    tintAmount: 0.2, ao: 0.16, bump: 0.3, roughVar: 0.1, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: true,\n    glow: 1.5, glowColor: 0x6fd6ff, glowThreshold: 0.72,\n  },\n\n  // --- Tier 4: modern & machined ----------------------------------------\n  // Fair-faced concrete: near-even grey with fine mottle and shutter-panel\n  // joint lines (the tiling grid, dialed way down) — the modern wall.\n  concrete: {\n    baseColor: 0xb5b3ac,\n    roughness: 0.88, metalness: 0, scale: 3.0, albedoVar: 0.08, tint: 0x8a887f,\n    tintAmount: 0.08, ao: 0.12, bump: 0.06, roughVar: 0.08, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: false,\n    tile: 1, tileW: 1.2, tileH: 0.6, mortar: 0.006, bond: 0, round: 0,\n    tileJitter: 0.05, mortarColor: 0x9a9891, tileRelief: 0.03,\n  },\n  // Modern painted render: almost flat, just enough micro-variation to be a\n  // material at all. Colour it anything; satin sheen.\n  paint: {\n    baseColor: 0xdedbd2,\n    roughness: 0.6, metalness: 0, scale: 6.0, albedoVar: 0.04, tint: 0xb8b4a8,\n    tintAmount: 0.05, ao: 0.05, bump: 0.02, roughVar: 0.05, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: false,\n  },\n  // Polished marble: near-white slab, dark warped veins (the grain rings at a\n  // very low frequency), glossy — lobby floors and counters.\n  marble: {\n    baseColor: 0xe8e6e0,\n    roughness: 0.22, metalness: 0, scale: 1.6, albedoVar: 0.08, tint: 0x7a8494,\n    tintAmount: 0.12, ao: 0.08, bump: 0.04, roughVar: 0.08, grain: 0.5,\n    grainScale: 0.7, grainAxis: V(0.35, 1, 0.2), flat: false,\n  },\n  // Terrazzo: a cement field packed with tiny per-cell chips, a share of them\n  // in the accent tint — the classic speckled floor.\n  terrazzo: {\n    baseColor: 0xd8d2c6,\n    roughness: 0.35, metalness: 0, scale: 10.0, albedoVar: 0.1, tint: 0x6a604f,\n    tintAmount: 0.04, ao: 0.06, bump: 0.03, roughVar: 0.08, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: false,\n    tile: 1, tileW: 0.045, tileH: 0.045, mortar: 0.01, bond: 0, round: 1,\n    tileJitter: 0.35, mortarColor: 0xcfc9bd, tileRelief: 0.02, tileTint: 0.18,\n  },\n  // Brushed stainless steel: fine directional streaks (the grain machinery\n  // pointed at metal), cool and semi-gloss — railings, kick plates.\n  steel: {\n    baseColor: 0xaeb4bc,\n    roughness: 0.38, metalness: 0.92, scale: 8.0, albedoVar: 0.06, tint: 0x6a707a,\n    tintAmount: 0.08, ao: 0.06, bump: 0.03, roughVar: 0.18, grain: 0.3,\n    grainScale: 26.0, grainAxis: V(1, 0, 0), flat: false,\n  },\n  // Chrome: near-mirror metal — fittings and trim. (Stylized: no envmap, the\n  // lighting rig does the selling.)\n  chrome: {\n    baseColor: 0xc9ced4,\n    roughness: 0.08, metalness: 1.0, scale: 5.0, albedoVar: 0.04, tint: 0x8a9098,\n    tintAmount: 0.05, ao: 0.04, bump: 0.01, roughVar: 0.05, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: false,\n  },\n  // Powder-coated metal: coloured semi-gloss with a whisper of orange peel —\n  // gates, frames, railings. Colour it from the palette.\n  paintedMetal: {\n    baseColor: 0x44505c,\n    roughness: 0.42, metalness: 0.35, scale: 14.0, albedoVar: 0.04, tint: 0x222a30,\n    tintAmount: 0.06, ao: 0.06, bump: 0.04, roughVar: 0.08, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: false,\n  },\n  // Corten weathering steel: the even architectural oxide bloom, warmer and\n  // calmer than 'rust' — feature walls and planters.\n  corten: {\n    baseColor: 0x9a5a34,\n    roughness: 0.82, metalness: 0.18, scale: 3.2, albedoVar: 0.16, tint: 0x5a2e16,\n    tintAmount: 0.22, ao: 0.16, bump: 0.1, roughVar: 0.18, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: false,\n  },\n  // Oiled teak: warm decking/furniture wood under a varnish sheen.\n  teak: {\n    baseColor: 0x8a5c36,\n    roughness: 0.3, metalness: 0, scale: 6.0, albedoVar: 0.08, tint: 0x3c2614,\n    tintAmount: 0.12, ao: 0.1, bump: 0.05, roughVar: 0.08, grain: 0.45,\n    grainScale: 4.5, grainAxis: V(1, 0, 0), flat: false,\n  },\n  // Large-format porcelain: big glossy slabs, hairline grout, offset courses.\n  porcelain: {\n    baseColor: 0xd9d6cf,\n    roughness: 0.18, metalness: 0, scale: 3.0, albedoVar: 0.05, tint: 0x9a968c,\n    tintAmount: 0.06, ao: 0.08, bump: 0.03, roughVar: 0.06, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: false,\n    tile: 1, tileW: 1.2, tileH: 0.6, mortar: 0.005, bond: 0.5, round: 0,\n    tileJitter: 0.06, mortarColor: 0xb0aca2, tileRelief: 0.03,\n  },\n  // Vitreous glaze: sanitaryware. Note it is NOT 'porcelain' — that preset is\n  // large-format porcelain FLOOR TILE, complete with grout, and a bath shell\n  // built from it comes out looking like a tiled box rather than one fired\n  // piece. Glaze is a single unbroken skin: glossy, almost no variation, and\n  // no tiling at all.\n  glaze: {\n    baseColor: 0xf2f0ea,\n    roughness: 0.12, metalness: 0, scale: 5.0, albedoVar: 0.02, tint: 0xc8c6be,\n    tintAmount: 0.05, ao: 0.07, bump: 0.008, roughVar: 0.03, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: false,\n  },\n  // Glass mosaic: tiny gridded tesserae, strong per-chip variation, a share of\n  // accent-tint chips, pale grout — pools and feature walls.\n  mosaic: {\n    baseColor: 0x3f7fae,\n    roughness: 0.25, metalness: 0, scale: 8.0, albedoVar: 0.08, tint: 0x1d4e74,\n    tintAmount: 0.05, ao: 0.08, bump: 0.04, roughVar: 0.1, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: false,\n    tile: 1, tileW: 0.055, tileH: 0.055, mortar: 0.006, bond: 0, round: 0,\n    tileJitter: 0.3, mortarColor: 0xd8d4c8, tileRelief: 0.05, tileTint: 0.3,\n  },\n  // Chevron parquet: narrow varnished planks laid in alternating ±45° bands.\n  parquet: {\n    baseColor: 0x9a6b40,\n    roughness: 0.32, metalness: 0, scale: 6.0, albedoVar: 0.07, tint: 0x4a2f18,\n    tintAmount: 0.1, ao: 0.08, bump: 0.04, roughVar: 0.08, grain: 0.3,\n    grainScale: 7.0, grainAxis: V(1, 0, 0), flat: false,\n    tile: 1, tileW: 0.5, tileH: 0.09, mortar: 0.006, bond: 0, round: 0,\n    tileJitter: 0.14, mortarColor: 0x5a3b22, tileRelief: 0.04, chevron: 1,\n  },\n  // Patterned cement tiles: a cream field, each tile stamped with a ring-and-\n  // dot motif in the tint colour — verandas, courtyards, feature floors.\n  patternedTile: {\n    baseColor: 0xdcd7c9,\n    roughness: 0.3, metalness: 0, scale: 3.0, albedoVar: 0.05, tint: 0x365f74,\n    tintAmount: 0.04, ao: 0.08, bump: 0.03, roughVar: 0.06, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: false,\n    tile: 1, tileW: 0.33, tileH: 0.33, mortar: 0.008, bond: 0, round: 0,\n    tileJitter: 0.05, mortarColor: 0xa9a396, tileRelief: 0.035, motif: 0.9,\n  },\n\n  // --- Tier 5: industrial ------------------------------------------------\n  // Sheet steel rolled into a wave, galvanised, and left out in the rain.\n  // The corrugation is the ONLY reason a flat plane reads as a roof from\n  // fifty metres, and it is why this is the most recognisable industrial\n  // material there is: a shanty wall, a barn, a lock-up, a site hoarding.\n  corrugatedIron: {\n    baseColor: 0x9aa2a6,\n    roughness: 0.58, metalness: 0.5, scale: 9, albedoVar: 0.1, tint: 0x6a5545,\n    tintAmount: 0.16, ao: 0.16, bump: 0.35, roughVar: 0.18, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: false,\n    ribs: 1, ribScale: 5,\n    // Rust takes in the valleys, where the water sits — but a sheet that is\n    // more rust than iron reads as rust, not as a roof.\n    crust: 0.3, crustColor: 0x8a4a26, crustRough: 0.95,\n  },\n  // Stones in tar. The chips are the point: a smooth mottle is mud, and\n  // the reason a road reads as a road at all is that it is visibly made of\n  // gravel somebody poured glue over.\n  asphalt: {\n    baseColor: 0x3b3b3e,\n    roughness: 0.93, metalness: 0, scale: 14, albedoVar: 0.1, tint: 0x1e1e20,\n    tintAmount: 0.18, ao: 0.2, bump: 0.4, roughVar: 0.1, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: false,\n    speck: 0.42, speckScale: 40,\n  },\n  // Tread plate: raised studs in a diamond lattice, so a gantry floor has\n  // grip and a stair tread reads as a stair tread.\n  diamondPlate: {\n    baseColor: 0x8d9399,\n    roughness: 0.44, metalness: 0.55, scale: 12, albedoVar: 0.05, tint: 0x5c6166,\n    tintAmount: 0.1, ao: 0.1, bump: 0.5, roughVar: 0.1, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: false,\n    ribs: 1, ribScale: 6, ribCross: 1,\n  },\n  // THE SPANGLE is the whole material: hot-dip galvanising freezes into\n  // visible zinc crystals, each catching the light its own way, and no\n  // other metal has that.\n  galvanised: {\n    baseColor: 0xa9b1b5,\n    roughness: 0.46, metalness: 0.5, scale: 3.5, albedoVar: 0.04, tint: 0x7d868b,\n    tintAmount: 0.06, ao: 0.05, bump: 0.1, roughVar: 0.05, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: false,\n    // Grains you can SEE, each catching the light its own way. Real spangle\n    // is millimetres, but a crystal too small to resolve is not a crystal —\n    // it is per-pixel noise, and on a metal that is a sparkling mess.\n    cells: 1, cellScale: 6, cellEdge: 0.22, cellJitter: 0.4,\n  },\n  // Copper does not stay copper. Verdigris grows in the cavities and on\n  // the up-facing side, and where it grows the metal is gone — which is\n  // why a green roof is matte and a copper one is not.\n  copperPatina: {\n    baseColor: 0x9c5b34,\n    roughness: 0.42, metalness: 0.75, scale: 6, albedoVar: 0.08, tint: 0x6b3a1f,\n    tintAmount: 0.12, ao: 0.14, bump: 0.2, roughVar: 0.12, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: false,\n    crust: 0.95, crustColor: 0x4fa88a, crustRough: 0.92,\n  },\n  // Columnar jointing: lava that cooled slowly and cracked into polygons,\n  // then stood up as columns. Laid out in PLAN and extruded, because that\n  // is what the rock actually did.\n  basalt: {\n    baseColor: 0x54585e,\n    roughness: 0.86, metalness: 0.04, scale: 3, albedoVar: 0.06, tint: 0x2b2e33,\n    tintAmount: 0.12, ao: 0.16, bump: 0.5, roughVar: 0.1, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: true,\n    cells: 1, cellScale: 3.2, cellEdge: 0.85, cellJitter: 0.16, cellPlan: 1,\n  },\n\n  // --- Tier 6: physical --------------------------------------------------\n  // Each of these is defined by a light response the standard model has no\n  // term for. They are the one part of the catalogue that costs more than a\n  // MeshStandardMaterial, and they are worth it only because nothing else\n  // gets you there.\n\n  // THE RIM IS THE MATERIAL. Velvet is dark where you look straight at it\n  // and bright at every grazing edge, because the pile scatters sideways —\n  // and no amount of albedo and roughness produces that.\n  velvet: {\n    baseColor: 0x6d1730,\n    roughness: 0.92, metalness: 0, scale: 7, albedoVar: 0.05, tint: 0x3a0a19,\n    tintAmount: 0.14, ao: 0.12, bump: 0.015, roughVar: 0.03, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: false,\n    physical: true, sheen: 1, sheenColor: 0xd8869c, sheenRough: 0.32,\n  },\n  // A stretched highlight instead of a round one: the thread runs one way,\n  // so the light does too.\n  silk: {\n    baseColor: 0xc9b7d8,\n    roughness: 0.2, metalness: 0.05, scale: 6, albedoVar: 0.04, tint: 0x8f7fa6,\n    tintAmount: 0.08, ao: 0.06, bump: 0.01, roughVar: 0.02, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: false,\n    physical: true, anisotropy: 0.9, anisotropyRotation: 0,\n    sheen: 0.35, sheenColor: 0xffffff, sheenRough: 0.2,\n  },\n  // The linisher went one way. Brushed aluminium, a kitchen front, a lift\n  // door — the streak is the only thing separating it from plain steel.\n  brushedMetal: {\n    baseColor: 0xb4b9be,\n    roughness: 0.34, metalness: 0.7, scale: 5, albedoVar: 0.02, tint: 0x8b9196,\n    tintAmount: 0.04, ao: 0.03, bump: 0.008, roughVar: 0.02, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: false,\n    physical: true, anisotropy: 0.95, anisotropyRotation: Math.PI / 2,\n  },\n  // Thin-film interference: the hue depends on how thick the film is and\n  // which way you are looking, which is why a shell has no fixed colour.\n  nacre: {\n    baseColor: 0xdcd8d0,\n    roughness: 0.12, metalness: 0.2, scale: 4, albedoVar: 0.04, tint: 0xa8b0c0,\n    tintAmount: 0.18, ao: 0.05, bump: 0.02, roughVar: 0.02, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: false,\n    // Low metalness on purpose. Iridescence is strongest over a metallic\n    // F0, but a metal with no environment map to reflect renders as dead\n    // grey — so the film sits over a pale pearl instead, and a thick one\n    // (a high IOR) makes the highlight visibly COLOURED rather than white.\n    physical: true, iridescence: 1, iridescenceIOR: 2.4,\n    iridescenceThickness: [300, 900],\n  },\n  // Light goes THROUGH. The cells are the fracture planes inside it — ice\n  // is not clear, it is full of the cracks it froze around.\n  ice: {\n    baseColor: 0xcfe8f2,\n    roughness: 0.13, metalness: 0, scale: 2.5, albedoVar: 0.05, tint: 0x7fb4cc,\n    tintAmount: 0.14, ao: 0.08, bump: 0.06, roughVar: 0.03, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: false,\n    cells: 1, cellScale: 1.8, cellEdge: 0.22, cellJitter: 0.08,\n    physical: true, transmission: 0.85, thickness: 0.5, ior: 1.31,\n    attenuationColor: 0x9fd4e8, attenuationDistance: 1.4,\n  },\n  // WHY A STONE IS CUT AT ALL. Glass and diamond are both transparent; the\n  // difference you can see across a room is that diamond has a different\n  // index of refraction for every wavelength, so the white light that goes\n  // in comes out separated. Facets exist to make that happen more often.\n  //\n  // Both halves of that are here. `dispersion` does the splitting — and the\n  // spread scales with the IOR, so a gem-grade 2.2 throws far more colour\n  // than a window's 1.5 at the same setting. `flat: true` does the facets:\n  // flat shading on a low-poly solid IS a cut stone, and the coarse cells\n  // are the inclusions that stop it looking like moulded acrylic.\n  gemstone: {\n    baseColor: 0xe6f4ff,\n    roughness: 0.03, metalness: 0, scale: 3.5, albedoVar: 0.03, tint: 0x8fc2e8,\n    tintAmount: 0.08, ao: 0.02, bump: 0, roughVar: 0.015, grain: 0,\n    grainScale: 1, grainAxis: V(0, 1, 0), flat: true,\n    cells: 0.5, cellScale: 2.2, cellEdge: 0.12, cellJitter: 0.25,\n    // A long attenuation distance on purpose. The colour is supposed to come\n    // OUT of the stone, and one that swallows the light on its way through\n    // is a dark blob whatever the IOR is doing.\n    physical: true, transmission: 1, thickness: 0.55, ior: 2.2, dispersion: 14,\n    attenuationColor: 0xb8e4ff, attenuationDistance: 2.4,\n  },\n};\n\nexport interface SurfaceOptions extends Partial<SurfaceParams> {\n  /** Base colour (hex int or three Color). Defaults to a neutral grey. */\n  color?: number | Color;\n  /**\n   * Seed offset so two props with the same colour still weather\n   * differently. Any number; shifts the noise field.\n   */\n  seed?: number;\n}\n\n// ---- GLSL --------------------------------------------------------------\n\nconst NOISE_GLSL = /* glsl */ `\n// World-space coordinates get large (props far from the origin, plus the seed\n// offset), and mobile GPUs default the fragment stage to mediump — where\n// fract() of a big number loses precision and the noise/grain visibly swims.\n// Force highp on the world varyings and the noise maths so it stays put.\nvarying highp vec3 vSurfWorldPos;\nvarying highp vec3 vSurfWorldNormal;\nuniform highp vec3 uSurfSeed;\nuniform float uSurfScale;\nuniform float uSurfAlbedoVar;\nuniform vec3  uSurfTint;\nuniform float uSurfTintAmount;\nuniform float uSurfAO;\nuniform float uSurfBump;\nuniform float uSurfRoughVar;\nuniform float uSurfGrain;\nuniform float uSurfGrainScale;\nuniform vec3  uSurfGrainAxis;\nuniform float uSurfTile;\nuniform highp vec2 uSurfTileSize;\nuniform float uSurfMortar;\nuniform float uSurfTileBond;\nuniform float uSurfTileRound;\nuniform float uSurfTileJitter;\nuniform vec3  uSurfMortarColor;\nuniform float uSurfTileRelief;\nuniform float uSurfTileTint;\nuniform float uSurfTileChevron;\nuniform float uSurfTileMotif;\nuniform float uSurfCap;\nuniform vec3  uSurfCapColor;\nuniform float uSurfCapUp;\nuniform float uSurfCapSharp;\nuniform float uSurfCapRough;\nuniform float uSurfGlow;\nuniform vec3  uSurfGlowColor;\nuniform float uSurfGlowThresh;\nuniform float uSurfWet;\nuniform float uSurfWetCling;\nuniform float uSurfRibs;\nuniform float uSurfRibScale;\nuniform float uSurfRibTurn;\nuniform float uSurfRibCross;\nuniform float uSurfSpeck;\nuniform float uSurfSpeckScale;\nuniform float uSurfCells;\nuniform float uSurfCellScale;\nuniform float uSurfCellEdge;\nuniform float uSurfCellJitter;\nuniform float uSurfCellPlan;\nuniform float uSurfCrust;\nuniform vec3  uSurfCrustColor;\nuniform float uSurfCrustRough;\n\nfloat scenaHash13(highp vec3 p){\n  p = fract(p * 0.1031);\n  p += dot(p, p.yzx + 33.33);\n  return fract((p.x + p.y) * p.z);\n}\nfloat scenaVNoise(highp vec3 x){\n  highp vec3 i = floor(x); highp vec3 f = fract(x);\n  f = f * f * (3.0 - 2.0 * f);\n  float n000 = scenaHash13(i + vec3(0.0,0.0,0.0));\n  float n100 = scenaHash13(i + vec3(1.0,0.0,0.0));\n  float n010 = scenaHash13(i + vec3(0.0,1.0,0.0));\n  float n110 = scenaHash13(i + vec3(1.0,1.0,0.0));\n  float n001 = scenaHash13(i + vec3(0.0,0.0,1.0));\n  float n101 = scenaHash13(i + vec3(1.0,0.0,1.0));\n  float n011 = scenaHash13(i + vec3(0.0,1.0,1.0));\n  float n111 = scenaHash13(i + vec3(1.0,1.0,1.0));\n  return mix(mix(mix(n000,n100,f.x), mix(n010,n110,f.x), f.y),\n             mix(mix(n001,n101,f.x), mix(n011,n111,f.x), f.y), f.z);\n}\nfloat scenaFbm(highp vec3 p){\n  float a = 0.5, s = 0.0;\n  for (int i = 0; i < 4; i++){ s += a * scenaVNoise(p); p *= 2.02; a *= 0.5; }\n  return s;\n}\n// Triplanar fbm: blend three axis-projected samples by the world normal, so\n// box faces need no UVs and adjacent boxes share one continuous field.\nfloat scenaTri(highp vec3 wp, vec3 wn, float scale){\n  highp vec3 p = wp * scale + uSurfSeed;\n  vec3 w = abs(normalize(wn)); w = pow(w, vec3(4.0)); w /= (w.x + w.y + w.z + 1e-4);\n  return scenaFbm(p.yzx) * w.x + scenaFbm(p.zxy) * w.y + scenaFbm(p.xyz) * w.z;\n}\n// Concentric grain rings around the grain axis, warped by noise.\nfloat scenaGrain(highp vec3 wp){\n  highp vec3 ax = normalize(uSurfGrainAxis);\n  highp float along = dot(wp, ax);\n  highp vec3 perp = wp - ax * along;\n  highp float rings = length(perp) * uSurfGrainScale + scenaFbm(wp * uSurfGrainScale * 0.4) * 2.0;\n  return abs(fract(rings) - 0.5) * 2.0; // triangle wave 0..1\n}\n// A masonry grid on the dominant-axis face (so box walls/floors/roofs get a\n// clean 2D pattern and abutting boxes align). Running-bond rows, mortar bands\n// and per-cell jitter. Returns: x = mortar mask (1 in the joint), y = per-cell\n// hash (0..1), z = surface height (tile face high → joint low), w = the domed\n// stone height for cobbles.\nvec4 scenaTile(highp vec3 wp, vec3 wn){\n  vec3 an = abs(normalize(wn));\n  highp vec2 uv;\n  if (an.x >= an.y && an.x >= an.z) uv = wp.zy;\n  else if (an.y >= an.x && an.y >= an.z) uv = wp.xz;\n  else uv = wp.xy;\n  uv += uSurfSeed.xy;\n  highp vec2 ts = max(uSurfTileSize, vec2(1e-3));\n  // Chevron parquet: shear alternate column bands ±45° (about each band's own\n  // centre, so the offset stays small and mediump-safe far from the origin).\n  if (uSurfTileChevron > 0.5) {\n    highp float band = floor(uv.x / ts.x);\n    highp float local = uv.x - (band + 0.5) * ts.x;\n    uv.y += (mod(band, 2.0) * 2.0 - 1.0) * local;\n  }\n  highp float row = floor(uv.y / ts.y);\n  highp float bond = mod(row, 2.0) * uSurfTileBond * 0.5;\n  highp float cxf = uv.x / ts.x + bond;\n  highp float col = floor(cxf);\n  highp vec2 cell = vec2(col, row);\n  highp float fx = fract(cxf);\n  highp float fy = fract(uv.y / ts.y);\n  // Distance to the nearest cell edge, in world units → mortar band.\n  float ex = min(fx, 1.0 - fx) * ts.x;\n  float ey = min(fy, 1.0 - fy) * ts.y;\n  float edge = min(ex, ey);\n  float m = max(uSurfMortar, 1e-4);\n  float mortar = 1.0 - smoothstep(m, m * 1.7, edge);\n  // Domed profile for cobbles: peaks at the cell centre, falls to the joint.\n  float dome = clamp(1.0 - length(vec2(fx - 0.5, fy - 0.5)) * 2.0, 0.0, 1.0);\n  float flatH = 1.0 - mortar;\n  float height = mix(flatH, dome * (1.0 - mortar), uSurfTileRound);\n  float h = scenaHash13(vec3(cell + vec2(3.1, 7.3), 5.0));\n  return vec4(mortar, h, height, dome);\n}\n// Snow / moss cap: settles on up-facing surfaces, its edge broken up by the\n// noise the shader already sampled (no extra noise cost). Returns 0..1.\nfloat scenaCapMask(vec3 wn, float breakup){\n  float up = normalize(wn).y * 0.5 + 0.5;      // 0 (down) .. 1 (up)\n  float s = max(uSurfCapSharp, 1e-3);\n  return clamp(smoothstep(uSurfCapUp - s, uSurfCapUp + s, up + (breakup - 0.5) * 0.6), 0.0, 1.0);\n}\n// Parallel ridges along an axis — a corrugated sheet. Crossed with a second\n// set, the two lattices intersect in isolated studs: tread plate.\nfloat scenaRibs(highp vec3 wp, vec3 wn){\n  if (uSurfRibs <= 0.0) return 0.0;\n  // In the FACE's own plane, like the masonry grid. A world axis is no use\n  // here: on a wall, two different world axes project onto the same\n  // direction, which turns a crossed tread plate back into plain stripes.\n  vec3 an = abs(normalize(wn));\n  highp vec2 uv;\n  if (an.x >= an.y && an.x >= an.z) uv = wp.zy;\n  else if (an.y >= an.x && an.y >= an.z) uv = wp.xz;\n  else uv = wp.xy;\n  uv = (uSurfRibTurn > 0.5 ? uv.yx : uv) * uSurfRibScale;\n  float r = abs(fract(uv.x) - 0.5) * 2.0;\n  if (uSurfRibCross > 0.5) {\n    // Two sets at ±45° IN THAT PLANE. MIN, not max: crossed ridges are high\n    // together only where they actually cross, and that is a field of studs\n    // rather than a waffle grid.\n    highp vec2 d = vec2(uv.x + uv.y, uv.x - uv.y) * 0.7071;\n    r = min(abs(fract(d.x) - 0.5), abs(fract(d.y) - 0.5)) * 2.0;\n  }\n  return r * r * (3.0 - 2.0 * r);   // round the triangle off\n}\n// Aggregate. Everything else in this shader runs on smooth fbm, which reads\n// as mottling; asphalt is STONES IN TAR, and stones have edges.\nfloat scenaSpeck(highp vec3 wp){\n  if (uSurfSpeck <= 0.0) return 0.5;\n  return scenaHash13(floor(wp * uSurfSpeckScale + uSurfSeed));\n}\n// Warped Voronoi. Returns x = per-cell hash, y = distance to the nearest\n// seam (0 on it). Basalt's columnar jointing and the zinc spangle on\n// galvanised steel are this one function two orders of magnitude apart.\nvec2 scenaCells(highp vec3 wp, vec3 wn){\n  if (uSurfCells <= 0.0) return vec2(0.5, 1.0);\n  highp vec2 uv;\n  if (uSurfCellPlan > 0.5) {\n    // Columnar jointing is a crazy paving seen from ABOVE, pulled up into\n    // columns — so it is laid out in plan whatever the face is pointing at.\n    uv = wp.xz;\n  } else {\n    vec3 an = abs(normalize(wn));\n    if (an.x >= an.y && an.x >= an.z) uv = wp.zy;\n    else if (an.y >= an.x && an.y >= an.z) uv = wp.xz;\n    else uv = wp.xy;\n  }\n  uv = uv * uSurfCellScale + uSurfSeed.xy;\n  highp vec2 g = floor(uv);\n  highp vec2 f = uv - g;\n  float d1 = 8.0, d2 = 8.0, id = 0.5;\n  for (int j = -1; j <= 1; j++) {\n    for (int i = -1; i <= 1; i++) {\n      vec2 o = vec2(float(i), float(j));\n      float h = scenaHash13(vec3(g + o, 11.0));\n      vec2 seed = o + vec2(h, fract(h * 37.31));\n      float d = length(seed - f);\n      if (d < d1) { d2 = d1; d1 = d; id = h; }\n      else if (d < d2) { d2 = d; }\n    }\n  }\n  // d2 - d1 is 0 exactly on the boundary between two cells and grows inward,\n  // which is a seam that does not care how big the cells are.\n  return vec2(id, clamp(d2 - d1, 0.0, 1.0));\n}\n// A mineral crust — verdigris, a rust bloom, lichen — taking hold in the\n// cavities and on the up-facing side.\nfloat scenaCrustMask(vec3 wn, float low){\n  if (uSurfCrust <= 0.0) return 0.0;\n  float up = normalize(wn).y * 0.5 + 0.5;\n  return clamp(smoothstep(0.66, 0.28, low) * uSurfCrust * mix(0.5, 1.0, up), 0.0, 1.0);\n}\n// WATER FILLS FROM THE BOTTOM. Wetness is a LEVEL, not a multiply: every\n// point has a height (the surface's own low-frequency band, with the\n// mortar joints counted as the lowest ground there is), and it is wet when\n// the level is above it. That is what makes a light shower read as dark\n// glossy lines in the joints and hollows while the faces stay dry, and a\n// downpour sheet the whole wall — from one scalar.\n//\n// The level is lower on a vertical face than a horizontal one, because\n// rain falls down: a sill soaks while the wall beneath it is merely damp.\nfloat scenaWetMask(vec3 wn, float low, float mortar){\n  if (uSurfWet <= 0.0) return 0.0;\n  float up = normalize(wn).y * 0.5 + 0.5;\n  float level = uSurfWet * mix(clamp(uSurfWetCling, 0.0, 1.0), 1.0, up) * 1.4 - 0.2;\n  float height = min(low, 1.0 - mortar);\n  return clamp(smoothstep(height - 0.2, height + 0.2, level), 0.0, 1.0);\n}\n`;\n\nfunction vertexPatch(src: string): string {\n  return src\n    .replace(\n      '#include <common>',\n      '#include <common>\\nvarying highp vec3 vSurfWorldPos;\\nvarying highp vec3 vSurfWorldNormal;'\n    )\n    .replace(\n      '#include <begin_vertex>',\n      `#include <begin_vertex>\n      {\n        vec4 scenaWP = modelMatrix * vec4(transformed, 1.0);\n        #ifdef USE_INSTANCING\n          scenaWP = modelMatrix * instanceMatrix * vec4(transformed, 1.0);\n        #endif\n        vSurfWorldPos = scenaWP.xyz;\n      }`\n    )\n    .replace(\n      '#include <beginnormal_vertex>',\n      `#include <beginnormal_vertex>\n      {\n        vec3 scenaON = objectNormal;\n        #ifdef USE_INSTANCING\n          scenaON = mat3(instanceMatrix) * scenaON;\n        #endif\n        vSurfWorldNormal = normalize(mat3(modelMatrix) * scenaON);\n      }`\n    );\n}\n\nfunction fragmentPatch(src: string): string {\n  return src\n    .replace('#include <common>', '#include <common>\\n' + NOISE_GLSL)\n    .replace(\n      '#include <map_fragment>',\n      `#include <map_fragment>\n      float scenaN   = scenaTri(vSurfWorldPos, vSurfWorldNormal, uSurfScale);\n      float scenaLow = scenaTri(vSurfWorldPos, vSurfWorldNormal, uSurfScale * 0.25);\n      float scenaG   = scenaGrain(vSurfWorldPos);\n      float scenaRib = scenaRibs(vSurfWorldPos, vSurfWorldNormal);\n      float scenaSp  = scenaSpeck(vSurfWorldPos);\n      vec2  scenaC   = scenaCells(vSurfWorldPos, vSurfWorldNormal);\n      // Seam mask: 1 on the join between two cells, 0 inside one.\n      float scenaSeam = (1.0 - smoothstep(0.0, 0.085, scenaC.y)) * uSurfCells;\n      // masonry grid (no-op when uSurfTile == 0)\n      vec4  scenaT   = scenaTile(vSurfWorldPos, vSurfWorldNormal);\n      float scenaMortar = scenaT.x * uSurfTile;\n      // fine mottle\n      diffuseColor.rgb *= 1.0 + (scenaN - 0.5) * uSurfAlbedoVar;\n      // per-cell brightness jitter, so no two bricks/stones read the same\n      diffuseColor.rgb *= 1.0 + uSurfTileJitter * (scenaT.y - 0.5) * uSurfTile;\n      // cavity ambient occlusion (dark where the low band is low)\n      diffuseColor.rgb *= 1.0 - uSurfAO * (1.0 - scenaLow);\n      // cavity tint\n      diffuseColor.rgb = mix(diffuseColor.rgb, uSurfTint, uSurfTintAmount * (1.0 - scenaLow));\n      // grain darkening (no-op when uSurfGrain == 0)\n      diffuseColor.rgb *= 1.0 - uSurfGrain * scenaG * 0.5;\n      // aggregate chips — hard-edged, unlike everything else here\n      diffuseColor.rgb *= 1.0 + (scenaSp - 0.5) * uSurfSpeck;\n      // cells: each one its own shade, and the seams between them dark\n      diffuseColor.rgb *= 1.0 + (scenaC.x - 0.5) * uSurfCellJitter * uSurfCells;\n      diffuseColor.rgb *= 1.0 - scenaSeam * uSurfCellEdge;\n      // the ridge valleys hold shadow the lighting alone will not give them\n      diffuseColor.rgb *= 1.0 - uSurfRibs * (1.0 - scenaRib) * 0.22;\n      // accent cells (mosaic chips) painted solid tint — a no-op at 0\n      float scenaAccent = uSurfTile * uSurfTileTint;\n      diffuseColor.rgb = mix(diffuseColor.rgb, uSurfTint, step(scenaT.y, scenaAccent) * uSurfTile);\n      // per-cell ring + dot motif (patterned cement tiles) — a no-op at 0\n      float scenaMotifM = smoothstep(0.40, 0.47, scenaT.w) - smoothstep(0.60, 0.68, scenaT.w)\n        + smoothstep(0.86, 0.93, scenaT.w);\n      diffuseColor.rgb = mix(diffuseColor.rgb, uSurfTint,\n        clamp(scenaMotifM, 0.0, 1.0) * uSurfTileMotif * uSurfTile);\n      // recessed mortar joint: to the mortar colour, shadowed in the groove\n      diffuseColor.rgb = mix(diffuseColor.rgb, uSurfMortarColor, scenaMortar);\n      diffuseColor.rgb *= 1.0 - 0.35 * scenaMortar;\n      // snow / moss cap settling on the up-facing faces (over the mortar too)\n      float scenaCapM = scenaCapMask(vSurfWorldNormal, scenaN) * uSurfCap;\n      diffuseColor.rgb = mix(diffuseColor.rgb, uSurfCapColor, scenaCapM);\n      // WET. Water darkens a surface because it fills the pores: light gets\n      // in, scatters, and comes back out with less of it. So POROUS things\n      // darken hard and sealed ones barely change — a wet flagstone is\n      // almost black, wet chrome is just chrome — and metal, which has no\n      // subsurface to wet, does not darken at all.\n      // A CRUST, not a tint: verdigris, rust bloom, lichen. It goes over\n      // everything above it, because it grew on top of all of it.\n      float scenaCrustM = scenaCrustMask(vSurfWorldNormal, scenaLow);\n      diffuseColor.rgb = mix(diffuseColor.rgb, uSurfCrustColor, scenaCrustM);\n      float scenaWetM = scenaWetMask(vSurfWorldNormal, scenaLow, scenaMortar);\n      float scenaPorous = (1.0 - clamp(metalness, 0.0, 1.0)) * clamp(roughness, 0.0, 1.0);\n      diffuseColor.rgb *= mix(1.0, mix(0.93, 0.45, scenaPorous), scenaWetM);`\n    )\n    .replace(\n      '#include <roughnessmap_fragment>',\n      `#include <roughnessmap_fragment>\n      roughnessFactor = clamp(roughnessFactor + (scenaN - 0.5) * uSurfRoughVar + uSurfGrain * scenaG * 0.12\n        + scenaMortar * 0.25 + (scenaT.y - 0.5) * uSurfTileJitter * 0.3 * uSurfTile, 0.04, 1.0);\n      roughnessFactor = clamp(roughnessFactor + (scenaSp - 0.5) * uSurfSpeck * 0.35\n        + scenaSeam * 0.2, 0.04, 1.0);\n      roughnessFactor = mix(roughnessFactor, uSurfCrustRough, scenaCrustM);\n      roughnessFactor = mix(roughnessFactor, uSurfCapRough, scenaCapM);\n      // A film of water is a mirror, whatever is underneath it.\n      roughnessFactor = mix(roughnessFactor, 0.05, scenaWetM * 0.92);`\n    )\n    .replace(\n      '#include <metalnessmap_fragment>',\n      `#include <metalnessmap_fragment>\n      // A mineral scab does not reflect like the metal it grew on, so where\n      // the crust has taken hold the metal is simply not there any more.\n      // This is the difference between patina and green paint.\n      metalnessFactor = mix(metalnessFactor, 0.0, scenaCrustM);`\n    )\n    .replace(\n      '#include <normal_fragment_maps>',\n      `#include <normal_fragment_maps>\n      {\n        // three's perturbNormalArb, in view space, driven by the noise height\n        // plus the tile relief (a step down into each mortar joint).\n        // Standing water fills the micro-relief, so the bump flattens out\n        // under it — the puddle is smooth even where the stone is not.\n        float scenaH = (scenaN + uSurfGrain * scenaG * 0.5 + scenaT.z * uSurfTile * uSurfTileRelief\n          + scenaRib * uSurfRibs * 0.9 + scenaC.y * uSurfCells * uSurfCellEdge * 0.5)\n          * (1.0 - scenaWetM * 0.7);\n        vec3 sX = dFdx(-vViewPosition);\n        vec3 sY = dFdy(-vViewPosition);\n        vec3 sN = normal;\n        vec3 R1 = cross(sY, sN);\n        vec3 R2 = cross(sN, sX);\n        float det = dot(sX, R1);\n        vec3 grad = sign(det) * (dFdx(scenaH) * R1 + dFdy(scenaH) * R2);\n        normal = normalize(abs(det) * sN - uSurfBump * grad);\n      }`\n    )\n    .replace(\n      '#include <emissivemap_fragment>',\n      `#include <emissivemap_fragment>\n      {\n        // Procedural glow (lava cracks, crystal): drawn straight into the\n        // emissive radiance, NOT via material.emissive — so it burns constant\n        // and the day/night cycle (which scales emissiveIntensity) can't dim\n        // it. A no-op when uSurfGlow == 0. Glow fills the low-noise areas.\n        float scenaGlow = smoothstep(uSurfGlowThresh + 0.16, uSurfGlowThresh - 0.16, scenaLow) * uSurfGlow;\n        totalEmissiveRadiance += uSurfGlowColor * scenaGlow;\n      }`\n    );\n}\n\n/**\n * Build a procedural surface material. Pass a preset name for the defaults,\n * plus any overrides (colour, roughness, bump, seed, …).\n */\nexport function createSurface(kind: SurfaceKind, options: SurfaceOptions = {}): MeshStandardMaterial {\n  const preset = SURFACE_PRESETS[kind];\n  const p: SurfaceParams = { ...preset, ...options };\n  const seed = options.seed ?? 0;\n\n  const base = {\n    color: options.color ?? preset.baseColor ?? 0x9a9a9a,\n    roughness: p.roughness,\n    metalness: p.metalness,\n    flatShading: p.flat,\n  };\n  // A MeshPhysicalMaterial only when the preset genuinely needs one. It is a\n  // bigger shader, and `transmission` makes three render the scene a second\n  // time — so the other 52 kinds keep the cheap material they have always had.\n  const material: MeshStandardMaterial = p.physical\n    ? new MeshPhysicalMaterial({\n        ...base,\n        ...(p.sheen === undefined ? {} : {\n          sheen: p.sheen,\n          sheenColor: new Color(p.sheenColor ?? 0xffffff),\n          sheenRoughness: p.sheenRough ?? 0.3,\n        }),\n        ...(p.anisotropy === undefined ? {} : {\n          anisotropy: p.anisotropy,\n          anisotropyRotation: p.anisotropyRotation ?? 0,\n        }),\n        ...(p.iridescence === undefined ? {} : {\n          iridescence: p.iridescence,\n          iridescenceIOR: p.iridescenceIOR ?? 1.3,\n          iridescenceThicknessRange: p.iridescenceThickness ?? [100, 400],\n        }),\n        ...(p.transmission === undefined ? {} : {\n          transmission: p.transmission,\n          thickness: p.thickness ?? 0.5,\n          ior: p.ior ?? 1.5,\n          // Only when asked for: three compiles USE_DISPERSION the moment\n          // this crosses zero, and that is three transmission samples a\n          // pixel instead of one.\n          ...(p.dispersion ? { dispersion: p.dispersion } : {}),\n          ...(p.attenuationColor === undefined ? {} : {\n            attenuationColor: new Color(p.attenuationColor),\n            attenuationDistance: p.attenuationDistance ?? 1,\n          }),\n        }),\n      })\n    : new MeshStandardMaterial(base);\n\n  const uniforms = {\n    uSurfScale: { value: p.scale },\n    uSurfAlbedoVar: { value: p.albedoVar },\n    uSurfTint: { value: new Color(p.tint) },\n    uSurfTintAmount: { value: p.tintAmount },\n    uSurfAO: { value: p.ao },\n    uSurfBump: { value: p.bump },\n    uSurfRoughVar: { value: p.roughVar },\n    uSurfGrain: { value: p.grain },\n    uSurfGrainScale: { value: p.grainScale },\n    uSurfGrainAxis: { value: p.grainAxis.clone().normalize() },\n    // A large, seed-driven world-space offset so equal colours weather apart.\n    uSurfSeed: {\n      value: new Vector3(\n        Math.sin(seed * 12.9898) * 43.75,\n        Math.cos(seed * 78.233) * 51.13,\n        Math.sin(seed * 37.719) * 29.41\n      ),\n    },\n    // Masonry tiling (uSurfTile 0 disables the whole grid at no visual cost).\n    uSurfTile: { value: p.tile ?? 0 },\n    uSurfTileSize: { value: new Vector2(p.tileW ?? 0.25, p.tileH ?? 0.1) },\n    uSurfMortar: { value: p.mortar ?? 0.014 },\n    uSurfTileBond: { value: p.bond ?? 1 },\n    uSurfTileRound: { value: p.round ?? 0 },\n    uSurfTileJitter: { value: p.tileJitter ?? 0.12 },\n    uSurfMortarColor: { value: new Color(p.mortarColor ?? 0x3a3a3a) },\n    uSurfTileRelief: { value: p.tileRelief ?? 0.06 },\n    uSurfTileTint: { value: p.tileTint ?? 0 },\n    uSurfTileChevron: { value: p.chevron ?? 0 },\n    uSurfTileMotif: { value: p.motif ?? 0 },\n    // Snow/moss cap (uSurfCap 0 disables it).\n    uSurfCap: { value: p.cap ?? 0 },\n    uSurfCapColor: { value: new Color(p.capColor ?? 0xf2f6fa) },\n    uSurfCapUp: { value: p.capUp ?? 0.5 },\n    uSurfCapSharp: { value: p.capSharp ?? 0.28 },\n    uSurfCapRough: { value: p.capRough ?? 0.88 },\n    // Emissive glow (uSurfGlow 0 keeps it dark, day-cycle-safe).\n    uSurfGlow: { value: p.glow ?? 0 },\n    uSurfGlowColor: { value: new Color(p.glowColor ?? 0xff6a2a) },\n    uSurfGlowThresh: { value: p.glowThreshold ?? 0.45 },\n    // Wear: water (uSurfWet 0 is bone dry and costs one compare).\n    uSurfWet: { value: p.wet ?? 0 },\n    uSurfWetCling: { value: p.wetCling ?? 0.55 },\n    // Ribs, aggregate, cells and crust (each 0 = off, and off costs a compare).\n    uSurfRibs: { value: p.ribs ?? 0 },\n    uSurfRibScale: { value: p.ribScale ?? 8 },\n    uSurfRibTurn: { value: p.ribTurn ?? 0 },\n    uSurfRibCross: { value: p.ribCross ?? 0 },\n    uSurfSpeck: { value: p.speck ?? 0 },\n    uSurfSpeckScale: { value: p.speckScale ?? 40 },\n    uSurfCells: { value: p.cells ?? 0 },\n    uSurfCellScale: { value: p.cellScale ?? 4 },\n    uSurfCellEdge: { value: p.cellEdge ?? 0.4 },\n    uSurfCellJitter: { value: p.cellJitter ?? 0.18 },\n    uSurfCellPlan: { value: p.cellPlan ?? 0 },\n    uSurfCrust: { value: p.crust ?? 0 },\n    uSurfCrustColor: { value: new Color(p.crustColor ?? 0x4fa88a) },\n    uSurfCrustRough: { value: p.crustRough ?? 0.9 },\n  };\n\n  material.onBeforeCompile = (shader) => {\n    Object.assign(shader.uniforms, uniforms);\n    shader.vertexShader = vertexPatch(shader.vertexShader);\n    shader.fragmentShader = fragmentPatch(shader.fragmentShader);\n    // Keep the live shader so weather can drive uniforms after compilation —\n    // the object three actually uploads from, not just our pre-compile copy.\n    (material.userData as { scenaShader?: typeof shader }).scenaShader = shader;\n  };\n  // All surface materials inject identical source (uniforms carry the\n  // differences), so one cache key groups them — and, crucially, keeps them\n  // from colliding with a plain MeshStandardMaterial that has matching base\n  // params but no injection. three still appends its own feature key, so\n  // flat/smooth/instanced variants stay separate programs.\n  const cacheKey = p.physical ? 'scena-surface-v5-physical' : 'scena-surface-v5';\n  material.customProgramCacheKey = () => cacheKey;\n\n  // Expose the live uniforms so weather can drive them after the fact — e.g.\n  // snow settling ramps uSurfCap, rain darkens/glosses via the same handles.\n  (material.userData as { scenaSurface?: typeof uniforms }).scenaSurface = uniforms;\n\n  return material;\n}\n","import { BoxGeometry, Group, Mesh } from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport { createSurface } from '../materials/surface';\nimport type { Carryable } from '../core/types';\n\nexport interface CrateOptions {\n  seed?: number;\n  size?: number;\n  /** 0–1 color wear. Default 0.3. */\n  weathering?: number;\n  palette?: Palette;\n}\n\n/**\n * A wooden crate: panel box with darker edge framing, seeded wear tint. It's\n * a **carryable** — hand it to ANIMA's `Carry` and a character hoists it to\n * the chest (`carry: 'crate'`), the hold point offset to the box's centre.\n */\nexport function createCrate(options: CrateOptions = {}): Carryable {\n  const rng = new Rng(options.seed ?? 1);\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const size = options.size ?? 1;\n  const wear = options.weathering ?? 0.3;\n\n  const group = new Group();\n  group.name = 'crate';\n\n  const panelMaterial = createSurface('plank', { color: palette.wood, seed: options.seed ?? 1 });\n  panelMaterial.color.offsetHSL(0, 0, -rng.range(0, wear * 0.18));\n  const frameMaterial = createSurface('wood', { color: palette.woodDark, seed: (options.seed ?? 1) + 3 });\n\n  const body = new Mesh(new BoxGeometry(size * 0.92, size * 0.92, size * 0.92), panelMaterial);\n  body.position.y = size / 2;\n  group.add(body);\n\n  const beam = size * 0.12;\n  const long = size * 1.0;\n  for (const y of [beam / 2, size - beam / 2]) {\n    for (const [rx, rz, w, d] of [\n      [0, size / 2 - beam / 2, long, beam],\n      [0, -(size / 2 - beam / 2), long, beam],\n      [size / 2 - beam / 2, 0, beam, long],\n      [-(size / 2 - beam / 2), 0, beam, long],\n    ] as const) {\n      const rail = new Mesh(new BoxGeometry(w, beam, d), frameMaterial);\n      rail.position.set(rx, y, rz);\n      group.add(rail);\n    }\n  }\n  for (const x of [-1, 1]) {\n    for (const z of [-1, 1]) {\n      const post = new Mesh(new BoxGeometry(beam, size, beam), frameMaterial);\n      post.position.set(x * (size / 2 - beam / 2), size / 2, z * (size / 2 - beam / 2));\n      group.add(post);\n    }\n  }\n  group.rotation.y = rng.range(0, Math.PI / 2);\n\n  return {\n    object: group,\n    obstacleRadius: size * 0.75,\n    carry: 'crate',\n    // Origin is the base: lift the hold point to the centre (y) and push it\n    // forward by half the depth (z) so the box rides IN FRONT of the chest,\n    // not merged into it.\n    grip: { y: -size / 2, z: size / 2 },\n  };\n}\n","import {\n  BoxGeometry,\n  CylinderGeometry,\n  Group,\n  Mesh,\n  MeshStandardMaterial,\n  PointLight,\n  SphereGeometry,\n} from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { Prop } from '../core/types';\n\nexport interface LampOptions {\n  seed?: number;\n  height?: number;\n  /** Add a real PointLight. Off by default — lights are a budget. */\n  light?: boolean;\n  lightIntensity?: number;\n  palette?: Palette;\n}\n\n/** A street lamp: post, head, glowing bulb, optional real PointLight. */\nexport function createLamp(options: LampOptions = {}): Prop {\n  const rng = new Rng(options.seed ?? 1);\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const height = options.height ?? rng.range(2.6, 3.1);\n\n  const group = new Group();\n  group.name = 'lamp';\n  const metal = new MeshStandardMaterial({ color: palette.metal, flatShading: true });\n\n  const post = new Mesh(new CylinderGeometry(0.05, 0.08, height, 6), metal);\n  post.position.y = height / 2;\n  group.add(post);\n\n  const head = new Mesh(new BoxGeometry(0.34, 0.26, 0.34), metal);\n  head.position.y = height + 0.1;\n  group.add(head);\n\n  const bulb = new Mesh(\n    new SphereGeometry(0.11, 8, 6),\n    new MeshStandardMaterial({\n      color: palette.lampGlow,\n      emissive: palette.lampGlow,\n      emissiveIntensity: 1.6,\n    })\n  );\n  bulb.position.y = height - 0.03;\n  group.add(bulb);\n\n  if (options.light) {\n    const light = new PointLight(palette.lampGlow, options.lightIntensity ?? 6, 12, 1.8);\n    light.position.y = height - 0.05;\n    group.add(light);\n  }\n\n  return { object: group, obstacleRadius: 0.25 };\n}\n","import {\n  DynamicDrawUsage,\n  Group,\n  InstancedMesh,\n  Matrix4,\n  Mesh,\n  Quaternion,\n  Vector3,\n} from 'three';\nimport { Rng, valueNoise2 } from '../core/random';\nimport type { Obstacle, Prop } from '../core/types';\n\nexport interface ScatterItem {\n  /** Prop factory, called once per visual variant with a seeded Rng. */\n  create(rng: Rng): Prop;\n  /**\n   * Simplified far-distance factory for LOD (e.g. a single cone for a\n   * tree). Only used when `ScatterOptions.lod` is set; items without one\n   * stay full-detail at every distance.\n   */\n  createFar?(rng: Rng): Prop;\n  /** Relative frequency among items. Default 1. */\n  weight?: number;\n  /** Distinct variants generated per item (visual variety). Default 4. */\n  variants?: number;\n  /** Per-instance uniform scale range. Default [0.8, 1.25]. */\n  scale?: [number, number];\n}\n\nexport interface ScatterOptions {\n  seed?: number;\n  items: ScatterItem[];\n  /** Placement region in the XZ plane. */\n  area: { min: { x: number; z: number }; max: { x: number; z: number } };\n  /** Ground height lookup; a number means flat ground. Default 0. */\n  surface?: number | ((x: number, z: number) => number);\n  /** Expected instances per square unit (thinned by density noise). */\n  density?: number;\n  /** Or an exact target count (before masks/spacing rejections). */\n  count?: number;\n  /** Veto function: return false to reject a candidate point. */\n  mask?: (x: number, z: number, y: number) => boolean;\n  /** Minimum distance between any two placements. Default 1.2. */\n  minSpacing?: number;\n  /** World-space circles to keep clear (paths, spawns, buildings). */\n  keepOut?: Obstacle[] | { center: { x: number; z: number }; radius: number }[];\n  /** Density-noise feature size in world units. Default 18. */\n  clumpScale?: number;\n  /**\n   * Tile-based LOD: placements are bucketed into square tiles; tiles\n   * beyond `distance` from the camera swap full-detail instances for the\n   * items' `createFar` variants (with 10% hysteresis so tiles don't\n   * flicker at the boundary). Call `result.update(camera)` each frame.\n   */\n  lod?: {\n    /** Camera distance at which tiles switch to far variants. */\n    distance: number;\n    /** Tile side in world units. Default 16. */\n    tileSize?: number;\n  };\n}\n\nexport interface Placement {\n  position: Vector3;\n  rotationY: number;\n  scale: number;\n  itemIndex: number;\n}\n\nexport interface ScatterTile {\n  center: { x: number; z: number };\n  near: Group;\n  far: Group;\n}\n\nexport interface ScatterResult {\n  /** One InstancedMesh per template part — a handful of draw calls total. */\n  group: Group;\n  placements: Placement[];\n  /** World-space steering obstacles for everything with a footprint. */\n  obstacles: Obstacle[];\n  count: number;\n  /** LOD tiles (present when `lod` was requested). */\n  tiles?: ScatterTile[];\n  /** Re-evaluate tile LOD against the camera (present when `lod` was requested). */\n  update?(camera: { position: Vector3 }): void;\n}\n\n/**\n * Populate an area with seeded, instanced props: \"empty plane → forest\"\n * in one call. Placement uses density noise for natural clumping, a\n * spatial hash for minimum spacing, and masks/keep-out circles for\n * exclusion. Rendering merges every placement into InstancedMeshes — a\n * few draw calls for thousands of props.\n *\n * ```ts\n * const forest = scatter({\n *   seed: 7,\n *   area: { min: { x: -40, z: -40 }, max: { x: 40, z: 40 } },\n *   surface: terrain.heightAt,\n *   density: 0.04,\n *   items: [\n *     { create: (rng) => createTree({ seed: rng.int(1, 1e9) }), weight: 3 },\n *     { create: (rng) => createRock({ seed: rng.int(1, 1e9) }) },\n *   ],\n *   mask: (x, z, y) => y > 0.5 && y < 5,        // between shore and peaks\n *   keepOut: [{ center: village, radius: 12 }],\n * });\n * scene.add(forest.group);\n * agent.addBehavior(new ObstacleAvoidance(() => forest.obstacles));\n * ```\n */\nexport function scatter(options: ScatterOptions): ScatterResult {\n  const seed = options.seed ?? 1;\n  const rng = new Rng(seed);\n  const { area } = options;\n  const width = area.max.x - area.min.x;\n  const depth = area.max.z - area.min.z;\n  const surface = options.surface ?? 0;\n  const heightAt =\n    typeof surface === 'number' ? () => surface : (x: number, z: number) => surface(x, z);\n  const minSpacing = options.minSpacing ?? 1.2;\n  const clumpScale = options.clumpScale ?? 18;\n  const attempts = options.count ?? Math.round(width * depth * (options.density ?? 0.03));\n\n  const keepOut = (options.keepOut ?? []).map((k) => ({\n    x: k.center.x,\n    z: 'z' in k.center ? k.center.z : (k.center as { z: number }).z,\n    radius: k.radius,\n  }));\n\n  // Weighted item choice.\n  const weights = options.items.map((i) => i.weight ?? 1);\n  const totalWeight = weights.reduce((a, b) => a + b, 0);\n  const pickItem = (): number => {\n    let r = rng.next() * totalWeight;\n    for (let i = 0; i < weights.length; i++) {\n      r -= weights[i];\n      if (r <= 0) return i;\n    }\n    return weights.length - 1;\n  };\n\n  // Spatial hash for min-spacing rejection.\n  const cell = Math.max(minSpacing, 0.001);\n  const occupied = new Map<string, Array<{ x: number; z: number }>>();\n  const tooClose = (x: number, z: number): boolean => {\n    const cx = Math.floor(x / cell);\n    const cz = Math.floor(z / cell);\n    for (let dx = -1; dx <= 1; dx++) {\n      for (let dz = -1; dz <= 1; dz++) {\n        const bucket = occupied.get(`${cx + dx},${cz + dz}`);\n        if (!bucket) continue;\n        for (const p of bucket) {\n          if ((p.x - x) ** 2 + (p.z - z) ** 2 < minSpacing * minSpacing) return true;\n        }\n      }\n    }\n    return false;\n  };\n\n  const placements: Placement[] = [];\n  for (let i = 0; i < attempts; i++) {\n    const x = rng.range(area.min.x, area.max.x);\n    const z = rng.range(area.min.z, area.max.z);\n    // Density noise: clumps and clearings instead of uniform confetti.\n    if (valueNoise2(x / clumpScale, z / clumpScale, seed + 77) < rng.range(0.15, 0.55)) continue;\n    if (keepOut.some((k) => (k.x - x) ** 2 + (k.z - z) ** 2 < k.radius * k.radius)) continue;\n    if (tooClose(x, z)) continue;\n    const y = heightAt(x, z);\n    if (options.mask && !options.mask(x, z, y)) continue;\n\n    const itemIndex = pickItem();\n    const [minScale, maxScale] = options.items[itemIndex].scale ?? [0.8, 1.25];\n    placements.push({\n      position: new Vector3(x, y, z),\n      rotationY: rng.range(0, Math.PI * 2),\n      scale: rng.range(minScale, maxScale),\n      itemIndex,\n    });\n    const key = `${Math.floor(x / cell)},${Math.floor(z / cell)}`;\n    let bucket = occupied.get(key);\n    if (!bucket) occupied.set(key, (bucket = []));\n    bucket.push({ x, z });\n  }\n\n  // Build variants per item, bucket placements per variant, then emit one\n  // InstancedMesh per (variant, mesh part).\n  const group = new Group();\n  group.name = 'scatter';\n  const obstacles: Obstacle[] = [];\n  const placementMatrix = new Matrix4();\n  const composed = new Matrix4();\n  const quaternion = new Quaternion();\n  const up = new Vector3(0, 1, 0);\n  const scaleVector = new Vector3();\n\n  const emit = (variant: Prop, list: Placement[], parent: Group): void => {\n    variant.object.updateMatrixWorld(true);\n    variant.object.traverse((child) => {\n      if (!(child instanceof Mesh)) return;\n      const instanced = new InstancedMesh(child.geometry, child.material, list.length);\n      instanced.instanceMatrix.setUsage(DynamicDrawUsage);\n      list.forEach((placement, index) => {\n        quaternion.setFromAxisAngle(up, placement.rotationY);\n        scaleVector.setScalar(placement.scale);\n        placementMatrix.compose(placement.position, quaternion, scaleVector);\n        composed.multiplyMatrices(placementMatrix, child.matrixWorld);\n        instanced.setMatrixAt(index, composed);\n      });\n      instanced.instanceMatrix.needsUpdate = true;\n      parent.add(instanced);\n    });\n  };\n\n  // LOD tiles: near/far group pairs, lazily created per occupied tile.\n  const tileSize = options.lod?.tileSize ?? 16;\n  const tileMap = new Map<string, ScatterTile>();\n  const tileFor = (x: number, z: number): ScatterTile => {\n    const tx = Math.floor(x / tileSize);\n    const tz = Math.floor(z / tileSize);\n    const key = `${tx},${tz}`;\n    let tile = tileMap.get(key);\n    if (!tile) {\n      tile = {\n        center: { x: (tx + 0.5) * tileSize, z: (tz + 0.5) * tileSize },\n        near: new Group(),\n        far: new Group(),\n      };\n      tile.far.visible = false;\n      group.add(tile.near, tile.far);\n      tileMap.set(key, tile);\n    }\n    return tile;\n  };\n\n  options.items.forEach((item, itemIndex) => {\n    const variantCount = item.variants ?? 4;\n    const variants: Prop[] = [];\n    for (let v = 0; v < variantCount; v++) variants.push(item.create(rng.fork()));\n    const useLod = options.lod !== undefined && item.createFar !== undefined;\n    const farVariants: Prop[] = [];\n    if (useLod) {\n      for (let v = 0; v < variantCount; v++) farVariants.push(item.createFar!(rng.fork()));\n    }\n\n    const byVariant: Placement[][] = variants.map(() => []);\n    for (const placement of placements) {\n      if (placement.itemIndex !== itemIndex) continue;\n      // Deterministic variant choice from position.\n      const v = Math.abs(Math.floor(placement.position.x * 31 + placement.position.z * 17)) % variantCount;\n      byVariant[v].push(placement);\n    }\n\n    variants.forEach((variant, v) => {\n      const list = byVariant[v];\n      if (list.length === 0) return;\n      if (useLod) {\n        // Split this variant's placements per tile, emit near + far pairs.\n        const byTile = new Map<ScatterTile, Placement[]>();\n        for (const placement of list) {\n          const tile = tileFor(placement.position.x, placement.position.z);\n          let bucket = byTile.get(tile);\n          if (!bucket) byTile.set(tile, (bucket = []));\n          bucket.push(placement);\n        }\n        for (const [tile, bucket] of byTile) {\n          emit(variant, bucket, tile.near);\n          emit(farVariants[v], bucket, tile.far);\n        }\n      } else {\n        emit(variant, list, group);\n      }\n      if (variant.obstacleRadius > 0) {\n        for (const placement of list) {\n          obstacles.push({\n            center: placement.position.clone(),\n            radius: variant.obstacleRadius * placement.scale,\n          });\n        }\n      }\n    });\n  });\n\n  const result: ScatterResult = { group, placements, obstacles, count: placements.length };\n  if (options.lod) {\n    const tiles = [...tileMap.values()];\n    const swapOut = options.lod.distance * 1.1; // hysteresis: no flicker\n    const swapIn = options.lod.distance * 0.9;\n    result.tiles = tiles;\n    result.update = (camera) => {\n      for (const tile of tiles) {\n        const dx = camera.position.x - tile.center.x;\n        const dz = camera.position.z - tile.center.z;\n        const distance = Math.hypot(dx, dz);\n        if (tile.near.visible && distance > swapOut) {\n          tile.near.visible = false;\n          tile.far.visible = true;\n        } else if (!tile.near.visible && distance < swapIn) {\n          tile.near.visible = true;\n          tile.far.visible = false;\n        }\n      }\n    };\n  }\n  return result;\n}\n","import {\n  BoxGeometry,\n  Color,\n  ConeGeometry,\n  CylinderGeometry,\n  Group,\n  IcosahedronGeometry,\n  Mesh,\n  MeshStandardMaterial,\n} from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { WindField } from '../environment/wind';\nimport type { Prop } from '../core/types';\n\nexport type TreeSpecies =\n  | 'pine'\n  | 'oak'\n  | 'cypress'\n  | 'birch'\n  | 'cedar'\n  | 'maple'\n  | 'sakura'\n  | 'palm'\n  | 'willow'\n  | 'sequoia'\n  | 'banyan'\n  | 'baobab'\n  | 'acacia';\n\n/** The season a tree wears. Currently shapes `sakura` (bloom / green / warm / bare). */\nexport type TreeSeason = 'spring' | 'summer' | 'autumn' | 'winter';\n\n/** Every species `createTree` can build. */\nexport const TREE_SPECIES: readonly TreeSpecies[] = [\n  'pine',\n  'oak',\n  'cypress',\n  'birch',\n  'cedar',\n  'maple',\n  'sakura',\n  'palm',\n  'willow',\n  'sequoia',\n  'banyan',\n  'baobab',\n  'acacia',\n];\n\nexport interface TreeOptions {\n  seed?: number;\n  /** Overall height in world units. Default is species-specific. */\n  height?: number;\n  /** Which species. Default: a seeded pick of pine or oak (new species are opt-in). */\n  species?: TreeSpecies;\n  /** @deprecated Use `species`. Kept as an alias so old calls keep working. */\n  style?: TreeSpecies;\n  /** Season — currently drives `sakura` (blossom in spring, green in summer, warm in autumn, bare in winter). */\n  season?: TreeSeason;\n  /** A WindField to sway the canopy in (the trunk stays planted). */\n  wind?: WindField;\n  palette?: Palette;\n}\n\n// --- shared helpers -----------------------------------------------------\n\nfunction mat(color: number): MeshStandardMaterial {\n  return new MeshStandardMaterial({ color, flatShading: true });\n}\n\n/** Blend a base colour toward another — species tints that still theme with the palette. */\nfunction tint(base: number, toward: number, t: number): number {\n  return new Color(base).lerp(new Color(toward), t).getHex();\n}\n\n// --- silhouette builders (shared by the recipes) ------------------------\n\n/** A gently curving trunk from stacked segments — the lean of a palm. Returns the crown position. */\nfunction curvedTrunk(\n  group: Group,\n  material: MeshStandardMaterial,\n  height: number,\n  baseR: number,\n  topR: number,\n  curve: number\n): { x: number; y: number } {\n  const segs = 7;\n  const segH = height / segs;\n  let cx = 0;\n  for (let i = 0; i < segs; i++) {\n    const f = i / segs;\n    const r0 = baseR + (topR - baseR) * f;\n    const r1 = baseR + (topR - baseR) * ((i + 1) / segs);\n    cx = curve * f * f; // accelerating lean\n    const seg = new Mesh(new CylinderGeometry(r1, r0, segH * 1.04, 6), material);\n    seg.position.set(cx, segH * (i + 0.5), 0);\n    seg.rotation.z = -curve * 0.12;\n    group.add(seg);\n  }\n  return { x: curve, y: height };\n}\n\n/** A crown of long, drooping, radial fronds — a palm top. */\nfunction frondCrown(\n  group: Group,\n  material: MeshStandardMaterial,\n  rng: Rng,\n  cx: number,\n  cy: number,\n  count: number,\n  length: number,\n  droopDeg: number\n): void {\n  const droop = (droopDeg * Math.PI) / 180;\n  for (let i = 0; i < count; i++) {\n    const a = (i / count) * Math.PI * 2 + rng.range(-0.12, 0.12);\n    const frond = new Group();\n    const w = length * 0.13;\n    const blade = new Mesh(new ConeGeometry(w, length, 4), material); // tapered blade\n    blade.rotation.z = -Math.PI / 2; // point along +x\n    blade.position.x = length * 0.5;\n    blade.scale.z = 0.28; // flatten into a frond\n    frond.add(blade);\n    frond.position.set(cx, cy, 0);\n    frond.rotation.y = a;\n    frond.rotation.z = -(droop + rng.range(-0.14, 0.14)); // droop down\n    group.add(frond);\n  }\n}\n\n/** Long strands hanging and swaying from the canopy hem — a willow's veil. */\nfunction droopStrands(\n  group: Group,\n  material: MeshStandardMaterial,\n  rng: Rng,\n  cy: number,\n  radius: number,\n  count: number,\n  minLen: number,\n  maxLen: number\n): void {\n  for (let i = 0; i < count; i++) {\n    const a = (i / count) * Math.PI * 2 + rng.range(-0.12, 0.12);\n    const rr = radius * rng.range(0.78, 1.02); // hang from the outer hem\n    const len = Math.min(rng.range(minLen, maxLen), cy - 0.4); // never punch through the ground\n    if (len <= 0.3) continue;\n    // A leafy strip, wide enough to read as a veil from any angle.\n    const strand = new Mesh(new BoxGeometry(0.12, len, 0.12), material);\n    strand.position.set(Math.cos(a) * rr, cy - len / 2, Math.sin(a) * rr);\n    strand.rotation.y = -a;\n    strand.rotation.z = rng.range(-0.08, 0.08);\n    group.add(strand);\n  }\n}\n\n/** A few splayed structural branches — visible on a bare sakura. */\nfunction branches(group: Group, material: MeshStandardMaterial, rng: Rng, trunkTop: number, count: number, len: number): void {\n  for (let i = 0; i < count; i++) {\n    const a = (i / count) * Math.PI * 2 + rng.range(-0.25, 0.25);\n    const br = new Mesh(new CylinderGeometry(0.025, 0.055, len, 5), material);\n    br.position.set(Math.cos(a) * len * 0.28, trunkTop + len * 0.34, Math.sin(a) * len * 0.28);\n    br.rotation.set(-Math.sin(a) * 0.7, 0, Math.cos(a) * 0.7);\n    group.add(br);\n  }\n}\n\n/** A massive trunk that flares into buttress roots at the base — a sequoia. */\nfunction buttressTrunk(group: Group, material: MeshStandardMaterial, rng: Rng, height: number, baseR: number, topR: number): void {\n  const trunk = new Mesh(new CylinderGeometry(topR, baseR, height, 9), material);\n  trunk.position.y = height / 2;\n  group.add(trunk);\n  const flares = 6;\n  for (let i = 0; i < flares; i++) {\n    const a = (i / flares) * Math.PI * 2;\n    const wedge = new Mesh(new ConeGeometry(baseR * 0.5, height * 0.16, 4), material);\n    wedge.position.set(Math.cos(a) * baseR * 0.65, height * 0.05, Math.sin(a) * baseR * 0.65);\n    wedge.rotation.set(-Math.sin(a) * 0.35, 0, Math.cos(a) * 0.35);\n    wedge.scale.z = 0.5;\n    group.add(wedge);\n  }\n}\n\n/** A fat, bulging bottle trunk tapering to a narrow top — a baobab. Returns the crown height. */\nfunction bottleTrunk(group: Group, material: MeshStandardMaterial, rng: Rng, height: number, baseR: number): number {\n  const trunkH = height * 0.68;\n  // Two stacked cylinders: a fat barrel, then a quick taper — the bottle bulge.\n  const belly = new Mesh(new CylinderGeometry(baseR * 0.62, baseR, trunkH * 0.66, 8), material);\n  belly.position.y = trunkH * 0.33;\n  group.add(belly);\n  const neck = new Mesh(new CylinderGeometry(baseR * 0.28, baseR * 0.62, trunkH * 0.34, 8), material);\n  neck.position.y = trunkH * 0.66 + trunkH * 0.17;\n  group.add(neck);\n  // A few stubby top branches.\n  const arms = rng.int(3, 5);\n  for (let i = 0; i < arms; i++) {\n    const a = (i / arms) * Math.PI * 2 + rng.range(-0.2, 0.2);\n    const arm = new Mesh(new CylinderGeometry(0.05, 0.11, height * 0.22, 5), material);\n    arm.position.set(Math.cos(a) * baseR * 0.3, trunkH + height * 0.06, Math.sin(a) * baseR * 0.3);\n    arm.rotation.set(-Math.sin(a) * 0.9, 0, Math.cos(a) * 0.9);\n    group.add(arm);\n  }\n  return trunkH + height * 0.12;\n}\n\n/** Aerial prop-roots dropping from the crown to the ground — a banyan. */\nfunction aerialRoots(group: Group, material: MeshStandardMaterial, rng: Rng, cy: number, radius: number, count: number): void {\n  for (let i = 0; i < count; i++) {\n    const a = (i / count) * Math.PI * 2 + rng.range(-0.2, 0.2);\n    const rr = radius * rng.range(0.45, 1.0);\n    const h = cy - 0.02;\n    const root = new Mesh(new CylinderGeometry(rng.range(0.04, 0.08), rng.range(0.07, 0.13), h, 5), material);\n    root.position.set(Math.cos(a) * rr, h / 2, Math.sin(a) * rr);\n    root.rotation.z = rng.range(-0.06, 0.06);\n    root.rotation.x = rng.range(-0.06, 0.06);\n    group.add(root);\n  }\n}\n\n/**\n * A species recipe: the height band, its wind response (how stiffly it sways),\n * its steering footprint, and how to build it. `build` returns the single\n * foliage material — the one the wind binds, leaving the trunk planted.\n */\ninterface Recipe {\n  heightRange: [number, number];\n  /** Wind stiffness exponent (higher = stiffer base). */\n  stiffness: number;\n  /** Fraction of height below which nothing sways (keeps the trunk still). */\n  anchorFrac: number;\n  /** Steering footprint radius (the GAMA handshake) — a number, or scaled from height for giants. */\n  obstacleRadius: number | ((height: number) => number);\n  build(group: Group, rng: Rng, palette: Palette, height: number, season?: TreeSeason): MeshStandardMaterial;\n}\n\n// --- species recipes ----------------------------------------------------\n\nconst SPECIES: Record<TreeSpecies, Recipe> = {\n  // Stacked cones — the classic conifer. (Verbatim from the original, so every\n  // seeded forest built before the species system renders identically.)\n  pine: {\n    heightRange: [3.2, 5.2],\n    stiffness: 2.4,\n    anchorFrac: 0.22,\n    obstacleRadius: 0.5,\n    build(group, rng, palette, height) {\n      const trunkMaterial = mat(palette.trunk);\n      const foliageMaterial = mat(rng.pick(palette.foliage));\n      const trunkHeight = height * 0.25;\n      const trunk = new Mesh(new CylinderGeometry(0.09, 0.14, trunkHeight, 6), trunkMaterial);\n      trunk.position.y = trunkHeight / 2;\n      group.add(trunk);\n\n      const tiers = rng.int(3, 4);\n      let y = trunkHeight;\n      let radius = height * rng.range(0.24, 0.3);\n      const tierHeight = (height - trunkHeight) / tiers + 0.15;\n      for (let i = 0; i < tiers; i++) {\n        const cone = new Mesh(new ConeGeometry(radius, tierHeight * 1.35, 7), foliageMaterial);\n        cone.position.y = y + tierHeight * 0.55;\n        cone.rotation.y = rng.range(0, Math.PI);\n        group.add(cone);\n        y += tierHeight * 0.8;\n        radius *= 0.72;\n      }\n      return foliageMaterial;\n    },\n  },\n\n  // Foliage blobs on a forked trunk. (Verbatim from the original.)\n  oak: {\n    heightRange: [3.2, 5.2],\n    stiffness: 2.4,\n    anchorFrac: 0.22,\n    obstacleRadius: 0.6,\n    build(group, rng, palette, height) {\n      const trunkMaterial = mat(palette.trunk);\n      const foliageMaterial = mat(rng.pick(palette.foliage));\n      const trunkHeight = height * 0.45;\n      const trunk = new Mesh(new CylinderGeometry(0.12, 0.2, trunkHeight, 6), trunkMaterial);\n      trunk.position.y = trunkHeight / 2;\n      trunk.rotation.z = rng.range(-0.08, 0.08);\n      group.add(trunk);\n\n      const blobs = rng.int(2, 4);\n      for (let i = 0; i < blobs; i++) {\n        const radius = height * rng.range(0.18, 0.28);\n        const blob = new Mesh(new IcosahedronGeometry(radius, 0), foliageMaterial);\n        blob.position.set(\n          rng.jitter(0, height * 0.16),\n          trunkHeight + radius * rng.range(0.5, 0.9) + i * radius * 0.35,\n          rng.jitter(0, height * 0.16)\n        );\n        blob.rotation.set(rng.range(0, Math.PI), rng.range(0, Math.PI), 0);\n        group.add(blob);\n      }\n      return foliageMaterial;\n    },\n  },\n\n  // Tall, narrow flame — a lumpy column of deep-green foliage tapering to a\n  // point. Barely moves in the wind; perfect for avenues and cemeteries.\n  cypress: {\n    heightRange: [6, 10],\n    stiffness: 3.4,\n    anchorFrac: 0.32,\n    obstacleRadius: 0.35,\n    build(group, rng, palette, height) {\n      const trunkMaterial = mat(palette.trunk);\n      const foliageMaterial = mat(tint(rng.pick(palette.foliage), 0x123a24, 0.5)); // deep green\n      const trunkH = height * 0.14;\n      const trunk = new Mesh(new CylinderGeometry(0.07, 0.11, trunkH, 6), trunkMaterial);\n      trunk.position.y = trunkH / 2;\n      group.add(trunk);\n\n      const maxR = height * 0.075; // narrow flame\n      const crownBase = trunkH * 0.6;\n      const crownH = height - crownBase;\n      const tiers = Math.max(7, Math.round(crownH / (maxR * 1.4)));\n      const step = crownH / tiers;\n      for (let i = 0; i < tiers; i++) {\n        const f = i / (tiers - 1);\n        // Rounded low, tapering steadily to a slim top.\n        const r = Math.max(0.05, maxR * (0.55 + 0.7 * Math.pow(1 - f, 0.8)) * (0.6 + 0.4 * Math.sin(f * Math.PI)));\n        const blob = new Mesh(new IcosahedronGeometry(r, 0), foliageMaterial);\n        blob.position.set(rng.jitter(0, maxR * 0.12), crownBase + i * step + step * 0.5, rng.jitter(0, maxR * 0.12));\n        blob.scale.y = 1.5; // stretch into a smooth column\n        blob.rotation.set(rng.range(0, Math.PI), rng.range(0, Math.PI), rng.range(0, Math.PI));\n        group.add(blob);\n      }\n      // A pointed cap to finish the flame.\n      const cap = new Mesh(new ConeGeometry(maxR * 0.7, crownH * 0.22, 6), foliageMaterial);\n      cap.position.y = crownBase + crownH + crownH * 0.02;\n      group.add(cap);\n      return foliageMaterial;\n    },\n  },\n\n  // Slender, high-canopied, pale cream bark with dark bands and a loose, light\n  // yellow-green crown.\n  birch: {\n    heightRange: [4, 7],\n    stiffness: 1.5,\n    anchorFrac: 0.45,\n    obstacleRadius: 0.32,\n    build(group, rng, palette, height) {\n      const barkMaterial = mat(0xe6e2d6); // birch cream\n      const bandMaterial = mat(0x4a453e);\n      const foliageMaterial = mat(tint(rng.pick(palette.foliage), 0xd2e69a, 0.4)); // light yellow-green\n      const trunkH = height * 0.72;\n      const trunk = new Mesh(new CylinderGeometry(0.05, 0.08, trunkH, 6), barkMaterial);\n      trunk.position.y = trunkH / 2;\n      trunk.rotation.z = rng.range(-0.04, 0.04);\n      group.add(trunk);\n\n      // Characteristic dark bark bands on the lower trunk.\n      const bands = rng.int(2, 4);\n      for (let i = 0; i < bands; i++) {\n        const band = new Mesh(new CylinderGeometry(0.076, 0.076, 0.05, 6), bandMaterial);\n        band.position.y = rng.range(trunkH * 0.15, trunkH * 0.8);\n        group.add(band);\n      }\n\n      // Sparse, loose crown up high.\n      const crownBase = trunkH * 0.85;\n      const blobs = rng.int(3, 5);\n      for (let i = 0; i < blobs; i++) {\n        const r = height * rng.range(0.12, 0.19);\n        const blob = new Mesh(new IcosahedronGeometry(r, 0), foliageMaterial);\n        blob.position.set(\n          rng.jitter(0, height * 0.14),\n          crownBase + rng.range(0, height * 0.22),\n          rng.jitter(0, height * 0.14)\n        );\n        blob.rotation.set(rng.range(0, Math.PI), rng.range(0, Math.PI), 0);\n        group.add(blob);\n      }\n      return foliageMaterial;\n    },\n  },\n\n  // Broad, flat horizontal tiers on a stout trunk — a spreading cedar.\n  cedar: {\n    heightRange: [4, 6],\n    stiffness: 2.8,\n    anchorFrac: 0.3,\n    obstacleRadius: 0.75,\n    build(group, rng, palette, height) {\n      const trunkMaterial = mat(palette.trunk);\n      const foliageMaterial = mat(tint(rng.pick(palette.foliage), 0x3a6b58, 0.45)); // blue-green\n      const trunkH = height * 0.32;\n      const trunk = new Mesh(new CylinderGeometry(0.13, 0.22, trunkH, 6), trunkMaterial);\n      trunk.position.y = trunkH / 2;\n      group.add(trunk);\n\n      const tiers = rng.int(3, 4);\n      const crownBase = trunkH * 0.8;\n      const crownH = height - crownBase;\n      const maxR = height * rng.range(0.4, 0.5); // broad\n      for (let i = 0; i < tiers; i++) {\n        const f = tiers > 1 ? i / (tiers - 1) : 0;\n        const r = maxR * (1 - f * 0.45);\n        const plate = new Mesh(new IcosahedronGeometry(r, 0), foliageMaterial);\n        plate.position.set(rng.jitter(0, maxR * 0.1), crownBase + f * crownH * 0.9, rng.jitter(0, maxR * 0.1));\n        plate.scale.y = 0.3; // flatten into a horizontal plate\n        plate.rotation.y = rng.range(0, Math.PI);\n        group.add(plate);\n      }\n      return foliageMaterial;\n    },\n  },\n\n  // A full, rounded dome on a straight trunk. Reads green in a meadow palette\n  // and blazes orange under the `autumn` palette.\n  maple: {\n    heightRange: [3.5, 5.5],\n    stiffness: 2.2,\n    anchorFrac: 0.24,\n    obstacleRadius: 0.65,\n    build(group, rng, palette, height) {\n      const trunkMaterial = mat(palette.trunk);\n      const foliageMaterial = mat(tint(rng.pick(palette.foliage), 0x86a83a, 0.2));\n      const trunkH = height * 0.4;\n      const trunk = new Mesh(new CylinderGeometry(0.12, 0.19, trunkH, 6), trunkMaterial);\n      trunk.position.y = trunkH / 2;\n      trunk.rotation.z = rng.range(-0.05, 0.05);\n      group.add(trunk);\n\n      const crownBase = trunkH + height * 0.12;\n      const R = height * rng.range(0.28, 0.34);\n      const center = new Mesh(new IcosahedronGeometry(R, 1), foliageMaterial); // detail 1 = rounder dome\n      center.position.y = crownBase;\n      center.rotation.set(rng.range(0, Math.PI), rng.range(0, Math.PI), 0);\n      group.add(center);\n\n      const ring = rng.int(4, 6);\n      for (let i = 0; i < ring; i++) {\n        const a = (i / ring) * Math.PI * 2 + rng.range(-0.2, 0.2);\n        const r = R * rng.range(0.55, 0.75);\n        const blob = new Mesh(new IcosahedronGeometry(r, 0), foliageMaterial);\n        blob.position.set(Math.cos(a) * R * 0.75, crownBase - R * 0.15 + rng.range(-0.1, 0.2), Math.sin(a) * R * 0.75);\n        blob.rotation.set(rng.range(0, Math.PI), rng.range(0, Math.PI), 0);\n        group.add(blob);\n      }\n      return foliageMaterial;\n    },\n  },\n\n  // A wide, low umbrella of blossom on a short dark trunk. `season` decides its\n  // dress: pink in spring, green in summer, warm in autumn, bare in winter.\n  sakura: {\n    heightRange: [3, 4.6],\n    stiffness: 2,\n    anchorFrac: 0.3,\n    obstacleRadius: 0.7,\n    build(group, rng, palette, height, season) {\n      const s = season ?? 'spring';\n      const barkMaterial = mat(tint(palette.trunk, 0x2e2320, 0.4)); // dark cherry bark\n      const trunkH = height * 0.4;\n      const trunk = new Mesh(new CylinderGeometry(0.1, 0.16, trunkH, 6), barkMaterial);\n      trunk.position.y = trunkH / 2;\n      trunk.rotation.z = rng.range(-0.06, 0.06);\n      group.add(trunk);\n      branches(group, barkMaterial, rng, trunkH, rng.int(4, 6), height * 0.5);\n\n      // Canopy colour by season (blossom pink is blossom pink, palette aside).\n      const canopyColor =\n        s === 'summer'\n          ? tint(rng.pick(palette.foliage), 0x7fb04a, 0.2)\n          : s === 'autumn'\n            ? tint(rng.pick(palette.foliage), 0xe08a3a, 0.7)\n            : tint(0xf3c1d6, 0xfdeaf1, rng.range(0, 0.4)); // spring blossom\n      const canopyMaterial = mat(canopyColor);\n\n      if (s !== 'winter') {\n        const crownBase = trunkH + height * 0.16;\n        const R = height * rng.range(0.34, 0.4);\n        const center = new Mesh(new IcosahedronGeometry(R, 1), canopyMaterial);\n        center.position.y = crownBase;\n        center.scale.y = 0.55; // flatten into an umbrella\n        group.add(center);\n        const ring = rng.int(5, 7);\n        for (let i = 0; i < ring; i++) {\n          const a = (i / ring) * Math.PI * 2 + rng.range(-0.2, 0.2);\n          const r = R * rng.range(0.5, 0.72);\n          const blob = new Mesh(new IcosahedronGeometry(r, 0), canopyMaterial);\n          blob.position.set(Math.cos(a) * R * 0.8, crownBase - R * 0.1 + rng.range(-0.05, 0.1), Math.sin(a) * R * 0.8);\n          blob.scale.y = 0.6;\n          group.add(blob);\n        }\n      }\n      return canopyMaterial;\n    },\n  },\n\n  // A curved bare stem crowned with long drooping fronds — a palm.\n  palm: {\n    heightRange: [5, 8],\n    stiffness: 1.2,\n    anchorFrac: 0.7,\n    obstacleRadius: 0.4,\n    build(group, rng, palette, height) {\n      const trunkMaterial = mat(tint(0x9c7b4e, palette.trunk, 0.3)); // tan stem\n      const crown = curvedTrunk(group, trunkMaterial, height * 0.86, 0.16, 0.1, height * 0.12);\n      const frondMaterial = mat(tint(rng.pick(palette.foliage), 0x4e8f3a, 0.3));\n      frondCrown(group, frondMaterial, rng, crown.x, crown.y, rng.int(9, 13), height * 0.42, 24);\n      // A cluster of coconuts under the crown.\n      const nutMaterial = mat(0x6b4a2f);\n      const nuts = rng.int(2, 4);\n      for (let i = 0; i < nuts; i++) {\n        const a = (i / nuts) * Math.PI * 2;\n        const nut = new Mesh(new IcosahedronGeometry(height * 0.045, 0), nutMaterial);\n        nut.position.set(crown.x + Math.cos(a) * 0.12, crown.y - 0.12, Math.sin(a) * 0.12);\n        group.add(nut);\n      }\n      return frondMaterial;\n    },\n  },\n\n  // A rounded crown trailing a veil of long swaying strands — a weeping willow.\n  willow: {\n    heightRange: [4, 6],\n    stiffness: 1.5,\n    anchorFrac: 0.05,\n    obstacleRadius: 0.7,\n    build(group, rng, palette, height) {\n      const trunkMaterial = mat(palette.trunk);\n      const trunkH = height * 0.42;\n      const trunk = new Mesh(new CylinderGeometry(0.12, 0.2, trunkH, 6), trunkMaterial);\n      trunk.position.y = trunkH / 2;\n      trunk.rotation.z = rng.range(-0.05, 0.05);\n      group.add(trunk);\n\n      const foliageMaterial = mat(tint(rng.pick(palette.foliage), 0xb6cf6e, 0.4)); // willow yellow-green\n      const crownBase = trunkH + height * 0.22;\n      const R = height * rng.range(0.32, 0.4);\n      const dome = new Mesh(new IcosahedronGeometry(R, 1), foliageMaterial);\n      dome.position.y = crownBase;\n      dome.scale.y = 0.7;\n      group.add(dome);\n\n      // The signature: a veil of strands hanging from the canopy hem.\n      droopStrands(group, foliageMaterial, rng, crownBase - R * 0.35, R * 0.95, rng.int(30, 38), height * 0.42, height * 0.72);\n      return foliageMaterial;\n    },\n  },\n\n  // A colossus — a thick buttressed redwood trunk carrying a high conical crown.\n  // Towers over an ordinary wood; place it sparingly.\n  sequoia: {\n    heightRange: [22, 32],\n    stiffness: 4,\n    anchorFrac: 0.5,\n    obstacleRadius: (h) => h * 0.06,\n    build(group, rng, palette, height) {\n      const barkMaterial = mat(0x8a4b32); // redwood bark\n      const foliageMaterial = mat(tint(rng.pick(palette.foliage), 0x1f4a34, 0.5)); // deep green\n      const baseR = height * 0.075;\n      buttressTrunk(group, barkMaterial, rng, height * 0.55, baseR, baseR * 0.4);\n\n      // A tall conical crown of stacked cones over the upper trunk.\n      const tiers = rng.int(5, 7);\n      let y = height * 0.42;\n      let radius = height * rng.range(0.16, 0.2);\n      const tierH = (height - y) / tiers + 0.4;\n      for (let i = 0; i < tiers; i++) {\n        const cone = new Mesh(new ConeGeometry(radius, tierH * 1.4, 8), foliageMaterial);\n        cone.position.y = y + tierH * 0.55;\n        cone.rotation.y = rng.range(0, Math.PI);\n        group.add(cone);\n        y += tierH * 0.82;\n        radius *= 0.74;\n      }\n      return foliageMaterial;\n    },\n  },\n\n  // A vast crown resting on a stout trunk and a curtain of aerial prop-roots —\n  // a whole grove from one tree.\n  banyan: {\n    heightRange: [5, 8],\n    stiffness: 3,\n    anchorFrac: 0.3,\n    obstacleRadius: (h) => h * 0.3,\n    build(group, rng, palette, height) {\n      const barkMaterial = mat(tint(palette.trunk, 0x4a3320, 0.3));\n      const foliageMaterial = mat(tint(rng.pick(palette.foliage), 0x1d5a3a, 0.35));\n      const trunkH = height * 0.4;\n      const trunk = new Mesh(new CylinderGeometry(height * 0.09, height * 0.15, trunkH, 8), barkMaterial);\n      trunk.position.y = trunkH / 2;\n      group.add(trunk);\n\n      const crownBase = trunkH + height * 0.2;\n      const R = height * rng.range(0.5, 0.62); // very wide\n      const center = new Mesh(new IcosahedronGeometry(R, 1), foliageMaterial);\n      center.position.y = crownBase;\n      center.scale.y = 0.62;\n      group.add(center);\n      const ring = rng.int(6, 9);\n      for (let i = 0; i < ring; i++) {\n        const a = (i / ring) * Math.PI * 2 + rng.range(-0.15, 0.15);\n        const r = R * rng.range(0.45, 0.65);\n        const blob = new Mesh(new IcosahedronGeometry(r, 0), foliageMaterial);\n        blob.position.set(Math.cos(a) * R * 0.85, crownBase - R * 0.12 + rng.range(-0.1, 0.15), Math.sin(a) * R * 0.85);\n        blob.scale.y = 0.7;\n        group.add(blob);\n      }\n      // Aerial roots drop from the crown to the ground.\n      aerialRoots(group, barkMaterial, rng, crownBase - R * 0.3, R * 0.7, rng.int(7, 11));\n      return foliageMaterial;\n    },\n  },\n\n  // A fat bottle trunk under a sparse, high crown — the upside-down savanna tree.\n  baobab: {\n    heightRange: [5, 8],\n    stiffness: 3.5,\n    anchorFrac: 0.55,\n    obstacleRadius: (h) => h * 0.16,\n    build(group, rng, palette, height) {\n      const barkMaterial = mat(tint(palette.trunk, 0x8f8272, 0.5)); // pale grey-brown bark\n      const foliageMaterial = mat(tint(rng.pick(palette.foliage), 0x6f8a3a, 0.3));\n      const crownY = bottleTrunk(group, barkMaterial, rng, height, height * 0.19);\n\n      // Sparse tufts of foliage at the branch tips.\n      const tufts = rng.int(4, 6);\n      for (let i = 0; i < tufts; i++) {\n        const a = (i / tufts) * Math.PI * 2 + rng.range(-0.3, 0.3);\n        const r = height * rng.range(0.12, 0.18);\n        const tuft = new Mesh(new IcosahedronGeometry(r, 0), foliageMaterial);\n        tuft.position.set(Math.cos(a) * height * 0.22, crownY + rng.range(0, height * 0.1), Math.sin(a) * height * 0.22);\n        tuft.scale.y = 0.7;\n        group.add(tuft);\n      }\n      return foliageMaterial;\n    },\n  },\n\n  // A thin trunk under a broad, flat-topped umbrella — the acacia of the savanna.\n  acacia: {\n    heightRange: [4, 6],\n    stiffness: 2.5,\n    anchorFrac: 0.4,\n    obstacleRadius: 0.5,\n    build(group, rng, palette, height) {\n      const barkMaterial = mat(tint(palette.trunk, 0x6a5030, 0.3));\n      const foliageMaterial = mat(tint(rng.pick(palette.foliage), 0x8fa04a, 0.35)); // dusty savanna green\n      const trunkH = height * 0.62;\n      const trunk = new Mesh(new CylinderGeometry(0.06, 0.13, trunkH, 6), barkMaterial);\n      trunk.position.y = trunkH / 2;\n      trunk.rotation.z = rng.range(-0.05, 0.05);\n      group.add(trunk);\n\n      // The umbrella: a wide, very flat canopy of overlapping plates.\n      const crownBase = trunkH + height * 0.08;\n      const R = height * rng.range(0.5, 0.6);\n      const plates = rng.int(3, 4);\n      for (let i = 0; i < plates; i++) {\n        const r = R * (1 - i * 0.16);\n        const plate = new Mesh(new IcosahedronGeometry(r, 0), foliageMaterial);\n        plate.position.set(rng.jitter(0, R * 0.12), crownBase + i * height * 0.05, rng.jitter(0, R * 0.12));\n        plate.scale.y = 0.22; // very flat umbrella\n        plate.rotation.y = rng.range(0, Math.PI);\n        group.add(plate);\n      }\n      return foliageMaterial;\n    },\n  },\n};\n\n/**\n * A seeded low-poly tree. Nine species — `pine` and `oak` (the originals), plus\n * `cypress` (a tall narrow flame), `birch` (slender, pale, banded), `cedar`\n * (broad flat tiers), `maple` (a full rounded dome), `sakura` (a blossom\n * umbrella), `palm` (a curved stem with drooping fronds) and `willow` (a veil of\n * swaying strands) — each with its own silhouette, colour, wind response and\n * steering footprint. Same seed → identical tree, forever.\n *\n * New species are opt-in via `species`; with none given, a forest stays the\n * familiar pine/oak mix, so existing scenes are untouched. `season` dresses a\n * `sakura` — pink in spring, green in summer, warm in autumn, bare in winter.\n *\n * ```ts\n * const cypress = createTree({ species: 'cypress', seed: 7 });\n * const bloom = createTree({ species: 'sakura', season: 'spring' });\n * const palm = createTree({ species: 'palm', seed: 3 });\n * ```\n */\nexport function createTree(options: TreeOptions = {}): Prop {\n  const rng = new Rng(options.seed ?? 1);\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  // Default stays pine/oak (one rng draw), so seeded forests never change.\n  const species = options.species ?? options.style ?? (rng.next() < 0.6 ? 'pine' : 'oak');\n  const recipe = SPECIES[species];\n  const height = options.height ?? rng.range(recipe.heightRange[0], recipe.heightRange[1]);\n\n  const group = new Group();\n  group.name = `tree-${species}`;\n  const foliageMaterial = recipe.build(group, rng, palette, height, options.season);\n  // Tag the canopy material so a Seasons controller can find and re-grade it\n  // (spring→autumn→winter) while leaving the trunk planted and unchanged.\n  (foliageMaterial.userData ??= {}).scenaFoliage = true;\n\n  // Only the canopy sways — the trunk material is left unbound, so it stays\n  // planted. (For a scattered forest, prefer applyWind(forest.group), which\n  // drives the shared clock from the rendered InstancedMesh.)\n  if (options.wind) {\n    options.wind.bind(foliageMaterial, {\n      height,\n      stiffness: recipe.stiffness,\n      anchor: height * recipe.anchorFrac,\n    });\n    options.wind.attach(group);\n  }\n\n  const obstacleRadius =\n    typeof recipe.obstacleRadius === 'function' ? recipe.obstacleRadius(height) : recipe.obstacleRadius;\n  return { object: group, obstacleRadius };\n}\n\n// --- biomes: a weighted species mix for scattering a wood in one call --------\n\nexport type TreeBiome =\n  | 'temperate'\n  | 'boreal'\n  | 'mediterranean'\n  | 'tropical'\n  | 'savanna'\n  | 'redwood'\n  | 'grove'\n  | 'wetland';\n\n/** The species mix (and relative frequency) each biome scatters. */\nexport const TREE_BIOMES: Record<TreeBiome, ReadonlyArray<{ species: TreeSpecies; weight: number }>> = {\n  temperate: [{ species: 'oak', weight: 4 }, { species: 'pine', weight: 3 }, { species: 'birch', weight: 2 }, { species: 'maple', weight: 2 }],\n  boreal: [{ species: 'pine', weight: 5 }, { species: 'cedar', weight: 2 }, { species: 'birch', weight: 2 }],\n  mediterranean: [{ species: 'cypress', weight: 3 }, { species: 'oak', weight: 3 }, { species: 'pine', weight: 2 }],\n  tropical: [{ species: 'palm', weight: 5 }, { species: 'banyan', weight: 1 }],\n  savanna: [{ species: 'acacia', weight: 4 }, { species: 'baobab', weight: 1 }],\n  redwood: [{ species: 'sequoia', weight: 1 }, { species: 'pine', weight: 4 }, { species: 'cedar', weight: 2 }],\n  grove: [{ species: 'sakura', weight: 1 }],\n  wetland: [{ species: 'willow', weight: 3 }, { species: 'birch', weight: 2 }],\n};\n\nexport interface TreeBiomeOptions {\n  palette?: Palette;\n  season?: TreeSeason;\n  /** Visual variants generated per species. Default 4. */\n  variants?: number;\n}\n\n/**\n * The species mix for a biome, ready to drop into `scatter({ items })` — so a\n * whole wood takes on a character in one word. A `redwood` stand towers with\n * sequoias over pines; a `tropical` shore is palms and the odd banyan; a\n * `savanna` is acacias and a baobab. Each species keeps its own silhouette,\n * wind response and (height-scaled) steering footprint.\n *\n * ```ts\n * scatter({ items: treeBiome('tropical', { palette }), area, density: 0.02 });\n * ```\n */\nexport function treeBiome(biome: TreeBiome, options: TreeBiomeOptions = {}): Array<{\n  create: (rng: Rng) => Prop;\n  weight: number;\n  variants: number;\n}> {\n  return TREE_BIOMES[biome].map(({ species, weight }) => ({\n    create: (rng: Rng) =>\n      createTree({ species, seed: rng.int(1, 1e9), palette: options.palette, season: options.season }),\n    weight,\n    variants: options.variants ?? 4,\n  }));\n}\n","import { BufferAttribute, Group, IcosahedronGeometry, Mesh } from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport { createSurface } from '../materials/surface';\nimport type { Prop } from '../core/types';\n\nexport interface RockOptions {\n  seed?: number;\n  /** Approximate radius. Default ~0.4–1.1 by seed. */\n  size?: number;\n  palette?: Palette;\n}\n\n/**\n * A seeded low-poly boulder: an icosahedron with jittered vertices and a\n * flattened underside so it sits on the ground.\n */\nexport function createRock(options: RockOptions = {}): Prop {\n  const rng = new Rng(options.seed ?? 1);\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const size = options.size ?? rng.range(0.4, 1.1);\n\n  const geometry = new IcosahedronGeometry(size, 0);\n  const positions = geometry.getAttribute('position') as BufferAttribute;\n  // Jitter welded-by-value: identical vertex values get identical offsets,\n  // so faces stay connected.\n  const seen = new Map<string, [number, number, number]>();\n  for (let i = 0; i < positions.count; i++) {\n    const key = `${positions.getX(i).toFixed(4)},${positions.getY(i).toFixed(4)},${positions.getZ(i).toFixed(4)}`;\n    let offset = seen.get(key);\n    if (!offset) {\n      offset = [rng.jitter(0, size * 0.22), rng.jitter(0, size * 0.16), rng.jitter(0, size * 0.22)];\n      seen.set(key, offset);\n    }\n    positions.setXYZ(\n      i,\n      positions.getX(i) + offset[0],\n      Math.max(positions.getY(i) + offset[1], -size * 0.15), // flatten the bottom\n      positions.getZ(i) + offset[2]\n    );\n  }\n  geometry.computeVertexNormals();\n\n  const rock = new Mesh(\n    geometry,\n    createSurface('stone', { color: rng.pick(palette.rock), seed: options.seed ?? 1 })\n  );\n  rock.position.y = size * 0.15;\n  rock.scale.y = rng.range(0.6, 0.9);\n\n  const group = new Group();\n  group.name = 'rock';\n  group.add(rock);\n  return { object: group, obstacleRadius: size * 1.05 };\n}\n","import { BoxGeometry, CylinderGeometry, Group, Mesh, MeshStandardMaterial } from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { Prop } from '../core/types';\n\nexport interface FenceOptions {\n  seed?: number;\n  /** Run length along local +x. Default 6. */\n  length?: number;\n  postSpacing?: number;\n  height?: number;\n  palette?: Palette;\n}\n\n/**\n * A rustic fence run along local +x, centered at the origin: posts with\n * two slightly-crooked rails. Chain several and rotate to enclose areas.\n * The obstacle radius covers the whole run (rough but steering-safe);\n * for tight navigation, bake a navmesh — the geometry is authoritative.\n */\nexport function createFence(options: FenceOptions = {}): Prop {\n  const rng = new Rng(options.seed ?? 1);\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const length = options.length ?? 6;\n  const spacing = options.postSpacing ?? 1.5;\n  const height = options.height ?? 1.1;\n\n  const group = new Group();\n  group.name = 'fence';\n  const postMaterial = new MeshStandardMaterial({ color: palette.woodDark, flatShading: true });\n  const railMaterial = new MeshStandardMaterial({ color: palette.wood, flatShading: true });\n\n  const posts = Math.max(2, Math.round(length / spacing) + 1);\n  const step = length / (posts - 1);\n  for (let i = 0; i < posts; i++) {\n    const post = new Mesh(new CylinderGeometry(0.06, 0.075, height, 5), postMaterial);\n    post.position.set(-length / 2 + i * step, height / 2, rng.jitter(0, 0.03));\n    post.rotation.z = rng.range(-0.04, 0.04);\n    group.add(post);\n  }\n  for (const railY of [height * 0.55, height * 0.85]) {\n    const rail = new Mesh(new BoxGeometry(length, 0.07, 0.05), railMaterial);\n    rail.position.y = rng.jitter(railY, 0.02);\n    rail.rotation.x = rng.range(-0.02, 0.02);\n    group.add(rail);\n  }\n\n  return { object: group, obstacleRadius: length / 2 };\n}\n","import { ConeGeometry, Group, IcosahedronGeometry, Mesh, MeshStandardMaterial } from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { WindField } from '../environment/wind';\nimport type { Prop } from '../core/types';\n\nexport interface GrassOptions {\n  seed?: number;\n  /** Blades per tuft. Default 4–6 by seed. */\n  blades?: number;\n  /** A WindField to sway the blades in. */\n  wind?: WindField;\n  palette?: Palette;\n}\n\n/**\n * A tuft of grass blades — pure scatter fodder (zero obstacle footprint,\n * walk straight through). Sways beautifully under `applyWind`.\n */\nexport function createGrassTuft(options: GrassOptions = {}): Prop {\n  const rng = new Rng(options.seed ?? 1);\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const blades = options.blades ?? rng.int(4, 6);\n  const group = new Group();\n  group.name = 'grass';\n  const material = new MeshStandardMaterial({\n    color: rng.next() < 0.5 ? palette.grassHigh : rng.pick(palette.foliage),\n    flatShading: true,\n  });\n  for (let i = 0; i < blades; i++) {\n    const height = rng.range(0.25, 0.5);\n    const blade = new Mesh(new ConeGeometry(0.035, height, 3), material);\n    blade.position.set(rng.jitter(0, 0.12), height / 2, rng.jitter(0, 0.12));\n    blade.rotation.set(rng.range(-0.25, 0.25), rng.range(0, Math.PI), rng.range(-0.25, 0.25));\n    group.add(blade);\n  }\n  // Whole-blade sway from near the base (soft, stiffness ~1.2).\n  if (options.wind) options.wind.sway(group, { height: 0.5, stiffness: 1.2, anchor: 0.04 });\n  return { object: group, obstacleRadius: 0 };\n}\n\nexport interface BushOptions {\n  seed?: number;\n  size?: number;\n  /** A WindField to gently sway the foliage in. */\n  wind?: WindField;\n  palette?: Palette;\n}\n\n/** A low foliage bush: two or three squashed blobs. Small footprint. */\nexport function createBush(options: BushOptions = {}): Prop {\n  const rng = new Rng(options.seed ?? 1);\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const size = options.size ?? rng.range(0.4, 0.7);\n  const group = new Group();\n  group.name = 'bush';\n  const material = new MeshStandardMaterial({ color: rng.pick(palette.foliage), flatShading: true });\n  const blobs = rng.int(2, 3);\n  for (let i = 0; i < blobs; i++) {\n    const radius = size * rng.range(0.55, 0.85);\n    const blob = new Mesh(new IcosahedronGeometry(radius, 0), material);\n    blob.position.set(rng.jitter(0, size * 0.4), radius * 0.7, rng.jitter(0, size * 0.4));\n    blob.scale.y = rng.range(0.7, 0.85);\n    blob.rotation.y = rng.range(0, Math.PI);\n    group.add(blob);\n  }\n  // Gentle, stiff sway — a bush barely nods.\n  if (options.wind) options.wind.sway(group, { height: size, stiffness: 2.2, anchor: size * 0.25 });\n  return { object: group, obstacleRadius: size * 0.6 };\n}\n","import { Vector3, type Object3D } from 'three';\nimport type { Obstacle } from '../core/types';\n\nexport interface Markers {\n  /** `spawn_<name>` → world position. */\n  spawns: Record<string, Vector3>;\n  /** `route_<name>_<index>` → world positions ordered by index. */\n  routes: Record<string, Vector3[]>;\n  /** `obstacle_<name>` → steering obstacle (radius from the node's scale). */\n  obstacles: Obstacle[];\n  /** `keepout_<name>` → scatter keep-out circle (radius from scale). */\n  keepOut: Array<{ center: { x: number; z: number }; radius: number }>;\n}\n\n/**\n * Extract gameplay markers from an object tree by naming convention — the\n * bridge between a DCC tool (Blender empties, glTF nodes) and SCENA/GAMA:\n *\n * - `spawn_player`, `spawn_boss` → named spawn points\n * - `route_patrol_0`, `route_patrol_1`, … → ordered patrol routes\n * - `obstacle_statue` → steering obstacle; radius = max(scale.x, scale.z)\n * - `keepout_plaza` → scatter keep-out circle; radius = max(scale.x, scale.z)\n *\n * Blender's duplicate suffixes (`.001`) are stripped, so `route_a_0.001`\n * still parses. Positions are world-space (the tree is updated first).\n *\n * ```ts\n * const gltf = await new GLTFLoader().loadAsync('level.glb');\n * const markers = extractMarkers(gltf.scene);\n * player.position.copy(markers.spawns.player);\n * guard.addBehavior(new FollowPath(new Path(markers.routes.patrol, true), 1.5));\n * scatter({ ..., keepOut: markers.keepOut });\n * ```\n */\nexport function extractMarkers(root: Object3D): Markers {\n  root.updateWorldMatrix(true, true);\n  const spawns: Record<string, Vector3> = {};\n  const routePoints: Record<string, Array<{ index: number; position: Vector3 }>> = {};\n  const obstacles: Obstacle[] = [];\n  const keepOut: Array<{ center: { x: number; z: number }; radius: number }> = [];\n\n  root.traverse((node) => {\n    const name = node.name.replace(/\\.\\d+$/, ''); // Blender's `.001` suffixes\n    const match = /^(spawn|route|obstacle|keepout)_(.+)$/.exec(name);\n    if (!match) return;\n    const [, kind, rest] = match;\n    const position = node.getWorldPosition(new Vector3());\n    const radius = Math.max(node.scale.x, node.scale.z);\n\n    if (kind === 'spawn') {\n      spawns[rest] = position;\n    } else if (kind === 'route') {\n      const step = /^(.*)_(\\d+)$/.exec(rest);\n      const routeName = step ? step[1] : rest;\n      const index = step ? parseInt(step[2], 10) : 0;\n      (routePoints[routeName] ??= []).push({ index, position });\n    } else if (kind === 'obstacle') {\n      obstacles.push({ center: position, radius });\n    } else {\n      keepOut.push({ center: { x: position.x, z: position.z }, radius });\n    }\n  });\n\n  const routes: Record<string, Vector3[]> = {};\n  for (const [name, points] of Object.entries(routePoints)) {\n    routes[name] = points.sort((a, b) => a.index - b.index).map((p) => p.position);\n  }\n  return { spawns, routes, obstacles, keepOut };\n}\n","import {\n  BoxGeometry,\n  CylinderGeometry,\n  Group,\n  InstancedMesh,\n  Matrix4,\n  Mesh,\n  MeshStandardMaterial,\n  PointLight,\n  SphereGeometry,\n  Vector3,\n} from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { Obstacle } from '../core/types';\n\n/**\n * The kit grid: every kit piece snaps to this cell size (in world units).\n * Shared snap dimensions are what make pieces combinable — a doorway cut\n * in one wall lines up with the corridor on the other side.\n */\nexport const KIT_UNIT = 2;\n\nexport interface KitOptions {\n  seed?: number;\n  /** Cell size override. Default KIT_UNIT. */\n  unit?: number;\n  /** Wall height. Default 2.6. */\n  wallHeight?: number;\n  /** Add real PointLights to this many torches. Default 4. */\n  torchLights?: number;\n  palette?: Palette;\n}\n\nexport interface Kit {\n  group: Group;\n  /** One obstacle per wall cell — feed GAMA's ObstacleAvoidance. */\n  obstacles: Obstacle[];\n  /** World positions of 'S' cells (player/NPC spawn points). */\n  spawns: Vector3[];\n  /** World positions of 'T' cells (torches), lit in placement order. */\n  torches: Vector3[];\n  /** Is (x, z) over a walkable floor cell? */\n  floorAt(x: number, z: number): boolean;\n  /** Footprint in world units: { width, depth } centered on the origin. */\n  size: { width: number; depth: number };\n}\n\n/**\n * Assemble a dungeon/compound from an ASCII map — each character is one\n * KIT_UNIT × KIT_UNIT cell, centered on the group origin:\n *\n * - `#` wall block (blocks movement, becomes an obstacle)\n * - `.` floor tile\n * - `D` doorway: floor + lintel spanning the gap overhead\n * - `T` floor + standing torch (emissive flame; `createDayCycle` adopts it)\n * - `S` floor + recorded spawn point\n * - ` ` nothing\n *\n * ```ts\n * const fort = assembleKit([\n *   '#######',\n *   '#..T..#',\n *   '#.....D',\n *   '#..S..#',\n *   '#######',\n * ], { palette });\n * fort.group.position.set(20, terrain.heightAt(20, 5), 5);\n * ```\n *\n * Walls and floors render as two InstancedMeshes regardless of map size.\n */\nexport function assembleKit(rows: string[], options: KitOptions = {}): Kit {\n  const rng = new Rng(options.seed ?? 1);\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const unit = options.unit ?? KIT_UNIT;\n  const wallHeight = options.wallHeight ?? 2.6;\n  let torchLights = options.torchLights ?? 4;\n\n  const height = rows.length;\n  const width = Math.max(...rows.map((r) => r.length), 0);\n  const originX = (-width / 2 + 0.5) * unit;\n  const originZ = (-height / 2 + 0.5) * unit;\n  const worldOf = (col: number, row: number): { x: number; z: number } => ({\n    x: originX + col * unit,\n    z: originZ + row * unit,\n  });\n\n  const group = new Group();\n  group.name = 'kit';\n  const obstacles: Obstacle[] = [];\n  const spawns: Vector3[] = [];\n  const torches: Vector3[] = [];\n  const floorCells = new Set<string>();\n\n  const wallCells: Array<{ x: number; z: number }> = [];\n  const floorTiles: Array<{ x: number; z: number }> = [];\n\n  for (let row = 0; row < height; row++) {\n    for (let col = 0; col < (rows[row] ?? '').length; col++) {\n      const cell = rows[row][col];\n      if (cell === ' ' || cell === undefined) continue;\n      const { x, z } = worldOf(col, row);\n\n      if (cell === '#') {\n        wallCells.push({ x, z });\n        obstacles.push({ center: new Vector3(x, wallHeight / 2, z), radius: unit * 0.71 });\n        continue;\n      }\n      // Everything else stands on a floor tile.\n      floorTiles.push({ x, z });\n      floorCells.add(`${col},${row}`);\n\n      if (cell === 'D') {\n        // Lintel over the opening, aligned with whichever axis the walls run.\n        const horizontalRun =\n          rows[row][col - 1] === '#' || rows[row][col + 1] === '#';\n        const lintel = new Mesh(\n          new BoxGeometry(\n            horizontalRun ? unit : unit * 0.4,\n            wallHeight * 0.25,\n            horizontalRun ? unit * 0.4 : unit\n          ),\n          new MeshStandardMaterial({ color: palette.woodDark, flatShading: true })\n        );\n        lintel.position.set(x, wallHeight * 0.875, z);\n        group.add(lintel);\n      } else if (cell === 'T') {\n        group.add(createTorch(x, z, palette, rng, torchLights > 0));\n        torchLights--;\n        torches.push(new Vector3(x, 0, z));\n        obstacles.push({ center: new Vector3(x, 0, z), radius: 0.3 });\n      } else if (cell === 'S') {\n        spawns.push(new Vector3(x, 0, z));\n      }\n    }\n  }\n\n  // Two draw calls for the architecture: instanced walls + instanced floors.\n  const stone = new MeshStandardMaterial({ color: rng.pick(palette.rock), flatShading: true });\n  const stoneDark = new MeshStandardMaterial({ color: palette.cliff, flatShading: true });\n  const matrix = new Matrix4();\n  if (wallCells.length > 0) {\n    const walls = new InstancedMesh(\n      new BoxGeometry(unit, wallHeight, unit),\n      stone,\n      wallCells.length\n    );\n    wallCells.forEach((cell, i) => {\n      walls.setMatrixAt(i, matrix.makeTranslation(cell.x, wallHeight / 2, cell.z));\n    });\n    walls.instanceMatrix.needsUpdate = true;\n    group.add(walls);\n  }\n  if (floorTiles.length > 0) {\n    const floors = new InstancedMesh(\n      new BoxGeometry(unit, 0.2, unit),\n      stoneDark,\n      floorTiles.length\n    );\n    floorTiles.forEach((cell, i) => {\n      floors.setMatrixAt(i, matrix.makeTranslation(cell.x, -0.1, cell.z));\n    });\n    floors.instanceMatrix.needsUpdate = true;\n    group.add(floors);\n  }\n\n  return {\n    group,\n    obstacles,\n    spawns,\n    torches,\n    floorAt(x, z) {\n      const col = Math.round((x - originX) / unit);\n      const row = Math.round((z - originZ) / unit);\n      return floorCells.has(`${col},${row}`);\n    },\n    size: { width: width * unit, depth: height * unit },\n  };\n}\n\nfunction createTorch(\n  x: number,\n  z: number,\n  palette: Palette,\n  rng: Rng,\n  light: boolean\n): Group {\n  const torch = new Group();\n  torch.name = 'torch';\n  const pole = new Mesh(\n    new CylinderGeometry(0.04, 0.06, 1.5, 5),\n    new MeshStandardMaterial({ color: palette.woodDark, flatShading: true })\n  );\n  pole.position.y = 0.75;\n  torch.add(pole);\n  const flame = new Mesh(\n    new SphereGeometry(0.1, 6, 5),\n    new MeshStandardMaterial({\n      color: palette.lampGlow,\n      emissive: palette.lampGlow,\n      emissiveIntensity: 1.8,\n    })\n  );\n  flame.position.y = 1.58;\n  flame.scale.y = rng.range(1.2, 1.5);\n  torch.add(flame);\n  if (light) {\n    const point = new PointLight(palette.lampGlow, 5, 9, 1.9);\n    point.position.y = 1.6;\n    torch.add(point);\n  }\n  torch.position.set(x, 0, z);\n  return torch;\n}\n","import {\n  BoxGeometry,\n  CylinderGeometry,\n  Group,\n  IcosahedronGeometry,\n  InstancedMesh,\n  Matrix4,\n  Mesh,\n  MeshStandardMaterial,\n  Object3D,\n  PointLight,\n  Vector3,\n} from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport { createSurface } from '../materials/surface';\nimport { makeFlame, animateFire } from '../props/fire';\nimport { KIT_UNIT } from './kit';\nimport type { Obstacle } from '../core/types';\n\nexport interface RoomOptions {\n  seed?: number;\n  /** Cell size override. Default KIT_UNIT. */\n  unit?: number;\n  /** Wall height. Default 3. */\n  wallHeight?: number;\n  /** Build a ceiling slab (with beams). Default true. */\n  ceiling?: boolean;\n  /** Floor finish. Default 'plank' (floorboards); 'stone' for flagstones. */\n  floor?: 'plank' | 'stone';\n  /** Give each hearth a real flickering PointLight. Default true. */\n  hearthLight?: boolean;\n  palette?: Palette;\n}\n\n/** A window opening in a room wall. */\nexport interface RoomWindow {\n  /** Center of the opening at the interior wall face (room-local). */\n  position: Vector3;\n  /** Unit vector pointing from the window INTO the room. */\n  normal: Vector3;\n  /** Opening width / height in world units. */\n  width: number;\n  height: number;\n  /** The daylight pane material — `createInteriorLight` brightens/dims it. */\n  pane: MeshStandardMaterial;\n}\n\n/** A fireplace built into a room wall. */\nexport interface RoomHearth {\n  /** Cell center of the hearth (room-local, y = 0). */\n  position: Vector3;\n  /** Unit vector pointing from the hearth INTO the room. */\n  normal: Vector3;\n}\n\n/**\n * A clear run of interior wall — somewhere to hang things.\n *\n * Runs are **merged**: five wall cells in a line become one 6 m wall, not\n * five 1.2 m panels, because \"hang a picture halfway along the north wall\"\n * is the question anyone actually has. A window or a hearth splits a run,\n * since you cannot hang a picture over either.\n *\n * Structurally a `HangSurface`, so it goes straight into `hangOn`.\n */\nexport interface RoomWall {\n  /**\n   * Anchor at the wall face, floor level, centred on the run: **+z points\n   * into the room, +x runs along the wall, +y is up**. Already parented into\n   * the room group.\n   */\n  anchor: Object3D;\n  /** Centre of the run at the interior face, room-local, y = 0. */\n  position: Vector3;\n  /** Unit vector pointing from the wall INTO the room. */\n  normal: Vector3;\n  /** Length of the clear run, in world units. */\n  length: number;\n  /** Wall height, in world units. */\n  height: number;\n}\n\nexport interface Room {\n  group: Group;\n  /** One obstacle per wall/window/hearth cell — feed GAMA's ObstacleAvoidance. */\n  obstacles: Obstacle[];\n  /** World positions of 'S' cells (player/NPC spawn points). */\n  spawns: Vector3[];\n  /** Window openings — `createInteriorLight` turns these into light shafts. */\n  windows: RoomWindow[];\n  /** Fireplaces (already burning; their light honors `hearthLight`). */\n  hearths: RoomHearth[];\n  /** Clear interior wall runs, longest first — feed these to `hangOn`. */\n  walls: RoomWall[];\n  /** Centers of '~' rug cells (a woven rug is already laid on each). */\n  rugs: Vector3[];\n  /** Centers of 'D' doorway cells — `furnishRoom` keeps them clear. */\n  doors: Vector3[];\n  /** The grid cell size this room was built on. */\n  unit: number;\n  /** Is (x, z) over a walkable floor cell? */\n  floorAt(x: number, z: number): boolean;\n  /** Footprint in world units: { width, depth } centered on the origin. */\n  size: { width: number; depth: number };\n  /**\n   * Show/hide the whole interior (geometry AND its real lights) in one call —\n   * the cheap culling switch for stepping outdoors.\n   */\n  setActive(active: boolean): void;\n}\n\n/** Characters that stand on a walkable floor tile. */\nconst FLOORISH = new Set(['.', 'D', 'T', 'S', '~']);\n\n/** Wall-face directions, in order: -z, +z, +x, -x. Index is the `dir` id. */\nconst FACE_DIRS: Array<[number, number]> = [\n  [0, -1],\n  [0, 1],\n  [1, 0],\n  [-1, 0],\n];\n\n/**\n * Assemble a furnished-ready interior from an ASCII map — the indoor\n * counterpart of `assembleKit`, sharing its grid, its cell vocabulary and its\n * `Kit`-shaped gameplay data, then adding what a room needs to feel indoors:\n * a beamed ceiling, plastered walls over floorboards, window openings that\n * know which way they face, and a burning hearth.\n *\n * - `#` wall block (blocks movement, becomes an obstacle)\n * - `.` floor tile\n * - `D` doorway: floor + lintel spanning the gap overhead\n * - `W` window: wall with an opening (sill + header), recorded in `windows`\n * - `H` hearth: wall cell replaced by a burning fireplace\n * - `T` floor + standing torch\n * - `S` floor + recorded spawn point\n * - `~` floor + woven rug\n * - ` ` nothing\n *\n * ```ts\n * const cottage = createRoom([\n *   '##H##',\n *   'W...W',\n *   '#.~.#',\n *   '#.S.#',\n *   '##D##',\n * ], { palette });\n * scene.add(cottage.group);\n * cottage.group.add(createInteriorLight(cottage).group); // daylight shafts\n * ```\n *\n * The architecture renders as a handful of InstancedMeshes regardless of map\n * size; only windows, hearths, rugs and torches add individual meshes.\n */\nexport function createRoom(rows: string[], options: RoomOptions = {}): Room {\n  const seed = options.seed ?? 1;\n  const rng = new Rng(seed);\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const unit = options.unit ?? KIT_UNIT;\n  const wallHeight = options.wallHeight ?? 3;\n  const withCeiling = options.ceiling ?? true;\n  const hearthLight = options.hearthLight ?? true;\n\n  const height = rows.length;\n  const width = Math.max(...rows.map((r) => r.length), 0);\n  const originX = (-width / 2 + 0.5) * unit;\n  const originZ = (-height / 2 + 0.5) * unit;\n  const worldOf = (col: number, row: number): { x: number; z: number } => ({\n    x: originX + col * unit,\n    z: originZ + row * unit,\n  });\n  const cellAt = (col: number, row: number): string => rows[row]?.[col] ?? ' ';\n\n  const group = new Group();\n  group.name = 'room';\n  const obstacles: Obstacle[] = [];\n  const spawns: Vector3[] = [];\n  const windows: RoomWindow[] = [];\n  const hearths: RoomHearth[] = [];\n  const rugs: Vector3[] = [];\n  const doors: Vector3[] = [];\n  const floorCells = new Set<string>();\n  const lights: PointLight[] = [];\n\n  // Shared materials — every wall/floor/ceiling cell batches on these.\n  const plaster = createSurface('plaster', { color: palette.wall, seed });\n  const floorMat =\n    (options.floor ?? 'plank') === 'stone'\n      ? createSurface('stone', { color: palette.rock[0], seed: seed + 1 })\n      : createSurface('plank', { color: palette.wood, seed: seed + 1 });\n  const beamWood = createSurface('wood', { color: palette.woodDark, seed: seed + 2 });\n  const trimMat = new MeshStandardMaterial({ color: palette.woodDark, flatShading: true });\n\n  // Window opening proportions (fractions of the cell / wall height).\n  const sillH = Math.min(0.95, wallHeight * 0.32);\n  const openH = Math.min(1.1, wallHeight - sillH - 0.6);\n  const openW = unit * 0.55;\n\n  const wallCells: Array<{ x: number; z: number }> = [];\n  const wallFaces: Array<{ col: number; row: number; dir: number }> = [];\n  const floorTiles: Array<{ x: number; z: number }> = [];\n  const ceilingTiles: Array<{ x: number; z: number }> = [];\n  const beamCells: Array<{ x: number; z: number }> = [];\n\n  /**\n   * For a wall-run cell (window/hearth), find which way the interior lies:\n   * the run axis from its wall neighbors, the inward normal from whichever\n   * side has floor. Returns null when the cell is not in a recognizable run.\n   */\n  const inwardOf = (col: number, row: number): { run: 'x' | 'z'; normal: Vector3 } => {\n    const horizontal = cellAt(col - 1, row) === '#' || cellAt(col + 1, row) === '#' ||\n      cellAt(col - 1, row) === 'W' || cellAt(col + 1, row) === 'W' ||\n      cellAt(col - 1, row) === 'H' || cellAt(col + 1, row) === 'H';\n    if (horizontal) {\n      // Wall runs along x; interior is on the +z or -z side.\n      const inward = FLOORISH.has(cellAt(col, row + 1)) ? 1 : -1;\n      return { run: 'x', normal: new Vector3(0, 0, inward) };\n    }\n    const inward = FLOORISH.has(cellAt(col + 1, row)) ? 1 : -1;\n    return { run: 'z', normal: new Vector3(inward, 0, 0) };\n  };\n\n  for (let row = 0; row < height; row++) {\n    for (let col = 0; col < (rows[row] ?? '').length; col++) {\n      const cell = rows[row][col];\n      if (cell === ' ' || cell === undefined) continue;\n      const { x, z } = worldOf(col, row);\n      if (cell !== ' ') ceilingTiles.push({ x, z });\n\n      if (cell === '#') {\n        wallCells.push({ x, z });\n        // Any side of this block that faces open floor is an interior face,\n        // and therefore somewhere a picture could go.\n        for (let d = 0; d < 4; d++) {\n          const [dc, dr] = FACE_DIRS[d];\n          if (FLOORISH.has(cellAt(col + dc, row + dr))) wallFaces.push({ col, row, dir: d });\n        }\n        obstacles.push({ center: new Vector3(x, wallHeight / 2, z), radius: unit * 0.71 });\n        continue;\n      }\n\n      if (cell === 'W') {\n        const { run, normal } = inwardOf(col, row);\n        buildWindow(group, x, z, run, unit, wallHeight, sillH, openH, openW, plaster, trimMat);\n        const pane = buildPane(group, x, z, run, sillH, openH, openW, palette);\n        windows.push({\n          position: new Vector3(x, sillH + openH / 2, z).addScaledVector(normal, unit * 0.5 + 0.02),\n          normal,\n          width: openW,\n          height: openH,\n          pane,\n        });\n        obstacles.push({ center: new Vector3(x, wallHeight / 2, z), radius: unit * 0.71 });\n        continue;\n      }\n\n      if (cell === 'H') {\n        const { normal } = inwardOf(col, row);\n        const light = buildHearth(group, rng, x, z, normal, unit, wallHeight, palette, hearthLight);\n        if (light) lights.push(light);\n        hearths.push({ position: new Vector3(x, 0, z), normal });\n        obstacles.push({ center: new Vector3(x, wallHeight / 2, z), radius: unit * 0.8 });\n        continue;\n      }\n\n      // Everything else stands on a floor tile.\n      floorTiles.push({ x, z });\n      floorCells.add(`${col},${row}`);\n      if (row % 2 === 0) beamCells.push({ x, z });\n\n      if (cell === 'D') {\n        doors.push(new Vector3(x, 0, z));\n        const horizontalRun = cellAt(col - 1, row) === '#' || cellAt(col + 1, row) === '#';\n        const lintel = new Mesh(\n          new BoxGeometry(\n            horizontalRun ? unit : unit * 0.4,\n            wallHeight * 0.22,\n            horizontalRun ? unit * 0.4 : unit\n          ),\n          trimMat\n        );\n        lintel.position.set(x, wallHeight * 0.89, z);\n        group.add(lintel);\n      } else if (cell === 'T') {\n        const torchLight = buildTorch(group, rng, x, z, palette);\n        lights.push(torchLight);\n        obstacles.push({ center: new Vector3(x, 0, z), radius: 0.3 });\n      } else if (cell === 'S') {\n        spawns.push(new Vector3(x, 0, z));\n      } else if (cell === '~') {\n        buildRug(group, rng, x, z, unit, palette);\n        rugs.push(new Vector3(x, 0, z));\n      }\n    }\n  }\n\n  // The architecture: instanced walls, floors, ceiling slab and beams.\n  const matrix = new Matrix4();\n  const instance = (\n    cells: Array<{ x: number; z: number }>,\n    geometry: BoxGeometry,\n    material: MeshStandardMaterial,\n    y: number\n  ): void => {\n    if (cells.length === 0) return;\n    const mesh = new InstancedMesh(geometry, material, cells.length);\n    cells.forEach((cell, i) => {\n      mesh.setMatrixAt(i, matrix.makeTranslation(cell.x, y, cell.z));\n    });\n    mesh.instanceMatrix.needsUpdate = true;\n    group.add(mesh);\n  };\n  instance(wallCells, new BoxGeometry(unit, wallHeight, unit), plaster, wallHeight / 2);\n  instance(floorTiles, new BoxGeometry(unit, 0.2, unit), floorMat, -0.1);\n  if (withCeiling) {\n    instance(ceilingTiles, new BoxGeometry(unit, 0.14, unit), beamWood, wallHeight + 0.07);\n    instance(beamCells, new BoxGeometry(unit, 0.12, 0.18), beamWood, wallHeight - 0.06);\n  }\n\n  // Merge the collected wall faces into runs. Grouped by direction and by\n  // the coordinate that stays fixed along that direction, then split wherever\n  // the cells stop being adjacent — which is what a window or a hearth does,\n  // and correctly so: neither is somewhere you can hang anything.\n  const walls: RoomWall[] = [];\n  const byRun = new Map<string, number[]>();\n  for (const face of wallFaces) {\n    const alongRow = face.dir <= 1; // -z / +z faces run along x (varying col)\n    const fixed = alongRow ? face.row : face.col;\n    const key = `${face.dir}:${fixed}`;\n    const list = byRun.get(key) ?? [];\n    list.push(alongRow ? face.col : face.row);\n    byRun.set(key, list);\n  }\n  for (const [key, cells] of byRun) {\n    const [dirStr, fixedStr] = key.split(':');\n    const dir = Number(dirStr);\n    const fixed = Number(fixedStr);\n    const alongRow = dir <= 1;\n    cells.sort((a, b) => a - b);\n    let start = cells[0];\n    for (let i = 0; i <= cells.length; i++) {\n      const contiguous = i < cells.length && cells[i] === cells[i - 1] + 1;\n      if (i > 0 && contiguous) continue;\n      if (i > 0) {\n        const end = cells[i - 1];\n        const mid = (start + end) / 2;\n        const col = alongRow ? mid : fixed;\n        const row = alongRow ? fixed : mid;\n        const { x, z } = { x: originX + col * unit, z: originZ + row * unit };\n        const normal = new Vector3(FACE_DIRS[dir][0], 0, FACE_DIRS[dir][1]);\n        const position = new Vector3(x, 0, z).addScaledVector(normal, unit * 0.5);\n        const anchor = new Object3D();\n        anchor.name = 'wall';\n        anchor.position.copy(position);\n        // Turn the anchor so its +z is the inward normal; its +x then runs\n        // along the wall, which is what `hangOn` walks along.\n        anchor.rotation.y = Math.atan2(normal.x, normal.z);\n        group.add(anchor);\n        walls.push({\n          anchor,\n          position,\n          normal,\n          length: (end - start + 1) * unit,\n          height: wallHeight,\n        });\n      }\n      start = cells[i];\n    }\n  }\n  walls.sort((a, b) => b.length - a.length);\n\n  return {\n    group,\n    obstacles,\n    spawns,\n    windows,\n    hearths,\n    walls,\n    rugs,\n    doors,\n    unit,\n    floorAt(x, z) {\n      const col = Math.round((x - originX) / unit);\n      const row = Math.round((z - originZ) / unit);\n      return floorCells.has(`${col},${row}`);\n    },\n    size: { width: width * unit, depth: height * unit },\n    setActive(active) {\n      group.visible = active;\n      for (const light of lights) light.visible = active;\n    },\n  };\n}\n\n/** Sill, header and jambs filling a wall cell around an open window hole. */\nfunction buildWindow(\n  group: Group,\n  x: number,\n  z: number,\n  run: 'x' | 'z',\n  unit: number,\n  wallHeight: number,\n  sillH: number,\n  openH: number,\n  openW: number,\n  plaster: MeshStandardMaterial,\n  trim: MeshStandardMaterial\n): void {\n  const jambW = (unit - openW) / 2;\n  const along = (w: number, h: number): BoxGeometry =>\n    run === 'x' ? new BoxGeometry(w, h, unit) : new BoxGeometry(unit, h, w);\n  const place = (mesh: Mesh, offset: number, y: number): void => {\n    mesh.position.set(run === 'x' ? x + offset : x, y, run === 'x' ? z : z + offset);\n    group.add(mesh);\n  };\n  place(new Mesh(along(unit, sillH), plaster), 0, sillH / 2);\n  const headH = wallHeight - sillH - openH;\n  place(new Mesh(along(unit, headH), plaster), 0, wallHeight - headH / 2);\n  place(new Mesh(along(jambW, openH), plaster), -(openW + jambW) / 2, sillH + openH / 2);\n  place(new Mesh(along(jambW, openH), plaster), (openW + jambW) / 2, sillH + openH / 2);\n  // A protruding sill board on both faces.\n  const board = new Mesh(\n    run === 'x' ? new BoxGeometry(openW + 0.2, 0.07, unit + 0.2) : new BoxGeometry(unit + 0.2, 0.07, openW + 0.2),\n    trim\n  );\n  board.position.set(x, sillH + 0.035, z);\n  group.add(board);\n}\n\n/** The glowing daylight pane filling a window opening. */\nfunction buildPane(\n  group: Group,\n  x: number,\n  z: number,\n  run: 'x' | 'z',\n  sillH: number,\n  openH: number,\n  openW: number,\n  palette: Palette\n): MeshStandardMaterial {\n  const pane = new MeshStandardMaterial({\n    color: palette.skyBottom,\n    emissive: palette.skyBottom,\n    emissiveIntensity: 1.1,\n  });\n  const geometry =\n    run === 'x' ? new BoxGeometry(openW, openH, 0.06) : new BoxGeometry(0.06, openH, openW);\n  const mesh = new Mesh(geometry, pane);\n  mesh.name = 'windowPane';\n  mesh.position.set(x, sillH + openH / 2, z);\n  group.add(mesh);\n  return pane;\n}\n\n/** A burning stone fireplace filling a wall cell, breast proud of the wall. */\nfunction buildHearth(\n  group: Group,\n  rng: Rng,\n  x: number,\n  z: number,\n  normal: Vector3,\n  unit: number,\n  wallHeight: number,\n  palette: Palette,\n  withLight: boolean\n): PointLight | null {\n  const hearth = new Group();\n  hearth.name = 'hearth';\n  const stone = createSurface('stone', { color: palette.rock[1] ?? palette.rock[0], seed: rng.int(1, 1e9) });\n\n  // Chimney breast: the wall cell, slightly wider and proud of the wall face.\n  const proud = 0.3;\n  const breast = new Mesh(\n    normal.z !== 0\n      ? new BoxGeometry(unit * 1.12, wallHeight, unit + proud)\n      : new BoxGeometry(unit + proud, wallHeight, unit * 1.12),\n    stone\n  );\n  breast.position.set(0, wallHeight / 2, 0).addScaledVector(normal, proud / 2);\n  hearth.add(breast);\n\n  // Fire opening on the interior face of the breast: a sooty back panel with\n  // stone cheeks and lintel framing it, so the fire itself stays visible.\n  const fw = unit * 0.55;\n  const fh = 0.85;\n  const faceD = unit / 2 + proud; // interior face of the breast\n  const face = normal.clone().multiplyScalar(faceD);\n  const soot = new MeshStandardMaterial({ color: 0x120c08, flatShading: true });\n  const back = new Mesh(\n    normal.z !== 0 ? new BoxGeometry(fw + 0.3, fh + 0.2, 0.07) : new BoxGeometry(0.07, fh + 0.2, fw + 0.3),\n    soot\n  );\n  back.position.set(face.x, (fh + 0.2) / 2, face.z).addScaledVector(normal, 0.045);\n  hearth.add(back);\n  for (const side of [-1, 1]) {\n    const cheek = new Mesh(\n      normal.z !== 0 ? new BoxGeometry(0.2, fh + 0.2, 0.34) : new BoxGeometry(0.34, fh + 0.2, 0.2),\n      stone\n    );\n    const offset = (fw + 0.3 + 0.2) / 2;\n    cheek.position\n      .set(face.x, (fh + 0.2) / 2, face.z)\n      .addScaledVector(normal, 0.14)\n      .add(normal.z !== 0 ? new Vector3(side * offset, 0, 0) : new Vector3(0, 0, side * offset));\n    hearth.add(cheek);\n  }\n  const lintelStone = new Mesh(\n    normal.z !== 0 ? new BoxGeometry(fw + 0.7, 0.18, 0.34) : new BoxGeometry(0.34, 0.18, fw + 0.7),\n    stone\n  );\n  lintelStone.position.set(face.x, fh + 0.29, face.z).addScaledVector(normal, 0.14);\n  hearth.add(lintelStone);\n\n  // Mantel shelf above, hearthstone slab below.\n  const mantel = new Mesh(\n    normal.z !== 0 ? new BoxGeometry(fw + 0.9, 0.1, 0.4) : new BoxGeometry(0.4, 0.1, fw + 0.9),\n    new MeshStandardMaterial({ color: palette.woodDark, flatShading: true })\n  );\n  mantel.position.set(face.x, fh + 0.44, face.z).addScaledVector(normal, 0.16);\n  hearth.add(mantel);\n  const slab = new Mesh(\n    normal.z !== 0 ? new BoxGeometry(fw + 0.5, 0.06, 0.7) : new BoxGeometry(0.7, 0.06, fw + 0.5),\n    stone\n  );\n  slab.position.set(face.x, 0.03, face.z).addScaledVector(normal, 0.3);\n  hearth.add(slab);\n\n  // Glowing coals + a live flame standing on the hearthstone.\n  const fireBase = face.clone().addScaledVector(normal, 0.22);\n  const coalMat = new MeshStandardMaterial({\n    color: 0x1a1008,\n    emissive: 0xff5518,\n    emissiveIntensity: 1.6,\n    flatShading: true,\n  });\n  for (let i = 0; i < 5; i++) {\n    const coal = new Mesh(new IcosahedronGeometry(rng.range(0.06, 0.11), 0), coalMat);\n    coal.position.set(\n      fireBase.x + rng.jitter(0, normal.z !== 0 ? 0.18 : 0.08),\n      0.1 + rng.range(0, 0.05),\n      fireBase.z + rng.jitter(0, normal.z !== 0 ? 0.08 : 0.18)\n    );\n    hearth.add(coal);\n  }\n  const fire = makeFlame(rng, 0.8, 4, 0.15, 0.6);\n  fire.group.position.set(fireBase.x, 0.12, fireBase.z);\n  hearth.add(fire.group);\n\n  let light: PointLight | null = null;\n  if (withLight) {\n    light = new PointLight(0xff8a3a, 6, 8, 2);\n    light.position.copy(fireBase).setY(0.75).addScaledVector(normal, 0.4);\n    hearth.add(light);\n  }\n  animateFire(fire.group.children[0] as Mesh, fire.flameU, fire.emberU, coalMat, 1.6, light, 6);\n\n  hearth.position.set(x, 0, z);\n  group.add(hearth);\n  return light;\n}\n\n/** A standing torch (kit-style) with a real PointLight. */\nfunction buildTorch(group: Group, rng: Rng, x: number, z: number, palette: Palette): PointLight {\n  const torch = new Group();\n  torch.name = 'torch';\n  const pole = new Mesh(\n    new CylinderGeometry(0.04, 0.06, 1.5, 5),\n    new MeshStandardMaterial({ color: palette.woodDark, flatShading: true })\n  );\n  pole.position.y = 0.75;\n  torch.add(pole);\n  const flame = new Mesh(\n    new IcosahedronGeometry(0.1, 0),\n    new MeshStandardMaterial({\n      color: palette.lampGlow,\n      emissive: palette.lampGlow,\n      emissiveIntensity: 1.8,\n    })\n  );\n  flame.position.y = 1.58;\n  flame.scale.y = rng.range(1.2, 1.5);\n  torch.add(flame);\n  const light = new PointLight(palette.lampGlow, 4, 8, 1.9);\n  light.position.y = 1.6;\n  torch.add(light);\n  torch.position.set(x, 0, z);\n  group.add(torch);\n  return light;\n}\n\n/** A simple woven rug: bordered octagon discs laid flat on the floor. */\nfunction buildRug(group: Group, rng: Rng, x: number, z: number, unit: number, palette: Palette): void {\n  const spin = rng.range(0, Math.PI / 4);\n  const border = new Mesh(\n    new CylinderGeometry(unit * 0.48, unit * 0.48, 0.025, 8),\n    new MeshStandardMaterial({ color: palette.roof, flatShading: true })\n  );\n  border.position.set(x, 0.013, z);\n  border.rotation.y = spin;\n  const field = new Mesh(\n    new CylinderGeometry(unit * 0.36, unit * 0.36, 0.03, 8),\n    new MeshStandardMaterial({ color: palette.sand, flatShading: true })\n  );\n  field.position.set(x, 0.017, z);\n  field.rotation.y = spin;\n  group.add(border, field);\n}\n","import {\n  AdditiveBlending,\n  BufferAttribute,\n  BufferGeometry,\n  Color,\n  CylinderGeometry,\n  DoubleSide,\n  Group,\n  IcosahedronGeometry,\n  Mesh,\n  MeshStandardMaterial,\n  Points,\n  PointLight,\n  ShaderMaterial,\n} from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport { createSurface } from '../materials/surface';\nimport type { Prop } from '../core/types';\n\nexport interface FireOptions {\n  seed?: number;\n  /** Add a flickering warm PointLight. Default true. */\n  light?: boolean;\n  /** Overall flame scale multiplier. Default 1. */\n  scale?: number;\n  palette?: Palette;\n}\n\n// ---- flame geometry (hand-merged so we need no BufferGeometryUtils) ----\n\ninterface Tongue {\n  cx: number;\n  cz: number;\n  r: number;\n  h: number;\n  phase: number;\n}\n\n/**\n * Merge several tapering \"tongues\" into one flame mesh. Each vertex carries\n * `aY` (0 at the base, 1 at the tip) and `aPhase` (per tongue), which the\n * shader uses to wobble the tips and flicker the height.\n */\nfunction flameGeometry(tongues: Tongue[], R = 5): BufferGeometry {\n  const position: number[] = [];\n  const aY: number[] = [];\n  const aPhase: number[] = [];\n  const index: number[] = [];\n  for (const t of tongues) {\n    const base = position.length / 3;\n    const rings = [\n      { y: 0, rad: t.r },\n      { y: t.h * 0.5, rad: t.r * 0.62 },\n    ];\n    for (const ring of rings) {\n      for (let i = 0; i < R; i++) {\n        const a = (i / R) * Math.PI * 2;\n        position.push(t.cx + Math.cos(a) * ring.rad, ring.y, t.cz + Math.sin(a) * ring.rad);\n        aY.push(ring.y / t.h);\n        aPhase.push(t.phase);\n      }\n    }\n    const apex = base + R * 2;\n    position.push(t.cx, t.h, t.cz);\n    aY.push(1);\n    aPhase.push(t.phase);\n    for (let i = 0; i < R; i++) {\n      const i0 = base + i;\n      const i1 = base + ((i + 1) % R);\n      const j0 = base + R + i;\n      const j1 = base + R + ((i + 1) % R);\n      index.push(i0, i1, j1, i0, j1, j0); // ring0 → ring1\n      index.push(j0, j1, apex); //           ring1 → apex\n    }\n  }\n  const geo = new BufferGeometry();\n  geo.setAttribute('position', new BufferAttribute(new Float32Array(position), 3));\n  geo.setAttribute('aY', new BufferAttribute(new Float32Array(aY), 1));\n  geo.setAttribute('aPhase', new BufferAttribute(new Float32Array(aPhase), 1));\n  geo.setIndex(index);\n  return geo;\n}\n\nconst FLAME_VERT = /* glsl */ `\nattribute float aY;\nattribute float aPhase;\nuniform float uTime;\nvarying float vY;\nvoid main() {\n  vY = aY;\n  vec3 p = position;\n  float w = aY * aY;                 // tips sway most, base is pinned\n  p.x += sin(uTime * 7.0 + aPhase + aY * 4.0) * 0.09 * w;\n  p.z += cos(uTime * 6.0 + aPhase * 1.3 + aY * 4.0) * 0.09 * w;\n  p.y *= 0.82 + 0.18 * sin(uTime * 13.0 + aPhase * 2.0); // lick up and down\n  gl_Position = projectionMatrix * modelViewMatrix * vec4(p, 1.0);\n}`;\n\nconst FLAME_FRAG = /* glsl */ `\nuniform vec3 uHot;\nuniform vec3 uCool;\nvarying float vY;\nvoid main() {\n  vec3 col = mix(uHot, uCool, vY);   // white-hot base → cool orange tip\n  float alpha = 1.0 - vY;            // fade out toward the tip\n  gl_FragColor = vec4(col * (1.2 - vY * 0.4), alpha);\n}`;\n\nconst EMBER_VERT = /* glsl */ `\nattribute float aPhase;\nattribute float aSpeed;\nattribute float aRad;\nattribute float aAng;\nuniform float uTime;\nuniform float uRise;\nuniform float uSize;\nvarying float vLife;\nvoid main() {\n  float life = fract(uTime * aSpeed + aPhase); // 0 born → 1 dead\n  vLife = life;\n  float ang = aAng + life * 2.2;\n  float rad = aRad * (1.0 - life * 0.35);\n  vec3 p = vec3(cos(ang) * rad, life * uRise, sin(ang) * rad);\n  vec4 mv = modelViewMatrix * vec4(p, 1.0);\n  gl_PointSize = uSize * (1.0 - life) * (260.0 / -mv.z);\n  gl_Position = projectionMatrix * mv;\n}`;\n\nconst EMBER_FRAG = /* glsl */ `\nuniform vec3 uColor;\nvarying float vLife;\nvoid main() {\n  float d = length(gl_PointCoord - 0.5);\n  if (d > 0.5) discard;\n  gl_FragColor = vec4(uColor, (1.0 - vLife) * (1.0 - d * 2.0));\n}`;\n\n/**\n * Build the animated flame + embers, plus the uniforms driving them.\n * Internal — shared with the room hearth; not part of the public API.\n */\nexport function makeFlame(\n  rng: Rng,\n  scale: number,\n  tongues: number,\n  spread: number,\n  baseH: number\n): { group: Group; flameU: { uTime: { value: number } }; emberU: { uTime: { value: number } } } {\n  const list: Tongue[] = [];\n  for (let i = 0; i < tongues; i++) {\n    const a = (i / tongues) * Math.PI * 2 + rng.range(0, 1);\n    const rad = i === 0 ? 0 : rng.range(0.3, 1) * spread;\n    list.push({\n      cx: Math.cos(a) * rad,\n      cz: Math.sin(a) * rad,\n      r: rng.range(0.1, 0.16) * scale,\n      h: baseH * rng.range(0.7, 1.15) * scale,\n      phase: rng.range(0, Math.PI * 2),\n    });\n  }\n  const flameMat = new ShaderMaterial({\n    uniforms: {\n      uTime: { value: 0 },\n      uHot: { value: new Color(0xffe89a) },\n      uCool: { value: new Color(0xe0400c) },\n    },\n    vertexShader: FLAME_VERT,\n    fragmentShader: FLAME_FRAG,\n    transparent: true,\n    depthWrite: false,\n    blending: AdditiveBlending,\n    side: DoubleSide,\n  });\n  const flame = new Mesh(flameGeometry(list), flameMat);\n\n  // Embers.\n  const N = Math.round(10 + tongues * 2);\n  const ep = new Float32Array(N * 3);\n  const aPhase = new Float32Array(N);\n  const aSpeed = new Float32Array(N);\n  const aRad = new Float32Array(N);\n  const aAng = new Float32Array(N);\n  for (let i = 0; i < N; i++) {\n    aPhase[i] = rng.next();\n    aSpeed[i] = rng.range(0.25, 0.5);\n    aRad[i] = rng.range(0.02, spread * 0.9);\n    aAng[i] = rng.range(0, Math.PI * 2);\n  }\n  const emberGeo = new BufferGeometry();\n  emberGeo.setAttribute('position', new BufferAttribute(ep, 3));\n  emberGeo.setAttribute('aPhase', new BufferAttribute(aPhase, 1));\n  emberGeo.setAttribute('aSpeed', new BufferAttribute(aSpeed, 1));\n  emberGeo.setAttribute('aRad', new BufferAttribute(aRad, 1));\n  emberGeo.setAttribute('aAng', new BufferAttribute(aAng, 1));\n  const emberMat = new ShaderMaterial({\n    uniforms: {\n      uTime: { value: 0 },\n      uRise: { value: baseH * 1.9 * scale },\n      uSize: { value: 3.2 * scale },\n      uColor: { value: new Color(0xff8a3c) },\n    },\n    vertexShader: EMBER_VERT,\n    fragmentShader: EMBER_FRAG,\n    transparent: true,\n    depthWrite: false,\n    blending: AdditiveBlending,\n  });\n  const embers = new Points(emberGeo, emberMat);\n  embers.frustumCulled = false;\n\n  const group = new Group();\n  group.add(flame, embers);\n  return { group, flameU: flameMat.uniforms as { uTime: { value: number } }, emberU: emberMat.uniforms as { uTime: { value: number } } };\n}\n\n/**\n * Wire self-animation onto a fire: the flame shader clock, the ember clock,\n * the glowing coals and an optional flickering PointLight are all advanced\n * from the render loop, so a fire lives on its own with no per-frame code —\n * drop it in `scatter` or a village and it burns.\n * Internal — shared with the room hearth; not part of the public API.\n */\nexport function animateFire(\n  driver: Mesh,\n  flameU: { uTime: { value: number } },\n  emberU: { uTime: { value: number } },\n  coals: MeshStandardMaterial,\n  coalBase: number,\n  light: PointLight | null,\n  lightBase: number\n): void {\n  driver.onBeforeRender = () => {\n    const t = performance.now() * 0.001;\n    flameU.uTime.value = t;\n    emberU.uTime.value = t;\n    // Pseudo-noise flicker from a few incommensurate sines.\n    const flick =\n      0.74 + 0.15 * Math.sin(t * 11.0) + 0.1 * Math.sin(t * 23.3 + 1.7) + 0.06 * Math.sin(t * 41.0 + 0.5);\n    coals.emissiveIntensity = coalBase * (0.8 + 0.3 * (flick - 0.74) * 3);\n    if (light) light.intensity = lightBase * Math.max(0.4, flick);\n  };\n}\n\n// ---- braziers & campfires ---------------------------------------------\n\n/**\n * A standing brazier: a metal fire-bowl on splayed legs, filled with glowing\n * coals under a live flame, ringed by rising embers and casting a flickering\n * warm light. Self-animating.\n */\nexport function createBrazier(options: FireOptions = {}): Prop {\n  const rng = new Rng(options.seed ?? 1);\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const seed = options.seed ?? 1;\n  const scale = options.scale ?? 1;\n  const withLight = options.light ?? true;\n\n  const group = new Group();\n  group.name = 'brazier';\n\n  const metal = createSurface('metal', { color: palette.metal, seed });\n  const bowlH = 0.9;\n  // Three splayed legs.\n  for (let i = 0; i < 3; i++) {\n    const a = (i / 3) * Math.PI * 2 + 0.5;\n    const leg = new Mesh(new CylinderGeometry(0.03, 0.04, bowlH, 5), metal);\n    leg.position.set(Math.cos(a) * 0.22, bowlH / 2, Math.sin(a) * 0.22);\n    leg.rotation.z = Math.cos(a) * 0.18;\n    leg.rotation.x = -Math.sin(a) * 0.18;\n    group.add(leg);\n  }\n  const bowl = new Mesh(new CylinderGeometry(0.42, 0.24, 0.32, 12, 1, true), metal);\n  bowl.position.y = bowlH + 0.02;\n  group.add(bowl);\n  const base = new Mesh(new CylinderGeometry(0.24, 0.24, 0.05, 12), metal);\n  base.position.y = bowlH - 0.13;\n  group.add(base);\n\n  const coalMat = new MeshStandardMaterial({\n    color: 0x1a1109,\n    emissive: 0xff5a1e,\n    emissiveIntensity: 1.4,\n    flatShading: true,\n  });\n  for (let i = 0; i < 5; i++) {\n    const coal = new Mesh(new IcosahedronGeometry(rng.range(0.07, 0.12), 0), coalMat);\n    coal.position.set(rng.jitter(0, 0.16), bowlH + 0.06 + rng.range(0, 0.04), rng.jitter(0, 0.16));\n    group.add(coal);\n  }\n\n  const fire = makeFlame(rng, scale, 5, 0.2, 0.5);\n  fire.group.position.y = bowlH + 0.1;\n  group.add(fire.group);\n\n  let light: PointLight | null = null;\n  if (withLight) {\n    light = new PointLight(0xff8a3a, 7, 9, 2);\n    light.position.set(0, bowlH + 0.4, 0);\n    group.add(light);\n  }\n  animateFire(fire.group.children[0] as Mesh, fire.flameU, fire.emberU, coalMat, 1.4, light, 7);\n\n  return { object: group, obstacleRadius: 0.45 };\n}\n\n/**\n * A campfire: a ring of stones around charred logs stacked in a lean, a live\n * flame with rising embers, glowing under a flickering warm light.\n * Self-animating.\n */\nexport function createCampfire(options: FireOptions = {}): Prop {\n  const rng = new Rng(options.seed ?? 1);\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const seed = options.seed ?? 1;\n  const scale = options.scale ?? 1;\n  const withLight = options.light ?? true;\n\n  const group = new Group();\n  group.name = 'campfire';\n\n  // Stone ring.\n  const stone = createSurface('stone', { color: palette.rock[0], seed });\n  const ringR = 0.7;\n  const stones = rng.int(7, 9);\n  for (let i = 0; i < stones; i++) {\n    const a = (i / stones) * Math.PI * 2;\n    const s = rng.range(0.16, 0.24);\n    const rock = new Mesh(new IcosahedronGeometry(s, 0), stone);\n    rock.position.set(Math.cos(a) * ringR, s * 0.5, Math.sin(a) * ringR);\n    rock.rotation.set(rng.range(0, 3), rng.range(0, 3), rng.range(0, 3));\n    rock.scale.y = 0.75;\n    group.add(rock);\n  }\n\n  // Charred logs stacked in a lean.\n  const wood = createSurface('wood', { color: palette.woodDark, seed: seed + 3 });\n  const charMat = new MeshStandardMaterial({ color: 0x1c140f, flatShading: true });\n  const logs = rng.int(3, 4);\n  for (let i = 0; i < logs; i++) {\n    const a = (i / logs) * Math.PI * 2 + rng.range(0, 0.4);\n    const log = new Mesh(new CylinderGeometry(0.07, 0.08, 0.95, 6), i % 2 ? charMat : wood);\n    log.position.set(Math.cos(a) * 0.18, 0.28, Math.sin(a) * 0.18);\n    log.rotation.set(Math.PI / 2 - 0.55, a, 0);\n    group.add(log);\n  }\n\n  const coalMat = new MeshStandardMaterial({\n    color: 0x1a1008,\n    emissive: 0xff5518,\n    emissiveIntensity: 1.6,\n    flatShading: true,\n  });\n  for (let i = 0; i < 6; i++) {\n    const coal = new Mesh(new IcosahedronGeometry(rng.range(0.08, 0.14), 0), coalMat);\n    coal.position.set(rng.jitter(0, 0.24), 0.08 + rng.range(0, 0.05), rng.jitter(0, 0.24));\n    group.add(coal);\n  }\n\n  const fire = makeFlame(rng, scale, 7, 0.42, 0.85);\n  fire.group.position.y = 0.14;\n  group.add(fire.group);\n\n  let light: PointLight | null = null;\n  if (withLight) {\n    light = new PointLight(0xff8636, 9, 12, 2);\n    light.position.set(0, 0.9, 0);\n    group.add(light);\n  }\n  animateFire(fire.group.children[0] as Mesh, fire.flameU, fire.emberU, coalMat, 1.6, light, 9);\n\n  return { object: group, obstacleRadius: 0.9 };\n}\n","import { Group, Vector3 } from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport type { Obstacle, Prop } from '../core/types';\nimport type { Room } from './room';\nimport {\n  createBed,\n  createCandle,\n  createChest,\n  createRug,\n  createSeat,\n  createShelf,\n  createTable,\n} from '../props/furniture';\nimport { createCounter, createForge, createLoom, createOven } from '../props/workshop';\nimport { createCrate } from '../props/crate';\n\nexport type RoomRole = 'cottage' | 'tavern' | 'smithy' | 'bakery' | 'weaver' | 'study' | 'barracks';\n\nexport interface FurnishOptions {\n  seed?: number;\n  /** What the room is for. Default 'cottage'. */\n  role?: RoomRole;\n  palette?: Palette;\n}\n\n/** Named points ANIMA characters can use: where to sit, sleep, work, warm up. */\nexport interface RoomMarkers {\n  /** One per seat (chairs, stools, bench places, counter fronts). */\n  sit: Vector3[];\n  /** One per sleeping place (bed decks). */\n  sleep: Vector3[];\n  /** In front of each work utility (forge, oven, loom, counter, desk). */\n  work: Vector3[];\n  /** A spot in front of each hearth, for warming hands. */\n  hearth: Vector3[];\n}\n\nexport interface Furnished {\n  /** Everything placed, already added to `group`. */\n  props: Prop[];\n  /** Room-local steering circles for the placed furniture. */\n  obstacles: Obstacle[];\n  /** Room-local gameplay markers by kind. */\n  markers: RoomMarkers;\n  /** The container — already a child of `room.group`. */\n  group: Group;\n}\n\ninterface Spot {\n  x: number;\n  z: number;\n  /** For wall cells: unit vector pointing away from the wall, into the room. */\n  normal: Vector3 | null;\n}\n\n/**\n * Furnish a `createRoom` interior for a role, using the room's own grid:\n * beds and shelves go against walls facing inward, tables take the middle\n * (the rug if there is one), seats gather round, and the role's trade\n * utility — a tavern's counter, a smith's forge, a baker's oven, a\n * weaver-less study's book wall — anchors the room. Doorways stay clear,\n * nothing overlaps, and the same seed always furnishes the same way.\n *\n * The payoff for agents: `markers` — named, room-local points (`sit`,\n * `sleep`, `work`, `hearth`) a GAMA/ANIMA character can walk to and use,\n * and `obstacles` ready for steering.\n *\n * ```ts\n * const tavern = furnishRoom(room, { role: 'tavern', seed: 4 });\n * guest.walkTo(room.group.localToWorld(tavern.markers.sit[0].clone()));\n * ```\n */\nexport function furnishRoom(room: Room, options: FurnishOptions = {}): Furnished {\n  const seed = options.seed ?? 1;\n  const rng = new Rng(seed);\n  const role = options.role ?? 'cottage';\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const unit = room.unit;\n\n  const group = new Group();\n  group.name = `furnish-${role}`;\n  room.group.add(group);\n  const props: Prop[] = [];\n  const obstacles: Obstacle[] = [];\n  const markers: RoomMarkers = { sit: [], sleep: [], work: [], hearth: [] };\n\n  // ---- survey the grid --------------------------------------------------\n  const cols = Math.round(room.size.width / unit);\n  const rows = Math.round(room.size.depth / unit);\n  const x0 = -room.size.width / 2 + unit / 2;\n  const z0 = -room.size.depth / 2 + unit / 2;\n  const nearDoor = (x: number, z: number): boolean =>\n    room.doors.some((door) => Math.hypot(door.x - x, door.z - z) < unit * 1.6);\n  const nearHearthFront = (x: number, z: number): boolean =>\n    room.hearths.some((hearth) => {\n      const front = hearth.position.clone().addScaledVector(hearth.normal, unit);\n      return Math.hypot(front.x - x, front.z - z) < unit * 0.9;\n    });\n\n  const wallSpots: Spot[] = [];\n  const openSpots: Spot[] = [];\n  for (let cz = 0; cz < rows; cz++) {\n    for (let cx = 0; cx < cols; cx++) {\n      const x = x0 + cx * unit;\n      const z = z0 + cz * unit;\n      if (!room.floorAt(x, z) || nearDoor(x, z) || nearHearthFront(x, z)) continue;\n      // Which neighbors are solid? That cell hugs a wall.\n      const solid: Vector3[] = [];\n      if (!room.floorAt(x - unit, z)) solid.push(new Vector3(1, 0, 0));\n      if (!room.floorAt(x + unit, z)) solid.push(new Vector3(-1, 0, 0));\n      if (!room.floorAt(x, z - unit)) solid.push(new Vector3(0, 0, 1));\n      if (!room.floorAt(x, z + unit)) solid.push(new Vector3(0, 0, -1));\n      if (solid.length > 0) wallSpots.push({ x, z, normal: rng.pick(solid) });\n      else openSpots.push({ x, z, normal: null });\n    }\n  }\n  // Seeded shuffle so different seeds pick different walls first.\n  const shuffle = <T>(list: T[]): T[] => {\n    for (let i = list.length - 1; i > 0; i--) {\n      const j = rng.int(0, i);\n      [list[i], list[j]] = [list[j], list[i]];\n    }\n    return list;\n  };\n  shuffle(wallSpots);\n  shuffle(openSpots);\n\n  const taken: Array<{ x: number; z: number; r: number }> = [];\n  const fits = (x: number, z: number, r: number): boolean =>\n    taken.every((t) => Math.hypot(t.x - x, t.z - z) >= (t.r + r) * 0.82);\n\n  /** Place a prop at a spot (facing its normal, or a given yaw), claim space. */\n  const put = (prop: Prop, spot: Spot | null, yaw?: number): Spot | null => {\n    if (!spot) return null;\n    const ry = yaw ?? (spot.normal ? Math.atan2(spot.normal.x, spot.normal.z) : rng.range(0, Math.PI * 2));\n    prop.object.position.set(spot.x, 0, spot.z);\n    prop.object.rotation.y = ry;\n    group.add(prop.object);\n    props.push(prop);\n    if (prop.obstacleRadius > 0) {\n      obstacles.push({ center: new Vector3(spot.x, 0, spot.z), radius: prop.obstacleRadius });\n      taken.push({ x: spot.x, z: spot.z, r: prop.obstacleRadius });\n    }\n    return spot;\n  };\n  const wallSpot = (r: number): Spot | null =>\n    wallSpots.find((spot) => fits(spot.x, spot.z, r)) ?? null;\n  const openSpot = (r: number): Spot | null =>\n    openSpots.find((spot) => fits(spot.x, spot.z, r)) ?? null;\n  /** The room-local point `dist` in front of a placed prop's facing. */\n  const inFront = (spot: Spot, dist: number, yaw?: number): Vector3 => {\n    const a = yaw ?? (spot.normal ? Math.atan2(spot.normal.x, spot.normal.z) : 0);\n    return new Vector3(spot.x + Math.sin(a) * dist, 0, spot.z + Math.cos(a) * dist);\n  };\n  /** Two sitting places spaced along a bench's long (local x) axis. */\n  const benchSits = (spot: Spot): Vector3[] => {\n    const a = spot.normal ? Math.atan2(spot.normal.x, spot.normal.z) : 0;\n    const along = new Vector3(Math.cos(a), 0, -Math.sin(a));\n    const center = new Vector3(spot.x, 0, spot.z);\n    return [center.clone().addScaledVector(along, 0.4), center.clone().addScaledVector(along, -0.4)];\n  };\n\n  // Rug cells make the best table spots; hearths always get a marker.\n  const centerSpot: Spot | null =\n    room.rugs.length > 0\n      ? { x: room.rugs[0].x, z: room.rugs[0].z, normal: null }\n      : openSpot(1.1);\n  for (const hearth of room.hearths) {\n    // A step back from the hearthstone — close enough to warm hands, not\n    // standing in the flames (the fire itself sits ~1.5 units from the cell).\n    markers.hearth.push(hearth.position.clone().addScaledVector(hearth.normal, unit * 1.35));\n  }\n\n  // ---- role scripts -----------------------------------------------------\n  const child = (): number => rng.int(1, 1e9);\n\n  /** A stool at a work point (if it exists), facing back at the work. */\n  const furnishSeatAt = (at: Vector3 | undefined): Vector3 | null => {\n    if (!at || !room.floorAt(at.x, at.z)) return null;\n    const stool = createSeat({ seed: child(), style: 'stool', palette });\n    stool.object.position.set(at.x, 0, at.z);\n    group.add(stool.object);\n    props.push(stool);\n    return at.clone();\n  };\n\n  const tableAndSeats = (style: 'round' | 'trestle', seats: number): void => {\n    const spot = centerSpot && fits(centerSpot.x, centerSpot.z, 1.05) ? centerSpot : openSpot(1.05);\n    const yaw = rng.range(0, Math.PI * 2);\n    const placed = put(createTable({ seed: child(), style, palette }), spot, yaw);\n    if (!placed) return;\n    for (let i = 0; i < seats; i++) {\n      const a = yaw + (i / seats) * Math.PI * 2 + 0.4;\n      const seat = createSeat({ seed: child(), style: i % 3 === 2 ? 'stool' : 'chair', palette });\n      const sx = placed.x + Math.sin(a) * 1.25;\n      const sz = placed.z + Math.cos(a) * 1.25;\n      if (!room.floorAt(sx, sz) || nearDoor(sx, sz)) continue;\n      seat.object.position.set(sx, 0, sz);\n      seat.object.rotation.y = a + Math.PI; // face the table\n      group.add(seat.object);\n      props.push(seat);\n      obstacles.push({ center: new Vector3(sx, 0, sz), radius: seat.obstacleRadius });\n      taken.push({ x: sx, z: sz, r: seat.obstacleRadius });\n      markers.sit.push(new Vector3(sx, 0, sz));\n    }\n    const candle = createCandle({ seed: child(), palette });\n    candle.object.position.set(placed.x + 0.25, 0.78, placed.z);\n    group.add(candle.object);\n    props.push(candle);\n  };\n\n  const bedAndChest = (size: 'single' | 'double'): void => {\n    const spot = wallSpot(1.15);\n    const placed = put(createBed({ seed: child(), size, palette }), spot);\n    if (!placed) return;\n    markers.sleep.push(new Vector3(placed.x, 0, placed.z));\n    if (size === 'double') markers.sleep.push(new Vector3(placed.x, 0, placed.z));\n    const foot = inFront(placed, 1.6);\n    if (room.floorAt(foot.x, foot.z) && fits(foot.x, foot.z, 0.55)) {\n      put(createChest({ seed: child(), palette }), { x: foot.x, z: foot.z, normal: spot!.normal });\n    }\n  };\n\n  const shelfOn = (stock: 'books' | 'pottery' | 'food'): void => {\n    put(createShelf({ seed: child(), stock, palette }), wallSpot(0.7));\n  };\n\n  const utility = (\n    prop: Prop,\n    kind: 'wall' | 'open',\n    workDist: number\n  ): void => {\n    const spot = kind === 'wall' ? wallSpot(prop.obstacleRadius) : openSpot(prop.obstacleRadius);\n    const placed = put(prop, spot);\n    if (placed) markers.work.push(inFront(placed, workDist));\n  };\n\n  switch (role) {\n    case 'cottage':\n      bedAndChest('single');\n      tableAndSeats('round', 2);\n      shelfOn(rng.next() < 0.5 ? 'books' : 'food');\n      put(createRug({ seed: child(), shape: 'runner', palette }), wallSpot(0));\n      break;\n    case 'tavern': {\n      utility(createCounter({ seed: child(), palette }), 'wall', 1.1);\n      shelfOn('pottery');\n      tableAndSeats('trestle', 4);\n      if (openSpots.length > 10) tableAndSeats('round', 3);\n      // Bench along a spare wall for waiting guests.\n      const benchSpot = wallSpot(0.8);\n      const bench = put(createSeat({ seed: child(), style: 'bench', palette }), benchSpot);\n      if (bench) markers.sit.push(...benchSits(bench));\n      put(createCandle({ seed: child(), style: 'candelabra', palette }), wallSpot(0.3));\n      break;\n    }\n    case 'smithy':\n      utility(createForge({ seed: child(), palette }), 'wall', 1.2);\n      put(createTable({ seed: child(), style: 'desk', palette }), wallSpot(0.75));\n      put(createChest({ seed: child(), palette }), wallSpot(0.55));\n      put(createCrate({ seed: child(), palette }), wallSpot(0.5));\n      put(createSeat({ seed: child(), style: 'stool', palette }), openSpot(0.3));\n      break;\n    case 'bakery':\n      utility(createOven({ seed: child(), palette }), 'wall', 1.15);\n      utility(createCounter({ seed: child(), palette }), 'wall', 1.1);\n      shelfOn('food');\n      tableAndSeats('round', 1);\n      put(createCrate({ seed: child(), palette }), wallSpot(0.5));\n      break;\n    case 'weaver': {\n      utility(createLoom({ seed: child(), palette }), 'wall', 0.9);\n      const weaverSeat = furnishSeatAt(markers.work[markers.work.length - 1]);\n      if (weaverSeat) markers.sit.push(weaverSeat);\n      shelfOn('food');\n      put(createRug({ seed: child(), shape: 'square', palette }), openSpot(0));\n      put(createChest({ seed: child(), palette }), wallSpot(0.55));\n      break;\n    }\n    case 'study': {\n      shelfOn('books');\n      shelfOn('books');\n      const desk = put(createTable({ seed: child(), style: 'desk', palette }), wallSpot(0.75));\n      if (desk) {\n        markers.work.push(inFront(desk, 0.7));\n        const chairAt = inFront(desk, 0.75);\n        const chair = createSeat({ seed: child(), style: 'chair', palette });\n        chair.object.position.copy(chairAt);\n        chair.object.rotation.y = (desk.normal ? Math.atan2(desk.normal.x, desk.normal.z) : 0) + Math.PI;\n        group.add(chair.object);\n        props.push(chair);\n        markers.sit.push(chairAt);\n      }\n      put(createCandle({ seed: child(), style: 'candelabra', palette }), wallSpot(0.3));\n      put(createRug({ seed: child(), shape: 'round', palette }), openSpot(0));\n      break;\n    }\n    case 'barracks': {\n      for (let i = 0; i < 3; i++) {\n        const spot = wallSpot(1.15);\n        const bunk = put(createBed({ seed: child(), size: 'single', palette }), spot);\n        if (bunk) {\n          markers.sleep.push(new Vector3(bunk.x, 0, bunk.z));\n          const foot = inFront(bunk, 1.6);\n          if (room.floorAt(foot.x, foot.z) && fits(foot.x, foot.z, 0.55)) {\n            put(createChest({ seed: child(), palette }), { x: foot.x, z: foot.z, normal: spot!.normal });\n          }\n        }\n      }\n      const bench = put(createSeat({ seed: child(), style: 'bench', palette }), openSpot(0.8));\n      if (bench) markers.sit.push(...benchSits(bench));\n      break;\n    }\n  }\n\n  return { props, obstacles, markers, group };\n}\n","import {\n  BoxGeometry,\n  CylinderGeometry,\n  Group,\n  IcosahedronGeometry,\n  Mesh,\n  MeshStandardMaterial,\n  PointLight,\n  SphereGeometry,\n  TorusGeometry,\n} from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport { createSurface } from '../materials/surface';\nimport { createPropSurface, createSlot } from '../core/types';\nimport type { Prop, PropSlot, PropSurface } from '../core/types';\n\n/**\n * Interior furniture — the cottage set. Every piece follows the Prop\n * contract (seeded, palette-themed, origin at floor level, honest\n * obstacleRadius), so it scatters, steers and re-themes like any other\n * SCENA prop; it just happens to live indoors.\n */\n\n// ---- tables ------------------------------------------------------------\n\nexport type TableStyle = 'round' | 'trestle' | 'desk';\n\nexport interface TableOptions {\n  seed?: number;\n  /** 'round' pedestal table, long 'trestle' board, or a small 'desk'. */\n  style?: TableStyle;\n  palette?: Palette;\n}\n\n/** A wooden table: round pedestal, long trestle board, or writing desk. */\nexport function createTable(options: TableOptions = {}): Prop {\n  const seed = options.seed ?? 1;\n  const rng = new Rng(seed);\n  const style = options.style ?? 'trestle';\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const top = createSurface('plank', { color: palette.wood, seed });\n  const legWood = createSurface('wood', { color: palette.woodDark, seed: seed + 1 });\n\n  const group = new Group();\n  group.name = `table-${style}`;\n  const h = 0.74 + rng.range(-0.02, 0.02);\n  const surfaces: PropSurface[] = [];\n  let radius = 0.8;\n\n  if (style === 'round') {\n    const board = new Mesh(new CylinderGeometry(0.72, 0.72, 0.07, 10), top);\n    board.position.y = h;\n    const stem = new Mesh(new CylinderGeometry(0.09, 0.13, h, 7), legWood);\n    stem.position.y = h / 2;\n    const foot = new Mesh(new CylinderGeometry(0.34, 0.4, 0.08, 8), legWood);\n    foot.position.y = 0.04;\n    group.add(board, stem, foot);\n    surfaces.push(createPropSurface('top', group, 0, h + 0.035, 0, 1.24, 1.24));\n    radius = 0.78;\n  } else if (style === 'trestle') {\n    const board = new Mesh(new BoxGeometry(2.0, 0.08, 0.9), top);\n    board.position.y = h;\n    group.add(board);\n    for (const side of [-1, 1]) {\n      for (const lean of [-1, 1]) {\n        const leg = new Mesh(new BoxGeometry(0.09, h, 0.12), legWood);\n        leg.position.set(side * 0.78, h / 2, 0);\n        leg.rotation.x = lean * 0.32;\n        group.add(leg);\n      }\n    }\n    const stretcher = new Mesh(new BoxGeometry(1.66, 0.08, 0.1), legWood);\n    stretcher.position.y = 0.24;\n    group.add(stretcher);\n    surfaces.push(createPropSurface('top', group, 0, h + 0.04, 0, 2.0, 0.9));\n    radius = 1.05;\n  } else {\n    const board = new Mesh(new BoxGeometry(1.3, 0.06, 0.68), top);\n    board.position.y = h;\n    group.add(board);\n    const apron = new Mesh(new BoxGeometry(1.18, 0.16, 0.56), legWood);\n    apron.position.y = h - 0.11;\n    group.add(apron);\n    for (const sx of [-1, 1]) {\n      for (const sz of [-1, 1]) {\n        const leg = new Mesh(new BoxGeometry(0.07, h, 0.07), legWood);\n        leg.position.set(sx * 0.56, h / 2, sz * 0.26);\n        group.add(leg);\n      }\n    }\n    surfaces.push(createPropSurface('top', group, 0, h + 0.03, 0, 1.3, 0.68));\n    radius = 0.72;\n  }\n  return { object: group, obstacleRadius: radius, surfaces };\n}\n\n// ---- seats -------------------------------------------------------------\n\nexport type SeatStyle = 'chair' | 'bench' | 'stool';\n\nexport interface SeatOptions {\n  seed?: number;\n  /** A slat-back 'chair', a long 'bench', or a three-legged 'stool'. */\n  style?: SeatStyle;\n  palette?: Palette;\n}\n\n/** Something to sit on: chair, bench or stool. Seat height ≈ 0.45. */\nexport function createSeat(options: SeatOptions = {}): Prop {\n  const seed = options.seed ?? 1;\n  const rng = new Rng(seed);\n  const style = options.style ?? 'chair';\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const wood = createSurface('wood', { color: palette.wood, seed });\n  const dark = createSurface('wood', { color: palette.woodDark, seed: seed + 1 });\n\n  const group = new Group();\n  group.name = `seat-${style}`;\n  const h = 0.45;\n  let radius = 0.3;\n\n  if (style === 'stool') {\n    const disc = new Mesh(new CylinderGeometry(0.24, 0.22, 0.06, 8), wood);\n    disc.position.y = h;\n    group.add(disc);\n    for (let i = 0; i < 3; i++) {\n      const a = (i / 3) * Math.PI * 2 + rng.range(0, 0.4);\n      const leg = new Mesh(new CylinderGeometry(0.035, 0.045, h, 5), dark);\n      leg.position.set(Math.cos(a) * 0.13, h / 2, Math.sin(a) * 0.13);\n      leg.rotation.z = Math.cos(a) * 0.22;\n      leg.rotation.x = -Math.sin(a) * 0.22;\n      group.add(leg);\n    }\n    radius = 0.26;\n  } else if (style === 'bench') {\n    const seat = new Mesh(new BoxGeometry(1.5, 0.06, 0.36), wood);\n    seat.position.y = h;\n    group.add(seat);\n    for (const side of [-1, 1]) {\n      const leg = new Mesh(new BoxGeometry(0.08, h, 0.3), dark);\n      leg.position.set(side * 0.6, h / 2, 0);\n      leg.rotation.z = side * 0.06;\n      group.add(leg);\n    }\n    radius = 0.78;\n  } else {\n    const seat = new Mesh(new BoxGeometry(0.44, 0.05, 0.42), wood);\n    seat.position.y = h;\n    group.add(seat);\n    for (const sx of [-1, 1]) {\n      for (const sz of [-1, 1]) {\n        const back = sz < 0;\n        const leg = new Mesh(new BoxGeometry(0.05, back ? 0.98 : h, 0.05), dark);\n        leg.position.set(sx * 0.18, back ? 0.49 : h / 2, sz * 0.17);\n        group.add(leg);\n      }\n    }\n    for (const y of [0.72, 0.88]) {\n      const slat = new Mesh(new BoxGeometry(0.36, 0.08, 0.03), wood);\n      slat.position.set(0, y, -0.17);\n      group.add(slat);\n    }\n    radius = 0.3;\n  }\n  // Sitting places — chairs and stools seat one, benches two.\n  const slots: PropSlot[] =\n    style === 'bench'\n      ? [createSlot('sit', 'sit', group, -0.4, 0, 0), createSlot('sit', 'sit', group, 0.4, 0, 0)]\n      : [createSlot('sit', 'sit', group, 0, 0, 0)];\n  return { object: group, obstacleRadius: radius, slots };\n}\n\n// ---- beds --------------------------------------------------------------\n\nexport type BedSize = 'single' | 'double' | 'bunk';\n\nexport interface BedOptions {\n  seed?: number;\n  /** 'single', wide 'double', or stacked 'bunk'. */\n  size?: BedSize;\n  palette?: Palette;\n}\n\n/** A post bed with mattress, quilt and pillow. Bunks stack two. */\nexport function createBed(options: BedOptions = {}): Prop {\n  const seed = options.seed ?? 1;\n  const rng = new Rng(seed);\n  const size = options.size ?? 'single';\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const frame = createSurface('wood', { color: palette.woodDark, seed });\n  const linen = new MeshStandardMaterial({ color: 0xefe6d2, flatShading: true });\n  const quiltMat = createSurface('canvas', { color: palette.roof, seed: seed + 2 });\n\n  const w = size === 'double' ? 1.6 : 0.95;\n  const l = 2.05;\n  const group = new Group();\n  group.name = `bed-${size}`;\n\n  const deck = (baseY: number): void => {\n    const base = new Mesh(new BoxGeometry(w, 0.1, l), frame);\n    base.position.y = baseY;\n    const mattress = new Mesh(new BoxGeometry(w - 0.08, 0.14, l - 0.08), linen);\n    mattress.position.y = baseY + 0.12;\n    const quilt = new Mesh(new BoxGeometry(w - 0.04, 0.08, l * 0.62), quiltMat);\n    quilt.position.set(0, baseY + 0.21, l * 0.16);\n    group.add(base, mattress, quilt);\n    const pillows = size === 'double' ? [-w / 4, w / 4] : [0];\n    for (const px of pillows) {\n      const pillow = new Mesh(new BoxGeometry(w * (size === 'double' ? 0.38 : 0.6), 0.09, 0.34), linen);\n      pillow.position.set(px, baseY + 0.22, -l / 2 + 0.28);\n      pillow.rotation.y = rng.jitter(0, 0.06);\n      group.add(pillow);\n    }\n    const head = new Mesh(new BoxGeometry(w, 0.5, 0.07), frame);\n    head.position.set(0, baseY + 0.3, -l / 2 + 0.03);\n    group.add(head);\n  };\n\n  const postH = size === 'bunk' ? 1.9 : 0.75;\n  for (const sx of [-1, 1]) {\n    for (const sz of [-1, 1]) {\n      const post = new Mesh(new BoxGeometry(0.09, postH, 0.09), frame);\n      post.position.set(sx * (w / 2 - 0.045), postH / 2, sz * (l / 2 - 0.045));\n      group.add(post);\n    }\n  }\n  deck(0.32);\n  if (size === 'bunk') {\n    deck(1.35);\n    // Ladder up the side.\n    for (const y of [0.55, 0.9, 1.25]) {\n      const rung = new Mesh(new CylinderGeometry(0.025, 0.025, 0.4, 5), frame);\n      rung.rotation.z = Math.PI / 2;\n      rung.position.set(w / 2 + 0.02, y, l * 0.22);\n      group.add(rung);\n    }\n  }\n  // Sleeping places: anchor at the foot end on the mattress, pitched flat\n  // so the body extends toward the headboard (ANIMA's sleep convention).\n  const sleepAt = (x: number, deckY: number): PropSlot =>\n    createSlot('sleep', 'sleep', group, x, deckY + 0.22, l / 2 - 0.3, 0, -Math.PI / 2);\n  const slots: PropSlot[] =\n    size === 'bunk'\n      ? [sleepAt(0, 0.32), sleepAt(0, 1.35)]\n      : size === 'double'\n        ? [sleepAt(-w / 4, 0.32), sleepAt(w / 4, 0.32)]\n        : [sleepAt(0, 0.32)];\n  return { object: group, obstacleRadius: size === 'double' ? 1.25 : 1.1, slots };\n}\n\n// ---- shelves -----------------------------------------------------------\n\nexport type ShelfStock = 'books' | 'pottery' | 'food' | 'empty';\n\nexport interface ShelfOptions {\n  seed?: number;\n  /** What lines the boards: 'books', 'pottery', 'food' or 'empty'. */\n  stock?: ShelfStock;\n  palette?: Palette;\n}\n\n/** A tall open shelf, boards lined with seeded books, pots or provisions. */\nexport function createShelf(options: ShelfOptions = {}): Prop {\n  const seed = options.seed ?? 1;\n  const rng = new Rng(seed);\n  const stock = options.stock ?? 'books';\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const wood = createSurface('wood', { color: palette.woodDark, seed });\n  const board = createSurface('plank', { color: palette.wood, seed: seed + 1 });\n\n  const W = 1.25;\n  const H = 1.85;\n  const D = 0.34;\n  const group = new Group();\n  group.name = `shelf-${stock}`;\n\n  for (const side of [-1, 1]) {\n    const panel = new Mesh(new BoxGeometry(0.06, H, D), wood);\n    panel.position.set(side * (W / 2 - 0.03), H / 2, 0);\n    group.add(panel);\n  }\n  const back = new Mesh(new BoxGeometry(W, H, 0.04), wood);\n  back.position.set(0, H / 2, -D / 2 + 0.02);\n  group.add(back);\n\n  const boardYs = [0.28, 0.78, 1.28, 1.72];\n  const surfaces: PropSurface[] = [];\n  // The top of the carcass is a surface too, and the most used one in any\n  // real room.\n  surfaces.push(createPropSurface('top', group, 0, H, 0, W - 0.14, D - 0.06));\n  for (const y of boardYs) {\n    const shelfBoard = new Mesh(new BoxGeometry(W - 0.1, 0.05, D - 0.04), board);\n    shelfBoard.position.set(0, y, 0);\n    group.add(shelfBoard);\n  }\n  // Only the boards that are not already stocked: dressing a shelf of books\n  // puts a mug inside the books.\n  const free = (options.stock ?? 'books') === 'empty' ? boardYs : boardYs.slice(3);\n  for (const y of free) {\n    surfaces.push(createPropSurface('shelf', group, 0, y + 0.025, 0, W - 0.14, D - 0.08));\n  }\n\n  if (stock !== 'empty') {\n    const hues = [palette.roof, palette.water, palette.foliage[0], palette.trunk, palette.metal, palette.path];\n    for (const y of boardYs.slice(0, 3)) {\n      let x = -W / 2 + 0.14;\n      while (x < W / 2 - 0.16) {\n        if (stock === 'books') {\n          const bh = rng.range(0.16, 0.26);\n          const bw = rng.range(0.035, 0.06);\n          const bookMat = new MeshStandardMaterial({ color: rng.pick(hues), flatShading: true });\n          const tilt = rng.next() < 0.12 ? rng.range(0.1, 0.22) : 0;\n          const bk = new Mesh(new BoxGeometry(bw, bh, 0.2), bookMat);\n          bk.position.set(x, y + 0.025 + bh / 2, 0);\n          bk.rotation.z = tilt;\n          group.add(bk);\n          x += bw + 0.012 + tilt * 0.1;\n        } else if (stock === 'pottery') {\n          const r = rng.range(0.05, 0.09);\n          const ph = rng.range(0.12, 0.22);\n          const pot = new Mesh(\n            new CylinderGeometry(r * rng.range(0.5, 0.8), r, ph, 7),\n            createSurface('terracotta', { seed: rng.int(1, 1e9) })\n          );\n          pot.position.set(x + r, y + 0.025 + ph / 2, rng.jitter(0, 0.04));\n          group.add(pot);\n          x += r * 2 + rng.range(0.05, 0.12);\n        } else {\n          // food: sacks and round loaves\n          const r = rng.range(0.07, 0.1);\n          const isSack = rng.next() < 0.5;\n          const item = new Mesh(\n            isSack ? new IcosahedronGeometry(r, 0) : new SphereGeometry(r, 7, 5),\n            isSack\n              ? createSurface('canvas', { color: palette.sand, seed: rng.int(1, 1e9) })\n              : new MeshStandardMaterial({ color: 0xb8874f, flatShading: true })\n          );\n          item.scale.y = 0.72;\n          item.position.set(x + r, y + 0.025 + r * 0.6, rng.jitter(0, 0.04));\n          group.add(item);\n          x += r * 2 + rng.range(0.04, 0.1);\n        }\n      }\n    }\n  }\n  return { object: group, obstacleRadius: 0.65, surfaces };\n}\n\n// ---- chests ------------------------------------------------------------\n\nexport interface ChestOptions {\n  seed?: number;\n  /** Tilt the lid open. Default false. */\n  open?: boolean;\n  palette?: Palette;\n}\n\n/** A banded storage chest with a domed lid; `open` tilts it back. */\nexport function createChest(options: ChestOptions = {}): Prop {\n  const seed = options.seed ?? 1;\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const wood = createSurface('plank', { color: palette.wood, seed });\n  const metal = new MeshStandardMaterial({ color: palette.metal, flatShading: true, metalness: 0.5, roughness: 0.5 });\n\n  const W = 0.95;\n  const H = 0.5;\n  const D = 0.55;\n  const group = new Group();\n  group.name = 'chest';\n\n  const body = new Mesh(new BoxGeometry(W, H, D), wood);\n  body.position.y = H / 2;\n  group.add(body);\n  for (const x of [-W * 0.32, W * 0.32]) {\n    const band = new Mesh(new BoxGeometry(0.06, H + 0.02, D + 0.02), metal);\n    band.position.set(x, H / 2, 0);\n    group.add(band);\n  }\n\n  // Lid: a slab hinged at the back edge, with its own metal bands.\n  const lid = new Group();\n  lid.name = 'lid';\n  const slab = new Mesh(new BoxGeometry(W + 0.04, 0.12, D + 0.04), wood);\n  slab.position.set(0, 0.06, D / 2);\n  lid.add(slab);\n  for (const x of [-W * 0.32, W * 0.32]) {\n    const band = new Mesh(new BoxGeometry(0.06, 0.14, D + 0.06), metal);\n    band.position.set(x, 0.06, D / 2);\n    lid.add(band);\n  }\n  lid.position.set(0, H, -D / 2);\n  if (options.open) lid.rotation.x = -1.1;\n  group.add(lid);\n\n  const hasp = new Mesh(new BoxGeometry(0.08, 0.14, 0.03), metal);\n  hasp.position.set(0, H - 0.02, D / 2 + 0.015);\n  group.add(hasp);\n\n  // A closed chest is a surface; an open one is a hole. Publishing the lid\n  // top regardless would stand a candle in mid-air over an open box.\n  const surfaces = options.open\n    ? []\n    : [createPropSurface('top', group, 0, H + 0.12, 0, W - 0.08, D - 0.08)];\n\n  return { object: group, obstacleRadius: 0.55, surfaces };\n}\n\n// ---- candles -----------------------------------------------------------\n\nexport type CandleStyle = 'single' | 'candelabra' | 'chandelier';\n\nexport interface CandleOptions {\n  seed?: number;\n  /**\n   * 'single' tabletop candle on a dish, a standing 'candelabra', or a\n   * 'chandelier' meant to hang (origin at the hook — position it at the\n   * ceiling and it hangs down).\n   */\n  style?: CandleStyle;\n  /** Add one real PointLight. Default false — glow is free, lights are not. */\n  light?: boolean;\n  palette?: Palette;\n}\n\n/** Candlelight: glowing flames with a gentle flicker; real light opt-in. */\nexport function createCandle(options: CandleOptions = {}): Prop {\n  const seed = options.seed ?? 1;\n  const rng = new Rng(seed);\n  const style = options.style ?? 'single';\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const wax = new MeshStandardMaterial({ color: 0xf2e8d0, flatShading: true });\n  const metal = new MeshStandardMaterial({ color: palette.metal, flatShading: true, metalness: 0.4, roughness: 0.55 });\n  const flameMat = new MeshStandardMaterial({\n    color: palette.lampGlow,\n    emissive: palette.lampGlow,\n    emissiveIntensity: 1.9,\n    flatShading: true,\n  });\n\n  const group = new Group();\n  group.name = `candle-${style}`;\n  let lightY = 0.3;\n  let radius = 0;\n\n  const candleAt = (x: number, y: number, z: number, h: number): void => {\n    const stick = new Mesh(new CylinderGeometry(0.025, 0.03, h, 6), wax);\n    stick.position.set(x, y + h / 2, z);\n    const flame = new Mesh(new IcosahedronGeometry(0.035, 0), flameMat);\n    flame.scale.y = 1.7;\n    flame.position.set(x, y + h + 0.05, z);\n    group.add(stick, flame);\n  };\n\n  if (style === 'single') {\n    const dish = new Mesh(new CylinderGeometry(0.09, 0.11, 0.025, 8), metal);\n    dish.position.y = 0.012;\n    group.add(dish);\n    candleAt(0, 0.025, 0, rng.range(0.14, 0.22));\n    lightY = 0.3;\n  } else if (style === 'candelabra') {\n    const foot = new Mesh(new CylinderGeometry(0.14, 0.18, 0.04, 8), metal);\n    foot.position.y = 0.02;\n    const stem = new Mesh(new CylinderGeometry(0.03, 0.04, 1.15, 6), metal);\n    stem.position.y = 0.6;\n    group.add(foot, stem);\n    const arm = new Mesh(new BoxGeometry(0.72, 0.04, 0.04), metal);\n    arm.position.y = 1.18;\n    group.add(arm);\n    for (const x of [-0.34, 0, 0.34]) candleAt(x, x === 0 ? 1.24 : 1.2, 0, 0.16);\n    lightY = 1.5;\n    radius = 0.24;\n  } else {\n    // chandelier: origin at the hook, hangs downward.\n    const chain = new Mesh(new CylinderGeometry(0.015, 0.015, 0.7, 5), metal);\n    chain.position.y = -0.35;\n    const ring = new Mesh(new TorusGeometry(0.5, 0.035, 6, 10), metal);\n    ring.rotation.x = Math.PI / 2;\n    ring.position.y = -0.75;\n    group.add(chain, ring);\n    const n = 6;\n    for (let i = 0; i < n; i++) {\n      const a = (i / n) * Math.PI * 2;\n      candleAt(Math.cos(a) * 0.5, -0.75, Math.sin(a) * 0.5, 0.14);\n    }\n    lightY = -0.45;\n  }\n\n  let light: PointLight | null = null;\n  if (options.light) {\n    light = new PointLight(palette.lampGlow, style === 'single' ? 1.6 : 3.5, 7, 2);\n    light.position.y = lightY;\n    group.add(light);\n  }\n\n  // A gentle wax-flame flicker, self-driving like every SCENA fire.\n  const phase = rng.range(0, 20);\n  const flames = group.children.filter(\n    (child) => (child as Mesh).material === flameMat\n  ) as Mesh[];\n  if (flames.length > 0) {\n    const base = light?.intensity ?? 0;\n    flames[0].onBeforeRender = () => {\n      const t = performance.now() * 0.001 + phase;\n      const flick = 0.86 + 0.09 * Math.sin(t * 9.0) + 0.05 * Math.sin(t * 17.3 + 1.2);\n      flameMat.emissiveIntensity = 1.9 * flick;\n      if (light) light.intensity = base * flick;\n    };\n  }\n\n  return { object: group, obstacleRadius: radius };\n}\n\n// ---- rugs --------------------------------------------------------------\n\nexport type RugShape = 'round' | 'square' | 'runner';\n\nexport interface RugOptions {\n  seed?: number;\n  /** 'round' banded disc, 'square' bordered mat, or a long 'runner'. */\n  shape?: RugShape;\n  palette?: Palette;\n}\n\n/** A woven rug: banded, palette-dyed, and walk-through (radius 0). */\nexport function createRug(options: RugOptions = {}): Prop {\n  const seed = options.seed ?? 1;\n  const rng = new Rng(seed);\n  const shape = options.shape ?? 'round';\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const dyes = [palette.roof, palette.sand, palette.water, palette.path];\n  const group = new Group();\n  group.name = `rug-${shape}`;\n\n  if (shape === 'round') {\n    const rings = [1.0, 0.78, 0.5];\n    rings.forEach((r, i) => {\n      const disc = new Mesh(\n        new CylinderGeometry(r, r, 0.02 + i * 0.006, 10),\n        new MeshStandardMaterial({ color: dyes[(i + rng.int(0, 3)) % dyes.length], flatShading: true })\n      );\n      disc.position.y = 0.011 + i * 0.004;\n      disc.rotation.y = rng.range(0, Math.PI / 5);\n      group.add(disc);\n    });\n  } else {\n    const long = shape === 'runner' ? 2.6 : 1.6;\n    const wide = shape === 'runner' ? 1.0 : 1.6;\n    const border = new Mesh(\n      new BoxGeometry(long, 0.02, wide),\n      new MeshStandardMaterial({ color: dyes[rng.int(0, 3)], flatShading: true })\n    );\n    border.position.y = 0.01;\n    group.add(border);\n    const bands = shape === 'runner' ? 5 : 3;\n    for (let i = 0; i < bands; i++) {\n      const band = new Mesh(\n        new BoxGeometry((long - 0.3) / bands - 0.06, 0.02, wide - 0.3),\n        new MeshStandardMaterial({ color: dyes[(i + 1 + rng.int(0, 2)) % dyes.length], flatShading: true })\n      );\n      band.position.set(-((long - 0.3) / 2) + (i + 0.5) * ((long - 0.3) / bands), 0.02, 0);\n      group.add(band);\n    }\n  }\n  return { object: group, obstacleRadius: 0 };\n}\n","import {\n  BoxGeometry,\n  CylinderGeometry,\n  Group,\n  IcosahedronGeometry,\n  Mesh,\n  MeshStandardMaterial,\n  PointLight,\n  SphereGeometry,\n} from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport { createSurface } from '../materials/surface';\nimport type { Prop } from '../core/types';\n\n/**\n * Trade utilities — the props that give a room a job: a smith's forge, a\n * baker's oven, a weaver's loom, a taverner's counter. Same Prop contract\n * as everything else; `furnishRoom` places them by role.\n */\n\nexport interface WorkshopOptions {\n  seed?: number;\n  /** Forge only: add the real flickering PointLight. Default true. */\n  light?: boolean;\n  palette?: Palette;\n}\n\n/** Glowing-coal material + a flicker driver shared by forge and oven. */\nfunction glowingCoals(\n  group: Group,\n  rng: Rng,\n  count: number,\n  cx: number,\n  cy: number,\n  cz: number,\n  spread: number,\n  light: PointLight | null\n): void {\n  const coalMat = new MeshStandardMaterial({\n    color: 0x1a1008,\n    emissive: 0xff5a1a,\n    emissiveIntensity: 1.7,\n    flatShading: true,\n  });\n  for (let i = 0; i < count; i++) {\n    const coal = new Mesh(new IcosahedronGeometry(rng.range(0.05, 0.09), 0), coalMat);\n    coal.position.set(cx + rng.jitter(0, spread), cy + rng.range(0, 0.05), cz + rng.jitter(0, spread));\n    group.add(coal);\n  }\n  const phase = rng.range(0, 20);\n  const base = light?.intensity ?? 0;\n  group.children[group.children.length - 1].onBeforeRender = () => {\n    const t = performance.now() * 0.001 + phase;\n    const flick = 0.8 + 0.12 * Math.sin(t * 10.0) + 0.08 * Math.sin(t * 21.7 + 1.4);\n    coalMat.emissiveIntensity = 1.7 * flick;\n    if (light) light.intensity = base * flick;\n  };\n}\n\n/** A smith's corner: coal forge, anvil on a stump, quench barrel. */\nexport function createForge(options: WorkshopOptions = {}): Prop {\n  const seed = options.seed ?? 1;\n  const rng = new Rng(seed);\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const stone = createSurface('stone', { color: palette.rock[0], seed });\n  const metal = new MeshStandardMaterial({ color: palette.metal, flatShading: true, metalness: 0.55, roughness: 0.45 });\n\n  const group = new Group();\n  group.name = 'forge';\n\n  // The coal hearth: a waist-high stone box with a bed of burning coals.\n  const bed = new Mesh(new BoxGeometry(1.0, 0.75, 0.85), stone);\n  bed.position.set(-0.35, 0.375, 0);\n  group.add(bed);\n  const lip = new Mesh(new BoxGeometry(1.08, 0.1, 0.93), stone);\n  lip.position.set(-0.35, 0.78, 0);\n  group.add(lip);\n\n  let light: PointLight | null = null;\n  if (options.light ?? true) {\n    light = new PointLight(0xff7a28, 4, 6, 2);\n    light.position.set(-0.35, 1.1, 0);\n    group.add(light);\n  }\n  glowingCoals(group, rng, 6, -0.35, 0.85, 0, 0.24, light);\n\n  // Anvil on a stump.\n  const stump = new Mesh(new CylinderGeometry(0.2, 0.24, 0.45, 8), createSurface('wood', { color: palette.woodDark, seed: seed + 1 }));\n  stump.position.set(0.55, 0.225, 0.1);\n  group.add(stump);\n  const anvilBody = new Mesh(new BoxGeometry(0.5, 0.14, 0.16), metal);\n  anvilBody.position.set(0.55, 0.53, 0.1);\n  const anvilWaist = new Mesh(new BoxGeometry(0.2, 0.1, 0.12), metal);\n  anvilWaist.position.set(0.55, 0.5 - 0.05, 0.1);\n  const horn = new Mesh(new CylinderGeometry(0.028, 0.06, 0.22, 6), metal);\n  horn.rotation.z = Math.PI / 2 + 0.15;\n  horn.position.set(0.86, 0.55, 0.1);\n  group.add(anvilBody, anvilWaist, horn);\n\n  // Quench barrel.\n  const barrel = new Mesh(new CylinderGeometry(0.19, 0.17, 0.5, 9), createSurface('plank', { color: palette.woodDark, seed: seed + 2 }));\n  barrel.position.set(0.35, 0.25, -0.55);\n  const water = new Mesh(new CylinderGeometry(0.16, 0.16, 0.02, 9), new MeshStandardMaterial({ color: 0x1c2c33, roughness: 0.2 }));\n  water.position.set(0.35, 0.49, -0.55);\n  group.add(barrel, water);\n\n  return { object: group, obstacleRadius: 1.05 };\n}\n\n/** A baker's dome oven: stone dome, ember-lit mouth, chimney stub. */\nexport function createOven(options: WorkshopOptions = {}): Prop {\n  const seed = options.seed ?? 1;\n  const rng = new Rng(seed);\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const stone = createSurface('stone', { color: palette.rock[1] ?? palette.rock[0], seed });\n  const brick = createSurface('brick', { color: palette.roof, seed: seed + 1 });\n\n  const group = new Group();\n  group.name = 'oven';\n\n  const plinth = new Mesh(new BoxGeometry(1.2, 0.7, 1.0), stone);\n  plinth.position.y = 0.35;\n  group.add(plinth);\n  const dome = new Mesh(new SphereGeometry(0.52, 9, 6), brick);\n  dome.scale.y = 0.72;\n  dome.position.y = 0.72;\n  group.add(dome);\n  const chimney = new Mesh(new BoxGeometry(0.16, 0.5, 0.16), brick);\n  chimney.position.set(0, 1.2, -0.2);\n  group.add(chimney);\n\n  // The glowing mouth: a dark arch with embers inside — faces +z.\n  const mouth = new Mesh(\n    new CylinderGeometry(0.24, 0.24, 0.1, 8, 1, false, Math.PI, Math.PI),\n    new MeshStandardMaterial({ color: 0x140d08, flatShading: true })\n  );\n  mouth.rotation.x = Math.PI / 2;\n  mouth.rotation.y = Math.PI / 2;\n  mouth.position.set(0, 0.74, 0.44);\n  group.add(mouth);\n  glowingCoals(group, rng, 4, 0, 0.72, 0.42, 0.12, null);\n\n  // A peel (baker's paddle) leaning on the side.\n  const peelWood = createSurface('wood', { color: palette.wood, seed: seed + 2 });\n  const handle = new Mesh(new CylinderGeometry(0.02, 0.02, 1.3, 5), peelWood);\n  handle.position.set(0.68, 0.7, 0.1);\n  handle.rotation.z = 0.28;\n  const blade = new Mesh(new BoxGeometry(0.2, 0.02, 0.28), peelWood);\n  blade.position.set(0.5, 0.1, 0.1);\n  group.add(handle, blade);\n\n  return { object: group, obstacleRadius: 0.95 };\n}\n\n/** A weaver's upright loom: frame, warp threads, cloth growing up it. */\nexport function createLoom(options: WorkshopOptions = {}): Prop {\n  const seed = options.seed ?? 1;\n  const rng = new Rng(seed);\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const wood = createSurface('wood', { color: palette.wood, seed });\n  const dark = createSurface('wood', { color: palette.woodDark, seed: seed + 1 });\n\n  const group = new Group();\n  group.name = 'loom';\n  const W = 1.1;\n  const H = 1.7;\n\n  for (const side of [-1, 1]) {\n    const upright = new Mesh(new BoxGeometry(0.08, H, 0.1), dark);\n    upright.position.set(side * W / 2, H / 2, 0);\n    upright.rotation.x = -0.14;\n    group.add(upright);\n    const foot = new Mesh(new BoxGeometry(0.09, 0.07, 0.5), dark);\n    foot.position.set(side * W / 2, 0.035, 0.05);\n    group.add(foot);\n  }\n  for (const y of [H - 0.08, 0.35]) {\n    const beam = new Mesh(new CylinderGeometry(0.05, 0.05, W + 0.1, 7), wood);\n    beam.rotation.z = Math.PI / 2;\n    beam.position.set(0, y, (H / 2 - y) * 0.14);\n    group.add(beam);\n  }\n  // Warp threads.\n  const thread = new MeshStandardMaterial({ color: 0xe8dfc8, flatShading: true });\n  const n = 9;\n  for (let i = 0; i < n; i++) {\n    const x = -W / 2 + 0.12 + (i / (n - 1)) * (W - 0.24);\n    const t = new Mesh(new BoxGeometry(0.012, H - 0.5, 0.012), thread);\n    t.position.set(x, (H - 0.5) / 2 + 0.35, (H / 2 - ((H - 0.5) / 2 + 0.35)) * 0.14);\n    t.rotation.x = -0.14;\n    group.add(t);\n  }\n  // The woven cloth climbing the lower half, dyed from the palette.\n  const cloth = new Mesh(\n    new BoxGeometry(W - 0.2, 0.55, 0.03),\n    createSurface('canvas', { color: rng.pick([palette.roof, palette.water, palette.sand]), seed: seed + 2 })\n  );\n  cloth.position.set(0, 0.66, (H / 2 - 0.66) * 0.14 + 0.012);\n  cloth.rotation.x = -0.14;\n  group.add(cloth);\n\n  return { object: group, obstacleRadius: 0.68 };\n}\n\n/** A taverner's counter: paneled bar with mugs and a jug on top. */\nexport function createCounter(options: WorkshopOptions = {}): Prop {\n  const seed = options.seed ?? 1;\n  const rng = new Rng(seed);\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const top = createSurface('plank', { color: palette.wood, seed });\n  const panel = createSurface('wood', { color: palette.woodDark, seed: seed + 1 });\n\n  const group = new Group();\n  group.name = 'counter';\n  const L = 2.2;\n  const H = 1.0;\n\n  const base = new Mesh(new BoxGeometry(L - 0.15, H - 0.08, 0.5), panel);\n  base.position.y = (H - 0.08) / 2;\n  group.add(base);\n  const slab = new Mesh(new BoxGeometry(L, 0.08, 0.68), top);\n  slab.position.y = H - 0.04;\n  group.add(slab);\n  const rail = new Mesh(new CylinderGeometry(0.025, 0.025, L - 0.3, 6), panel);\n  rail.rotation.z = Math.PI / 2;\n  rail.position.set(0, 0.16, 0.32);\n  group.add(rail);\n\n  // Mugs and a jug along the top.\n  const glaze = new MeshStandardMaterial({ color: palette.path, flatShading: true });\n  const mugs = rng.int(2, 4);\n  for (let i = 0; i < mugs; i++) {\n    const mug = new Mesh(new CylinderGeometry(0.045, 0.05, 0.1, 7), glaze);\n    mug.position.set(rng.range(-L / 2 + 0.3, L / 2 - 0.3), H + 0.05, rng.jitter(0, 0.16));\n    group.add(mug);\n  }\n  const jug = new Mesh(\n    new CylinderGeometry(0.06, 0.1, 0.24, 8),\n    createSurface('terracotta', { seed: seed + 3 })\n  );\n  jug.position.set(rng.range(-L / 2 + 0.3, L / 2 - 0.3), H + 0.12, 0);\n  group.add(jug);\n\n  return { object: group, obstacleRadius: 1.15 };\n}\n","import { BoxGeometry, Group, Mesh, MeshStandardMaterial, Vector3 } from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport { createSurface } from '../materials/surface';\nimport { createGlass } from '../materials/glass';\nimport {\n  createCladding,\n  createModernWindow,\n  createPlanter,\n  createRailing,\n} from '../props/modern';\n\nexport interface BungalowOptions {\n  seed?: number;\n  /** Storeys: 1 or 2. Default 2. */\n  floors?: 1 | 2;\n  /** Ground-floor footprint. Defaults seeded around 9 × 7. */\n  width?: number;\n  depth?: number;\n  palette?: Palette;\n}\n\nexport interface Bungalow {\n  /** The villa, origin at ground level, entry facing +z. */\n  object: Group;\n  /** Steering circle for the whole footprint. */\n  obstacleRadius: number;\n  /** Every glass pane material — all `nightGlow`, ready for a day cycle. */\n  panes: MeshStandardMaterial[];\n  /** World-local point just outside the entry (spawn/walk-to target). */\n  entry: Vector3;\n}\n\n/**\n * A seeded modern bungalow — the Tier-4 materials composed into\n * architecture: a rendered ground box under a cantilevered concrete upper\n * box, floor-to-ceiling glazing on the garden face, a teak-slat or stone\n * accent, a balcony behind a glass or laser-cut railing, flat parapet\n * roofs, an entry canopy on steel posts and corten planters by the door.\n *\n * Every seed masses differently (cantilever side, accent style, glazing\n * rhythm, upper-box proportions); one palette themes the street. All the\n * glazing defaults to `nightGlow`, so listing the bungalow in a\n * `createDayCycle`'s `lamps` lights the house window-by-window at dusk.\n */\nexport function createBungalow(options: BungalowOptions = {}): Bungalow {\n  const seed = options.seed ?? 1;\n  const rng = new Rng(seed);\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const floors = options.floors ?? 2;\n  const W = options.width ?? rng.range(8.4, 10.5);\n  const D = options.depth ?? rng.range(6.2, 7.6);\n  const H = 3.0; // storey height\n\n  const group = new Group();\n  group.name = 'bungalow';\n  const panes: MeshStandardMaterial[] = [];\n\n  const render = createSurface('paint', { color: palette.wall, seed });\n  const concrete = createSurface('concrete', { seed: seed + 1 });\n  const fascia = new MeshStandardMaterial({ color: palette.roof, flatShading: true });\n\n  const slab = (w: number, d: number, x: number, y: number, z: number, h = 0.22): void => {\n    const roof = new Mesh(new BoxGeometry(w + 0.5, h, d + 0.5), fascia);\n    roof.position.set(x, y + h / 2, z);\n    group.add(roof);\n    const lip = new Mesh(new BoxGeometry(w + 0.56, 0.16, d + 0.56), fascia);\n    lip.position.set(x, y + h + 0.02, z);\n    group.add(lip);\n  };\n\n  const glazeBand = (w: number, h: number, x: number, y: number, z: number, cols: number): void => {\n    const win = createModernWindow({\n      seed: rng.int(1, 1e9), width: w, height: h, mullions: [cols, 1], palette,\n    });\n    win.object.position.set(x, y, z);\n    group.add(win.object);\n    panes.push(win.pane);\n  };\n\n  // ---- ground floor: rendered box, glazed garden face, teak entry ------\n  const ground = new Mesh(new BoxGeometry(W, H, D), render);\n  ground.position.y = H / 2;\n  group.add(ground);\n  // Floor-to-ceiling glazing across most of the front (+z).\n  const glassW = W * rng.range(0.42, 0.55);\n  glazeBand(glassW, H - 0.55, -W / 2 + glassW / 2 + 0.6, 0.06, D / 2 + 0.05, rng.int(3, 4));\n  // Entry: teak-framed door band on the other side of the front.\n  const doorX = W / 2 - 1.4;\n  const surround = new Mesh(new BoxGeometry(1.7, H - 0.3, 0.14), createSurface('teak', { seed: seed + 2 }));\n  surround.position.set(doorX, (H - 0.3) / 2, D / 2 + 0.03);\n  group.add(surround);\n  const door = createGlass({ frosted: true, nightGlow: true });\n  const doorPane = new Mesh(new BoxGeometry(1.06, H - 0.8, 0.05), door);\n  doorPane.position.set(doorX, (H - 0.8) / 2 + 0.02, D / 2 + 0.12);\n  group.add(doorPane);\n  panes.push(door);\n  // Entry canopy on two slim steel posts.\n  const canopy = new Mesh(new BoxGeometry(2.4, 0.12, 1.6), fascia);\n  canopy.position.set(doorX, H - 0.25, D / 2 + 0.8);\n  group.add(canopy);\n  const steel = createSurface('steel', { seed: seed + 3 });\n  for (const dx of [-0.9, 0.9]) {\n    const post = new Mesh(new BoxGeometry(0.07, H - 0.31, 0.07), steel);\n    post.position.set(doorX + dx, (H - 0.31) / 2, D / 2 + 1.45);\n    group.add(post);\n  }\n  // A side window on the gable face.\n  glazeBand(1.6, 1.3, W / 2 + 0.05, 1.1, D * rng.range(-0.2, 0.2), 2);\n  group.children[group.children.length - 1].rotation.y = Math.PI / 2;\n\n  // ---- accent cladding: teak slats or stone, on a front corner ---------\n  const accent = createCladding({\n    style: rng.next() < 0.6 ? 'slats' : 'stone',\n    width: rng.range(1.8, 2.6),\n    height: floors === 2 ? H * 2 + 0.3 : H,\n    seed: seed + 4,\n  });\n  accent.object.position.set(-W / 2 + 1.3, 0, D / 2 + 0.08);\n  group.add(accent.object);\n\n  if (floors === 2) {\n    // ---- upper floor: concrete box cantilevered toward the front -------\n    const W2 = W * rng.range(0.68, 0.85);\n    const D2 = D * rng.range(0.8, 0.95);\n    const side = rng.next() < 0.5 ? -1 : 1;\n    const x2 = side * (W - W2) * rng.range(0.15, 0.4);\n    const cant = rng.range(0.9, 1.5); // overhang toward +z\n    const z2 = (D2 - D) / 2 + cant;\n    const upper = new Mesh(new BoxGeometry(W2, H, D2), rng.next() < 0.5 ? concrete : render);\n    upper.position.set(x2, H * 1.5, z2);\n    group.add(upper);\n    // Sliding glazing across the upper front.\n    const upGlassW = W2 * rng.range(0.5, 0.65);\n    glazeBand(upGlassW, 1.6, x2 - W2 * 0.1, H + 0.7, z2 + D2 / 2 + 0.05, 2);\n    // Balcony: the cantilever roof of the ground box, behind a railing.\n    const balconyW = W2 * 0.9;\n    const railing = createRailing({\n      style: rng.next() < 0.5 ? 'glass' : 'panel',\n      length: balconyW,\n      seed: seed + 5,\n      palette,\n    });\n    railing.object.position.set(x2, H, z2 + D2 / 2 + 0.85);\n    group.add(railing.object);\n    slab(W2, D2, x2, H * 2, z2);\n    // The exposed strip of ground-floor roof becomes the balcony deck.\n    const deck = new Mesh(new BoxGeometry(balconyW + 0.4, 0.08, 1.7), createSurface('teak', { seed: seed + 6 }));\n    deck.position.set(x2, H + 0.04, z2 + D2 / 2 + 0.1);\n    group.add(deck);\n  } else {\n    slab(W, D, 0, H, 0);\n  }\n  if (floors === 2) {\n    // Cap any exposed ground-floor roof at the back.\n    slab(W, D * 0.55, 0, H, -D * 0.22, 0.18);\n  }\n\n  // ---- a corten planter by the entry ------------------------------------\n  const planter = createPlanter({ seed: seed + 7, length: rng.range(1.2, 1.8), palette });\n  planter.object.position.set(doorX - 1.7, 0, D / 2 + 1.1);\n  group.add(planter.object);\n\n  return {\n    object: group,\n    obstacleRadius: Math.max(W, D) * 0.62,\n    panes,\n    entry: new Vector3(doorX, 0, D / 2 + 2.2),\n  };\n}\n","import { Color, MeshStandardMaterial } from 'three';\n\n/**\n * Stylized architectural glass — the facade material for modern windows,\n * balustrades, doors and curtain walls.\n *\n * Real transmission is far too heavy for whole facades, so this is a\n * transparent `MeshStandardMaterial` with two shader tricks patched in:\n *\n * - **Fresnel opacity**: face-on the pane stays see-through; edge-on it\n *   turns opaque and reflective, exactly how glass reads in life.\n * - **A procedural sky streak**: the reflected view direction samples a tiny\n *   built-in sky gradient, so panes carry a believable reflection with no\n *   environment map, no cube camera, no setup.\n *\n * `nightGlow` follows the house-window convention: the material's emissive\n * is set at the intensity `createDayCycle` scans for, so listing the mesh\n * (or its building) in the cycle's `lamps` makes the glass ignite at dusk —\n * the classic lit-window skyline, free.\n */\nexport interface GlassOptions {\n  /** Glass tint. Default a cool clear blue-grey. */\n  tint?: number | Color;\n  /** Face-on opacity (0–1). Default 0.24 (clear); frosted overrides higher. */\n  opacity?: number;\n  /** Milky translucent finish: higher opacity, rough, muted reflection. */\n  frosted?: boolean;\n  /** Sky-reflection strength (0–1). Default 0.55. */\n  reflect?: number;\n  /**\n   * Warm interior glow for `createDayCycle` to ignite at dusk (adds an\n   * emissive at lamp-scan intensity). Default false.\n   */\n  nightGlow?: boolean;\n  /** Sky gradient the reflection samples: zenith / horizon colours. */\n  sky?: number;\n  horizon?: number;\n}\n\nconst GLASS_FRAG_ALPHA = /* glsl */ `\n  // Fresnel: see-through face-on, mirror-like edge-on.\n  vec3 scenaV = normalize(vViewPosition);\n  float scenaFresnel = pow(1.0 - clamp(dot(normal, scenaV), 0.0, 1.0), 3.0);\n  diffuseColor.a = clamp(uGlassOpacity + (1.0 - uGlassOpacity) * scenaFresnel, 0.0, 1.0);\n`;\n\nconst GLASS_FRAG_SKY = /* glsl */ `\n  {\n    // Reflect the view ray and sample a tiny procedural sky by its height —\n    // an environment map's worth of \"glassiness\" for two mixes. View-space\n    // reflection is fine at this stylization level.\n    vec3 scenaR = reflect(-scenaV, normal);\n    float scenaUp = clamp(scenaR.y * 0.5 + 0.5, 0.0, 1.0);\n    vec3 scenaSky = mix(uGlassHorizon, uGlassSky, scenaUp);\n    totalEmissiveRadiance += scenaSky * uGlassReflect * (0.25 + 0.75 * scenaFresnel);\n  }\n`;\n\nexport function createGlass(options: GlassOptions = {}): MeshStandardMaterial {\n  const frosted = options.frosted ?? false;\n  const tint = new Color(options.tint ?? 0x9fc4d8);\n  const opacity = options.opacity ?? (frosted ? 0.62 : 0.24);\n  const reflect = (options.reflect ?? 0.55) * (frosted ? 0.35 : 1);\n\n  const material = new MeshStandardMaterial({\n    color: tint,\n    roughness: frosted ? 0.55 : 0.08,\n    metalness: 0.1,\n    transparent: true,\n    opacity,\n    depthWrite: false,\n  });\n  if (options.nightGlow) {\n    // The lamp-scan convention: emissiveIntensity > 0.5 means \"adopt me\" —\n    // createDayCycle dims it by day and ignites it at night.\n    material.emissive.set(0xffc978);\n    material.emissiveIntensity = 1.1;\n  }\n\n  const uniforms = {\n    uGlassOpacity: { value: opacity },\n    uGlassReflect: { value: reflect },\n    uGlassSky: { value: new Color(options.sky ?? 0x87a8c8) },\n    uGlassHorizon: { value: new Color(options.horizon ?? 0xd8e2e8) },\n  };\n\n  material.onBeforeCompile = (shader) => {\n    Object.assign(shader.uniforms, uniforms);\n    shader.fragmentShader = shader.fragmentShader\n      .replace(\n        '#include <common>',\n        `#include <common>\n        uniform float uGlassOpacity;\n        uniform float uGlassReflect;\n        uniform vec3 uGlassSky;\n        uniform vec3 uGlassHorizon;`\n      )\n      // After the normal is final, before lighting: fresnel drives alpha…\n      .replace('#include <normal_fragment_maps>', '#include <normal_fragment_maps>\\n' + GLASS_FRAG_ALPHA)\n      // …and the sky streak lands with the emissive term.\n      .replace('#include <emissivemap_fragment>', '#include <emissivemap_fragment>\\n' + GLASS_FRAG_SKY);\n  };\n  material.customProgramCacheKey = () => 'scena-glass-v1';\n  (material.userData as { scenaGlass?: typeof uniforms }).scenaGlass = uniforms;\n\n  return material;\n}\n","import {\n  BoxGeometry,\n  CylinderGeometry,\n  Group,\n  IcosahedronGeometry,\n  Mesh,\n  MeshStandardMaterial,\n  PointLight,\n} from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport { createSurface } from '../materials/surface';\nimport { createGlass } from '../materials/glass';\nimport type { Prop } from '../core/types';\n\n/**\n * Modern building components — the steel-railing tier. Everything is on the\n * standard Prop contract and themed by the Tier-4 surfaces: brushed steel,\n * powder-coat, teak, corten, concrete and architectural glass.\n */\n\n// ---- railings ----------------------------------------------------------\n\nexport type RailingStyle = 'bars' | 'cable' | 'glass' | 'panel';\n\nexport interface RailingOptions {\n  seed?: number;\n  /** Vertical 'bars', horizontal 'cable', frameless 'glass', or a decorative laser-cut 'panel'. */\n  style?: RailingStyle;\n  /** Run length along local +x. Default 4. */\n  length?: number;\n  /** Rail height. Default 1.05. */\n  height?: number;\n  palette?: Palette;\n}\n\n/** A modern railing run — balconies, terraces, stairs. Like `createFence`,\n * the run lies along local +x and the obstacle circle spans it. */\nexport function createRailing(options: RailingOptions = {}): Prop {\n  const seed = options.seed ?? 1;\n  const style = options.style ?? 'bars';\n  const length = options.length ?? 4;\n  const height = options.height ?? 1.05;\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const steel = createSurface('steel', { seed });\n  const coat = createSurface('paintedMetal', { color: palette.metal, seed: seed + 1 });\n\n  const group = new Group();\n  group.name = `railing-${style}`;\n\n  const bays = Math.max(1, Math.round(length / 1.1));\n  const bayW = length / bays;\n  for (let i = 0; i <= bays; i++) {\n    const post = new Mesh(new BoxGeometry(0.05, height, 0.05), style === 'glass' ? steel : coat);\n    post.position.set(-length / 2 + i * bayW, height / 2, 0);\n    group.add(post);\n  }\n  const rail = new Mesh(new CylinderGeometry(0.03, 0.03, length + 0.06, 8), steel);\n  rail.rotation.z = Math.PI / 2;\n  rail.position.y = height;\n  group.add(rail);\n\n  if (style === 'bars') {\n    const n = Math.round(length / 0.13);\n    for (let i = 1; i < n; i++) {\n      const bar = new Mesh(new CylinderGeometry(0.011, 0.011, height - 0.12, 5), coat);\n      bar.position.set(-length / 2 + (i / n) * length, (height - 0.12) / 2 + 0.02, 0);\n      group.add(bar);\n    }\n  } else if (style === 'cable') {\n    for (let i = 1; i <= 5; i++) {\n      const cable = new Mesh(new CylinderGeometry(0.007, 0.007, length, 5), steel);\n      cable.rotation.z = Math.PI / 2;\n      cable.position.y = (i / 6) * height;\n      group.add(cable);\n    }\n  } else if (style === 'glass') {\n    // ONE glass for the whole run. Every bay in a balustrade is the same pane,\n    // and building it inside the loop gave a seven-bay railing seven identical\n    // materials for the renderer to bind separately — `npm run geometry`\n    // counts exactly this.\n    const glass = createGlass();\n    for (let i = 0; i < bays; i++) {\n      const pane = new Mesh(new BoxGeometry(bayW - 0.12, height - 0.2, 0.02), glass);\n      pane.position.set(-length / 2 + (i + 0.5) * bayW, (height - 0.2) / 2 + 0.06, 0);\n      group.add(pane);\n    }\n  } else {\n    // Decorative laser-cut sheet: the per-cell motif stamped in a darker tone.\n    const sheet = createSurface('paintedMetal', {\n      color: palette.metal, seed: seed + 2,\n      tile: 1, tileW: 0.18, tileH: 0.18, mortar: 0.002, bond: 0,\n      motif: 0.85, tint: 0x14181c, tileJitter: 0.02, tileRelief: 0.02,\n    });\n    const panel = new Mesh(new BoxGeometry(length - 0.08, height - 0.18, 0.02), sheet);\n    panel.position.y = (height - 0.18) / 2 + 0.04;\n    group.add(panel);\n  }\n  return { object: group, obstacleRadius: length / 2 };\n}\n\n// ---- windows -----------------------------------------------------------\n\nexport type ModernWindowStyle = 'fixed' | 'sliding';\n\nexport interface ModernWindowOptions {\n  seed?: number;\n  width?: number;\n  height?: number;\n  /** Mullion grid: [columns, rows] of panes. Default [2, 1]. */\n  mullions?: [number, number];\n  /** 'fixed' glazing or 'sliding' (two offset panes on a track). */\n  style?: ModernWindowStyle;\n  /** Glass options passthrough. */\n  tint?: number;\n  frosted?: boolean;\n  /** Emissive pane the day cycle ignites at dusk. Default true. */\n  nightGlow?: boolean;\n  palette?: Palette;\n}\n\nexport interface ModernWindowProp extends Prop {\n  /** The glass material — hand it to a day cycle via the building's lamps. */\n  pane: MeshStandardMaterial;\n}\n\n/** A framed modern window standing on local origin, facing ±z. */\nexport function createModernWindow(options: ModernWindowOptions = {}): ModernWindowProp {\n  const seed = options.seed ?? 1;\n  const width = options.width ?? 1.8;\n  const height = options.height ?? 1.5;\n  const [cols, rows] = options.mullions ?? [2, 1];\n  const style = options.style ?? 'fixed';\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const frame = createSurface('paintedMetal', { color: palette.metal, seed });\n  const pane = createGlass({\n    tint: options.tint,\n    frosted: options.frosted,\n    nightGlow: options.nightGlow ?? true,\n  });\n\n  const group = new Group();\n  group.name = `window-${style}`;\n  const t = 0.06; // frame thickness\n\n  const bar = (w: number, h: number, x: number, y: number, z = 0): void => {\n    const m = new Mesh(new BoxGeometry(w, h, 0.07), frame);\n    m.position.set(x, y, z);\n    group.add(m);\n  };\n  bar(width, t, 0, t / 2);\n  bar(width, t, 0, height - t / 2);\n  bar(t, height, -width / 2 + t / 2, height / 2);\n  bar(t, height, width / 2 - t / 2, height / 2);\n\n  if (style === 'fixed') {\n    for (let i = 1; i < cols; i++) bar(t * 0.7, height, -width / 2 + (i / cols) * width, height / 2);\n    for (let j = 1; j < rows; j++) bar(width, t * 0.7, 0, (j / rows) * height);\n    const glassPane = new Mesh(new BoxGeometry(width - t * 2, height - t * 2, 0.02), pane);\n    glassPane.position.y = height / 2;\n    group.add(glassPane);\n  } else {\n    // Two sliding leaves on a visible track, one offset behind the other.\n    const track = new Mesh(new BoxGeometry(width, 0.04, 0.12), frame);\n    track.position.y = 0.02;\n    group.add(track);\n    for (const [dir, dz] of [[-1, 0.025], [1, -0.025]] as const) {\n      const leafW = width / 2 + t;\n      const leaf = new Group();\n      const lf = new Mesh(new BoxGeometry(leafW, height - 0.08, 0.03), frame);\n      leaf.add(lf);\n      const lg = new Mesh(new BoxGeometry(leafW - t * 2, height - 0.08 - t * 2, 0.015), pane);\n      lg.position.z = 0.012;\n      leaf.add(lg);\n      leaf.position.set((dir * (width - leafW)) / 2, height / 2, dz);\n      group.add(leaf);\n    }\n  }\n  return { object: group, obstacleRadius: 0, pane };\n}\n\n// ---- gates -------------------------------------------------------------\n\nexport type GateStyle = 'slat' | 'bars' | 'panel';\n\nexport interface GateOptions {\n  seed?: number;\n  /** Horizontal 'slat' (teak or steel), vertical 'bars', or motif 'panel'. */\n  style?: GateStyle;\n  /** Clear opening width. Default 3.2. */\n  width?: number;\n  /** Leaf height. Default 1.6. */\n  height?: number;\n  /** Masonry pillars flanking the gate (with warm cap lamps). Default true. */\n  pillars?: boolean;\n  /** 0 closed … 1 fully open. Default 0. */\n  open?: number;\n  /** One sliding leaf instead of two swing leaves. */\n  sliding?: boolean;\n  palette?: Palette;\n}\n\nexport interface GateProp extends Prop {\n  /** Drive the gate: 0 closed … 1 open (swing leaves rotate, sliders slide). */\n  setOpen(fraction: number): void;\n}\n\n/** A modern driveway gate between concrete pillars. */\nexport function createGate(options: GateOptions = {}): GateProp {\n  const seed = options.seed ?? 1;\n  const style = options.style ?? 'slat';\n  const width = options.width ?? 3.2;\n  const height = options.height ?? 1.6;\n  const withPillars = options.pillars ?? true;\n  const sliding = options.sliding ?? false;\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const coat = createSurface('paintedMetal', { color: palette.metal, seed });\n  const teak = createSurface('teak', { seed: seed + 1 });\n\n  const group = new Group();\n  group.name = `gate-${style}`;\n\n  if (withPillars) {\n    for (const side of [-1, 1]) {\n      const pillar = new Mesh(new BoxGeometry(0.45, height + 0.5, 0.45), createSurface('concrete', { seed: seed + 2 }));\n      pillar.position.set(side * (width / 2 + 0.24), (height + 0.5) / 2, 0);\n      group.add(pillar);\n      const cap = new Mesh(new BoxGeometry(0.3, 0.1, 0.3), new MeshStandardMaterial({\n        color: palette.lampGlow, emissive: palette.lampGlow, emissiveIntensity: 1.2,\n      }));\n      cap.position.set(side * (width / 2 + 0.24), height + 0.56, 0);\n      group.add(cap);\n      if (side === 1) {\n        const lamp = new PointLight(palette.lampGlow, 0, 7, 2); // day cycle drives it\n        lamp.position.set(side * (width / 2 + 0.24), height + 0.7, 0);\n        group.add(lamp);\n      }\n    }\n  }\n\n  const buildLeaf = (leafW: number): Group => {\n    const leaf = new Group();\n    const frame = (w: number, h: number, x: number, y: number): void => {\n      const m = new Mesh(new BoxGeometry(w, h, 0.05), coat);\n      m.position.set(x, y, 0);\n      leaf.add(m);\n    };\n    frame(leafW, 0.07, leafW / 2, 0.1);\n    frame(leafW, 0.07, leafW / 2, height - 0.05);\n    frame(0.07, height - 0.05, 0.035, height / 2);\n    frame(0.07, height - 0.05, leafW - 0.035, height / 2);\n    if (style === 'slat') {\n      const n = 7;\n      for (let i = 1; i < n; i++) {\n        const slat = new Mesh(new BoxGeometry(leafW - 0.1, 0.09, 0.03), teak);\n        slat.position.set(leafW / 2, 0.12 + (i / n) * (height - 0.2), 0);\n        leaf.add(slat);\n      }\n    } else if (style === 'bars') {\n      const n = Math.round(leafW / 0.13);\n      for (let i = 1; i < n; i++) {\n        const gbar = new Mesh(new CylinderGeometry(0.012, 0.012, height - 0.2, 5), coat);\n        gbar.position.set((i / n) * leafW, height / 2, 0);\n        leaf.add(gbar);\n      }\n    } else {\n      const sheet = createSurface('paintedMetal', {\n        color: palette.metal, seed: seed + 3,\n        tile: 1, tileW: 0.2, tileH: 0.2, mortar: 0.002, bond: 0,\n        motif: 0.85, tint: 0x14181c, tileJitter: 0.02, tileRelief: 0.02,\n      });\n      const panel = new Mesh(new BoxGeometry(leafW - 0.1, height - 0.22, 0.02), sheet);\n      panel.position.set(leafW / 2, height / 2, 0);\n      leaf.add(panel);\n    }\n    return leaf;\n  };\n\n  const leaves: Array<{ leaf: Group; dir: number }> = [];\n  if (sliding) {\n    const leaf = buildLeaf(width + 0.2);\n    leaf.position.set(-width / 2 - 0.1, 0, 0.16);\n    group.add(leaf);\n    leaves.push({ leaf, dir: 1 });\n  } else {\n    for (const dir of [-1, 1]) {\n      const leaf = buildLeaf(width / 2 + 0.02);\n      leaf.position.set(dir * (width / 2), 0, 0);\n      if (dir === 1) leaf.scale.x = -1; // hinge both leaves at the pillars\n      group.add(leaf);\n      leaves.push({ leaf, dir });\n    }\n  }\n\n  const setOpen = (fraction: number): void => {\n    const f = Math.min(1, Math.max(0, fraction));\n    for (const { leaf, dir } of leaves) {\n      if (sliding) leaf.position.x = -width / 2 - 0.1 - f * (width + 0.2);\n      else leaf.rotation.y = dir * f * 1.9;\n    }\n  };\n  setOpen(options.open ?? 0);\n\n  return { object: group, obstacleRadius: width / 2 + 0.5, setOpen };\n}\n\n// ---- cladding & pergola ------------------------------------------------\n\nexport type CladdingStyle = 'slats' | 'louvers' | 'stone';\n\nexport interface CladdingOptions {\n  seed?: number;\n  /** Vertical teak 'slats', angled 'louvers', or a 'stone' feature panel. */\n  style?: CladdingStyle;\n  width?: number;\n  height?: number;\n  palette?: Palette;\n}\n\n/** A facade accent panel — the modern-bungalow signature. Flat against ±z. */\nexport function createCladding(options: CladdingOptions = {}): Prop {\n  const seed = options.seed ?? 1;\n  const style = options.style ?? 'slats';\n  const width = options.width ?? 3;\n  const height = options.height ?? 3;\n  const group = new Group();\n  group.name = `cladding-${style}`;\n\n  if (style === 'stone') {\n    const panel = new Mesh(new BoxGeometry(width, height, 0.14), createSurface('slate', {\n      seed, tile: 1, tileW: 0.55, tileH: 0.14, mortar: 0.008, bond: 1,\n      tileJitter: 0.22, mortarColor: 0x22262b, tileRelief: 0.08,\n    }));\n    panel.position.y = height / 2;\n    group.add(panel);\n  } else {\n    const teak = createSurface('teak', { seed });\n    const n = Math.round(width / 0.16);\n    for (let i = 0; i < n; i++) {\n      const slat = new Mesh(new BoxGeometry(0.09, height, 0.04), teak);\n      slat.position.set(-width / 2 + (i + 0.5) * (width / n), height / 2, 0);\n      if (style === 'louvers') slat.rotation.y = 0.6;\n      group.add(slat);\n    }\n    for (const y of [0.06, height - 0.06]) {\n      const rail = new Mesh(new BoxGeometry(width, 0.06, 0.03), teak);\n      rail.position.set(0, y, -0.035);\n      group.add(rail);\n    }\n  }\n  return { object: group, obstacleRadius: 0 };\n}\n\nexport interface PergolaOptions {\n  seed?: number;\n  width?: number;\n  depth?: number;\n  palette?: Palette;\n}\n\n/** A teak pergola: four posts, doubled beams, rafter slats. Walk-through\n * (obstacleRadius 0) — feed the posts to steering yourself if needed. */\nexport function createPergola(options: PergolaOptions = {}): Prop {\n  const seed = options.seed ?? 1;\n  const width = options.width ?? 3.6;\n  const depth = options.depth ?? 3;\n  const teak = createSurface('teak', { seed });\n  const H = 2.5;\n\n  const group = new Group();\n  group.name = 'pergola';\n  for (const sx of [-1, 1]) {\n    for (const sz of [-1, 1]) {\n      const post = new Mesh(new BoxGeometry(0.14, H, 0.14), teak);\n      post.position.set(sx * (width / 2 - 0.1), H / 2, sz * (depth / 2 - 0.1));\n      group.add(post);\n    }\n  }\n  for (const sz of [-1, 1]) {\n    const beam = new Mesh(new BoxGeometry(width + 0.5, 0.16, 0.08), teak);\n    beam.position.set(0, H + 0.08, sz * (depth / 2 - 0.1));\n    group.add(beam);\n  }\n  const rafters = Math.round(width / 0.42);\n  for (let i = 0; i <= rafters; i++) {\n    const rafter = new Mesh(new BoxGeometry(0.06, 0.12, depth + 0.5), teak);\n    rafter.position.set(-width / 2 + (i / rafters) * width, H + 0.22, 0);\n    group.add(rafter);\n  }\n  return { object: group, obstacleRadius: 0 };\n}\n\nexport interface PlanterOptions {\n  seed?: number;\n  /** Trough length. Default 1.6. */\n  length?: number;\n  palette?: Palette;\n}\n\n/** A corten planter trough with low greenery. */\nexport function createPlanter(options: PlanterOptions = {}): Prop {\n  const seed = options.seed ?? 1;\n  const rng = new Rng(seed);\n  const length = options.length ?? 1.6;\n  const palette = options.palette ?? DEFAULT_PALETTE;\n\n  const group = new Group();\n  group.name = 'planter';\n  const box = new Mesh(new BoxGeometry(length, 0.5, 0.45), createSurface('corten', { seed }));\n  box.position.y = 0.25;\n  group.add(box);\n  const soil = new Mesh(new BoxGeometry(length - 0.06, 0.04, 0.39), createSurface('dirt', { seed: seed + 1 }));\n  soil.position.y = 0.5;\n  group.add(soil);\n  const leaf = new MeshStandardMaterial({ color: rng.pick(palette.foliage), flatShading: true });\n  const clumps = Math.max(2, Math.round(length / 0.4));\n  for (let i = 0; i < clumps; i++) {\n    const clump = new Mesh(new IcosahedronGeometry(rng.range(0.14, 0.22), 0), leaf);\n    clump.position.set(-length / 2 + (i + 0.5) * (length / clumps), 0.58 + rng.range(0, 0.06), rng.jitter(0, 0.08));\n    group.add(clump);\n  }\n  return { object: group, obstacleRadius: length / 2 };\n}\n","import {\n  BoxGeometry,\n  Group,\n  InstancedMesh,\n  Matrix4,\n  Mesh,\n  MeshStandardMaterial,\n  Vector3,\n} from 'three';\nimport { Rng } from '../core/random';\nimport { DEFAULT_PALETTE, type Palette } from '../core/palette';\nimport { createSurface } from '../materials/surface';\nimport { createGlass } from '../materials/glass';\n\nexport interface HighriseOptions {\n  seed?: number;\n  /** Storeys above the lobby. Default 8. */\n  floors?: number;\n  /** Footprint. Defaults seeded around 12 × 10. */\n  width?: number;\n  depth?: number;\n  /** 'grid' punched windows in render, or full 'curtain' glazing. Seeded default. */\n  facade?: 'grid' | 'curtain';\n  /** Fraction of windows lit at night — the \"who's home\" mask. Default 0.55. */\n  occupancy?: number;\n  palette?: Palette;\n}\n\nexport interface Highrise {\n  /** The building, origin at ground level. */\n  object: Group;\n  /** Steering circle for the footprint. */\n  obstacleRadius: number;\n  /** Storeys above the lobby. */\n  floors: number;\n  /** The occupied-window glass — `nightGlow`, day-cycle adoptable. */\n  litPanes: MeshStandardMaterial;\n  /** How many of the tower's windows belong to the lit set. */\n  litCount: number;\n  /** Total windows. */\n  windowCount: number;\n}\n\n/**\n * A multi-storey modern tower whose cost does NOT scale with height: every\n * repeated element — windows, spandrels, mullions, floor bands — is an\n * `InstancedMesh`, so a 30-floor tower draws the same handful of calls as a\n * 6-floor one.\n *\n * The facade is either **punched windows in render** (`'grid'`) or a full\n * **curtain wall** (`'curtain'`): glass units around all four faces, split\n * into two seeded sets — *occupied* windows use `nightGlow` glass, the rest\n * stay dark. List the tower in a `createDayCycle`'s `lamps` and the classic\n * random lit-window skyline appears at dusk for free.\n *\n * Below and above the shaft: a double-height glazed lobby with a steel\n * canopy, and a parapet roof carrying the plant room.\n */\nexport function createHighrise(options: HighriseOptions = {}): Highrise {\n  const seed = options.seed ?? 1;\n  const rng = new Rng(seed);\n  const palette = options.palette ?? DEFAULT_PALETTE;\n  const floors = Math.max(2, options.floors ?? 8);\n  const W = options.width ?? rng.range(10.5, 13.5);\n  const D = options.depth ?? rng.range(8.5, 11);\n  const facade = options.facade ?? (rng.next() < 0.5 ? 'grid' : 'curtain');\n  const occupancy = options.occupancy ?? 0.55;\n  const H = 3.0; // storey height\n  const LOBBY = 4.2;\n\n  const group = new Group();\n  group.name = `tower-${facade}`;\n\n  const render = createSurface('paint', { color: palette.wall, seed });\n  const concrete = createSurface('concrete', { seed: seed + 1 });\n  const fascia = new MeshStandardMaterial({ color: palette.roof, flatShading: true });\n  const litGlass = createGlass({ nightGlow: true });\n  const darkGlass = createGlass({ tint: 0x6a7e8c, reflect: 0.4 });\n\n  // ---- the shaft: a solid core the windows sit proud of ----------------\n  const shaftH = floors * H;\n  const core = new Mesh(new BoxGeometry(W, shaftH, D), facade === 'grid' ? render : concrete);\n  core.position.y = LOBBY + shaftH / 2;\n  group.add(core);\n\n  // ---- window instances around all four faces --------------------------\n  const baysX = Math.max(2, Math.round(W / 1.6));\n  const baysZ = Math.max(2, Math.round(D / 1.6));\n  const winW = facade === 'curtain' ? 1.0 : 0.72; // fraction of the bay\n  const winH = facade === 'curtain' ? H - 0.5 : 1.6;\n  const sillY = facade === 'curtain' ? 0.25 : 0.8;\n\n  interface Slot { position: Vector3; rotY: number }\n  const slots: Slot[] = [];\n  for (let f = 0; f < floors; f++) {\n    const y = LOBBY + f * H + sillY + winH / 2;\n    for (let i = 0; i < baysX; i++) {\n      const x = -W / 2 + ((i + 0.5) / baysX) * W;\n      slots.push({ position: new Vector3(x, y, D / 2 + 0.04), rotY: 0 });\n      slots.push({ position: new Vector3(x, y, -D / 2 - 0.04), rotY: Math.PI });\n    }\n    for (let i = 0; i < baysZ; i++) {\n      const z = -D / 2 + ((i + 0.5) / baysZ) * D;\n      slots.push({ position: new Vector3(W / 2 + 0.04, y, z), rotY: Math.PI / 2 });\n      slots.push({ position: new Vector3(-W / 2 - 0.04, y, z), rotY: -Math.PI / 2 });\n    }\n  }\n  // Seeded partition: which windows are \"home\" tonight.\n  const lit: Slot[] = [];\n  const dark: Slot[] = [];\n  for (const slot of slots) (rng.next() < occupancy ? lit : dark).push(slot);\n\n  const bayW = Math.min(W / baysX, D / baysZ) * winW;\n  const paneGeo = new BoxGeometry(bayW, winH, 0.06);\n  const matrix = new Matrix4();\n  const rot = new Matrix4();\n  const instance = (list: Slot[], material: MeshStandardMaterial): void => {\n    if (list.length === 0) return;\n    const mesh = new InstancedMesh(paneGeo, material, list.length);\n    list.forEach((slot, i) => {\n      rot.makeRotationY(slot.rotY);\n      matrix.makeTranslation(slot.position.x, slot.position.y, slot.position.z).multiply(rot);\n      mesh.setMatrixAt(i, matrix);\n    });\n    mesh.instanceMatrix.needsUpdate = true;\n    group.add(mesh);\n  };\n  instance(lit, litGlass);\n  instance(dark, darkGlass);\n\n  // Mullion frames as one instanced element (a slim vertical per window).\n  const mullionGeo = new BoxGeometry(bayW + 0.1, winH + 0.12, 0.03);\n  const frames = new InstancedMesh(mullionGeo, fascia, slots.length);\n  slots.forEach((slot, i) => {\n    rot.makeRotationY(slot.rotY);\n    // A hair behind the pane, along each window's own facade normal.\n    matrix\n      .makeTranslation(\n        slot.position.x - Math.sin(slot.rotY) * 0.02,\n        slot.position.y,\n        slot.position.z - Math.cos(slot.rotY) * 0.02\n      )\n      .multiply(rot);\n    frames.setMatrixAt(i, matrix);\n  });\n  frames.instanceMatrix.needsUpdate = true;\n  group.add(frames);\n\n  // Floor bands ringing the shaft — one instance per storey.\n  const bandGeo = new BoxGeometry(W + 0.2, 0.32, D + 0.2);\n  const bands = new InstancedMesh(bandGeo, fascia, floors + 1);\n  for (let f = 0; f <= floors; f++) {\n    bands.setMatrixAt(f, matrix.makeTranslation(0, LOBBY + f * H, 0));\n  }\n  bands.instanceMatrix.needsUpdate = true;\n  group.add(bands);\n\n  // ---- lobby: double-height glazing, concrete piers, entry canopy ------\n  const lobbyGlass = new Mesh(new BoxGeometry(W - 0.6, LOBBY - 0.5, D - 0.6), litGlass);\n  lobbyGlass.position.y = (LOBBY - 0.5) / 2 + 0.1;\n  group.add(lobbyGlass);\n  for (const sx of [-1, 1]) {\n    for (const sz of [-1, 1]) {\n      const pier = new Mesh(new BoxGeometry(0.6, LOBBY, 0.6), concrete);\n      pier.position.set(sx * (W / 2 - 0.3), LOBBY / 2, sz * (D / 2 - 0.3));\n      group.add(pier);\n    }\n  }\n  const canopy = new Mesh(new BoxGeometry(W * 0.45, 0.14, 2.4), fascia);\n  canopy.position.set(0, LOBBY * 0.62, D / 2 + 1.1);\n  group.add(canopy);\n  const steel = createSurface('steel', { seed: seed + 2 });\n  for (const dx of [-W * 0.16, W * 0.16]) {\n    const post = new Mesh(new BoxGeometry(0.08, LOBBY * 0.62, 0.08), steel);\n    post.position.set(dx, LOBBY * 0.31, D / 2 + 2.1);\n    group.add(post);\n  }\n\n  // ---- roof: parapet + plant room --------------------------------------\n  const roofY = LOBBY + shaftH;\n  const parapet = new Mesh(new BoxGeometry(W + 0.3, 0.7, D + 0.3), concrete);\n  parapet.position.y = roofY + 0.35;\n  group.add(parapet);\n  const plant = new Mesh(\n    new BoxGeometry(W * rng.range(0.25, 0.4), 1.6, D * rng.range(0.3, 0.45)),\n    concrete\n  );\n  plant.position.set(W * rng.range(-0.15, 0.15), roofY + 1.5, D * rng.range(-0.15, 0.15));\n  group.add(plant);\n\n  return {\n    object: group,\n    obstacleRadius: Math.max(W, D) * 0.62,\n    floors,\n    litPanes: litGlass,\n    litCount: lit.length,\n    windowCount: slots.length,\n  };\n}\n"],"mappings":"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","names":["import_three","import_three","import_three","import_three","import_three","import_three","import_three","import_three","import_three","import_three","import_three","import_three","import_three","import_three","maxScale","import_three","import_three","import_three","import_three","import_three","import_three","import_three","import_three","inward","import_three","import_three","import_three","import_three","import_three","tint","import_three","import_three"]}