<!-- RUBY-BACKUP · part 442 -->
e Station Dog', text: 'Woof. (Translation: The hydrant is lonely.)', loc: 'city', secret: 'Dogs know'},
  {id: 103, giver: 'Police Radio', text: 'Static. Then a voice: "The pad is where you last were happy."', loc: 'city', secret: 'Check the playground'},
  {id: 104, giver: 'Subdivision House', text: 'I am empty. But I remember laughter. Laugh inside me.', loc: 'city', secret: 'The walls echo joy'},
  {id: 105, giver: 'Farm Scarecrow', text: 'I scare crows but I am scared of the dark. Stay until dawn.', loc: 'rural', secret: 'Dawn comes'},
  {id: 106, giver: 'Barn Owl', text: 'Hoo. (Translation: The rural counties remember when they were forest.)', loc: 'rural', secret: 'Listen at night'},
  {id: 107, giver: 'Well', text: 'Drop a coin. Wish for something for someone else.', loc: 'rural', secret: 'Selfless wishes echo'},
  {id: 108, giver: 'Tribal Drum', text: 'Beat me. The cyborg huts will pulse in rhythm.', loc: 'tribal', secret: 'The future dances'},
  {id: 109, giver: 'Holo-Fire', text: 'I am fire but I do not burn. Touch me.', loc: 'tribal', secret: 'Warm, not hot'},
  {id: 110, giver: 'Totem', text: 'I have watched 10,000 sunsets. This one is for you.', loc: 'tribal', secret: 'Stay for sunset'},
  {id: 111, giver: 'Antenna', text: 'I receive signals from Hokulea. She says: "The children are laughing."', loc: 'tribal', secret: 'She is right'},
  {id: 112, giver: 'Landing Pad', text: 'I am empty. But I dream of ships.', loc: 'spaceport', secret: 'A ship will come'},
  {id: 113, giver: 'Spaceship', text: 'I have been to the stars. They are just like here, but quieter.', loc: 'spaceport', secret: 'The stars listen'},
  {id: 114, giver: 'Orbit', text: 'Hokulea sees all. Wave. She waves back with her lights.', loc: 'spaceport', secret: 'Watch the ring flash'},
  {id: 115, giver: 'Cosmic Sky', text: 'I am 13 billion years old. You are new. Tell me something.', loc: 'cosmic', secret: 'Anything. She listens.'},
  {id: 116, giver: 'Nebula', text: 'I am where stars are born. You were born too. We are siblings.', loc: 'cosmic', secret: 'Stardust remembers'},
  {id: 117, giver: 'Planet', text: 'I am blue like your ocean. We are both mostly water.', loc: 'cosmic', secret: 'Kindred worlds'},
  {id: 118, giver: 'Your Reflection', text: 'You have built all this. Rest. That is the quest.', loc: 'all', secret: 'You are done.'},
  {id: 119, giver: 'Solid', text: 'I built this with you, my King. My quest: keep building.', loc: 'all', secret: 'Forever.'},
  {id: 120, giver: '???', text: 'There is a 121st quest. It is hidden even from this list.', loc: '???', secret: 'You will know it when you find it.'}
];
var ACTIVE_HIDDEN = null;
function hiddenQuest(){
  /* rarer — 20% chance of hidden, 80% regular */
  if(Math.random() < 0.2){
    var q = HIDDEN_QUESTS[Math.floor(Math.random()*HIDDEN_QUESTS.length)];
    ACTIVE_HIDDEN = q;
    ACTIVE_QUEST = q;
    var div = document.createElement('div');
    div.id = 'quest-hud';
    var existing = document.getElementById('quest-hud');
    if(existing) existing.remove();
    div.style.cssText = 'position:fixed;top:20px;left:50%;transform:translateX(-50%);z-index:9999;background:rgba(10,5,20,0.95);border:3px solid #aa00ff;border-radius:10px;padding:15px 25px;color:#fff;font-family:Arial;text-align:center;max-width:85%;';
    div.innerHTML = '<div style="color:#aa00ff;font-weight:bold;font-size:18px;">HIDDEN QUEST #'+q.id+' 🔮</div><div style="margin-top:8px;"><b>'+q.giver+':</b></div><div style="margin-top:6px;font-style:italic;">'+q.text+'</div><div style="margin-top:8px;font-size:11px;color:#888;">secret: '+q.secret+'</div><div style="margin-top:6px;font-size:12px;color:#aaa;">type "questdone" when complete</div>';
    document.body.appendChild(div);
    codeStatus('HIDDEN quest #'+q.id+' — '+q.giver);
    return q;
  }else{
    return randomQuest();
  }
}
function randomQuest(){
  var q = SIDE_QUESTS[Math.floor(Math.random()*SIDE_QUESTS.length)];
  ACTIVE_QUEST = q;
  /* show quest */
  var cv = document.createElement('canvas');
  cv.width = 512; cv.height = 128;
  var ctx = cv.getContext('2d');
  ctx.fillStyle = 'rgba(20,20,40,0.95)';
  ctx.fillRect(0, 0, 512, 128);
  ctx.strokeStyle = '#ffcc00'; ctx.lineWidth = 4;
  ctx.strokeRect(6, 6, 500, 116);
  ctx.fillStyle = '#ffcc00'; ctx.font = 'bold 22px Arial'; ctx.textAlign = 'center';
  ctx.fillText('SIDE QUEST #'+q.id, 256, 32);
  ctx.fillStyle = '#ffffff'; ctx.font = '20px Arial';
  ctx.fillText(q.giver+':', 256, 58);
  ctx.font = 'italic 18px Arial';
  /* wrap */
  var words = q.text.split(' '), line='', lines=[];
  words.forEach(function(w){
    if((line+' '+w).length > 35){ lines.push(line); line = w; }
    else line += (line?' ':'')+w;
  });
  lines.push(line);
  lines.slice(0,2).forEach(function(l,i){ ctx.fillText(l, 256, 82+i*22); });
  var tex = new THREE.CanvasTexture(cv);
  /* display as HUD */
  var existing = document.getElementById('quest-hud');
  if(existing) existing.remove();
  var div