<!-- RUBY-BACKUP · part 479 -->
.anim);
  });
  WILD_ANIMALS = [];
  codeStatus('wildlife cleared');
}
function showPets(){
  var p = document.getElementById('pets');
  if(!p){
    p = document.createElement('div');
    p.id = 'pets';
    p.style.cssText = 'position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:10000;background:rgba(0,20,0,0.95);border:2px solid #44ff44;border-radius:12px;padding:20px;color:#fff;font:13px monospace;max-width:400px;max-height:80vh;overflow:auto;';
    document.body.appendChild(p);
  }
  p.style.display = 'block';
  var html = '<b style="color:#4f4;font-size:16px;">CHOOSE YOUR PET</b> ';
  html += '<button onclick="hidePets()">CLOSE</button> ';
  if(ACTIVE_PET) html += '<button onclick="dismissPet()">DISMISS</button>';
  html += '<br><br>';
  PETS.forEach(function(pet){
    var sel = ACTIVE_PET===pet.id;
    html += '<div style="padding:8px;margin-bottom:6px;border:2px solid '+(sel?'#4f4':'#333')+';border-radius:8px">';
    html += '<div style="width:30px;height:30px;border-radius:50%;background:'+pet.color+';display:inline-block;vertical-align:middle;margin-right:10px"></div>';
    html += '<b style="color:#4f4">'+pet.name+'</b> <i style="color:#aaa">'+pet.desc+'</i><br>';
    if(!sel) html += '<button onclick="selectPet(\''+pet.id+'\')">ADOPT</button>';
    else html += '<span style="color:#4f4">WITH YOU</span>';
    html += '</div>';
  });
  p.innerHTML = html;
}
function hidePets(){
  var p = document.getElementById('pets');
  if(p) p.style.display='none';
}
function selectPet(id){
  ACTIVE_PET = id;
  try{ localStorage.setItem('ruby-pet', id); }catch(e){}
  spawnPet(id);
  showPets();
}
function dismissPet(){
  ACTIVE_PET = null;
  try{ localStorage.removeItem('ruby-pet'); }catch(e){}
  if(PET_MESH && typeof scene!=='undefined'){
    try{ scene.remove(PET_MESH); }catch(e){}
    PET_MESH = null;
  }
  if(PET_ANIM){ clearInterval(PET_ANIM); PET_ANIM = null; }
  codeStatus('pet dismissed');
  showPets();
}
function spawnPet(id){
  if(PET_MESH && typeof scene!=='undefined'){
    try{ scene.remove(PET_MESH); }catch(e){}
  }
  if(PET_ANIM) clearInterval(PET_ANIM);
  var pet = PETS.find(function(x){ return x.id===id; });
  if(!pet || typeof THREE==='undefined' || typeof scene==='undefined') return;
  /* small cute pet — sphere with eyes */
  var group = new THREE.Group();
  var bodyM = new THREE.Mesh(
    new THREE.SphereGeometry(0.15, 14, 14),
    new THREE.MeshStandardMaterial({color: new THREE.Color(pet.color), roughness: 0.6})
  );
  group.add(bodyM);
  /* eyes */
  var dark = new THREE.MeshStandardMaterial({color: 0x222222});
  [-1,1].forEach(function(s){
    var eye = new THREE.Mesh(new THREE.SphereGeometry(0.03, 8, 8), dark);
    eye.position.set(s*0.06, 0.05, 0.12);
    group.add(eye);
  });
  PET_MESH = group;
  if(typeof mePos!=='undefined'){
    PET_MESH.position.set(mePos.x*0.13+0.5, 0.3, mePos.z*0.13+0.5);
  }
  scene.add(PET_MESH);
  /* follow the player */
  var t = 0;
  PET_ANIM = setInterval(function(){
    t += 0.1;
    if(!PET_MESH || typeof mePos==='undefined') return;
    /* hop toward player */
    var tx = mePos.x*0.13+0.5, tz = mePos.z*0.13+0.5;
    var dx = tx - PET_MESH.position.x, dz = tz - PET_MESH.position.z;
    var dist = Math.sqrt(dx*dx+dz*dz);
    if(dist > 0.3){
      PET_MESH.position.x += dx*0.05;
      PET_MESH.position.z += dz*0.05;
      PET_MESH.position.y = 0.3 + Math.abs(Math.sin(t*4))*0.1; /* hop */
    }else{
      PET_MESH.position.y = 0.3 + Math.sin(t*2)*0.03; /* idle bob */
    }
  }, 50);
  codeStatus(pet.name+' adopted! It follows you.');
}
setTimeout(function(){
  try{
    var saved = localStorage.getItem('ruby-pet');
    if(saved){ ACTIVE_PET = saved; spawnPet(saved); }
  }catch(e){}
}, 5000);

/* CHILDREN ONLY — kid-safe characters */
var KID_SAFE = ['dancer','youngking','joy','curious','brave','shy','healer','scout','dreamer','builder','spark','calm','wonder','circle','matriarch','patriarch','sovereign','sentinel','titan','wraith','strider','swift','cyborg','ember','tide','gale','mist','root','echo','proud','humble','sage','guardian','wanderer','keeper','oracle','nomad','artisan','kai','leilani','makoa','nalani','keala','kainalu'];

/* ADULT ONLY — not for children */
var ADULT_ONLY = ['unimpressed','smugbug','reluctant','anger','sorrow','warrior','trickster','wraith','inferno','abyss','brimstone','shadowdemon','malice'];
function isAdultOnly(id){
  return ADULT_ONLY.indexOf(id) >= 0;
}
function isKidSafe(id){
  return KID_SAFE.indexOf(id) >= 0;
}
function getVisibleAvatars(){
  /* children see only kid-safe ones */
  var age = (typeof getAge==='function') ? getAge() : null;
  var kidMode = (typeof KIDMODE_ON!=='undefined' && KIDMODE_ON);
  if((age!==null && age<18) || kidMode){
    return AVATARS.filter(function(a){ return isKidSafe(a.id); });
  }
  return AVATARS;
}
function showAvatars(){
  var a = document.getElementById('avatars');
  if(!a){
    a = document.createElement('div');
    a.id = 'avatars';
 