/* ============================================================
   COPPER_AGENT_CARTRIDGE — app.js
   Created: 2026-06-26  Reason: engine + bilingual (EN/ES) UI for
   the ported Copper app. Zero runtime dependencies.
   - OCC engine ported WITH the decode() bug fixed
     (body.indexOf('b:')===0, never body.indexOf('b:'===0)).
   - Persistence routed through window.CartridgePlatform
     (namespaced localStorage) per CARTRIDGE_SOCKET_STANDARD v1.2,
     with COP1_v11_ localStorage fallback.
   - Language via CartridgePlatform.get/setLanguage (en default).
   - All renderers reproduce the source Copper feature surface:
     fact rotator, quick-lookup grid, category-pill accordions
     (default OPEN), private notes, copper price estimator,
     experiments intro + Top-10 + 18 accordions. Email setup +
     settings (email + owner key → adapter requestUnlock).
   Byte-identical across all three build targets. Loaded AFTER
   the platform adapter and AFTER content.js.
   ============================================================ */
(function(){
'use strict';

/* ---- platform adapter handle (adapter loads before this file) ---- */
var P = (typeof window!=='undefined' && window.CartridgePlatform) ? window.CartridgePlatform : null;

/* ══════════════ OCC ENGINE (bug-fixed) ══════════════ */
var OCC = (function(){
  var B62='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
  function b62e(n){if(n===0)return'0';var s='';while(n>0){s=B62[n%62]+s;n=Math.floor(n/62);}return s;}
  function b62d(s){var n=0;for(var i=0;i<s.length;i++)n=n*62+B62.indexOf(s[i]);return n;}
  function lzEnc(str){
    var W=255,L=12,out=[],pos=0;
    while(pos<str.length){
      var bo=0,bl=0,start=Math.max(0,pos-W);
      for(var i=start;i<pos;i++){
        var l=0;
        while(l<L&&pos+l<str.length&&str[i+l]===str[pos+l])l++;
        if(l>bl){bl=l;bo=pos-i;}
      }
      if(bl>=3){out.push([1,bo,bl]);pos+=bl;}
      else{out.push([0,str.charCodeAt(pos)]);pos++;}
    }
    return out;
  }
  function lzDec(tok){
    var out='';
    for(var i=0;i<tok.length;i++){
      var t=tok[i];
      if(t[0]===0)out+=String.fromCharCode(t[1]);
      else{var s=out.length-t[1];for(var j=0;j<t[2];j++)out+=out[s+j];}
    }
    return out;
  }
  function encode(obj){
    try{
      var json=JSON.stringify(obj);
      var tok=lzEnc(json);
      var parts=tok.map(function(t){return t[0]===0?'L'+b62e(t[1]):'M'+b62e(t[1])+'.'+b62e(t[2]);});
      return 'OCC1:'+parts.join('|');
    }catch(e){return 'OCC1:b:'+btoa(unescape(encodeURIComponent(JSON.stringify(obj))));}
  }
  function decode(str){
    if(!str||str.indexOf('OCC1:')<0)return null;
    var body=str.slice(5);
    try{
      // FIX 2026-06-26: was body.indexOf('b:'===0) which is always false →
      // always took LZ branch on base64 payloads → null. Corrected below.
      if(body.indexOf('b:')===0)return JSON.parse(decodeURIComponent(escape(atob(body.slice(2)))));
      var parts=body.split('|');
      var tok=parts.map(function(p){
        if(p[0]==='L')return[0,b62d(p.slice(1))];
        var sp=p.slice(1).split('.');
        return[1,b62d(sp[0]),b62d(sp[1])];
      });
      return JSON.parse(lzDec(tok));
    }catch(e){
      try{return JSON.parse(decodeURIComponent(escape(atob(body.indexOf('b:')===0?body.slice(2):body))));}
      catch(e2){return null;}
    }
  }
  /* persistence via platform adapter (namespaced) with localStorage fallback */
  function save(k,v){
    var enc=encode(v);
    if(P&&P.saveLocalData){try{P.saveLocalData(k,enc);return;}catch(e){}}
    try{localStorage.setItem('COP1_v11_'+k,enc);}catch(e){}
  }
  function load(k){
    var r=null;
    if(P&&P.loadLocalData){try{r=P.loadLocalData(k);}catch(e){}}
    if(r==null){try{r=localStorage.getItem('COP1_v11_'+k);}catch(e){}}
    if(!r)return null;
    var d=decode(r);
    if(d!==null)return d;
    try{return JSON.parse(r);}catch(e){return null;}
  }
  return{encode:encode,decode:decode,save:save,load:load};
})();

/* ══════════════ LANGUAGE ══════════════ */
var LANG = (P&&P.getLanguage)?(P.getLanguage()||'en'):'en';
if(LANG!=='en'&&LANG!=='es')LANG='en';
function setLang(l){
  if(l!=='en'&&l!=='es')return;
  LANG=l;
  if(P&&P.setLanguage){try{P.setLanguage(l);}catch(e){}}
  applyI18n();
  renderAll();
  var em=OCC.load('userEmail'); if(em) applyEmail(em);
  updateLangToggleUI();
}
function t(key){var s=STRINGS[LANG]; return (s&&s[key]!=null)?s[key]:(STRINGS.en[key]!=null?STRINGS.en[key]:key);}

/* ══════════════ UI STRING TABLE (EN/ES) ══════════════ */
var STRINGS = {
 en:{
  hdr_title:'Copper',
  hdr_sub:'An offline library of copper — health, history, kitchen, science, and markets',
  setup_title:'Personalize Your App',
  setup_body:'Enter your email address to make this app yours — it will greet you by name every time you open it.',
  setup_ph:'you@example.com',
  setup_confirm:'Confirm My Email →',
  setup_note:'Your email never leaves this device. It is only used to personalize your display.',
  setup_err:'Please enter a valid email address (e.g. you@example.com).',
  tab_home:'HOME', tab_health:'HEALTH', tab_history:'HISTORY', tab_cooking:'COOKING',
  tab_science:'SCIENCE', tab_invest:'INVEST', tab_experiments:'EXPERIMENTS',
  fact_label:'COPPER FACT OF THE DAY', fact_prev:'‹ Prev', fact_next:'Next ›', fact_loading:'Loading...',
  notes_title:'Private Notes', notes_ph:'Save a copper insight...', notes_save:'Save',
  notes_empty:'No notes yet. Anything you save stays on this device.',
  price_title:'Copper Price Estimator',
  price_sub:'Calculate scrap copper or investment value at current price.',
  price_lb:'Price ($/lb)', price_lb_ph:'e.g. 4.50',
  price_wt:'Weight (lbs)', price_wt_ph:'e.g. 100',
  price_calc:'Calculate Value', price_total:'Total Value:',
  price_need:'Enter both a price and a weight.',
  exp_topten_title:'Top 10 Easy Experiments to Start With',
  settings_title:'Settings', settings_email_lbl:'YOUR EMAIL', settings_key_lbl:'OWNER KEY',
  settings_key_ph:'Enter lifetime owner key', settings_save:'Save Settings',
  settings_ver:'Copper Agent v1.0',
  ftr_rights:'All Rights Reserved', ftr_created:'Created with', ftr_patent:'· Patent Pending',
  you_word:'You',
  toast_saved:'Settings saved', toast_personalized:'Personalized for', toast_unlock:'Owner key saved'
 },
 es:{
  hdr_title:'Cobre',
  hdr_sub:'Una biblioteca offline del cobre — salud, historia, cocina, ciencia y mercados',
  setup_title:'Personaliza tu App',
  setup_body:'Ingresa tu correo electrónico para hacer tuya esta app — te saludará por tu nombre cada vez que la abras.',
  setup_ph:'tu@example.com',
  setup_confirm:'Confirmar mi Correo →',
  setup_note:'Tu correo nunca sale de este dispositivo. Solo se usa para personalizar tu pantalla.',
  setup_err:'Por favor ingresa un correo válido (p. ej. tu@example.com).',
  tab_home:'INICIO', tab_health:'SALUD', tab_history:'HISTORIA', tab_cooking:'COCINA',
  tab_science:'CIENCIA', tab_invest:'INVERSIÓN', tab_experiments:'EXPERIMENTOS',
  fact_label:'DATO DEL COBRE DEL DÍA', fact_prev:'‹ Anterior', fact_next:'Siguiente ›', fact_loading:'Cargando...',
  notes_title:'Notas Privadas', notes_ph:'Guarda una idea sobre el cobre...', notes_save:'Guardar',
  notes_empty:'Aún no hay notas. Todo lo que guardes permanece en este dispositivo.',
  price_title:'Estimador de Precio del Cobre',
  price_sub:'Calcula el valor del cobre de chatarra o de inversión al precio actual.',
  price_lb:'Precio ($/lb)', price_lb_ph:'p. ej. 4.50',
  price_wt:'Peso (lbs)', price_wt_ph:'p. ej. 100',
  price_calc:'Calcular Valor', price_total:'Valor Total:',
  price_need:'Ingresa tanto un precio como un peso.',
  exp_topten_title:'Top 10 Experimentos Fáciles para Empezar',
  settings_title:'Ajustes', settings_email_lbl:'TU CORREO', settings_key_lbl:'CLAVE DE PROPIETARIO',
  settings_key_ph:'Ingresa la clave de propietario vitalicia', settings_save:'Guardar Ajustes',
  settings_ver:'Copper Agent v1.0',
  ftr_rights:'Todos los Derechos Reservados', ftr_created:'Creado con', ftr_patent:'· Patente en Trámite',
  you_word:'Tú',
  toast_saved:'Ajustes guardados', toast_personalized:'Personalizado para', toast_unlock:'Clave de propietario guardada'
 }
};

/* ══════════════ UTILITIES ══════════════ */
function $(id){return document.getElementById(id);}
function esc(s){return (s||'').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');}
function L(item){return item[LANG]||item.en;}

/* ══════════════ I18N — static chrome ══════════════ */
function applyI18n(){
  document.querySelectorAll('[data-i18n]').forEach(function(el){
    el.textContent=t(el.getAttribute('data-i18n'));
  });
  document.querySelectorAll('[data-i18n-ph]').forEach(function(el){
    el.setAttribute('placeholder',t(el.getAttribute('data-i18n-ph')));
  });
  document.documentElement.lang=LANG;
}

/* ══════════════ TABS ══════════════ */
function showTab(id,btn){
  document.querySelectorAll('.panel').forEach(function(p){p.classList.remove('active');});
  document.querySelectorAll('.tab-btn').forEach(function(b){b.classList.remove('active');});
  var panel=$('panel-'+id); if(panel)panel.classList.add('active');
  if(btn)btn.classList.add('active');
  else{var tb=$('tab-'+id); if(tb)tb.classList.add('active');}
}

/* ══════════════ FACT ROTATOR ══════════════ */
var factIdx=0;
function showFact(){
  var f=CONTENT.FACTS[factIdx]; if(!f)return;
  if($('factText'))$('factText').textContent=L(f);
  if($('factCounter'))$('factCounter').textContent=(factIdx+1)+' / '+CONTENT.FACTS.length;
}
function nextFact(){factIdx=(factIdx+1)%CONTENT.FACTS.length;showFact();}
function prevFact(){factIdx=(factIdx-1+CONTENT.FACTS.length)%CONTENT.FACTS.length;showFact();}

/* ══════════════ QUICK LOOKUP GRID ══════════════ */
function renderLookups(){
  var el=$('lookupGrid'); if(!el)return;
  while(el.firstChild)el.removeChild(el.firstChild);
  CONTENT.LOOKUPS.forEach(function(d){
    var card=document.createElement('div'); card.className='lookup-card';
    var v=document.createElement('div'); v.className='lookup-val'; v.textContent=String(d.val);
    var l=document.createElement('div'); l.className='lookup-lbl'; l.textContent=String(d[LANG]||d.en||'');
    card.appendChild(v); card.appendChild(l); el.appendChild(card);
  });
}

/* ══════════════ CATEGORY-PILL ACCORDIONS (default OPEN) ══════════════ */
function buildAccordions(cid,data){
  var c=$(cid); if(!c)return;
  while(c.firstChild)c.removeChild(c.firstChild);
  data.forEach(function(item){
    var d=L(item);
    var wrap=document.createElement('div'); wrap.className='acc-item open'; wrap.id='acc-'+item.id;
    var head=document.createElement('div'); head.className='acc-head';
    head.addEventListener("click", function(){ CA.toggleAcc(head); });
    var cat=document.createElement('span'); cat.className='acc-cat '+(d.catcls||''); cat.textContent=String(d.cat||'');
    var lab=document.createElement('span'); lab.className='acc-label'; lab.textContent=String(d.label||'');
    var arrow=document.createElement('span'); arrow.className='acc-arrow'; arrow.textContent='\u2304';
    head.appendChild(cat); head.appendChild(lab); head.appendChild(arrow);
    var body=document.createElement('div'); body.className='acc-body'; body.textContent=String(d.detail||'');
    if(d.warn){ var w=document.createElement('div'); w.className='acc-warn'; w.textContent=String(d.warn); body.appendChild(w); }
    wrap.appendChild(head); wrap.appendChild(body); c.appendChild(wrap);
  });
}
function toggleAcc(head){var item=head.closest('.acc-item');if(item)item.classList.toggle('open');}

/* ══════════════ EXPERIMENTS (intro + top10 + accordions) ══════════════ */
function renderExperiments(){
  var intro=$('expIntro');
  if(intro){
    var ei=L(CONTENT.EXP_INTRO);
    while(intro.firstChild)intro.removeChild(intro.firstChild);
    var t1=document.createElement('div'); t1.className='card-title'; t1.style.cssText='margin-bottom:6px;font-size:17px'; t1.textContent=String(ei.title||'');
    var p1=document.createElement('p'); p1.style.cssText='font-size:14.5px;color:var(--copper2);line-height:1.65;margin:0 0 8px'; p1.textContent=String(ei.p1||'');
    var p2=document.createElement('p'); p2.style.cssText='font-size:14px;color:var(--copper2);line-height:1.6;margin:0'; p2.textContent=String(ei.p2||'');
    intro.appendChild(t1); intro.appendChild(p1); intro.appendChild(p2);
  }
  var top=$('expTop10');
  if(top){
    var et=L(CONTENT.EXP_TOP10);
    while(top.firstChild)top.removeChild(top.firstChild);
    var tt=document.createElement('div'); tt.className='card-title'; tt.style.marginBottom='8px'; tt.textContent=String(et.title||'');
    var introP=document.createElement('p'); introP.style.cssText='font-size:13.5px;color:var(--text2);line-height:1.55;margin:0 0 10px;font-style:italic'; introP.textContent=String(et.intro||'');
    var ol=document.createElement('ol'); ol.style.cssText='margin:0 0 0 22px;padding:0;font-size:14px;color:var(--copper2);line-height:1.7';
    (et.items||[]).forEach(function(x){ var li=document.createElement('li'); li.textContent=String(x); ol.appendChild(li); });
    var note=document.createElement('p'); note.style.cssText='font-size:13px;color:var(--text3);line-height:1.55;margin:10px 0 0;font-style:italic'; note.textContent=String(et.note||'');
    top.appendChild(tt); top.appendChild(introP); top.appendChild(ol); top.appendChild(note);
  }
  buildAccordions('experimentsAccordions',CONTENT.EXPERIMENTS);
}

/* ══════════════ BUILD ALL ACCORDIONS ══════════════ */
function buildAllAccordions(){
  buildAccordions('healthAccordions',CONTENT.HEALTH);
  buildAccordions('historyAccordions',CONTENT.HISTORY);
  buildAccordions('cookingAccordions',CONTENT.COOKING);
  buildAccordions('scienceAccordions',CONTENT.SCIENCE);
  buildAccordions('investAccordions',CONTENT.INVEST);
  renderExperiments();
}

/* ══════════════ PRIVATE NOTES ══════════════ */
function validateNotes(arr){
  if(!Array.isArray(arr)) return [];
  var out=[];
  for(var i=0;i<arr.length && out.length<30;i++){
    var n=arr[i];
    if(!n||typeof n!=='object') continue;
    var text=typeof n.text==='string'?n.text:'';
    var author=typeof n.author==='string'?n.author:'You';
    if(!text||text.length>500) continue;
    out.push({author:author.slice(0,40),text:text});
  }
  return out;
}
function renderNotes(){
  var notes=validateNotes(OCC.load('notes'));
  var el=$('homeNotes'); if(!el)return;
  while(el.firstChild)el.removeChild(el.firstChild);
  if(!notes.length){
    var empty=document.createElement('div');
    empty.style.cssText='font-size:.85em;color:var(--text3);text-align:center;padding:10px 4px;font-style:italic';
    empty.textContent=t('notes_empty');
    el.appendChild(empty);
    return;
  }
  notes.forEach(function(n){
    var item=document.createElement('div'); item.className='note-item';
    var a=document.createElement('div'); a.className='note-author'; a.textContent=String(n.author||'You');
    var tx=document.createElement('div'); tx.className='note-text'; tx.textContent=String(n.text||'');
    item.appendChild(a); item.appendChild(tx); el.appendChild(item);
  });
}
function firstNameFromEmail(email){
  var local=(email.split('@')[0]||'').replace(/^[-_]+/,'');
  var first=local.split(/[.\-_]/).filter(function(s){return s.replace(/[0-9]/g,'').length>0;})[0]||t('you_word');
  first=first.replace(/[^a-zA-Z]/g,'');
  return first.charAt(0).toUpperCase()+first.slice(1).toLowerCase();
}
function addNote(){
  var inp=$('newNote'); if(!inp)return;
  var val=inp.value.trim(); if(!val)return;
  if(val.length>500){alert('Note too long');return;}
  var notes=validateNotes(OCC.load('notes'));
  notes.unshift({author:'You',text:val});
  notes=validateNotes(notes.slice(0,30));
  OCC.save('notes',notes);
  inp.value='';
  renderNotes();
}

/* ══════════════ COPPER PRICE ESTIMATOR ══════════════ */
function calcCopper(){
  var price=parseFloat(($('pricePerLb')||{}).value);
  var weight=parseFloat(($('weightLbs')||{}).value);
  var res=$('copperResult'); if(!res)return;
  if(isNaN(price)||isNaN(weight)){alert(t('price_need'));return;}
  var total=(price*weight).toFixed(2);
  var perOz=(price/16).toFixed(4);
  var perKg=(price*2.20462).toFixed(2);
  res.style.display='block';
  while(res.firstChild)res.removeChild(res.firstChild);
  var d1=document.createElement('div'); d1.style.marginBottom='6px'; d1.textContent=t('price_total'); res.appendChild(d1);
  var d2=document.createElement('div'); d2.className='result-val'; d2.textContent=String.fromCharCode(36)+total; res.appendChild(d2);
  var d3=document.createElement('div'); d3.style.cssText='margin-top:8px;font-size:13px;color:var(--text3)';
  d3.textContent=String.fromCharCode(36)+perOz+'/oz  ·  '+String.fromCharCode(36)+perKg+'/kg'; res.appendChild(d3);
}

/* ══════════════ EMAIL PERSONALIZATION ══════════════ */
function applyEmail(){ if($('headerEmail'))$('headerEmail').textContent='FREE FOREVER · OFFLINE'; }
function confirmEmail(){ if($('setup-overlay'))$('setup-overlay').classList.remove('show'); if($('headerEmail'))$('headerEmail').textContent='FREE FOREVER · OFFLINE'; }

/* ══════════════ SETTINGS PANEL ══════════════ */
function openSettings(){
  if($('settingsEmail'))$('settingsEmail').value=OCC.load('userEmail')||'';
  if($('ownerKeyInput'))$('ownerKeyInput').value=OCC.load('ownerKey')||'';
  if($('settingsOverlay'))$('settingsOverlay').style.display='block';
  if($('settingsPanel'))$('settingsPanel').style.display='block';
}
function closeSettings(){
  if($('settingsOverlay'))$('settingsOverlay').style.display='none';
  if($('settingsPanel'))$('settingsPanel').style.display='none';
}
function saveSettings(){ showToast(t('toast_saved')||'Saved'); closeSettings(); }

/* ══════════════ UNLOCK (via adapter, owner key) ══════════════ */
function requestUnlock(){ return Promise.resolve({status:'free_forever',unlocked:true}); }

/* ══════════════ TOAST ══════════════ */
var toastTmr=null;
function showToast(msg){
  var el=$('toast'); if(!el)return;
  el.textContent=msg; el.classList.add('show');
  clearTimeout(toastTmr); toastTmr=setTimeout(function(){el.classList.remove('show');},2500);
}

/* ══════════════ LANG TOGGLE UI ══════════════ */
function updateLangToggleUI(){
  document.querySelectorAll('.lang-btn').forEach(function(b){b.classList.toggle('on',b.dataset.lang===LANG);});
}

/* ══════════════ RENDER-ALL (used on lang switch) ══════════════ */
function renderAll(){
  showFact();
  renderLookups();
  buildAllAccordions();
  renderNotes();
}

/* ══════════════ INIT ══════════════ */
function init(){
  applyI18n();
  updateLangToggleUI();
  showFact();
  renderLookups();
  buildAllAccordions();
  renderNotes();
  if($('setup-overlay'))$('setup-overlay').classList.remove('show');
  if($('headerEmail'))$('headerEmail').textContent='FREE FOREVER · OFFLINE';
  if($('footer-owner'))$('footer-owner').textContent='COP1 Free Forever · Offline';
}

/* ══════════════ PUBLIC API (onclick handlers) ══════════════ */
window.CA={
  showTab:showTab, nextFact:nextFact, prevFact:prevFact, toggleAcc:toggleAcc,
  addNote:addNote, calcCopper:calcCopper, confirmEmail:confirmEmail,
  openSettings:openSettings, closeSettings:closeSettings, saveSettings:saveSettings,
  requestUnlock:requestUnlock, setLang:setLang, OCC:OCC
};

if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',init);
else init();

})();
