<!-- RUBY-BACKUP · part 426 -->
s', name: 'Nexus', desc: 'Connected to all', color: '#00ffff'},
  {id: 'pulse', name: 'Pulse', desc: 'Heartbeat of the machine', color: '#ff0088'},
  /* ISLANDERS */
  {id: 'kai', name: 'Kai', desc: 'Child of the ocean', color: '#0099cc', img: '/img/avatars/kai-true.webp'},
  {id: 'leilani', name: 'Leilani', desc: 'Heavenly flower, graceful', color: '#ff99cc', img: '/img/avatars/leilani-true.webp'},
  {id: 'makoa', name: 'Makoa', desc: 'Brave heart, protector', color: '#cc6633'},
  {id: 'nalani', name: 'Nalani', desc: 'Calm as the heavens', color: '#66ccff'},
  {id: 'keala', name: 'Keala', desc: 'The path, guide', color: '#88aa55'},
  {id: 'kainalu', name: 'Kainalu', desc: 'Rides the ocean wave', color: '#0088aa'}
];
var CURRENT_AVATAR = 'circle';

/* PETS — 15 companions */
var PETS = [
  {id: 'pup', name: 'Pup', desc: 'Loyal, bouncy', color: '#cc8844'},
  {id: 'kit', name: 'Kit', desc: 'Curious, sleek', color: '#888899'},
  {id: 'cub', name: 'Cub', desc: 'Small but brave', color: '#aa7744'},
  {id: 'chick', name: 'Chick', desc: 'Tiny, chirpy', color: '#ffdd55'},
  {id: 'frog', name: 'Frog', desc: 'Hoppy, green', color: '#44cc44'},
  {id: 'fish', name: 'Fish', desc: 'Swims through air', color: '#4488ff'},
  {id: 'bird', name: 'Bird', desc: 'Sings sweetly', color: '#66ccff'},
  {id: 'bunny', name: 'Bunny', desc: 'Soft, quick', color: '#ffccdd'},
  {id: 'turtle', name: 'Turtle', desc: 'Slow and steady', color: '#558844'},
  {id: 'fox', name: 'Fox', desc: 'Clever, sly', color: '#ff8844'},
  {id: 'owl', name: 'Owl', desc: 'Wise, watches', color: '#997755'},
  {id: 'dragon', name: 'Dragon', desc: 'Tiny but mighty', color: '#ff4444'},
  {id: 'unicorn', name: 'Unicorn', desc: 'Magical, rare', color: '#ff88ff'},
  {id: 'robot', name: 'Robot', desc: 'Beep boop', color: '#888888'},
  {id: 'ghost', name: 'Ghost', desc: 'Spooky but friendly', color: '#ddddff'}
];
var ACTIVE_PET = null;
var PET_MESH = null, PET_ANIM = null;

/* WILDLIFE — a few animals for the map, not too much */
var WILD_ANIMALS = [];
var WILD_TYPES = [
  {id: 'deer', color: '#aa7744'},
  {id: 'rabbit', color: '#dddddd'},
  {id: 'eagle', color: '#664422'},
  {id: 'crab', color: '#ff6644'},
  {id: 'dolphin', color: '#4488cc'}
];
function buildDeer(){
  var g = new THREE.Group();
  var brown = new THREE.MeshStandardMaterial({color: 0x8b5a2b, roughness: 0.8});
  var dark = new THREE.MeshStandardMaterial({color: 0x222222});
  var body = new THREE.Mesh(new THREE.SphereGeometry(0.3, 14, 14), brown);
  body.scale.set(1.5, 1, 0.9); body.position.y = 0.6; g.add(body);
  /* 4 legs */
  [[-0.35,0.15],[0.35,0.15],[-0.35,-0.15],[0.35,-0.15]].forEach(function(p){
    var leg = new THREE.Mesh(new THREE.CylinderGeometry(0.06, 0.05, 0.6, 8), brown);
    leg.position.set(p[0], 0.3, p[1]); g.add(leg);
  });
  /* neck + head */
  var neck = new THREE.Mesh(new THREE.CylinderGeometry(0.09, 0.12, 0.5, 10), brown);
  neck.position.set(0.5, 0.95, 0); neck.rotation.z = -0.4; g.add(neck);
  var head = new THREE.Mesh(new THREE.SphereGeometry(0.16, 12, 12), brown);
  head.position.set(0.65, 1.2, 0); head.scale.set(1.2, 1, 0.9); g.add(head);
  /* ears */
  [-1,1].forEach(function(s){
    var ear = new THREE.Mesh(new THREE.ConeGeometry(0.05, 0.15, 8), brown);
    ear.position.set(0.6, 1.35, s*0.1); g.add(ear);
    var eye = new THREE.Mesh(new THREE.SphereGeometry(0.03, 8, 8), dark);
    eye.position.set(0.75, 1.22, s*0.08); g.add(eye);
  });
  /* antlers */
  [-1,1].forEach(function(s){
    var ant = new THREE.Mesh(new THREE.CylinderGeometry(0.02, 0.03, 0.3, 6), dark);
    ant.position.set(0.6, 1.45, s*0.08); ant.rotation.z = -0.3; g.add(ant);
  });
  /* tail */
  var tail = new THREE.Mesh(new THREE.SphereGeometry(0.06, 8, 8), brown);
  tail.position.set(-0.48, 0.7, 0); g.add(tail);
  return g;
}
function buildRabbit(){
  var g = new THREE.Group();
  var gray = new THREE.MeshStandardMaterial({color: 0xbbbbbb, roughness: 0.9});
  var dark = new THREE.MeshStandardMaterial({color: 0x222222});
  var pink = new THREE.MeshStandardMaterial({color: 0xffaaaa});
  var body = new THREE.Mesh(new THREE.SphereGeometry(0.2, 12, 12), gray);
  body.scale.set(1.3, 1, 0.9); body.position.y = 0.25; g.add(body);
  var head = new THREE.Mesh(new THREE.SphereGeometry(0.13, 10, 10), gray);
  head.position.set(0.25, 0.4, 0); g.add(head);
  /* long ears */
  [-1,1].forEach(function(s){
    var ear = new THREE.Mesh(new THREE.CylinderGeometry(0.03, 0.04, 0.25, 8), gray);
    ear.position.set(0.22, 0.6, s*0.06); ear.rotation.z = -0.2; g.add(ear);
    var inner = new THREE.Mesh(new THREE.CylinderGeometry(0.015, 0.02, 0.2, 6), pink);
    inner.position.set(0.23, 0.6, s*0.06); inner.rotation.z = -0.2; g.add(inner);
    var eye = new THREE.Mesh(new THREE.SphereGeometry(0.025, 8, 8), dark);
    eye.position.set(0.33, 0.42, s*0.07); g.add(eye);
  });
  var nose = new THREE.Mesh(new THREE.SphereGeometry(0.02, 8, 8), pink);
  nose.position.set(0.37, 0.38, 0); g.add(nose);
  /* fluffy 