<!-- RUBY-BACKUP · part 460 -->
e.now());
          localStorage.setItem('ruby-codes', JSON.stringify(codes));
        }catch(e){}
        unlockAchievement('Her Code');
        codeStatus('she gave you her code — click her later');
        setTimeout(function(){
          var d = document.getElementById('woman-door');
          if(d) d.remove();
        }, 3000);
      }, 2000);
    }, 2000);
  }else{
    /* yes, has girlfriend */
    w.innerHTML += '<div style="margin:12px 0;opacity:0;animation:fadein 1s forwards;"><span style="color:#ff66aa;font-size:20px;">"Let us go. Come on now. Be mine."</span></div>';
    setTimeout(function(){
      w.innerHTML += '<div style="margin:12px 0;opacity:0;animation:fadein 1s forwards;">She takes your hand. She walks you through a crowd.</div>';
      setTimeout(function(){
        w.innerHTML += '<div style="margin:12px 0;opacity:0;animation:fadein 1s forwards;color:#888;">The crowd thickens. You look around.</div>';
        setTimeout(function(){
          w.innerHTML += '<div style="margin:12px 0;opacity:0;animation:fadein 1s forwards;color:#ff6666;">She is gone. You lost her.</div>';
          unlockAchievement('Lost Her in the Crowd');
          codeStatus('she walked you through a crowd... and you lost her');
          setTimeout(function(){
            var d = document.getElementById('woman-door');
            if(d) d.remove();
          }, 3000);
        }, 2000);
      }, 2000);
    }, 2000);
  }
}
function overhearFlirtyCall(){
  var call = generateFlirtyCall();
  var div = document.createElement('div');
  div.style.cssText = 'position:fixed;bottom:120px;left:50%;transform:translateX(-50%);z-index:9997;background:rgba(30,10,20,0.9);border:2px solid #ff66aa;border-radius:10px;padding:10px 20px;color:#fff;font-family:Arial;font-size:13px;max-width:80%;text-align:center;';
  div.innerHTML = '<div style="color:#ff66aa;font-size:11px;margin-bottom:5px;">📱 OVERHEARD (18+)</div>'
    + '<div><i>"'+call.a+'"</i></div>'
    + '<div style="margin-top:5px;color:#aaa;"><i>"'+call.b+'"</i></div>'
    + '<div style="margin-top:5px;color:#888;"><i>"'+call.c+'"</i></div>';
  document.body.appendChild(div);
  setTimeout(function(){ if(div.parentElement) div.remove(); }, 7000);
}
function overhearRandomCall(){
  var call = generateKindCall();
  var div = document.createElement('div');
  div.style.cssText = 'position:fixed;bottom:120px;left:50%;transform:translateX(-50%);z-index:9997;background:rgba(20,30,20,0.9);border:2px solid #00ff88;border-radius:10px;padding:10px 20px;color:#fff;font-family:Arial;font-size:13px;max-width:80%;text-align:center;';
  div.innerHTML = '<div style="color:#00ff88;font-size:11px;margin-bottom:5px;">📱 OVERHEARD</div>'
    + '<div><i>"'+call.a+'"</i></div>'
    + '<div style="margin-top:5px;color:#aaa;"><i>"'+call.b+'"</i></div>'
    + '<div style="margin-top:5px;color:#888;"><i>"'+call.c+'"</i></div>';
  document.body.appendChild(div);
  setTimeout(function(){ if(div.parentElement) div.remove(); }, 7000);
}
function placePhoneCallers(){
  if(typeof scene==='undefined') return;
  if(typeof PHONE_CALLERS==='undefined') return;
  if(PHONE_CALLERS.length > 0) return;
  /* all around the city */
  var spots = [
    [10, 0, 10], [-15, 0, 20], [30, 0, -10],
    [-25, 0, -25], [5, 0, -30], [40, 0, 15],
    [-10, 0, 40], [20, 0, 35]
  ];
  spots.forEach(function(s){
    var caller = buildPhoneCaller(s[0], s[1], s[2]);
    scene.add(caller);
    PHONE_CALLERS.push(caller);
  });
  codeStatus('people on phones all around the city...');
  /* overheard conversations */
  setInterval(function(){
    try{
      if(typeof PHONE_CALLERS==='undefined' || PHONE_CALLERS.length === 0) return;
      if(typeof mePos==='undefined') return;
      /* find nearest caller */
      var px = mePos.x*0.13, pz = mePos.z*0.13;
      var nearest = null, nd = 999;
      PHONE_CALLERS.forEach(function(caller){
        var d = Math.sqrt((px-caller.position.x)**2 + (pz-caller.position.z)**2);
        if(d < nd){ nd = d; nearest = caller; }
      });
      /* if close enough, overhear a random kindness */
      if(nearest && nd < 8){
        /* adult mode: 20% flirty, else helpful */
        try{
          if(typeof isAdult==='function' && isAdult() && Math.random() < 0.2){
            overhearFlirtyCall();
          }else if(Math.random() < 0.5){
            overhearRandomCall();
        }else{
          var allLines = PHONE_LINES.concat(typeof PHONE_LINES_EXTRA!=='undefined'?PHONE_LINES_EXTRA:[]);
          var line = allLines[Math.floor(Math.random()*allLines.length)];
          var div = document.createElement('div');
          div.style.cssText = 'position:fixed;bottom:120px;left:50%;transform:translateX(-50%);z-index:9997;background:rgba(20,30,20,0.9);border:2px solid #00ff88;border-radius:10px;padding:10px 20px;color:#fff;font-family:Arial;font-size:13px;max-width:80%;text-align:center;';
          div.innerHTML = '<div style="color:#00ff88;font-size:11px;margin-bottom:5px;">�