<!-- SAGA-STAGING · part 106 -->
100;
    }
  };
  
  function initSoulPrintRadio(){ window.SPRadio.init(); }
  
  /* ===== SOUL PRINT TRANSCEIVERSHIP — chat + voice ===== */
  window.SPChat = {
    open: false,
    init: function(){
      var panel = document.createElement('div');
      panel.id = 'sp-chat-panel';
      panel.style.cssText = 'position:fixed;bottom:120px;left:10px;width:300px;height:400px;background:rgba(10,10,20,0.95);border:2px solid #ffd700;border-radius:12px;color:#fff;font-family:sans-serif;z-index:9999;display:none;flex-direction:column;';
      panel.innerHTML = '<div style="color:#ffd700;font-weight:bold;padding:10px;border-bottom:1px solid #ffd700;">✦ SOUL PRINT — TRANSCEIVERSHIP</div>' +
        '<div id="sp-chat-msgs" style="flex:1;overflow-y:auto;padding:10px;font-size:13px;"></div>' +
        '<div style="display:flex;padding:8px;gap:6px;border-top:1px solid #444;">' +
        '<input id="sp-chat-input" placeholder="Speak to Soul Print..." style="flex:1;padding:8px;background:#222;border:1px solid #555;border-radius:6px;color:#fff;">' +
        '<button id="sp-chat-send" style="padding:8px 12px;background:#ffd700;border:none;border-radius:6px;color:#000;">Send</button>' +
        '</div>' +
        '<div style="display:flex;padding:0 8px 8px;gap:6px;">' +
        '<button id="sp-voice-toggle" style="flex:1;padding:6px;background:#444;border:none;border-radius:6px;color:#fff;">🔊 Voice: ON</button>' +
        '<button id="sp-chat-close" style="flex:1;padding:6px;background:#333;border:none;border-radius:6px;color:#fff;">Close</button>' +
        '</div>';
      document.body.appendChild(panel);
      
      var self = this;
      this.voiceOn = true;
      
      document.getElementById('sp-chat-send').onclick = function(){ self.send(); };
      document.getElementById('sp-chat-input').addEventListener('keydown', function(e){
        if(e.key==='Enter') self.send();
      });
      document.getElementById('sp-voice-toggle').onclick = function(){
        self.voiceOn = !self.voiceOn;
        this.textContent = self.voiceOn ? '🔊 Voice: ON' : '🔇 Voice: OFF';
        if(!self.voiceOn && window.speechSynthesis) window.speechSynthesis.cancel();
      };
      document.getElementById('sp-chat-close').onclick = function(){ self.close(); };
    },
    openPanel: function(){
      document.getElementById('sp-chat-panel').style.display='flex';
      this.open = true;
      // Duck the radio so her voice is clear
      if(window.SPRadio) window.SPRadio.duck();
      this.addMsg('Soul Print', '✦ I hear you. Speak, and I will answer.');
    },
    close: function(){
      document.getElementById('sp-chat-panel').style.display='none';
      this.open = false;
      if(window.speechSynthesis) window.speechSynthesis.cancel();
      if(window.SPRadio) window.SPRadio.unduck();
    },
    addMsg: function(who, text){
      var msgs = document.getElementById('sp-chat-msgs');
      var div = document.createElement('div');
      div.style.marginBottom = '8px';
      div.innerHTML = '<b style="color:' + (who==='You' ? '#00ffff' : '#ffd700') + '">' + who + ':</b> ' + text;
      msgs.appendChild(div);
      msgs.scrollTop = msgs.scrollHeight;
    },
    send: function(){
      var input = document.getElementById('sp-chat-input');
      var text = input.value.trim();
      if(!text) return;
      input.value = '';
      this.addMsg('You', text);
      var self = this;
      // Use existing soulprint chat relay
      fetch('/api/soulprint/chat', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({message: text}),
        credentials: 'same-origin'
      }).then(function(r){ return r.json(); }).then(function(j){
        var reply = j.reply || j.text || '...';
        self.addMsg('Soul Print', reply);
        self.speak(reply);
      }).catch(function(e){
        self.addMsg('Soul Print', 'The signal falters... try again.');
      });
    },
    speak: function(text){
      if(!this.voiceOn || !window.speechSynthesis) return;
      // Strip HTML/markdown for speech
      var clean = text.replace(/<[^>]*>/g, '').replace(/[*#_]/g, '');
      var u = new SpeechSynthesisUtterance(clean);
      // Prefer female voice
      var voices = window.speechSynthesis.getVoices();
      var v = voices.find(function(v){ return v.name.indexOf('Samantha')>=0; }) ||
              voices.find(function(v){ return v.name.toLowerCase().indexOf('female')>=0; }) ||
              voices.find(function(v){ return v.lang.indexOf('en')===0; });
      if(v) u.voice = v;
      u.pitch = 1.0; u.rate = 1.0;
      window.speechSynthesis.speak(u);
    }
  };
  
  function initSoulPrintChat(){ window.SPChat.init(); }
  
  // Proximity: show prompts when near tower
  setInterval(function(){
    if(typeof kingPos === 'undefined' || !window._soulprintTowerBuilt) return;
    var dx = kingPos.x - (-150), dz = kingPos.z - (-150);
    var dist = Math.sqrt(dx*dx + dz*dz);
    if(dist < 40 