// world/biomes.js (Lane A) — the biome registry. Palette/fog values are transcribed from
// ART_BIBLE.md §Biome palettes; gameplay defaults (flow, coatDrain) are sane seeds that
// Lane C overrides per-segment in level JSON (`segments[].flow`). C owns the tuning, this
// owns the look.
//
// Canonical ids — level JSON `segments[].biome` must be one of these:
//   oral · esophagus · stomach · small_intestine · large_intestine · appendix
// Unknown id => NEUTRAL fallback + one console warning, never a crash.
//
// `wave.amp` is displacement in units, inward, at the crest — and it is a GAMEPLAY number, not
// just a look: world.wallRho() subtracts (amp + breathe) as its conservative margin, so raising
// it narrows Lane B's flight envelope. Esophagus 1.4 was measured in the harness, not guessed:
// the stub's 0.9 renders as a barely-legible ripple, and GDD §2 makes riding a crest for boost
// the level's signature mechanic — B cannot surf a crest the player can't see. 1.4 reads as
// distinct rings and still leaves ~78% of a radius-10 tube flyable. The other biomes are scaled
// in proportion and are UNVERIFIED until each one is actually built and eyeballed.

export const BIOMES = {
  oral: {
    id: 'oral',
    palette: { tint: 0xa8c4d8, rim: 0xdff2ff, void: 0x06090e },
    fog: 0.016,          // clinical, bright, tutorial-readable => you can see across the cavity
    flow: 5,
    coatDrain: 0.15,
    wave: { amp: 0.5, breathe: 0.10 },    // saliva tides, not real peristalsis
  },
  esophagus: {
    id: 'esophagus',
    palette: { tint: 0x1e6e64, rim: 0x5affd2, void: 0x02100d },
    fog: 0.028,
    flow: 14,
    coatDrain: 0.5,
    wave: { amp: 1.4, breathe: 0.15 },    // the signature: ribbed rings rushing past (measured)
  },
  stomach: {
    id: 'stomach',
    palette: { tint: 0xb0571e, rim: 0xffb13a, void: 0x120801 },
    fog: 0.020,
    flow: 4,
    coatDrain: 2.2,      // the acid sea: brutal in open acid (GDD §Player systems)
    wave: { amp: 0.7, breathe: 0.25 },    // churn, not transit
  },
  small_intestine: {
    id: 'small_intestine',
    palette: { tint: 0x7a2a6e, rim: 0xff6ad5, void: 0x0d0312 },
    fog: 0.050,          // dense: villi forest occludes sightlines
    flow: 9,
    coatDrain: 0.8,
    wave: { amp: 1.5, breathe: 0.18 },
  },
  large_intestine: {
    id: 'large_intestine',
    palette: { tint: 0x3a4a26, rim: 0x9dff4a, void: 0x050702 },
    fog: 0.075,          // darkness is the mechanic here; scanner light is the safety bubble
    flow: 5,
    coatDrain: 0.6,
    wave: { amp: 1.2, breathe: 0.2 },
  },
  appendix: {
    id: 'appendix',
    palette: { tint: 0x8a7020, rim: 0xffe066, void: 0x0a0800 },
    fog: 0.030,
    flow: 2,
    coatDrain: 0.3,
    wave: { amp: 0.5, breathe: 0.12 },
  },
};

const NEUTRAL = {
  id: 'neutral',
  palette: { tint: 0x557066, rim: 0x9fd8c8, void: 0x050a08 },
  fog: 0.03, flow: 10, coatDrain: 0.4, wave: { amp: 0.9, breathe: 0.15 },
};

const warned = new Set();

export function biome(id) {
  const b = BIOMES[id];
  if (b) return b;
  if (!warned.has(id)) {
    warned.add(id);
    console.warn(`[world] unknown biome "${id}" — falling back to neutral. Valid: ${Object.keys(BIOMES).join(', ')}`);
  }
  return NEUTRAL;
}
