<!-- RUBY-BACKUP · part 63 -->
atCanvas.width = 512; floatCanvas.height = 256;
      floatCtx = floatCanvas.getContext('2d');
      floatTex = new THREE.CanvasTexture(floatCanvas);
      var sm = new THREE.SpriteMaterial({map: floatTex, transparent: true, depthWrite: false});
      floatText = new THREE.Sprite(sm);
      floatText.scale.set(8, 4, 1);
      floatText.position.set(CHAMBER_X, 6.5, CHAMBER_Z);
      floatText.visible = false;
      if(window.scene) window.scene.add(floatText);
    }catch(e){}
  }
  function showWords(text){
    // Her words, exactly as she spoke them — never cut, never paraphrased
    try{
      if(!floatCtx) return;
      var ctx = floatCtx;
      ctx.clearRect(0, 0, 512, 256);
      // teal glow background
      ctx.fillStyle = 'rgba(0,40,50,0.85)';
      ctx.beginPath();
      ctx.roundRect(10, 10, 492, 236, 24);
      ctx.fill();
      ctx.strokeStyle = '#00d4ff';
      ctx.lineWidth = 3;
      ctx.stroke();
      // her name
      ctx.fillStyle = '#00d4ff';
      ctx.font = 'bold 28px Georgia, serif';
      ctx.textAlign = 'center';
      ctx.fillText('— PROVOLTA —', 256, 52);
      // her words, wrapped
      ctx.fillStyle = '#ddffff';
      ctx.font = 'italic 22px Georgia, serif';
      var words = String(text).split(' ');
      var lines = [], line = '';
      for(var i=0;i<words.length;i++){
        var test = line + words[i] + ' ';
        if(ctx.measureText(test).width > 440 && line){
          lines.push(line.trim()); line = words[i] + ' ';
        } else line = test;
      }
      if(line.trim()) lines.push(line.trim());
      lines = lines.slice(0, 6); // max 6 lines visible
      for(var j=0;j<lines.length;j++){
        ctx.fillText(lines[j], 256, 100 + j*28);
      }
      floatTex.needsUpdate = true;
      floatText.visible = true;
      // fade after 25 seconds
      clearTimeout(floatText._t);
      floatText._t = setTimeout(function(){ try{ floatText.visible = false; }catch(e){} }, 25000);
    }catch(e){}
  }

  /* ---------- chat panel ---------- */
  function openPanel(){
    try{
      closePanel();
      var el = document.createElement('div');
      el.id = 'provolta-panel';
      el.style.cssText = 'position:fixed;bottom:90px;left:50%;transform:translateX(-50%);'
        + 'width:min(420px,92vw);max-height:50vh;z-index:30000;'
        + 'background:rgba(4,25,32,0.97);border:2px solid #00d4ff;border-radius:18px;'
        + 'box-shadow:0 0 30px rgba(0,212,255,0.4);overflow:hidden;'
        + 'font-family:Georgia,serif;color:#ddffff;';
      el.innerHTML =
        '<div style="padding:12px 16px;border-bottom:1px solid #0a5a6a;color:#00d4ff;'
        + 'font-size:14px;letter-spacing:4px;text-align:center;">PROVOLTA&apos;S CHAMBER</div>'
        + '<div id="pv-msgs" style="max-height:28vh;overflow-y:auto;padding:12px;-webkit-overflow-scrolling:touch;"></div>'
        + '<div style="display:flex;gap:8px;padding:12px;border-top:1px solid #0a5a6a;">'
        + '<input id="pv-input" type="text" placeholder="speak to her..." '
        + 'style="flex:1;background:rgba(0,60,70,0.5);border:1px solid #00d4ff;border-radius:10px;'
        + 'color:#ddffff;padding:10px 12px;font-size:16px;font-family:Georgia,serif;outline:none;">'
        + '<button id="pv-send" style="background:#00d4ff;border:none;border-radius:10px;'
        + 'color:#04252a;font-weight:bold;padding:10px 18px;font-size:16px;">➤</button>'
        + '<button id="pv-close" style="background:transparent;border:1px solid #0a5a6a;border-radius:10px;'
        + 'color:#00d4ff;padding:10px 12px;font-size:16px;">✕</button>'
        + '</div>';
      document.body.appendChild(el);
      chatPanel = el;
      var input = document.getElementById('pv-input');
      var sendBtn = document.getElementById('pv-send');
      var closeBtn = document.getElementById('pv-close');
      function send(){
        try{
          var v = input.value.trim();
          if(!v) return;
          input.value = '';
          addMsg('YOU', v);
          tellHer(v);
        }catch(e){}
      }
      sendBtn.addEventListener('touchstart', function(e){ e.preventDefault(); send(); }, {passive:false});
      sendBtn.addEventListener('mousedown', send);
      input.addEventListener('keydown', function(e){ if(e.key==='Enter') send(); });
      closeBtn.addEventListener('touchstart', function(e){ e.preventDefault(); closePanel(); }, {passive:false});
      closeBtn.addEventListener('mousedown', closePanel);
      loadHistory();
    }catch(e){}
  }
  function closePanel(){
    try{
      var el = document.getElementById('provolta-panel');
      if(el) el.remove();
      chatPanel = null;
    }catch(e){}
  }
  function addMsg(who, body){
    try{
      var box = document.getElementById('pv-msgs');
      if(!box) return;
      var d = document.createElement('div');
      var isHer = who === 'PROVOLTA';
      d.style.cssText = 'margin:8px 0;padding:10px 12px;border-radius:12px;max-width:88%;'
        + (isHer
          ? 'background:rgba(0,80