`; } async function savePage(silent){ const {data,error}=await sb.from('builder_pages').upsert({ id: activePage.id, builder_site_id: activePage.builder_site_id, slug: activePage.slug, title: activePage.title, blocks: activePage.blocks, nav_order: activePage.nav_order ?? 0, show_in_nav: activePage.show_in_nav !== false, meta_description: activePage.meta_description || null, updated_at: new Date().toISOString(), }, {onConflict:'builder_site_id,slug'}).select().single(); if(error){ toast(error.message); return false; } Object.assign(activePage,data); const idx=pages.findIndex(p=>p.slug===activePage.slug); if(idx>=0) pages[idx]=activePage; dirty=false; if(!silent) toast('Saved'); return true; } async function togglePublish(){ const site=currentSite(); if(dirty){ const ok=await savePage(true); if(!ok) return; } const {data,error}=await sb.from('builder_sites').update({published:!site.published,updated_at:new Date().toISOString()}).eq('id',site.id).select().single(); if(error){ toast(error.message); return; } Object.assign(site,data); toast(site.published ? `Published β€” live at ${site.custom_domain||(site.subdomain+'.360-search.com')}` : 'Unpublished'); renderEditor(); } function openSiteSettingsModal(){ const site=currentSite(); const theme=site.theme||{accent:'#3b82f6',bg:'#ffffff',text:'#111827'}; const overlay=document.createElement('div'); overlay.className='cv-modal-overlay'; overlay.innerHTML=`

Site settings

CNAME your domain to ${escHtml(site.subdomain)}.360-search.com, then click Verify. Requires the domain be pointed through Cloudflare (custom hostnames) β€” ask if you need the DNS steps.
`; document.body.appendChild(overlay); const close=()=>overlay.remove(); overlay.addEventListener('click',e=>{if(e.target===overlay)close();}); document.getElementById('ss-cancel').addEventListener('click',close); document.getElementById('ss-verify-domain').addEventListener('click',async()=>{ const domain=document.getElementById('ss-domain').value.trim().toLowerCase(); const errEl=document.getElementById('ss-err'); if(!domain){errEl.textContent='Enter a domain first.';return;} try{ const res=await fetch(`https://dns.google/resolve?name=${encodeURIComponent(domain)}&type=CNAME`); const data=await res.json(); const target=(data.Answer||[]).map(a=>String(a.data||'').replace(/\.$/,'').toLowerCase()); const expected=`${site.subdomain}.360-search.com`; if(target.includes(expected)){ await sb.from('builder_sites').update({custom_domain:domain,custom_domain_verified:true}).eq('id',site.id); toast('Domain verified!'); close(); loadSites(); openEditor(site.id); } else { errEl.textContent=`CNAME not found yet β€” make sure ${domain} points to ${expected}.`; } }catch(e){ errEl.textContent='DNS lookup failed, try again.'; } }); document.getElementById('ss-save').addEventListener('click',async()=>{ const {error}=await sb.from('builder_sites').update({ title:document.getElementById('ss-title').value.trim()||site.title, logo_url:document.getElementById('ss-logo').value.trim()||null, theme:{accent:document.getElementById('ss-accent').value,bg:document.getElementById('ss-bg').value,text:document.getElementById('ss-text').value}, }).eq('id',site.id); if(error){document.getElementById('ss-err').textContent=error.message;return;} toast('Saved'); close(); loadSites(); openEditor(site.id); }); } initAuth();