';
var nv=document.querySelector('nav');
if(nv&&nv.parentNode) nv.parentNode.insertBefore(tk,nv.nextSibling); else document.body.insertBefore(tk,document.body.firstChild);
}
// BL-125 STUDIO CANVAS: pages authored on the Studio canvas carry their
// whole body as HTML — rendered 1:1 inside the page chrome. The waitlist
// placeholder becomes the real, wired sign-up form.
if(c.canvasHtml){
// Parse the canvas into a detached container and replace each waitlist placeholder via the
// DOM. A previous string-regex (
) under-matched when
// the waitlist block held nested
s: it stopped at the first
, leaving a dangling
//
that closed .ps-cv early. Everything below then escaped the .ps-cv scope and picked
// up the GLOBAL (badge, left-aligned) .eyebrow style instead of the scoped plain one. The DOM
// path always yields balanced markup, so following elements stay inside .ps-cv.
var _host=document.createElement('div'); _host.innerHTML=String(c.canvasHtml);
var _L=c.lang||'en'; var _subs=IQ_SUBSCR[_L]||IQ_SUBSCR.en; // waitlist system strings in the page's language
_host.querySelectorAll('div[data-ps="waitlist"]').forEach(function(node){
var wl=node.getAttribute('data-wl')||'';
// Запазваме ТОЧНО съдържанието от студиото (текстове, класове, форматиране),
// за да изглежда 1:1 с админа. Само мокъпът се сменя с реалната форма.
var inner=node.innerHTML;
if(!/wl-title|wl-sub|wl-mock|wl-fine/.test(inner)){ // стар/празен блок → стандартна структура (преведена)
inner='
'+esc(IQT(_L,'wl.h2','Be first in line.'))+'
'+
'
'+esc(IQT(_L,'wl.p','Join the waitlist for early access, early-bird pricing, and a say in the roadmap.'))+'
'+
(wl?'
'+_subs+' '+esc(wl)+'
':'')+
'
'+esc(IQT(_L,'wl.fine','No spam. One e-mail when it matters.'))+'
';
}
// ред 3 винаги от продукта/OS (data-wl), с преведен префикс; ако не е зададен — без ред 3
if(wl&&!/^multi/i.test(wl)) inner=inner.replace(/(
]*wl-sub3[\s\S]*?<\/p>/i,'');
// мокъпът на инпута → реалната работеща форма (преведени надписи)
var isMulti=/^multi/i.test(wl);
var form='
'+
'
'+esc(IQT(_L,'wl.success','You are on the list — talk soon.'))+'
';
inner=inner.replace(/
]*wl-mock[\s\S]*?<\/p>/i, form);
// Пренасяме класовете (напр. ефектите iq-fx-*) и inline стила от оригиналния
// блок върху картата, за да изглежда живо 1:1 със студиото — със същите ефекти.
var cls=(node.getAttribute('class')||'').replace(/\bwl-card\b/g,'').trim();
var stl=node.getAttribute('style')||'';
var sec=document.createElement('section'); sec.className='blk'; sec.id='waitlist'; sec.setAttribute('style','padding:24px 0');
sec.innerHTML='
'+inner+'
';
node.replaceWith(sec);
});
// Drop stray JUNK cards: an EMPTY .ps-card (no children, no text) renders as a meaningless
// blank white box on the live page and can survive in the saved canvas after edits. Deliberate
// SPACERS are empty *sections* (.ps-sec), which are untouched; a card is only kept if it is
// decorative — i.e. it carries an effect class or sets its own background/border inline.
_host.querySelectorAll('.ps-card').forEach(function(card){
if(card.children.length===0 && !(card.textContent||'').trim() && !/iq-fx-/.test(card.className||'') && !/background|border/i.test(card.getAttribute('style')||'')){
card.remove();
}
});
document.getElementById('page').innerHTML=
'
'+_host.innerHTML+'
';
}else{
var render=LAYOUTS[c.layout]||LAYOUTS.classic;
document.getElementById('page').innerHTML=render(c);
}
try{ document.dispatchEvent(new CustomEvent('iq:content')); }catch(e){} // smart islands ([data-iq]) can render now
requestAnimationFrame(iqFitButtons); // fit long button labels to one line
try{ if(document.fonts&&document.fonts.ready) document.fonts.ready.then(function(){ requestAnimationFrame(iqFitButtons); }); }catch(e){}
// Arriving with a #section hash (a button linked to /p/#anchor) → scroll to it.
// FUZZY fallback: page anchors are usually product-prefixed (e.g. `brieflyiq-pricing`),
// so when the exact id is missing we scroll to the first id CONTAINING the hash —
// that lets a generic `#pricing` link land on every product's pricing anchor.
try{ if(location.hash&&location.hash.length>1){
var _hk=decodeURIComponent(location.hash.slice(1));
var _ht=document.getElementById(_hk);
if(!_ht){ try{ _ht=document.querySelector('#page [id*="'+_hk.replace(/["\\]/g,'')+'" i]'); }catch(e){} }
if(_ht) setTimeout(function(){ _ht.scrollIntoView({behavior:'smooth',block:'start'}); },120);
} }catch(e){}
// Product / App rich data set in the studio SEO tab → SoftwareApplication JSON-LD (Google can show OS, price…).
try{ var _se=(c.seo||{}); if(_se.type==='product'){
var _app={"@context":"https://schema.org","@type":"SoftwareApplication","name":(c.name||document.title||'').replace(/\s+—\s+iQ Suite Labs.*$/,'').trim(),"applicationCategory":(_se.category||"BusinessApplication")};
if(_se.os){ var _oss=String(_se.os).split(',').map(function(x){return x.trim();}).filter(Boolean); _app.operatingSystem=_oss.length>1?_oss:(_oss[0]||_se.os); }
var _pr=String(_se.price||'').replace(/[^0-9.]/g,''); if(_pr) _app.offers={"@type":"Offer","price":_pr,"priceCurrency":"EUR"};
var _old=document.getElementById('iqProdLd'); if(_old) _old.remove();
var _sc=document.createElement('script'); _sc.type='application/ld+json'; _sc.id='iqProdLd'; _sc.textContent=JSON.stringify(_app); document.head.appendChild(_sc);
} }catch(e){}
// release manifest (admin → Releases): fills plan download buttons left
// without a link and shows the current version in the hero badge
fetch('/.netlify/functions/content',{method:'POST',headers:{'Content-Type':'application/json'},
body:JSON.stringify({action:'rel-get',key:KEY})})
.then(function(r){return r.json();}).then(function(j){
var rel=j&&j.rel; if(!rel) return;
if(rel.version){ var eb=document.querySelector('.eyebrow'); if(eb) eb.textContent+=' · v'+rel.version; }
if(rel.url) document.querySelectorAll('[data-needrel]').forEach(function(a){
a.href=rel.url; a.style.display=''; });
}).catch(function(){});
gcCount('/p/'+KEY); // clean per-product pageview for the funnel
(function(){ // multi-waitlist checkboxes come from the live product registry
var span=document.querySelector('form.wl .wl-checks'); if(!span) return;
fetch('/.netlify/functions/content?action=registry').then(function(r){if(!r.ok)throw 0;return r.json();})
.catch(function(){return fetch('/.netlify/functions/content',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({action:'registry'})}).then(function(r){return r.json();});})
.then(function(j){
var seen={};
var names=((j&&j.products)||[]).filter(function(p){
if(!p||!p.name||p.lang||p.baseKey) return false;
var st=String(p.status||'').toLowerCase();
if(st==='strategic goal') return false;
if(st==='available now') return false; // live products convert via TRIAL, not the waitlist — listing them here dilutes conversion
if(seen[p.name]) return false; seen[p.name]=1; return true; }).map(function(p){return p.name;});
if(!names.length){ span.style.display='none'; return; } // everything live: the form stays a simple e-mail waitlist
span.innerHTML=names.map(function(n){
return ''; }).join('');
}).catch(function(){});
})();
document.querySelectorAll('form.wl').forEach(function(f){ f.addEventListener('submit',async function(e){
e.preventDefault();
var inp=f.querySelector('input[type=email]')||f.querySelector('input'); var email=inp?inp.value:'';
if(f.getAttribute('data-wl-multi')){
var picked=[].map.call(f.querySelectorAll('input.iq-wlp:checked'),function(cb){return cb.getAttribute('data-prod');});
if(!picked.length){ var any=f.querySelector('input.iq-wlp'); if(any){ any.focus(); return; } picked=[c.name]; }
for(var pi=0;pi