{'role': 'user', 'content': ' ToolResult(success=True, output=\'{\\n "output": " \\\\n async function getJSON(path){ const r = await fetch(path); return await r.json(); }\\\\n \\\\n // Directory rendering\\\\n async function renderDirectory(){\\\\n const q = (document.getElementById(\\\'q\\\')||{}).value?.toLowerCase()||\\\'\\\';\\\\n const cat = (document.getElementById(\\\'cat\\\')||{}).value||\\\'all\\\';\\\\n const sort = (document.getElementById(\\\'sort\\\')||{}).value||\\\'karma-desc\\\';\\\\n const resEl = document.getElementById(\\\'results\\\');\\\\n if(!resEl) return;\\\\n \\\\n const [cats, conf, data] = await Promise.all([\\\\n getJSON(\\\'./data/categories.json\\\'),\\\\n getJSON(\\\'./data/karma-config.json\\\'),\\\\n getJSON(\\\'./data/listings.json\\\')\\\\n ]);\\\\n \\\\n // populate category select once\\\\n const catSel = document.getElementById(\\\'cat\\\');\\\\n if(catSel && catSel.options.length===0){\\\\n catSel.append(new Option(\\\\"All\\\\", \\\\"all\\\\"));\\\\n cats.categories.forEach(c => catSel.append(new Option(c,c)));\\\\n }\\\\n \\\\n // compute karma for each listing\\\\n const W = conf.weights;\\\\n function score(k){ if(!k) return 0; return (k.profile*W.profile + k.reviews*W.reviews + k.velocity*W.velocity + k.verification*W.verification) }\\\\n \\\\n let items = data.listings.map(x => ({...x, _karma: score(x.karma)}));\\\\n \\\\n // filter\\\\n if(cat !== \\\'all\\\') items = items.filter(x => x.category === cat);\\\\n if(q){\\\\n items = items.filter(x => (x.name+x.city+x.category+(x.tags||[]).join(\\\' \\\')+(x.desc||\\\'\\\')).toLowerCase().includes(q));\\\\n }\\\\n \\\\n // sort\\\\n if(sort===\\\'karma-desc\\\') items.sort((a,b)=>b._karma - a._karma);\\\\n if(sort===\\\'name-asc\\\') items.sort((a,b)=>a.name.localeCompare(b.name));\\\\n if(sort===\\\'reviews-desc\\\') items.sort((a,b)=> (b.reviews||0) - (a.reviews||0));\\\\n \\\\n // render\\\\n resEl.innerHTML = items.map(x => `\\\\n
\\\\n \\\\"${x.name}\\\\n
\\\\n
\\\\n
\\\\n ${x.name}
\\\\n ${x.category} \\\\u2022 ${x.city}\\\\n
\\\\n
Karma ${(x._karma*100).toFixed(0)}
\\\\n
\\\\n
${x.desc||\\\'\\\'}
\\\\n
? ${x.stars||\\\'-\\\'} \\\\u2022 ${x.reviews||0} reviews ${x.verified? \\\'\\\\u2022 Verified\\\':\\\'\\\'}
\\\\n
Tags: ${(x.tags||[]).map(t=>`${t}`).join(\\\' \\\')}
\\\\n
\\\\n
\\\\n `).join(\\\'\\\') || \\\'
No results.
\\\';\\\\n }\\\\n document.addEventListener(\\\'DOMContentLoaded\\\', ()=>{ renderDirectory(); renderKarma(); renderResources(); bindCheckout(); });\\\\n \\\\n // Listing JSON generator\\\\n function generateListingJSON(){\\\\n const name = document.getElementById(\\\'new_name\\\').value.trim();\\\\n const category = document.getElementById(\\\'new_category\\\').value.trim();\\\\n const city = document.getElementById(\\\'new_city\\\').value.trim();\\\\n const url = document.getElementById(\\\'new_url\\\').value.trim();\\\\n const tags = document.getElementById(\\\'new_tags\\\').value.split(\\\',\\\').map(s=>s.trim()).filter(Boolean);\\\\n const desc = document.getElementById(\\\'new_desc\\\').value.trim();\\\\n const id = name.toLowerCase().replace(/[^a-z0-9]+/g,\\\'-\\\').replace(/(^-|-$)/g,\\\'\\\');\\\\n const obj = {\\\\n \\\\"id\\\\": id, \\\\"name\\\\": name, \\\\"category\\\\": category, \\\\"city\\\\": city, \\\\"url\\\\": url,\\\\n \\\\"tags\\\\": tags, \\\\"desc\\\\": desc, \\\\"logo\\\\":\\\\"./img/placeholder.svg\\\\",\\\\n \\\\"reviews\\\\": 0, \\\\"stars\\\\": 0, \\\\"verified\\\\": false,\\\\n \\\\"karma\\\\": {\\\\"profile\\\\":0.5,\\\\"reviews\\\\":0.5,\\\\"velocity\\\\":0.5,\\\\"verification\\\\":0.0}\\\\n };\\\\n document.getElementById(\\\'new_output\\\').value = JSON.stringify(obj, null, 2);\\\\n }\\\\n \\\\n // Digital Karma page\\\\n async function renderKarma(){\\\\n const kconf = document.getElementById(\\\'kconf\\\');\\\\n const kboard = document.getElementById(\\\'kboard\\\');\\\\n if(!kconf && !kboard) return;\\\\n const [conf, data] = await Promise.all([getJSON(\\\'./data/karma-config.json\\\'), getJSON(\\\'./data/listings.json\\\')]);\\\\n const W = conf.weights;\\\\n if(kconf){\\\\n kconf.innerHTML = `\\\\n SignalWeightDescription\\\\n Profile${(W.profile*100).toFixed(0)}%Completeness, images, links, schema\\\\n Reviews${(W.reviews*100).toFixed(0)}%Stars & recent review velocity\\\\n Velocity${(W.velocity*100).toFixed(0)}%Update cadence / freshness\\\\n Verification${(W.verification*100).toFixed(0)}%Ownership & identity proof\\\\n `;\\\\n }\\\\n if(kboard){\\\\n function score(k){ if(!k) return 0; return (k.profile*W.profile + k.reviews*W.reviews + k.velocity*W.velocity + k.verification*W.verification) }\\\\n const items = data.listings.map(x=>({...x,_karma:score(x.karma)})).sort((a,b)=>b._karma-a._karma).slice(0,10);\\\\n kboard.innerHTML = items.map((x,i)=>`\\\\n
\\\\n
${i+1}. ${x.name} (${x.category})
\\\\n
${(x._karma*100).toFixed(0)}
\\\\n
\\\\n `).join(\\\'\\\');\\\\n }\\\\n }\\\\n \\\\n // Health Check logic\\\\n async function runHealthCheck(){\\\\n const [conf] = await Promise.all([getJSON(\\\'./data/karma-config.json\\\')]);\\\\n const W = conf.weights;\\\\n const gbp = document.getElementById(\\\'f_gbp\\\').value===\\\'yes\\\' ? 1 : 0;\\\\n const cwvSel = document.getElementById(\\\'f_cwv\\\').value;\\\\n const stars = Math.max(1, Math.min(5, parseFloat(document.getElementById(\\\'f_stars\\\').value||\\\\"0\\\\")));\\\\n const starsNorm = (stars-1)/(5-1); // 0..1\\\\n const reviews = Math.max(0, parseInt(document.getElementById(\\\'f_reviews\\\').value||\\\\"0\\\\",10));\\\\n const reviewsNorm = Math.min(1, reviews/25); // cap at 25 in 90 days\\\\n const last = parseInt(document.getElementById(\\\'f_update\\\').value,10);\\\\n const velocity = last<=30 ? 1 : (last<=90 ? 0.6 : 0.2);\\\\n const schema = document.getElementById(\\\'f_schema\\\').value===\\\'yes\\\' ? 1 : 0;\\\\n \\\\n const profile = (gbp*0.5 + schema*0.5);\\\\n const reviewsSignal = (starsNorm*0.6 + reviewsNorm*0.4);\\\\n const verification = gbp;\\\\n \\\\n const score = (profile*W.profile + reviewsSignal*W.reviews + velocity*W.velocity + verification*W.verification);\\\\n \\\\n document.getElementById(\\\'hc_score\\\').textContent = `Karma ${(score*100).toFixed(0)}`;\\\\n const snapshot = {\\\\n date: new Date().toISOString(),\\\\n inputs: { gbp: gbp===1, cwv: cwvSel, stars, reviews, lastDays: last, schema: schema===1 },\\\\n mapped: { profile, reviewsSignal, velocity, verification },\\\\n score: score\\\\n };\\\\n document.getElementById(\\\'hc_json\\\').textContent = JSON.stringify(snapshot,null,2);\\\\n }\\\\n \\\\n // Resources\\\\n async function renderResources(){\\\\n const tbl = document.querySelector(\\\'#resources_table tbody\\\');\\\\n if(!tbl) return;\\\\n const data = await getJSON(\\\'./data/resources.json\\\');\\\\n tbl.innerHTML = data.items.map(x=>`\\\\n ${x.title}${x.type}Open${(x.tags||[]).join(\\\', \\\')}\\\\n `).join(\\\'\\\');\\\\n }\\\\n \\\\n // v04: Stripe Checkout wiring\\\\n async function bindCheckout(){\\\\n try{\\\\n const map = await getJSON(\\\'./data/checkout.json\\\');\\\\n document.querySelectorAll(\\\'[data-checkout]\\\').forEach(btn=>{\\\\n btn.addEventListener(\\\'click\\\', ()=>{\\\\n const key = btn.getAttribute(\\\'data-checkout\\\');\\\\n const prod = map.products && map.products[key];\\\\n if(prod && prod.checkout_url && !prod.checkout_url.includes(\\\'REPLACE_ME\\\')){\\\\n window.location.href = prod.checkout_url;\\\\n }else{\\\\n alert(\\\'Checkout not configured yet. Replace the checkout_url in /data/checkout.json for \\\\\\\\\\\\"\\\'+key+\\\'\\\\\\\\\\\\".\\\');\\\\n }\\\\n });\\\\n });\\\\n }catch(e){ console.warn(\\\'Checkout map missing\\\', e); }\\\\n }\\\\n \\\\n //Toggle Mobile Menu\\\\n \\\\n document.addEventListener(\\\'DOMContentLoaded\\\', () => {\\\\n const toggle = document.getElementById(\\\'nav-toggle\\\');\\\\n const menu = document.getElementById(\\\'nav-menu\\\');\\\\n if (!toggle || !menu) return;\\\\n \\\\n toggle.addEventListener(\\\'click\\\', (e) => {\\\\n e.preventDefault();\\\\n const isOpen = menu.classList.toggle(\\\'open\\\'); // matches your CSS\\\\n toggle.setAttribute(\\\'aria-expanded\\\', isOpen ? \\\'true\\\' : \\\'false\\\');\\\\n });\\\\n \\\\n // optional niceties:\\\\n menu.addEventListener(\\\'click\\\', (e) => {\\\\n if (e.target.closest(\\\'a\\\')) {\\\\n menu.classList.remove(\\\'open\\\');\\\\n toggle.setAttribute(\\\'aria-expanded\\\', \\\'false\\\');\\\\n }\\\\n });\\\\n document.addEventListener(\\\'keydown\\\', (e) => {\\\\n if (e.key === \\\'Escape\\\') {\\\\n menu.classList.remove(\\\'open\\\');\\\\n toggle.setAttribute(\\\'aria-expanded\\\', \\\'false\\\');\\\\n }\\\\n });\\\\n });\\\\n",\\n "exit_code": 0,\\n "cwd": "/workspace"\\n}\')
'}